diff --git a/.eslintignore b/.eslintignore index 04348c410..1db5125d0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,4 +4,5 @@ docs/Setup.md cypress.config.js cypress/plugins/index.js coverage -*.json \ No newline at end of file +*.json +node_modules diff --git a/.eslintrc.cjs b/.eslintrc.cjs index e6f99a8bf..273aa47b9 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -38,12 +38,17 @@ module.exports = { '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-floating-promises': 'error', '@typescript-eslint/no-misused-promises': 'error', '@typescript-eslint/ban-ts-comment': [ @@ -123,6 +128,14 @@ module.exports = { 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', }, }, diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 3ddf86ea5..2f87cd60c 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -50,19 +50,20 @@ body: attributes: label: Setup description: |- - Please fill out the below info. - Note that you only need to fill out one and not both sections. + Please fill out the info below. + Note that you only need to fill out the relevant section value: |- - **Desktop** - - - OS and Version: [Windows, Linux, Mac, ...] + - Mermaid version: - Browser and Version: [Chrome, Edge, Firefox] - - **Smartphone** - - - Device: [Samsung, iPhone, ...] - - OS and Version: [Android, iOS, ...] - - Browser and Version: [Chrome, Safari, ...] + - type: textarea + attributes: + label: Suggested Solutions + description: > + If applicable, suggest solutions that could resolve the bug. + It would help maintainers/contributors to not waste time looking for the solution. Even pointing the line causing the bug would be great! + placeholder: |- + - Variable `parser` in file is not initialised ... + - Add a new type for ... - type: textarea attributes: label: Additional Context diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 8710d49aa..44b16532c 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,4 +1,4 @@ -blank_issues_enabled: false +blank_issues_enabled: true contact_links: - name: GitHub Discussions url: https://github.com/mermaid-js/mermaid/discussions diff --git a/.github/ISSUE_TEMPLATE/diagram_proposal.yml b/.github/ISSUE_TEMPLATE/diagram_proposal.yml index 67dad5d3a..59bda6d6d 100644 --- a/.github/ISSUE_TEMPLATE/diagram_proposal.yml +++ b/.github/ISSUE_TEMPLATE/diagram_proposal.yml @@ -3,6 +3,7 @@ description: Suggest a new Diagram Type to add to Mermaid. labels: - 'Status: Triage' - 'Type: Enhancement' + - 'Type: New Diagram' body: - type: markdown @@ -17,6 +18,14 @@ body: - Use a clear and concise title - Fill out the text fields with as much detail as possible. - Never be shy to give us screenshots and/or code samples. It will help! + + ## Example issues + + Refer to the discussions here to get an idea of how the diagram syntax is created. + + - https://github.com/mermaid-js/mermaid/issues/4269 + - https://github.com/mermaid-js/mermaid/issues/4282 + - type: textarea attributes: label: Proposal @@ -35,8 +44,17 @@ body: description: If applicable, add screenshots to show possible examples of how the diagram may look like. - type: textarea attributes: - label: Code Sample + label: Syntax description: |- - If applicable, add a code sample for how to implement this new diagram. - The text will automatically be rendered as JavaScript code. - render: javascript + If possible, include a syntax which could be used to write the diagram. + Try to add one or two examples of valid use-cases here. + - type: dropdown + id: implementation + attributes: + label: Implementation + description: |- + Would you like to implement this yourself, or is it a proposal for the community? + If there is no corresponding PR from your side after 30 days, the diagram will be open for everyone to implement. + options: + - I will try and implement it myself. + - This is a proposal which I'd love to see built into mermaid by the wonderful community. diff --git a/.github/codecov.yaml b/.github/codecov.yaml new file mode 100644 index 000000000..950edb6a9 --- /dev/null +++ b/.github/codecov.yaml @@ -0,0 +1,17 @@ +codecov: + branch: develop + +comment: + layout: 'reach, diff, flags, files' + behavior: default + require_changes: false # if true: only post the comment if coverage changes + require_base: no # [yes :: must have a base report to post] + require_head: yes # [yes :: must have a head report to post] + +coverage: + status: + project: + off + # Turing off for now as code coverage isn't stable and causes unnecessary build failures. + # default: + # threshold: 2% diff --git a/.github/lychee.toml b/.github/lychee.toml new file mode 100644 index 000000000..b13e53616 --- /dev/null +++ b/.github/lychee.toml @@ -0,0 +1,44 @@ +############################# Display ############################# + +# Verbose program output +# Accepts log level: "error", "warn", "info", "debug", "trace" +verbose = "debug" + +# Don't show interactive progress bar while checking links. +no_progress = true + +############################# Cache ############################### + +# Enable link caching. This can be helpful to avoid checking the same links on +# multiple runs. +cache = true + +# Discard all cached requests older than this duration. +max_cache_age = "1d" + +############################# Requests ############################ + +# Comma-separated list of accepted status codes for valid links. +accept = [200, 429] + +############################# Exclusions ########################## + +# Exclude URLs and mail addresses from checking (supports regex). +exclude = [ +# Network error: Forbidden +"https://codepen.io", + +# Timeout error, maybe Twitter has anti-bot defenses against GitHub's CI servers? +"https://twitter.com/mermaidjs_", + +# Don't check files that are generated during the build via `pnpm docs:code` +'packages/mermaid/src/docs/config/setup/*', + +# Ignore slack invite +"https://join.slack.com/" +] + +# Exclude all private IPs from checking. +# Equivalent to setting `exclude_private`, `exclude_link_local`, and +# `exclude_loopback` to true. +exclude_all_private = true diff --git a/.github/pr-labeler.yml b/.github/pr-labeler.yml index 077cc568b..0bbd8db66 100644 --- a/.github/pr-labeler.yml +++ b/.github/pr-labeler.yml @@ -1,3 +1,4 @@ -'Type: Bug / Error': 'bug/*' -'Type: Enhancement': 'feature/*' -'Type: Other': 'other/*' +'Type: Bug / Error': ['bug/*', fix/*] +'Type: Enhancement': ['feature/*', 'feat/*'] +'Type: Other': ['other/*', 'chore/*', 'test/*', 'refactor/*'] +'Area: Documentation': ['docs/*'] diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3574c3599..ff34d24fd 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -13,6 +13,6 @@ Describe the way your implementation works or what design decisions you made if Make sure you - [ ] :book: have read the [contribution guidelines](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) -- [ ] :computer: have added unit/e2e tests (if appropriate) -- [ ] :notebook: have added documentation (if appropriate) +- [ ] :computer: have added necessary unit/e2e tests. +- [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/community/development.md#3-update-documentation) is used for all new features. - [ ] :bookmark: targeted `develop` branch diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 278151bca..e650f8dd1 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,14 +1,27 @@ 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' - label: 'Type: Other' + 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 diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml new file mode 100644 index 000000000..152b177ae --- /dev/null +++ b/.github/workflows/build-docs.yml @@ -0,0 +1,37 @@ +name: Build Vitepress docs + +on: + push: + branches: + - master + - release/* + pull_request: + merge_group: + +permissions: + contents: read + +jobs: + build-docs: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: pnpm/action-setup@v2 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + cache: pnpm + node-version: 18 + + - name: Install Packages + run: pnpm install --frozen-lockfile + + - name: Verify release verion + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release')) }} + run: pnpm --filter mermaid run docs:verify-version + + - name: Run Build + run: pnpm --filter mermaid run docs:build:vitepress diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2a70b5901..eeb557ebb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,7 @@ name: Build on: push: {} + merge_group: pull_request: types: - opened @@ -12,7 +13,7 @@ permissions: contents: read jobs: - build: + build-mermaid: runs-on: ubuntu-latest strategy: matrix: diff --git a/.github/workflows/check-readme-in-sync.yml b/.github/workflows/check-readme-in-sync.yml index 13912e5b9..5a8ca319b 100644 --- a/.github/workflows/check-readme-in-sync.yml +++ b/.github/workflows/check-readme-in-sync.yml @@ -14,7 +14,7 @@ permissions: contents: read jobs: - check: + check-readme: runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 396ff4e6e..9f9f316c4 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,15 +1,16 @@ on: - push: {} + push: + merge_group: pull_request: types: - opened - synchronize - ready_for_review -name: Static analysis +name: Static analysis on Test files jobs: - test: + check-tests: runs-on: ubuntu-latest name: check tests if: github.repository_owner == 'mermaid-js' diff --git a/.github/workflows/e2e-applitools.yml b/.github/workflows/e2e-applitools.yml index da6dbdb1f..5b1943142 100644 --- a/.github/workflows/e2e-applitools.yml +++ b/.github/workflows/e2e-applitools.yml @@ -19,7 +19,7 @@ env: USE_APPLI: ${{ secrets.APPLITOOLS_API_KEY && 'true' || '' }} jobs: - test: + e2e-applitools: runs-on: ubuntu-latest strategy: matrix: @@ -38,15 +38,8 @@ jobs: - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: - cache: pnpm node-version: ${{ matrix.node-version }} - - name: Install Packages - run: | - pnpm install --frozen-lockfile - env: - CYPRESS_CACHE_FOLDER: .cache/Cypress - - if: ${{ env.USE_APPLI }} name: Notify applitools of new batch # Copied from docs https://applitools.com/docs/topics/integrations/github-integration-ci-setup.html @@ -54,19 +47,22 @@ jobs: env: # e.g. mermaid-js/mermaid/my-branch APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }} - APPLITOOLS_PARENT_BRANCH: ${{ github.inputs.parent_branch }} + APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }} APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }} APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' - - name: Run E2E Tests - run: pnpm run e2e + - name: Cypress run + uses: cypress-io/github-action@v4 + id: cypress + with: + start: pnpm run dev + wait-on: 'http://localhost:9000' env: - CYPRESS_CACHE_FOLDER: .cache/Cypress # Mermaid applitools.config.js uses this to pick batch name. APPLI_BRANCH: ${{ github.ref_name }} APPLITOOLS_BATCH_ID: ${{ github.sha }} # e.g. mermaid-js/mermaid/my-branch APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }} - APPLITOOLS_PARENT_BRANCH: ${{ github.inputs.parent_branch }} + APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }} APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }} APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index aff5852db..3e6966677 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -1,12 +1,15 @@ name: E2E -on: [push, pull_request] +on: + push: + pull_request: + merge_group: permissions: contents: read jobs: - build: + e2e: runs-on: ubuntu-latest strategy: fail-fast: false @@ -21,11 +24,7 @@ jobs: - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 - # Need to skip setup if Cypress run is skipped, otherwise an error - # is thrown since the pnpm cache step fails - if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }} with: - cache: pnpm node-version: ${{ matrix.node-version }} # Install NPM dependencies, cache them correctly @@ -37,7 +36,7 @@ jobs: # Otherwise (e.g. if running from fork), we run on a single container only if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }} with: - start: pnpm run dev + start: pnpm run dev:coverage wait-on: 'http://localhost:9000' # Disable recording if we don't have an API key # e.g. if this action was run from a fork @@ -45,7 +44,19 @@ jobs: parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }} env: CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} - + VITEST_COVERAGE: true + CYPRESS_COMMIT: ${{ github.sha }} + - name: Upload Coverage to Codecov + uses: codecov/codecov-action@v3 + # 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: + files: coverage/cypress/lcov.info + flags: e2e + name: mermaid-codecov + fail_ci_if_error: false + verbose: true + token: 6845cc80-77ee-4e17-85a1-026cd95e0766 - name: Upload Artifacts uses: actions/upload-artifact@v3 if: ${{ failure() && steps.cypress.conclusion == 'failure' }} diff --git a/.github/workflows/link-checker.yml b/.github/workflows/link-checker.yml index 566548ecf..70580bfff 100644 --- a/.github/workflows/link-checker.yml +++ b/.github/workflows/link-checker.yml @@ -14,12 +14,13 @@ on: pull_request: branches: - master + workflow_dispatch: schedule: # * is a special character in YAML so you have to quote this string - cron: '30 8 * * *' jobs: - linkChecker: + link-checker: runs-on: ubuntu-latest permissions: # lychee only uses the GITHUB_TOKEN to avoid rate-limiting @@ -35,9 +36,13 @@ jobs: restore-keys: cache-lychee- - name: Link Checker - uses: lycheeverse/lychee-action@v1.5.4 + uses: lycheeverse/lychee-action@v1.8.0 with: - args: --verbose --no-progress --cache --max-cache-age 1d packages/mermaid/src/docs/**/*.md README.md README.zh-CN.md + args: >- + --config .github/lychee.toml + packages/mermaid/src/docs/**/*.md + README.md + README.zh-CN.md fail: true jobSummary: true env: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a21fbc005..f59c8af31 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,7 +1,8 @@ name: Lint on: - push: {} + push: + merge_group: pull_request: types: - opened @@ -42,7 +43,7 @@ jobs: if ! pnpm run lint; then # print a nice error message on lint failure ERROR_MESSAGE='Running `pnpm run lint` failed.' - ERROR_MESSAGE+=' Running `pnpm run lint:fix` may fix this issue. ' + ERROR_MESSAGE+=' Running `pnpm -w run lint:fix` may fix this issue. ' ERROR_MESSAGE+=" If this error doesn't occur on your local machine," ERROR_MESSAGE+=' make sure your packages are up-to-date by running `pnpm install`.' ERROR_MESSAGE+=' You may also need to delete your prettier cache by running' @@ -52,6 +53,33 @@ jobs: exit 1 fi + - name: Verify `./src/config.type.ts` is in sync with `./src/schemas/config.schema.yaml` + shell: bash + run: | + if ! pnpm run --filter mermaid types:verify-config; then + ERROR_MESSAGE='Running `pnpm run --filter mermaid types:verify-config` failed.' + ERROR_MESSAGE+=' This should be fixed by running' + ERROR_MESSAGE+=' `pnpm run --filter mermaid types:build-config`' + ERROR_MESSAGE+=' on your local machine.' + echo "::error title=Lint failure::${ERROR_MESSAGE}" + # make sure to return an error exitcode so that GitHub actions shows a red-cross + exit 1 + fi + + - name: Verify no circular dependencies + working-directory: ./packages/mermaid + shell: bash + run: | + if ! pnpm run --filter mermaid checkCircle; then + ERROR_MESSAGE='Circular dependency detected.' + ERROR_MESSAGE+=' This should be fixed by removing the circular dependency.' + ERROR_MESSAGE+=' Run `pnpm run --filter mermaid checkCircle` on your local machine' + ERROR_MESSAGE+=' to see the circular dependency.' + echo "::error title=Lint failure::${ERROR_MESSAGE}" + # make sure to return an error exitcode so that GitHub actions shows a red-cross + exit 1 + fi + - name: Verify Docs id: verifyDocs working-directory: ./packages/mermaid diff --git a/.github/workflows/pr-labeler-config-validator.yml b/.github/workflows/pr-labeler-config-validator.yml index af5c477d6..ff5d8d0a1 100644 --- a/.github/workflows/pr-labeler-config-validator.yml +++ b/.github/workflows/pr-labeler-config-validator.yml @@ -1,11 +1,15 @@ name: Validate PR Labeler Configuration on: - push: {} + push: + paths: + - .github/workflows/pr-labeler-config-validator.yml + - .github/workflows/pr-labeler.yml + - .github/pr-labeler.yml pull_request: - types: - - opened - - synchronize - - ready_for_review + paths: + - .github/workflows/pr-labeler-config-validator.yml + - .github/workflows/pr-labeler.yml + - .github/pr-labeler.yml jobs: pr-labeler: diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index cdd6167b7..f63e58750 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -5,10 +5,6 @@ on: push: branches: - master - pull_request: - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: @@ -23,7 +19,7 @@ concurrency: jobs: # Build job - build: + build-docs: runs-on: ubuntu-latest steps: - name: Checkout @@ -52,13 +48,12 @@ jobs: path: packages/mermaid/src/vitepress/.vitepress/dist # Deployment job - deploy: - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + deploy-docs: environment: name: github-pages runs-on: ubuntu-latest - needs: build + needs: build-docs steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v2 diff --git a/.github/workflows/release-preview-publish.yml b/.github/workflows/release-preview-publish.yml index 5f4936ab6..221e3836e 100644 --- a/.github/workflows/release-preview-publish.yml +++ b/.github/workflows/release-preview-publish.yml @@ -6,7 +6,7 @@ on: - 'release/**' jobs: - publish: + publish-preview: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/release-publish.yml b/.github/workflows/release-publish.yml index 28094453e..eb28fe9c8 100644 --- a/.github/workflows/release-publish.yml +++ b/.github/workflows/release-publish.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: fregante/setup-git-user@v1 + - uses: fregante/setup-git-user@v2 - uses: pnpm/action-setup@v2 # uses version from "packageManager" field in package.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6397e5305..7c32795e8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,12 +1,12 @@ name: Unit Tests -on: [push, pull_request] +on: [push, pull_request, merge_group] permissions: contents: read jobs: - build: + unit-test: runs-on: ubuntu-latest strategy: matrix: @@ -31,13 +31,24 @@ jobs: - name: Run Unit Tests run: | - pnpm run ci --coverage + pnpm test:coverage - - name: Upload Coverage to Coveralls - # it feels a bit weird to use @master, but that's what the docs use - # (coveralls also doesn't publish a @v1 we can use) - # https://github.com/marketplace/actions/coveralls-github-action - uses: coverallsapp/github-action@master + - name: Run ganttDb tests using California timezone + env: + # Makes sure that gantt db works even in a timezone that has daylight savings + # since some days have 25 hours instead of 24. + TZ: America/Los_Angeles + run: | + pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage + + - name: Upload Coverage to Codecov + uses: codecov/codecov-action@v3 + # Run step only pushes to develop and pull_requests + if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }} with: - github-token: ${{ secrets.GITHUB_TOKEN }} - flag-name: unit + files: ./coverage/vitest/lcov.info + flags: unit + name: mermaid-codecov + fail_ci_if_error: false + verbose: true + token: 6845cc80-77ee-4e17-85a1-026cd95e0766 diff --git a/.github/workflows/update-browserlist.yml b/.github/workflows/update-browserlist.yml index 4155ec988..813a400b3 100644 --- a/.github/workflows/update-browserlist.yml +++ b/.github/workflows/update-browserlist.yml @@ -5,7 +5,7 @@ on: workflow_dispatch: jobs: - build: + update-browser-list: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.gitignore b/.gitignore index f29286825..6a1cc85e5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,10 @@ node_modules/ coverage/ .idea/ +.pnpm-store/ dist +v8-compile-cache-0 yarn-error.log .npmrc @@ -36,3 +38,11 @@ tsconfig.tsbuildinfo knsv*.html local*.html stats/ + +**/user-avatars/* +**/contributor-names.json +.pnpm-store +.nyc_output + +demos/dev/** +!/demos/dev/example.html diff --git a/.lintstagedrc.mjs b/.lintstagedrc.mjs index ac2623093..3ae66bba2 100644 --- a/.lintstagedrc.mjs +++ b/.lintstagedrc.mjs @@ -1,5 +1,5 @@ export default { - '!(docs/**/*)*.{ts,js,json,html,md,mts}': [ + '!(docs/**/*)*.{ts,js,html,md,mts}': [ 'eslint --cache --cache-strategy content --fix', // don't cache prettier yet, since we use `prettier-plugin-jsdoc`, // and prettier doesn't invalidate cache on plugin updates" diff --git a/.lycheeignore b/.lycheeignore deleted file mode 100644 index 79cf4428b..000000000 --- a/.lycheeignore +++ /dev/null @@ -1,16 +0,0 @@ -# These links are ignored by our link checker https://github.com/lycheeverse/lychee -# The file allows you to list multiple regular expressions for exclusion (one pattern per line). - -# Network error: Forbidden -https://codepen.io - -# Network error: The certificate was not trusted -https://mkdocs.org/ -https://osawards.com/javascript/#nominees -https://osawards.com/javascript/2019 - -# Timeout error, maybe Twitter has anti-bot defences against GitHub's CI servers? -https://twitter.com/mermaidjs_ - -# Don't check files that are generated during the build via `pnpm docs:code` -packages/mermaid/src/docs/config/setup/* diff --git a/.npmrc b/.npmrc index 289684302..4c2f52b3b 100644 --- a/.npmrc +++ b/.npmrc @@ -1,3 +1,2 @@ auto-install-peers=true strict-peer-dependencies=false -use-inline-specifiers-lockfile-format=true diff --git a/.prettierignore b/.prettierignore index b66f97d1c..8a9086315 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,4 +4,9 @@ cypress/platform/xss3.html coverage # Autogenerated by PNPM pnpm-lock.yaml -stats \ No newline at end of file +stats +**/.vitepress/components.d.ts +**/.vitepress/cache +.nyc_output +# Autogenerated by `pnpm run --filter mermaid types:build-config` +packages/mermaid/src/config.type.ts diff --git a/.vite/build.ts b/.vite/build.ts index 268db3270..b89df9e31 100644 --- a/.vite/build.ts +++ b/.vite/build.ts @@ -2,14 +2,19 @@ import { build, InlineConfig, type PluginOption } from 'vite'; import { resolve } from 'path'; import { fileURLToPath } from 'url'; import jisonPlugin from './jisonPlugin.js'; +import jsonSchemaPlugin from './jsonSchemaPlugin.js'; import { readFileSync } from 'fs'; +import typescript from '@rollup/plugin-typescript'; import { visualizer } from 'rollup-plugin-visualizer'; import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js'; +import istanbul from 'vite-plugin-istanbul'; const visualize = process.argv.includes('--visualize'); const watch = process.argv.includes('--watch'); const mermaidOnly = process.argv.includes('--mermaid'); +const coverage = process.env.VITE_COVERAGE === 'true'; const __dirname = fileURLToPath(new URL('.', import.meta.url)); +const sourcemap = false; type OutputOptions = Exclude< Exclude['rollupOptions'], @@ -42,6 +47,11 @@ const packageOptions = { packageName: 'mermaid-example-diagram', file: 'detector.ts', }, + 'mermaid-zenuml': { + name: 'mermaid-zenuml', + packageName: 'mermaid-zenuml', + file: 'detector.ts', + }, }; interface BuildOptions { @@ -59,9 +69,15 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions) { name, format: 'esm', - sourcemap: true, + sourcemap, entryFileNames: `${name}.esm${minify ? '.min' : ''}.mjs`, }, + { + name, + format: 'umd', + sourcemap, + entryFileNames: `${name}${minify ? '.min' : ''}.js`, + }, ]; if (core) { @@ -78,7 +94,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions) { name, format: 'esm', - sourcemap: true, + sourcemap, entryFileNames: `${name}.core.mjs`, }, ]; @@ -102,9 +118,21 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions) }, }, resolve: { - extensions: ['.jison', '.js', '.ts', '.json'], + extensions: [], }, - plugins: [jisonPlugin(), ...visualizerOptions(packageName, core)], + 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__'], + extension: ['.js', '.ts'], + requireEnv: true, + forceBuildInstrument: coverage, + }), + ...visualizerOptions(packageName, core), + ], }; if (watch && config.build) { @@ -133,6 +161,7 @@ if (watch) { 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' })); } } else if (visualize) { await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' })); diff --git a/.vite/jisonTransformer.ts b/.vite/jisonTransformer.ts index a5734e125..314df8a33 100644 --- a/.vite/jisonTransformer.ts +++ b/.vite/jisonTransformer.ts @@ -1,8 +1,6 @@ -// @ts-ignore No typings for jison import jison from 'jison'; export const transformJison = (src: string): string => { - // @ts-ignore No typings for jison const parser = new jison.Generator(src, { moduleType: 'js', 'token-stack': true, diff --git a/.vite/jsonSchemaPlugin.ts b/.vite/jsonSchemaPlugin.ts new file mode 100644 index 000000000..671a9612e --- /dev/null +++ b/.vite/jsonSchemaPlugin.ts @@ -0,0 +1,150 @@ +import { load, JSON_SCHEMA } from 'js-yaml'; +import assert from 'node:assert'; +import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js'; +import { PluginOption } from 'vite'; + +import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js'; + +/** + * 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', + 'requirement', + 'mindmap', + 'timeline', + 'gitGraph', + 'c4', + 'sankey', +] as const; + +/** + * Generate default values from the JSON Schema. + * + * AJV does not support nested default values yet (or default values with $ref), + * so we need to manually find them (this may be fixed in ajv v9). + * + * @param mermaidConfigSchema - The Mermaid JSON Schema to use. + * @returns The default mermaid config object. + */ +function generateDefaults(mermaidConfigSchema: JSONSchemaType) { + const ajv = new Ajv2019({ + useDefaults: true, + allowUnionTypes: true, + strict: true, + }); + + ajv.addKeyword({ + keyword: 'meta:enum', // used by jsonschema2md + errors: false, + }); + ajv.addKeyword({ + keyword: 'tsType', // used by json-schema-to-typescript + errors: false, + }); + + // ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718 + // (may be fixed in v9) so we need to manually use sub-schemas + const mermaidDefaultConfig = {}; + + assert.ok(mermaidConfigSchema.$defs); + const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig; + + for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) { + const subSchemaRef = mermaidConfigSchema.properties[key].$ref; + const [root, defs, defName] = subSchemaRef.split('/'); + assert.strictEqual(root, '#'); + assert.strictEqual(defs, '$defs'); + const subSchema = { + $schema: mermaidConfigSchema.$schema, + $defs: mermaidConfigSchema.$defs, + ...mermaidConfigSchema.$defs[defName], + } as JSONSchemaType; + + const validate = ajv.compile(subSchema); + + mermaidDefaultConfig[key] = {}; + + for (const required of subSchema.required ?? []) { + if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) { + mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default; + } + } + if (!validate(mermaidDefaultConfig[key])) { + throw new Error( + `schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify( + validate.errors, + undefined, + 2 + )}` + ); + } + } + + const validate = ajv.compile(mermaidConfigSchema); + + if (!validate(mermaidDefaultConfig)) { + throw new Error( + `Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify( + validate.errors, + undefined, + 2 + )}` + ); + } + + return mermaidDefaultConfig; +} + +/** + * Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file. + * + * Use `my-example.schema.yaml?only-defaults=true` to only load the default values. + */ +export default function jsonSchemaPlugin(): PluginOption { + return { + name: 'json-schema-plugin', + transform(src: string, id: string) { + const idAsUrl = new URL(id, 'file:///'); + + if (!idAsUrl.pathname.endsWith('schema.yaml')) { + return; + } + + if (idAsUrl.searchParams.get('only-defaults')) { + const jsonSchema = load(src, { + filename: idAsUrl.pathname, + // only allow JSON types in our YAML doc (will probably be default in YAML 1.3) + // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`. + schema: JSON_SCHEMA, + }) as JSONSchemaType; + return { + code: `export default ${JSON.stringify(generateDefaults(jsonSchema), undefined, 2)};`, + map: null, // no source map + }; + } else { + return { + code: `export default ${JSON.stringify( + load(src, { + filename: idAsUrl.pathname, + // only allow JSON types in our YAML doc (will probably be default in YAML 1.3) + // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`. + schema: JSON_SCHEMA, + }), + undefined, + 2 + )};`, + map: null, // provide source map if available + }; + } + }, + }; +} diff --git a/.vite/server.ts b/.vite/server.ts index 7a65cba00..41e510c83 100644 --- a/.vite/server.ts +++ b/.vite/server.ts @@ -8,12 +8,14 @@ async function createServer() { // Create Vite server in middleware mode const vite = await createViteServer({ configFile: './vite.config.ts', + mode: 'production', server: { middlewareMode: true }, - appType: 'custom', // don't include Vite's default HTML handling middlewares + appType: 'custom', // don't include Vite's default HTML handling middleware }); app.use(cors()); app.use(express.static('./packages/mermaid/dist')); + app.use(express.static('./packages/mermaid-zenuml/dist')); app.use(express.static('./packages/mermaid-example-diagram/dist')); app.use(vite.middlewares); app.use(express.static('demos')); diff --git a/.vscode/launch.json b/.vscode/launch.json index 83b80fa40..dc5ec94a1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -17,7 +17,7 @@ "name": "Docs generation", "type": "node", "request": "launch", - "args": ["src/docs.mts"], + "args": ["scripts/docs.cli.mts"], "runtimeArgs": ["--loader", "ts-node/esm"], "cwd": "${workspaceRoot}/packages/mermaid", "skipFiles": ["/**", "**/node_modules/**"], diff --git a/CHANGELOG.md b/CHANGELOG.md index c5903cd91..7552efa3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,105 @@ -# Change Log +# Changelog -// TODO: Populate changelog +## [10.0.0](https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0) + +### Mermaid is ESM only! + +We've dropped CJS support. So, you will have to update your import scripts as follows. + +```html + +``` + +You can keep using v9 by adding the `@9` in the CDN URL. + +```diff +- ++ +``` + +### mermaid.render is async and doesn't accept callbacks + +```js +// < v10 +mermaid.render('id', 'graph TD;\nA-->B', (svg, bindFunctions) => { + element.innerHTML = svg; + if (bindFunctions) { + bindFunctions(element); + } +}); + +// Shorter syntax +if (bindFunctions) { + bindFunctions(element); +} +// can be replaced with the `?.` shorthand +bindFunctions?.(element); + +// >= v10 with async/await +const { svg, bindFunctions } = await mermaid.render('id', 'graph TD;\nA-->B'); +element.innerHTML = svg; +bindFunctions?.(element); + +// >= v10 with promise.then +mermaid.render('id', 'graph TD;A-->B').then(({ svg, bindFunctions }) => { + element.innerHTML = svg; + bindFunctions?.(element); +}); +``` + +### mermaid.parse is async and ParseError is removed + +```js +// < v10 +mermaid.parse(text, parseError); + +//>= v10 +await mermaid.parse(text).catch(parseError); +// or +try { + await mermaid.parse(text); +} catch (err) { + parseError(err); +} +``` + +### Init deprecated and InitThrowsErrors removed + +The config passed to `init` was not being used eariler. +It will now be used. +The `init` function is deprecated and will be removed in the next major release. +init currently works as a wrapper to `initialize` and `run`. + +```js +// < v10 +mermaid.init(config, selector, cb); + +//>= v10 +mermaid.initialize(config); +mermaid.run({ + querySelector: selector, + postRenderCallback: cb, + suppressErrors: true, +}); +``` + +```js +// < v10 +mermaid.initThrowsErrors(config, selector, cb); + +//>= v10 +mermaid.initialize(config); +mermaid.run({ + querySelector: selector, + postRenderCallback: cb, + suppressErrors: false, +}); +``` + +// TODO: Populate changelog pre v10 - Config has a lot of changes - globalReset resets to `defaultConfig` instead of current config. Use `reset` instead. diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 000000000..2f14a4b3d --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,16 @@ +cff-version: 1.2.0 +title: 'Mermaid: Generate diagrams from markdown-like text' +message: >- + If you use this software, please cite it using the metadata from this file. +type: software +authors: + - family-names: Sveidqvist + given-names: Knut + - name: 'Contributors to Mermaid' +repository-code: 'https://github.com/mermaid-js/mermaid' +date-released: 2014-12-02 +url: 'https://mermaid.js.org/' +abstract: >- + JavaScript based diagramming and charting tool that renders Markdown-inspired + text definitions to create and modify diagrams dynamically. +license: MIT diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0320b36e..3142c5760 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,14 +1,10 @@ # Contributing -So you want to help? That's great! +Please read in detail about how to contribute documentation and code on the [Mermaid documentation site.](https://mermaid-js.github.io/mermaid/#/development) -![Happy people jumping with excitement](https://media.giphy.com/media/BlVnrxJgTGsUw/giphy.gif) +--- -Here are a few things to know to get you started on the right path. - -Below link will help you making a copy of the repository in your local system. - -https://docs.github.com/en/get-started/quickstart/fork-a-repo +# Mermaid contribution cheat-sheet ## Requirements @@ -18,161 +14,65 @@ https://docs.github.com/en/get-started/quickstart/fork-a-repo ## Development Installation +If you don't have direct access to push to mermaid repositories, make a fork first. Then clone. Or clone directly from mermaid-js: + ```bash git clone git@github.com:mermaid-js/mermaid.git cd mermaid +``` + +Install required packages: + +```bash # npx is required for first install as volta support for pnpm is not added yet. npx pnpm install +pnpm test # run unit tests +pnpm dev # starts a dev server +``` + +Open in your browser after starting the dev server. +You can also duplicate the `example.html` file in `demos/dev`, rename it and add your own mermaid code to it. +That will be served at . + +### Docker + +If you are using docker and docker-compose, you have self-documented `run` bash script, which is a convenient alias for docker-compose commands: + +```bash +./run install # npx pnpm install +./run test # pnpm test +``` + +## Testing + +```bash +# Run unit test pnpm test +# Run unit test in watch mode +pnpm test:watch +# Run E2E test +pnpm e2e +# Debug E2E tests +pnpm dev +pnpm cypress:open # in another terminal ``` -## Committing code - -We make all changes via pull requests. As we have many pull requests from developers new to mermaid, the current approach is to have _knsv, Knut Sveidqvist_ as a main reviewer of changes and merging pull requests. More precisely like this: - -- Large changes reviewed by knsv or other developer asked to review by knsv -- Smaller low-risk changes like dependencies, documentation, etc. can be merged by active collaborators -- Documentation (updates to the `package/mermaid/src/docs` folder is also allowed via direct commits) - -To commit code, create a branch, let it start with the type like feature or bug followed by the issue number for reference and some describing text. - -One example: - -`feature/945_state_diagrams` - -Another: - -`bug/123_nasty_bug_branch` - -## Committing documentation - -Less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator. - -The documentation is written in **Markdown**. For more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). - -### Documentation source files are in [`/packages/mermaid/src/docs`](packages/mermaid/src/docs) - -The source files for the project documentation are located in the [`/packages/mermaid/src/docs`](packages/mermaid/src/docs) directory. This is where you should make changes. -The files under `/packages/mermaid/src/docs` are processed to generate the published documentation, and the resulting files are put into the `/docs` directory. - -```mermaid -flowchart LR - classDef default fill:#fff,color:black,stroke:black - - source["files in /packages/mermaid/src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"] +## Branch name format: +```text + [feature | bug | chore | docs]/[issue number]_[short description using dashes ('-') or underscores ('_') instead of spaces] ``` -You can use `note`, `tip`, `warning` and `danger` in triple backticks to add a note, tip, warning or danger box. -Do not use vitepress specific markdown syntax `::: warning` as it will not be processed correctly. +eg: `feature/2945_state-diagram-new-arrow-florbs`, `bug/1123_fix_random_ugly_red_text` -```` -```note -Note content -``` +## Documentation -```tip -Tip content -``` +Documentation is necessary for all non bugfix/refactoring changes. -```warning -Warning content -``` +Only make changes to files that are in [`/packages/mermaid/src/docs`](packages/mermaid/src/docs) -```danger -Danger content -``` +**_DO NOT CHANGE FILES IN `/docs` MANUALLY_** -```` - -**_DO NOT CHANGE FILES IN `/docs`_** - -### The official documentation site - -**[The mermaid documentation site](https://mermaid-js.github.io/mermaid/) is powered by [Vitepress](https://vitepress.vuejs.org/), a simple documentation site generator.** - -If you want to preview the whole documentation site on your machine: - -```sh -cd packages/mermaid -pnpm i -pnpm docs:dev -``` - -You can now build and serve the documentation site: - -```sh -pnpm docs:serve -``` - -## Branching - -Going forward we will use a git flow inspired approach to branching. So development is done in develop, to do the development in the develop. - -Once development is done we branch a release branch from develop for testing. - -Once the release happens we merge the release branch to master and kill the release branch. - -This means... **branch off your pull request from develop** - -## Content of a pull request - -A new feature has been born. Great! But without the steps below it might just ... fade away ... - -### **Add unit tests for the parsing part** - -This is important so that, if someone else does a change to the grammar that does not know about this great feature, gets notified early on when that change breaks the parser. Another important aspect is that without proper parsing tests refactoring is pretty much impossible. - -### **Add e2e tests** - -This tests the rendering and visual appearance of the diagram. This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks! - -To start working with the e2e tests, run `pnpm run dev` to start the dev server, after that start cypress by running `pnpm exec cypress open` in the mermaid folder. - -The rendering tests are very straightforward to create. There is a function imgSnapshotTest. This function takes a diagram in text form, the mermaid options and renders that diagram in cypress. - -When running in ci it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag for review it if it differs. - -This is what a rendering test looks like: - -```javascript -it('should render forks and joins', () => { - imgSnapshotTest( - ` - stateDiagram - 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 --> [*] - `, - { logLevel: 0 } - ); - cy.get('svg'); -}); -``` - -### **Add documentation for it** - -Finally, if it is not in the documentation, no one will know about it and then **no one will use it**. Wouldn't that be sad? With all the effort that was put into the feature? - -The source files for documentation are in `/packages/mermaid/src/docs` and are written in markdown. Just pick the right section and start typing. See the [Committing Documentation](#committing-documentation) section for more about how the documentation is generated. - -#### Adding to or changing the documentation organization - -If you want to add a new section or change the organization (structure), then you need to make sure to **change the side navigation** in `mermaid/src/docs/.vitepress/config.js`. - -When changes are committed and then released, they become part of the `master` branch and become part of the published documentation on https://mermaid-js.github.io/mermaid/ - -## Last words - -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. +The `/docs` folder will be rebuilt and committed as part of a pre-commit hook. [Join our slack community if you want closer contact!](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) - -![A superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif) diff --git a/README.md b/README.md index f4cf8e105..98741a689 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Mermaid Generate diagrams from markdown-like text.

- +

@@ -27,7 +27,7 @@ Generate diagrams from markdown-like text. [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid) -[![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) +[![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 Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) @@ -60,7 +60,7 @@ Use Mermaid with your favorite applications, check out the list of [Integrations You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications—check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations.md). -For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/community/n00b-overview.md), [Usage](./docs/config/usage.md) and [Tutorials](./docs/config/Tutorials.md). +For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/intro/getting-started.md), [Usage](./docs/config/usage.md) and [Tutorials](./docs/config/Tutorials.md). 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. @@ -165,6 +165,13 @@ class Class10 { int id size() } +namespace Namespace01 { + class Class11 + class Class12 { + int id + size() + } +} ``` ```mermaid @@ -184,6 +191,13 @@ class Class10 { int id size() } +namespace Namespace01 { + class Class11 + class Class12 { + int id + size() + } +} ``` ### State diagram [docs - live editor] @@ -226,6 +240,44 @@ pie ### Git graph [experimental - live editor] +### Bar chart (using gantt chart) [docs - live editor] + +``` +gantt + title Git Issues - days since last update + dateFormat X + axisFormat %s + + section Issue19062 + 71 : 0, 71 + section Issue19401 + 36 : 0, 36 + section Issue193 + 34 : 0, 34 + section Issue7441 + 9 : 0, 9 + section Issue1300 + 5 : 0, 5 +``` + +```mermaid +gantt + title Git Issues - days since last update + dateFormat X + axisFormat %s + + section Issue19062 + 71 : 0, 71 + section Issue19401 + 36 : 0, 36 + section Issue193 + 34 : 0, 34 + section Issue7441 + 9 : 0, 9 + section Issue1300 + 5 : 0, 5 +``` + ### User Journey diagram [docs - live editor] ``` @@ -334,7 +386,7 @@ Update version number in `package.json`. npm publish ``` -The above command generates files into the `dist` folder and publishes them to npmjs.org. +The above command generates files into the `dist` folder and publishes them to . ## Related projects @@ -350,7 +402,7 @@ Detailed information about how to contribute can be found in the [contribution g ## Security and safe diagrams -For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitise the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes. +For public sites, it can be precarious to retrieve text from users on the internet, storing that content for presentation in a browser at a later stage. The reason is that the user content can contain embedded malicious scripts that will run when the data is presented. For Mermaid this is a risk, specially as mermaid diagrams contain many characters that are used in html which makes the standard sanitation unusable as it also breaks the diagrams. We still make an effort to sanitize the incoming code and keep refining the process but it is hard to guarantee that there are no loop holes. 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. @@ -358,7 +410,7 @@ _Unfortunately you can not have a cake and eat it at the same time which in this ## Reporting vulnerabilities -To report a vulnerability, please e-mail security@mermaid.live with a description of the issue, the steps you took to create the issue, affected versions, and if known, mitigations for the issue. +To report a vulnerability, please e-mail with a description of the issue, the steps you took to create the issue, affected versions, and if known, mitigations for the issue. ## Appreciation diff --git a/README.zh-CN.md b/README.zh-CN.md index 65cf38645..80e715509 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -8,7 +8,7 @@ Mermaid 通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。

- +

@@ -27,7 +27,7 @@ Mermaid [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid) -[![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master) +[![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 Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) @@ -55,7 +55,7 @@ Mermaid 通过允许用户创建便于修改的图表来解决这一难题,它 Mermaid 甚至能让非程序员也能通过 [Mermaid Live Editor](https://mermaid.live/) 轻松创建详细的图表。
你可以访问 [教程](./docs/config/Tutorials.md) 来查看 Live Editor 的视频教程,也可以查看 [Mermaid 的集成和使用](./docs/ecosystem/integrations.md) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。 -如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/community/n00b-overview.md), [用法](./docs/config/usage.md) 和 [教程](./docs/config/Tutorials.md). +如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/intro/getting-started.md), [用法](./docs/config/usage.md) 和 [教程](./docs/config/Tutorials.md). @@ -322,7 +322,7 @@ Rel(SystemC, customerA, "Sends e-mails to") npm publish ``` -以上的命令会将文件打包到 `dist` 目录并发布至 npmjs.org. +以上的命令会将文件打包到 `dist` 目录并发布至 . ## 相关项目 diff --git a/V10-BreakingChanges.md b/V10-BreakingChanges.md deleted file mode 100644 index 121fdd596..000000000 --- a/V10-BreakingChanges.md +++ /dev/null @@ -1,58 +0,0 @@ -# A collection of updates that change the behavior - -## Async - -`parse`, `render` are now async. - -## Lazy loading and asynchronisity - -- Invalid dates are rendered as syntax error instead of returning best guess or the current date - -## ParseError is removed - -```js -//< v10.0.0 -mermaid.parse(text, parseError); - -//>= v10.0.0 -await mermaid.parse(text).catch(parseError); -// or -try { - await mermaid.parse(text); -} catch (err) { - parseError(err); -} -``` - -## Init deprecated and InitThrowsErrors removed - -The config passed to `init` was not being used eariler. -It will now be used. -The `init` function is deprecated and will be removed in the next major release. -init currently works as a wrapper to `initialize` and `run`. - -```js -//< v10.0.0 -mermaid.init(config, selector, cb); - -//>= v10.0.0 -mermaid.initialize(config); -mermaid.run({ - querySelector: selector, - postRenderCallback: cb, - suppressErrors: true, -}); -``` - -```js -//< v10.0.0 -mermaid.initThrowsErrors(config, selector, cb); - -//>= v10.0.0 -mermaid.initialize(config); -mermaid.run({ - querySelector: selector, - postRenderCallback: cb, - suppressErrors: false, -}); -``` diff --git a/__mocks__/d3.ts b/__mocks__/d3.ts index af35020c5..97bd01665 100644 --- a/__mocks__/d3.ts +++ b/__mocks__/d3.ts @@ -1,5 +1,4 @@ -// @ts-nocheck TODO: Fix TS -import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3'; +import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3.js'; export const select = function () { return new MockedD3(); diff --git a/__mocks__/pieRenderer.ts b/__mocks__/pieRenderer.ts new file mode 100644 index 000000000..439800f8c --- /dev/null +++ b/__mocks__/pieRenderer.ts @@ -0,0 +1,8 @@ +/** + * Mocked pie (picChart) diagram renderer + */ +import { vi } from 'vitest'; + +const draw = vi.fn().mockImplementation(() => ''); + +export const renderer = { draw }; diff --git a/__mocks__/pieRenderer.js b/__mocks__/sankeyRenderer.js similarity index 76% rename from __mocks__/pieRenderer.js rename to __mocks__/sankeyRenderer.js index 317c69901..76324c93f 100644 --- a/__mocks__/pieRenderer.js +++ b/__mocks__/sankeyRenderer.js @@ -1,5 +1,5 @@ /** - * Mocked pie (picChart) diagram renderer + * Mocked Sankey diagram renderer */ import { vi } from 'vitest'; diff --git a/cSpell.json b/cSpell.json index 6f93af103..e8d718316 100644 --- a/cSpell.json +++ b/cSpell.json @@ -5,11 +5,14 @@ "acyclicer", "adamiecki", "alois", + "aloisklink", "antiscript", + "antlr", "appli", "applitools", "asciidoctor", "ashish", + "ashishjain", "astah", "bbox", "bilkent", @@ -19,23 +22,32 @@ "brkt", "brolin", "brotli", + "città", "classdef", "codedoc", "colour", + "commitlint", "cpettitt", "customizability", "cuzon", "cytoscape", "dagre", + "deepdwn", "descr", "docsify", "docsy", "doku", "dompurify", + "dont", + "doublecircle", "edgechromium", + "elems", "elkjs", + "elle", "faber", "flatmap", + "foswiki", + "frontmatter", "ftplugin", "gantt", "gitea", @@ -45,30 +57,48 @@ "graphviz", "grav", "greywolf", + "gzipped", + "huynh", + "huynhicode", "inkdrop", "jaoude", + "jgreywolf", "jison", + "jiti", "kaufmann", "khroma", "klemm", "klink", "knsv", "knut", + "knutsveidqvist", "laganeckas", + "linetype", "lintstagedrc", "logmsg", "lucida", + "markdownish", "matthieu", + "matthieumorel", "mdast", "mdbook", + "mermaidjs", "mermerd", "mindaugas", "mindmap", "mindmaps", "mitigations", "mkdocs", + "mmorel", "mult", + "neurodiverse", + "nextra", + "nikolay", + "nirname", + "npmjs", "orlandoni", + "pathe", + "pbrolin", "phpbb", "plantuml", "playfair", @@ -79,17 +109,29 @@ "ranksep", "rect", "rects", + "reda", "redmine", + "regexes", + "rehype", "roledescription", + "rozhkov", "sandboxed", + "sankey", "setupgraphviewbox", "shiki", "sidharth", "sidharthv", "sphinxcontrib", + "startx", + "starty", "statediagram", + "steph", + "stopx", + "stopy", "stylis", + "subhash-halder", "substate", + "sulais", "sveidqvist", "swimm", "techn", @@ -97,16 +139,26 @@ "textlength", "treemap", "ts-nocheck", + "tsdoc", "tuleap", + "tylerlong", + "typora", "ugge", "unist", + "unocss", + "upvoting", + "valign", "verdana", "viewports", "vinod", "visio", "vitepress", + "vueuse", "xlink", - "yash" + "yash", + "yokozuna", + "zenuml", + "zune" ], "patterns": [ { "name": "Markdown links", "pattern": "\\((.*)\\)", "description": "" }, @@ -146,6 +198,7 @@ ], "ignorePaths": [ "packages/mermaid/src/docs/CHANGELOG.md", - "packages/mermaid/src/docs/.vitepress/redirect.ts" + "packages/mermaid/src/docs/.vitepress/redirect.ts", + "packages/mermaid/src/docs/.vitepress/contributor-names.json" ] } diff --git a/cypress.config.cjs b/cypress.config.cjs index 6fe0ae5ab..30076c56e 100644 --- a/cypress.config.cjs +++ b/cypress.config.cjs @@ -2,12 +2,14 @@ const { defineConfig } = require('cypress'); const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin'); +const coverage = require('@cypress/code-coverage/task'); module.exports = defineConfig({ projectId: 'n2sma2', e2e: { specPattern: 'cypress/integration/**/*.{js,jsx,ts,tsx}', setupNodeEvents(on, config) { + coverage(on, config); addMatchImageSnapshotPlugin(on, config); // copy any needed variables from process.env to config.env config.env.useAppli = process.env.USE_APPLI ? true : false; diff --git a/cypress/helpers/util.js b/cypress/helpers/util.js deleted file mode 100644 index 533cca499..000000000 --- a/cypress/helpers/util.js +++ /dev/null @@ -1,93 +0,0 @@ -const utf8ToB64 = (str) => { - return window.btoa(unescape(encodeURIComponent(str))); -}; - -const batchId = 'mermaid-batch' + new Date().getTime(); - -export const mermaidUrl = (graphStr, options, api) => { - const obj = { - code: graphStr, - mermaid: options, - }; - const objStr = JSON.stringify(obj); - let url = 'http://localhost:9000/e2e.html?graph=' + utf8ToB64(objStr); - if (api) { - url = 'http://localhost:9000/xss.html?graph=' + graphStr; - } - - if (options.listUrl) { - cy.log(options.listId, ' ', url); - } - - return url; -}; - -export const imgSnapshotTest = (graphStr, _options, api = false, validation) => { - cy.log(_options); - const options = Object.assign(_options); - if (!options.fontFamily) { - options.fontFamily = 'courier'; - } - if (!options.sequence) { - options.sequence = {}; - } - if (!options.sequence || (options.sequence && !options.sequence.actorFontFamily)) { - options.sequence.actorFontFamily = 'courier'; - } - if (options.sequence && !options.sequence.noteFontFamily) { - options.sequence.noteFontFamily = 'courier'; - } - options.sequence.actorFontFamily = 'courier'; - options.sequence.noteFontFamily = 'courier'; - options.sequence.messageFontFamily = 'courier'; - if (options.sequence && !options.sequence.actorFontFamily) { - options.sequence.actorFontFamily = 'courier'; - } - if (!options.fontSize) { - options.fontSize = '16px'; - } - const url = mermaidUrl(graphStr, options, api); - openURLAndVerifyRendering(url, options, validation); -}; - -export const urlSnapshotTest = (url, _options, api = false, validation) => { - const options = Object.assign(_options); - openURLAndVerifyRendering(url, options, validation); -}; - -export const renderGraph = (graphStr, options, api) => { - const url = mermaidUrl(graphStr, options, api); - openURLAndVerifyRendering(url, options); -}; - -const openURLAndVerifyRendering = (url, options, validation = undefined) => { - const useAppli = Cypress.env('useAppli'); - const name = (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, - }); - } - - cy.visit(url); - cy.window().should('have.property', 'rendered', true); - cy.get('svg').should('be.visible'); - - if (validation) { - cy.get('svg').should(validation); - } - - if (useAppli) { - cy.log('Check eyes' + Cypress.spec.name); - cy.eyesCheckWindow('Click!'); - cy.log('Closing eyes' + Cypress.spec.name); - cy.eyesClose(); - } else { - cy.matchImageSnapshot(name); - } -}; diff --git a/cypress/helpers/util.ts b/cypress/helpers/util.ts new file mode 100644 index 000000000..4160f4cbd --- /dev/null +++ b/cypress/helpers/util.ts @@ -0,0 +1,136 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Buffer } from 'buffer'; +import type { MermaidConfig } from '../../packages/mermaid/src/config.type.js'; + +interface CypressConfig { + listUrl?: boolean; + listId?: string; + name?: string; +} +type CypressMermaidConfig = MermaidConfig & CypressConfig; + +interface CodeObject { + code: string; + mermaid: CypressMermaidConfig; +} + +const utf8ToB64 = (str: string): string => { + return Buffer.from(decodeURIComponent(encodeURIComponent(str))).toString('base64'); +}; + +const batchId: string = + 'mermaid-batch-' + + (Cypress.env('useAppli') + ? Date.now().toString() + : Cypress.env('CYPRESS_COMMIT') || Date.now().toString()); + +export const mermaidUrl = ( + graphStr: string, + options: CypressMermaidConfig, + api: boolean +): string => { + 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) { + url = `http://localhost:9000/xss.html?graph=${graphStr}`; + } + + if (options.listUrl) { + cy.log(options.listId, ' ', url); + } + + return url; +}; + +export const imgSnapshotTest = ( + graphStr: string, + _options: CypressMermaidConfig = {}, + api = false, + validation?: any +): void => { + cy.log(JSON.stringify(_options)); + const options: CypressMermaidConfig = Object.assign(_options); + if (!options.fontFamily) { + options.fontFamily = 'courier'; + } + if (!options.sequence) { + options.sequence = {}; + } + if (!options.sequence || (options.sequence && !options.sequence.actorFontFamily)) { + options.sequence.actorFontFamily = 'courier'; + } + if (options.sequence && !options.sequence.noteFontFamily) { + options.sequence.noteFontFamily = 'courier'; + } + options.sequence.actorFontFamily = 'courier'; + options.sequence.noteFontFamily = 'courier'; + options.sequence.messageFontFamily = 'courier'; + if (options.sequence && !options.sequence.actorFontFamily) { + options.sequence.actorFontFamily = 'courier'; + } + if (!options.fontSize) { + options.fontSize = 16; + } + + const url: string = mermaidUrl(graphStr, options, api); + openURLAndVerifyRendering(url, options, validation); +}; + +export const urlSnapshotTest = ( + url: string, + _options: CypressMermaidConfig, + _api = false, + validation?: any +): void => { + const options: CypressMermaidConfig = Object.assign(_options); + openURLAndVerifyRendering(url, options, validation); +}; + +export const renderGraph = ( + graphStr: string, + options: CypressMermaidConfig = {}, + api = false +): void => { + const url: string = mermaidUrl(graphStr, options, api); + openURLAndVerifyRendering(url, options); +}; + +export const openURLAndVerifyRendering = ( + url: string, + 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, + }); + } + + cy.visit(url); + cy.window().should('have.property', 'rendered', true); + cy.get('svg').should('be.visible'); + + if (validation) { + cy.get('svg').should(validation); + } + + if (useAppli) { + cy.log(`Check eyes ${Cypress.spec.name}`); + cy.eyesCheckWindow('Click!'); + cy.log(`Closing eyes ${Cypress.spec.name}`); + cy.eyesClose(); + } else { + cy.matchImageSnapshot(name); + } +}; diff --git a/cypress/integration/other/configuration.spec.js b/cypress/integration/other/configuration.spec.js index 513cf0714..7cbc5d105 100644 --- a/cypress/integration/other/configuration.spec.js +++ b/cypress/integration/other/configuration.spec.js @@ -1,4 +1,4 @@ -import { renderGraph } from '../../helpers/util'; +import { renderGraph } from '../../helpers/util.ts'; describe('Configuration', () => { describe('arrowMarkerAbsolute', () => { it('should handle default value false of arrowMarkerAbsolute', () => { diff --git a/cypress/integration/other/external-diagrams.spec.js b/cypress/integration/other/external-diagrams.spec.js index c94235162..704222f2f 100644 --- a/cypress/integration/other/external-diagrams.spec.js +++ b/cypress/integration/other/external-diagrams.spec.js @@ -1,4 +1,4 @@ -import { urlSnapshotTest } from '../../helpers/util'; +import { urlSnapshotTest } from '../../helpers/util.ts'; describe('mermaid', () => { describe('registerDiagram', () => { diff --git a/cypress/integration/other/ghsa.spec.js b/cypress/integration/other/ghsa.spec.js index 4fadc7855..48eb57a91 100644 --- a/cypress/integration/other/ghsa.spec.js +++ b/cypress/integration/other/ghsa.spec.js @@ -1,4 +1,4 @@ -import { urlSnapshotTest } from '../../helpers/util'; +import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts'; describe('CSS injections', () => { it('should not allow CSS injections outside of the diagram', () => { @@ -13,4 +13,11 @@ describe('CSS injections', () => { flowchart: { htmlLabels: false }, }); }); + it('should not allow manipulating styletags using arrowheads', () => { + openURLAndVerifyRendering('http://localhost:9000/xss23-css.html', { + logLevel: 1, + arrowMarkerAbsolute: false, + flowchart: { htmlLabels: true }, + }); + }); }); diff --git a/cypress/integration/other/xss.spec.js b/cypress/integration/other/xss.spec.js index 76b2c47f2..fa4ca4fc8 100644 --- a/cypress/integration/other/xss.spec.js +++ b/cypress/integration/other/xss.spec.js @@ -1,4 +1,4 @@ -import { mermaidUrl } from '../../helpers/util.js'; +import { mermaidUrl } from '../../helpers/util.ts'; describe('XSS', () => { it('should handle xss in tags', () => { const str = diff --git a/cypress/integration/rendering/appli.spec.js b/cypress/integration/rendering/appli.spec.js index 462fe869c..5def96815 100644 --- a/cypress/integration/rendering/appli.spec.js +++ b/cypress/integration/rendering/appli.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('Git Graph diagram', () => { it('1: should render a simple gitgraph with commit on main branch', () => { diff --git a/cypress/integration/rendering/c4.spec.js b/cypress/integration/rendering/c4.spec.js index 0cf128ff6..59af6504b 100644 --- a/cypress/integration/rendering/c4.spec.js +++ b/cypress/integration/rendering/c4.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('C4 diagram', () => { it('should render a simple C4Context diagram', () => { diff --git a/cypress/integration/rendering/classDiagram-v2.spec.js b/cypress/integration/rendering/classDiagram-v2.spec.js index 9536a074d..37e9cada0 100644 --- a/cypress/integration/rendering/classDiagram-v2.spec.js +++ b/cypress/integration/rendering/classDiagram-v2.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('Class diagram V2', () => { it('0: should render a simple class diagram', () => { imgSnapshotTest( @@ -13,7 +13,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('1: should render a simple class diagram', () => { @@ -47,7 +46,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('2: should render a simple class diagrams with cardinality', () => { @@ -76,7 +74,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('should render a simple class diagram with different visibilities', () => { @@ -94,7 +91,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('should render multiple class diagrams', () => { @@ -147,7 +143,6 @@ describe('Class diagram V2', () => { ], { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('4: should render a simple class diagram with comments', () => { @@ -177,7 +172,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('5: should render a simple class diagram with abstract method', () => { @@ -189,7 +183,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('6: should render a simple class diagram with static method', () => { @@ -201,7 +194,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('7: should render a simple class diagram with Generic class', () => { @@ -221,7 +213,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('8: should render a simple class diagram with Generic class and relations', () => { @@ -242,7 +233,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('9: should render a simple class diagram with clickable link', () => { @@ -264,7 +254,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('10: should render a simple class diagram with clickable callback', () => { @@ -286,7 +275,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('11: should render a simple class diagram with return type on method', () => { @@ -301,7 +289,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('12: should render a simple class diagram with generic types', () => { @@ -317,7 +304,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('13: should render a simple class diagram with css classes applied', () => { @@ -335,7 +321,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('14: should render a simple class diagram with css classes applied directly', () => { @@ -351,7 +336,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('15: should render a simple class diagram with css classes applied two multiple classes', () => { @@ -365,7 +349,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('16a: should render a simple class diagram with static field', () => { @@ -378,7 +361,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('16b: should handle the direction statement with TB', () => { @@ -403,32 +385,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); - }); - - it('18: 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, flowchart: { htmlLabels: false } } - ); - cy.get('svg'); }); it('17a: should handle the direction statement with BT', () => { imgSnapshotTest( @@ -452,7 +408,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('17b: should handle the direction statement with RL', () => { imgSnapshotTest( @@ -476,10 +431,33 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); - it('18: should render a simple class diagram with notes', () => { + 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, flowchart: { htmlLabels: false } } + ); + }); + + it('18b: should render a simple class diagram with notes', () => { imgSnapshotTest( ` classDiagram-v2 @@ -493,7 +471,6 @@ describe('Class diagram V2', () => { `, { logLevel: 1, flowchart: { htmlLabels: false } } ); - cy.get('svg'); }); it('1433: should render a simple class with a title', () => { @@ -503,8 +480,95 @@ title: simple class diagram --- classDiagram-v2 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-v2 + class Class10 + `, + { logLevel: 1, flowchart: { htmlLabels: false } } ); }); }); diff --git a/cypress/integration/rendering/classDiagram.spec.js b/cypress/integration/rendering/classDiagram.spec.js index e21be67ec..a23430b08 100644 --- a/cypress/integration/rendering/classDiagram.spec.js +++ b/cypress/integration/rendering/classDiagram.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('Class diagram', () => { it('1: should render a simple class diagram', () => { @@ -286,7 +286,7 @@ describe('Class diagram', () => { cy.get('svg'); }); - it('15: should render a simple class diagram with css classes applied two multiple classes', () => { + it('15: should render a simple class diagram with css classes applied to multiple classes', () => { imgSnapshotTest( ` classDiagram @@ -423,4 +423,82 @@ describe('Class diagram', () => { ); cy.get('svg'); }); + + it('should render class diagram with newlines in title', () => { + imgSnapshotTest(` + classDiagram + Animal <|-- \`Du\nck\` + Animal : +int age + Animal : +String gender + Animal: +isMammal() + Animal: +mate() + class \`Du\nck\` { + +String beakColor + +String featherColor + +swim() + +quack() + } + `); + cy.get('svg'); + }); + + it('should render class diagram with many newlines in title', () => { + imgSnapshotTest(` + classDiagram + class \`This\nTitle\nHas\nMany\nNewlines\` { + +String Also + -Stirng Many + #int Members + +And() + -Many() + #Methods() + } + `); + }); + + it('should render with newlines in title and an annotation', () => { + imgSnapshotTest(` + classDiagram + class \`This\nTitle\nHas\nMany\nNewlines\` { + +String Also + -Stirng Many + #int Members + +And() + -Many() + #Methods() + } + <<Interface>> \`This\nTitle\nHas\nMany\nNewlines\` + `); + }); + + it('should handle newline title in namespace', () => { + imgSnapshotTest(` + classDiagram + namespace testingNamespace { + class \`This\nTitle\nHas\nMany\nNewlines\` { + +String Also + -Stirng Many + #int Members + +And() + -Many() + #Methods() + } + } + `); + }); + + it('should handle newline in string label', () => { + imgSnapshotTest(` + classDiagram + class A["This has\na newline!"] { + +String boop + -Int beep + #double bop + } + + class B["This title also has\na newline"] + B : +with(more) + B : -methods() + `); + }); }); diff --git a/cypress/integration/rendering/conf-and-directives.spec.js b/cypress/integration/rendering/conf-and-directives.spec.js index 3fc0f7f02..401a24894 100644 --- a/cypress/integration/rendering/conf-and-directives.spec.js +++ b/cypress/integration/rendering/conf-and-directives.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('Configuration and directives - nodes should be light blue', () => { it('No config - use default', () => { @@ -14,7 +14,6 @@ describe('Configuration and directives - nodes should be light blue', () => { `, {} ); - cy.get('svg'); }); it('Settings from initialize - nodes should be green', () => { imgSnapshotTest( @@ -28,7 +27,6 @@ graph TD end `, { theme: 'forest' } ); - cy.get('svg'); }); it('Settings from initialize overriding themeVariable - nodes should be red', () => { imgSnapshotTest( @@ -46,7 +44,6 @@ graph TD `, { theme: 'base', themeVariables: { primaryColor: '#ff0000' }, logLevel: 0 } ); - cy.get('svg'); }); it('Settings from directive - nodes should be grey', () => { imgSnapshotTest( @@ -62,7 +59,24 @@ graph TD `, {} ); - cy.get('svg'); + }); + it('Settings from frontmatter - nodes should be grey', () => { + imgSnapshotTest( + ` +--- +config: + theme: neutral +--- +graph TD + A(Start) --> B[/Another/] + A[/Another/] --> C[End] + subgraph section + B + C + end + `, + {} + ); }); it('Settings from directive overriding theme variable - nodes should be red', () => { @@ -79,7 +93,6 @@ graph TD `, {} ); - cy.get('svg'); }); it('Settings from initialize and directive - nodes should be grey', () => { imgSnapshotTest( @@ -95,7 +108,6 @@ graph TD `, { theme: 'forest' } ); - cy.get('svg'); }); it('Theme from initialize, directive overriding theme variable - nodes should be red', () => { imgSnapshotTest( @@ -111,8 +123,71 @@ graph TD `, { theme: 'base' } ); - cy.get('svg'); }); + it('Theme from initialize, frontmatter overriding theme variable - nodes should be red', () => { + imgSnapshotTest( + ` +--- +config: + theme: base + themeVariables: + primaryColor: '#ff0000' +--- +graph TD + A(Start) --> B[/Another/] + A[/Another/] --> C[End] + subgraph section + B + C + end + `, + { theme: 'forest' } + ); + }); + it('Theme from initialize, frontmatter overriding theme variable, directive overriding primaryColor - nodes should be red', () => { + imgSnapshotTest( + ` +--- +config: + theme: base + themeVariables: + primaryColor: '#00ff00' +--- +%%{init: {'theme': 'base', 'themeVariables':{ 'primaryColor': '#ff0000'}}}%% +graph TD + A(Start) --> B[/Another/] + A[/Another/] --> C[End] + subgraph section + B + C + end + `, + { theme: 'forest' } + ); + }); + + it('should render if values are not quoted properly', () => { + // #ff0000 is not quoted properly, and will evaluate to null. + // This test ensures that the rendering still works. + imgSnapshotTest( + `--- +config: + theme: base + themeVariables: + primaryColor: #ff0000 +--- +graph TD + A(Start) --> B[/Another/] + A[/Another/] --> C[End] + subgraph section + B + C + end + `, + { theme: 'forest' } + ); + }); + it('Theme variable from initialize, theme from directive - nodes should be red', () => { imgSnapshotTest( ` @@ -127,13 +202,11 @@ graph TD `, { themeVariables: { primaryColor: '#ff0000' } } ); - cy.get('svg'); }); describe('when rendering several diagrams', () => { it('diagrams should not taint later diagrams', () => { const url = 'http://localhost:9000/theme-directives.html'; cy.visit(url); - cy.get('svg'); cy.matchImageSnapshot('conf-and-directives.spec-when-rendering-several-diagrams-diagram-1'); }); }); diff --git a/cypress/integration/rendering/current.spec.js b/cypress/integration/rendering/current.spec.js index 033752c66..d7bc08105 100644 --- a/cypress/integration/rendering/current.spec.js +++ b/cypress/integration/rendering/current.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('Current diagram', () => { it('should render a state with states in it', () => { diff --git a/cypress/integration/rendering/debug.spec.js b/cypress/integration/rendering/debug.spec.js index 673cadf3e..56ad0f15f 100644 --- a/cypress/integration/rendering/debug.spec.js +++ b/cypress/integration/rendering/debug.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('Flowchart', () => { it('34: testing the label width in percy', () => { diff --git a/cypress/integration/rendering/erDiagram.spec.js b/cypress/integration/rendering/erDiagram.spec.js index c72df49b6..578f5a398 100644 --- a/cypress/integration/rendering/erDiagram.spec.js +++ b/cypress/integration/rendering/erDiagram.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('Entity Relationship Diagram', () => { it('should render a simple ER diagram', () => { @@ -10,7 +10,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagram with a recursive relationship', () => { @@ -23,7 +22,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagram with multiple relationships between the same two entities', () => { @@ -35,7 +33,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render a cyclical ER diagram', () => { @@ -48,7 +45,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render a not-so-simple ER diagram', () => { @@ -66,7 +62,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render multiple ER diagrams', () => { @@ -85,7 +80,6 @@ describe('Entity Relationship Diagram', () => { ], { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagram with blank or empty labels', () => { @@ -98,7 +92,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render an ER diagrams when useMaxWidth is true (default)', () => { @@ -151,7 +144,6 @@ describe('Entity Relationship Diagram', () => { `, { er: { useMaxWidth: false } } ); - cy.get('svg'); }); it('should render entities with and without attributes', () => { @@ -164,7 +156,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with generic and array attributes', () => { @@ -179,7 +170,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with length in attributes type', () => { @@ -188,12 +178,11 @@ describe('Entity Relationship Diagram', () => { erDiagram CLUSTER { varchar(99) name - string(255) description + string(255) description } `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities and attributes with big and small entity names', () => { @@ -209,6 +198,26 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); + }); + + it('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 + } + `, + { loglevel: 1 } + ); cy.get('svg'); }); @@ -228,7 +237,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with comments', () => { @@ -247,7 +255,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with keys and comments', () => { @@ -267,7 +274,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('should render entities with aliases', () => { @@ -285,7 +291,6 @@ describe('Entity Relationship Diagram', () => { `, { logLevel: 1 } ); - cy.get('svg'); }); it('1433: should render a simple ER diagram with a title', () => { @@ -300,4 +305,21 @@ ORDER ||--|{ LINE-ITEM : contains {} ); }); + + it('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 + `, + { logLevel: 1 } + ); + }); }); diff --git a/cypress/integration/rendering/errorDiagram.spec.js b/cypress/integration/rendering/errorDiagram.spec.js new file mode 100644 index 000000000..e837565d3 --- /dev/null +++ b/cypress/integration/rendering/errorDiagram.spec.js @@ -0,0 +1,45 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +describe('Error Diagrams', () => { + beforeEach(() => { + cy.on('uncaught:exception', (err) => { + expect(err.message).to.include('Parse error'); + // return false to prevent the error from + // failing this test + return false; + }); + }); + + it('should render a simple ER diagram', () => { + imgSnapshotTest( + ` + error + `, + { logLevel: 1 } + ); + }); + + it('should render error diagram for actual errors', () => { + imgSnapshotTest( + ` + flowchart TD + A[Christmas] --|Get money| B(Go shopping) + `, + { logLevel: 1 } + ); + }); + + it('should render error for wrong ER diagram', () => { + imgSnapshotTest( + ` + erDiagram + ATLAS-ORGANIZATION ||--|{ ATLAS-PROJECTS : "has many" + ATLAS-PROJECTS ||--|{ MONGODB-CLUSTERS : "has many" + ATLAS-PROJECTS ||--|{ ATLAS-TEAMS : "has many" + MONGODB-CLUSTERS ||..|{ + ATLAS-TEAMS ||..|{ + `, + { logLevel: 1 } + ); + }); +}); diff --git a/cypress/integration/rendering/flowchart-elk.spec.js b/cypress/integration/rendering/flowchart-elk.spec.js index 0d4ec4211..a5292afd1 100644 --- a/cypress/integration/rendering/flowchart-elk.spec.js +++ b/cypress/integration/rendering/flowchart-elk.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('Flowchart ELK', () => { it('1-elk: should render a simple flowchart', () => { @@ -681,7 +681,166 @@ title: Simple flowchart flowchart-elk TD A --> B `, - { titleTopMargin: 0 } + { flowchart: { titleTopMargin: 0 } } ); }); + it('elk: should include classes on the edges', () => { + renderGraph( + `flowchart-elk TD + A --> B --> C --> D + `, + {} + ); + cy.get('svg').should((svg) => { + const edges = svg.querySelectorAll('.edges > path'); + edges.forEach((edge) => { + expect(edge).to.have.class('flowchart-link'); + }); + }); + }); + describe('Markdown strings flowchart-elk (#4220)', () => { + describe('html labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + 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 + classDef someclass fill:#f96 +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR +b(\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`) --> c + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart-elk LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + }); + + describe('svg text labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + 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 + classDef someclass fill:#f96 +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR +b("\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart-elk LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + }); + }); }); diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 30ae4f0d2..aac4a31b1 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('Flowchart v2', () => { it('1: should render a simple flowchart', () => { @@ -172,7 +172,7 @@ describe('Flowchart v2', () => { ); }); - it('52: handle nested subgraphs in several levels', () => { + it('52: handle nested subgraphs in several levels.', () => { imgSnapshotTest( `flowchart TB b-->B @@ -449,7 +449,7 @@ flowchart TD { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); - it('65: text-color from classes', () => { + it('65-1: text-color from classes', () => { imgSnapshotTest( ` flowchart LR @@ -460,6 +460,31 @@ flowchart TD { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); + it('65-2: bold text from classes', () => { + imgSnapshotTest( + ` + flowchart + classDef cat fill:#f9d5e5, stroke:#233d4d,stroke-width:2px, font-weight:bold; + CS(A long bold text to be viewed):::cat + `, + { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } + ); + }); + it('65-3: bigger font from classes', () => { + imgSnapshotTest( + ` +flowchart + Node1:::class1 --> Node2:::class2 + Node1:::class1 --> Node3:::class2 + Node3 --> Node4((I am a circle)):::larger + + classDef class1 fill:lightblue + classDef class2 fill:pink + classDef larger font-size:30px,fill:yellow + `, + { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } + ); + }); it('66: More nested subgraph cases (TB)', () => { imgSnapshotTest( ` @@ -671,7 +696,182 @@ title: Simple flowchart flowchart TD A --> B `, - { titleTopMargin: 0 } + { flowchart: { titleTopMargin: 10 } } ); }); + it('3192: It should be possieble to render flowcharts with invisible edges', () => { + imgSnapshotTest( + `--- +title: Simple flowchart with invisible edges +--- +flowchart TD +A ~~~ B +`, + { flowchart: { titleTopMargin: 10 } } + ); + }); + it('4023: Should render html labels with images and-or text correctly', () => { + imgSnapshotTest( + `flowchart TD + B[] + B-->C[ more text ] + B-->D( some text) + B-->E(plain)`, + {} + ); + }); + + it('4439: Should render the graph even if some images are missing', () => { + imgSnapshotTest( + `flowchart TD + B[] + B-->C[]`, + {} + ); + }); + describe('Markdown strings flowchart (#4220)', () => { + describe('html labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + 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 + classDef someclass fill:#f96 +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +b("\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": true}} }%% +flowchart LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + }); + + describe('svg text labels', () => { + it('With styling and classes', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR + A:::someclass --> B["\`The **cat** in the hat\`"]:::someclass + 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 + classDef someclass fill:#f96 +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('With formatting in a node', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR + a{"\`The **cat** in the hat\`"} -- 1o --> b + a -- 2o --> c + a -- 3o --> d + g --2i--> a + d --1i--> a + h --3i -->a + b --> d(The dog in the hog) + c --> d +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('New line in node and formatted edge label', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR +b("\`The dog in **the** hog.(1) +NL\`") --"\`1o **bold**\`"--> c +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Wrapping long text with a new line', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR +b("\`The dog in **the** hog.(1).. a a a a *very long text* about it +Word! + +Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. \`") --> c + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + it('Sub graphs and markdown strings', () => { + imgSnapshotTest( + `%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end + +`, + { flowchart: { titleTopMargin: 0 } } + ); + }); + }); + }); }); diff --git a/cypress/integration/rendering/flowchart.spec.js b/cypress/integration/rendering/flowchart.spec.js index c4ef54fcf..e4766e792 100644 --- a/cypress/integration/rendering/flowchart.spec.js +++ b/cypress/integration/rendering/flowchart.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('Graph', () => { it('1: should render a simple flowchart no htmlLabels', () => { @@ -891,4 +891,27 @@ graph TD { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); + it('66: apply class called default on node called default', () => { + imgSnapshotTest( + ` + graph TD + classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff + hello --> default + `, + { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } + ); + }); + + it('67: should be able to style default node independently', () => { + imgSnapshotTest( + ` + flowchart TD + classDef default fill:#a34 + hello --> default + + style default stroke:#000,stroke-width:4px + `, + { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } + ); + }); }); diff --git a/cypress/integration/rendering/gantt.spec.js b/cypress/integration/rendering/gantt.spec.js index c0156eee3..7c1690952 100644 --- a/cypress/integration/rendering/gantt.spec.js +++ b/cypress/integration/rendering/gantt.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('Gantt diagram', () => { beforeEach(() => { @@ -133,6 +133,24 @@ describe('Gantt diagram', () => { ); }); + it('should default to showing today marker', () => { + // This test only works if the environment thinks today is 1010-10-10 + imgSnapshotTest( + ` + gantt + title Show today marker (vertical line should be visible) + dateFormat YYYY-MM-DD + axisFormat %d + %% Should default to being on + %% todayMarker on + section Section1 + Yesterday: 1010-10-09, 1d + Today: 1010-10-10, 1d + `, + {} + ); + }); + it('should hide today marker', () => { imgSnapshotTest( ` @@ -142,7 +160,8 @@ describe('Gantt diagram', () => { axisFormat %d todayMarker off section Section1 - Today: 1, -1h + Yesterday: 1010-10-09, 1d + Today: 1010-10-10, 1d `, {} ); @@ -157,7 +176,8 @@ describe('Gantt diagram', () => { axisFormat %d todayMarker stroke-width:5px,stroke:#00f,opacity:0.5 section Section1 - Today: 1, -1h + Yesterday: 1010-10-09, 1d + Today: 1010-10-10, 1d `, {} ); @@ -310,6 +330,48 @@ describe('Gantt diagram', () => { ); }); + it('should render a gantt diagram with tick is 2 milliseconds', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat SSS + axisFormat %Lms + tickInterval 2millisecond + excludes weekends + + section Section + A task : a1, 000, 6ms + Another task : after a1, 6ms + section Another + Task in sec : a2, 006, 3ms + another task : 3ms + `, + {} + ); + }); + + it('should render a gantt diagram with tick is 2 seconds', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat ss + axisFormat %Ss + tickInterval 2second + excludes weekends + + section Section + A task : a1, 00, 6s + Another task : after a1, 6s + section Another + Task in sec : 06, 3s + another task : 3s + `, + {} + ); + }); + it('should render a gantt diagram with tick is 15 minutes', () => { imgSnapshotTest( ` @@ -394,6 +456,28 @@ describe('Gantt diagram', () => { ); }); + it('should render a gantt diagram with tick is 1 week, with the day starting on monday', () => { + imgSnapshotTest( + ` + gantt + title A Gantt Diagram + dateFormat YYYY-MM-DD + axisFormat %m-%d + tickInterval 1week + weekday monday + excludes weekends + + section Section + A task : a1, 2022-10-01, 30d + Another task : after a1, 20d + section Another + Task in sec : 2022-10-20, 12d + another task : 24d + `, + {} + ); + }); + it('should render a gantt diagram with tick is 1 month', () => { imgSnapshotTest( ` @@ -435,4 +519,39 @@ describe('Gantt diagram', () => { { gantt: { topAxis: true } } ); }); + + it('should render when compact is true', () => { + imgSnapshotTest( + ` + --- + displayMode: compact + --- + gantt + title GANTT compact + dateFormat HH:mm:ss + axisFormat %Hh%M + + section DB Clean + Clean: 12:00:00, 10m + Clean: 12:30:00, 12m + Clean: 13:00:00, 8m + Clean: 13:30:00, 9m + Clean: 14:00:00, 13m + Clean: 14:30:00, 10m + Clean: 15:00:00, 11m + + section Sessions + A: 12:00:00, 63m + B: 12:30:00, 12m + C: 13:05:00, 12m + D: 13:06:00, 33m + E: 13:15:00, 55m + F: 13:20:00, 12m + G: 13:32:00, 18m + H: 13:50:00, 20m + I: 14:10:00, 10m + `, + {} + ); + }); }); diff --git a/cypress/integration/rendering/gitGraph.spec.js b/cypress/integration/rendering/gitGraph.spec.js index 43f91a983..c01a55796 100644 --- a/cypress/integration/rendering/gitGraph.spec.js +++ b/cypress/integration/rendering/gitGraph.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('Git Graph diagram', () => { it('1: should render a simple gitgraph with commit on main branch', () => { @@ -333,4 +333,372 @@ gitGraph {} ); }); + it('15: should render a simple gitgraph with commit on main branch | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "1" + commit id: "2" + commit id: "3" + `, + {} + ); + }); + it('16: should render a simple gitgraph with commit on main branch with Id | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "One" + commit id: "Two" + commit id: "Three" + `, + {} + ); + }); + it('17: should render a simple gitgraph with different commitTypes on main branch | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "Normal Commit" + commit id: "Reverse Commit" type: REVERSE + commit id: "Hightlight Commit" type: HIGHLIGHT + `, + {} + ); + }); + it('18: should render a simple gitgraph with tags commitTypes on main branch | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "Normal Commit with tag" tag: "v1.0.0" + commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1" + commit id: "Hightlight Commit" type: HIGHLIGHT tag: "8.8.4" + `, + {} + ); + }); + it('19: should render a simple gitgraph with two branches | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "1" + commit id: "2" + branch develop + checkout develop + commit id: "3" + commit id: "4" + checkout main + commit id: "5" + commit id: "6" + `, + {} + ); + }); + it('20: should render a simple gitgraph with two branches and merge commit | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "1" + commit id: "2" + branch develop + checkout develop + commit id: "3" + commit id: "4" + checkout main + merge develop + commit id: "5" + commit id: "6" + `, + {} + ); + }); + it('21: should render a simple gitgraph with three branches and tagged merge commit | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "1" + commit id: "2" + branch nice_feature + checkout nice_feature + commit id: "3" + checkout main + commit id: "4" + checkout nice_feature + branch very_nice_feature + checkout very_nice_feature + commit id: "5" + checkout main + commit id: "6" + checkout nice_feature + commit id: "7" + checkout main + merge nice_feature id: "12345" tag: "my merge commit" + checkout very_nice_feature + commit id: "8" + checkout main + commit id: "9" + `, + {} + ); + }); + it('22: should render a simple gitgraph with more than 8 branchs & overriding variables | Vertical Branch', () => { + imgSnapshotTest( + `%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { + 'gitBranchLabel0': '#ffffff', + 'gitBranchLabel1': '#ffffff', + 'gitBranchLabel2': '#ffffff', + 'gitBranchLabel3': '#ffffff', + 'gitBranchLabel4': '#ffffff', + 'gitBranchLabel5': '#ffffff', + 'gitBranchLabel6': '#ffffff', + 'gitBranchLabel7': '#ffffff', + } } }%% + gitGraph TB: + checkout main + branch branch1 + branch branch2 + branch branch3 + branch branch4 + branch branch5 + branch branch6 + branch branch7 + branch branch8 + branch branch9 + checkout branch1 + commit id: "1" + `, + {} + ); + }); + it('23: should render a simple gitgraph with rotated labels | Vertical Branch', () => { + imgSnapshotTest( + `%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': { + 'rotateCommitLabel': true + } } }%% + gitGraph TB: + commit id: "75f7219e83b321cd3fdde7dcf83bc7c1000a6828" + commit id: "0db4784daf82736dec4569e0dc92980d328c1f2e" + commit id: "7067e9973f9eaa6cd4a4b723c506d1eab598e83e" + commit id: "66972321ad6c199013b5b31f03b3a86fa3f9817d" + `, + {} + ); + }); + it('24: should render a simple gitgraph with horizontal labels | Vertical Branch', () => { + imgSnapshotTest( + `%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': { + 'rotateCommitLabel': false + } } }%% + gitGraph TB: + commit id: "Alpha" + commit id: "Beta" + commit id: "Gamma" + commit id: "Delta" + `, + {} + ); + }); + it('25: should render a simple gitgraph with cherry pick commit | Vertical Branch', () => { + imgSnapshotTest( + ` + gitGraph TB: + commit id: "ZERO" + branch develop + commit id:"A" + checkout main + commit id:"ONE" + checkout develop + commit id:"B" + checkout main + commit id:"TWO" + cherry-pick id:"A" + commit id:"THREE" + checkout develop + commit id:"C" + `, + {} + ); + }); + it('26: should render a gitgraph with cherry pick commit with custom tag | Vertical Branch', () => { + imgSnapshotTest( + ` + gitGraph TB: + commit id: "ZERO" + branch develop + commit id:"A" + checkout main + commit id:"ONE" + checkout develop + commit id:"B" + checkout main + commit id:"TWO" + cherry-pick id:"A" tag: "snapshot" + commit id:"THREE" + checkout develop + commit id:"C" + `, + {} + ); + }); + it('27: should render a gitgraph with cherry pick commit with no tag | Vertical Branch', () => { + imgSnapshotTest( + ` + gitGraph TB: + commit id: "ZERO" + branch develop + commit id:"A" + checkout main + commit id:"ONE" + checkout develop + commit id:"B" + checkout main + commit id:"TWO" + cherry-pick id:"A" tag: "" + commit id:"THREE" + checkout develop + commit id:"C" + `, + {} + ); + }); + it('28: should render a simple gitgraph with two cherry pick commit | Vertical Branch', () => { + imgSnapshotTest( + ` + gitGraph TB: + commit id: "ZERO" + branch develop + commit id:"A" + checkout main + commit id:"ONE" + checkout develop + commit id:"B" + branch featureA + commit id:"FIX" + commit id: "FIX-2" + checkout main + commit id:"TWO" + cherry-pick id:"A" + commit id:"THREE" + cherry-pick id:"FIX" + checkout develop + commit id:"C" + merge featureA + `, + {} + ); + }); + it('29: should render commits for more than 8 branches | Vertical Branch', () => { + imgSnapshotTest( + ` + gitGraph TB: + checkout main + %% Make sure to manually set the ID of all commits, for consistent visual tests + commit id: "1-abcdefg" + checkout main + branch branch1 + commit id: "2-abcdefg" + checkout main + merge branch1 + branch branch2 + commit id: "3-abcdefg" + checkout main + merge branch2 + branch branch3 + commit id: "4-abcdefg" + checkout main + merge branch3 + branch branch4 + commit id: "5-abcdefg" + checkout main + merge branch4 + branch branch5 + commit id: "6-abcdefg" + checkout main + merge branch5 + branch branch6 + commit id: "7-abcdefg" + checkout main + merge branch6 + branch branch7 + commit id: "8-abcdefg" + checkout main + merge branch7 + branch branch8 + commit id: "9-abcdefg" + checkout main + merge branch8 + branch branch9 + commit id: "10-abcdefg" + `, + {} + ); + }); + it('30: should render a simple gitgraph with three branches,custom merge commit id,tag,type | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id: "1" + commit id: "2" + branch nice_feature + checkout nice_feature + commit id: "3" + checkout main + commit id: "4" + checkout nice_feature + branch very_nice_feature + checkout very_nice_feature + commit id: "5" + checkout main + commit id: "6" + checkout nice_feature + commit id: "7" + checkout main + merge nice_feature id: "customID" tag: "customTag" type: REVERSE + checkout very_nice_feature + commit id: "8" + checkout main + commit id: "9" + `, + {} + ); + }); + it('31: should render a simple gitgraph with a title | Vertical Branch', () => { + imgSnapshotTest( + `--- +title: simple gitGraph +--- +gitGraph TB: + commit id: "1-abcdefg" +`, + {} + ); + }); + it('32: should render a simple gitgraph overlapping commits | Vertical Branch', () => { + imgSnapshotTest( + `gitGraph TB: + commit id:"s1" + commit id:"s2" + branch branch1 + commit id:"s3" + commit id:"s4" + checkout main + commit id:"s5" + checkout branch1 + commit id:"s6" + commit id:"s7" + merge main + `, + {} + ); + }); + it('33: should render a simple gitgraph overlapping commits', () => { + imgSnapshotTest( + `gitGraph + commit id:"s1" + commit id:"s2" + branch branch1 + commit id:"s3" + commit id:"s4" + checkout main + commit id:"s5" + checkout branch1 + commit id:"s6" + commit id:"s7" + merge main + `, + {} + ); + }); }); diff --git a/cypress/integration/rendering/info.spec.js b/cypress/integration/rendering/info.spec.js deleted file mode 100644 index bcfce30e3..000000000 --- a/cypress/integration/rendering/info.spec.js +++ /dev/null @@ -1,13 +0,0 @@ -import { imgSnapshotTest } from '../../helpers/util.js'; - -describe('Sequencediagram', () => { - it('should render a simple info diagrams', () => { - imgSnapshotTest( - ` - info - showInfo - `, - {} - ); - }); -}); diff --git a/cypress/integration/rendering/info.spec.ts b/cypress/integration/rendering/info.spec.ts new file mode 100644 index 000000000..97b384eb5 --- /dev/null +++ b/cypress/integration/rendering/info.spec.ts @@ -0,0 +1,11 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +describe('info diagram', () => { + it('should handle an info definition', () => { + imgSnapshotTest(`info`); + }); + + it('should handle an info definition with showInfo', () => { + imgSnapshotTest(`info showInfo`); + }); +}); diff --git a/cypress/integration/rendering/journey.spec.js b/cypress/integration/rendering/journey.spec.js index 6f9d9bb60..d8bef6d1b 100644 --- a/cypress/integration/rendering/journey.spec.js +++ b/cypress/integration/rendering/journey.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('User journey diagram', () => { it('Simple test', () => { diff --git a/cypress/integration/rendering/mindmap.spec.ts b/cypress/integration/rendering/mindmap.spec.ts index 4663f6225..a77459f58 100644 --- a/cypress/integration/rendering/mindmap.spec.ts +++ b/cypress/integration/rendering/mindmap.spec.ts @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest } from '../../helpers/util.ts'; /** * Check whether the SVG Element has a Mindmap root @@ -52,6 +52,17 @@ root[A root with a long text that wraps to keep the node size in check] ); }); + it('a root with wrapping text and long words that exceed width', () => { + imgSnapshotTest( + `mindmap +root[A few smaller words but then averylongsetofcharacterswithoutwhitespacetoseparate that we expect to wrapontonextlinesandnotexceedwidthparameters] + `, + {}, + undefined, + shouldHaveRoot + ); + }); + it('a root with an icon', () => { imgSnapshotTest( `mindmap @@ -223,5 +234,17 @@ mindmap shouldHaveRoot ); }); + describe('Markdown strings mindmaps (#4220)', () => { + it('Formatted label with linebreak and a wrapping label and emojis', () => { + imgSnapshotTest( + `mindmap + id1[\`**Start** with + a second line 😎\`] + id2[\`The dog in **the** hog... a *very long text* about it +Word!\`] +` + ); + }); + }); /* The end */ }); diff --git a/cypress/integration/rendering/pie.spec.js b/cypress/integration/rendering/pie.spec.ts similarity index 56% rename from cypress/integration/rendering/pie.spec.js rename to cypress/integration/rendering/pie.spec.ts index 019fa41af..269efafb2 100644 --- a/cypress/integration/rendering/pie.spec.js +++ b/cypress/integration/rendering/pie.spec.ts @@ -1,78 +1,85 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; -describe('Pie Chart', () => { +describe('pie chart', () => { it('should render a simple pie diagram', () => { imgSnapshotTest( + `pie title Sports in Sweden + "Bandy": 40 + "Ice-Hockey": 80 + "Football": 90 ` - pie title Sports in Sweden - "Bandy" : 40 - "Ice-Hockey" : 80 - "Football" : 90 - `, - {} ); - cy.get('svg'); }); + it('should render a simple pie diagram with long labels', () => { imgSnapshotTest( + `pie title NETFLIX + "Time spent looking for movie": 90 + "Time spent watching it": 10 ` - pie title NETFLIX - "Time spent looking for movie" : 90 - "Time spent watching it" : 10 - `, - {} ); - cy.get('svg'); }); + it('should render a simple pie diagram with capital letters for labels', () => { imgSnapshotTest( + `pie title What Voldemort doesn't have? + "FRIENDS": 2 + "FAMILY": 3 + "NOSE": 45 ` - pie title What Voldemort doesn't have? - "FRIENDS" : 2 - "FAMILY" : 3 - "NOSE" : 45 - `, - {} ); - cy.get('svg'); }); + it('should render a pie diagram when useMaxWidth is true (default)', () => { renderGraph( - ` - pie title Sports in Sweden - "Bandy" : 40 - "Ice-Hockey" : 80 - "Football" : 90 + `pie title Sports in Sweden + "Bandy": 40 + "Ice-Hockey": 80 + "Football": 90 `, { pie: { useMaxWidth: true } } ); cy.get('svg').should((svg) => { expect(svg).to.have.attr('width', '100%'); - // expect(svg).to.have.attr('height'); - // const height = parseFloat(svg.attr('height')); - // expect(height).to.eq(450); const style = svg.attr('style'); expect(style).to.match(/^max-width: [\d.]+px;$/); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); expect(maxWidthValue).to.eq(984); }); }); + it('should render a pie diagram when useMaxWidth is false', () => { renderGraph( - ` - pie title Sports in Sweden - "Bandy" : 40 - "Ice-Hockey" : 80 - "Football" : 90 + `pie title Sports in Sweden + "Bandy": 40 + "Ice-Hockey": 80 + "Football": 90 `, { pie: { useMaxWidth: false } } ); cy.get('svg').should((svg) => { - // const height = parseFloat(svg.attr('height')); const width = parseFloat(svg.attr('width')); - // expect(height).to.eq(450); expect(width).to.eq(984); expect(svg).to.not.have.attr('style'); }); }); + + it('should render a pie diagram when textPosition is setted', () => { + imgSnapshotTest( + `pie + "Dogs": 50 + "Cats": 25 + `, + { logLevel: 1, pie: { textPosition: 0.9 } } + ); + }); + + it('should render a pie diagram with showData', () => { + imgSnapshotTest( + `pie showData + "Dogs": 50 + "Cats": 25 + ` + ); + }); }); diff --git a/cypress/integration/rendering/quadrantChart.spec.js b/cypress/integration/rendering/quadrantChart.spec.js new file mode 100644 index 000000000..50520eb1a --- /dev/null +++ b/cypress/integration/rendering/quadrantChart.spec.js @@ -0,0 +1,163 @@ +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; + +describe('Quadrant Chart', () => { + it('should render if only chart type is provided', () => { + imgSnapshotTest( + ` + quadrantChart + `, + {} + ); + cy.get('svg'); + }); + it('should render a complete quadrant chart', () => { + imgSnapshotTest( + ` + quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + Campaign A: [0.3, 0.6] + Campaign B: [0.45, 0.23] + Campaign C: [0.57, 0.69] + Campaign D: [0.78, 0.34] + Campaign E: [0.40, 0.34] + Campaign F: [0.35, 0.78] + `, + {} + ); + cy.get('svg'); + }); + it('should render without points', () => { + imgSnapshotTest( + ` + quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + `, + {} + ); + cy.get('svg'); + }); + it('should able to render y-axix on right side', () => { + imgSnapshotTest( + ` + %%{init: {"quadrantChart": {"yAxisPosition": "right"}}}%% + quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + `, + {} + ); + cy.get('svg'); + }); + it('should able to render x-axix on bottom', () => { + imgSnapshotTest( + ` + %%{init: {"quadrantChart": {"xAxisPosition": "bottom"}}}%% + quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + `, + {} + ); + cy.get('svg'); + }); + it('should able to render x-axix on bottom and y-axis on right', () => { + imgSnapshotTest( + ` + %%{init: {"quadrantChart": {"xAxisPosition": "bottom", "yAxisPosition": "right"}}}%% + quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + `, + {} + ); + cy.get('svg'); + }); + it('should render without title', () => { + imgSnapshotTest( + ` + quadrantChart + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + `, + {} + ); + cy.get('svg'); + }); + it('should use all the config', () => { + imgSnapshotTest( + ` + %%{init: {"quadrantChart": {"chartWidth": 600, "chartHeight": 600, "titlePadding": 20, "titleFontSize": 10, "quadrantPadding": 20, "quadrantTextTopPadding": 40, "quadrantLabelFontSize": 20, "quadrantInternalBorderStrokeWidth": 3, "quadrantExternalBorderStrokeWidth": 5, "xAxisLabelPadding": 20, "xAxisLabelFontSize": 20, "yAxisLabelPadding": 20, "yAxisLabelFontSize": 20, "pointTextPadding": 20, "pointLabelFontSize": 20, "pointRadius": 10 }}}%% + quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + Campaign A: [0.3, 0.6] + Campaign B: [0.45, 0.23] + Campaign C: [0.57, 0.69] + Campaign D: [0.78, 0.34] + Campaign E: [0.40, 0.34] + Campaign F: [0.35, 0.78] + `, + {} + ); + cy.get('svg'); + }); + it('should use all the theme variable', () => { + imgSnapshotTest( + ` + %%{init: {"themeVariables": {"quadrant1Fill": "#b4dcff","quadrant2Fill": "#fef0ff", "quadrant3Fill": "#fffaf0", "quadrant4Fill": "#f0fff2", "quadrant1TextFill": "#ff0000", "quadrant2TextFill": "#2d00df", "quadrant3TextFill": "#00ffda", "quadrant4TextFill": "#e68300", "quadrantPointFill": "#0149ff", "quadrantPointTextFill": "#dc00ff", "quadrantXAxisTextFill": "#ffb500", "quadrantYAxisTextFill": "#fae604", "quadrantInternalBorderStrokeFill": "#3636f2", "quadrantExternalBorderStrokeFill": "#ff1010", "quadrantTitleFill": "#00ea19"} }}%% + quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + Campaign A: [0.3, 0.6] + Campaign B: [0.45, 0.23] + Campaign C: [0.57, 0.69] + Campaign D: [0.78, 0.34] + Campaign E: [0.40, 0.34] + Campaign F: [0.35, 0.78] + `, + {} + ); + cy.get('svg'); + }); +}); diff --git a/cypress/integration/rendering/requirement.spec.js b/cypress/integration/rendering/requirement.spec.js index 0bf9014bf..f33ae7a0c 100644 --- a/cypress/integration/rendering/requirement.spec.js +++ b/cypress/integration/rendering/requirement.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.js'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('Requirement diagram', () => { it('sample', () => { diff --git a/cypress/integration/rendering/sankey.spec.ts b/cypress/integration/rendering/sankey.spec.ts new file mode 100644 index 000000000..ad0d75f18 --- /dev/null +++ b/cypress/integration/rendering/sankey.spec.ts @@ -0,0 +1,144 @@ +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; + +describe('Sankey Diagram', () => { + it('should render a simple example', () => { + imgSnapshotTest( + ` + sankey-beta + + sourceNode,targetNode,10 + `, + {} + ); + }); + + describe('when given a linkColor', function () { + this.beforeAll(() => { + cy.wrap( + `sankey-beta + a,b,10 + ` + ).as('graph'); + }); + + it('links should use hex color', function () { + renderGraph(this.graph, { sankey: { linkColor: '#636465' } }); + + cy.get('.link path').should((link) => { + expect(link.attr('stroke')).to.equal('#636465'); + }); + }); + + it('links should be the same color as source node', function () { + renderGraph(this.graph, { sankey: { linkColor: 'source' } }); + + cy.get('.link path').then((link) => { + cy.get('.node[id="node-1"] rect').should((node) => + expect(link.attr('stroke')).to.equal(node.attr('fill')) + ); + }); + }); + + it('links should be the same color as target node', function () { + renderGraph(this.graph, { sankey: { linkColor: 'target' } }); + + cy.get('.link path').then((link) => { + cy.get('.node[id="node-2"] rect').should((node) => + expect(link.attr('stroke')).to.equal(node.attr('fill')) + ); + }); + }); + + it('links must be gradient', function () { + renderGraph(this.graph, { sankey: { linkColor: 'gradient' } }); + + cy.get('.link path').should((link) => { + expect(link.attr('stroke')).to.equal('url(#linearGradient-3)'); + }); + }); + }); + + describe('when given a nodeAlignment', function () { + this.beforeAll(() => { + cy.wrap( + ` + sankey-beta + + a,b,8 + b,c,8 + c,d,8 + d,e,8 + + x,c,4 + c,y,4 + ` + ).as('graph'); + }); + + this.afterEach(() => { + cy.get('.node[id="node-1"]').should((node) => { + expect(node.attr('x')).to.equal('0'); + }); + cy.get('.node[id="node-2"]').should((node) => { + expect(node.attr('x')).to.equal('100'); + }); + cy.get('.node[id="node-3"]').should((node) => { + expect(node.attr('x')).to.equal('200'); + }); + cy.get('.node[id="node-4"]').should((node) => { + expect(node.attr('x')).to.equal('300'); + }); + cy.get('.node[id="node-5"]').should((node) => { + expect(node.attr('x')).to.equal('400'); + }); + }); + + it('should justify nodes', function () { + renderGraph(this.graph, { + sankey: { nodeAlignment: 'justify', width: 410, useMaxWidth: false }, + }); + cy.get('.node[id="node-6"]').should((node) => { + expect(node.attr('x')).to.equal('0'); + }); + cy.get('.node[id="node-7"]').should((node) => { + expect(node.attr('x')).to.equal('400'); + }); + }); + + it('should align nodes left', function () { + renderGraph(this.graph, { + sankey: { nodeAlignment: 'left', width: 410, useMaxWidth: false }, + }); + cy.get('.node[id="node-6"]').should((node) => { + expect(node.attr('x')).to.equal('0'); + }); + cy.get('.node[id="node-7"]').should((node) => { + expect(node.attr('x')).to.equal('300'); + }); + }); + + it('should align nodes right', function () { + renderGraph(this.graph, { + sankey: { nodeAlignment: 'right', width: 410, useMaxWidth: false }, + }); + cy.get('.node[id="node-6"]').should((node) => { + expect(node.attr('x')).to.equal('100'); + }); + cy.get('.node[id="node-7"]').should((node) => { + expect(node.attr('x')).to.equal('400'); + }); + }); + + it('should center nodes', function () { + renderGraph(this.graph, { + sankey: { nodeAlignment: 'center', width: 410, useMaxWidth: false }, + }); + cy.get('.node[id="node-6"]').should((node) => { + expect(node.attr('x')).to.equal('100'); + }); + cy.get('.node[id="node-7"]').should((node) => { + expect(node.attr('x')).to.equal('300'); + }); + }); + }); +}); diff --git a/cypress/integration/rendering/sequencediagram.spec.js b/cypress/integration/rendering/sequencediagram.spec.js index 1f063c13e..765913824 100644 --- a/cypress/integration/rendering/sequencediagram.spec.js +++ b/cypress/integration/rendering/sequencediagram.spec.js @@ -1,6 +1,6 @@ /// -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; context('Sequence diagram', () => { it('should render a sequence diagram with boxes', () => { @@ -88,6 +88,16 @@ context('Sequence diagram', () => { {} ); }); + it('should handle empty lines', () => { + imgSnapshotTest( + ` + sequenceDiagram + Alice->>John: Hello John
+ John-->>Alice: Great

day! + `, + {} + ); + }); it('should handle line breaks and wrap annotations', () => { imgSnapshotTest( ` @@ -116,7 +126,109 @@ context('Sequence diagram', () => { loop Loopy Bob->>Alice: Pasten end `, - { wrap: true } + { + sequence: { + wrap: true, + }, + } + ); + }); + it('should render a sequence diagram with par_over', () => { + imgSnapshotTest( + ` + sequenceDiagram + participant Alice + participant Bob + participant John + par_over Section title + Alice ->> Bob: Message 1
Second line + Bob ->> John: Message 2 + end + par_over Two line
section title + Note over Alice: Alice note + Note over Bob: Bob note
Second line + Note over John: John note + end + par_over Mixed section + Alice ->> Bob: Message 1 + Note left of Bob: Alice/Bob Note + end + ` + ); + }); + it('should render a sequence diagram with basic actor creation and destruction', () => { + imgSnapshotTest( + ` + sequenceDiagram + Alice ->> Bob: Hello Bob, how are you ? + Bob ->> Alice: Fine, thank you. And you? + create participant Polo + Alice ->> Polo: Hi Polo! + create actor Ola1 as Ola + Polo ->> Ola1: Hiii + Ola1 ->> Alice: Hi too + destroy Ola1 + Alice --x Ola1: Bye! + Alice ->> Bob: And now? + create participant Ola2 as Ola + Alice ->> Ola2: Hello again + destroy Alice + Alice --x Ola2: Bye for me! + destroy Bob + Ola2 --> Bob: The end + ` + ); + }); + it('should render a sequence diagram with actor creation and destruction coupled with backgrounds, loops and notes', () => { + imgSnapshotTest( + ` + sequenceDiagram + accTitle: test the accTitle + accDescr: Test a description + + participant Alice + participant Bob + autonumber 10 10 + rect rgb(200, 220, 100) + rect rgb(200, 255, 200) + + Alice ->> Bob: Hello Bob, how are you? + create participant John as John
Second Line + Bob-->>John: How about you John? + end + + Bob--x Alice: I am good thanks! + Bob-x John: I am good thanks! + Note right of John: John thinks a long
long time, so long
that the text does
not fit on a row. + + Bob-->Alice: Checking with John... + Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit. + Bob-x John: Hey John - we're still waiting to know
how you're doing + Note over John:nowrap: John's trying hard not to break his train of thought. + destroy John + Bob-x John: John! Cmon! + Note over John: After a few more moments, John
finally snaps out of it. + end + + autonumber off + alt either this + create actor Lola + Alice->>+Lola: Yes + Lola-->>-Alice: OK + else or this + autonumber + Alice->>Lola: No + else or this will happen + Alice->Lola: Maybe + end + autonumber 200 + par this happens in parallel + destroy Bob + Alice -->> Bob: Parallel message 1 + and + Alice -->> Lola: Parallel message 2 + end + ` ); }); context('font settings', () => { diff --git a/cypress/integration/rendering/stateDiagram-v2.spec.js b/cypress/integration/rendering/stateDiagram-v2.spec.js index 047e240fc..9a1a27abe 100644 --- a/cypress/integration/rendering/stateDiagram-v2.spec.js +++ b/cypress/integration/rendering/stateDiagram-v2.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('State diagram', () => { it('v2 should render a simple info', () => { @@ -530,7 +530,7 @@ stateDiagram-v2 [*] --> A A --> B: test({ foo#colon; 'far' }) B --> [*] - classDef badBadEvent fill:#f00,color:white,font-weight:bold + classDef badBadEvent fill:#f00,color:white,font-weight:bold class B badBadEvent `, { logLevel: 0, fontFamily: 'courier' } @@ -543,14 +543,14 @@ stateDiagram-v2 classDef notMoving fill:white classDef movement font-style:italic; classDef badBadEvent fill:#f00,color:white,font-weight:bold - + [*] --> Still Still --> [*] Still --> Moving Moving --> Still Moving --> Crash Crash --> [*] - + class Still notMoving class Moving, Crash movement class Crash badBadEvent diff --git a/cypress/integration/rendering/stateDiagram.spec.js b/cypress/integration/rendering/stateDiagram.spec.js index cdcc48a07..01e7a2b44 100644 --- a/cypress/integration/rendering/stateDiagram.spec.js +++ b/cypress/integration/rendering/stateDiagram.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util'; +import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; describe('State diagram', () => { it('should render a simple state diagrams', () => { diff --git a/cypress/integration/rendering/theme.spec.js b/cypress/integration/rendering/theme.spec.js index ef3bd9a4b..c84ad0c4b 100644 --- a/cypress/integration/rendering/theme.spec.js +++ b/cypress/integration/rendering/theme.spec.js @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('themeCSS balancing, it', () => { it('should not allow unbalanced CSS definitions', () => { diff --git a/cypress/integration/rendering/timeline.spec.ts b/cypress/integration/rendering/timeline.spec.ts index 6fae82fb4..68da01d50 100644 --- a/cypress/integration/rendering/timeline.spec.ts +++ b/cypress/integration/rendering/timeline.spec.ts @@ -1,4 +1,4 @@ -import { imgSnapshotTest } from '../../helpers/util.js'; +import { imgSnapshotTest } from '../../helpers/util.ts'; describe('Timeline diagram', () => { it('1: should render a simple timeline with no specific sections', () => { diff --git a/cypress/integration/rendering/zenuml.spec.js b/cypress/integration/rendering/zenuml.spec.js new file mode 100644 index 000000000..53d8ae346 --- /dev/null +++ b/cypress/integration/rendering/zenuml.spec.js @@ -0,0 +1,19 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +describe('Zen UML', () => { + it('Basic Zen UML diagram', () => { + imgSnapshotTest( + ` + zenuml + A.method() { + if(x) { + B.method() { + selfCall() { return X } + } + } + } + `, + {} + ); + }); +}); diff --git a/cypress/platform/ashish2.html b/cypress/platform/ashish2.html index bcea4f4cc..76fbd36f7 100644 --- a/cypress/platform/ashish2.html +++ b/cypress/platform/ashish2.html @@ -188,7 +188,7 @@ mindmap //import mindmap from '../../packages/mermaid-mindmap/src/detector'; // import example from '../../packages/mermaid-example-diagram/src/detector'; // import timeline from '../../packages/mermaid-timeline/src/detector'; - import mermaid from '../../packages/mermaid/src/mermaid'; + import mermaid from './mermaid.esm.mjs'; // await mermaid.registerExternalDiagrams([]); mermaid.parseError = function (err, hash) { // console.error('Mermaid error: ', err); diff --git a/cypress/platform/bundle-test.js b/cypress/platform/bundle-test.js index edd3dfbc4..f5bf0ecd6 100644 --- a/cypress/platform/bundle-test.js +++ b/cypress/platform/bundle-test.js @@ -1,4 +1,5 @@ -import mermaid from '../../packages/mermaid/src/mermaid'; +// TODO: this file should be testing the ./mermaid.core.mjs file, as that's the file listed in the package.json file that users will use +import mermaid from './mermaid.esm.mjs'; let code = `flowchart LR Power_Supply --> Transmitter_A diff --git a/cypress/platform/class.html b/cypress/platform/class.html index 052dd18b9..2f853bbc1 100644 --- a/cypress/platform/class.html +++ b/cypress/platform/class.html @@ -12,7 +12,6 @@ + + +

+      graph TB
+      subgraph One
+        a1-->a2-->a3
+      end
+    
+
+      graph TB
+        a_a --> b_b:::apa --> c_c:::apa
+        classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
+        class a_a apa;
+    
+
+      graph TB
+        a_a(Aftonbladet) --> b_b[gorilla]:::apa --> c_c{chimp}:::apa -->a_a
+        a_a --> c --> d_d --> c_c
+        classDef apa fill:#f9f,stroke:#333,stroke-width:4px;
+        class a_a apa;
+        click a_a "http://www.aftonbladet.se" "apa"
+    
+ + + + diff --git a/cypress/platform/info.html b/cypress/platform/info.html deleted file mode 100644 index c35446153..000000000 --- a/cypress/platform/info.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - -

info below

-
-info
-    
- - - diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index f6ee1ef03..512333c01 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -42,368 +42,86 @@ -
-flowchart LR
-  subgraph one
-    direction LR
-    A[myClass1] --> B[default]
-    subgraph two
-      direction BT
-      C[myClass2] --> D[default]
-    end
-  end
+    
+      %%{init: {"flowchart": {"htmlLabels": true}} }%%
+      flowchart LR
+      b("`The dog in **the** hog.(1).. a a a a *very long text* about it
+      Word!
+      
+      Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words. Another line with many, many words.`") --apa--> c
+      
+          
+
+      classDiagram-v2
 
+      classA -- classB : Inheritance
+      classA -- classC : link
+      classC -- classD : link
+      classB -- classD
     
-
-flowchart LR
-  classDef aPID stroke:#4e4403,fill:#fdde29,color:#4e4403,rx:5px,ry:5px;
-  classDef crm stroke:#333333,fill:#DCDCDC,color:#333333,rx:5px,ry:5px;
-  classDef type stroke:#502604,fill:#FAB565,color:#502604,rx:20px,ry:20px;;
-
-  O0("Joe")
-  class O0 aPID;
-
-  O1("Person")
-  class O1 crm;
-  O0 -- has type -->O1["Person"]
-
-  O2("aat:300411314")
-  class O2 type;
-  click O2 function "Sorry the newline html tags are not being processed correctly
So all of this appears on the
same line." - O0 -- has type -->O2["Bug"] - click O0 function "Lots of great info about Joe
Lots of great info about Joe
burt
fred"; +
+      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
+      loop Loopy
+          Bob->>Alice: Pasten
+      end
     
-
-flowchart TD
-    subgraph test
-    direction TB
-    subgraph test2
-      direction LR
-      F --> D
-    end
-    subgraph test3
-      direction TB
-      G --> H
-    end
-    end
+    
+      %%{init: {"flowchart": {"htmlLabels": false}} }%%
+      flowchart LR
+      b("`The dog in **the** hog.(1)
+      NL`") --"`1o **bold**`"--> c[new strings svg labels]
     
-
-flowchart TD
-
-  release-branch[Create Release Branch]:::relClass
-  develop-branch[Update Develop Branch]:::relClass
-  github-release-draft[GitHub Release Draft]:::relClass
-  trigger-pipeline[Trigger Jenkins pipeline]:::fixClass
-  github-release[GitHub Release]:::postClass
-
-  build-ready --> release-branch
-  build-ready --> develop-branch
-  release-branch --> jenkins-release-build
-  jenkins-release-build --> github-release-draft
-  jenkins-release-build --> install-release
-  install-release --> verify-release
-  jenkins-release-build --> announce
-  github-release-draft --> github-release
-  verify-release --> verify-check
-  verify-check -- Yes --> github-release
-  verify-check -- No --> release-fix
-  release-fix --> release-branch-pr
-  verify-check -- No --> delete-artifacts
-  release-branch-pr --> trigger-pipeline
-  delete-artifacts --> trigger-pipeline
-  trigger-pipeline --> jenkins-release-build
-
-
+    
+      %%{init: {"flowchart": {"htmlLabels": true}} }%%
+      flowchart LR
+      b("`The dog in **the** hog.(1)
+      NL`") --"`1o **bold**`"--> c[new strings html labels]
     
-
-flowchart LR
-        a["Haiya"]===>b
+    
+      %%{init: {"flowchart": {"htmlLabels": true}} }%%
+      flowchart LR
+      b("The dog in the hog.(1)\nNL") --"1o bold"--> c[old strings svg labels]
     
-
-flowchart TD
-    A --> B
-    A --> C
-    B --> C
-    
-
-flowchart 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; -
-
-   sequenceDiagram
-      title: My Sequence Diagram Title
-      accTitle: My Acc Sequence Diagram
-      accDescr: My Sequence Diagram Description
-
-      Alice->>John: Hello John, how are you?
-      John-->>Alice: Great!
-      Alice-)John: See you later!
-    
-
-graph TD
-    A -->|000| B
-    B -->|111| C
-
-    linkStyle 1 stroke:#ff3,stroke-width:4px,color:red;
-    
-
-  journey
-      accTitle: My User Journey Diagram
-      accDescr: My User Journey Diagram Description
-
-      title My working day
-      section Go to work
-        Make tea: 5: Me
-        Go upstairs: 3: Me
-        Do work: 1: Me, Cat
-      section Go home
-        Go downstairs: 5: Me
-        Sit down: 5: Me
-    
-
-        info
-    
-
-requirementDiagram
-      accTitle: My req Diagram
-      accDescr: My req Diagram Description
-
-    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
-    }
-
-    element test_entity {
-    type: simulation
-    }
-
-    element test_entity2 {
-    type: word doc
-    docRef: reqs/test_entity
-    }
-
-
-    test_entity - satisfies -> test_req2
-    test_req - traces -> test_req2
-    test_req - contains -> test_req3
-    test_req <- copies - test_entity2
-    
-
-gantt
-    dateFormat  YYYY-MM-DD
-    title       Adding GANTT diagram functionality to mermaid
-    excludes    weekends
-    %% (`excludes` accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".)
-
-    section A section
-    Completed task            :done,    des1, 2014-01-06,2014-01-08
-    Active task               :active,  des2, 2014-01-09, 3d
-    Future task               :         des3, after des2, 5d
-    Future task2              :         des4, after des3, 5d
-
-    section Critical tasks
-    Completed task in the critical line :crit, done, 2014-01-06,24h
-    Implement parser and jison          :crit, done, after des1, 2d
-    Create tests for parser             :crit, active, 3d
-    Future task in critical line        :crit, 5d
-    Create tests for renderer           :2d
-    Add to mermaid                      :1d
-    Functionality added                 :milestone, 2014-01-25, 0d
-
-    section Documentation
-    Describe gantt syntax               :active, a1, after des1, 3d
-    Add gantt diagram to demo page      :after a1  , 20h
-    Add another diagram to demo page    :doc1, after a1  , 48h
-
-    section Last section
-    Describe gantt syntax               :after doc1, 3d
-    Add gantt diagram to demo page      :20h
-    Add another diagram to demo page    :48h
-    
-
-stateDiagram
-  state Active {
-    Idle
-  }
-  Inactive --> Idle: ACT
-  Active --> Active: LOG
-    
-
-      flowchart TB
-        accTitle: My flowchart
-        accDescr: My flowchart Description
-        subgraph One
-          a1-->a2-->a3
-        end
-    
-
-        sequenceDiagram
-          A ->> B: 1
-          rect rgb(204, 0, 102)
-            break yes
-              rect rgb(0, 204, 204)
-                C ->> C: 0
-              end
-            end
-          end
-          B ->> A: Return
-    
-
-classDiagram
-accTitle: My class diagram
-accDescr: My class diagram Description
-Class01 <|-- AveryLongClass : Cool
-Class09 --> C2 : Where am i?
-Class09 --* C3
-Class09 --|> Class07
-Class07 : equals()
-Class07 : Object[] elementData
-Class01 : size()
-Class01 : int chimp
-Class01 : int gorilla
-class Class10 {
-  int id
-  size()
-}
-    
-
-%%{init: {'config': {'wrap': true }}}%%
-        sequenceDiagram
-        participant A as Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
-        A->>Bob: Hola
-        Bob-->A: Pasten !
-    
-
-      gitGraph
-       commit id: "ZERO"
-       branch develop
-       commit id:"A"
-       checkout main
-       commit id:"ONE"
-       checkout develop
-       commit id:"B"
-       branch featureA
-       commit id:"FIX"
-       commit id: "FIX-2"
-       checkout main
-       commit id:"TWO"
-       cherry-pick id:"A"
-       commit id:"THREE"
-       cherry-pick id:"FIX"
-       checkout develop
-       commit id:"C"
-       merge featureA
-    
-
-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]
-    
-
-        classDiagram
-          Animal "1" <|-- Duck
-          Animal <|-- Fish
-          Animal <--o 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()
-          }
-    
-
-        erDiagram
-    CAR ||--o{ NAMED-DRIVER : allows
-    CAR {
-        string registrationNumber
-        string make
-        string model
-    }
-    PERSON ||--o{ NAMED-DRIVER : is
-    PERSON {
-        string firstName
-        string lastName
-        int age
-    }
-    
- - - - diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index fccd65004..f9a9f3756 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -29,9 +29,9 @@ } .mermaid svg { /* font-size: 18px !important; */ - background-color: #eee; - background-image: radial-gradient(#fff 1%, transparent 11%), - radial-gradient(#fff 1%, transparent 11%); + background-color: #efefef; + background-image: radial-gradient(#fff 51%, transparent 91%), + radial-gradient(#fff 51%, transparent 91%); background-size: 20px 20px; background-position: 0 0, 10px 10px; background-repeat: repeat; @@ -51,27 +51,118 @@ font-family: monospace; font-size: 72px; } + /* tspan { + font-size: 6px !important; + } */
-%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
-graph BT
-a{The cat in the hat} -- 1o --> b
-a -- 2o --> c
-a -- 3o --> d
-g --2i--> a
-d --1i--> a
-h --3i -->a
-b --> d(The dog in the hog)
-c --> d
+      flowchart
+        classDef mainCategories fill:#f9d5e5, stroke:#233d4d,stroke-width:2px, font-weight:bold;
+        CS(Customer Awareness Journey):::mainCategories
+      
+
+flowchart
+Node1:::class1 --> Node2:::class2
+Node1:::class1 --> Node3:::class2
+Node3 --> Node4((I am a circle)):::larger
+
+classDef class1 fill:lightblue
+classDef class2 fill:pink
+classDef larger font-size:30px,fill:yellow
+      
+
+stateDiagram-v2
+    [*] --> Still
+    Still --> [*]
+    Still --> Moving
+    Moving --> Still
+    Moving --> Crash
+    Crash --> [*]    
+
+flowchart RL
+    subgraph "`one`"
+      a1 -- l1 --> a2
+      a1 -- l2 --> a2
+    end
     
-flowchart-elk TB
-      a --> b
-      a --> c
-      b --> d
-      c --> 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"}} }%%
@@ -89,7 +180,7 @@ flowchart TB
     rom --> core2
   end
 
-  subgraph amd[AMD Latte GPU]
+  subgraph amd["`**AMD** Latte GPU`"]
     mem[Memory & I/O Bridge]
     dram[DRAM Controller]
     edram[32 MB EDRAM MEM1]
@@ -128,6 +219,62 @@ flowchart TB
   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
@@ -263,25 +410,37 @@ mindmap
 
     
+  
+
diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js
index 69d93b4a4..ef985866e 100644
--- a/cypress/support/e2e.js
+++ b/cypress/support/e2e.js
@@ -13,8 +13,8 @@
 // https://on.cypress.io/configuration
 // ***********************************************************
 
+import '@cypress/code-coverage/support';
 import '@applitools/eyes-cypress/commands';
-
 // Import commands.js using ES2015 syntax:
 import './commands';
 
diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json
index e3351cebe..baa9a7217 100644
--- a/cypress/tsconfig.json
+++ b/cypress/tsconfig.json
@@ -2,7 +2,9 @@
   "compilerOptions": {
     "target": "es2020",
     "lib": ["es2020", "dom"],
-    "types": ["cypress", "node"]
+    "types": ["cypress", "node"],
+    "allowImportingTsExtensions": true,
+    "noEmit": true
   },
   "include": ["**/*.ts"]
 }
diff --git a/demos/classchart.html b/demos/classchart.html
index b20dda2a3..3ad8fb100 100644
--- a/demos/classchart.html
+++ b/demos/classchart.html
@@ -38,12 +38,14 @@
         +quack()
       }
       class Fish{
-        -int sizeInFeet
+        -Listint sizeInFeet
         -canEat()
       }
       class Zebra{
         +bool is_wild
-        +run()
+        +run(List~T~, List~OT~)
+        %% +run-composite(List~T, K~)
+        +run-nested(List~List~OT~~)
       }
 
     
@@ -80,6 +82,7 @@ Class01 : #size() Class01 : -int chimp Class01 : +int gorilla + Class01 : +abstractAttribute string* class Class10~T~ { <<service>> int id @@ -122,6 +125,8 @@ classDiagram direction LR Animal ()-- Dog + Animal ()-- Cat + note for Cat "should have no members area" Dog : bark() Dog : species()
@@ -151,6 +156,30 @@ ~InternalProperty : string ~AnotherInternalProperty : List~List~string~~ } + class People List~List~Person~~ +
+
+ +
+    classDiagram
+      A1 --> B1
+      namespace A {
+        class A1 {
+          +foo : string
+        }
+        class A2 {
+          +bar : int
+        }
+      }
+      namespace B {
+        class B1 {
+          +foo : bool
+        }
+        class B2 {
+          +bar : float
+        }
+      }
+      A2 --> B2
     

diff --git a/demos/dev/example.html b/demos/dev/example.html new file mode 100644 index 000000000..482343014 --- /dev/null +++ b/demos/dev/example.html @@ -0,0 +1,34 @@ + + + + + Mermaid development page + + +
+graph TB
+      a --> b
+      a --> c
+      b --> d
+      c --> d
+    
+ +
+ + + + diff --git a/demos/er.html b/demos/er.html index 49f0a683f..027c2e277 100644 --- a/demos/er.html +++ b/demos/er.html @@ -21,6 +21,8 @@
       ---
       title: This is a title
+      config:
+        theme: forest
       ---
       erDiagram
         %% title This is a title
@@ -108,6 +110,35 @@
         }
         MANUFACTURER only one to zero or more CAR : makes
     
+
+ +
+    erDiagram
+      p[Person] {
+          string firstName
+          string lastName
+      }
+      a["Customer Account"] {
+          string email
+      }
+      p ||--o| a : has
+    
+
+ +
+    erDiagram
+      _customer_order {
+          bigint id PK
+          bigint customer_id FK
+          text shipping_address 
+          text delivery_method 
+          timestamp_with_time_zone ordered_at 
+          numeric total_tax_amount 
+          numeric total_price 
+          text payment_method 
+      }
+    
+
+ + diff --git a/demos/flowchart.html b/demos/flowchart.html index 02405c5ed..8389510b2 100644 --- a/demos/flowchart.html +++ b/demos/flowchart.html @@ -123,6 +123,13 @@

flowchart

+    ---
+    title: This is another complicated flow
+    config:
+      theme: base
+      flowchart:
+        curve: cardinal
+    ---
     flowchart LR
     sid-B3655226-6C29-4D00-B685-3D5C734DC7E1["
 
@@ -1505,6 +1512,34 @@
     

+
+    graph TD
+      A([Start]) ==> B[Step 1]
+      B ==> C{Flow 1}
+      C -- Choice 1.1 --> D[Step 2.1]
+      C -- Choice 1.3 --> I[Step 2.3]
+      C == Choice 1.2 ==> E[Step 2.2]
+      D --> F{Flow 2}
+      E ==> F{Flow 2}
+      F{Flow 2} == Choice 2.1 ==> H[Feedback node]
+      H[Feedback node] ==> B[Step 1]
+      F{Flow 2} == Choice 2.2 ==> G((Finish))
+      
+      linkStyle 0,1,4,6,7,8,9 stroke:gold, stroke-width:4px
+
+      classDef active_node fill:#0CF,stroke:#09F,stroke-width:6px
+      classDef unactive_node fill:#e0e0e0,stroke:#bdbdbd,stroke-width:3px      
+      classDef bugged_node fill:#F88,stroke:#F22,stroke-width:3px
+      classDef start_node,finish_node fill:#3B1,stroke:#391,stroke-width:8px
+
+      class A start_node;
+      class B,C,E,F,H active_node;
+      class D unactive_node;
+      class G finish_node;
+      class I bugged_node
+    
+
+

Anchor for "link-clicked" test

+ + diff --git a/demos/journey.html b/demos/journey.html index 40fa5d390..b0131ea3f 100644 --- a/demos/journey.html +++ b/demos/journey.html @@ -17,7 +17,7 @@

Journey diagram demo

     ---
-    title: My working day 
+    title: My working day
     ---
      journey
       accTitle: Very simple journey demo
diff --git a/demos/mindmap.html b/demos/mindmap.html
index a5b554a1a..2e7d47719 100644
--- a/demos/mindmap.html
+++ b/demos/mindmap.html
@@ -40,7 +40,6 @@
 
     
   
diff --git a/demos/quadrantchart.html b/demos/quadrantchart.html
new file mode 100644
index 000000000..a2a60d0a1
--- /dev/null
+++ b/demos/quadrantchart.html
@@ -0,0 +1,55 @@
+
+
+  
+    
+    
+    Mermaid Quick Test Page
+    
+    
+  
+
+  
+    

Quadrant chart demos

+
+    %%{init: {"quadrantChart": {"quadrantPadding": 10}, "theme": "forest", "themeVariables": {"quadrant1TextFill": "blue"}} }%%
+    quadrantChart
+      x-axis Urgent --> Not Urgent
+      y-axis Not Important --> important
+      quadrant-1 Plan
+      quadrant-2 Do
+      quadrant-3 Deligate
+      quadrant-4 Delete
+    
+ +
+    %%{init: {"quadrantChart": {"chartWidth": 600, "chartHeight": 600} } }%%
+    quadrantChart
+      title Analytics and Business Intelligence Platforms
+      x-axis "Completeness of Vision ❤" -->
+      y-axis Ability to Execute
+      quadrant-1 Leaders
+      quadrant-2 Challengers
+      quadrant-3 Niche
+      quadrant-4 Visionaries
+      Microsoft: [0.75, 0.75]
+      Salesforce: [0.55, 0.60]
+      IBM: [0.51, 0.40]
+      Incorta: [0.20, 0.30]
+    
+
+ + + + diff --git a/demos/sankey.html b/demos/sankey.html new file mode 100644 index 000000000..5a76f476a --- /dev/null +++ b/demos/sankey.html @@ -0,0 +1,124 @@ + + + + + + Sankey Mermaid Quick Test Page + + + + +

Sankey diagram demos

+

FY20-21 Performance

+
+      ---
+      config:
+        sankey:
+          showValues: true
+          prefix: $
+          suffix: B
+          width: 800
+          nodeAlignment: left
+      ---
+      sankey-beta
+        Revenue,Expenses,10
+        Revenue,Profit,10
+        Expenses,Manufacturing,5
+        Expenses,Tax,3
+        Expenses,Research,2
+    
+ +

Energy flow

+
+      ---
+      config:
+        sankey:
+          showValues: false
+          width: 1200
+          height: 600
+          linkColor: gradient
+          nodeAlignment: justify
+      ---
+      sankey-beta
+
+      Agricultural 'waste',Bio-conversion,124.729
+      Bio-conversion,Liquid,0.597
+      Bio-conversion,Losses,26.862
+      Bio-conversion,Solid,280.322
+      Bio-conversion,Gas,81.144
+      Biofuel imports,Liquid,35
+      Biomass imports,Solid,35
+      Coal imports,Coal,11.606
+      Coal reserves,Coal,63.965
+      Coal,Solid,75.571
+      District heating,Industry,10.639
+      District heating,Heating and cooling - commercial,22.505
+      District heating,Heating and cooling - homes,46.184
+      Electricity grid,Over generation / exports,104.453
+      Electricity grid,Heating and cooling - homes,113.726
+      Electricity grid,H2 conversion,27.14
+      Electricity grid,Industry,342.165
+      Electricity grid,Road transport,37.797
+      Electricity grid,Agriculture,4.412
+      Electricity grid,Heating and cooling - commercial,40.858
+      Electricity grid,Losses,56.691
+      Electricity grid,Rail transport,7.863
+      Electricity grid,Lighting & appliances - commercial,90.008
+      Electricity grid,Lighting & appliances - homes,93.494
+      Gas imports,Ngas,40.719
+      Gas reserves,Ngas,82.233
+      Gas,Heating and cooling - commercial,0.129
+      Gas,Losses,1.401
+      Gas,Thermal generation,151.891
+      Gas,Agriculture,2.096
+      Gas,Industry,48.58
+      Geothermal,Electricity grid,7.013
+      H2 conversion,H2,20.897
+      H2 conversion,Losses,6.242
+      H2,Road transport,20.897
+      Hydro,Electricity grid,6.995
+      Liquid,Industry,121.066
+      Liquid,International shipping,128.69
+      Liquid,Road transport,135.835
+      Liquid,Domestic aviation,14.458
+      Liquid,International aviation,206.267
+      Liquid,Agriculture,3.64
+      Liquid,National navigation,33.218
+      Liquid,Rail transport,4.413
+      Marine algae,Bio-conversion,4.375
+      Ngas,Gas,122.952
+      Nuclear,Thermal generation,839.978
+      Oil imports,Oil,504.287
+      Oil reserves,Oil,107.703
+      Oil,Liquid,611.99
+      Other waste,Solid,56.587
+      Other waste,Bio-conversion,77.81
+      Pumped heat,Heating and cooling - homes,193.026
+      Pumped heat,Heating and cooling - commercial,70.672
+      Solar PV,Electricity grid,59.901
+      Solar Thermal,Heating and cooling - homes,19.263
+      Solar,Solar Thermal,19.263
+      Solar,Solar PV,59.901
+      Solid,Agriculture,0.882
+      Solid,Thermal generation,400.12
+      Solid,Industry,46.477
+      Thermal generation,Electricity grid,525.531
+      Thermal generation,Losses,787.129
+      Thermal generation,District heating,79.329
+      Tidal,Electricity grid,9.452
+      UK land based bioenergy,Bio-conversion,182.01
+      Wave,Electricity grid,19.013
+      Wind,Electricity grid,289.366
+    
+ + + + diff --git a/demos/sequence.html b/demos/sequence.html index aa2332520..b2733a384 100644 --- a/demos/sequence.html +++ b/demos/sequence.html @@ -144,6 +144,26 @@ >
+
+      sequenceDiagram
+      participant Alice
+      participant Bob
+      participant John
+      par_over Section title
+        Alice ->> Bob: Message 1
Second line + Bob ->> John: Message 2 + end + par_over Two line
section title + Note over Alice: Alice note + Note over Bob: Bob note
Second line + Note over John: John note + end + par_over Mixed section + Alice ->> Bob: Message 1 + Note left of Bob: Alice/Bob Note + end +
+ + + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..5827a5cc6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +version: '3.9' +services: + mermaid: + image: node:18.17.1-alpine3.18 + stdin_open: true + tty: true + working_dir: /mermaid + mem_limit: '4G' + environment: + - NODE_OPTIONS=--max_old_space_size=4096 + volumes: + - ./:/mermaid + - root_cache:/root/.cache + - root_local:/root/.local + - root_npm:/root/.npm + ports: + - 9000:9000 + - 3333:3333 + cypress: + image: cypress/included:12.17.4 + stdin_open: true + tty: true + working_dir: /mermaid + mem_limit: '2G' + entrypoint: cypress + environment: + - DISPLAY + volumes: + - ./:/mermaid + - /tmp/.X11-unix:/tmp/.X11-unix + network_mode: host + +volumes: + root_cache: + root_local: + root_npm: diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md deleted file mode 100644 index c854a139c..000000000 --- a/docs/CHANGELOG.md +++ /dev/null @@ -1,1054 +0,0 @@ -> **Warning** -> -> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. -> -> ## Please edit the corresponding file in [/packages/mermaid/src/docs/CHANGELOG.md](../packages/mermaid/src/docs/CHANGELOG.md). - -# Change Log - -All changes are in descending order, beginning with the newest (latest) version. - -## Unreleased - -[Full Changelog](https://github.com/knsv/mermaid/compare/8.7.0...HEAD) - -## 8.7.0 (2020-08-09) - -🔖 [Release Notes](https://github.com/mermaid-js/mermaid/releases/tag/8.7.0) | -📜 [Full Changelog](https://github.com/mermaid-js/mermaid/compare/8.6.0...8.7.0) - -This version brings with it a system for [dynamic and integrated configuration of the diagram themes](config/theming.md). -The objective of this is to increase the customizability of mermaid and the ease of Styling, with the customization of themes through the `%%init%%` directive and `initialize` calls. - -Themes follow and build upon the Levels of Configuration and employ `directives` to modify and create custom configurations, as they were introduced in Version [8.6.0](config/8.6.0_docs.md). - -**These Theming Configurations, similar to directives, will also be made applicable in the Live-Editor, for easier styling.** - -### Site-wide Themes - -Site-wide themes are still declared via `initialize` by site owners. - -Example of `Initalize` call setting `theme` to `base`: - -```javascript -mermaidAPI.initialize({ - securityLevel: 'loose', - theme: 'base', -}); -``` - -**Notes**: Only site owners can use the `mermaidAPI.initialize` call, to set values. Site-Users will have to use `%%init%%` to modify or create the theme for their diagrams. - -### Themes at the Local or Current Level - -When Generating a diagram using on a webpage that supports mermaid. -It is also possible to override site-wide theme settings locally, for a specific diagram, using directives, as long as it is not prohibited by the `secure` array. - -**Following is an example:** - -```mermaid-example -%%{init: {'theme':'base'}}%% - graph TD - a --> b -``` - -```mermaid -%%{init: {'theme':'base'}}%% - graph TD - a --> b -``` - -### Making a Custom Theme with `themeVariables` - -The easiest way to make a custom theme is to start with the base theme, and just modify theme variables through `themeVariables`, via `%%init%%`. - -| Parameter | Description | Type | Required | Objects contained | -| -------------- | ------------------------------------------------------------------ | ----- | -------- | ---------------------------------- | -| themeVariables | Array containing objects, modifiable with the `%%init%%` directive | Array | Required | primaryColor, lineColor, textColor | - -Here is an example of overriding `primaryColor` and giving everything a different look, using `%%init%%`. - -```mermaid-example -%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%% - 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': '#ff0000'}}}%% - 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 -``` - -**Notes:** -Leaving it empty will set all variable values to default. - -## 8.6.0 (2020-07-13) - -🔖 [Release Notes](https://github.com/mermaid-js/mermaid/releases/tag/8.6.0) - -[Version 8.6.0](../getting-started/8.6.0_docs.md) introduces New Configuration Protocols and Directives and a Beta for the [New Mermaid Live-Editor](https://mermaid-js.github.io/docs/mermaid-live-editor-beta/#/edit/eyJjb2RlIjoiJSV7aW5pdDoge1widGhlbWVcIjogXCJmb3Jlc3RcIiwgXCJsb2dMZXZlbFwiOiAxIH19JSVcbmdyYXBoIFREXG4gIEFbQ2hyaXN0bWFzXSAtLT58R2V0IG1vbmV5fCBCKEdvIHNob3BwaW5nKVxuICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgQyAtLT58T25lfCBEW0xhcHRvcF1cbiAgQyAtLT58VHdvfCBFW2lQaG9uZV1cbiAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl1cblx0XHQiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGFyayJ9fQ) - -**With version 8.6.0 comes the release of directives for mermaid, a new system for modifying configurations, with the aim of establishing centralized, sane defaults and simple implementation.** - -Directives allow for a diagram specific overriding of config, as it has been discussed in Configurations. -This allows site users to input modifications to config alongside diagram definitions, when creating diagrams on a private webpage that supports Mermaid. - -## 8.5.0 (2020-04-11) - -🔖 [Release Notes](https://github.com/mermaid-js/mermaid/releases/tag/untagged-31c93788afe260d914bb) - -This version introduces New diagrams! - -**New diagrams in 8.5** - -With version 8.5 there are some bug fixes and enhancements, plus a new diagram type, entity relationship diagrams. - -![Image showing the new ER diagram type](./img/er.png) - -## 8.2.0 (2019-07-17) - -🏷️ [Tag](https://github.com/mermaid-js/mermaid/tree/8.2.0) - -Version 8.2.0, introduces a security improvement. - -A `securityLevel` configuration has to first be cleared, `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. -This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use. - -### securityLevel - -| Parameter | Description | Type | Required | Values | -| ------------- | --------------------------------- | ------ | -------- | ------------------------- | -| securitylevel | Level of trust for parsed diagram | String | Required | Strict, Loose, antiscript | - -**Notes:** - -- **strict**: (**default**) tags in text are encoded, click functionality is disabled -- **loose**: tags in text are allowed, click functionality is enabled -- **antiscript**: html tags in text are allowed, (only script element is removed), click functionality is enabled - -⚠️ **Note**: This changes the default behaviour of mermaid so that after upgrade to 8.2, if the `securityLevel` is not configured, tags in flowcharts are encoded as tags and clicking is prohibited. - -If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing. -By doing this clicks and tags are again allowed. - -### To change `securityLevel` with `mermaidAPI.initialize`: - -```javascript -mermaidAPI.initialize({ - securityLevel: 'loose', -}); -``` - -**Closed issues:** - -- please add tag for 8.0.0 release [#863](https://github.com/knsv/mermaid/issues/863) -- classDiagram breaks on any edit [#858](https://github.com/knsv/mermaid/issues/858) - -## [8.1.0](https://github.com/knsv/mermaid/tree/8.1.0) (2019-06-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.5...8.1.0) - -**Implemented enhancements:** - -- Theme for dark background [#301](https://github.com/knsv/mermaid/issues/301) -- \[Feature request] gantt diagram axis format [#269](https://github.com/knsv/mermaid/issues/269) -- Implement render function for server side rendering using phantomjs [#169](https://github.com/knsv/mermaid/issues/169) - -**Fixed bugs:** - -- mermaid -v filename.mmd gives You must specify at least one source file. [#328](https://github.com/knsv/mermaid/issues/328) -- Not Able to See Labels even htmlLabels:false added [#268](https://github.com/knsv/mermaid/issues/268) - -**Closed issues:** - -- Gantt and sequence diagram do not render [#853](https://github.com/knsv/mermaid/issues/853) -- margins around flowchart are not balanced [#852](https://github.com/knsv/mermaid/issues/852) -- Smaller bundles [#843](https://github.com/knsv/mermaid/issues/843) -- unicode in labels [#776](https://github.com/knsv/mermaid/issues/776) -- Hard-changing drawing of arrows per edge type [#775](https://github.com/knsv/mermaid/issues/775) -- SequenceDiagram wrong [#773](https://github.com/knsv/mermaid/issues/773) -- Render mermaid on github pages with simple code [#772](https://github.com/knsv/mermaid/issues/772) -- FlowChart - large space between text and the image [#754](https://github.com/knsv/mermaid/issues/754) -- Class Diagram Issues when using Mermaid in Stackedit [#748](https://github.com/knsv/mermaid/issues/748) -- Multi-platform CI [#744](https://github.com/knsv/mermaid/issues/744) -- gantt: sections can't have a colon [#742](https://github.com/knsv/mermaid/issues/742) -- Yarn build does not add mermaid.min.css to dist [#732](https://github.com/knsv/mermaid/issues/732) -- Is there a grammar / keyword / more than just the basic examples? [#718](https://github.com/knsv/mermaid/issues/718) -- Click event and react component [#717](https://github.com/knsv/mermaid/issues/717) -- Long text going outside the box [#706](https://github.com/knsv/mermaid/issues/706) -- How to migrate from yUML to mermaid? [#704](https://github.com/knsv/mermaid/issues/704) -- Issue on Dynamic Creation in PHP [#690](https://github.com/knsv/mermaid/issues/690) -- `click "\#target"` and `click "http://url"` should create regular links [#689](https://github.com/knsv/mermaid/issues/689) -- Support Chinese punctuation [#687](https://github.com/knsv/mermaid/issues/687) -- \[Question] Proper way to install on Mac? [#681](https://github.com/knsv/mermaid/issues/681) -- Has Mermaid a graphical interface to make diagrams? [#668](https://github.com/knsv/mermaid/issues/668) -- mermaid installation on debian [#649](https://github.com/knsv/mermaid/issues/649) -- "Cannot activate" in sequenceDiagram [#647](https://github.com/knsv/mermaid/issues/647) -- Link ("click" statement) in flowchart does not work in exported SVG [#646](https://github.com/knsv/mermaid/issues/646) -- How to pass styling [#639](https://github.com/knsv/mermaid/issues/639) -- The live editor cant show seq diagram with notes for 8.0.0-alpha.3 [#638](https://github.com/knsv/mermaid/issues/638) -- import mermaid.css with ES6 + NPM [#634](https://github.com/knsv/mermaid/issues/634) -- Actor line cuts through other elements [#633](https://github.com/knsv/mermaid/issues/633) -- Graph TD line out of the picture (left side) [#630](https://github.com/knsv/mermaid/issues/630) -- Flowchart labels appear "cutoff" [#628](https://github.com/knsv/mermaid/issues/628) -- Uncaught TypeError: \_.constant is not a function (mermaid.js) [#626](https://github.com/knsv/mermaid/issues/626) -- Missing tags and releases for newer versions [#623](https://github.com/knsv/mermaid/issues/623) -- Mermaid and Leo / Leo Vue [#622](https://github.com/knsv/mermaid/issues/622) -- mermaidAPI gantt Vue.js [#621](https://github.com/knsv/mermaid/issues/621) -- Gantt sections are not separated by colors - Fix: set numberSectionStyles to 4 instead of 3 [#620](https://github.com/knsv/mermaid/issues/620) -- how to get mermaidAPI? [#617](https://github.com/knsv/mermaid/issues/617) -- Error in startOnLoad documentation? [#616](https://github.com/knsv/mermaid/issues/616) -- Example export to SVG generates error [#614](https://github.com/knsv/mermaid/issues/614) -- The new online editor does not support previously generated links [#613](https://github.com/knsv/mermaid/issues/613) -- Grammar / Syntax documentation for flowcharts [#607](https://github.com/knsv/mermaid/issues/607) -- Mermaid does not work with d3.js [#606](https://github.com/knsv/mermaid/issues/606) -- Why does this code's flowchart lines get cut-off on screen? [#604](https://github.com/knsv/mermaid/issues/604) -- click keyword does not fire my callback (on the demo Website too) [#603](https://github.com/knsv/mermaid/issues/603) -- Online Editor fails to show exported SVG [#601](https://github.com/knsv/mermaid/issues/601) -- Just saying thanks! [#597](https://github.com/knsv/mermaid/issues/597) -- stylesheet crashed with other library like abcjs [#596](https://github.com/knsv/mermaid/issues/596) -- Missing connection [#594](https://github.com/knsv/mermaid/issues/594) -- How to use mermaid on node.js restful api? [#593](https://github.com/knsv/mermaid/issues/593) -- Remove status code [#589](https://github.com/knsv/mermaid/issues/589) -- Golang based editor [#588](https://github.com/knsv/mermaid/issues/588) -- sequenceDiagram -> notetext css font is hardcoded [#587](https://github.com/knsv/mermaid/issues/587) -- Multiple graph in the live editor [#586](https://github.com/knsv/mermaid/issues/586) -- All \ elements in page are colored black [#584](https://github.com/knsv/mermaid/issues/584) -- Styling: classes aren't applied to elements. [#582](https://github.com/knsv/mermaid/issues/582) -- Rounded connections [#580](https://github.com/knsv/mermaid/issues/580) -- Arrows are not being shown correctly in the dark theme [#578](https://github.com/knsv/mermaid/issues/578) -- The documentation for CLI seems outdated. [#572](https://github.com/knsv/mermaid/issues/572) -- No effect of click event:can not open link [#571](https://github.com/knsv/mermaid/issues/571) -- Text colors are not correct in VSCODE [#570](https://github.com/knsv/mermaid/issues/570) -- Nodes aren't aligned properly (just need an explanation) [#568](https://github.com/knsv/mermaid/issues/568) -- setting margin around figure in R [#567](https://github.com/knsv/mermaid/issues/567) -- Arrows should Come out in upward and Downward direction from decision Node [#566](https://github.com/knsv/mermaid/issues/566) -- TypeError: Cannot read property 'select' of undefined [#563](https://github.com/knsv/mermaid/issues/563) -- A little bug [#557](https://github.com/knsv/mermaid/issues/557) -- Japanese text appears garbled [#554](https://github.com/knsv/mermaid/issues/554) -- classdiagram not works in mermaid live_editor [#553](https://github.com/knsv/mermaid/issues/553) -- font awesome in link text? [#546](https://github.com/knsv/mermaid/issues/546) -- q: heard of the cosmogol standard? [#545](https://github.com/knsv/mermaid/issues/545) -- Arrow heads missing (cli, 7.0.3) [#544](https://github.com/knsv/mermaid/issues/544) -- No Edge Boxes if useHtmlLabels=false [#541](https://github.com/knsv/mermaid/issues/541) -- how to change mermaid text color or line text block color? [#534](https://github.com/knsv/mermaid/issues/534) -- FlowChart visualization broken when downloading from live editor [#533](https://github.com/knsv/mermaid/issues/533) -- Can't get flowchart to render paths at the top of the diagram; I even tried the online editor and that shows the same issue. Thoughts? [#532](https://github.com/knsv/mermaid/issues/532) -- live editor make browser(safari on macOS\&iOS) not longer respond [#531](https://github.com/knsv/mermaid/issues/531) -- css classes need a prefix/namespace [#527](https://github.com/knsv/mermaid/issues/527) -- input activate/deactivate cause safari unresponding [#521](https://github.com/knsv/mermaid/issues/521) -- Cannot Render the Mermaid Graph to PDF ? [#520](https://github.com/knsv/mermaid/issues/520) -- clicking links works from inset in subgraph but not from nodes [#516](https://github.com/knsv/mermaid/issues/516) -- Strange syntax error - when importing mermaid.js [#515](https://github.com/knsv/mermaid/issues/515) -- gantt x-axis display [#510](https://github.com/knsv/mermaid/issues/510) -- phantomjs renamed to phantomjs-prebuilt [#508](https://github.com/knsv/mermaid/issues/508) -- issue when using sphinxcontrib-mermaid extension for sphinx [#507](https://github.com/knsv/mermaid/issues/507) -- layout of docs page looks broken [#504](https://github.com/knsv/mermaid/issues/504) -- Problem showing graph with php on localhost [#502](https://github.com/knsv/mermaid/issues/502) -- logLevel's option doesn't 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) -- 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) -- Very different styles when rendering as png vs. svg [#489](https://github.com/knsv/mermaid/issues/489) -- New editor that supports mermaid: Caret [#488](https://github.com/knsv/mermaid/issues/488) -- Gant PNG margin [#486](https://github.com/knsv/mermaid/issues/486) -- ReferenceError: window is not defined [#485](https://github.com/knsv/mermaid/issues/485) -- Menu and layout bugs in docs [#484](https://github.com/knsv/mermaid/issues/484) -- Mermaid resets some of the page CSS styles [#482](https://github.com/knsv/mermaid/issues/482) -- Arrows rendering incorrectly in online editor [#480](https://github.com/knsv/mermaid/issues/480) -- CSS stroke-dasharray ignored by browsers but not other viewers [#474](https://github.com/knsv/mermaid/issues/474) -- mermaid - Browser Support issue [#472](https://github.com/knsv/mermaid/issues/472) -- Totally love mermaid I might pop! [#471](https://github.com/knsv/mermaid/issues/471) -- Sequence Diagram: Missing x on async arrows (png) [#469](https://github.com/knsv/mermaid/issues/469) -- live editor: the svg file rendered from graph is not supported by browsers [#468](https://github.com/knsv/mermaid/issues/468) -- Not found css [#462](https://github.com/knsv/mermaid/issues/462) -- Phantomjs Dependency [#461](https://github.com/knsv/mermaid/issues/461) -- Mermaid cli not working for subgraphs [#459](https://github.com/knsv/mermaid/issues/459) -- Support for notes across multiple participants? [#458](https://github.com/knsv/mermaid/issues/458) -- Related to Issue #329: Phantomjs issues. [#455](https://github.com/knsv/mermaid/issues/455) -- Add a click style [#426](https://github.com/knsv/mermaid/issues/426) -- Add Parallel block (par) to sequence diagrams [#425](https://github.com/knsv/mermaid/issues/425) -- updating shapes after the flow chart rendering complete [#424](https://github.com/knsv/mermaid/issues/424) -- can't catch parse error Maximum call stack size exceeded on safari [#421](https://github.com/knsv/mermaid/issues/421) -- Arrows endings are missing [#419](https://github.com/knsv/mermaid/issues/419) -- shouldn't mermaid become more like Markdown ? [#417](https://github.com/knsv/mermaid/issues/417) -- Live editor show rendered diagram if syntax invalid [#415](https://github.com/knsv/mermaid/issues/415) -- Linkstyle stroke does not work [#410](https://github.com/knsv/mermaid/issues/410) -- flowchart id's with dots in them .. break links [#408](https://github.com/knsv/mermaid/issues/408) -- Flowchart: Link text beginning with lowercase 'o' causes flowchart to break [#407](https://github.com/knsv/mermaid/issues/407) -- Some Chinese character will case Safari no responding. [#405](https://github.com/knsv/mermaid/issues/405) -- Cannot center-justify text in nodes? [#397](https://github.com/knsv/mermaid/issues/397) -- Edge labels should have white background in live editor [#396](https://github.com/knsv/mermaid/issues/396) -- Live editor does not support activate/deactivate [#394](https://github.com/knsv/mermaid/issues/394) -- Styling subgraph? [#391](https://github.com/knsv/mermaid/issues/391) -- Update live editor to version 6.0.0 [#387](https://github.com/knsv/mermaid/issues/387) -- sequence diagram config issue [#385](https://github.com/knsv/mermaid/issues/385) -- How to add newline in the text [#384](https://github.com/knsv/mermaid/issues/384) -- PhantomJS crashes on a large graph [#380](https://github.com/knsv/mermaid/issues/380) -- Finnish support for class diagrams using plantuml syntax [#377](https://github.com/knsv/mermaid/issues/377) -- mermaidAPI.render generated different svg code from mermaid.int() [#374](https://github.com/knsv/mermaid/issues/374) -- Put your own action on the chart [#372](https://github.com/knsv/mermaid/issues/372) -- when declaring participants the elements are generated twice [#370](https://github.com/knsv/mermaid/issues/370) -- Example Flowchart is cut in display (Chrome). [#368](https://github.com/knsv/mermaid/issues/368) -- Add shebang support to diagrams [#365](https://github.com/knsv/mermaid/issues/365) -- Silencing CLI output [#352](https://github.com/knsv/mermaid/issues/352) -- SequenceDiagram: 3+ Alternative Paths [#348](https://github.com/knsv/mermaid/issues/348) -- Smaller height of actor boxes [#342](https://github.com/knsv/mermaid/issues/342) -- Question: lib/phantomscript.js - foreignObjects in SVG - related to #58 [#340](https://github.com/knsv/mermaid/issues/340) -- npm test fails on osx being blocked at Can not load "PhantomJS", it is not registered! [#337](https://github.com/knsv/mermaid/issues/337) -- Tabs & subgraphs cause rendering error [#336](https://github.com/knsv/mermaid/issues/336) -- Display question: right angles [#335](https://github.com/knsv/mermaid/issues/335) -- No Arrows rendered v0.5.8 [#330](https://github.com/knsv/mermaid/issues/330) -- You had errors in your syntax. Use --help for further information. [#327](https://github.com/knsv/mermaid/issues/327) -- Allow alternate arrow syntax that doesn't close html comments [#322](https://github.com/knsv/mermaid/issues/322) -- Comment in subgraph [#319](https://github.com/knsv/mermaid/issues/319) -- Update graph [#311](https://github.com/knsv/mermaid/issues/311) -- css conflicts with boostrap's css [#308](https://github.com/knsv/mermaid/issues/308) -- Can not get click event to fire. [#306](https://github.com/knsv/mermaid/issues/306) -- Fix phantomjs2 compatibility [#304](https://github.com/knsv/mermaid/issues/304) -- Flowcharts do not work in native IE11 [#303](https://github.com/knsv/mermaid/issues/303) -- Integration with remark.js - tutorial added [#302](https://github.com/knsv/mermaid/issues/302) -- Sequence diagram Loops: changing boxMargin spoils the "loop" notation [#299](https://github.com/knsv/mermaid/issues/299) -- src/mermaid.js generates bad code [#297](https://github.com/knsv/mermaid/issues/297) -- Fresh fork: jasmine tests fail [#294](https://github.com/knsv/mermaid/issues/294) -- CSS clash [#292](https://github.com/knsv/mermaid/issues/292) -- Mermaid does not work in Chrome 48 [#281](https://github.com/knsv/mermaid/issues/281) -- circle and ellipse cannot change color by classDef [#271](https://github.com/knsv/mermaid/issues/271) -- npm run watch doesn't work due missing dependencies [#266](https://github.com/knsv/mermaid/issues/266) -- label out of node [#262](https://github.com/knsv/mermaid/issues/262) -- IE11 Support issue [#261](https://github.com/knsv/mermaid/issues/261) -- mermaid without browser [#260](https://github.com/knsv/mermaid/issues/260) -- Insufficient capacity of gantt diagrams [#226](https://github.com/knsv/mermaid/issues/226) -- some WARN about installation [#222](https://github.com/knsv/mermaid/issues/222) -- Live editor offline access [#217](https://github.com/knsv/mermaid/issues/217) -- suggest: code highlight mode config for editors [#212](https://github.com/knsv/mermaid/issues/212) -- Uncaught RangeError: Maximum call stack size exceeded [#189](https://github.com/knsv/mermaid/issues/189) -- Styling label texts [#50](https://github.com/knsv/mermaid/issues/50) - -**Merged pull requests:** - -- Remove console.log in classDB. [#861](https://github.com/knsv/mermaid/pull/861) ([Arthaey](https://github.com/Arthaey)) -- Bump sshpk from 1.13.1 to 1.16.1 [#851](https://github.com/knsv/mermaid/pull/851) ([dependabot\[bot\]](https://github.com/apps/dependabot)) -- Significantly smaller bundles [#850](https://github.com/knsv/mermaid/pull/850) ([fabiospampinato](https://github.com/fabiospampinato)) -- Support styling of subgraphs [#845](https://github.com/knsv/mermaid/pull/845) ([Qix-](https://github.com/Qix-)) -- fix dark theme loop labels not visible [#837](https://github.com/knsv/mermaid/pull/837) ([jnnnnn](https://github.com/jnnnnn)) -- fix draw function can only call once [#832](https://github.com/knsv/mermaid/pull/832) ([vaniship](https://github.com/vaniship)) -- Fix dotted lines not appearing in flowcharts when HTML labels disabled [#828](https://github.com/knsv/mermaid/pull/828) ([stanhu](https://github.com/stanhu)) -- Fix issue with XML line breaks inside vertex labels [#824](https://github.com/knsv/mermaid/pull/824) ([jsyang](https://github.com/jsyang)) -- fixed diagrams [#810](https://github.com/knsv/mermaid/pull/810) ([0xflotus](https://github.com/0xflotus)) -- Clickable gantt tasks [#804](https://github.com/knsv/mermaid/pull/804) ([abzicht](https://github.com/abzicht)) -- linkStyle now supports list of indexes with a few tests [#798](https://github.com/knsv/mermaid/pull/798) ([ivan-danilov](https://github.com/ivan-danilov)) -- fix class diagram mermaid [#795](https://github.com/knsv/mermaid/pull/795) ([DanShai](https://github.com/DanShai)) -- Added exclude weekdays to definition [#792](https://github.com/knsv/mermaid/pull/792) ([jopapo](https://github.com/jopapo)) -- SVG link rendering [#791](https://github.com/knsv/mermaid/pull/791) ([flying-sheep](https://github.com/flying-sheep)) -- Gantt milestones [#788](https://github.com/knsv/mermaid/pull/788) ([gijswijs](https://github.com/gijswijs)) -- Remove duplicate code [#768](https://github.com/knsv/mermaid/pull/768) ([znxkznxk1030](https://github.com/znxkznxk1030)) -- Render nodes as real links [#765](https://github.com/knsv/mermaid/pull/765) ([flying-sheep](https://github.com/flying-sheep)) -- Fix issue with marker-end. [#757](https://github.com/knsv/mermaid/pull/757) ([gjlubbertsen](https://github.com/gjlubbertsen)) -- Make Class Diagrams usable in Stackedit and Live Editor [#749](https://github.com/knsv/mermaid/pull/749) ([monsterkrampe](https://github.com/monsterkrampe)) -- Adding trapezoid and inverse trapezoid vertex options. [#741](https://github.com/knsv/mermaid/pull/741) ([adamwulf](https://github.com/adamwulf)) -- Add option for right angles [#721](https://github.com/knsv/mermaid/pull/721) ([paulbland](https://github.com/paulbland)) -- Add nested activation classes [#720](https://github.com/knsv/mermaid/pull/720) ([paulbland](https://github.com/paulbland)) -- wip: class diagram cardinality display [#705](https://github.com/knsv/mermaid/pull/705) ([Vrixyz](https://github.com/Vrixyz)) -- add comments about CSS in config [#688](https://github.com/knsv/mermaid/pull/688) ([imma90](https://github.com/imma90)) -- SequenceDiagram: Add support for multiple alt else statements [#641](https://github.com/knsv/mermaid/pull/641) ([sechel](https://github.com/sechel)) -- fix #426 - add class .clickable on nodes with click function or link [#598](https://github.com/knsv/mermaid/pull/598) ([thomasleveil](https://github.com/thomasleveil)) -- Spec fix 1 [#595](https://github.com/knsv/mermaid/pull/595) ([frankschmitt](https://github.com/frankschmitt)) - -## [7.0.5](https://github.com/knsv/mermaid/tree/7.0.5) (2017-09-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.3...7.0.5) - -**Closed issues:** - -- live editor latin error after update [#560](https://github.com/knsv/mermaid/issues/560) -- Simple full example in online documentation is broken [#558](https://github.com/knsv/mermaid/issues/558) -- Graph No Arrow Head v7.0.3 [#543](https://github.com/knsv/mermaid/issues/543) -- Conflict while using mermaid along with core-js [#512](https://github.com/knsv/mermaid/issues/512) -- Export to pdf on website [#496](https://github.com/knsv/mermaid/issues/496) -- New downstream project: Mermaid Preview for VSCode [#442](https://github.com/knsv/mermaid/issues/442) -- Can't Zoom the flowchart ? [#399](https://github.com/knsv/mermaid/issues/399) -- line labels are not rendered correctly in live editor [#366](https://github.com/knsv/mermaid/issues/366) -- mermaid-loader [#361](https://github.com/knsv/mermaid/issues/361) -- Are there any documentation or examples for classDiagram and gitGraph? [#359](https://github.com/knsv/mermaid/issues/359) -- \# character broken in 0.5.8 [#347](https://github.com/knsv/mermaid/issues/347) -- Documentation issue: CSS example is not visible [#345](https://github.com/knsv/mermaid/issues/345) -- Include documentation for command line usage [#326](https://github.com/knsv/mermaid/issues/326) -- Fresh fork: can't build dist [#296](https://github.com/knsv/mermaid/issues/296) -- Invalid value for \ attribute viewBox="0 0 -Infinity -Infinity" [#291](https://github.com/knsv/mermaid/issues/291) -- Webpack require fails [#277](https://github.com/knsv/mermaid/issues/277) -- New documentation - need improved logo [#216](https://github.com/knsv/mermaid/issues/216) - -## [7.0.3](https://github.com/knsv/mermaid/tree/7.0.3) (2017-06-04) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.2...7.0.3) - -**Closed issues:** - -- the documentation website is down [#539](https://github.com/knsv/mermaid/issues/539) -- Good example of interactivity with mermaidAPI [#514](https://github.com/knsv/mermaid/issues/514) - -## [7.0.2](https://github.com/knsv/mermaid/tree/7.0.2) (2017-06-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.0...7.0.2) - -**Closed issues:** - -- CDN is not working [#511](https://github.com/knsv/mermaid/issues/511) -- A sampe sequenceDiagram crashes mermaid-cli [#492](https://github.com/knsv/mermaid/issues/492) -- Mermaid doesn't delete nodes when called multiple times [#491](https://github.com/knsv/mermaid/issues/491) -- API crashes on 2nd render() call [#478](https://github.com/knsv/mermaid/issues/478) -- sequenceDiagram: dotted line for alt and empty bracket should be hidden [#456](https://github.com/knsv/mermaid/issues/456) -- SVG output (almost) not correct [#434](https://github.com/knsv/mermaid/issues/434) -- How to set axisFormatter of gantt in mermaid CLI? [#428](https://github.com/knsv/mermaid/issues/428) -- customizing link style with any color sets `fill` property to `black` instead of `none` [#416](https://github.com/knsv/mermaid/issues/416) -- New line at the end of SVG file [#400](https://github.com/knsv/mermaid/issues/400) -- CLI doesn't work [#389](https://github.com/knsv/mermaid/issues/389) -- Can't render subgraphs with htmlLabels: false [#367](https://github.com/knsv/mermaid/issues/367) -- Color arrowhead [#362](https://github.com/knsv/mermaid/issues/362) -- CLI: Invisible text, lines in SVG output [#341](https://github.com/knsv/mermaid/issues/341) - -**Merged pull requests:** - -- Support Multi-line Actor Descriptions [#764](https://github.com/knsv/mermaid/pull/764) ([watsoncj](https://github.com/watsoncj)) -- Update Travis config [#538](https://github.com/knsv/mermaid/pull/538) ([tylerlong](https://github.com/tylerlong)) -- Fix spelling of 'you' in sequenceDiagram docs [#537](https://github.com/knsv/mermaid/pull/537) ([ctruelson](https://github.com/ctruelson)) -- Improve CLI output [#536](https://github.com/knsv/mermaid/pull/536) ([gibson042](https://github.com/gibson042)) -- Modernize mermaid [#524](https://github.com/knsv/mermaid/pull/524) ([tylerlong](https://github.com/tylerlong)) -- Modernize mermaid [#519](https://github.com/knsv/mermaid/pull/519) ([tylerlong](https://github.com/tylerlong)) -- Update CLI instructions [#509](https://github.com/knsv/mermaid/pull/509) ([filipedeschamps](https://github.com/filipedeschamps)) -- Add style for classDiagram to dark/default theme [#503](https://github.com/knsv/mermaid/pull/503) ([yudenzel](https://github.com/yudenzel)) -- Fix documentation for git graph. [#498](https://github.com/knsv/mermaid/pull/498) ([gomlgs](https://github.com/gomlgs)) -- Fix links in documentations [#497](https://github.com/knsv/mermaid/pull/497) ([saveman71](https://github.com/saveman71)) -- Update README.md with git graph sample [#481](https://github.com/knsv/mermaid/pull/481) ([raghur](https://github.com/raghur)) -- Fix misspelling of “another” [#479](https://github.com/knsv/mermaid/pull/479) ([stevenschobert](https://github.com/stevenschobert)) -- Fixed #456 sequenceDiagram: dotted line for alt and empty bracket sho… [#477](https://github.com/knsv/mermaid/pull/477) ([brookhong](https://github.com/brookhong)) -- Add viewbox attr to class diagram [#473](https://github.com/knsv/mermaid/pull/473) ([gnkm](https://github.com/gnkm)) -- add par statement to sequenceDiagram [#470](https://github.com/knsv/mermaid/pull/470) ([u-minor](https://github.com/u-minor)) - -## [7.0.0](https://github.com/knsv/mermaid/tree/7.0.0) (2017-01-29) - -[Full Changelog](https://github.com/knsv/mermaid/compare/6.0.0...7.0.0) - -**Implemented enhancements:** - -- npm install -g mermaid does not install phantomjs [#329](https://github.com/knsv/mermaid/issues/329) -- activation boxes [#313](https://github.com/knsv/mermaid/issues/313) - -**Closed issues:** - -- demos on io site not working [#466](https://github.com/knsv/mermaid/issues/466) -- Can not be generated PNG pictures through CLI with Chinese [#451](https://github.com/knsv/mermaid/issues/451) -- Round nodes cannot be styled with CSS classes [#443](https://github.com/knsv/mermaid/issues/443) -- webpack gulp UglifyJsPlugin error. [#440](https://github.com/knsv/mermaid/issues/440) -- String concatenation isn't working [#432](https://github.com/knsv/mermaid/issues/432) -- text flow/wrap in actor box of sequence diagram [#422](https://github.com/knsv/mermaid/issues/422) -- Online live editor still use old version [#402](https://github.com/knsv/mermaid/issues/402) -- uncaught TypeError: t.getTransformToElement is not a function [#401](https://github.com/knsv/mermaid/issues/401) -- Only works when using browserify'd code [#373](https://github.com/knsv/mermaid/issues/373) -- document the use of shebang line in mmd files [#364](https://github.com/knsv/mermaid/issues/364) -- Diagrams are small and unreadable in IE 11 - since 0.5.1 [#356](https://github.com/knsv/mermaid/issues/356) -- \[Feature Request] ER-Diagram Support [#354](https://github.com/knsv/mermaid/issues/354) -- The need for mermaid.css should be mentioned explicitly in the intro docs... [#273](https://github.com/knsv/mermaid/issues/273) - -**Merged pull requests:** - -- Update index.html [#465](https://github.com/knsv/mermaid/pull/465) ([bmsleight](https://github.com/bmsleight)) -- Fix for #416, customizing link style with any color sets `fill` property to `black` instead of `none` [#452](https://github.com/knsv/mermaid/pull/452) ([joshuacolvin](https://github.com/joshuacolvin)) -- Allow .node>circle to receive css styles [#449](https://github.com/knsv/mermaid/pull/449) ([bfriedz](https://github.com/bfriedz)) -- Fix spelling [#447](https://github.com/knsv/mermaid/pull/447) ([jawn](https://github.com/jawn)) -- added tests and fix cli css style selector lowercase problem [#445](https://github.com/knsv/mermaid/pull/445) ([whyzdev](https://github.com/whyzdev)) -- Update d3.js [#441](https://github.com/knsv/mermaid/pull/441) ([hetz](https://github.com/hetz)) -- added tests to reproduce #434 in flowchart [#439](https://github.com/knsv/mermaid/pull/439) ([whyzdev](https://github.com/whyzdev)) -- Code Climate config [#437](https://github.com/knsv/mermaid/pull/437) ([larkinscott](https://github.com/larkinscott)) -- fix gantt and sequence digram cli cfg [#435](https://github.com/knsv/mermaid/pull/435) ([whyzdev](https://github.com/whyzdev)) -- fix gantt chart cli configuration broken [#433](https://github.com/knsv/mermaid/pull/433) ([whyzdev](https://github.com/whyzdev)) -- fix gantt chart cli configuration parsing including functions [#430](https://github.com/knsv/mermaid/pull/430) ([whyzdev](https://github.com/whyzdev)) -- Uses an empty text node instead of a string for svg group labels [#429](https://github.com/knsv/mermaid/pull/429) ([daveaglick](https://github.com/daveaglick)) -- use tspan via d3.textwrap to place actor text in sequence diagram [#427](https://github.com/knsv/mermaid/pull/427) ([whyzdev](https://github.com/whyzdev)) -- \#422 use foreignObject/div to place actor label in sequence diagram [#423](https://github.com/knsv/mermaid/pull/423) ([whyzdev](https://github.com/whyzdev)) -- Clarify the need for a CSS stylesheet [#413](https://github.com/knsv/mermaid/pull/413) ([sifb](https://github.com/sifb)) -- Added hads downstream project [#412](https://github.com/knsv/mermaid/pull/412) ([sinedied](https://github.com/sinedied)) -- update usage and fix #273 [#406](https://github.com/knsv/mermaid/pull/406) ([jinntrance](https://github.com/jinntrance)) -- Add to downstream projects docs page [#404](https://github.com/knsv/mermaid/pull/404) ([raghur](https://github.com/raghur)) -- New neutral theme [#395](https://github.com/knsv/mermaid/pull/395) ([sinedied](https://github.com/sinedied)) -- fix cli issues [#390](https://github.com/knsv/mermaid/pull/390) ([ben-page](https://github.com/ben-page)) -- Add missing space for 'Labels out of bounds' section [#386](https://github.com/knsv/mermaid/pull/386) ([The-Alchemist](https://github.com/The-Alchemist)) -- Fix typo: `pats` -> `paths` [#382](https://github.com/knsv/mermaid/pull/382) ([swhgoon](https://github.com/swhgoon)) -- Added class diagram example to README.md [#379](https://github.com/knsv/mermaid/pull/379) ([HustLion](https://github.com/HustLion)) -- override normal flowchart arrowhead to allow css styling [#376](https://github.com/knsv/mermaid/pull/376) ([dodoinblue](https://github.com/dodoinblue)) -- added sphinx extension [#371](https://github.com/knsv/mermaid/pull/371) ([mgaitan](https://github.com/mgaitan)) -- Fix typo in the sequence diagram documentation [#369](https://github.com/knsv/mermaid/pull/369) ([ggpasqualino](https://github.com/ggpasqualino)) - -## [6.0.0](https://github.com/knsv/mermaid/tree/6.0.0) (2016-05-29) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.8...6.0.0) - -**Closed issues:** - -- Docs css: code hard to read [#324](https://github.com/knsv/mermaid/issues/324) -- About Markpad integration [#323](https://github.com/knsv/mermaid/issues/323) -- How to link backwards in flowchart? [#321](https://github.com/knsv/mermaid/issues/321) -- Help with editor [#310](https://github.com/knsv/mermaid/issues/310) -- \+1 [#293](https://github.com/knsv/mermaid/issues/293) -- Basic chart does not render on Chome, but does in Firefox [#290](https://github.com/knsv/mermaid/issues/290) -- Live editor is broken [#285](https://github.com/knsv/mermaid/issues/285) -- "No such file or directory" trying to run mermaid 0.5.7 on OS X [#284](https://github.com/knsv/mermaid/issues/284) -- participant name as "Long Long Name" [#283](https://github.com/knsv/mermaid/issues/283) -- Windows - cli - could not find phantomjs at the specified path [#236](https://github.com/knsv/mermaid/issues/236) - -**Merged pull requests:** - -- The option of gantt for the spaces for the section names. [#353](https://github.com/knsv/mermaid/pull/353) ([zeroyonichihachi](https://github.com/zeroyonichihachi)) -- Gitgraph: Make reset work with parent ref carets [#350](https://github.com/knsv/mermaid/pull/350) ([raghur](https://github.com/raghur)) -- Remove the text-shadows that make the text look blurry [#349](https://github.com/knsv/mermaid/pull/349) ([AsaAyers](https://github.com/AsaAyers)) -- add line interpolation to linkStyle in flowchart [#346](https://github.com/knsv/mermaid/pull/346) ([AlanHohn](https://github.com/AlanHohn)) -- Support git graph diagrams in mermaid [#344](https://github.com/knsv/mermaid/pull/344) ([raghur](https://github.com/raghur)) -- Build and test execution changes [#338](https://github.com/knsv/mermaid/pull/338) ([ssbarnea](https://github.com/ssbarnea)) -- Reformatting of css files [#331](https://github.com/knsv/mermaid/pull/331) ([Jmuccigr](https://github.com/Jmuccigr)) -- (WIP) Sequence Diagram Title Support [#320](https://github.com/knsv/mermaid/pull/320) ([bronsoja](https://github.com/bronsoja)) -- activations doc + few fixes [#318](https://github.com/knsv/mermaid/pull/318) ([ciekawy](https://github.com/ciekawy)) -- Dark theme for better contrast on darker backgrounds [#317](https://github.com/knsv/mermaid/pull/317) ([crodriguez1a](https://github.com/crodriguez1a)) -- Activations [#316](https://github.com/knsv/mermaid/pull/316) ([ciekawy](https://github.com/ciekawy)) -- Support leading comments for sequenceDiagrams [#312](https://github.com/knsv/mermaid/pull/312) ([ashsearle](https://github.com/ashsearle)) -- Show a little lenience for white-space around names [#309](https://github.com/knsv/mermaid/pull/309) ([ashsearle](https://github.com/ashsearle)) -- Update list of downstream projects [#307](https://github.com/knsv/mermaid/pull/307) ([maxArturo](https://github.com/maxArturo)) -- Issue 299: Sequence diagram Loops: changing boxMargin spoils the "loop" notation [#300](https://github.com/knsv/mermaid/pull/300) ([LarryKlugerDS](https://github.com/LarryKlugerDS)) -- Issue 297 - src/mermaid.js generates bad code [#298](https://github.com/knsv/mermaid/pull/298) ([LarryKlugerDS](https://github.com/LarryKlugerDS)) -- Updated instructions for running tests [#295](https://github.com/knsv/mermaid/pull/295) ([LarryKlugerDS](https://github.com/LarryKlugerDS)) -- Add Markdown Plus to Downstream projects [#288](https://github.com/knsv/mermaid/pull/288) ([tylerlong](https://github.com/tylerlong)) -- Quote phantomPath so that it doesn't fail on window [#286](https://github.com/knsv/mermaid/pull/286) ([raghur](https://github.com/raghur)) - -## [0.5.8](https://github.com/knsv/mermaid/tree/0.5.8) (2016-01-27) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.7...0.5.8) - -## [0.5.7](https://github.com/knsv/mermaid/tree/0.5.7) (2016-01-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.6...0.5.7) - -**Closed issues:** - -- Mermaid + LightPaper = ❤️ [#280](https://github.com/knsv/mermaid/issues/280) -- Bower Integration [#278](https://github.com/knsv/mermaid/issues/278) -- Mermaid breaks when variables end in 'v' [#276](https://github.com/knsv/mermaid/issues/276) -- sequence diagrams don't support participant aliasing [#263](https://github.com/knsv/mermaid/issues/263) -- One diagram that fails to render stops further execution on the page [#259](https://github.com/knsv/mermaid/issues/259) -- Where to find line layout algorithm? [#258](https://github.com/knsv/mermaid/issues/258) -- Compatibility with node.js [#257](https://github.com/knsv/mermaid/issues/257) -- Label resizing with dynamically loaded fonts [#255](https://github.com/knsv/mermaid/issues/255) -- SVG arrowheads are broken in the CLI [#249](https://github.com/knsv/mermaid/issues/249) -- Cannot read property 'replace' of undefined [#239](https://github.com/knsv/mermaid/issues/239) - -**Merged pull requests:** - -- gh-50 Allow styling of edge labels in css [#267](https://github.com/knsv/mermaid/pull/267) ([Anoia](https://github.com/Anoia)) -- Allow sequenceDiagram participant aliasing [#265](https://github.com/knsv/mermaid/pull/265) ([gibson042](https://github.com/gibson042)) - -## [0.5.6](https://github.com/knsv/mermaid/tree/0.5.6) (2015-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.5...0.5.6) - -**Implemented enhancements:** - -- Add download SVG link to the live editor [#144](https://github.com/knsv/mermaid/issues/144) - -**Fixed bugs:** - -- Live Editor: Permalink address not being parsed [#202](https://github.com/knsv/mermaid/issues/202) - -**Closed issues:** - -- title doesn't work in sequenceDiagram [#248](https://github.com/knsv/mermaid/issues/248) -- hypen-minus should be valid in sequence diagram alt/else/etc. descriptions [#247](https://github.com/knsv/mermaid/issues/247) -- Broken in firefox? [#245](https://github.com/knsv/mermaid/issues/245) -- When there is a Chinese symbol in the flowchart, it will crash。 [#238](https://github.com/knsv/mermaid/issues/238) -- Non-alpha characters included in ALPHA token (flow graph jison) [#232](https://github.com/knsv/mermaid/issues/232) -- subgraph not rendering with change to sample [#231](https://github.com/knsv/mermaid/issues/231) -- sequence diagram requires a new line at the end? [#229](https://github.com/knsv/mermaid/issues/229) - -**Merged pull requests:** - -- Make sequenceDiagram terminal newline optional [#253](https://github.com/knsv/mermaid/pull/253) ([gibson042](https://github.com/gibson042)) -- Support sequenceDiagram "over" notes [#252](https://github.com/knsv/mermaid/pull/252) ([gibson042](https://github.com/gibson042)) -- Properly handle "rest of line" statements [#251](https://github.com/knsv/mermaid/pull/251) ([gibson042](https://github.com/gibson042)) -- CLI: Propagate exit code from lib (i.e., phantomjs) [#250](https://github.com/knsv/mermaid/pull/250) ([gibson042](https://github.com/gibson042)) -- flowRender.js - Fix FontAwesome icon insert [#244](https://github.com/knsv/mermaid/pull/244) ([ma-zal](https://github.com/ma-zal)) -- updated sequence diagram link in live editor [#242](https://github.com/knsv/mermaid/pull/242) ([r-a-v-a-s](https://github.com/r-a-v-a-s)) -- updated links in README.md [#240](https://github.com/knsv/mermaid/pull/240) ([r-a-v-a-s](https://github.com/r-a-v-a-s)) -- Ellipse syntax [#237](https://github.com/knsv/mermaid/pull/237) ([spect88](https://github.com/spect88)) -- Allow keywords as suffixes of node ids [#235](https://github.com/knsv/mermaid/pull/235) ([spect88](https://github.com/spect88)) -- Highlighted the editor in the nav [#234](https://github.com/knsv/mermaid/pull/234) ([knsv](https://github.com/knsv)) -- Live editor tweaks [#233](https://github.com/knsv/mermaid/pull/233) ([spect88](https://github.com/spect88)) -- Add a Gitter chat badge to README.md [#230](https://github.com/knsv/mermaid/pull/230) ([gitter-badger](https://github.com/gitter-badger)) - -## [0.5.5](https://github.com/knsv/mermaid/tree/0.5.5) (2015-10-21) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.4...0.5.5) - -**Closed issues:** - -- sequence diagram, arrowhead instead of crosshead [#227](https://github.com/knsv/mermaid/issues/227) - -**Merged pull requests:** - -- Fix a typo: crosshead --> arrowhead [#228](https://github.com/knsv/mermaid/pull/228) ([tylerlong](https://github.com/tylerlong)) - -## [0.5.4](https://github.com/knsv/mermaid/tree/0.5.4) (2015-10-19) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.3...0.5.4) - -**Implemented enhancements:** - -- Set log level from mermaid configuration [#220](https://github.com/knsv/mermaid/issues/220) -- Links in sequence diagrams [#159](https://github.com/knsv/mermaid/issues/159) -- Add syntax for double headed arrows [#123](https://github.com/knsv/mermaid/issues/123) - -**Fixed bugs:** - -- comment characters `%%` cause parse error [#141](https://github.com/knsv/mermaid/issues/141) - -**Closed issues:** - -- Marker-end arrow cannot be shown for URL with query parameter [#225](https://github.com/knsv/mermaid/issues/225) -- Please update bower's D3 version [#221](https://github.com/knsv/mermaid/issues/221) -- Width fixed to 400px [#204](https://github.com/knsv/mermaid/issues/204) -- render to png from the cli does not display the marker-end arrow heads [#181](https://github.com/knsv/mermaid/issues/181) - -**Merged pull requests:** - -- Allow `end` as a substring of vertex id [#224](https://github.com/knsv/mermaid/pull/224) ([spect88](https://github.com/spect88)) -- Remove duplicate npm dependencies: d3 and he [#223](https://github.com/knsv/mermaid/pull/223) ([spect88](https://github.com/spect88)) - -## [0.5.3](https://github.com/knsv/mermaid/tree/0.5.3) (2015-10-04) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.2...0.5.3) - -## [0.5.2](https://github.com/knsv/mermaid/tree/0.5.2) (2015-10-04) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.1...0.5.2) - -**Implemented enhancements:** - -- Support for hyperlink and tooltip [#34](https://github.com/knsv/mermaid/issues/34) - -**Closed issues:** - -- Installing “atom-mermaid\@0.1.3” failed [#218](https://github.com/knsv/mermaid/issues/218) -- node feature request [#211](https://github.com/knsv/mermaid/issues/211) -- Please add prefix for styles [#208](https://github.com/knsv/mermaid/issues/208) -- Bad handling of block arguments [#207](https://github.com/knsv/mermaid/issues/207) -- please consider port to mac osx [#203](https://github.com/knsv/mermaid/issues/203) -- allow phantomjs >=1.9.x [#201](https://github.com/knsv/mermaid/issues/201) -- syntax for venn diagrams? [#200](https://github.com/knsv/mermaid/issues/200) -- Broken CLI Graphs? (v0.5.1) [#196](https://github.com/knsv/mermaid/issues/196) -- Static site does not render under HTTPS [#194](https://github.com/knsv/mermaid/issues/194) -- Error on simple graph [#192](https://github.com/knsv/mermaid/issues/192) -- Escape "\~" [#191](https://github.com/knsv/mermaid/issues/191) -- Trying to add link using 'click' to flowchart [#188](https://github.com/knsv/mermaid/issues/188) -- cli: no lines and arrowheads rendered / only dotted lines [#187](https://github.com/knsv/mermaid/issues/187) -- text of mermaid div displayed on page [#186](https://github.com/knsv/mermaid/issues/186) -- using mermaid with laravel [#185](https://github.com/knsv/mermaid/issues/185) -- Atom editor package [#183](https://github.com/knsv/mermaid/issues/183) -- Auto linewrap for notes in sequence diagrams [#178](https://github.com/knsv/mermaid/issues/178) -- Execute code after initialize [#176](https://github.com/knsv/mermaid/issues/176) -- Autoscaling for all diagram types [#175](https://github.com/knsv/mermaid/issues/175) -- Problem wit click event callback [#174](https://github.com/knsv/mermaid/issues/174) -- How to escape characters? [#170](https://github.com/knsv/mermaid/issues/170) -- it can not work [#167](https://github.com/knsv/mermaid/issues/167) -- Broken subgraph using the CLI [#153](https://github.com/knsv/mermaid/issues/153) -- IE Support issue [#142](https://github.com/knsv/mermaid/issues/142) -- Flowchart truncated [#140](https://github.com/knsv/mermaid/issues/140) -- Double Quote as text is not working [#219](https://github.com/knsv/mermaid/issues/219) -- classDef / class not working with htmlLabels? [#210](https://github.com/knsv/mermaid/issues/210) -- Links in graph missing [#209](https://github.com/knsv/mermaid/issues/209) -- Last word in comment boxes getting cut off by word wrap library : ( [#195](https://github.com/knsv/mermaid/issues/195) -- Escaping characters in sequence diagram [#193](https://github.com/knsv/mermaid/issues/193) -- SVG foreignObject rendering [#180](https://github.com/knsv/mermaid/issues/180) -- IE9 issue [#179](https://github.com/knsv/mermaid/issues/179) -- inoperable in an AMD/requirejs environment: IPython Notebook [#127](https://github.com/knsv/mermaid/issues/127) -- \[Parser] Hyphen in participant name bring TypeError [#74](https://github.com/knsv/mermaid/issues/74) - -**Merged pull requests:** - -- Update flowchart.md [#214](https://github.com/knsv/mermaid/pull/214) ([orschiro](https://github.com/orschiro)) -- Default style when using the CLI [#205](https://github.com/knsv/mermaid/pull/205) ([gillesdemey](https://github.com/gillesdemey)) -- Gantt chart - add minutes and seconds durations [#198](https://github.com/knsv/mermaid/pull/198) ([dbrans](https://github.com/dbrans)) -- Using QUnit for AMD testing [#190](https://github.com/knsv/mermaid/pull/190) ([bollwyvl](https://github.com/bollwyvl)) -- Update phantomscript.js [#182](https://github.com/knsv/mermaid/pull/182) ([phairow](https://github.com/phairow)) - -## [0.5.1](https://github.com/knsv/mermaid/tree/0.5.1) (2015-06-21) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.0...0.5.1) - -**Implemented enhancements:** - -- To SVG Export [#146](https://github.com/knsv/mermaid/issues/146) -- Possibility to set the width of the generated flowchart [#129](https://github.com/knsv/mermaid/issues/129) -- Special characters break parsing [#54](https://github.com/knsv/mermaid/issues/54) -- Responsive graph layout for mobile viewers [#51](https://github.com/knsv/mermaid/issues/51) -- Styling connector lines [#31](https://github.com/knsv/mermaid/issues/31) - -**Fixed bugs:** - -- flowchart - styling of edges via css overrides specific styles set in the graph definition [#128](https://github.com/knsv/mermaid/issues/128) - -**Closed issues:** - -- Live editor is broken [#173](https://github.com/knsv/mermaid/issues/173) -- 0.5.0 no longer respects custom date definitions in Gantt diagrams [#171](https://github.com/knsv/mermaid/issues/171) -- Drop label character restrictions [#162](https://github.com/knsv/mermaid/issues/162) -- can't nest subgraphs in flowchart [#161](https://github.com/knsv/mermaid/issues/161) -- Unable to generate gantt diagram with mermaid CLI [#158](https://github.com/knsv/mermaid/issues/158) -- Inline css by "mermaid" [#157](https://github.com/knsv/mermaid/issues/157) -- Finite State Machine Diagram [#152](https://github.com/knsv/mermaid/issues/152) -- How to center align gantt diagram [#150](https://github.com/knsv/mermaid/issues/150) -- Security concern regarding class definition [#148](https://github.com/knsv/mermaid/issues/148) -- File Extension [#147](https://github.com/knsv/mermaid/issues/147) -- `setTimeout` with clusters problematic with programmatic edits and no callback [#133](https://github.com/knsv/mermaid/issues/133) -- module.exports.cloneCssStyles() in combination with Angularjs breaks display in Chrome and IE [#126](https://github.com/knsv/mermaid/issues/126) -- Gantt - suitable xAxis for longer project [#125](https://github.com/knsv/mermaid/issues/125) -- How to get started with this project ? [#64](https://github.com/knsv/mermaid/issues/64) - -**Merged pull requests:** - -- Remove moot `version` property from bower.json [#172](https://github.com/knsv/mermaid/pull/172) ([kkirsche](https://github.com/kkirsche)) - -## [0.5.0](https://github.com/knsv/mermaid/tree/0.5.0) (2015-06-07) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.4.0...0.5.0) - -**Implemented enhancements:** - -- Add a css file, mermaid.css, with default styling [#122](https://github.com/knsv/mermaid/issues/122) -- software architecture diagram [#36](https://github.com/knsv/mermaid/issues/36) -- Support for bar charts and pie diagrams [#22](https://github.com/knsv/mermaid/issues/22) - -**Closed issues:** - -- uglifyjs wanrings which means we can improve the code [#156](https://github.com/knsv/mermaid/issues/156) -- New(er) features unavailable in downloadable js files? [#151](https://github.com/knsv/mermaid/issues/151) -- Add gh-gapes link to description [#143](https://github.com/knsv/mermaid/issues/143) -- Some examples not displayed on Firefox 36.0.1 [#138](https://github.com/knsv/mermaid/issues/138) -- tags ending in a "v" don't render [#132](https://github.com/knsv/mermaid/issues/132) -- Links in flowchart [#131](https://github.com/knsv/mermaid/issues/131) -- Using the library for iOS development [#130](https://github.com/knsv/mermaid/issues/130) -- Add capability for gantt diagrams [#118](https://github.com/knsv/mermaid/issues/118) -- lower case v causes error in the parser [#108](https://github.com/knsv/mermaid/issues/108) -- Label's css conflict with boostrap's .label [#67](https://github.com/knsv/mermaid/issues/67) -- TypeError: Cannot read property 'layout' of undefined [#37](https://github.com/knsv/mermaid/issues/37) - -**Merged pull requests:** - -- Dev 0.5.0 [#168](https://github.com/knsv/mermaid/pull/168) ([knsv](https://github.com/knsv)) -- Fix spacing [#164](https://github.com/knsv/mermaid/pull/164) ([rhcarvalho](https://github.com/rhcarvalho)) -- Fixing typo: "Think" -> "Thick" [#160](https://github.com/knsv/mermaid/pull/160) ([it0a](https://github.com/it0a)) -- IE, local html, cssRules access is denied [#155](https://github.com/knsv/mermaid/pull/155) ([tylerlong](https://github.com/tylerlong)) -- Add automatically generated change log file. [#139](https://github.com/knsv/mermaid/pull/139) ([skywinder](https://github.com/skywinder)) -- Adding init argument to the global API [#137](https://github.com/knsv/mermaid/pull/137) ([bollwyvl](https://github.com/bollwyvl)) -- Add description of manual calling of init [#136](https://github.com/knsv/mermaid/pull/136) ([bollwyvl](https://github.com/bollwyvl)) -- Allow other forms of node selection for init() [#135](https://github.com/knsv/mermaid/pull/135) ([bollwyvl](https://github.com/bollwyvl)) -- Use a library-level variable for assigning ids [#134](https://github.com/knsv/mermaid/pull/134) ([bollwyvl](https://github.com/bollwyvl)) - -## [0.4.0](https://github.com/knsv/mermaid/tree/0.4.0) (2015-03-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.5...0.4.0) - -**Implemented enhancements:** - -- Assymetric shapes not documented [#82](https://github.com/knsv/mermaid/issues/82) -- Improve arrows [#3](https://github.com/knsv/mermaid/issues/3) - -**Fixed bugs:** - -- NoModificationAllowedError [#23](https://github.com/knsv/mermaid/issues/23) - -**Closed issues:** - -- subgraph background is black in rendered flowchart PNG via CLI [#121](https://github.com/knsv/mermaid/issues/121) -- Integrate editor at [#110](https://github.com/knsv/mermaid/issues/110) -- Internet Explorer Support [#99](https://github.com/knsv/mermaid/issues/99) - -## [0.3.5](https://github.com/knsv/mermaid/tree/0.3.5) (2015-02-15) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.4...0.3.5) - -## [0.3.4](https://github.com/knsv/mermaid/tree/0.3.4) (2015-02-15) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.3...0.3.4) - -**Implemented enhancements:** - -- Apply styling from css when using the CLI utility [#85](https://github.com/knsv/mermaid/issues/85) -- Generated SVG works poorly outside web browsers [#58](https://github.com/knsv/mermaid/issues/58) -- Generating SVG text blob for use in Node [#2](https://github.com/knsv/mermaid/issues/2) - -**Closed issues:** - -- Subgraph syntax bug? [#120](https://github.com/knsv/mermaid/issues/120) -- Live editor [#115](https://github.com/knsv/mermaid/issues/115) -- Error in "Basic Syntax" wiki page [#113](https://github.com/knsv/mermaid/issues/113) -- semicolons, anyone? [#111](https://github.com/knsv/mermaid/issues/111) -- undefined `sequenceConfig` fails [#109](https://github.com/knsv/mermaid/issues/109) -- Sequence Diagrams: Show Actors below as well [#106](https://github.com/knsv/mermaid/issues/106) -- Allow overriding sequence diagram configuration (SVG properties) [#103](https://github.com/knsv/mermaid/issues/103) -- Error when rendering A-- This is the text -- B [#102](https://github.com/knsv/mermaid/issues/102) -- Clipping in documentation [#97](https://github.com/knsv/mermaid/issues/97) -- isolate class styling to the svg container [#92](https://github.com/knsv/mermaid/issues/92) -- Make the new graph declaration more visual [#40](https://github.com/knsv/mermaid/issues/40) - -**Merged pull requests:** - -- Add live editor [#119](https://github.com/knsv/mermaid/pull/119) ([naseer](https://github.com/naseer)) -- Adds CSS option to the CLI [#116](https://github.com/knsv/mermaid/pull/116) ([fardog](https://github.com/fardog)) -- Update flowchart.md in response Issue #113 [#114](https://github.com/knsv/mermaid/pull/114) ([vijay40](https://github.com/vijay40)) -- Ignore all files except the license and dist/ folder when installing with Bower. [#112](https://github.com/knsv/mermaid/pull/112) ([jasonbellamy](https://github.com/jasonbellamy)) - -## [0.3.3](https://github.com/knsv/mermaid/tree/0.3.3) (2015-01-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.2...0.3.3) - -**Implemented enhancements:** - -- Support for dotted links [#26](https://github.com/knsv/mermaid/issues/26) - -**Closed issues:** - -- Missing arrows in sequence diagram [#98](https://github.com/knsv/mermaid/issues/98) -- Error with >9 linkStyles [#95](https://github.com/knsv/mermaid/issues/95) - -**Merged pull requests:** - -- Require d3 directly to better support Node usage [#107](https://github.com/knsv/mermaid/pull/107) ([markdalgleish](https://github.com/markdalgleish)) -- update doc with -c option [#105](https://github.com/knsv/mermaid/pull/105) ([jjmr](https://github.com/jjmr)) -- Add new parameter to the console client to override the svg configuration in sequence diagrams [#104](https://github.com/knsv/mermaid/pull/104) ([jjmr](https://github.com/jjmr)) -- Text based labels, new shape [#101](https://github.com/knsv/mermaid/pull/101) ([bjowes](https://github.com/bjowes)) -- fix html tags in example usage [#100](https://github.com/knsv/mermaid/pull/100) ([deiwin](https://github.com/deiwin)) - -## [0.3.2](https://github.com/knsv/mermaid/tree/0.3.2) (2015-01-11) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.1...0.3.2) - -**Implemented enhancements:** - -- Make link text look like it is on the line [#53](https://github.com/knsv/mermaid/issues/53) - -**Closed issues:** - -- disable auto render [#91](https://github.com/knsv/mermaid/issues/91) -- Tidy breaks mermaid (linebreaks in \
) [#87](https://github.com/knsv/mermaid/issues/87) -- Bug: \
being rendered as text in node [#73](https://github.com/knsv/mermaid/issues/73) -- Graph edges appear to render outside of the canvas [#70](https://github.com/knsv/mermaid/issues/70) - -**Merged pull requests:** - -- 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)) -- 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) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.0...0.3.1) - -**Implemented enhancements:** - -- Support for sequence diagrams [#16](https://github.com/knsv/mermaid/issues/16) -- Client utility for mermaid [#6](https://github.com/knsv/mermaid/issues/6) - -**Closed issues:** - -- Non ASCII chars in labels [#84](https://github.com/knsv/mermaid/issues/84) -- 'undefined' titles of Quicklinks on the usage page [#80](https://github.com/knsv/mermaid/issues/80) -- \[cli] Enhancement proposal: not fail --version / --help if phantomjs isn't installed [#71](https://github.com/knsv/mermaid/issues/71) - -**Merged pull requests:** - -- Flowchart doc: Text in the circle now in a circle [#81](https://github.com/knsv/mermaid/pull/81) ([Grahack](https://github.com/Grahack)) -- Fix for issue #73 [#79](https://github.com/knsv/mermaid/pull/79) ([it0a](https://github.com/it0a)) -- Ink template [#78](https://github.com/knsv/mermaid/pull/78) ([gkchic](https://github.com/gkchic)) -- Show help and version even if phantom isn't present. Fixes #71 [#75](https://github.com/knsv/mermaid/pull/75) ([fardog](https://github.com/fardog)) -- Add apostrophe & 'and' [#72](https://github.com/knsv/mermaid/pull/72) ([sudodoki](https://github.com/sudodoki)) - -## [0.3.0](https://github.com/knsv/mermaid/tree/0.3.0) (2014-12-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.16...0.3.0) - -**Implemented enhancements:** - -- How do I do comments? [#47](https://github.com/knsv/mermaid/issues/47) -- Improve readability with new line as terminator and whitespace [#38](https://github.com/knsv/mermaid/issues/38) - -**Fixed bugs:** - -- This characters failed the lexical parsing [#46](https://github.com/knsv/mermaid/issues/46) - -**Closed issues:** - -- Trailing whitespace at the end of lines is not ignored [#55](https://github.com/knsv/mermaid/issues/55) -- Use classes instead of inline style for easy styling [#24](https://github.com/knsv/mermaid/issues/24) - -**Merged pull requests:** - -- Adds Command Line Interface for generating PNGs from mermaid description files [#69](https://github.com/knsv/mermaid/pull/69) ([fardog](https://github.com/fardog)) -- Allow special symbols for direction along with acronyms [#66](https://github.com/knsv/mermaid/pull/66) ([vijay40](https://github.com/vijay40)) - -## [0.2.16](https://github.com/knsv/mermaid/tree/0.2.16) (2014-12-15) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.15...0.2.16) - -**Fixed bugs:** - -- Lines routed outside visible area [#19](https://github.com/knsv/mermaid/issues/19) - -**Closed issues:** - -- Mermaid not rendering properly on Wordpress pages [#59](https://github.com/knsv/mermaid/issues/59) -- Improve example page with live demo [#52](https://github.com/knsv/mermaid/issues/52) -- Does not render upon AngularJS Updates [#45](https://github.com/knsv/mermaid/issues/45) -- Download link in README.MD doesn't work. [#42](https://github.com/knsv/mermaid/issues/42) -- linkStyle usage is not obvious [#41](https://github.com/knsv/mermaid/issues/41) -- Move \*.spec.js in src/ to test/ [#35](https://github.com/knsv/mermaid/issues/35) - -**Merged pull requests:** - -- New grammar will allow statements ending without semicolon as disccused in Issue #38 [#63](https://github.com/knsv/mermaid/pull/63) ([vijay40](https://github.com/vijay40)) -- Class based styling [#62](https://github.com/knsv/mermaid/pull/62) ([bjowes](https://github.com/bjowes)) -- Fix typos [#60](https://github.com/knsv/mermaid/pull/60) ([sublimino](https://github.com/sublimino)) -- Included .DS_Store in gitignore [#57](https://github.com/knsv/mermaid/pull/57) ([alvynmcq](https://github.com/alvynmcq)) -- Improves readability discussed in issue #38 [#56](https://github.com/knsv/mermaid/pull/56) ([vijay40](https://github.com/vijay40)) -- Added a linting task for gulp [#43](https://github.com/knsv/mermaid/pull/43) ([serv](https://github.com/serv)) - -## [0.2.15](https://github.com/knsv/mermaid/tree/0.2.15) (2014-12-05) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.14...0.2.15) - -**Fixed bugs:** - -- Error with some characters [#25](https://github.com/knsv/mermaid/issues/25) -- Cap-cased words break parser [#8](https://github.com/knsv/mermaid/issues/8) - -**Closed issues:** - -- Question marks don't render properly with /dist/mermaid.full.min.js [#30](https://github.com/knsv/mermaid/issues/30) -- Provide parse function in browser widthout `require`? [#21](https://github.com/knsv/mermaid/issues/21) -- Better label text support [#18](https://github.com/knsv/mermaid/issues/18) - -**Merged pull requests:** - -- Include bower_components/ to .gitignore [#33](https://github.com/knsv/mermaid/pull/33) ([serv](https://github.com/serv)) -- Fixed reference to Git repo. [#32](https://github.com/knsv/mermaid/pull/32) ([guyellis](https://github.com/guyellis)) - -## [0.2.14](https://github.com/knsv/mermaid/tree/0.2.14) (2014-12-03) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.13...0.2.14) - -## [0.2.13](https://github.com/knsv/mermaid/tree/0.2.13) (2014-12-03) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.10...0.2.13) - -**Implemented enhancements:** - -- Publish to NPM [#7](https://github.com/knsv/mermaid/issues/7) - -**Closed issues:** - -- modified init to be applied more than once [#29](https://github.com/knsv/mermaid/issues/29) -- Wanted to know build process for the project. [#28](https://github.com/knsv/mermaid/issues/28) -- can not support Chinese description [#20](https://github.com/knsv/mermaid/issues/20) -- Support unicode chars in labels [#9](https://github.com/knsv/mermaid/issues/9) - -## [0.2.10](https://github.com/knsv/mermaid/tree/0.2.10) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.9...0.2.10) - -## [0.2.9](https://github.com/knsv/mermaid/tree/0.2.9) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.8...0.2.9) - -**Closed issues:** - -- Add link to jsbin playground to README [#11](https://github.com/knsv/mermaid/issues/11) -- What are the requirements ? [#10](https://github.com/knsv/mermaid/issues/10) - -**Merged pull requests:** - -- Allow unicode chars in labels [#13](https://github.com/knsv/mermaid/pull/13) ([codebeige](https://github.com/codebeige)) - -## [0.2.8](https://github.com/knsv/mermaid/tree/0.2.8) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.7...0.2.8) - -## [0.2.7](https://github.com/knsv/mermaid/tree/0.2.7) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.6...0.2.7) - -**Closed issues:** - -- Provide parser as separate module [#4](https://github.com/knsv/mermaid/issues/4) - -## [0.2.6](https://github.com/knsv/mermaid/tree/0.2.6) (2014-11-27) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.5...0.2.6) - -## [0.2.5](https://github.com/knsv/mermaid/tree/0.2.5) (2014-11-27) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.4...0.2.5) - -**Merged pull requests:** - -- Added new shapes! [#1](https://github.com/knsv/mermaid/pull/1) ([bjowes](https://github.com/bjowes)) - -## [0.2.4](https://github.com/knsv/mermaid/tree/0.2.4) (2014-11-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.3...0.2.4) - -## [0.2.3](https://github.com/knsv/mermaid/tree/0.2.3) (2014-11-24) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.2...0.2.3) - -## [0.2.2](https://github.com/knsv/mermaid/tree/0.2.2) (2014-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.1...0.2.2) - -## [0.2.1](https://github.com/knsv/mermaid/tree/0.2.1) (2014-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.0...0.2.1) - -## [0.2.0](https://github.com/knsv/mermaid/tree/0.2.0) (2014-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.1.1...0.2.0) - -## [0.1.1](https://github.com/knsv/mermaid/tree/0.1.1) (2014-11-17) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.1.0...0.1.1) - -## [0.1.0](https://github.com/knsv/mermaid/tree/0.1.0) (2014-11-16) diff --git a/docs/community/code.md b/docs/community/code.md new file mode 100644 index 000000000..e77a25467 --- /dev/null +++ b/docs/community/code.md @@ -0,0 +1,176 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/community/code.md](../../packages/mermaid/src/docs/community/code.md). + +# Contributing Code + +The basic steps for contributing code are: + +```mermaid-example +graph LR + git[1. Checkout a git branch] --> codeTest[2. Write tests and code] --> doc[3. Update documentation] --> submit[4. Submit a PR] --> review[5. Review and merge] +``` + +```mermaid +graph LR + git[1. Checkout a git branch] --> codeTest[2. Write tests and code] --> doc[3. Update documentation] --> submit[4. Submit a PR] --> review[5. Review and merge] +``` + +1. **Create** and checkout a git branch and work on your code in the branch +2. Write and update **tests** (unit and perhaps even integration (e2e) tests) (If you do TDD/BDD, the order might be different.) +3. **Let users know** that things have changed or been added in the documents! This is often overlooked, but _critical_ +4. **Submit** your code as a _pull request_. +5. Maintainers will **review** your code. If there are no changes necessary, the PR will be merged. Otherwise, make the requested changes and repeat. + +## 1. Checkout a git branch + +Mermaid uses a [Git Flow](https://guides.github.com/introduction/flow/)–inspired approach to branching. + +Development is done in the `develop` branch. + +Once development is done we create a `release/vX.X.X` branch from `develop` for testing. + +Once the release happens we add a tag to the `release` branch and merge it with `master`. The live product and on-line documentation are what is in the `master` branch. + +**All new work should be based on the `develop` branch.** + +**When you are ready to do work, always, ALWAYS:** + +1. Make sure you have the most up-to-date version of the `develop` branch. (fetch or pull to update it) +2. Check out the `develop` branch +3. Create a new branch for your work. Please name the branch following our naming convention below. + +We use the following naming convention for branches: + +```txt + [feature | bug | chore | docs]/[issue number]_[short description using dashes ('-') or underscores ('_') instead of spaces] +``` + +You can always check current [configuration of labelling and branch prefixes](https://github.com/mermaid-js/mermaid/blob/develop/.github/pr-labeler.yml) + +- The first part is the **type** of change: a feature, bug, chore, or documentation change ('docs') +- followed by a _slash_ (which helps to group like types together in many git tools) +- followed by the **issue number** +- followed by an _underscore_ ('\_') +- followed by a short text description (but use dashes ('-') or underscores ('\_') instead of spaces) + +If your work is specific to a single diagram type, it is a good idea to put the diagram type at the start of the description. This will help us keep release notes organized: it will help us keep changes for a diagram type together. + +**Ex: A new feature described in issue 2945 that adds a new arrow type called 'florbs' to state diagrams** + +`feature/2945_state-diagram-new-arrow-florbs` + +**Ex: A bug described in issue 1123 that causes random ugly red text in multiple diagram types** +`bug/1123_fix_random_ugly_red_text` + +## 2. Write Tests + +Tests ensure that each function, module, or part of code does what it says it will do. This is critically +important when other changes are made to ensure that existing code is not broken (no regression). + +Just as important, the tests act as _specifications:_ they specify what the code does (or should do). +Whenever someone is new to a section of code, they should be able to read the tests to get a thorough understanding of what it does and why. + +If you are fixing a bug, you should add tests to ensure that your code has actually fixed the bug, to specify/describe what the code is doing, and to ensure the bug doesn't happen again. +(If there had been a test for the situation, the bug never would have happened in the first place.) +You may need to change existing tests if they were inaccurate. + +If you are adding a feature, you will definitely need to add tests. Depending on the size of your feature, you may need to add integration tests. + +### Unit Tests + +Unit tests are tests that test a single function or module. They are the easiest to write and the fastest to run. + +Unit tests are mandatory all code except the renderers. (The renderers are tested with integration tests.) + +We use [Vitest](https://vitest.dev) to run unit tests. + +You can use the following command to run the unit tests: + +```sh +pnpm test +``` + +When writing new tests, it's easier to have the tests automatically run as you make changes. You can do this by running the following command: + +```sh +pnpm test:watch +``` + +### Integration/End-to-End (e2e) tests + +These test the rendering and visual appearance of the diagrams. +This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks! + +To start working with the e2e tests: + +1. Run `pnpm dev` to start the dev server +2. Start **Cypress** by running `pnpm cypress:open`. + +The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress. + +When running in CI it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag it for review if it differs. + +This is what a rendering test looks like: + +```js +it('should render forks and joins', () => { + imgSnapshotTest( + ` + stateDiagram + 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 --> [*] + `, + { logLevel: 0 } + ); + cy.get('svg'); +}); +``` + +**_\[TODO - running the tests against what is expected in development. ]_** + +**_\[TODO - how to generate new screenshots]_** +.... + +## 3. Update Documentation + +If the users have no way to know that things have changed, then you haven't really _fixed_ anything for the users; you've just added to making Mermaid feel broken. +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 to users know that things have changed and added! +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 (v+)` + +We know it can sometimes be hard to code _and_ write user documentation. + +Our documentation is managed in `packages/mermaid/src/docs`. Details on how to edit is in the [Contributing Documentation](#contributing-documentation) section. + +Create another issue specifically for the documentation.\ +You will need to help with the PR, but definitely ask for help if you feel stuck. +When it feels hard to write stuff out, explaining it to someone and having that person ask you clarifying questions can often be 80% of the work! + +When in doubt, write up and submit what you can. It can be clarified and refined later. (With documentation, something is better than nothing!) + +## 4. Submit your pull request + +**\[TODO - PR titles should start with (fix | feat | ....)]** + +We make all changes via Pull Requests (PRs). As we have many Pull Requests from developers new to Mermaid, we have put in place a process wherein _knsv, Knut Sveidqvist_ is in charge of the final release process and the active maintainers are in charge of reviewing and merging most PRs. + +- PRs will be reviewed by active maintainers, who will provide feedback and request changes as needed. +- The maintainers will request a review from knsv, if necessary. +- Once the PR is approved, the maintainers will merge the PR into the `develop` branch. +- When a release is ready, the `release/x.x.x` branch will be created, extensively tested and knsv will be in charge of the release process. + +**Reminder: Pull Requests should be submitted to the develop branch.** diff --git a/docs/community/development.md b/docs/community/development.md index 58ca4670b..c9d8dab97 100644 --- a/docs/community/development.md +++ b/docs/community/development.md @@ -4,7 +4,11 @@ > > ## Please edit the corresponding file in [/packages/mermaid/src/docs/community/development.md](../../packages/mermaid/src/docs/community/development.md). -# Development and Contribution 🙌 +# Contributing to Mermaid + +> The following documentation describes how to work with Mermaid in your host environment. +> There's also a [Docker installation guide](../community/docker-development.md) +> if you prefer to work in a Docker environment. So you want to help? That's great! @@ -12,125 +16,76 @@ So you want to help? That's great! Here are a few things to get you started on the right path. -**The Docs Structure is dictated by [.vitepress/config.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/.vitepress/config.ts)**. +## Get the Source Code -**Note: Commits and Pull Requests should be directed to the develop branch.** +In GitHub, you first **fork** a repository when you are going to make changes and submit pull requests. -## Branching +Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with. -Mermaid uses a [Git Flow](https://guides.github.com/introduction/flow/)–inspired approach to branching. So development is done in the `develop` branch. +[Fork mermaid](https://github.com/mermaid-js/mermaid/fork) to start contributing to the main project and its documentation, or [search for other repositories](https://github.com/orgs/mermaid-js/repositories). -Once development is done we branch a `release` branch from `develop` for testing. +[Here is a GitHub document that gives an overview of the process.](https://docs.github.com/en/get-started/quickstart/fork-a-repo) -Once the release happens we merge the `release` branch with `master` and kill the `release` branch. +## Technical Requirements -This means that **you should branch off your pull request from develop** and direct all Pull Requests to it. +> The following documentation describes how to work with Mermaid in your host environment. +> There's also a [Docker installation guide](../community/docker-development.md) +> if you prefer to work in a Docker environment. -## Contributing Code +These are the tools we use for working with the code and documentation: -We make all changes via Pull Requests. As we have many Pull Requests from developers new to mermaid, we have put in place a process, wherein _knsv, Knut Sveidqvist_ is the primary reviewer of changes and merging pull requests. The process is as follows: +- [volta](https://volta.sh/) to manage node versions. +- [Node.js](https://nodejs.org/en/). `volta install node` +- [pnpm](https://pnpm.io/) package manager. `volta install pnpm` +- [npx](https://docs.npmjs.com/cli/v8/commands/npx) the packaged executor in npm. This is needed [to install pnpm.](#install-packages) -- Large changes reviewed by knsv or other developer asked to review by knsv -- Smaller, low-risk changes like dependencies, documentation, etc. can be merged by active collaborators -- Documentation (we encourage updates to the `/packages/mermaid/src/docs` folder; you can submit them via direct commits) +Follow the setup steps below to install them and start the development. -When you commit code, create a branch with the following naming convention: +## Setup and Launch -Start with the type, such as **feature** or **bug**, followed by the issue number for reference, and a text that describes the issue. +### Switch to project -**One example:** +Once you have cloned the repository onto your development machine, change into the `mermaid` project folder (the top level directory of the mermaid project repository) -`feature/945_state_diagrams` - -**Another example:** - -`bug/123_nasty_bug_branch` - -## Contributing to Documentation - -If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature? - -The docs are located in the `src/docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via **[.vitepress/config.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/.vitepress/config.ts)**. - -> **All the documents displayed in the GitHub.io page are listed in [.vitepress/config.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/.vitepress/config.ts)**. - -The contents of are based on the docs from the `master` branch. Updates committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released. - -## How to Contribute to Documentation - -We are a little less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator. - -The documentation is located in the `src/docs` directory and organized according to relevant subfolder. - -The `docs` folder will be automatically generated when committing to `src/docs` and should not be edited manually. - -We encourage contributions to the documentation at [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s) - -### Add Unit Tests for Parsing - -This is important so that, if someone that does not know about this great feature suggests a change to the grammar, they get notified early on when that change breaks the parser. Another important aspect is that, without proper parsing, tests refactoring is pretty much impossible. - -### Add E2E Tests - -This tests the rendering and visual appearance of the diagrams. This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks! - -To start working with the e2e tests: - -1. Run `pnpm run dev` to start the dev server -2. Start **Cypress** by running `pnpm exec cypress open` in the **mermaid** folder. - -The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress. - -When running in CI it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag it for review if it differs. - -This is what a rendering test looks like: - -```js -it('should render forks and joins', () => { - imgSnapshotTest( - ` - stateDiagram - 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 --> [*] - `, - { logLevel: 0 } - ); - cy.get('svg'); -}); +```bash +cd mermaid ``` -### Any Questions or Suggestions? +### Install packages -After logging in at [GitHub.com](https://www.github.com), open or append to an issue [using the GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Documentation%22). +Run `npx pnpm install`. You will need `npx` for this because volta doesn't support it yet. -### How to Contribute a Suggestion +```bash +npx pnpm install # npx is required for first install +``` -Markdown is used to format the text, for more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). +### Launch -To edit Docs on your computer: +```bash +npx pnpm run dev +``` -1. Find the Markdown file (.md) to edit in the [packages/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs) directory in the `develop` branch. -2. Create a fork of the develop branch. -3. Make changes or add new documentation. -4. Commit changes to your fork and push it to GitHub. -5. Create a Pull Request of your fork. +Now you are ready to make your changes! Edit whichever files in `src` as required. -To edit Docs on GitHub: +Open in your browser, after starting the dev server. +There is a list of demos that can be used to see and test your changes. -1. Login to [GitHub.com](https://www.github.com). -2. Navigate to [packages/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs). -3. To edit a file, click the pencil icon at the top-right of the file contents panel. -4. Describe what you changed in the **Propose file change** section, located at the bottom of the page. -5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch). -6. Create a Pull Request of your newly forked branch by clicking the green **Create Pull Request** button. +If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy. + +That will be served at . +After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!) + +## Verify Everything is Working + +You can run the `test` script to verify that pnpm is working _and_ that the repository has been cloned correctly: + +```bash +pnpm test +``` + +The `test` script and others are in the top-level `package.json` file. + +All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.) ## Last Words diff --git a/docs/community/docker-development.md b/docs/community/docker-development.md new file mode 100644 index 000000000..9df0c8d59 --- /dev/null +++ b/docs/community/docker-development.md @@ -0,0 +1,109 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/community/docker-development.md](../../packages/mermaid/src/docs/community/docker-development.md). + +# Contributing to Mermaid via Docker + +> The following documentation describes how to work with Mermaid in a Docker environment. +> There's also a [host installation guide](../community/development.md) +> if you prefer to work without a Docker environment. + +So you want to help? That's great! + +![Image of happy people jumping with excitement](https://media.giphy.com/media/BlVnrxJgTGsUw/giphy.gif) + +Here are a few things to get you started on the right path. + +## Get the Source Code + +In GitHub, you first **fork** a repository when you are going to make changes and submit pull requests. + +Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with. + +[Fork mermaid](https://github.com/mermaid-js/mermaid/fork) to start contributing to the main project and its documentation, or [search for other repositories](https://github.com/orgs/mermaid-js/repositories). + +[Here is a GitHub document that gives an overview of the process.](https://docs.github.com/en/get-started/quickstart/fork-a-repo) + +## Technical Requirements + +> The following documentation describes how to work with Mermaid in a Docker environment. +> There's also a [host installation guide](../community/development.md) +> if you prefer to work without a Docker environment. + +[Install Docker](https://docs.docker.com/engine/install/). And that is pretty much all you need. + +Optionally, to run GUI (Cypress) within Docker you will also need an X11 server installed. +You might already have it installed, so check this by running: + +```bash +echo $DISPLAY +``` + +If the `$DISPLAY` variable is not empty, then an X11 server is running. Otherwise you may need to install one. + +## Setup and Launch + +### Switch to project + +Once you have cloned the repository onto your development machine, change into the `mermaid` project folder (the top level directory of the mermaid project repository) + +```bash +cd mermaid +``` + +### Make `./run` executable + +For development using Docker there is a self-documented `run` bash script, which provides convenient aliases for `docker compose` commands. + +Ensure `./run` script is executable: + +```bash +chmod +x run +``` + +> **💡 Tip** +> To get detailed help simply type `./run` or `./run help`. +> +> It also has short _Development quick start guide_ embedded. + +### Install packages + +```bash +./run pnpm install # Install packages +``` + +### Launch + +```bash +./run dev +``` + +Now you are ready to make your changes! Edit whichever files in `src` as required. + +Open in your browser, after starting the dev server. +There is a list of demos that can be used to see and test your changes. + +If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy. + +That will be served at . +After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!) + +## Verify Everything is Working + +```bash +./run pnpm test +``` + +The `test` script and others are in the top-level `package.json` file. + +All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.) + +## Last Words + +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. + +[Join our Slack community if you want closer contact!](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) + +![Image of superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif) diff --git a/docs/community/documentation.md b/docs/community/documentation.md new file mode 100644 index 000000000..67d35d395 --- /dev/null +++ b/docs/community/documentation.md @@ -0,0 +1,105 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/community/documentation.md](../../packages/mermaid/src/docs/community/documentation.md). + +# Contributing Documentation + +**_\[TODO: This section is still a WIP. It still needs MAJOR revision.]_** + +If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature? + +The docs are located in the `packages/mermaid/src/docs` folder and are written in Markdown. Just pick the right section and start typing. + +The contents of [mermaid.js.org](https://mermaid.js.org/) are based on the docs from the `master` branch. +Updates committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid.js.org/) once published. + +## How to Contribute to Documentation + +We are a little less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator. + +The documentation is located in the `packages/mermaid/src/docs` directory and organized according to relevant subfolder. + +The `docs` folder will be automatically generated when committing to `packages/mermaid/src/docs` and **should not** be edited manually. + +```mermaid-example +flowchart LR + classDef default fill:#fff,color:black,stroke:black + + source["files in /packages/mermaid/src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"] + +``` + +```mermaid +flowchart LR + classDef default fill:#fff,color:black,stroke:black + + source["files in /packages/mermaid/src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"] + +``` + +You can use `note`, `tip`, `warning` and `danger` in triple backticks to add a note, tip, warning or danger box. +Do not use vitepress specific markdown syntax `::: warning` as it will not be processed correctly. + +````markdown +```note +Note content +``` + +```tip +Tip content +``` + +```warning +Warning content +``` + +```danger +Danger content +``` +```` + +> **Note** +> If the change is _only_ to the documentation, you can get your changes published to the site quicker by making a PR to the `master` branch. In that case, your branch should be based on master, not develop. + +We encourage contributions to the documentation at [packages/mermaid/src/docs in the _develop_ branch](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs). + +**_DO NOT CHANGE FILES IN `/docs`_** + +## The official documentation site + +**[The mermaid documentation site](https://mermaid.js.org/) is powered by [Vitepress](https://vitepress.vuejs.org/).** + +To run the documentation site locally: + +1. Run `pnpm --filter mermaid run docs:dev` to start the dev server. (Or `pnpm docs:dev` inside the `packages/mermaid` directory.) +2. Open in your browser. + +Markdown is used to format the text, for more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). + +To edit Docs on your computer: + +_\[TODO: need to keep this in sync with [check out a git branch in Contributing Code above](#1-checkout-a-git-branch) ]_ + +1. Create a fork of the develop branch to work on. +2. Find the Markdown file (.md) to edit in the `packages/mermaid/src/docs` directory. +3. Make changes or add new documentation. +4. Commit changes to your branch and push it to GitHub (which should create a new branch). +5. Create a Pull Request from the branch of your fork. + +To edit Docs on GitHub: + +1. Login to [GitHub.com](https://www.github.com). +2. Navigate to [packages/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs) in the mermaid-js repository. +3. To edit a file, click the pencil icon at the top-right of the file contents panel. +4. Describe what you changed in the **Propose file change** section, located at the bottom of the page. +5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch). +6. Visit the Actions tab in Github, `https://github.com//mermaid/actions` and enable the actions for your fork. This will ensure that the documentation is built and updated in your fork. +7. Create a Pull Request of your newly forked branch by clicking the green **Create Pull Request** button. + +## Documentation organization: Sidebar 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.** + +The sidebar navigation is defined in [the vitepress configuration file config.ts](../.vitepress/config.ts). diff --git a/docs/community/n00b-overview.md b/docs/community/n00b-overview.md deleted file mode 100644 index e0056d912..000000000 --- a/docs/community/n00b-overview.md +++ /dev/null @@ -1,74 +0,0 @@ -> **Warning** -> -> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. -> -> ## Please edit the corresponding file in [/packages/mermaid/src/docs/community/n00b-overview.md](../../packages/mermaid/src/docs/community/n00b-overview.md). - -# Overview for Beginners - -**Explaining with a Diagram** - -A picture is worth a thousand words, a good diagram is undoubtedly worth more. They make understanding easier. - -## Creating and Maintaining Diagrams - -Anyone who has used Visio, or (God Forbid) Excel to make a Gantt Chart, knows how hard it is to create, edit and maintain good visualizations. - -Diagrams/Charts are significant but also become obsolete/inaccurate very fast. This catch-22 hobbles the productivity of teams. - -# Doc Rot in Diagrams - -Doc-Rot kills diagrams as quickly as it does text, but it takes hours in a desktop application to produce a diagram. - -Mermaid seeks to change using markdown-inspired syntax. The process is a quicker, less complicated, and more convenient way of going from concept to visualization. - -It is a relatively straightforward solution to a significant hurdle with the software teams. - -# Definition of Terms/ Dictionary - -**Mermaid text definitions can be saved for later reuse and editing.** - -> These are the Mermaid diagram definitions inside `
` tags, with the `class=mermaid`. - -```html -
-    graph TD
-    A[Client] --> B[Load Balancer]
-    B --> C[Server01]
-    B --> D[Server02]
-
-``` - -**render** - -> This is the core function of the Mermaid API. It reads all the `Mermaid Definitions` inside `div` tags and returns an SVG file, based on the definition. - -**Nodes** - -> These are the boxes that contain text or otherwise discrete pieces of each diagram, separated generally by arrows, except for Gantt Charts and User Journey Diagrams. They will be referred often in the instructions. Read for Diagram Specific [Syntax](../intro/n00b-syntaxReference.md) - -## Advantages of using Mermaid - -- Ease to generate, modify and render diagrams when you make them. -- The number of integrations and plugins it has. -- You can add it to your or companies website. -- Diagrams can be created through comments like this in a script: - -## The catch-22 of Diagrams and Charts: - -**Diagramming and charting is a large waste of developer's time, but not having diagrams ruins productivity.** - -Mermaid solves this by reducing the time and effort required to create diagrams and charts. - -Because, the text base for the diagrams allows it to be updated easily. Also, it can be made part of production scripts (and other pieces of code). So less time is spent on documenting, as a separate task. - -## Catching up with Development - -Being based on markdown, Mermaid can be used, not only by accomplished front-end developers, but by most computer savvy people to render diagrams, at much faster speeds. -In fact one can pick up the syntax for it quite easily from the examples given and there are many tutorials available in the internet. - -## Mermaid is for everyone. - -Video [Tutorials](https://mermaid-js.github.io/mermaid/#/../config/Tutorials) are also available for the mermaid [live editor](https://mermaid.live/). - -Alternatively you can use Mermaid [Plug-Ins](https://mermaid-js.github.io/mermaid/#/./integrations), with tools you already use, like Google Docs. diff --git a/docs/community/newDiagram.md b/docs/community/newDiagram.md index bb7e2a961..b90d192b2 100644 --- a/docs/community/newDiagram.md +++ b/docs/community/newDiagram.md @@ -10,7 +10,7 @@ #### Grammar -This would be to define a jison grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2. +This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2. For instance: @@ -19,7 +19,7 @@ For instance: #### Store data found during parsing -There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call a object provided to the parser by the user of the parser. This object can be called during parsing for storing data. +There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call an object provided to the parser by the user of the parser. This object can be called during parsing for storing data. ```jison statement @@ -35,7 +35,7 @@ In the extract of the grammar above, it is defined that a call to the setTitle m > **Note** > Make sure that the `parseError` function for the parser is defined and calling `mermaid.parseError`. This way a common way of detecting parse errors is provided for the end-user. -For more info look in the example diagram type: +For more info look at the example diagram type: The `yy` object has the following function: @@ -54,15 +54,15 @@ parser.yy = db; ### Step 2: Rendering -Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather then the flowchart renderer as this is a more generic example. +Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather than the flowchart renderer as this is a more generic example. Place the renderer in the diagram folder. ### Step 3: Detection of the new diagram type -The second thing to do is to add the capability to detect the new diagram to type to the detectType in utils.js. The detection should return a key for the new diagram type. +The second thing to do is to add the capability to detect the new diagram to type to the detectType in `diagram-api/detectType.ts`. The detection should return a key for the new diagram type. [This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type. -For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader +For example, if your new diagram uses a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram. Note that the diagram type key does not have to be the same as the diagram keyword chosen for the [grammar](#grammar), but it is helpful if they are the same. @@ -122,54 +122,7 @@ There are a few features that are common between the different types of diagrams - Themes, there is a common way to modify the styling of diagrams in Mermaid. - Comments should follow mermaid standards -Here some pointers on how to handle these different areas. - -#### [Directives](../config/directives.md) - -Here is example handling from flowcharts: -Jison: - -```jison -/* lexical grammar */ -%lex -%x open_directive -%x type_directive -%x arg_directive -%x close_directive - -\%\%\{ { this.begin('open_directive'); return 'open_directive'; } -((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } -":" { this.popState(); this.begin('arg_directive'); return ':'; } -\}\%\% { this.popState(); this.popState(); return 'close_directive'; } -((?:(?!\}\%\%).|\n)*) return 'arg_directive'; - -/* language grammar */ - -/* ... */ - -directive - : openDirective typeDirective closeDirective separator - | openDirective typeDirective ':' argDirective closeDirective separator - ; - -openDirective - : open_directive { yy.parseDirective('%%{', 'open_directive'); } - ; - -typeDirective - : type_directive { yy.parseDirective($1, 'type_directive'); } - ; - -argDirective - : arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); } - ; - -closeDirective - : close_directive { yy.parseDirective('}%%', 'close_directive', 'flowchart'); } - ; -``` - -It is probably a good idea to keep the handling similar to this in your new diagram. The parseDirective function is provided by the mermaidAPI. +Here are some pointers on how to handle these different areas. ## Accessibility @@ -187,9 +140,9 @@ See [the definition of aria-roledescription](https://www.w3.org/TR/wai-aria-1.1/ ### accessible title and description -The syntax for accessible titles and descriptions is described in [the Accessibility documenation section.](../config/accessibility.md) +The syntax for accessible titles and descriptions is described in [the Accessibility documentation section.](../config/accessibility.md) -In a similar way to the directives, the jison syntax are quite similar between the diagrams. +As a design goal, the jison syntax should be similar between the diagrams. ```jison diff --git a/docs/community/questions-and-suggestions.md b/docs/community/questions-and-suggestions.md new file mode 100644 index 000000000..23d6de50f --- /dev/null +++ b/docs/community/questions-and-suggestions.md @@ -0,0 +1,26 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/community/questions-and-suggestions.md](../../packages/mermaid/src/docs/community/questions-and-suggestions.md). + +# Questions or Suggestions? + +**_\[TODO: This section is still a WIP. It still needs MAJOR revision.]_** + +## First search to see if someone has already asked (and hopefully been answered) or suggested the same thing. + +- Search in Discussions +- Search in open Issues +- Search in closed Issues + +If you find an open issue or discussion thread that is similar to your question but isn't answered, you can let us know that you are also interested in it. +Use the GitHub reactions to add a thumbs-up to the issue or discussion thread. + +This helps the team know the relative interest in something and helps them set priorities and assignments. + +Feel free to add to the discussion on the issue or topic. + +If you can't find anything that already addresses your question or suggestion, _open a new issue:_ + +Log in to [GitHub.com](https://www.github.com), open or append to an issue [using the GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Documentation%22). diff --git a/docs/config/Tutorials.md b/docs/config/Tutorials.md index 7dda89801..f3bad9ade 100644 --- a/docs/config/Tutorials.md +++ b/docs/config/Tutorials.md @@ -6,7 +6,7 @@ # Tutorials -This is list of publicly available Tutorials for using Mermaid.JS . This is intended as a basic introduction for the use of the Live Editor for generating diagrams, and deploying Mermaid.JS through HTML. +This is a list of publicly available Tutorials for using Mermaid.JS and is intended as a basic introduction for the use of the Live Editor for generating diagrams, and deploying Mermaid.JS through HTML. **Note that these tutorials might display an older interface, but the usage of the live-editor will largely be the same.** @@ -26,9 +26,13 @@ The definitions that can be generated the Live-Editor are also backwards-compati [Eddie Jaoude: Can you code your diagrams?](https://www.youtube.com/watch?v=9HZzKkAqrX8) +## Mermaid with OpenAI + +[Elle Neal: Mind Mapping with AI: An Accessible Approach for Neurodiverse Learners Tutorial:](https://medium.com/@elle.neal_71064/mind-mapping-with-ai-an-accessible-approach-for-neurodiverse-learners-1a74767359ff), [Demo:](https://databutton.com/v/jk9vrghc) + ## Mermaid with HTML -Examples are provided in [Getting Started](../intro/n00b-gettingStarted.md) +Examples are provided in [Getting Started](../intro/getting-started.md) **CodePen Examples:** @@ -58,10 +62,10 @@ from IPython.display import Image, display import matplotlib.pyplot as plt def mm(graph): - graphbytes = graph.encode("ascii") - base64_bytes = base64.b64encode(graphbytes) - base64_string = base64_bytes.decode("ascii") - display(Image(url="https://mermaid.ink/img/" + base64_string)) + graphbytes = graph.encode("utf8") + base64_bytes = base64.b64encode(graphbytes) + base64_string = base64_bytes.decode("ascii") + display(Image(url="https://mermaid.ink/img/" + base64_string)) mm(""" graph LR; diff --git a/docs/config/n00b-advanced.md b/docs/config/advanced.md similarity index 79% rename from docs/config/n00b-advanced.md rename to docs/config/advanced.md index 39c20d632..28c0ca724 100644 --- a/docs/config/n00b-advanced.md +++ b/docs/config/advanced.md @@ -2,9 +2,9 @@ > > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. > -> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/n00b-advanced.md](../../packages/mermaid/src/docs/config/n00b-advanced.md). +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/advanced.md](../../packages/mermaid/src/docs/config/advanced.md). -# Advanced n00b mermaid (Coming soon..) +# Advanced mermaid (Coming soon..) ## splitting mermaid code from html diff --git a/docs/config/configuration.md b/docs/config/configuration.md index c7b780143..1e85427ea 100644 --- a/docs/config/configuration.md +++ b/docs/config/configuration.md @@ -10,10 +10,41 @@ When mermaid starts, configuration is extracted to determine a configuration to - The default configuration - Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**. -- Directives - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config. +- Frontmatter (v\+) - diagram authors can update select configuration parameters in the frontmatter of the diagram. These are applied to the render config. +- Directives (Deprecated by Frontmatter) - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config. **The render config** is configuration that is used when rendering by applying these configurations. +## Frontmatter config + +The entire mermaid configuration (except the secure configs) can be overridden by the diagram author in the frontmatter of the diagram. The frontmatter is a YAML block at the top of the diagram. + +```mermaid-example +--- +title: Hello Title +config: + theme: base + themeVariables: + primaryColor: "#00ff00" +--- +flowchart + Hello --> World + +``` + +```mermaid +--- +title: Hello Title +config: + theme: base + themeVariables: + primaryColor: "#00ff00" +--- +flowchart + Hello --> World + +``` + ## Theme configuration ## Starting mermaid diff --git a/docs/config/directives.md b/docs/config/directives.md index e845596ad..943d51217 100644 --- a/docs/config/directives.md +++ b/docs/config/directives.md @@ -6,13 +6,16 @@ # Directives +> **Warning** +> Directives are deprecated from v\. Please use the `config` key in frontmatter to pass configuration. See [Configuration](./configuration.md) for more details. + ## Directives -Directives gives a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration. +Directives give a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration. -The significance of having directives is that you have them available while writing the diagram, and can modify the default global and diagram specific configurations. So, directives are applied on top of the default configurations. The beauty of directives is that you can use them to alter configuration settings for a specific diagram, i.e. at an individual level. +The significance of having directives is that you have them available while writing the diagram, and can modify the default global and diagram-specific configurations. So, directives are applied on top of the default configuration. The beauty of directives is that you can use them to alter configuration settings for a specific diagram, i.e. at an individual level. -While directives allow you to change most of the default configuration settings, there are some that are not available, that too for security reasons. Also, you do have the _option to define the set of configurations_ that you would allow to be available to the diagram author for overriding with help of directives. +While directives allow you to change most of the default configuration settings, there are some that are not available, for security reasons. Also, you have the _option to define the set of configurations_ that you wish to allow diagram authors to override with directives. ## Types of Directives options @@ -20,29 +23,29 @@ Mermaid basically supports two types of configuration options to be overridden b 1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are: -- theme -- fontFamily -- logLevel -- securityLevel -- startOnLoad -- secure + - theme + - fontFamily + - logLevel + - securityLevel + - startOnLoad + - secure -2. _Diagram specific configurations_ : These are the configurations that are available and applied to a specific diagram. For each diagram there are specific configuration that will alter how that particular diagram looks and behaves. - For example, `mirrorActors` is a configuration that is specific to the `SequenceDiagram` and alter whether the actors are mirrored or not. So this config is available only for the `SequenceDiagram` type. +2. _Diagram-specific configurations_ : These are the configurations that are available and applied to a specific diagram. For each diagram there are specific configuration that will alter how that particular diagram looks and behaves. + For example, `mirrorActors` is a configuration that is specific to the `SequenceDiagram` and alters whether the actors are mirrored or not. So this config is available only for the `SequenceDiagram` type. -**NOTE:** These options listed here are not all the configuration options. To get hold of all the configuration options, please refer to the [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. +**NOTE:** Not all configuration options are listed here. To get hold of all the configuration options, please refer to the [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. > **Note** -> We plan to publish a complete list of top-level configurations & all the diagram specific configurations, with their possible values in the docs soon. +> We plan to publish a complete list of top-level configurations & diagram-specific configurations with their possible values in the docs soon. ## Declaring directives Now that we have defined the types of configurations that are available, we can learn how to declare directives. -A directive always starts and end `%%` sign with directive text in between, like `%% {directive_text} %%`. +A directive always starts and ends with `%%` signs with directive text in between, like `%% {directive_text} %%`. Here the structure of a directive text is like a nested key-value pair map or a JSON object with root being _init_. Where all the general configurations are defined in the top level, and all the diagram specific configurations are defined one level deeper with diagram type as key/root for that section. -Following code snippet shows the structure of a directive: +The following code snippet shows the structure of a directive: %%{ init: { @@ -61,14 +64,14 @@ Following code snippet shows the structure of a directive: You can also define the directives in a single line, like this: - %%{init: { **insert argument here**}}%% + %%{init: { **insert configuration options here** } }%% For example, the following code snippet: %%{init: { "sequence": { "mirrorActors":false }}}%% **Notes:** -The json object that is passed as {**argument** } must be valid key value pairs and encased in quotation marks or it will be ignored. +The JSON object that is passed as {**argument**} must be valid key value pairs and encased in quotation marks or it will be ignored. Valid Key Value pairs can be found in config. Example with a simple graph: @@ -87,7 +90,7 @@ A-->B Here the directive declaration will set the `logLevel` to `debug` and the `theme` to `dark` for a rendered mermaid diagram, changing the appearance of the diagram itself. -Note: You can use 'init' or 'initialize' as both acceptable as init directives. Also note that `%%init%%` and `%%initialize%%` directives will be grouped together after they are parsed. This means: +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-example %%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% @@ -101,7 +104,7 @@ Note: You can use 'init' or 'initialize' as both acceptable as init directives. ... ``` -parsing the above generates a single `%%init%%` JSON object below, combining the two directives and carrying over the last value given for `loglevel`: +For example, parsing the above generates a single `%%init%%` JSON object below, combining the two directives and carrying over the last value given for `loglevel`: ```json { @@ -115,16 +118,15 @@ This will then be sent to `mermaid.initialize(...)` for rendering. ## Directive Examples -More directive examples for diagram specific configuration overrides -Now that the concept of directives has been explained, Let us see some more examples for directives usage: +Now that the concept of directives has been explained, let us see some more examples of directive usage: -### Changing Theme via directive +### Changing theme via directive -The following code snippet changes theme to forest: +The following code snippet changes `theme` to `forest`: `%%{init: { "theme": "forest" } }%%` -Possible themes value are: `default`,`base`, `dark`, `forest` and `neutral`. +Possible theme values are: `default`, `base`, `dark`, `forest` and `neutral`. Default Value is `default`. Example: @@ -155,7 +157,7 @@ A --> C[End] ### Changing fontFamily via directive -The following code snippet changes fontFamily to rebuchet MS, Verdana, Arial, Sans-Serif: +The following code snippet changes fontFamily to Trebuchet MS, Verdana, Arial, Sans-Serif: `%%{init: { "fontFamily": "Trebuchet MS, Verdana, Arial, Sans-Serif" } }%%` @@ -187,11 +189,11 @@ A --> C[End] ### Changing logLevel via directive -The following code snippet changes logLevel to 2: +The following code snippet changes `logLevel` to `2`: `%%{init: { "logLevel": 2 } }%%` -Possible logLevel values are: +Possible `logLevel` values are: - `1` for _debug_, - `2` for _info_ @@ -234,14 +236,14 @@ Some common flowchart configurations are: - _diagramPadding_: number - _useMaxWidth_: number -For complete list of flowchart configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. -_Soon we plan to publish a complete list all diagram specific configurations updated in the docs_ +For a complete list of flowchart configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. +_Soon we plan to publish a complete list of all diagram-specific configurations updated in the docs._ The following code snippet changes flowchart config: `%%{init: { "flowchart": { "htmlLabels": true, "curve": "linear" } } }%%` -Here were are overriding only the flowchart config, and not the general config, where HtmlLabels is set to true and curve is set to linear. +Here we are overriding only the flowchart config, and not the general config, setting `htmlLabels` to `true` and `curve` to `linear`. ```mermaid-example %%{init: { "flowchart": { "htmlLabels": true, "curve": "linear" } } }%% @@ -267,7 +269,7 @@ A --> C[End] ### Changing Sequence diagram config via directive -Some common sequence configurations are: +Some common sequence diagram configurations are: - _width_: number - _height_: number @@ -278,8 +280,8 @@ Some common sequence configurations are: - _showSequenceNumbers_: boolean - _wrap_: boolean -For complete list of sequence diagram configurations, see _defaultConfig.ts_ in the source code. -_Soon we plan to publish a complete list all diagram specific configurations updated in the docs_ +For a complete list of sequence diagram configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. +_Soon we plan to publish a complete list of all diagram-specific configurations updated in the docs._ So, `wrap` by default has a value of `false` for sequence diagrams. @@ -289,7 +291,7 @@ Let us see an example: sequenceDiagram Alice->Bob: Hello Bob, how are you? -Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion? +Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion? Alice->Bob: Good. Bob->Alice: Cool ``` @@ -298,7 +300,7 @@ Bob->Alice: Cool sequenceDiagram Alice->Bob: Hello Bob, how are you? -Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion? +Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion? Alice->Bob: Good. Bob->Alice: Cool ``` @@ -309,13 +311,13 @@ The following code snippet changes sequence diagram config for `wrap` to `true`: `%%{init: { "sequence": { "wrap": true} } }%%` -Using in the diagram above, the wrap will be enabled. +By applying that snippet to the diagram above, `wrap` will be enabled: ```mermaid-example %%{init: { "sequence": { "wrap": true, "width":300 } } }%% sequenceDiagram Alice->Bob: Hello Bob, how are you? -Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion? +Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion? Alice->Bob: Good. Bob->Alice: Cool ``` @@ -324,7 +326,7 @@ Bob->Alice: Cool %%{init: { "sequence": { "wrap": true, "width":300 } } }%% sequenceDiagram Alice->Bob: Hello Bob, how are you? -Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion? +Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion? Alice->Bob: Good. Bob->Alice: Cool ``` diff --git a/docs/config/setup/interfaces/mermaidAPI.ParseOptions.md b/docs/config/setup/interfaces/mermaidAPI.ParseOptions.md index 93708863c..2082a081e 100644 --- a/docs/config/setup/interfaces/mermaidAPI.ParseOptions.md +++ b/docs/config/setup/interfaces/mermaidAPI.ParseOptions.md @@ -16,4 +16,4 @@ #### Defined in -[mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70) +[mermaidAPI.ts:78](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L78) diff --git a/docs/config/setup/interfaces/mermaidAPI.RenderResult.md b/docs/config/setup/interfaces/mermaidAPI.RenderResult.md index de4f763a0..f84a51b87 100644 --- a/docs/config/setup/interfaces/mermaidAPI.RenderResult.md +++ b/docs/config/setup/interfaces/mermaidAPI.RenderResult.md @@ -8,41 +8,6 @@ [mermaidAPI](../modules/mermaidAPI.md).RenderResult -Function that renders an svg with a graph from a chart definition. Usage example below. - -```javascript -mermaidAPI.initialize({ - startOnLoad: true, -}); -$(function () { - const graphDefinition = 'graph TB\na-->b'; - const cb = function (svgGraph) { - console.log(svgGraph); - }; - mermaidAPI.render('id1', graphDefinition, cb); -}); -``` - -**`Param`** - -The id for the SVG element (the element to be rendered) - -**`Param`** - -The text for the graph definition - -**`Param`** - -Callback which is called after rendering is finished with the svg code as in param. - -**`Param`** - -HTML element where the svg will be inserted. (Is usually element with the .mermaid class) -If no svgContainingElement is provided then the SVG element will be appended to the body. -Selector to element in which a div with the graph temporarily will be -inserted. If one is provided a hidden div will be inserted in the body of the page instead. The -element will be removed when rendering is completed. - ## Properties ### bindFunctions @@ -53,6 +18,15 @@ element will be removed when rendering is completed. ▸ (`element`): `void` +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. +``` + ##### Parameters | Name | Type | @@ -65,7 +39,7 @@ element will be removed when rendering is completed. #### Defined in -[mermaidAPI.ts:384](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L384) +[mermaidAPI.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L98) --- @@ -73,6 +47,8 @@ element will be removed when rendering is completed. • **svg**: `string` +The svg code for the rendered graph. + #### Defined in -[mermaidAPI.ts:383](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L383) +[mermaidAPI.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L88) diff --git a/docs/config/setup/modules/config.md b/docs/config/setup/modules/config.md index 8381dc8c7..f1de64e2d 100644 --- a/docs/config/setup/modules/config.md +++ b/docs/config/setup/modules/config.md @@ -14,7 +14,7 @@ #### Defined in -[config.ts:7](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L7) +[config.ts:8](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L8) ## Functions @@ -26,9 +26,9 @@ Pushes in a directive to the configuration #### Parameters -| Name | Type | Description | -| :---------- | :---- | :----------------------- | -| `directive` | `any` | The directive to push in | +| Name | Type | Description | +| :---------- | :-------------- | :----------------------- | +| `directive` | `MermaidConfig` | The directive to push in | #### Returns @@ -36,7 +36,7 @@ Pushes in a directive to the configuration #### Defined in -[config.ts:191](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L191) +[config.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L188) --- @@ -60,7 +60,7 @@ The currentConfig #### Defined in -[config.ts:137](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L137) +[config.ts:131](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L131) --- @@ -118,7 +118,7 @@ The siteConfig #### Defined in -[config.ts:223](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L223) +[config.ts:218](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L218) --- @@ -147,7 +147,7 @@ options in-place #### Defined in -[config.ts:152](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L152) +[config.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L146) --- @@ -242,10 +242,10 @@ The new siteConfig #### Parameters -| Name | Type | -| :------------ | :-------------- | -| `siteCfg` | `MermaidConfig` | -| `_directives` | `any`\[] | +| Name | Type | +| :------------ | :----------------- | +| `siteCfg` | `MermaidConfig` | +| `_directives` | `MermaidConfig`\[] | #### Returns @@ -253,7 +253,7 @@ The new siteConfig #### Defined in -[config.ts:14](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L14) +[config.ts:15](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L15) --- diff --git a/docs/config/setup/modules/defaultConfig.md b/docs/config/setup/modules/defaultConfig.md index 302bd51e1..effaec7b1 100644 --- a/docs/config/setup/modules/defaultConfig.md +++ b/docs/config/setup/modules/defaultConfig.md @@ -10,47 +10,24 @@ ### configKeys -• `Const` **configKeys**: `string`\[] +• `Const` **configKeys**: `Set`<`string`> #### Defined in -[defaultConfig.ts:2084](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L2084) +[defaultConfig.ts:268](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L268) --- ### default -• `Const` **default**: `Partial`<`MermaidConfig`> +• `Const` **default**: `RequiredDeep`<`MermaidConfig`> -**Configuration methods in Mermaid version 8.6.0 have been updated, to learn more\[[click -here](8.6.0_docs.md)].** +Default mermaid configuration options. -## **What follows are config instructions for older versions** - -These are the default options which can be overridden with the initialization call like so: - -**Example 1:** - -```js -mermaid.initialize({ flowchart: { htmlLabels: false } }); -``` - -**Example 2:** - -```html - -``` - -A summary of all options and their defaults is found [here](#mermaidapi-configuration-defaults). -A description of each option follows below. +Please see the Mermaid config JSON Schema for the default JSON values. +Non-JSON JS default values are listed in this file, e.g. functions, or +`undefined` (explicitly set so that `configKeys` finds them). #### Defined in -[defaultConfig.ts:33](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L33) +[defaultConfig.ts:18](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L18) diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index aa0885707..d5d4a1cbc 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -25,13 +25,13 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi) #### Defined in -[mermaidAPI.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L75) +[mermaidAPI.ts:82](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L82) ## Variables ### mermaidAPI -• `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<`boolean` | `void`> ; `parseDirective`: (`p`: `any`, `statement`: `string`, `context`: `string`, `type`: `string`) => `void` ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }> +• `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<`boolean`> ; `parseDirective`: (`p`: `any`, `statement`: `string`, `context`: `string`, `type`: `string`) => `void` ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }> ## mermaidAPI configuration defaults @@ -88,6 +88,7 @@ const config = { numberSectionStyles: 4, axisFormat: '%Y-%m-%d', topAxis: false, + displayMode: '', }, }; mermaid.initialize(config); @@ -95,7 +96,7 @@ mermaid.initialize(config); #### Defined in -[mermaidAPI.ts:668](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L668) +[mermaidAPI.ts:673](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L673) ## Functions @@ -126,7 +127,7 @@ Return the last node appended #### Defined in -[mermaidAPI.ts:291](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L291) +[mermaidAPI.ts:310](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L310) --- @@ -152,7 +153,7 @@ the cleaned up svgCode #### Defined in -[mermaidAPI.ts:242](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L242) +[mermaidAPI.ts:256](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L256) --- @@ -178,7 +179,7 @@ the string with all the user styles #### Defined in -[mermaidAPI.ts:171](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L171) +[mermaidAPI.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L185) --- @@ -201,7 +202,7 @@ the string with all the user styles #### Defined in -[mermaidAPI.ts:219](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L219) +[mermaidAPI.ts:233](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L233) --- @@ -228,7 +229,7 @@ with an enclosing block that has each of the cssClasses followed by !important; #### Defined in -[mermaidAPI.ts:155](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L155) +[mermaidAPI.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L169) --- @@ -248,7 +249,7 @@ with an enclosing block that has each of the cssClasses followed by !important; #### Defined in -[mermaidAPI.ts:135](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L135) +[mermaidAPI.ts:155](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L155) --- @@ -268,7 +269,7 @@ with an enclosing block that has each of the cssClasses followed by !important; #### Defined in -[mermaidAPI.ts:106](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L106) +[mermaidAPI.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L126) --- @@ -294,7 +295,7 @@ Put the svgCode into an iFrame. Return the iFrame code #### Defined in -[mermaidAPI.ts:270](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L270) +[mermaidAPI.ts:287](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L287) --- @@ -319,4 +320,4 @@ Remove any existing elements from the given document #### Defined in -[mermaidAPI.ts:341](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L341) +[mermaidAPI.ts:360](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L360) diff --git a/docs/config/theming.md b/docs/config/theming.md index 014ac1374..63271a39b 100644 --- a/docs/config/theming.md +++ b/docs/config/theming.md @@ -73,9 +73,9 @@ To make a custom theme, modify `themeVariables` via `init`. 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-reference-table)) | +| Parameter | Description | Type | Properties | +| -------------- | ------------------------------------ | ------ | ----------------------------------------------------------------------------------- | +| themeVariables | Modifiable with the `init` directive | Object | `primaryColor`, `primaryTextColor`, `lineColor` ([see full list](#theme-variables)) | Example of modifying `themeVariables` using the `init` directive: @@ -261,6 +261,34 @@ The theming engine will only recognize hex colors and not color names. So, the v | activationBkgColor | secondaryColor | Activation Background Color | | sequenceNumberColor | calculated from lineColor | Sequence Number Color | +## Pie Diagram Variables + +| Variable | Default value | Description | +| ------------------- | ------------------------------ | ------------------------------------------ | +| pie1 | primaryColor | Fill for 1st section in pie diagram | +| pie2 | secondaryColor | Fill for 2nd section in pie diagram | +| pie3 | calculated from tertiary | Fill for 3rd section in pie diagram | +| pie4 | calculated from primaryColor | Fill for 4th section in pie diagram | +| pie5 | calculated from secondaryColor | Fill for 5th section in pie diagram | +| pie6 | calculated from tertiaryColor | Fill for 6th section in pie diagram | +| pie7 | calculated from primaryColor | Fill for 7th section in pie diagram | +| pie8 | calculated from primaryColor | Fill for 8th section in pie diagram | +| pie9 | calculated from primaryColor | Fill for 9th section in pie diagram | +| pie10 | calculated from primaryColor | Fill for 10th section in pie diagram | +| pie11 | calculated from primaryColor | Fill for 11th section in pie diagram | +| pie12 | calculated from primaryColor | Fill for 12th section in pie diagram | +| pieTitleTextSize | 25px | Title text size | +| pieTitleTextColor | taskTextDarkColor | Title text color | +| pieSectionTextSize | 17px | Text size of individual section labels | +| pieSectionTextColor | textColor | Text color of individual section labels | +| pieLegendTextSize | 17px | Text size of labels in diagram legend | +| pieLegendTextColor | taskTextDarkColor | Text color of labels in diagram legend | +| pieStrokeColor | black | Border color of individual pie sections | +| pieStrokeWidth | 2px | Border width of individual pie sections | +| pieOuterStrokeWidth | 2px | Border width of pie diagram's outer circle | +| pieOuterStrokeColor | black | Border color of pie diagram's outer circle | +| pieOpacity | 0.7 | Opacity of individual pie sections | + ## State Colors | Variable | Default value | Description | diff --git a/docs/config/usage.md b/docs/config/usage.md index 866dd6be7..8bd34345f 100644 --- a/docs/config/usage.md +++ b/docs/config/usage.md @@ -20,29 +20,34 @@ Please note that you can switch versions through the dropdown box at the top rig For the majority of users, Using the [Live Editor](https://mermaid.live/) would be sufficient, however you may also opt to deploy mermaid as a dependency or using the [Mermaid API](./setup/README.md). -We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermaid Live Editor. +We have compiled some Video [Tutorials](./Tutorials.md) on how to use the Mermaid Live Editor. ### Installing and Hosting Mermaid on a Webpage **Using the npm package:** -1. You will need to install `node v16`, which would have npm. +Requirements: -2. Download `yarn` using npm. +- Node >= 16 -3. Enter the following command: `yarn add mermaid`. - -4. At this point, you can add mermaid as a dev dependency using this command: `yarn add --dev mermaid`. - -5. Alternatively, you can also deploy mermaid using the script tag in an HTML file with mermaid diagram descriptions as is shown in the example below. +```bash +# NPM +npm install mermaid +# Yarn +yarn add mermaid +# PNPM +pnpm add mermaid +``` **Hosting mermaid on a web page:** -> Note:This topic explored in greater depth in the [User Guide for Beginners](../intro/n00b-gettingStarted.md) +> Note: This topic is explored in greater depth in the [User Guide for Beginners](../intro/getting-started.md) The easiest way to integrate mermaid on a web page requires two elements: -- A graph definition, inside `
` tags labeled `class=mermaid`. Example:
+- A graph definition, inside `
` tags labeled `class=mermaid`.
+
+Example:
 
 ```html
 
@@ -53,14 +58,13 @@ The easiest way to integrate mermaid on a web page requires two elements:
 
``` -- Inclusion of the mermaid address in the html page body using a `script` tag as an ESM import, and the `mermaidAPI` call. +- The mermaid js script. Added using a `script` tag as an ESM import. Example: ```html ``` @@ -71,9 +75,6 @@ Example: ```html - - -
   graph LR
@@ -83,7 +84,6 @@ Example:
     
@@ -95,11 +95,12 @@ An id attribute is also added to mermaid tags without one. Mermaid can load multiple diagrams, in the same page. -> Try it out, save this code as HTML and load it using any browser.(Except Internet Explorer, please don't use Internet Explorer.) +> Try it out, save this code as HTML and load it using any browser. +> (Except Internet Explorer, please don't use Internet Explorer.) ## Enabling Click Event and Tags in Nodes -A `securityLevel` configuration has to first be cleared, `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduce in version 8.2 as a security improvement, aimed at preventing malicious use. +A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use. **It is the site owner's responsibility to discriminate between trustworthy and untrustworthy user-bases and we encourage the use of discretion.** @@ -107,41 +108,32 @@ A `securityLevel` configuration has to first be cleared, `securityLevel` sets th | Parameter | Description | Type | Required | Values | | ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ | -| securityLevel | Level of trust for parsed diagram | String | Required | 'sandbox', 'strict', 'loose', 'antiscript' | +| securityLevel | Level of trust for parsed diagram | String | Optional | 'sandbox', 'strict', 'loose', 'antiscript' | Values: -- **strict**: (**default**) tags in text are encoded, click functionality is disabled -- **loose**: tags in text are allowed, click functionality is enabled -- **antiscript**: html tags in text are allowed, (only script element is removed), click functionality is enabled -- **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This prevent any JavaScript running in the context. This may hinder interactive functionality of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc. +- **strict**: (**default**) HTML tags in the text are encoded and click functionality is disabled. +- **antiscript**: HTML tags in text are allowed (only script elements are removed) and click functionality is enabled. +- **loose**: HTML tags in text are allowed and click functionality is enabled. +- **sandbox**: With this security level, all rendering takes place in a sandboxed iframe. This prevents any JavaScript from running in the context. This may hinder interactive functionality of the diagram, like scripts, popups in the sequence diagram, links to other tabs or targets, etc. > **Note** > This changes the default behaviour of mermaid so that after upgrade to 8.2, unless the `securityLevel` is not changed, tags in flowcharts are encoded as tags and clicking is disabled. > **sandbox** security level is still in the beta version. -**If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing . This allows clicks and tags are allowed.** +**If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing. This allows clicks and tags are allowed.** -**To change `securityLevel`, you have to call `mermaidAPI.initialize`:** +**To change `securityLevel`, you have to call `mermaid.initialize`:** ```javascript -mermaidAPI.initialize({ +mermaid.initialize({ securityLevel: 'loose', }); ``` ### Labels out of bounds -If you use dynamically loaded fonts that are loaded through CSS, such as Google fonts, mermaid should wait for the -whole page to load (dom + assets, particularly the fonts file). - -```javascript -$(document).load(function () { - mermaid.initialize(); -}); -``` - -or +If you use dynamically loaded fonts that are loaded through CSS, such as fonts, mermaid should wait for the whole page to load (dom + assets, particularly the fonts file). ```javascript $(document).ready(function () { @@ -154,12 +146,54 @@ Not doing so will most likely result in mermaid rendering graphs that have label If your page has other fonts in its body those might be used instead of the mermaid font. Specifying the font in your styling is a workaround for this. ```css -div.mermaid { +pre.mermaid { font-family: 'trebuchet ms', verdana, arial; } ``` -### Calling `mermaid.init` +### Using `mermaid.run` + +mermaid.run was added in v10 and is the preferred way of handling more complex integration. +By default, `mermaid.run` will be called when the document is ready, rendering all elements with `class="mermaid"`. + +You can customize that behavior by calling `await mermaid.run()`. + +`mermaid.initialize({startOnLoad: false})` will prevent `mermaid.run` from being called automatically after load. + +Render all elements with querySelector ".someOtherClass" + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + querySelector: '.someOtherClass', +}); +``` + +Render all elements passed as an array + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + nodes: [document.getElementById('someId'), document.getElementById('anotherId')], +}); +await mermaid.run({ + nodes: document.querySelectorAll('.yetAnotherClass'), +}); +``` + +Render all `.mermaid` elements while suppressing any error + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + suppressErrors: true, +}); +``` + +### Calling `mermaid.init` - Deprecated + +> **Warning** +> mermaid.init is deprecated in v10 and will be removed in v11. Please use mermaid.run instead. By default, `mermaid.init` will be called when the document is ready, finding all elements with `class="mermaid"`. If you are adding content after mermaid is loaded, or otherwise need @@ -192,25 +226,41 @@ mermaid fully supports webpack. Here is a [working demo](https://github.com/merm ## API usage -The main idea of the API is to be able to call a render function with the graph definition as a string. The render function -will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to -fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. +The main idea of the API is to be able to call a render function with the graph definition as a string. The render function will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. -The example below show an outline of how this could be used. The example just logs the resulting SVG to the JavaScript console. +The example below shows an example of how this could be used. The example just logs the resulting SVG to the JavaScript console. ```html +``` + +To determine the type of diagram present in a given text, you can utilize the `mermaid.detectType` function, as demonstrated in the example below. + +```html + ``` @@ -223,17 +273,17 @@ The example code below is an extract of what mermaid does when using the API. Th bind events to an SVG when using the API for rendering. ```javascript -const insertSvg = function (svgCode, bindFunctions) { - element.innerHTML = svgCode; - if (typeof callback !== 'undefined') { - callback(id); +// Example of using the bindFunctions +const drawDiagram = async function () { + element = document.querySelector('#graphDiv'); + const graphDefinition = 'graph TB\na-->b'; + const { svg, bindFunctions } = await mermaid.render('graphDiv', graphDefinition); + element.innerHTML = svg; + // This can also be written as `bindFunctions?.(element);` using the `?` shorthand. + if (bindFunctions) { + bindFunctions(element); } - bindFunctions(element); }; - -const id = 'theGraph'; - -mermaidAPI.render(id, txt, insertSvg, element); ``` 1. The graph is generated using the render call. @@ -298,10 +348,10 @@ mermaid.parseError = function (err, hash) { displayErrorInGui(err); }; -const textFieldUpdated = function () { +const textFieldUpdated = async function () { const textStr = getTextFromFormField('code'); - if (mermaid.parse(textStr)) { + if (await mermaid.parse(textStr)) { reRender(textStr); } }; diff --git a/docs/ecosystem/integrations.md b/docs/ecosystem/integrations.md index 33b6b966e..7e645e243 100644 --- a/docs/ecosystem/integrations.md +++ b/docs/ecosystem/integrations.md @@ -6,6 +6,20 @@ # Integrations +## Recommendations + +### File Extension + +Applications that support mermaid files [SHOULD](https://datatracker.ietf.org/doc/html/rfc2119#section-3) use `.mermaid` or `.mmd` file extensions. + +### MIME Type + +The recommended [MIME type](https://www.iana.org/assignments/media-types/media-types.xhtml) for mermaid media is `text/vnd.mermaid`. + +[IANA](https://www.iana.org/) recognition pending. + +--- + The following list is a compilation of different integrations and plugins that allow the rendering of mermaid definitions within other applications. They also serve as proof of concept, for the variety of things that can be built with mermaid. @@ -16,21 +30,26 @@ They also serve as proof of concept, for the variety of things that can be built - [Using code blocks](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) (**Native support**) - [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action) - [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator) + - [GitHub Writer](https://github.com/ckeditor/github-writer) - [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**) - [Gitea](https://gitea.io) (**Native support**) - [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**) - [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) (**Native support**) +- [Mermaid Flow Visual Editor](https://www.mermaidflow.app) (**Native support**) +- [Deepdwn](https://billiam.itch.io/deepdwn) (**Native support**) - [Joplin](https://joplinapp.org) (**Native support**) +- [Slab](https://slab.com) (**Native support**) - [Swimm](https://swimm.io) (**Native support**) - [Notion](https://notion.so) (**Native support**) - [Observable](https://observablehq.com/@observablehq/mermaid) (**Native support**) -- [Obsidian](https://help.obsidian.md/How+to/Format+your+notes#Diagram) (**Native support**) +- [Obsidian](https://help.obsidian.md/Editing+and+formatting/Advanced+formatting+syntax#Diagram) (**Native support**) - [GitBook](https://gitbook.com) - [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid) - [Markdown with Mermaid CLI](https://github.com/miao1007/gitbook-plugin-mermaid-cli) - [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf) - [LiveBook](https://livebook.dev) (**Native support**) - [Atlassian Products](https://www.atlassian.com) + - [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview) - [Mermaid Plugin for Confluence](https://marketplace.atlassian.com/apps/1214124/mermaid-plugin-for-confluence?hosting=server&tab=overview) - [CloudScript.io Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview) - [Auto convert diagrams in Jira](https://github.com/coddingtonbear/jirafs-mermaid) @@ -48,13 +67,15 @@ They also serve as proof of concept, for the variety of things that can be built ## Blogs -- [Wordpress](https://wordpress.org) +- [WordPress](https://wordpress.org) - [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md) - [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/) - [Hexo](https://hexo.io) - [hexo-filter-mermaid-diagrams](https://github.com/webappdevelp/hexo-filter-mermaid-diagrams) - [hexo-tag-mermaid](https://github.com/JameChou/hexo-tag-mermaid) - [hexo-mermaid-diagrams](https://github.com/mslxl/hexo-mermaid-diagrams) +- [Nextra](https://nextra.site/) + - [Mermaid](https://nextra.site/docs/guide/mermaid) ## CMS @@ -64,7 +85,7 @@ They also serve as proof of concept, for the variety of things that can be built - [Plugin for Mermaid.js](https://github.com/eFrane/vuepress-plugin-mermaidjs) - [Grav CMS](https://getgrav.org/) - [Mermaid Diagrams](https://github.com/DanielFlaum/grav-plugin-mermaid-diagrams) - - [Gitlab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter) + - [GitLab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter) ## Communication @@ -84,10 +105,10 @@ They also serve as proof of concept, for the variety of things that can be built - [Flex Diagrams Extension](https://www.mediawiki.org/wiki/Extension:Flex_Diagrams) - [Semantic Media Wiki](https://semantic-mediawiki.org) - [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid) -- [FosWiki](https://foswiki.org) +- [Foswiki](https://foswiki.org) - [Mermaid Plugin](https://foswiki.org/Extensions/MermaidPlugin) - [DokuWiki](https://dokuwiki.org) - - [Flowcharts](https://www.dokuwiki.org/plugin:flowcharts?s[]=mermaid) + - [Mermaid Plugin](https://www.dokuwiki.org/plugin:mermaid) - [ComboStrap](https://combostrap.com/mermaid) - [TiddlyWiki](https://tiddlywiki.com/) - [mermaid-tw5: full js library](https://github.com/efurlanm/mermaid-tw5) @@ -139,16 +160,24 @@ They also serve as proof of concept, for the variety of things that can be built - [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams) - [GNU Nano](https://www.nano-editor.org/) - [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid) +- [CKEditor](https://github.com/ckeditor/ckeditor5) + - [CKEditor 5 Mermaid plugin](https://github.com/ckeditor/ckeditor5-mermaid) +- [Standard Notes](https://standardnotes.com/) + - [sn-mermaid](https://github.com/nienow/sn-mermaid) ## Document Generation - [Sphinx](https://www.sphinx-doc.org/en/master/) - [sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid) -- [remark.js](https://remark.js.org/) - - [remark-mermaid](https://github.com/temando/remark-mermaid) -- [jSDoc](https://jsdoc.app/) +- [remark](https://remark.js.org/) + - [remark-mermaidjs](https://github.com/remcohaszing/remark-mermaidjs) +- [rehype](https://github.com/rehypejs/rehype) + - [rehype-mermaidjs](https://github.com/remcohaszing/rehype-mermaidjs) +- [Gatsby](https://www.gatsbyjs.com/) + - [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid) +- [JSDoc](https://jsdoc.app/) - [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid) -- [MkDocs](https://mkdocs.org) +- [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/) - [Type Doc](https://typedoc.org/) @@ -158,6 +187,8 @@ They also serve as proof of concept, for the variety of things that can be built - [codedoc-mermaid-plugin](https://www.npmjs.com/package/codedoc-mermaid-plugin) - [mdbook](https://rust-lang.github.io/mdBook/index.html) - [mdbook-mermaid](https://github.com/badboy/mdbook-mermaid) +- [Quarto](https://quarto.org/) +- [Typora](https://typora.io/) ([Native support](https://support.typora.io/Draw-Diagrams-With-Markdown/#mermaid)) ## Browser Extensions @@ -185,6 +216,10 @@ They also serve as proof of concept, for the variety of things that can be built - [bisheng-plugin-mermaid](https://github.com/yct21/bisheng-plugin-mermaid) - [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) - [ExDoc](https://github.com/elixir-lang/ex_doc) - [Rendering Mermaid graphs](https://github.com/elixir-lang/ex_doc#rendering-mermaid-graphs) +- [NiceGUI: Let any browser be the frontend of your Python code](https://nicegui.io) + - [ui.mermaid(...)](https://nicegui.io/reference#mermaid_diagrams) + - [ui.markdown(..., extras=\['mermaid'\])](https://nicegui.io/reference#markdown_element) diff --git a/docs/intro/n00b-gettingStarted.md b/docs/intro/getting-started.md similarity index 86% rename from docs/intro/n00b-gettingStarted.md rename to docs/intro/getting-started.md index 87592ba27..246e7364c 100644 --- a/docs/intro/n00b-gettingStarted.md +++ b/docs/intro/getting-started.md @@ -2,13 +2,13 @@ > > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. > -> ## Please edit the corresponding file in [/packages/mermaid/src/docs/intro/n00b-gettingStarted.md](../../packages/mermaid/src/docs/intro/n00b-gettingStarted.md). +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/intro/getting-started.md](../../packages/mermaid/src/docs/intro/getting-started.md). # A Mermaid User-Guide for Beginners Mermaid is composed of three parts: Deployment, Syntax and Configuration. -This section talks about the different ways to deploy Mermaid. Learning the [Syntax](n00b-syntaxReference.md) would be of great help to the beginner. +This section talks about the different ways to deploy Mermaid. Learning the [Syntax](syntax-reference.md) would be of great help to the beginner. > Generally the live editor is enough for most general uses of mermaid, and is a good place to start learning. @@ -53,7 +53,7 @@ graph TD In the `Code` section one can write or edit raw mermaid code, and instantly `Preview` the rendered result on the panel beside it. -The `Configuration` Section is for changing the appearance and behavior of mermaid diagrams. An easy introduction to mermaid configuration is found in the [Advanced usage](../config/n00b-advanced.md) section. A complete configuration reference cataloging the default values can be found on the [mermaidAPI](../config/setup/README.md) page. +The `Configuration` Section is for changing the appearance and behavior of mermaid diagrams. An easy introduction to mermaid configuration is found in the [Advanced usage](../config/advanced.md) section. A complete configuration reference cataloging the default values can be found on the [mermaidAPI](../config/setup/README.md) page. ![Code,Config and Preview](./img/Code-Preview-Config.png) @@ -103,7 +103,7 @@ When writing the .html file, we give two instructions inside the html code to th a. The mermaid code for the diagram we want to create. -b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process . +b. The importing of mermaid library through the `mermaid.esm.mjs` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process. **a. The embedded mermaid diagram definition inside a `
`:**
 
@@ -135,7 +135,7 @@ b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm
 ```
 
 **Notes**:
-Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can place `mermaid.initialize()` inside `mermaid.esm.min.mjs` for brevity. However, doing the opposite lets you control when it starts looking for `
`tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `
` tags may have loaded on the execution of `mermaid.esm.min.mjs` file. +Rendering in Mermaid is initialized by `mermaid.initialize()` call. However, doing the opposite lets you control when it starts looking for `
` tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `
` tags may have loaded on the execution of `mermaid.esm.min.mjs` file.
 
 `startOnLoad` is one of the parameters that can be defined by `mermaid.initialize()`
 
@@ -143,10 +143,6 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac
 | ----------- | --------------------------------- | ------- | ----------- |
 | startOnLoad | Toggle for Rendering upon loading | Boolean | true, false |
 
-### Adding external diagrams to mermaid
-
-Please refer to the [Mindmap](../syntax/mindmap.md?id=integrating-with-your-librarywebsite) section for more information.
-
 ### Working Examples
 
 **Here is a full working example of the mermaidAPI being called through the CDN:**
@@ -225,4 +221,4 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file,
 
 **Comments from Knut Sveidqvist, creator of mermaid:**
 
-- In early versions of mermaid, the `
 ```
 
-**Doing so will command the mermaid parser to look for the `
` or `
` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.**
+**Doing so commands the mermaid parser to look for the `
` or `
` tags with `class="mermaid"`. From these tags, mermaid tries read the diagram/chart definitions and render them into SVG charts.**
 
-**Examples can be found at** [Other examples](../syntax/examples.md)
+**Examples can be found in** [Other examples](../syntax/examples.md)
 
 ## Sibling projects
 
@@ -298,7 +345,19 @@ Together we could continue the work with things like:
 
 Don't hesitate to contact me if you want to get involved!
 
-## For contributors
+## Contributors
+
+
+ +[![Good first issue](https://img.shields.io/github/labels/mermaid-js/mermaid/Good%20first%20issue%21)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%21%22) +[![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) +[![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) + +
+ +Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. + +Detailed information about how to contribute can be found in the [contribution guideline](/community/development). ### Requirements @@ -306,7 +365,7 @@ Don't hesitate to contact me if you want to get involved! - [Node.js](https://nodejs.org/en/). `volta install node` - [pnpm](https://pnpm.io/) package manager. `volta install pnpm` -## Development Installation +### Development Installation ```bash git clone git@github.com:mermaid-js/mermaid.git @@ -343,19 +402,7 @@ Update version number in `package.json`. npm publish ``` -The above command generates files into the `dist` folder and publishes them to \. - -## Related projects - -- [Command Line Interface](https://github.com/mermaid-js/mermaid-cli) -- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) -- [HTTP Server](https://github.com/TomWright/mermaid-server) - -## Contributors [![Good first issue](https://img.shields.io/github/labels/mermaid-js/mermaid/Good%20first%20issue%21)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) - -Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. - -Detailed information about how to contribute can be found in the [contribution guide](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) +The above command generates files into the `dist` folder and publishes them to [npmjs.com](https://www.npmjs.com/). ## Security and safe diagrams @@ -386,20 +433,15 @@ A quick note from Knut Sveidqvist: _Mermaid was created by Knut Sveidqvist for easier documentation._ diff --git a/docs/intro/n00b-syntaxReference.md b/docs/intro/syntax-reference.md similarity index 90% rename from docs/intro/n00b-syntaxReference.md rename to docs/intro/syntax-reference.md index c51b1680e..f1fdf6569 100644 --- a/docs/intro/n00b-syntaxReference.md +++ b/docs/intro/syntax-reference.md @@ -2,7 +2,7 @@ > > ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. > -> ## Please edit the corresponding file in [/packages/mermaid/src/docs/intro/n00b-syntaxReference.md](../../packages/mermaid/src/docs/intro/n00b-syntaxReference.md). +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/intro/syntax-reference.md](../../packages/mermaid/src/docs/intro/syntax-reference.md). # Diagram Syntax @@ -42,7 +42,7 @@ erDiagram PRODUCT ||--o{ ORDER-ITEM : "ordered in" ``` -The [Getting Started](./n00b-gettingStarted.md) section can also provide some practical examples of mermaid syntax. +The [Getting Started](./getting-started.md) section can also provide some practical examples of mermaid syntax. ## Diagram Breaking @@ -56,30 +56,30 @@ One should **beware the use of some words or symbols** that can break diagrams. | 'end' | The word "End" can cause Flowcharts and Sequence diagrams to break | Wrap them in quotation marks to prevent breakage. | | [Nodes inside Nodes](../syntax/flowchart.md?id=special-characters-that-break-syntax) | Mermaid gets confused with nested shapes | wrap them in quotation marks to prevent breaking | -### Mermaid Live Editor +## Mermaid Live Editor Now, that you've seen what you should not add to your diagrams, you can play around with them in the [Mermaid Live Editor](https://mermaid.live). -# Configuration +## Configuration Configuration is the third part of Mermaid, after deployment and syntax. It deals with the different ways that Mermaid can be customized across different deployments. If you are interested in altering and customizing your Mermaid Diagrams, you will find the methods and values available for [Configuration](../config/setup/README.md) here. It includes themes. This section will introduce the different methods of configuring the behaviors and appearances of Mermaid Diagrams. -The following are the most commonly used methods, and they are all tied to Mermaid [Deployment](./n00b-gettingStarted.md) methods. +The following are the most commonly used methods, and they are all tied to Mermaid [Deployment](./getting-started.md) methods. ### Configuration Section in the [Live Editor](https://mermaid.live). Here you can edit certain values to change the behavior and appearance of the diagram. -### [The initialize() call](https://mermaid-js.github.io/mermaid/#/n00b-gettingStarted?id=_3-calling-the-javascript-api), +### [The initialize() call](./getting-started.md#_3-calling-the-javascript-api) Used when Mermaid is called via an API, or through a ` ``` + +## Examples + +### Bar chart (using gantt chart) + +```mermaid-example +gantt + title Git Issues - days since last update + dateFormat X + axisFormat %s + section Issue19062 + 71 : 0, 71 + section Issue19401 + 36 : 0, 36 + section Issue193 + 34 : 0, 34 + section Issue7441 + 9 : 0, 9 + section Issue1300 + 5 : 0, 5 +``` + +```mermaid +gantt + title Git Issues - days since last update + dateFormat X + axisFormat %s + section Issue19062 + 71 : 0, 71 + section Issue19401 + 36 : 0, 36 + section Issue193 + 34 : 0, 34 + section Issue7441 + 9 : 0, 9 + section Issue1300 + 5 : 0, 5 +``` diff --git a/docs/syntax/gitgraph.md b/docs/syntax/gitgraph.md index 964fe3886..f2609e31c 100644 --- a/docs/syntax/gitgraph.md +++ b/docs/syntax/gitgraph.md @@ -825,6 +825,82 @@ NOTE: Because we have overridden the `mainBranchOrder` to `2`, the `main` branch Here, we have changed the default main branch name to `MetroLine1`. +## Orientation (v10.3.0+) + +In Mermaid, the default orientation is Left to Right. The branches are lined vertically. + +Usage example: + +```mermaid-example + gitGraph + commit + commit + branch develop + commit + commit + commit + checkout main + commit + commit + merge develop + commit + commit +``` + +```mermaid + gitGraph + commit + commit + branch develop + commit + commit + commit + checkout main + commit + commit + merge develop + commit + commit +``` + +Sometimes we may want to change the orientation. Currently, Mermaid supports two orientations: **Left to Right**(default) and **Top to Bottom**. + +In order to change the orientation from top to bottom i.e. branches lined horizontally, you need to add `TB` along with `gitGraph`. + +Usage example: + +```mermaid-example + gitGraph TB: + commit + commit + branch develop + commit + commit + commit + checkout main + commit + commit + merge develop + commit + commit +``` + +```mermaid + gitGraph TB: + commit + commit + branch develop + commit + commit + commit + checkout main + commit + commit + merge develop + commit + commit +``` + ## 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). diff --git a/docs/syntax/img/zenuml-participant-annotators.png b/docs/syntax/img/zenuml-participant-annotators.png new file mode 100644 index 000000000..13789371f Binary files /dev/null and b/docs/syntax/img/zenuml-participant-annotators.png differ diff --git a/docs/syntax/mindmap.md b/docs/syntax/mindmap.md index ad8aab77f..0bbd825cb 100644 --- a/docs/syntax/mindmap.md +++ b/docs/syntax/mindmap.md @@ -58,7 +58,7 @@ mindmap The syntax for creating Mindmaps is simple and relies on indentation for setting the levels in the hierarchy. -In the following example you can see how there are 3 different levels. One with starting at the left of the text and another level with two rows starting at the same column, defining the node A. At the end there is one more level where the text is indented further then the previous lines defining the nodes B and C. +In the following example you can see how there are 3 different levels. One with starting at the left of the text and another level with two rows starting at the same column, defining the node A. At the end there is one more level where the text is indented further than the previous lines defining the nodes B and C. mindmap Root @@ -66,7 +66,7 @@ In the following example you can see how there are 3 different levels. One with B C -In summary is a simple text outline where there are one node at the root level called `Root` which has one child `A`. `A` in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. +In summary is a simple text outline where there is one node at the root level called `Root` which has one child `A`. `A` in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. ```mermaid-example mindmap @@ -182,7 +182,7 @@ More shapes will be added, beginning with the shapes available in flowcharts. ## Icons -As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parenthesis like in the following example where icons for material design and fontawesome 4 are displayed. The intention is that this approach should be used for all diagrams supporting icons. **Experimental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. +As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parenthesis like in the following example where icons for material design and [Font Awesome 5](https://fontawesome.com/v5/search?o=r&m=free) are displayed. The intention is that this approach should be used for all diagrams supporting icons. **Experimental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. ```mermaid-example mindmap @@ -224,11 +224,11 @@ mindmap C ``` -_These classes needs top be supplied by the site administrator._ +_These classes need to be supplied by the site administrator._ ## Unclear indentation -The actual indentation does not really matter only compared with the previous rows. If we take the previous example and disrupt it a little we can se how the calculations are performed. Let us start with placing C with a smaller indentation than `B`but larger then `A`. +The actual indentation does not really matter only compared with the previous rows. If we take the previous example and disrupt it a little we can see how the calculations are performed. Let us start with placing C with a smaller indentation than `B` but larger then `A`. mindmap Root @@ -254,6 +254,34 @@ Root C ``` +## Markdown Strings + +The "Markdown Strings" feature enhances 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 +mindmap + id1["`**Root** with +a second line +Unicode works too: 🤓`"] + id2["`The dog in **the** hog... a *very long text* that wraps to a new line`"] + id3[Regular labels still works] +``` + +```mermaid +mindmap + id1["`**Root** with +a second line +Unicode works too: 🤓`"] + id2["`The dog in **the** hog... a *very long text* that wraps to a new line`"] + id3[Regular labels still works] +``` + +Formatting: + +- For bold text, use double asterisks \*\* before and after the text. +- For italics, use single asterisks \* before and after the text. +- With traditional strings, you needed to add
tags for text to wrap in nodes. However, markdown strings automatically wrap text when it becomes too long and allows you to start a new line by simply using a newline character instead of a
tag. + ## Integrating with your library/website. Mindmap uses the experimental lazy loading & async rendering features which could change in the future. From version 9.4.0 this diagram is included in mermaid but use lazy loading in order to keep the size of mermaid down. This is important in order to be able to add additional diagrams going forward. diff --git a/docs/syntax/pie.md b/docs/syntax/pie.md index 63f371e87..8b1de3856 100644 --- a/docs/syntax/pie.md +++ b/docs/syntax/pie.md @@ -48,6 +48,7 @@ Drawing a pie chart is really simple in mermaid. ## Example ```mermaid-example +%%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%% pie showData title Key elements in Product X "Calcium" : 42.96 @@ -57,6 +58,7 @@ pie showData ``` ```mermaid +%%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%% pie showData title Key elements in Product X "Calcium" : 42.96 @@ -64,3 +66,11 @@ pie showData "Magnesium" : 10.01 "Iron" : 5 ``` + +## Configuration + +Possible pie diagram configuration parameters: + +| Parameter | Description | Default value | +| -------------- | ------------------------------------------------------------------------------------------------------------ | ------------- | +| `textPosition` | The axial position of the pie slice labels, from 0.0 at the center to 1.0 at the outside edge of the circle. | `0.75` | diff --git a/docs/syntax/quadrantChart.md b/docs/syntax/quadrantChart.md new file mode 100644 index 000000000..39b57fd13 --- /dev/null +++ b/docs/syntax/quadrantChart.md @@ -0,0 +1,168 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/quadrantChart.md](../../packages/mermaid/src/docs/syntax/quadrantChart.md). + +# Quadrant Chart + +> A quadrant chart is a visual representation of data that is divided into four quadrants. It is used to plot data points on a two-dimensional grid, with one variable represented on the x-axis and another variable represented on the y-axis. The quadrants are determined by dividing the chart into four equal parts based on a set of criteria that is specific to the data being analyzed. Quadrant charts are often used to identify patterns and trends in data, and to prioritize actions based on the position of data points within the chart. They are commonly used in business, marketing, and risk management, among other fields. + +## Example + +```mermaid-example +quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + Campaign A: [0.3, 0.6] + Campaign B: [0.45, 0.23] + Campaign C: [0.57, 0.69] + Campaign D: [0.78, 0.34] + Campaign E: [0.40, 0.34] + Campaign F: [0.35, 0.78] +``` + +```mermaid +quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + Campaign A: [0.3, 0.6] + Campaign B: [0.45, 0.23] + Campaign C: [0.57, 0.69] + Campaign D: [0.78, 0.34] + Campaign E: [0.40, 0.34] + Campaign F: [0.35, 0.78] +``` + +## Syntax + +> **Note** +> If there are no points available in the chart both **axis** text and **quadrant** will be rendered in the center of the respective quadrant. +> If there are points **x-axis** labels will rendered from the left of the respective quadrant also they will be displayed at the bottom of the chart, and **y-axis** labels will be rendered at the bottom of the respective quadrant, the quadrant text will render at the top of the respective quadrant. + +> **Note** +> For points x and y value min value is 0 and max value is 1. + +### Title + +The title is a short description of the chart and it will always render on top of the chart. + +#### Example + + quadrantChart + title This is a sample example + +### x-axis + +The x-axis determines what text would be displayed in the x-axis. In x-axis there is two part **left** and **right** you can pass **both** or you can pass only **left**. The statement should start with `x-axis` then the `left axis text` followed by the delimiter `-->` then `right axis text`. + +#### Example + +1. `x-axis --> ` both the left and right axis text will be rendered. +2. `x-axis ` only the left axis text will be rendered. + +### y-axis + +The y-axis determines what text would be displayed in the y-axis. In y-axis there is two part **top** and **bottom** you can pass **both** or you can pass only **bottom**. The statement should start with `y-axis` then the `bottom axis text` followed by the delimiter `-->` then `top axis text`. + +#### Example + +1. `y-axis --> ` both the bottom and top axis text will be rendered. +2. `y-axis ` only the bottom axis text will be rendered. + +### Quadrants text + +The `quadrant-[1,2,3,4]` determine what text would be displayed inside the quadrants. + +#### Example + +1. `quadrant-1 ` determine what text will be rendered inside the top right quadrant. +2. `quadrant-2 ` determine what text will be rendered inside the top left quadrant. +3. `quadrant-3 ` determine what text will be rendered inside the bottom left quadrant. +4. `quadrant-4 ` determine what text will be rendered inside the bottom right quadrant. + +### Points + +Points are used to plot a circle inside the quadrantChart. The syntax is `: [x, y]` here x and y value is in the range 0 - 1. + +#### Example + +1. `Point 1: [0.75, 0.80]` here the Point 1 will be drawn in the top right quadrant. +2. `Point 2: [0.35, 0.24]` here the Point 2 will be drawn in the bottom left quadrant. + +## Chart Configurations + +| Parameter | Description | Default value | +| --------------------------------- | ------------------------------------------------------------------------------------------------- | :-----------: | +| chartWidth | Width of the chart | 500 | +| chartHeight | Height of the chart | 500 | +| titlePadding | Top and Bottom padding of the title | 10 | +| titleFontSize | Title font size | 20 | +| quadrantPadding | Padding outside all the quadrants | 5 | +| quadrantTextTopPadding | Quadrant text top padding when text is drawn on top ( not data points are there) | 5 | +| quadrantLabelFontSize | Quadrant text font size | 16 | +| quadrantInternalBorderStrokeWidth | Border stroke width inside the quadrants | 1 | +| quadrantExternalBorderStrokeWidth | Quadrant external border stroke width | 2 | +| xAxisLabelPadding | Top and bottom padding of x-axis text | 5 | +| xAxisLabelFontSize | X-axis texts font size | 16 | +| xAxisPosition | Position of x-axis (top , bottom) if there are points the x-axis will alway be rendered in bottom | 'top' | +| yAxisLabelPadding | Left and Right padding of y-axis text | 5 | +| yAxisLabelFontSize | Y-axis texts font size | 16 | +| yAxisPosition | Position of y-axis (left , right) | 'left' | +| pointTextPadding | Padding between point and the below text | 5 | +| pointLabelFontSize | Point text font size | 12 | +| pointRadius | Radius of the point to be drawn | 5 | + +## Chart Theme Variables + +| Parameter | Description | +| -------------------------------- | --------------------------------------- | +| quadrant1Fill | Fill color of the top right quadrant | +| quadrant2Fill | Fill color of the top left quadrant | +| quadrant3Fill | Fill color of the bottom left quadrant | +| quadrant4Fill | Fill color of the bottom right quadrant | +| quadrant1TextFill | Text color of the top right quadrant | +| quadrant2TextFill | Text color of the top left quadrant | +| quadrant3TextFill | Text color of the bottom left quadrant | +| quadrant4TextFill | Text color of the bottom right quadrant | +| quadrantPointFill | Points fill color | +| quadrantPointTextFill | Points text color | +| quadrantXAxisTextFill | X-axis text color | +| quadrantYAxisTextFill | Y-axis text color | +| quadrantInternalBorderStrokeFill | Quadrants inner border color | +| quadrantExternalBorderStrokeFill | Quadrants outer border color | +| quadrantTitleFill | Title color | + +## Example on config and theme + +```mermaid-example +%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%% +quadrantChart + x-axis Urgent --> Not Urgent + y-axis Not Important --> "Important ❤" + quadrant-1 Plan + quadrant-2 Do + quadrant-3 Delegate + quadrant-4 Delete +``` + +```mermaid +%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%% +quadrantChart + x-axis Urgent --> Not Urgent + y-axis Not Important --> "Important ❤" + quadrant-1 Plan + quadrant-2 Do + quadrant-3 Delegate + quadrant-4 Delete +``` diff --git a/docs/syntax/sankey.md b/docs/syntax/sankey.md new file mode 100644 index 000000000..6b408441a --- /dev/null +++ b/docs/syntax/sankey.md @@ -0,0 +1,294 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/sankey.md](../../packages/mermaid/src/docs/syntax/sankey.md). + +# Sankey diagram (v10.3.0+) + +> A sankey diagram is a visualization used to depict a flow from one set of values to another. + +::: warning +This is an experimental diagram. Its syntax are very close to plain CSV, but it is to be extended in the nearest future. +::: + +The things being connected are called nodes and the connections are called links. + +## Example + +This example taken from [observable](https://observablehq.com/@d3/sankey/2?collection=@d3/d3-sankey). It may be rendered a little bit differently, though, in terms of size and colors. + +```mermaid-example +sankey-beta + +Agricultural 'waste',Bio-conversion,124.729 +Bio-conversion,Liquid,0.597 +Bio-conversion,Losses,26.862 +Bio-conversion,Solid,280.322 +Bio-conversion,Gas,81.144 +Biofuel imports,Liquid,35 +Biomass imports,Solid,35 +Coal imports,Coal,11.606 +Coal reserves,Coal,63.965 +Coal,Solid,75.571 +District heating,Industry,10.639 +District heating,Heating and cooling - commercial,22.505 +District heating,Heating and cooling - homes,46.184 +Electricity grid,Over generation / exports,104.453 +Electricity grid,Heating and cooling - homes,113.726 +Electricity grid,H2 conversion,27.14 +Electricity grid,Industry,342.165 +Electricity grid,Road transport,37.797 +Electricity grid,Agriculture,4.412 +Electricity grid,Heating and cooling - commercial,40.858 +Electricity grid,Losses,56.691 +Electricity grid,Rail transport,7.863 +Electricity grid,Lighting & appliances - commercial,90.008 +Electricity grid,Lighting & appliances - homes,93.494 +Gas imports,Ngas,40.719 +Gas reserves,Ngas,82.233 +Gas,Heating and cooling - commercial,0.129 +Gas,Losses,1.401 +Gas,Thermal generation,151.891 +Gas,Agriculture,2.096 +Gas,Industry,48.58 +Geothermal,Electricity grid,7.013 +H2 conversion,H2,20.897 +H2 conversion,Losses,6.242 +H2,Road transport,20.897 +Hydro,Electricity grid,6.995 +Liquid,Industry,121.066 +Liquid,International shipping,128.69 +Liquid,Road transport,135.835 +Liquid,Domestic aviation,14.458 +Liquid,International aviation,206.267 +Liquid,Agriculture,3.64 +Liquid,National navigation,33.218 +Liquid,Rail transport,4.413 +Marine algae,Bio-conversion,4.375 +Ngas,Gas,122.952 +Nuclear,Thermal generation,839.978 +Oil imports,Oil,504.287 +Oil reserves,Oil,107.703 +Oil,Liquid,611.99 +Other waste,Solid,56.587 +Other waste,Bio-conversion,77.81 +Pumped heat,Heating and cooling - homes,193.026 +Pumped heat,Heating and cooling - commercial,70.672 +Solar PV,Electricity grid,59.901 +Solar Thermal,Heating and cooling - homes,19.263 +Solar,Solar Thermal,19.263 +Solar,Solar PV,59.901 +Solid,Agriculture,0.882 +Solid,Thermal generation,400.12 +Solid,Industry,46.477 +Thermal generation,Electricity grid,525.531 +Thermal generation,Losses,787.129 +Thermal generation,District heating,79.329 +Tidal,Electricity grid,9.452 +UK land based bioenergy,Bio-conversion,182.01 +Wave,Electricity grid,19.013 +Wind,Electricity grid,289.366 +``` + +```mermaid +sankey-beta + +Agricultural 'waste',Bio-conversion,124.729 +Bio-conversion,Liquid,0.597 +Bio-conversion,Losses,26.862 +Bio-conversion,Solid,280.322 +Bio-conversion,Gas,81.144 +Biofuel imports,Liquid,35 +Biomass imports,Solid,35 +Coal imports,Coal,11.606 +Coal reserves,Coal,63.965 +Coal,Solid,75.571 +District heating,Industry,10.639 +District heating,Heating and cooling - commercial,22.505 +District heating,Heating and cooling - homes,46.184 +Electricity grid,Over generation / exports,104.453 +Electricity grid,Heating and cooling - homes,113.726 +Electricity grid,H2 conversion,27.14 +Electricity grid,Industry,342.165 +Electricity grid,Road transport,37.797 +Electricity grid,Agriculture,4.412 +Electricity grid,Heating and cooling - commercial,40.858 +Electricity grid,Losses,56.691 +Electricity grid,Rail transport,7.863 +Electricity grid,Lighting & appliances - commercial,90.008 +Electricity grid,Lighting & appliances - homes,93.494 +Gas imports,Ngas,40.719 +Gas reserves,Ngas,82.233 +Gas,Heating and cooling - commercial,0.129 +Gas,Losses,1.401 +Gas,Thermal generation,151.891 +Gas,Agriculture,2.096 +Gas,Industry,48.58 +Geothermal,Electricity grid,7.013 +H2 conversion,H2,20.897 +H2 conversion,Losses,6.242 +H2,Road transport,20.897 +Hydro,Electricity grid,6.995 +Liquid,Industry,121.066 +Liquid,International shipping,128.69 +Liquid,Road transport,135.835 +Liquid,Domestic aviation,14.458 +Liquid,International aviation,206.267 +Liquid,Agriculture,3.64 +Liquid,National navigation,33.218 +Liquid,Rail transport,4.413 +Marine algae,Bio-conversion,4.375 +Ngas,Gas,122.952 +Nuclear,Thermal generation,839.978 +Oil imports,Oil,504.287 +Oil reserves,Oil,107.703 +Oil,Liquid,611.99 +Other waste,Solid,56.587 +Other waste,Bio-conversion,77.81 +Pumped heat,Heating and cooling - homes,193.026 +Pumped heat,Heating and cooling - commercial,70.672 +Solar PV,Electricity grid,59.901 +Solar Thermal,Heating and cooling - homes,19.263 +Solar,Solar Thermal,19.263 +Solar,Solar PV,59.901 +Solid,Agriculture,0.882 +Solid,Thermal generation,400.12 +Solid,Industry,46.477 +Thermal generation,Electricity grid,525.531 +Thermal generation,Losses,787.129 +Thermal generation,District heating,79.329 +Tidal,Electricity grid,9.452 +UK land based bioenergy,Bio-conversion,182.01 +Wave,Electricity grid,19.013 +Wind,Electricity grid,289.366 +``` + +## Syntax + +The idea behind syntax is that a user types `sankey-beta` keyword first, then pastes raw CSV below and get the result. + +It implements CSV standard as [described here](https://www.ietf.org/rfc/rfc4180.txt) with subtle **differences**: + +- CSV must contain **3 columns only** +- It is **allowed** to have **empty lines** without comma separators for visual purposes + +### Basic + +It is implied that 3 columns inside CSV should represent `source`, `target` and `value` accordingly: + +```mermaid-example +sankey-beta + +%% source,target,value +Electricity grid,Over generation / exports,104.453 +Electricity grid,Heating and cooling - homes,113.726 +Electricity grid,H2 conversion,27.14 +``` + +```mermaid +sankey-beta + +%% source,target,value +Electricity grid,Over generation / exports,104.453 +Electricity grid,Heating and cooling - homes,113.726 +Electricity grid,H2 conversion,27.14 +``` + +### Empty Lines + +CSV does not support empty lines without comma delimiters by default. But you can add them if needed: + +```mermaid-example +sankey-beta + +Bio-conversion,Losses,26.862 + +Bio-conversion,Solid,280.322 + +Bio-conversion,Gas,81.144 +``` + +```mermaid +sankey-beta + +Bio-conversion,Losses,26.862 + +Bio-conversion,Solid,280.322 + +Bio-conversion,Gas,81.144 +``` + +### Commas + +If you need to have a comma, wrap it in double quotes: + +```mermaid-example +sankey-beta + +Pumped heat,"Heating and cooling, homes",193.026 +Pumped heat,"Heating and cooling, commercial",70.672 +``` + +```mermaid +sankey-beta + +Pumped heat,"Heating and cooling, homes",193.026 +Pumped heat,"Heating and cooling, commercial",70.672 +``` + +### Double Quotes + +If you need to have double quote, put a pair of them inside quoted string: + +```mermaid-example +sankey-beta + +Pumped heat,"Heating and cooling, ""homes""",193.026 +Pumped heat,"Heating and cooling, ""commercial""",70.672 +``` + +```mermaid +sankey-beta + +Pumped heat,"Heating and cooling, ""homes""",193.026 +Pumped heat,"Heating and cooling, ""commercial""",70.672 +``` + +## Configuration + +You can customize link colors, node alignments and diagram dimensions. + +```html + +``` + +### Links Coloring + +You can adjust links' color by setting `linkColor` to one of those: + +- `source` - link will be of a source node color +- `target` - link will be of a target node color +- `gradient` - link color will be smoothly transient between source and target node colors +- hex code of color, like `#a1a1a1` + +### Node Alignment + +Graph layout can be changed by setting `nodeAlignment` to: + +- `justify` +- `center` +- `left` +- `right` diff --git a/docs/syntax/sequenceDiagram.md b/docs/syntax/sequenceDiagram.md index 5ca9a55f8..fbfa59d13 100644 --- a/docs/syntax/sequenceDiagram.md +++ b/docs/syntax/sequenceDiagram.md @@ -94,6 +94,43 @@ sequenceDiagram J->>A: Great! ``` +### Actor Creation and Destruction (v10.3.0+) + +It is possible to create and destroy actors by messages. To do so, add a create or destroy directive before the message. + + create participant B + A --> B: Hello + +Create directives support actor/participant distinction and aliases. The sender or the recipient of a message can be destroyed but only the recipient can be created. + +```mermaid-example +sequenceDiagram + Alice->>Bob: Hello Bob, how are you ? + Bob->>Alice: Fine, thank you. And you? + create participant Carl + Alice->>Carl: Hi Carl! + create actor D as Donald + Carl->>D: Hi! + destroy Carl + Alice-xCarl: We are too many + destroy Bob + Bob->>Alice: I agree +``` + +```mermaid +sequenceDiagram + Alice->>Bob: Hello Bob, how are you ? + Bob->>Alice: Fine, thank you. And you? + create participant Carl + Alice->>Carl: Hi Carl! + create actor D as Donald + Carl->>D: Hi! + destroy Carl + Alice-xCarl: We are too many + destroy Bob + Bob->>Alice: I agree +``` + ### Grouping / Box The actor(s) can be grouped in vertical boxes. You can define a color (if not, it will be transparent) and/or a descriptive label using the following notation: @@ -127,7 +164,7 @@ The actor(s) can be grouped in vertical boxes. You can define a color (if not, i end A->>J: Hello John, how are you? J->>A: Great! - A->>B: Hello Bob, how is Charly ? + A->>B: Hello Bob, how is Charly? B->>C: Hello Charly, how are you? ``` @@ -143,7 +180,7 @@ The actor(s) can be grouped in vertical boxes. You can define a color (if not, i end A->>J: Hello John, how are you? J->>A: Great! - A->>B: Hello Bob, how is Charly ? + A->>B: Hello Bob, how is Charly? B->>C: Hello Charly, how are you? ``` @@ -595,7 +632,7 @@ It is possible to get a sequence number attached to each arrow in a sequence dia ``` -It can also be be turned on via the diagram code as in the diagram: +It can also be turned on via the diagram code as in the diagram: ```mermaid-example sequenceDiagram diff --git a/docs/syntax/stateDiagram.md b/docs/syntax/stateDiagram.md index 807d6149a..4c28c82b3 100644 --- a/docs/syntax/stateDiagram.md +++ b/docs/syntax/stateDiagram.md @@ -487,7 +487,7 @@ where - the second _property_ is `color` and its _value_ is `white` - the third _property_ is `font-weight` and its _value_ is `bold` - the fourth _property_ is `stroke-width` and its _value_ is `2px` -- the fifth _property_ is `stroke` and its _value_ is `yello` +- the fifth _property_ is `stroke` and its _value_ is `yellow` ### Apply classDef styles to states diff --git a/docs/syntax/timeline.md b/docs/syntax/timeline.md index 58b12313d..d42a2dc7c 100644 --- a/docs/syntax/timeline.md +++ b/docs/syntax/timeline.md @@ -8,7 +8,7 @@ > Timeline: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stable except for the icon integration which is the experimental part. -"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia +"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia ### An example of a timeline. @@ -137,7 +137,7 @@ timeline 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. @@ -151,7 +151,7 @@ timeline 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. @@ -213,7 +213,7 @@ However, if there is no section defined, then we have two possibilities: ``` -Note that this is no, section defined, and each time period and its corresponding events will have its own color scheme. +Note that there are no sections defined, and each time period and its corresponding events will have its own color scheme. 2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme. @@ -257,9 +257,11 @@ let us look at same example, where we have disabled the multiColor option. ### Customizing Color scheme -You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on. +You can customize the color scheme using the `cScale0` to `cScale11` theme variables, which will change the background colors. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on. In case you have more than 12 sections, the color scheme will start to repeat. +If you also want to change the foreground color of a section, you can do so use theme variables corresponding `cScaleLabel0` to `cScaleLabel11` variables. + NOTE: Default values for these theme variables are picked from the selected theme. If you want to override the default values, you can use the `initialize` call to add your custom theme variable values. Example: @@ -268,9 +270,9 @@ Now let's override the default values for the `cScale0` to `cScale2` variables: ```mermaid-example %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { - 'cScale0': '#ff0000', + 'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff', 'cScale1': '#00ff00', - 'cScale2': '#0000ff' + 'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff' } } }%% timeline title History of Social Media Platform @@ -286,9 +288,9 @@ Now let's override the default values for the `cScale0` to `cScale2` variables: ```mermaid %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { - 'cScale0': '#ff0000', + 'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff', 'cScale1': '#00ff00', - 'cScale2': '#0000ff' + 'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff' } } }%% timeline title History of Social Media Platform diff --git a/docs/syntax/zenuml.md b/docs/syntax/zenuml.md new file mode 100644 index 000000000..9e9b11255 --- /dev/null +++ b/docs/syntax/zenuml.md @@ -0,0 +1,472 @@ +> **Warning** +> +> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. +> +> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/zenuml.md](../../packages/mermaid/src/docs/syntax/zenuml.md). + +# ZenUML + +> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order. + +Mermaid can render sequence diagrams with [ZenUML](https://zenuml.com). Note that ZenUML uses a different +syntax than the original Sequence Diagram in mermaid. + +```mermaid-example +zenuml + title Demo + Alice->John: Hello John, how are you? + John->Alice: Great! + Alice->John: See you later! +``` + +```mermaid +zenuml + title Demo + Alice->John: Hello John, how are you? + John->Alice: Great! + Alice->John: See you later! +``` + +## Syntax + +### Participants + +The participants can be defined implicitly as in the first example on this page. The participants or actors are +rendered in order of appearance in the diagram source text. Sometimes you might want to show the participants in a +different order than how they appear in the first message. It is possible to specify the actor's order of +appearance by doing the following: + +```mermaid-example +zenuml + title Declare participant (optional) + Bob + Alice + Alice->Bob: Hi Bob + Bob->Alice: Hi Alice +``` + +```mermaid +zenuml + title Declare participant (optional) + Bob + Alice + Alice->Bob: Hi Bob + Bob->Alice: Hi Alice +``` + +### Annotators + +If you specifically want to use symbols instead of just rectangles with text you can do so by using the annotator syntax to declare participants as per below. + +```mermaid-example +zenuml + title Annotators + @Actor Alice + @Database Bob + Alice->Bob: Hi Bob + Bob->Alice: Hi Alice +``` + +```mermaid +zenuml + title Annotators + @Actor Alice + @Database Bob + Alice->Bob: Hi Bob + Bob->Alice: Hi Alice +``` + +Here are the available annotators: +![img.png](img/zenuml-participant-annotators.png) + +### Aliases + +The participants can have a convenient identifier and a descriptive label. + +```mermaid-example +zenuml + title Aliases + A as Alice + J as John + A->J: Hello John, how are you? + J->A: Great! +``` + +```mermaid +zenuml + title Aliases + A as Alice + J as John + A->J: Hello John, how are you? + J->A: Great! +``` + +## Messages + +Messages can be one of: + +1. Sync message +2. Async message +3. Creation message +4. Reply message + +### Sync message + +You can think of a sync (blocking) method in a programming language. + +```mermaid-example +zenuml + title Sync message + A.SyncMessage + A.SyncMessage(with, parameters) { + B.nestedSyncMessage() + } +``` + +```mermaid +zenuml + title Sync message + A.SyncMessage + A.SyncMessage(with, parameters) { + B.nestedSyncMessage() + } +``` + +### Async message + +You can think of an async (non-blocking) method in a programming language. +Fire an event and forget about it. + +```mermaid-example +zenuml + title Async message + Alice->Bob: How are you? +``` + +```mermaid +zenuml + title Async message + Alice->Bob: How are you? +``` + +### Creation message + +We use `new` keyword to create an object. + +```mermaid-example +zenuml + new A1 + new A2(with, parameters) +``` + +```mermaid +zenuml + new A1 + new A2(with, parameters) +``` + +### Reply message + +There are three ways to express a reply message: + +```mermaid-example +zenuml + // 1. assign a variable from a sync message. + a = A.SyncMessage() + + // 1.1. optionally give the variable a type + SomeType a = A.SyncMessage() + + // 2. use return keyword + A.SyncMessage() { + return result + } + + // 3. use @return or @reply annotator on an async message + @return + A->B: result +``` + +```mermaid +zenuml + // 1. assign a variable from a sync message. + a = A.SyncMessage() + + // 1.1. optionally give the variable a type + SomeType a = A.SyncMessage() + + // 2. use return keyword + A.SyncMessage() { + return result + } + + // 3. use @return or @reply annotator on an async message + @return + A->B: result +``` + +The third way `@return` is rarely used, but it is useful when you want to return to one level up. + +```mermaid-example +zenuml + title Reply message + Client->A.method() { + B.method() { + if(condition) { + return x1 + // return early + @return + A->Client: x11 + } + } + return x2 + } +``` + +```mermaid +zenuml + title Reply message + Client->A.method() { + B.method() { + if(condition) { + return x1 + // return early + @return + A->Client: x11 + } + } + return x2 + } +``` + +## Nesting + +Sync messages and Creation messages are naturally nestable with `{}`. + +```mermaid-example +zenuml + A.method() { + B.nested_sync_method() + B->C: nested async message + } +``` + +```mermaid +zenuml + A.method() { + B.nested_sync_method() + B->C: nested async message + } +``` + +## Comments + +It is possible to add comments to a sequence diagram with `// comment` syntax. +Comments will be rendered above the messages or fragments. Comments on other places +are ignored. Markdown is supported. + +See the example below: + +```mermaid-example +zenuml + // a comment on a participant will not be rendered + BookService + // a comment on a message. + // **Markdown** is supported. + BookService.getBook() +``` + +```mermaid +zenuml + // a comment on a participant will not be rendered + BookService + // a comment on a message. + // **Markdown** is supported. + BookService.getBook() +``` + +## Loops + +It is possible to express loops in a ZenUML diagram. This is done by any of the +following notations: + +1. while +2. for +3. forEach, foreach +4. loop + +```zenuml +while(condition) { + ...statements... +} +``` + +See the example below: + +```mermaid-example +zenuml + Alice->John: Hello John, how are you? + while(true) { + John->Alice: Great! + } +``` + +```mermaid +zenuml + Alice->John: Hello John, how are you? + while(true) { + John->Alice: Great! + } +``` + +## Alt + +It is possible to express alternative paths in a sequence diagram. This is done by the notation + +```zenuml +if(condition1) { + ...statements... +} else if(condition2) { + ...statements... +} else { + ...statements... +} +``` + +See the example below: + +```mermaid-example +zenuml + Alice->Bob: Hello Bob, how are you? + if(is_sick) { + Bob->Alice: Not so good :( + } else { + Bob->Alice: Feeling fresh like a daisy + } +``` + +```mermaid +zenuml + Alice->Bob: Hello Bob, how are you? + if(is_sick) { + Bob->Alice: Not so good :( + } else { + Bob->Alice: Feeling fresh like a daisy + } +``` + +## Opt + +It is possible to render an `opt` fragment. This is done by the notation + +```zenuml +opt { + ...statements... +} +``` + +See the example below: + +```mermaid-example +zenuml + Alice->Bob: Hello Bob, how are you? + Bob->Alice: Not so good :( + opt { + Bob->Alice: Thanks for asking + } +``` + +```mermaid +zenuml + Alice->Bob: Hello Bob, how are you? + Bob->Alice: Not so good :( + opt { + Bob->Alice: Thanks for asking + } +``` + +## Parallel + +It is possible to show actions that are happening in parallel. + +This is done by the notation + +```zenuml +par { + statement1 + statement2 + statement3 +} +``` + +See the example below: + +```mermaid-example +zenuml + par { + Alice->Bob: Hello guys! + Alice->John: Hello guys! + } +``` + +```mermaid +zenuml + par { + Alice->Bob: Hello guys! + Alice->John: Hello guys! + } +``` + +## Try/Catch/Finally (Break) + +It is possible to indicate a stop of the sequence within the flow (usually used to model exceptions). + +This is done by the notation + + try { + ...statements... + } catch { + ...statements... + } finally { + ...statements... + } + +See the example below: + +```mermaid-example +zenuml + try { + Consumer->API: Book something + API->BookingService: Start booking process + } catch { + API->Consumer: show failure + } finally { + API->BookingService: rollback status + } +``` + +```mermaid +zenuml + try { + Consumer->API: Book something + API->BookingService: Start booking process + } catch { + API->Consumer: show failure + } finally { + API->BookingService: rollback status + } +``` + +## Integrating with your library/website. + +Zenuml uses the experimental lazy loading & async rendering features which could change in the future. + +You can use this method to add mermaid including the zenuml diagram to a web page: + +```html + +``` diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 000000000..2853f4c82 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,18 @@ +# Settings in the [build] context are global and are applied to +# all contexts unless otherwise overridden by more specific contexts. +[build] + # Directory where the build system installs dependencies + # and runs your build. Store your package.json, .nvmrc, etc here. + # If not set, defaults to the root directory. + base = "" + + # Directory that contains the deploy-ready HTML files and + # assets generated by the build. This is an absolute path relative + # to the base directory, which is the root by default (/). + # This sample publishes the directory located at the absolute + # path "root/project/build-output" + + publish = "mermaid-live-editor/docs" + + # Default build command. + command = "./scripts/editor.bash" diff --git a/package.json b/package.json index 8e4c50118..232f23be1 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "mermaid-monorepo", "private": true, - "version": "9.4.0", + "version": "10.2.4", "description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "type": "module", - "packageManager": "pnpm@7.27.0", + "packageManager": "pnpm@8.7.1", "keywords": [ "diagram", "markdown", @@ -18,17 +18,23 @@ "build:vite": "ts-node-esm --transpileOnly .vite/build.ts", "build:mermaid": "pnpm build:vite --mermaid", "build:viz": "pnpm build:mermaid --visualize", - "build:types": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-example-diagram/tsconfig.json --emitDeclarationOnly", + "build:types": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-zenuml/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-example-diagram/tsconfig.json --emitDeclarationOnly", "build:watch": "pnpm build:vite --watch", "build": "pnpm run -r clean && pnpm build:types && pnpm build:vite", "dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"", + "dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev", "release": "pnpm build", "lint": "eslint --cache --cache-strategy content --ignore-path .gitignore . && pnpm lint:jison && prettier --cache --check .", "lint:fix": "eslint --cache --cache-strategy content --fix --ignore-path .gitignore . && prettier --write . && ts-node-esm scripts/fixCSpell.ts", "lint:jison": "ts-node-esm ./scripts/jison/lint.mts", + "contributors": "ts-node-esm scripts/updateContributors.ts", "cypress": "cypress run", "cypress:open": "cypress open", "e2e": "start-server-and-test dev http://localhost:9000/ cypress", + "coverage:cypress:clean": "rimraf .nyc_output coverage/cypress", + "e2e:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm e2e", + "coverage:merge": "ts-node-esm scripts/coverage.ts", + "coverage": "pnpm test:coverage --run && pnpm e2e:coverage && pnpm coverage:merge", "ci": "vitest run", "test": "pnpm lint && vitest run", "test:watch": "vitest --watch", @@ -54,64 +60,71 @@ ] }, "devDependencies": { - "@applitools/eyes-cypress": "^3.27.6", - "@commitlint/cli": "^17.2.0", - "@commitlint/config-conventional": "^17.2.0", - "@cspell/eslint-plugin": "^6.14.2", + "@applitools/eyes-cypress": "^3.33.1", + "@commitlint/cli": "^17.6.1", + "@commitlint/config-conventional": "^17.6.1", + "@cspell/eslint-plugin": "^6.31.1", + "@cypress/code-coverage": "^3.10.7", + "@rollup/plugin-typescript": "^11.1.1", "@types/cors": "^2.8.13", - "@types/eslint": "^8.4.10", + "@types/eslint": "^8.37.0", "@types/express": "^4.17.17", "@types/js-yaml": "^4.0.5", - "@types/jsdom": "^21.0.0", - "@types/lodash": "^4.14.188", - "@types/mdast": "^3.0.10", - "@types/node": "^18.11.9", - "@types/prettier": "^2.7.1", + "@types/jsdom": "^21.1.1", + "@types/lodash": "^4.14.194", + "@types/mdast": "^3.0.11", + "@types/node": "^18.16.0", + "@types/prettier": "^2.7.2", "@types/rollup-plugin-visualizer": "^4.2.1", - "@typescript-eslint/eslint-plugin": "^5.48.2", - "@typescript-eslint/parser": "^5.48.2", - "@vitest/coverage-c8": "^0.28.4", - "@vitest/spy": "^0.28.4", - "@vitest/ui": "^0.28.4", - "concurrently": "^7.5.0", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "@vitest/coverage-v8": "^0.34.0", + "@vitest/spy": "^0.34.0", + "@vitest/ui": "^0.34.0", + "ajv": "^8.12.0", + "concurrently": "^8.0.1", "cors": "^2.8.5", - "coveralls": "^3.1.1", - "cypress": "^12.0.0", + "cypress": "^12.10.0", "cypress-image-snapshot": "^4.0.1", - "esbuild": "^0.17.0", - "eslint": "^8.32.0", - "eslint-config-prettier": "^8.6.0", - "eslint-plugin-cypress": "^2.12.1", + "esbuild": "^0.19.0", + "eslint": "^8.39.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-cypress": "^2.13.2", "eslint-plugin-html": "^7.1.0", - "eslint-plugin-jest": "^27.1.5", - "eslint-plugin-jsdoc": "^39.6.2", + "eslint-plugin-jest": "^27.2.1", + "eslint-plugin-jsdoc": "^46.0.0", "eslint-plugin-json": "^3.1.0", "eslint-plugin-lodash": "^7.4.0", "eslint-plugin-markdown": "^3.0.0", "eslint-plugin-no-only-tests": "^3.1.0", "eslint-plugin-tsdoc": "^0.2.17", - "eslint-plugin-unicorn": "^45.0.0", + "eslint-plugin-unicorn": "^47.0.0", "express": "^4.18.2", - "globby": "^13.1.2", - "husky": "^8.0.2", - "jest": "^29.3.1", + "globby": "^13.1.4", + "husky": "^8.0.3", + "jest": "^29.5.0", "jison": "^0.4.18", "js-yaml": "^4.1.0", - "jsdom": "^21.0.0", - "lint-staged": "^13.0.3", + "jsdom": "^22.0.0", + "lint-staged": "^13.2.1", + "nyc": "^15.1.0", "path-browserify": "^1.0.1", - "pnpm": "^7.15.0", - "prettier": "^2.7.1", + "pnpm": "^8.6.8", + "prettier": "^2.8.8", "prettier-plugin-jsdoc": "^0.4.2", - "rimraf": "^4.0.0", - "rollup-plugin-visualizer": "^5.8.3", - "start-server-and-test": "^1.15.4", + "rimraf": "^5.0.0", + "rollup-plugin-visualizer": "^5.9.2", + "start-server-and-test": "^2.0.0", "ts-node": "^10.9.1", - "typescript": "^4.8.4", - "vite": "^4.1.1", - "vitest": "^0.28.5" + "typescript": "^5.1.3", + "vite": "^4.3.9", + "vite-plugin-istanbul": "^4.1.0", + "vitest": "^0.34.0" }, "volta": { - "node": "18.14.0" + "node": "18.17.1" + }, + "nyc": { + "report-dir": "coverage/cypress" } } diff --git a/packages/mermaid-example-diagram/package.json b/packages/mermaid-example-diagram/package.json index 3c71a2ac3..dc468a6c7 100644 --- a/packages/mermaid-example-diagram/package.json +++ b/packages/mermaid-example-diagram/package.json @@ -38,7 +38,7 @@ ] }, "dependencies": { - "@braintree/sanitize-url": "^6.0.0", + "@braintree/sanitize-url": "^6.0.1", "cytoscape": "^3.23.0", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.1.0", @@ -48,13 +48,10 @@ }, "devDependencies": { "@types/cytoscape": "^3.19.9", - "concurrently": "^7.5.0", - "rimraf": "^4.0.0", + "concurrently": "^8.0.0", + "rimraf": "^5.0.0", "mermaid": "workspace:*" }, - "resolutions": { - "d3": "^7.0.0" - }, "files": [ "dist" ], diff --git a/packages/mermaid-example-diagram/src/detector.ts b/packages/mermaid-example-diagram/src/detector.ts index 93fd42762..54b9d555b 100644 --- a/packages/mermaid-example-diagram/src/detector.ts +++ b/packages/mermaid-example-diagram/src/detector.ts @@ -3,7 +3,7 @@ import type { ExternalDiagramDefinition } from 'mermaid'; const id = 'example-diagram'; const detector = (txt: string) => { - return txt.match(/^\s*example-diagram/) !== null; + return /^\s*example-diagram/.test(txt); }; const loader = async () => { diff --git a/packages/mermaid-example-diagram/src/diagram-definition.ts b/packages/mermaid-example-diagram/src/diagram-definition.ts index c31b3d6e7..f29c8ee7f 100644 --- a/packages/mermaid-example-diagram/src/diagram-definition.ts +++ b/packages/mermaid-example-diagram/src/diagram-definition.ts @@ -1,9 +1,9 @@ // @ts-ignore: TODO Fix ts errors -import parser from './parser/exampleDiagram'; -import * as db from './exampleDiagramDb'; -import renderer from './exampleDiagramRenderer'; -import styles from './styles'; -import { injectUtils } from './mermaidUtils'; +import parser from './parser/exampleDiagram.jison'; +import * as db from './exampleDiagramDb.js'; +import renderer from './exampleDiagramRenderer.js'; +import styles from './styles.js'; +import { injectUtils } from './mermaidUtils.js'; export const diagram = { db, diff --git a/packages/mermaid-example-diagram/src/exampleDiagram.spec.js b/packages/mermaid-example-diagram/src/exampleDiagram.spec.js index 96c8cd5b2..9cfe33a1b 100644 --- a/packages/mermaid-example-diagram/src/exampleDiagram.spec.js +++ b/packages/mermaid-example-diagram/src/exampleDiagram.spec.js @@ -1,6 +1,6 @@ -import { parser } from './parser/exampleDiagram'; -import * as db from './exampleDiagramDb'; -import { injectUtils } from './mermaidUtils'; +import { parser } from './parser/exampleDiagram.jison'; +import * as db from './exampleDiagramDb.js'; +import { injectUtils } from './mermaidUtils.js'; // Todo fix utils functions for tests import { log, @@ -8,7 +8,7 @@ import { getConfig, sanitizeText, setupGraphViewBox, -} from '../../mermaid/src/diagram-api/diagramAPI'; +} from '../../mermaid/src/diagram-api/diagramAPI.js'; injectUtils(log, setLogLevel, getConfig, sanitizeText, setupGraphViewBox); diff --git a/packages/mermaid-example-diagram/src/exampleDiagramDb.js b/packages/mermaid-example-diagram/src/exampleDiagramDb.js index 8429ec5d6..21ba9e248 100644 --- a/packages/mermaid-example-diagram/src/exampleDiagramDb.js +++ b/packages/mermaid-example-diagram/src/exampleDiagramDb.js @@ -1,5 +1,5 @@ /** Created by knut on 15-01-14. */ -import { log } from './mermaidUtils'; +import { log } from './mermaidUtils.js'; var message = ''; var info = false; @@ -22,7 +22,6 @@ export const setInfo = (inf) => { info = inf; }; -/** @returns Returns the info flag */ export const getInfo = () => { return info; }; diff --git a/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js b/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js index 0d7340677..9b3854aaf 100644 --- a/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js +++ b/packages/mermaid-example-diagram/src/exampleDiagramRenderer.js @@ -1,6 +1,6 @@ /** Created by knut on 14-12-11. */ import { select } from 'd3'; -import { log, getConfig, setupGraphViewbox } from './mermaidUtils'; +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. @@ -8,7 +8,6 @@ import { log, getConfig, setupGraphViewbox } from './mermaidUtils'; * @param {any} text * @param {any} id * @param {any} version - * @param diagObj */ export const draw = (text, id, version) => { try { diff --git a/packages/mermaid-example-diagram/src/mermaidUtils.ts b/packages/mermaid-example-diagram/src/mermaidUtils.ts index 44cc85f73..eeeca05c5 100644 --- a/packages/mermaid-example-diagram/src/mermaidUtils.ts +++ b/packages/mermaid-example-diagram/src/mermaidUtils.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ const warning = (s: string) => { // Todo remove debug code // eslint-disable-next-line no-console @@ -28,7 +29,6 @@ export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; export let getConfig: () => object; export let sanitizeText: (str: string) => string; export let commonDb: () => object; -// eslint-disable @typescript-eslint/no-explicit-any export let setupGraphViewbox: ( graph: any, svgElem: any, diff --git a/packages/mermaid-example-diagram/tsconfig.json b/packages/mermaid-example-diagram/tsconfig.json index 310137cc0..45076b7b5 100644 --- a/packages/mermaid-example-diagram/tsconfig.json +++ b/packages/mermaid-example-diagram/tsconfig.json @@ -1,6 +1,5 @@ { "extends": "../../tsconfig.json", - "module": "esnext", "compilerOptions": { "rootDir": "./src", "outDir": "./dist" diff --git a/packages/mermaid-zenuml/README.md b/packages/mermaid-zenuml/README.md new file mode 120000 index 000000000..4300aecbe --- /dev/null +++ b/packages/mermaid-zenuml/README.md @@ -0,0 +1 @@ +../mermaid/src/docs/syntax/zenuml.md diff --git a/packages/mermaid-zenuml/package.json b/packages/mermaid-zenuml/package.json new file mode 100644 index 000000000..b907e2cba --- /dev/null +++ b/packages/mermaid-zenuml/package.json @@ -0,0 +1,47 @@ +{ + "name": "@mermaid-js/mermaid-zenuml", + "version": "0.1.2", + "description": "MermaidJS plugin for ZenUML integration", + "module": "dist/mermaid-zenuml.core.mjs", + "types": "dist/detector.d.ts", + "type": "module", + "exports": { + ".": { + "import": "./dist/mermaid-zenuml.core.mjs", + "types": "./dist/detector.d.ts" + }, + "./*": "./*" + }, + "keywords": [ + "diagram", + "markdown", + "zenuml", + "mermaid" + ], + "scripts": { + "prepublishOnly": "pnpm -w run build" + }, + "repository": { + "type": "git", + "url": "https://github.com/mermaid-js/mermaid", + "directory": "packages/mermaid-zenuml" + }, + "contributors": [ + "Peng Xiao (https://github.com/MrCoder)", + "Sidharth Vinod (https://sidharth.dev)", + "Dong Cai (https://github.com/dontry)" + ], + "license": "MIT", + "dependencies": { + "@zenuml/core": "^3.0.6" + }, + "devDependencies": { + "mermaid": "workspace:^" + }, + "peerDependencies": { + "mermaid": "workspace:>=10.0.0" + }, + "files": [ + "dist" + ] +} diff --git a/packages/mermaid-zenuml/src/detector.ts b/packages/mermaid-zenuml/src/detector.ts new file mode 100644 index 000000000..d782ffe33 --- /dev/null +++ b/packages/mermaid-zenuml/src/detector.ts @@ -0,0 +1,20 @@ +import type { ExternalDiagramDefinition } from 'mermaid'; + +const id = 'zenuml'; + +const detector = (txt: string) => { + return /^\s*zenuml/.test(txt); +}; + +const loader = async () => { + const { diagram } = await import('./zenuml-definition.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid-zenuml/src/mermaidUtils.ts b/packages/mermaid-zenuml/src/mermaidUtils.ts new file mode 100644 index 000000000..623685879 --- /dev/null +++ b/packages/mermaid-zenuml/src/mermaidUtils.ts @@ -0,0 +1,58 @@ +import type { MermaidConfig } from 'mermaid'; + +const warning = (s: string) => { + // Todo remove debug code + // eslint-disable-next-line no-console + console.error('Log function was called before initialization', s); +}; + +export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; + +export const LEVELS: Record = { + trace: 0, + debug: 1, + info: 2, + warn: 3, + error: 4, + fatal: 5, +}; + +export const log: Record = { + trace: warning, + debug: warning, + info: warning, + warn: warning, + error: warning, + fatal: warning, +}; + +export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void; +export let getConfig: () => MermaidConfig; +export let sanitizeText: (str: string) => string; +// eslint-disable @typescript-eslint/no-explicit-any +export let setupGraphViewbox: ( + graph: any, + svgElem: any, + padding: any, + useMaxWidth: boolean +) => void; + +export const injectUtils = ( + _log: Record, + _setLogLevel: any, + _getConfig: any, + _sanitizeText: any, + _setupGraphViewbox: any +) => { + _log.info('Mermaid utils injected'); + log.trace = _log.trace; + log.debug = _log.debug; + log.info = _log.info; + log.warn = _log.warn; + log.error = _log.error; + log.fatal = _log.fatal; + setLogLevel = _setLogLevel; + getConfig = _getConfig; + sanitizeText = _sanitizeText; + setupGraphViewbox = _setupGraphViewbox; +}; diff --git a/packages/mermaid-zenuml/src/parser.ts b/packages/mermaid-zenuml/src/parser.ts new file mode 100644 index 000000000..8c0ca55d5 --- /dev/null +++ b/packages/mermaid-zenuml/src/parser.ts @@ -0,0 +1,12 @@ +/** + * ZenUML manage parsing internally. It uses Antlr4 to parse the DSL. + * The parser is defined in https://github.com/ZenUml/vue-sequence/blob/main/src/parser/index.js + * + * This is a dummy parser that satisfies the mermaid API logic. + */ +export default { + parser: { yy: {} }, + parse: () => { + // no op + }, +}; diff --git a/packages/mermaid-zenuml/src/zenuml-definition.ts b/packages/mermaid-zenuml/src/zenuml-definition.ts new file mode 100644 index 000000000..ab287ff81 --- /dev/null +++ b/packages/mermaid-zenuml/src/zenuml-definition.ts @@ -0,0 +1,17 @@ +import { injectUtils } from './mermaidUtils.js'; +import parser from './parser.js'; +import renderer from './zenumlRenderer.js'; + +export const diagram = { + db: { + clear: () => { + // no-op + }, + }, + renderer, + parser, + styles: () => { + // no-op + }, + injectUtils, +}; diff --git a/packages/mermaid-zenuml/src/zenumlRenderer.ts b/packages/mermaid-zenuml/src/zenumlRenderer.ts new file mode 100644 index 000000000..e8ab69cdd --- /dev/null +++ b/packages/mermaid-zenuml/src/zenumlRenderer.ts @@ -0,0 +1,68 @@ +import { getConfig, log } from './mermaidUtils.js'; +import ZenUml from '@zenuml/core'; + +const regexp = /^\s*zenuml/; + +// Create a Zen UML container outside the svg first for rendering, otherwise the Zen UML diagram cannot be rendered properly +function createTemporaryZenumlContainer(id: string) { + const container = document.createElement('div'); + container.id = `container-${id}`; + container.style.display = 'flex'; + container.innerHTML = `
`; + const app = container.querySelector(`#zenUMLApp-${id}`) as HTMLElement; + return { container, app }; +} + +// Create a foreignObject to wrap the Zen UML container in the svg +function createForeignObject(id: string) { + const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject'); + foreignObject.setAttribute('x', '0'); + foreignObject.setAttribute('y', '0'); + foreignObject.setAttribute('width', '100%'); + foreignObject.setAttribute('height', '100%'); + const { container, app } = createTemporaryZenumlContainer(id); + foreignObject.appendChild(container); + return { foreignObject, container, app }; +} + +/** + * Draws a Zen UML in the tag with id: id based on the graph definition in text. + * + * @param text - The text of the diagram + * @param id - The id of the diagram which will be used as a DOM element id¨ + */ +export const draw = async function (text: string, id: string) { + log.info('draw with Zen UML renderer', ZenUml); + + text = text.replace(regexp, ''); + const { securityLevel } = getConfig(); + // Handle root and Document for when rendering in sandbox mode + let sandboxElement: HTMLIFrameElement | null = null; + if (securityLevel === 'sandbox') { + sandboxElement = document.getElementById('i' + id) as HTMLIFrameElement; + } + + const root = securityLevel === 'sandbox' ? sandboxElement?.contentWindow?.document : document; + + const svgContainer = root?.querySelector(`svg#${id}`); + + if (!root || !svgContainer) { + log.error('Cannot find root or svgContainer'); + return; + } + + const { foreignObject, container, app } = createForeignObject(id); + svgContainer.appendChild(foreignObject); + // @ts-expect-error @zenuml/core@3.0.0 exports the wrong type for ZenUml + const zenuml = new ZenUml(app); + // default is a theme name. More themes to be added and will be configurable in the future + await zenuml.render(text, 'theme-mermaid'); + + const { width, height } = window.getComputedStyle(container); + log.debug('zenuml diagram size', width, height); + svgContainer.setAttribute('style', `width: ${width}; height: ${height};`); +}; + +export default { + draw, +}; diff --git a/packages/mermaid-zenuml/tsconfig.json b/packages/mermaid-zenuml/tsconfig.json new file mode 100644 index 000000000..45076b7b5 --- /dev/null +++ b/packages/mermaid-zenuml/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["./src/**/*.ts"], + "typeRoots": ["./src/types"] +} diff --git a/packages/mermaid/.gitignore b/packages/mermaid/.gitignore index 6ed32bcf7..91c74fe7d 100644 --- a/packages/mermaid/.gitignore +++ b/packages/mermaid/.gitignore @@ -1,3 +1,6 @@ src/vitepress src/docs/config/setup -README.* \ No newline at end of file +README.* +src/docs/public/user-avatars/ +src/docs/.vitepress/cache +src/docs/.vitepress/components.d.ts diff --git a/packages/mermaid/.lintstagedrc.mjs b/packages/mermaid/.lintstagedrc.mjs index fe79ad254..955000e20 100644 --- a/packages/mermaid/.lintstagedrc.mjs +++ b/packages/mermaid/.lintstagedrc.mjs @@ -4,4 +4,5 @@ export default { 'src/docs/**': ['pnpm --filter mermaid run docs:build --git'], 'src/docs.mts': ['pnpm --filter mermaid run docs:build --git'], 'src/(defaultConfig|config|mermaidAPI).ts': ['pnpm --filter mermaid run docs:build --git'], + 'src/schemas/config.schema.yaml': ['pnpm --filter mermaid run types:build-config --git'], }; diff --git a/packages/mermaid/.madgerc b/packages/mermaid/.madgerc new file mode 100644 index 000000000..1a558d9e6 --- /dev/null +++ b/packages/mermaid/.madgerc @@ -0,0 +1,22 @@ +{ + "detectiveOptions": { + "ts": { + "skipTypeImports": true + }, + "es6": { + "skipTypeImports": true + } + }, + "fileExtensions": [ + "js", + "ts" + ], + "excludeRegExp": [ + "node_modules", + "docs", + "vitepress", + "detector", + "Detector" + ], + "tsConfig": "./tsconfig.json" +} diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index c069672b5..7b4de70a9 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -1,14 +1,15 @@ { "name": "mermaid", - "version": "10.0.0-rc.3", + "version": "10.4.0", "description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "type": "module", "module": "./dist/mermaid.core.mjs", "types": "./dist/mermaid.d.ts", "exports": { ".": { + "types": "./dist/mermaid.d.ts", "import": "./dist/mermaid.core.mjs", - "types": "./dist/mermaid.d.ts" + "default": "./dist/mermaid.core.mjs" }, "./*": "./*" }, @@ -23,14 +24,21 @@ ], "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 && ts-node-esm src/docs.mts", - "docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm src/docs.mts --verify", - "docs:pre:vitepress": "rimraf src/vitepress && pnpm docs:code && ts-node-esm src/docs.mts --vitepress", - "docs:build:vitepress": "pnpm docs:pre:vitepress && vitepress build src/vitepress && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing", - "docs:dev": "pnpm docs:pre:vitepress && concurrently \"vitepress dev src/vitepress\" \"ts-node-esm src/docs.mts --watch --vitepress\"", + "docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts", + "docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts --verify", + "docs:pre:vitepress": "pnpm --filter ./src/docs prefetch && rimraf src/vitepress && pnpm docs:code && ts-node-esm 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\" \"ts-node-esm scripts/docs.cli.mts --watch --vitepress\"", + "docs:dev:docker": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev:docker\" \"ts-node-esm scripts/docs.cli.mts --watch --vitepress\"", "docs:serve": "pnpm docs:build:vitepress && vitepress serve src/vitepress", "docs:spellcheck": "cspell --config ../../cSpell.json \"src/docs/**/*.md\"", + "docs:release-version": "ts-node-esm scripts/update-release-version.mts", + "docs:verify-version": "ts-node-esm scripts/update-release-version.mts --verify", + "types:build-config": "ts-node-esm --transpileOnly scripts/create-types-from-json-schema.mts", + "types:verify-config": "ts-node-esm scripts/create-types-from-json-schema.mts --verify", + "checkCircle": "npx madge --circular ./src", "release": "pnpm build", "prepublishOnly": "cpy '../../README.*' ./ --cwd=. && pnpm -w run build" }, @@ -51,62 +59,78 @@ ] }, "dependencies": { - "@braintree/sanitize-url": "^6.0.0", + "@braintree/sanitize-url": "^6.0.1", + "@types/d3-scale": "^4.0.3", + "@types/d3-scale-chromatic": "^3.0.0", "cytoscape": "^3.23.0", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.1.0", "d3": "^7.4.0", - "dagre-d3-es": "7.0.8", - "dompurify": "2.4.3", + "d3-sankey": "^0.12.3", + "dagre-d3-es": "7.0.10", + "dayjs": "^1.11.7", + "dompurify": "^3.0.5", "elkjs": "^0.8.2", "khroma": "^2.0.0", "lodash-es": "^4.17.21", - "moment-mini": "^2.29.4", + "mdast-util-from-markdown": "^1.3.0", "non-layered-tidy-tree-layout": "^2.0.2", - "stylis": "^4.1.2", + "stylis": "^4.1.3", "ts-dedent": "^2.2.0", "uuid": "^9.0.0", "web-worker": "^1.2.0" }, "devDependencies": { + "@adobe/jsonschema2md": "^7.1.4", "@types/cytoscape": "^3.19.9", "@types/d3": "^7.4.0", - "@types/dompurify": "^2.4.0", - "@types/jsdom": "^21.0.0", - "@types/lodash-es": "^4.17.6", + "@types/d3-sankey": "^0.12.1", + "@types/d3-scale": "^4.0.3", + "@types/d3-selection": "^3.0.5", + "@types/d3-shape": "^3.1.1", + "@types/dompurify": "^3.0.2", + "@types/jsdom": "^21.1.1", + "@types/lodash-es": "^4.17.7", "@types/micromatch": "^4.0.2", - "@types/prettier": "^2.7.1", + "@types/prettier": "^2.7.2", "@types/stylis": "^4.0.2", - "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^5.42.1", - "@typescript-eslint/parser": "^5.42.1", + "@types/uuid": "^9.0.1", + "@typescript-eslint/eslint-plugin": "^5.59.0", + "@typescript-eslint/parser": "^5.59.0", + "ajv": "^8.11.2", "chokidar": "^3.5.3", - "concurrently": "^7.5.0", - "coveralls": "^3.1.1", + "concurrently": "^8.0.1", "cpy-cli": "^4.2.0", - "cspell": "^6.14.3", - "globby": "^13.1.2", + "cspell": "^6.31.1", + "csstree-validator": "^3.0.0", + "globby": "^13.1.4", "jison": "^0.4.18", - "js-base64": "^3.7.2", - "jsdom": "^21.0.0", + "js-base64": "^3.7.5", + "jsdom": "^22.0.0", + "json-schema-to-typescript": "^11.0.3", "micromatch": "^4.0.5", "path-browserify": "^1.0.1", - "prettier": "^2.7.1", + "prettier": "^2.8.8", "remark": "^14.0.2", "remark-frontmatter": "^4.0.1", "remark-gfm": "^3.0.1", - "rimraf": "^4.0.0", - "start-server-and-test": "^1.14.0", - "typedoc": "^0.23.18", - "typedoc-plugin-markdown": "^3.13.6", - "typescript": "^4.8.4", + "rimraf": "^5.0.0", + "start-server-and-test": "^2.0.0", + "type-fest": "^4.1.0", + "typedoc": "^0.25.0", + "typedoc-plugin-markdown": "^3.15.2", + "typescript": "^5.0.4", "unist-util-flatmap": "^1.0.0", - "vitepress": "^1.0.0-alpha.46", - "vitepress-plugin-search": "^1.0.4-alpha.19" + "unist-util-visit": "^4.1.2", + "vitepress": "^1.0.0-alpha.72", + "vitepress-plugin-search": "^1.0.4-alpha.20" }, "files": [ - "dist", + "dist/", "README.md" ], - "sideEffects": false + "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 new file mode 100644 index 000000000..836aaa448 --- /dev/null +++ b/packages/mermaid/scripts/create-types-from-json-schema.mts @@ -0,0 +1,254 @@ +/** + * Script to load Mermaid Config JSON Schema from YAML and to: + * + * - Validate JSON Schema + * + * Then to generate: + * + * - config.types.ts TypeScript file + */ + +/* eslint-disable no-console */ + +import { readFile, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import assert from 'node:assert'; +import { execFile } from 'node:child_process'; +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; + +// !!! -- The config.type.js file is created by this script -- !!! +import type { MermaidConfig } from '../src/config.type.js'; + +// options for running the main command +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', + 'requirement', + 'mindmap', + 'timeline', + 'gitGraph', + 'c4', + 'sankey', +]; + +/** + * Loads the MermaidConfig JSON schema YAML file. + * + * @returns The loaded JSON Schema, use {@link validateSchema} to confirm it is a valid JSON Schema. + */ +async function loadJsonSchemaFromYaml() { + const configSchemaFile = join('src', 'schemas', 'config.schema.yaml'); + const contentsYaml = await readFile(configSchemaFile, { encoding: 'utf8' }); + const jsonSchema = load(contentsYaml, { + filename: configSchemaFile, + // only allow JSON types in our YAML doc (will probably be default in YAML 1.3) + // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`. + schema: JSON_SCHEMA, + }); + return jsonSchema; +} + +/** + * Asserts that the given value is a valid JSON Schema object. + * + * @param jsonSchema - The value to validate as JSON Schema 2019-09 + * @throws {Error} if the given object is invalid. + */ +function validateSchema(jsonSchema: unknown): asserts jsonSchema is JSONSchemaType { + if (typeof jsonSchema !== 'object') { + throw new Error(`jsonSchema param is not an object: actual type is ${typeof jsonSchema}`); + } + if (jsonSchema === null) { + throw new Error('jsonSchema param must not be null'); + } + const ajv = new Ajv2019({ + allErrors: true, + allowUnionTypes: true, + strict: true, + }); + + ajv.addKeyword({ + keyword: 'meta:enum', // used by jsonschema2md (in docs.mts script) + errors: false, + }); + ajv.addKeyword({ + keyword: 'tsType', // used by json-schema-to-typescript + errors: false, + }); + + ajv.compile(jsonSchema); +} + +/** + * Generate a typescript definition from a JSON Schema using json-schema-to-typescript. + * + * @param mermaidConfigSchema - The input JSON Schema. + */ +async function generateTypescript(mermaidConfigSchema: JSONSchemaType) { + /** + * Replace all usages of `allOf` with `extends`. + * + * `extends` is only valid JSON Schema in very old versions of JSON Schema. + * However, json-schema-to-typescript creates much nicer types when using + * `extends`, so we should use them instead when possible. + * + * @param schema - The input schema. + * @returns The schema with `allOf` replaced with `extends`. + */ + function replaceAllOfWithExtends(schema: JSONSchemaType>) { + if (schema['allOf']) { + const { allOf, ...schemaWithoutAllOf } = schema; + return { + ...schemaWithoutAllOf, + extends: allOf, + }; + } + return schema; + } + + /** + * For backwards compatibility with older Mermaid Typescript defs, + * we need to make all value optional instead of required. + * + * This is because the `MermaidConfig` type is used as an input, and everything is optional, + * since all the required values have default values.s + * + * In the future, we should make make the input to Mermaid `Partial`. + * + * @todo TODO: Remove this function when Mermaid releases a new breaking change. + * @param schema - The input schema. + * @returns The schema with all required values removed. + */ + function removeRequired(schema: JSONSchemaType>) { + return { ...schema, required: [] }; + } + + /** + * This is a temporary hack to control the order the types are generated in. + * + * By default, json-schema-to-typescript outputs the $defs in the order they + * are used, then any unused schemas at the end. + * + * **The only purpose of this function is to make the `git diff` simpler** + * **We should remove this later to simplify the code** + * + * @todo TODO: Remove this function in a future PR. + * @param schema - The input schema. + * @returns The schema with all `$ref`s removed. + */ + function unrefSubschemas(schema: 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)), + + $defs: Object.fromEntries( + Object.entries(mermaidConfigSchema.$defs).map(([key, subSchema]) => { + return [key, removeRequired(replaceAllOfWithExtends(subSchema))]; + }) + ), + }; + + const typescriptFile = await compile( + modifiedSchema as JSONSchema, // json-schema-to-typescript only allows JSON Schema 4 as input type + 'MermaidConfig', + { + additionalProperties: false, // in JSON Schema 2019-09, these are called `unevaluatedProperties` + unreachableDefinitions: true, // definition for FontConfig is unreachable + style: (await prettier.resolveConfig('.')) ?? {}, + } + ); + + // TODO, should we somehow use the functions from `docs.mts` instead? + if (verifyOnly) { + const originalFile = await readFile('./src/config.type.ts', { encoding: 'utf-8' }); + if (typescriptFile !== originalFile) { + console.error('❌ Error: ./src/config.type.ts will be changed.'); + console.error("Please run 'pnpm run --filter mermaid types:build-config' to update this"); + process.exitCode = 1; + } else { + console.log('✅ ./src/config.type.ts will be unchanged'); + } + } else { + console.log('Writing typescript file to ./src/config.type.ts'); + await writeFile('./src/config.type.ts', typescriptFile, { encoding: 'utf8' }); + if (git) { + console.log('📧 Git: Adding ./src/config.type.ts changed'); + await promisify(execFile)('git', ['add', './src/config.type.ts']); + } + } +} + +/** Main function */ +async function main() { + if (verifyOnly) { + console.log( + 'Verifying that ./src/config.type.ts is in sync with src/schemas/config.schema.yaml' + ); + } + + const configJsonSchema = await loadJsonSchemaFromYaml(); + + validateSchema(configJsonSchema); + + // Generate types from JSON Schema + await generateTypescript(configJsonSchema); +} + +main().catch((error) => { + console.error(error); + process.exitCode = 1; +}); diff --git a/packages/mermaid/scripts/docs.cli.mts b/packages/mermaid/scripts/docs.cli.mts new file mode 100644 index 000000000..067eec1c5 --- /dev/null +++ b/packages/mermaid/scripts/docs.cli.mts @@ -0,0 +1,3 @@ +import { processDocs } from './docs.mjs'; + +void processDocs(); diff --git a/packages/mermaid/src/docs.mts b/packages/mermaid/scripts/docs.mts similarity index 71% rename from packages/mermaid/src/docs.mts rename to packages/mermaid/scripts/docs.mts index 7f3ab4e8b..3689cb68b 100644 --- a/packages/mermaid/src/docs.mts +++ b/packages/mermaid/scripts/docs.mts @@ -27,14 +27,21 @@ * get their absolute paths. Ensures that the location of those 2 directories is not dependent on * where this file resides. * - * @todo Write a test file for this. (Will need to be able to deal .mts file. Jest has trouble with - * it.) */ +// @ts-ignore: we're importing internal jsonschema2md functions +import { default as schemaLoader } from '@adobe/jsonschema2md/lib/schemaProxy.js'; +// @ts-ignore: we're importing internal jsonschema2md functions +import { default as traverseSchemas } from '@adobe/jsonschema2md/lib/traverseSchema.js'; +// @ts-ignore: we're importing internal jsonschema2md functions +import { default as buildMarkdownFromSchema } from '@adobe/jsonschema2md/lib/markdownBuilder.js'; +// @ts-ignore: we're importing internal jsonschema2md functions +import { default as jsonSchemaReadmeBuilder } from '@adobe/jsonschema2md/lib/readmeBuilder.js'; import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync, rmdirSync } from 'fs'; import { exec } from 'child_process'; import { globby } from 'globby'; import { JSDOM } from 'jsdom'; -import type { Code, Root } from 'mdast'; +import { dump, load, JSON_SCHEMA } from 'js-yaml'; +import type { Code, ListItem, Root, Text, YAML } from 'mdast'; import { posix, dirname, relative, join } from 'path'; import prettier from 'prettier'; import { remark } from 'remark'; @@ -44,10 +51,11 @@ import chokidar from 'chokidar'; import mm from 'micromatch'; // @ts-ignore No typescript declaration file import flatmap from 'unist-util-flatmap'; +import { visit } from 'unist-util-visit'; -const MERMAID_MAJOR_VERSION = ( - JSON.parse(readFileSync('../mermaid/package.json', 'utf8')).version as string -).split('.')[0]; +export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8')) + .version as string; +const MERMAID_MAJOR_VERSION = MERMAID_RELEASE_VERSION.split('.')[0]; const CDN_URL = 'https://cdn.jsdelivr.net/npm'; // 'https://unpkg.com'; const MERMAID_KEYWORD = 'mermaid'; @@ -70,7 +78,7 @@ const vitepress: boolean = process.argv.includes('--vitepress'); const noHeader: boolean = process.argv.includes('--noHeader') || vitepress; // These paths are from the root of the mono-repo, not from the mermaid subdirectory -const SOURCE_DOCS_DIR = 'src/docs'; +export const SOURCE_DOCS_DIR = 'src/docs'; const FINAL_DOCS_DIR = vitepress ? 'src/vitepress' : '../../docs'; const LOGMSG_TRANSFORMED = 'transformed'; @@ -122,7 +130,7 @@ const changeToFinalDocDir = (file: string): string => { const logWasOrShouldBeTransformed = (filename: string, wasCopied: boolean) => { const changeMsg = wasCopied ? LOGMSG_TRANSFORMED : LOGMSG_TO_BE_TRANSFORMED; let logMsg: string; - logMsg = ` File ${changeMsg}: ${filename}`; + logMsg = ` File ${changeMsg}: ${filename.replace(FINAL_DOCS_DIR, SOURCE_DOCS_DIR)}`; if (wasCopied) { logMsg += LOGMSG_COPIED; } @@ -150,13 +158,14 @@ const copyTransformedContents = (filename: string, doCopy = false, transformedCo } filesTransformed.add(fileInFinalDocDir); + if (doCopy) { writeFileSync(fileInFinalDocDir, newBuffer); } logWasOrShouldBeTransformed(fileInFinalDocDir, doCopy); }; -const readSyncedUTF8file = (filename: string): string => { +export const readSyncedUTF8file = (filename: string): string => { return readFileSync(filename, 'utf8'); }; @@ -207,6 +216,8 @@ interface TransformMarkdownAstOptions { originalFilename: string; /** If `true`, add a warning that the file is autogenerated */ addAutogeneratedWarning?: boolean; + /** If `true`, adds an `editLink: "https://..."` YAML frontmatter field */ + addEditLink?: boolean; /** * If `true`, remove the YAML metadata from the Markdown input. * Generally, YAML metadata is only used for Vitepress. @@ -229,6 +240,7 @@ interface TransformMarkdownAstOptions { export function transformMarkdownAst({ originalFilename, addAutogeneratedWarning, + addEditLink, removeYAML, }: TransformMarkdownAstOptions) { return (tree: Root, _file?: any): Root => { @@ -268,6 +280,27 @@ export function transformMarkdownAst({ } } + if (addEditLink) { + // add originalFilename as custom editLink in YAML frontmatter + let yamlFrontMatter: YAML; + if (astWithTransformedBlocks.children[0].type === 'yaml') { + yamlFrontMatter = astWithTransformedBlocks.children[0]; + } else { + yamlFrontMatter = { + type: 'yaml', + value: '', + }; + astWithTransformedBlocks.children.unshift(yamlFrontMatter); + } + const filePathFromRoot = posix.join('packages/mermaid', originalFilename); + yamlFrontMatter.value = dump({ + ...(load(yamlFrontMatter.value, { schema: JSON_SCHEMA }) as + | Record + | undefined), + editLink: `https://github.com/mermaid-js/mermaid/edit/develop/${filePathFromRoot}`, + }); + } + if (removeYAML) { const firstNode = astWithTransformedBlocks.children[0]; if (firstNode.type == 'yaml') { @@ -304,6 +337,7 @@ const transformMarkdown = (file: string) => { // mermaid project specific plugin originalFilename: file, addAutogeneratedWarning: !noHeader, + addEditLink: noHeader, removeYAML: !noHeader, }) .processSync(doc) @@ -321,6 +355,115 @@ const transformMarkdown = (file: string) => { copyTransformedContents(file, !verifyOnly, formatted); }; +/** + * Transforms the given JSON Schema into Markdown documentation + */ +async function transformJsonSchema(file: string) { + const yamlContents = readSyncedUTF8file(file); + const jsonSchema = load(yamlContents, { + filename: file, + // only allow JSON types in our YAML doc (will probably be default in YAML 1.3) + // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`. + schema: JSON_SCHEMA, + }); + + /** Location of the `schema.yaml` files */ + const SCHEMA_INPUT_DIR = 'src/schemas/'; + /** + * Location to store the generated `schema.json` file for the website + * + * Because Vitepress doesn't handle bundling `.json` files properly, we need + * to instead place it into a `public/` subdirectory. + */ + const SCHEMA_OUTPUT_DIR = 'src/docs/public/schemas/'; + const VITEPRESS_PUBLIC_DIR = 'src/docs/public'; + /** + * Location to store the generated Schema Markdown docs. + * Links to JSON Schemas should automatically be rewritten to point to + * `SCHEMA_OUTPUT_DIR`. + */ + const SCHEMA_MARKDOWN_OUTPUT_DIR = join('src', 'docs', 'config', 'schema-docs'); + + // write .schema.json files + const jsonFileName = file + .replace('.schema.yaml', '.schema.json') + .replace(SCHEMA_INPUT_DIR, SCHEMA_OUTPUT_DIR); + copyTransformedContents(jsonFileName, !verifyOnly, JSON.stringify(jsonSchema, undefined, 2)); + + const schemas = traverseSchemas([schemaLoader()(jsonFileName, jsonSchema)]); + + // ignore output of this function + // for some reason, without calling this function, we get some broken links + // this is probably a bug in @adobe/jsonschema2md + jsonSchemaReadmeBuilder({ readme: true })(schemas); + + // write Markdown files + const markdownFiles = buildMarkdownFromSchema({ + header: true, + // links, + includeProperties: ['tsType'], // Custom TypeScript type + exampleFormat: 'json', + // skipProperties, + /** + * Automatically rewrite schema paths passed to `schemaLoader` + * (e.g. src/docs/schemas/config.schema.json) + * to relative links (e.g. /schemas/config.schema.json) + * + * See https://vitepress.vuejs.org/guide/asset-handling + * + * @param origin - Original schema path (relative to this script). + * @returns New absolute Vitepress path to schema + */ + rewritelinks: (origin: string) => { + return `/${relative(VITEPRESS_PUBLIC_DIR, origin)}`; + }, + })(schemas); + + for (const [name, markdownAst] of Object.entries(markdownFiles)) { + /* + * Converts list entries of shape '- tsType: () => Partial' + * into '- tsType: `() => Partial`' (e.g. escaping with back-ticks), + * as otherwise VitePress doesn't like the bit. + */ + visit(markdownAst as Root, 'listItem', (listEntry: ListItem) => { + let listText: Text; + const blockItem = listEntry.children[0]; + if (blockItem.type === 'paragraph' && blockItem.children[0].type === 'text') { + listText = blockItem.children[0]; + } // @ts-expect-error: MD AST output from @adobe/jsonschema2md is technically wrong + else if (blockItem.type === 'text') { + listText = blockItem; + } else { + return; // skip + } + + if (listText.value.startsWith('tsType: ')) { + listText.value = listText.value.replace(/tsType: (.*)/g, 'tsType: `$1`'); + } + }); + + const transformer = remark() + .use(remarkGfm) + .use(remarkFrontmatter, ['yaml']) // support YAML front-matter in Markdown + .use(transformMarkdownAst, { + // mermaid project specific plugin + originalFilename: file, + addAutogeneratedWarning: !noHeader, + addEditLink: noHeader, + removeYAML: !noHeader, + }); + + const transformed = transformer.stringify(await transformer.run(markdownAst as Root)); + + const formatted = prettier.format(transformed, { + parser: 'markdown', + ...prettierConfig, + }); + const newFileName = join(SCHEMA_MARKDOWN_OUTPUT_DIR, `${name}.md`); + copyTransformedContents(newFileName, !verifyOnly, formatted); + } +} + /** * Transform an HTML file and write the transformed file to the directory for published * documentation @@ -361,20 +504,26 @@ const transformHtml = (filename: string) => { copyTransformedContents(filename, !verifyOnly, formattedHTML); }; -const getGlobs = (globs: string[]): string[] => { - globs.push('!**/dist', '!**/redirect.spec.ts', '!**/landing'); +export const getGlobs = (globs: string[]): string[] => { + globs.push('!**/dist/**', '!**/redirect.spec.ts', '!**/landing/**', '!**/node_modules/**'); if (!vitepress) { - globs.push('!**/.vitepress', '!**/vite.config.ts', '!src/docs/index.md'); + globs.push( + '!**/.vitepress/**', + '!**/vite.config.ts', + '!src/docs/index.md', + '!**/package.json', + '!**/user-avatars/**' + ); } return globs; }; -const getFilesFromGlobs = async (globs: string[]): Promise => { +export const getFilesFromGlobs = async (globs: string[]): Promise => { return await globby(globs, { dot: true }); }; /** Main method (entry point) */ -const main = async () => { +export const processDocs = async () => { if (verifyOnly) { console.log('Verifying that all files are in sync with the source files'); } @@ -382,6 +531,14 @@ const main = async () => { const sourceDirGlob = posix.join('.', SOURCE_DOCS_DIR, '**'); const action = verifyOnly ? 'Verifying' : 'Transforming'; + if (vitepress) { + console.log(`${action} 1 .schema.yaml file`); + await transformJsonSchema('src/schemas/config.schema.yaml'); + } else { + // skip because this creates so many Markdown files that it lags git + console.log('Skipping 1 .schema.yaml file'); + } + const mdFileGlobs = getGlobs([posix.join(sourceDirGlob, '*.md')]); const mdFiles = await getFilesFromGlobs(mdFileGlobs); console.log(`${action} ${mdFiles.length} markdown files...`); @@ -444,5 +601,3 @@ const main = async () => { }); } }; - -void main(); diff --git a/packages/mermaid/src/docs.spec.ts b/packages/mermaid/scripts/docs.spec.ts similarity index 90% rename from packages/mermaid/src/docs.spec.ts rename to packages/mermaid/scripts/docs.spec.ts index 50feaee6a..c84bc1bac 100644 --- a/packages/mermaid/src/docs.spec.ts +++ b/packages/mermaid/scripts/docs.spec.ts @@ -105,6 +105,29 @@ This Markdown should be kept. }); }); + it('should add an editLink in the YAML frontmatter if `addEditLink: true`', async () => { + const contents = `--- +title: Flowcharts Syntax +--- + +This Markdown should be kept. +`; + const withYaml = ( + await remarkBuilder() + .use(transformMarkdownAst, { originalFilename, addEditLink: true }) + .process(contents) + ).toString(); + expect(withYaml).toEqual(`--- +title: Flowcharts Syntax +editLink: >- + https://github.com/mermaid-js/mermaid/edit/develop/packages/mermaid/example-input-filename.md + +--- + +This Markdown should be kept. +`); + }); + describe('transformToBlockQuote', () => { // TODO Is there a way to test this with --vitepress given as a process argument? diff --git a/packages/mermaid/scripts/update-release-version.mts b/packages/mermaid/scripts/update-release-version.mts new file mode 100644 index 000000000..7f292f21b --- /dev/null +++ b/packages/mermaid/scripts/update-release-version.mts @@ -0,0 +1,53 @@ +/* eslint-disable no-console */ + +/** + * @file Update the MERMAID_RELEASE_VERSION placeholder in the documentation source files with the current version of mermaid. + * So contributors adding new features will only have to add the placeholder and not worry about updating the version number. + * + */ +import { posix } from 'path'; +import { + getGlobs, + getFilesFromGlobs, + SOURCE_DOCS_DIR, + readSyncedUTF8file, + MERMAID_RELEASE_VERSION, +} from './docs.mjs'; +import { writeFile } from 'fs/promises'; + +const verifyOnly: boolean = process.argv.includes('--verify'); +const versionPlaceholder = ''; + +const main = async () => { + const sourceDirGlob = posix.join('.', SOURCE_DOCS_DIR, '**'); + const mdFileGlobs = getGlobs([posix.join(sourceDirGlob, '*.md')]); + mdFileGlobs.push('!**/community/development.md'); + const mdFiles = await getFilesFromGlobs(mdFileGlobs); + mdFiles.sort(); + const mdFilesWithPlaceholder: string[] = []; + for (const mdFile of mdFiles) { + const content = readSyncedUTF8file(mdFile); + if (content.includes(versionPlaceholder)) { + mdFilesWithPlaceholder.push(mdFile); + } + } + + if (mdFilesWithPlaceholder.length === 0) { + return; + } + + if (verifyOnly) { + console.log( + `${mdFilesWithPlaceholder.length} file(s) were found with the placeholder ${versionPlaceholder}. Run \`pnpm --filter mermaid docs:release-version\` to update them.` + ); + process.exit(1); + } + + for (const mdFile of mdFilesWithPlaceholder) { + const content = readSyncedUTF8file(mdFile); + const newContent = content.replace(versionPlaceholder, MERMAID_RELEASE_VERSION); + await writeFile(mdFile, newContent); + } +}; + +void main(); diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index 3a0818854..308e141d0 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -1,17 +1,26 @@ -import * as configApi from './config'; -import { log } from './logger'; -import { getDiagram, registerDiagram } from './diagram-api/diagramAPI'; -import { detectType, getDiagramLoader } from './diagram-api/detectType'; -import { extractFrontMatter } from './diagram-api/frontmatter'; -import { UnknownDiagramError } from './errors'; -import { DetailedError } from './utils'; +import * as configApi from './config.js'; +import { log } from './logger.js'; +import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js'; +import { detectType, getDiagramLoader } from './diagram-api/detectType.js'; +import { extractFrontMatter } from './diagram-api/frontmatter.js'; +import { UnknownDiagramError } from './errors.js'; +import { cleanupComments } from './diagram-api/comments.js'; +import type { DetailedError } from './utils.js'; +import type { DiagramDefinition } from './diagram-api/types.js'; export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void; + +/** + * An object representing a parsed mermaid diagram definition. + * @privateRemarks This is exported as part of the public mermaidAPI. + */ export class Diagram { type = 'graph'; - parser; - renderer; - db; + parser: DiagramDefinition['parser']; + renderer: DiagramDefinition['renderer']; + db: DiagramDefinition['db']; + private init?: DiagramDefinition['init']; + private detectError?: UnknownDiagramError; constructor(public text: string) { this.text += '\n'; @@ -26,7 +35,6 @@ export class Diagram { log.debug('Type ' + this.type); // Setup diagram this.db = diagram.db; - this.db.clear?.(); this.renderer = diagram.renderer; this.parser = diagram.parser; const originalParse = this.parser.parse.bind(this.parser); @@ -38,12 +46,12 @@ export class Diagram { // Similarly, we can't do this in getDiagramFromText() because some code // calls diagram.db.clear(), which would reset anything set by // extractFrontMatter(). - this.parser.parse = (text: string) => originalParse(extractFrontMatter(text, this.db)); + + this.parser.parse = (text: string) => + originalParse(cleanupComments(extractFrontMatter(text, this.db, configApi.addDirective))); + this.parser.parser.yy = this.db; - if (diagram.init) { - diagram.init(cnf); - log.info('Initialized diagram ' + this.type, cnf); - } + this.init = diagram.init; this.parse(); } @@ -52,6 +60,7 @@ export class Diagram { throw this.detectError; } this.db.clear?.(); + this.init?.(configApi.getConfig()); this.parser.parse(this.text); } @@ -68,8 +77,17 @@ export class Diagram { } } -export const getDiagramFromText = async (txt: string): Promise => { - const type = detectType(txt, configApi.getConfig()); +/** + * Parse the text asynchronously and generate a Diagram object asynchronously. + * **Warning:** This function may be changed in the future. + * @alpha + * @param text - The mermaid diagram definition. + * @returns A the Promise of a Diagram object. + * @throws {@link UnknownDiagramError} if the diagram type can not be found. + * @privateRemarks This is exported as part of the public mermaidAPI. + */ +export const getDiagramFromText = async (text: string): Promise => { + const type = detectType(text, configApi.getConfig()); try { // Trying to find the diagram getDiagram(type); @@ -78,10 +96,10 @@ export const getDiagramFromText = async (txt: string): Promise => { if (!loader) { throw new UnknownDiagramError(`Diagram ${type} not found.`); } - // Diagram not available, loading it + // Diagram not available, loading it. // new diagram will try getDiagram again and if fails then it is a valid throw const { id, diagram } = await loader(); registerDiagram(id, diagram); } - return new Diagram(txt); + return new Diagram(text); }; diff --git a/packages/mermaid/src/__mocks__/mermaidAPI.ts b/packages/mermaid/src/__mocks__/mermaidAPI.ts index 95b87d990..a2d19ef24 100644 --- a/packages/mermaid/src/__mocks__/mermaidAPI.ts +++ b/packages/mermaid/src/__mocks__/mermaidAPI.ts @@ -3,9 +3,9 @@ * * We can't easily use `vi.spyOn(mermaidAPI, "function")` since the object is frozen with `Object.freeze()`. */ -import * as configApi from '../config'; +import * as configApi from '../config.js'; import { vi } from 'vitest'; -import { mermaidAPI as mAPI } from '../mermaidAPI'; +import { mermaidAPI as mAPI } from '../mermaidAPI.js'; // original version cannot be modified since it was frozen with `Object.freeze()` export const mermaidAPI = { diff --git a/packages/mermaid/src/accessibility.spec.ts b/packages/mermaid/src/accessibility.spec.ts index 60415ea37..7745e02ef 100644 --- a/packages/mermaid/src/accessibility.spec.ts +++ b/packages/mermaid/src/accessibility.spec.ts @@ -1,27 +1,24 @@ -import { MockedD3 } from './tests/MockedD3'; -import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility'; -import { D3Element } from './mermaidAPI'; +import { MockedD3 } from './tests/MockedD3.js'; +import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js'; +import type { D3Element } from './mermaidAPI.js'; describe('accessibility', () => { - const fauxSvgNode = new MockedD3(); + const fauxSvgNode: MockedD3 = new MockedD3(); describe('setA11yDiagramInfo', () => { - it('sets the svg element role to "graphics-document document"', () => { - // @ts-ignore Required to easily handle the d3 select types + it('should set svg element role to "graphics-document document"', () => { const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode); setA11yDiagramInfo(fauxSvgNode, 'flowchart'); expect(svgAttrSpy).toHaveBeenCalledWith('role', 'graphics-document document'); }); - it('sets the aria-roledescription to the diagram type', () => { - // @ts-ignore Required to easily handle the d3 select types + it('should set aria-roledescription to the diagram type', () => { const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode); setA11yDiagramInfo(fauxSvgNode, 'flowchart'); expect(svgAttrSpy).toHaveBeenCalledWith('aria-roledescription', 'flowchart'); }); - it('does not set the aria-roledescription if the diagram type is empty', () => { - // @ts-ignore Required to easily handle the d3 select types + it('should not set aria-roledescription if the diagram type is empty', () => { const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode); setA11yDiagramInfo(fauxSvgNode, ''); expect(svgAttrSpy).toHaveBeenCalledTimes(1); @@ -32,8 +29,8 @@ describe('accessibility', () => { describe('addSVGa11yTitleDescription', () => { const givenId = 'theBaseId'; - describe('with the given svg d3 object:', () => { - it('does nothing if there is no insert defined', () => { + describe('with svg d3 object', () => { + it('should do nothing if there is no insert defined', () => { const noInsertSvg = { attr: vi.fn(), }; @@ -42,28 +39,25 @@ describe('accessibility', () => { expect(noInsertAttrSpy).not.toHaveBeenCalled(); }); - // ---------------- - // Convenience functions to DRY up the spec + // convenience functions to DRY up the spec - function expectAriaLabelledByIsTitleId( + function expectAriaLabelledByItTitleId( svgD3Node: D3Element, - title: string | null | undefined, - desc: string | null | undefined, + title: string | undefined, + desc: string | undefined, givenId: string - ) { - // @ts-ignore Required to easily handle the d3 select types + ): void { const svgAttrSpy = vi.spyOn(svgD3Node, 'attr').mockReturnValue(svgD3Node); addSVGa11yTitleDescription(svgD3Node, title, desc, givenId); expect(svgAttrSpy).toHaveBeenCalledWith('aria-labelledby', `chart-title-${givenId}`); } - function expectAriaDescribedByIsDescId( + function expectAriaDescribedByItDescId( svgD3Node: D3Element, - title: string | null | undefined, - desc: string | null | undefined, + title: string | undefined, + desc: string | undefined, givenId: string - ) { - // @ts-ignore Required to easily handle the d3 select types + ): void { const svgAttrSpy = vi.spyOn(svgD3Node, 'attr').mockReturnValue(svgD3Node); addSVGa11yTitleDescription(svgD3Node, title, desc, givenId); expect(svgAttrSpy).toHaveBeenCalledWith('aria-describedby', `chart-desc-${givenId}`); @@ -71,154 +65,148 @@ describe('accessibility', () => { function a11yTitleTagInserted( svgD3Node: D3Element, - title: string | null | undefined, - desc: string | null | undefined, + title: string | undefined, + desc: string | undefined, givenId: string, callNumber: number - ) { + ): void { a11yTagInserted(svgD3Node, title, desc, givenId, callNumber, 'title', title); } function a11yDescTagInserted( svgD3Node: D3Element, - title: string | null | undefined, - desc: string | null | undefined, + title: string | undefined, + desc: string | undefined, givenId: string, callNumber: number - ) { + ): void { a11yTagInserted(svgD3Node, title, desc, givenId, callNumber, 'desc', desc); } function a11yTagInserted( - svgD3Node: D3Element, - title: string | null | undefined, - desc: string | null | undefined, + _svgD3Node: D3Element, + title: string | undefined, + desc: string | undefined, givenId: string, callNumber: number, expectedPrefix: string, - expectedText: string | null | undefined - ) { - const fauxInsertedD3 = new MockedD3(); - const svgInsertSpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxInsertedD3); - // @ts-ignore Required to easily handle the d3 select types + expectedText: string | undefined + ): void { + const fauxInsertedD3: MockedD3 = new MockedD3(); + const svginsertpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxInsertedD3); const titleAttrSpy = vi.spyOn(fauxInsertedD3, 'attr').mockReturnValue(fauxInsertedD3); const titleTextSpy = vi.spyOn(fauxInsertedD3, 'text'); addSVGa11yTitleDescription(fauxSvgNode, title, desc, givenId); - expect(svgInsertSpy).toHaveBeenCalledWith(expectedPrefix, ':first-child'); + expect(svginsertpy).toHaveBeenCalledWith(expectedPrefix, ':first-child'); expect(titleAttrSpy).toHaveBeenCalledWith('id', `chart-${expectedPrefix}-${givenId}`); expect(titleTextSpy).toHaveBeenNthCalledWith(callNumber, expectedText); } - // ---------------- - describe('given an a11y title', () => { + describe('with a11y title', () => { const a11yTitle = 'a11y title'; - describe('given an a11y description', () => { + describe('with a11y description', () => { const a11yDesc = 'a11y description'; - it('sets aria-labelledby to the title id inserted as a child', () => { - expectAriaLabelledByIsTitleId(fauxSvgNode, a11yTitle, a11yDesc, givenId); + it('shold set aria-labelledby to the title id inserted as a child', () => { + expectAriaLabelledByItTitleId(fauxSvgNode, a11yTitle, a11yDesc, givenId); }); - it('sets aria-describedby to the description id inserted as a child', () => { - expectAriaDescribedByIsDescId(fauxSvgNode, a11yTitle, a11yDesc, givenId); + it('should set aria-describedby to the description id inserted as a child', () => { + expectAriaDescribedByItDescId(fauxSvgNode, a11yTitle, a11yDesc, givenId); }); - it('inserts a title tag as the first child with the text set to the accTitle given', () => { + it('should insert title tag as the first child with the text set to the accTitle given', () => { a11yTitleTagInserted(fauxSvgNode, a11yTitle, a11yDesc, givenId, 2); }); - it('inserts a desc tag as the 2nd child with the text set to accDescription given', () => { + it('should insert desc tag as the 2nd child with the text set to accDescription given', () => { a11yDescTagInserted(fauxSvgNode, a11yTitle, a11yDesc, givenId, 1); }); }); - describe(`no a11y description`, () => { + describe(`without a11y description`, () => { const a11yDesc = undefined; - it('sets aria-labelledby to the title id inserted as a child', () => { - expectAriaLabelledByIsTitleId(fauxSvgNode, a11yTitle, a11yDesc, givenId); + it('should set aria-labelledby to the title id inserted as a child', () => { + expectAriaLabelledByItTitleId(fauxSvgNode, a11yTitle, a11yDesc, givenId); }); - it('no aria-describedby is set', () => { - // @ts-ignore Required to easily handle the d3 select types + it('should not set aria-describedby', () => { const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); expect(svgAttrSpy).not.toHaveBeenCalledWith('aria-describedby', expect.anything()); }); - it('inserts a title tag as the first child with the text set to the accTitle given', () => { + it('should insert title tag as the first child with the text set to the accTitle given', () => { a11yTitleTagInserted(fauxSvgNode, a11yTitle, a11yDesc, givenId, 1); }); - it('no description tag is inserted', () => { - const fauxTitle = new MockedD3(); - const svgInsertSpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxTitle); + it('should not insert description tag', () => { + const fauxTitle: MockedD3 = new MockedD3(); + const svginsertpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxTitle); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); - expect(svgInsertSpy).not.toHaveBeenCalledWith('desc', ':first-child'); + expect(svginsertpy).not.toHaveBeenCalledWith('desc', ':first-child'); }); }); }); - describe('no a11y title', () => { + describe('without a11y title', () => { const a11yTitle = undefined; - describe('given an a11y description', () => { + describe('with a11y description', () => { const a11yDesc = 'a11y description'; - it('no aria-labelledby is set', () => { - // @ts-ignore Required to easily handle the d3 select types + it('should not set aria-labelledby', () => { const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); expect(svgAttrSpy).not.toHaveBeenCalledWith('aria-labelledby', expect.anything()); }); - it('no title tag inserted', () => { - const fauxTitle = new MockedD3(); - const svgInsertSpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxTitle); + it('should not insert title tag', () => { + const fauxTitle: MockedD3 = new MockedD3(); + const svginsertpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxTitle); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); - expect(svgInsertSpy).not.toHaveBeenCalledWith('title', ':first-child'); + expect(svginsertpy).not.toHaveBeenCalledWith('title', ':first-child'); }); - it('sets aria-describedby to the description id inserted as a child', () => { - expectAriaDescribedByIsDescId(fauxSvgNode, a11yTitle, a11yDesc, givenId); + it('should set aria-describedby to the description id inserted as a child', () => { + expectAriaDescribedByItDescId(fauxSvgNode, a11yTitle, a11yDesc, givenId); }); - it('inserts a desc tag as the 2nd child with the text set to accDescription given', () => { + it('should insert desc tag as the 2nd child with the text set to accDescription given', () => { a11yDescTagInserted(fauxSvgNode, a11yTitle, a11yDesc, givenId, 1); }); }); - describe('no a11y description', () => { + describe('without a11y description', () => { const a11yDesc = undefined; - it('no aria-labelledby is set', () => { - // @ts-ignore Required to easily handle the d3 select types + it('should not set aria-labelledby', () => { const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); expect(svgAttrSpy).not.toHaveBeenCalledWith('aria-labelledby', expect.anything()); }); - it('no aria-describedby is set', () => { - // @ts-ignore Required to easily handle the d3 select types + it('should not set aria-describedby', () => { const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); expect(svgAttrSpy).not.toHaveBeenCalledWith('aria-describedby', expect.anything()); }); - it('no title tag inserted', () => { - const fauxTitle = new MockedD3(); - const svgInsertSpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxTitle); + it('should not insert title tag', () => { + const fauxTitle: MockedD3 = new MockedD3(); + const svginsertpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxTitle); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); - expect(svgInsertSpy).not.toHaveBeenCalledWith('title', ':first-child'); + expect(svginsertpy).not.toHaveBeenCalledWith('title', ':first-child'); }); - it('no description tag inserted', () => { - const fauxDesc = new MockedD3(); - const svgInsertSpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxDesc); + it('should not insert description tag', () => { + const fauxDesc: MockedD3 = new MockedD3(); + const svginsertpy = vi.spyOn(fauxSvgNode, 'insert').mockReturnValue(fauxDesc); addSVGa11yTitleDescription(fauxSvgNode, a11yTitle, a11yDesc, givenId); - expect(svgInsertSpy).not.toHaveBeenCalledWith('desc', ':first-child'); + expect(svginsertpy).not.toHaveBeenCalledWith('desc', ':first-child'); }); }); }); diff --git a/packages/mermaid/src/accessibility.ts b/packages/mermaid/src/accessibility.ts index 8e073aa76..69e22b301 100644 --- a/packages/mermaid/src/accessibility.ts +++ b/packages/mermaid/src/accessibility.ts @@ -1,13 +1,11 @@ /** - * Accessibility (a11y) functions, types, helpers + * Accessibility (a11y) functions, types, helpers. + * * @see https://www.w3.org/WAI/ * @see https://www.w3.org/TR/wai-aria-1.1/ * @see https://www.w3.org/TR/svg-aam-1.0/ - * */ -import { D3Element } from './mermaidAPI'; - -import isEmpty from 'lodash-es/isEmpty.js'; +import type { D3Element } from './mermaidAPI.js'; /** * SVG element role: @@ -21,50 +19,47 @@ import isEmpty from 'lodash-es/isEmpty.js'; const SVG_ROLE = 'graphics-document document'; /** - * Add role and aria-roledescription to the svg element + * Add role and aria-roledescription to the svg element. * * @param svg - d3 object that contains the SVG HTML element * @param diagramType - diagram name for to the aria-roledescription */ -export function setA11yDiagramInfo(svg: D3Element, diagramType: string | null | undefined) { +export function setA11yDiagramInfo(svg: D3Element, diagramType: string) { svg.attr('role', SVG_ROLE); - if (!isEmpty(diagramType)) { + if (diagramType !== '') { svg.attr('aria-roledescription', diagramType); } } + /** * Add an accessible title and/or description element to a chart. * The title is usually not displayed and the description is never displayed. * - * The following charts display their title as a visual and accessibility element: gantt + * The following charts display their title as a visual and accessibility element: gantt. * * @param svg - d3 node to insert the a11y title and desc info - * @param a11yTitle - a11y title. null and undefined are meaningful: means to skip it - * @param a11yDesc - a11y description. null and undefined are meaningful: means to skip it + * @param a11yTitle - a11y title. undefined or empty strings mean to skip them + * @param a11yDesc - a11y description. undefined or empty strings mean to skip them * @param baseId - id used to construct the a11y title and description id */ export function addSVGa11yTitleDescription( svg: D3Element, - a11yTitle: string | null | undefined, - a11yDesc: string | null | undefined, + a11yTitle: string | undefined, + a11yDesc: string | undefined, baseId: string -) { +): void { if (svg.insert === undefined) { return; } - if (a11yTitle || a11yDesc) { - if (a11yDesc) { - const descId = 'chart-desc-' + baseId; - svg.attr('aria-describedby', descId); - svg.insert('desc', ':first-child').attr('id', descId).text(a11yDesc); - } - if (a11yTitle) { - const titleId = 'chart-title-' + baseId; - svg.attr('aria-labelledby', titleId); - svg.insert('title', ':first-child').attr('id', titleId).text(a11yTitle); - } - } else { - return; + if (a11yDesc) { + const descId = `chart-desc-${baseId}`; + svg.attr('aria-describedby', descId); + svg.insert('desc', ':first-child').attr('id', descId).text(a11yDesc); + } + if (a11yTitle) { + const titleId = `chart-title-${baseId}`; + svg.attr('aria-labelledby', titleId); + svg.insert('title', ':first-child').attr('id', titleId).text(a11yTitle); } } diff --git a/packages/mermaid/src/assignWithDepth.js b/packages/mermaid/src/assignWithDepth.ts similarity index 65% rename from packages/mermaid/src/assignWithDepth.js rename to packages/mermaid/src/assignWithDepth.ts index 898481c30..125b6f434 100644 --- a/packages/mermaid/src/assignWithDepth.js +++ b/packages/mermaid/src/assignWithDepth.ts @@ -1,32 +1,36 @@ -'use strict'; +/* eslint-disable @typescript-eslint/no-explicit-any */ + /** - * @function assignWithDepth Extends the functionality of {@link ObjectConstructor.assign} with the + * assignWithDepth Extends the functionality of {@link Object.assign} with the * ability to merge arbitrary-depth objects For each key in src with path `k` (recursively) * performs an Object.assign(dst[`k`], src[`k`]) with a slight change from the typical handling of - * undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to {} and + * undefined for dst[`k`]: instead of raising an error, dst[`k`] is auto-initialized to `{}` and * effectively merged with src[`k`]

Additionally, dissimilar types will not clobber unless the * config.clobber parameter === true. Example: * - * ```js - * let config_0 = { foo: { bar: 'bar' }, bar: 'foo' }; - * let config_1 = { foo: 'foo', bar: 'bar' }; - * let result = assignWithDepth(config_0, config_1); - * console.log(result); - * //-> result: { foo: { bar: 'bar' }, bar: 'bar' } - * ``` + * ``` + * const config_0 = { foo: { bar: 'bar' }, bar: 'foo' }; + * const config_1 = { foo: 'foo', bar: 'bar' }; + * const result = assignWithDepth(config_0, config_1); + * console.log(result); + * //-> result: { foo: { bar: 'bar' }, bar: 'bar' } + * ``` * * Traditional Object.assign would have clobbered foo in config_0 with foo in config_1. If src is a * destructured array of objects and dst is not an array, assignWithDepth will apply each element * of src to dst in order. - * @param {any} dst - The destination of the merge - * @param {any} src - The source object(s) to merge into destination - * @param {{ depth: number; clobber: boolean }} [config={ depth: 2, clobber: false }] - Depth: depth - * to traverse within src and dst for merging - clobber: should dissimilar types clobber (default: - * { depth: 2, clobber: false }). Default is `{ depth: 2, clobber: false }` - * @returns {any} + * @param dst - The destination of the merge + * @param src - The source object(s) to merge into destination + * @param config - + * * depth: depth to traverse within src and dst for merging + * * clobber: should dissimilar types clobber */ -const assignWithDepth = function (dst, src, config) { - const { depth, clobber } = Object.assign({ depth: 2, clobber: false }, config); +const assignWithDepth = ( + dst: any, + src: any, + { depth = 2, clobber = false }: { depth?: number; clobber?: boolean } = {} +): any => { + const config: { depth: number; clobber: boolean } = { depth, clobber }; if (Array.isArray(src) && !Array.isArray(dst)) { src.forEach((s) => assignWithDepth(dst, s, config)); return dst; diff --git a/packages/mermaid/src/commonDb.ts b/packages/mermaid/src/commonDb.ts deleted file mode 100644 index 42ffde004..000000000 --- a/packages/mermaid/src/commonDb.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { sanitizeText as _sanitizeText } from './diagrams/common/common'; -import { getConfig } from './config'; -let title = ''; -let diagramTitle = ''; -let description = ''; -const sanitizeText = (txt: string): string => _sanitizeText(txt, getConfig()); - -export const clear = function (): void { - title = ''; - description = ''; - diagramTitle = ''; -}; - -export const setAccTitle = function (txt: string): void { - title = sanitizeText(txt).replace(/^\s+/g, ''); -}; - -export const getAccTitle = function (): string { - return title || diagramTitle; -}; - -export const setAccDescription = function (txt: string): void { - description = sanitizeText(txt).replace(/\n\s+/g, '\n'); -}; - -export const getAccDescription = function (): string { - return description; -}; - -export const setDiagramTitle = function (txt: string): void { - diagramTitle = sanitizeText(txt); -}; - -export const getDiagramTitle = function (): string { - return diagramTitle; -}; - -export default { - setAccTitle, - getAccTitle, - setDiagramTitle, - getDiagramTitle: getDiagramTitle, - getAccDescription, - setAccDescription, - clear, -}; diff --git a/packages/mermaid/src/config.spec.js b/packages/mermaid/src/config.spec.js deleted file mode 100644 index b104f37cc..000000000 --- a/packages/mermaid/src/config.spec.js +++ /dev/null @@ -1,56 +0,0 @@ -import * as configApi from './config'; - -describe('when working with site config', function () { - beforeEach(() => { - // Resets the site config to default config - configApi.setSiteConfig({}); - }); - it('should set site config and config properly', function () { - let config_0 = { foo: 'bar', bar: 0 }; - configApi.setSiteConfig(config_0); - let config_1 = configApi.getSiteConfig(); - let config_2 = configApi.getConfig(); - expect(config_1.foo).toEqual(config_0.foo); - expect(config_1.bar).toEqual(config_0.bar); - expect(config_1).toEqual(config_2); - }); - it('should respect secure keys when applying directives', function () { - let config_0 = { - foo: 'bar', - bar: 'cant-be-changed', - secure: [...configApi.defaultConfig.secure, 'bar'], - }; - configApi.setSiteConfig(config_0); - const directive = { foo: 'baf', bar: 'should-not-be-allowed' }; - const cfg = configApi.updateCurrentConfig(config_0, [directive]); - expect(cfg.foo).toEqual(directive.foo); - expect(cfg.bar).toBe(config_0.bar); - }); - it('should set reset config properly', function () { - let config_0 = { foo: 'bar', bar: 0 }; - configApi.setSiteConfig(config_0); - let config_1 = { foo: 'baf' }; - configApi.setConfig(config_1); - let config_2 = configApi.getConfig(); - expect(config_2.foo).toEqual(config_1.foo); - configApi.reset(); - let config_3 = configApi.getConfig(); - expect(config_3.foo).toEqual(config_0.foo); - let config_4 = configApi.getSiteConfig(); - expect(config_4.foo).toEqual(config_0.foo); - }); - it('should set global reset config properly', function () { - let config_0 = { foo: 'bar', bar: 0 }; - configApi.setSiteConfig(config_0); - let config_1 = configApi.getSiteConfig(); - expect(config_1.foo).toEqual(config_0.foo); - let config_2 = configApi.getConfig(); - expect(config_2.foo).toEqual(config_0.foo); - configApi.setConfig({ foobar: 'bar0' }); - let config_3 = configApi.getConfig(); - expect(config_3.foobar).toEqual('bar0'); - configApi.reset(); - let config_4 = configApi.getConfig(); - expect(config_4.foobar).toBeUndefined(); - }); -}); diff --git a/packages/mermaid/src/config.spec.ts b/packages/mermaid/src/config.spec.ts new file mode 100644 index 000000000..8dd4ff33c --- /dev/null +++ b/packages/mermaid/src/config.spec.ts @@ -0,0 +1,81 @@ +/* eslint-disable @typescript-eslint/no-non-null-assertion */ +import * as configApi from './config.js'; +import type { MermaidConfig } from './config.type.js'; + +describe('when working with site config', () => { + beforeEach(() => { + // Resets the site config to default config + configApi.setSiteConfig({}); + }); + it('should set site config and config properly', () => { + const config_0 = { fontFamily: 'foo-font', fontSize: 150 }; + configApi.setSiteConfig(config_0); + const config_1 = configApi.getSiteConfig(); + const config_2 = configApi.getConfig(); + expect(config_1.fontFamily).toEqual(config_0.fontFamily); + expect(config_1.fontSize).toEqual(config_0.fontSize); + expect(config_1).toEqual(config_2); + }); + it('should respect secure keys when applying directives', () => { + const config_0: MermaidConfig = { + fontFamily: 'foo-font', + securityLevel: 'strict', // can't be changed + fontSize: 12345, // can't be changed + secure: [...configApi.defaultConfig.secure!, 'fontSize'], + }; + configApi.setSiteConfig(config_0); + const directive: MermaidConfig = { + fontFamily: 'baf', + // fontSize and securityLevel shouldn't be changed + fontSize: 54321, + securityLevel: 'loose', + }; + const cfg: MermaidConfig = configApi.updateCurrentConfig(config_0, [directive]); + expect(cfg.fontFamily).toEqual(directive.fontFamily); + expect(cfg.fontSize).toBe(config_0.fontSize); + expect(cfg.securityLevel).toBe(config_0.securityLevel); + }); + it('should allow setting partial options', () => { + const defaultConfig = configApi.getConfig(); + + configApi.setConfig({ + quadrantChart: { + chartHeight: 600, + }, + }); + + const updatedConfig = configApi.getConfig(); + + // deep options we didn't update should remain the same + expect(defaultConfig.quadrantChart!.chartWidth).toEqual( + updatedConfig.quadrantChart!.chartWidth + ); + }); + it('should set reset config properly', () => { + const config_0 = { fontFamily: 'foo-font', fontSize: 150 }; + configApi.setSiteConfig(config_0); + const config_1 = { fontFamily: 'baf' }; + configApi.setConfig(config_1); + const config_2 = configApi.getConfig(); + expect(config_2.fontFamily).toEqual(config_1.fontFamily); + configApi.reset(); + const config_3 = configApi.getConfig(); + expect(config_3.fontFamily).toEqual(config_0.fontFamily); + const config_4 = configApi.getSiteConfig(); + expect(config_4.fontFamily).toEqual(config_0.fontFamily); + }); + it('should set global reset config properly', () => { + const config_0 = { fontFamily: 'foo-font', fontSize: 150 }; + configApi.setSiteConfig(config_0); + const config_1 = configApi.getSiteConfig(); + expect(config_1.fontFamily).toEqual(config_0.fontFamily); + const config_2 = configApi.getConfig(); + expect(config_2.fontFamily).toEqual(config_0.fontFamily); + configApi.setConfig({ altFontFamily: 'bar-font' }); + const config_3 = configApi.getConfig(); + expect(config_3.altFontFamily).toEqual('bar-font'); + configApi.reset(); + const config_4 = configApi.getConfig(); + expect(config_4.altFontFamily).toBeUndefined(); + }); +}); diff --git a/packages/mermaid/src/config.ts b/packages/mermaid/src/config.ts index 8750c8fa5..eb24b6268 100644 --- a/packages/mermaid/src/config.ts +++ b/packages/mermaid/src/config.ts @@ -1,17 +1,18 @@ -import assignWithDepth from './assignWithDepth'; -import { log } from './logger'; -import theme from './themes'; -import config from './defaultConfig'; -import type { MermaidConfig } from './config.type'; +import assignWithDepth from './assignWithDepth.js'; +import { log } from './logger.js'; +import theme from './themes/index.js'; +import config from './defaultConfig.js'; +import type { MermaidConfig } from './config.type.js'; +import { sanitizeDirective } from './utils.js'; export const defaultConfig: MermaidConfig = Object.freeze(config); let siteConfig: MermaidConfig = assignWithDepth({}, defaultConfig); let configFromInitialize: MermaidConfig; -let directives: any[] = []; +let directives: MermaidConfig[] = []; let currentConfig: MermaidConfig = assignWithDepth({}, defaultConfig); -export const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: any[]) => { +export const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: MermaidConfig[]) => { // start with config being the siteConfig let cfg: MermaidConfig = assignWithDepth({}, siteCfg); // let sCfg = assignWithDepth(defaultConfig, siteConfigDelta); @@ -20,7 +21,6 @@ export const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: any[]) let sumOfDirectives: MermaidConfig = {}; for (const d of _directives) { sanitize(d); - // Apply the data from the directive where the the overrides the themeVariables sumOfDirectives = assignWithDepth(sumOfDirectives, d); } @@ -111,12 +111,6 @@ export const getSiteConfig = (): MermaidConfig => { * @returns The currentConfig merged with the sanitized conf */ export const setConfig = (conf: MermaidConfig): MermaidConfig => { - // sanitize(conf); - // Object.keys(conf).forEach(key => { - // const manipulator = manipulators[key]; - // conf[key] = manipulator ? manipulator(conf[key]) : conf[key]; - // }); - checkConfig(conf); assignWithDepth(currentConfig, conf); @@ -150,9 +144,12 @@ export const getConfig = (): MermaidConfig => { * @param options - The potential setConfig parameter */ export const sanitize = (options: any) => { + if (!options) { + return; + } // Checking that options are not in the list of excluded options ['secure', ...(siteConfig.secure ?? [])].forEach((key) => { - if (options[key] !== undefined) { + if (Object.hasOwn(options, key)) { // DO NOT attempt to print options[key] within `${}` as a malicious script // can exploit the logger's attempt to stringify the value and execute arbitrary code log.debug(`Denied attempt to modify a secure key ${key}`, options[key]); @@ -162,7 +159,7 @@ export const sanitize = (options: any) => { // Check that there no attempts of prototype pollution Object.keys(options).forEach((key) => { - if (key.indexOf('__') === 0) { + if (key.startsWith('__')) { delete options[key]; } }); @@ -188,16 +185,14 @@ export const sanitize = (options: any) => { * * @param directive - The directive to push in */ -export const addDirective = (directive: any) => { - if (directive.fontFamily) { - if (!directive.themeVariables) { - directive.themeVariables = { fontFamily: directive.fontFamily }; - } else { - if (!directive.themeVariables.fontFamily) { - directive.themeVariables = { fontFamily: directive.fontFamily }; - } - } +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 }; } + directives.push(directive); updateCurrentConfig(siteConfig, directives); }; @@ -226,9 +221,11 @@ export const reset = (config = siteConfig): void => { updateCurrentConfig(config, directives); }; -enum ConfigWarning { - 'LAZY_LOAD_DEPRECATED' = 'The configuration options lazyLoadedDiagrams and loadExternalDiagramsAtStartup are deprecated. Please use registerExternalDiagrams instead.', -} +const ConfigWarning = { + LAZY_LOAD_DEPRECATED: + 'The configuration options lazyLoadedDiagrams and loadExternalDiagramsAtStartup are deprecated. Please use registerExternalDiagrams instead.', +} as const; + type ConfigWarningStrings = keyof typeof ConfigWarning; const issuedWarnings: { [key in ConfigWarningStrings]?: boolean } = {}; const issueWarning = (warning: ConfigWarningStrings) => { @@ -243,6 +240,7 @@ const checkConfig = (config: MermaidConfig) => { if (!config) { return; } + // @ts-expect-error Properties were removed in v10. Warning should exist. if (config.lazyLoadedDiagrams || config.loadExternalDiagramsAtStartup) { issueWarning('LAZY_LOAD_DEPRECATED'); } diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 474075824..ca55d9af4 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -1,26 +1,144 @@ -// TODO: This was auto generated from defaultConfig. Needs to be verified. +/* eslint-disable */ +/** + * This file was automatically generated by json-schema-to-typescript. + * DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file, + * and run json-schema-to-typescript to regenerate this file. + */ -import DOMPurify from 'dompurify'; +/** + * Configuration options to pass to the `dompurify` library. + */ +export type DOMPurifyConfiguration = import('dompurify').Config; +/** + * JavaScript function that returns a `FontConfig`. + * + * By default, these return the appropriate `*FontSize`, `*FontFamily`, `*FontWeight` + * values. + * + * For example, the font calculator called `boundaryFont` might be defined as: + * + * ```javascript + * boundaryFont: function () { + * return { + * fontFamily: this.boundaryFontFamily, + * fontSize: this.boundaryFontSize, + * fontWeight: this.boundaryFontWeight, + * }; + * } + * ``` + * + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "FontCalculator". + */ +export type FontCalculator = () => Partial; +/** + * Picks the color of the sankey diagram links, using the colors of the source and/or target of the links. + * + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "SankeyLinkColor". + */ +export type SankeyLinkColor = 'source' | 'target' | 'gradient'; +/** + * Controls the alignment of the Sankey diagrams. + * + * See . + * + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "SankeyNodeAlignment". + */ +export type SankeyNodeAlignment = 'left' | 'right' | 'center' | 'justify'; +/** + * The font size to use + */ +export type CSSFontSize = string | number; export interface MermaidConfig { - /** @deprecated use mermaid.registerLazyDiagrams instead */ - lazyLoadedDiagrams?: string[]; - /** @deprecated use mermaid.registerLazyDiagrams instead */ - loadExternalDiagramsAtStartup?: boolean; - theme?: string; + /** + * Theme, the CSS style sheet. + * You may also use `themeCSS` to override this value. + * + */ + theme?: string | 'default' | 'forest' | 'dark' | 'neutral' | 'null'; themeVariables?: any; themeCSS?: string; + /** + * The maximum allowed size of the users text diagram + */ maxTextSize?: number; darkMode?: boolean; htmlLabels?: boolean; + /** + * Specifies the font to be used in the rendered diagrams. + * Can be any possible CSS `font-family`. + * See https://developer.mozilla.org/en-US/docs/Web/CSS/font-family + * + */ fontFamily?: string; altFontFamily?: string; - logLevel?: number; - securityLevel?: string; + /** + * This option decides the amount of logging to be used by mermaid. + * + */ + logLevel?: + | number + | string + | 0 + | 2 + | 1 + | 'trace' + | 'debug' + | 'info' + | 'warn' + | 'error' + | 'fatal' + | 3 + | 4 + | 5 + | undefined; + /** + * Level of trust for parsed diagram + */ + securityLevel?: string | 'strict' | 'loose' | 'antiscript' | 'sandbox' | undefined; + /** + * Dictates whether mermaid starts on Page load + */ startOnLoad?: 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 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`. + * + * This prevents malicious graph directives from overriding a site's default security. + * + */ secure?: string[]; + /** + * This option controls if the generated ids of nodes in the SVG are + * generated randomly or based on a seed. + * If set to `false`, the IDs are generated based on the current date and + * thus are not deterministic. This is the default behavior. + * + * This matters if your files are checked into source control e.g. git and + * should not change unless content is changed. + * + */ deterministicIds?: boolean; + /** + * This option is the optional seed for deterministic ids. + * If set to `undefined` but deterministicIds is `true`, a simple number iterator is used. + * You can set this attribute to base the seed on a static string. + * + */ deterministicIDSeed?: string; flowchart?: FlowchartDiagramConfig; sequence?: SequenceDiagramConfig; @@ -31,99 +149,347 @@ export interface MermaidConfig { state?: StateDiagramConfig; er?: ErDiagramConfig; pie?: PieDiagramConfig; + quadrantChart?: QuadrantChartConfig; requirement?: RequirementDiagramConfig; mindmap?: MindmapDiagramConfig; gitGraph?: GitGraphDiagramConfig; c4?: C4DiagramConfig; - dompurifyConfig?: DOMPurify.Config; + sankey?: SankeyDiagramConfig; + dompurifyConfig?: DOMPurifyConfiguration; wrap?: boolean; fontSize?: number; } - -// TODO: More configs needs to be moved in here +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "BaseDiagramConfig". + */ export interface BaseDiagramConfig { useWidth?: number; + /** + * When this flag is set to `true`, the height and width is set to 100% + * and is then scaled with the available space. + * If set to `false`, the absolute space required is used. + * + */ useMaxWidth?: boolean; } - +/** + * The object containing configurations specific for c4 diagrams + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "C4DiagramConfig". + */ export interface C4DiagramConfig 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 shapes + */ c4ShapeMargin?: number; + /** + * Padding between shapes + */ c4ShapePadding?: number; + /** + * Width of person boxes + */ width?: number; + /** + * Height of person boxes + */ height?: number; + /** + * Margin around boxes + */ boxMargin?: number; + /** + * How many shapes to place in each row. + */ c4ShapeInRow?: number; nextLinePaddingX?: number; + /** + * How many boundaries to place in each row. + */ c4BoundaryInRow?: number; + /** + * This sets the font size of Person shape for the diagram + */ personFontSize?: string | number; + /** + * This sets the font weight of Person shape for the diagram + */ personFontFamily?: string; + /** + * This sets the font weight of Person shape for the diagram + */ personFontWeight?: string | number; + /** + * This sets the font size of External Person shape for the diagram + */ external_personFontSize?: string | number; + /** + * This sets the font family of External Person shape for the diagram + */ external_personFontFamily?: string; + /** + * This sets the font weight of External Person shape for the diagram + */ external_personFontWeight?: string | number; + /** + * This sets the font size of System shape for the diagram + */ systemFontSize?: string | number; + /** + * This sets the font family of System shape for the diagram + */ systemFontFamily?: string; + /** + * This sets the font weight of System shape for the diagram + */ systemFontWeight?: string | number; + /** + * This sets the font size of External System shape for the diagram + */ external_systemFontSize?: string | number; + /** + * This sets the font family of External System shape for the diagram + */ external_systemFontFamily?: string; + /** + * This sets the font weight of External System shape for the diagram + */ external_systemFontWeight?: string | number; + /** + * This sets the font size of System DB shape for the diagram + */ system_dbFontSize?: string | number; + /** + * This sets the font family of System DB shape for the diagram + */ system_dbFontFamily?: string; + /** + * This sets the font weight of System DB shape for the diagram + */ system_dbFontWeight?: string | number; + /** + * This sets the font size of External System DB shape for the diagram + */ external_system_dbFontSize?: string | number; + /** + * This sets the font family of External System DB shape for the diagram + */ external_system_dbFontFamily?: string; + /** + * This sets the font weight of External System DB shape for the diagram + */ external_system_dbFontWeight?: string | number; + /** + * This sets the font size of System Queue shape for the diagram + */ system_queueFontSize?: string | number; + /** + * This sets the font family of System Queue shape for the diagram + */ system_queueFontFamily?: string; + /** + * This sets the font weight of System Queue shape for the diagram + */ system_queueFontWeight?: string | number; + /** + * This sets the font size of External System Queue shape for the diagram + */ external_system_queueFontSize?: string | number; + /** + * This sets the font family of External System Queue shape for the diagram + */ external_system_queueFontFamily?: string; + /** + * This sets the font weight of External System Queue shape for the diagram + */ external_system_queueFontWeight?: string | number; + /** + * This sets the font size of Boundary shape for the diagram + */ boundaryFontSize?: string | number; + /** + * This sets the font family of Boundary shape for the diagram + */ boundaryFontFamily?: string; + /** + * This sets the font weight of Boundary shape for the diagram + */ boundaryFontWeight?: string | number; + /** + * This sets the font size of Message shape for the diagram + */ messageFontSize?: string | number; + /** + * This sets the font family of Message shape for the diagram + */ messageFontFamily?: string; + /** + * This sets the font weight of Message shape for the diagram + */ messageFontWeight?: string | number; + /** + * This sets the font size of Container shape for the diagram + */ containerFontSize?: string | number; + /** + * This sets the font family of Container shape for the diagram + */ containerFontFamily?: string; + /** + * This sets the font weight of Container shape for the diagram + */ containerFontWeight?: string | number; + /** + * This sets the font size of External Container shape for the diagram + */ external_containerFontSize?: string | number; + /** + * This sets the font family of External Container shape for the diagram + */ external_containerFontFamily?: string; + /** + * This sets the font weight of External Container shape for the diagram + */ external_containerFontWeight?: string | number; + /** + * This sets the font size of Container DB shape for the diagram + */ container_dbFontSize?: string | number; + /** + * This sets the font family of Container DB shape for the diagram + */ container_dbFontFamily?: string; + /** + * This sets the font weight of Container DB shape for the diagram + */ container_dbFontWeight?: string | number; + /** + * This sets the font size of External Container DB shape for the diagram + */ external_container_dbFontSize?: string | number; + /** + * This sets the font family of External Container DB shape for the diagram + */ external_container_dbFontFamily?: string; + /** + * This sets the font weight of External Container DB shape for the diagram + */ external_container_dbFontWeight?: string | number; + /** + * This sets the font size of Container Queue shape for the diagram + */ container_queueFontSize?: string | number; + /** + * This sets the font family of Container Queue shape for the diagram + */ container_queueFontFamily?: string; + /** + * This sets the font weight of Container Queue shape for the diagram + */ container_queueFontWeight?: string | number; + /** + * This sets the font size of External Container Queue shape for the diagram + */ external_container_queueFontSize?: string | number; + /** + * This sets the font family of External Container Queue shape for the diagram + */ external_container_queueFontFamily?: string; + /** + * This sets the font weight of External Container Queue shape for the diagram + */ external_container_queueFontWeight?: string | number; + /** + * This sets the font size of Component shape for the diagram + */ componentFontSize?: string | number; + /** + * This sets the font family of Component shape for the diagram + */ componentFontFamily?: string; + /** + * This sets the font weight of Component shape for the diagram + */ componentFontWeight?: string | number; + /** + * This sets the font size of External Component shape for the diagram + */ external_componentFontSize?: string | number; + /** + * This sets the font family of External Component shape for the diagram + */ external_componentFontFamily?: string; + /** + * This sets the font weight of External Component shape for the diagram + */ external_componentFontWeight?: string | number; + /** + * This sets the font size of Component DB shape for the diagram + */ component_dbFontSize?: string | number; + /** + * This sets the font family of Component DB shape for the diagram + */ component_dbFontFamily?: string; + /** + * This sets the font weight of Component DB shape for the diagram + */ component_dbFontWeight?: string | number; + /** + * This sets the font size of External Component DB shape for the diagram + */ external_component_dbFontSize?: string | number; + /** + * This sets the font family of External Component DB shape for the diagram + */ external_component_dbFontFamily?: string; + /** + * This sets the font weight of External Component DB shape for the diagram + */ external_component_dbFontWeight?: string | number; + /** + * This sets the font size of Component Queue shape for the diagram + */ component_queueFontSize?: string | number; + /** + * This sets the font family of Component Queue shape for the diagram + */ component_queueFontFamily?: string; + /** + * This sets the font weight of Component Queue shape for the diagram + */ component_queueFontWeight?: string | number; + /** + * This sets the font size of External Component Queue shape for the diagram + */ external_component_queueFontSize?: string | number; + /** + * This sets the font family of External Component Queue shape for the diagram + */ external_component_queueFontFamily?: string; + /** + * This sets the font weight of External Component Queue shape for the diagram + */ external_component_queueFontWeight?: 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; person_bg_color?: string; person_border_color?: string; @@ -188,8 +554,14 @@ 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; @@ -198,16 +570,29 @@ export interface GitGraphDiagramConfig extends BaseDiagramConfig { showCommitLabel?: boolean; showBranches?: boolean; rotateCommitLabel?: 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; @@ -219,28 +604,163 @@ export interface RequirementDiagramConfig extends BaseDiagramConfig { 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 { - useMaxWidth: boolean; - padding: number; - maxNodeWidth: number; + padding?: number; + maxNodeWidth?: number; } - -export type PieDiagramConfig = BaseDiagramConfig; - +/** + * 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; +} +/** + * 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; - layoutDirection?: string; + /** + * Directional bias for layout of entities + */ + layoutDirection?: string | '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; @@ -252,143 +772,560 @@ export interface StateDiagramConfig extends BaseDiagramConfig { 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; - defaultRenderer?: string; + /** + * Decides which rendering engine that is to be used for the rendering. + * + */ + defaultRenderer?: string | '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; - defaultRenderer?: string; + /** + * Decides which rendering engine that is to be used for the rendering. + * + */ + defaultRenderer?: string | '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; - messageAlign?: string; + /** + * Multiline message alignment + */ + messageAlign?: string | '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; - messageAlign?: string; + /** + * Multiline message alignment + */ + messageAlign?: string | '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?: string | '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; - messageAlign?: string; + /** + * Multiline message alignment + */ + messageAlign?: string | '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; - noteAlign?: string; + /** + * This sets the text alignment of actor-attached notes + */ + noteAlign?: string | '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; 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; - curve?: string; + /** + * Defines how mermaid renders curves for flowcharts. + * + */ + curve?: string | 'basis' | 'linear' | 'cardinal'; + /** + * Represents the padding between the labels and the shape + * + * **Only used in new experimental rendering.** + * + */ padding?: number; - defaultRenderer?: string; + /** + * Decides which rendering engine that is to be used for the rendering. + * + */ + defaultRenderer?: string | '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. + * + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "SankeyDiagramConfig". + */ +export interface SankeyDiagramConfig extends BaseDiagramConfig { + width?: number; + height?: number; + /** + * The color of the links in the sankey diagram. + * + */ + linkColor?: SankeyLinkColor | string; + /** + * Controls the alignment of the Sankey diagrams. + * + * See . + * + */ + nodeAlignment?: 'left' | 'right' | 'center' | 'justify'; + useMaxWidth?: boolean; + /** + * Toggle to display or hide values along with title. + * + */ + showValues?: boolean; + /** + * The prefix to use for values + * + */ + prefix?: string; + /** + * The suffix to use for values + * + */ + suffix?: string; +} +/** + * This interface was referenced by `MermaidConfig`'s JSON-Schema + * via the `definition` "FontConfig". + */ export interface FontConfig { - fontSize?: string | number; + fontSize?: CSSFontSize; + /** + * The CSS [`font-family`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family) to use. + */ fontFamily?: string; + /** + * The font weight to use. + */ fontWeight?: string | number; } - -export type FontCalculator = () => Partial; - -export {}; diff --git a/packages/mermaid/src/dagre-wrapper/GraphObjects.md b/packages/mermaid/src/dagre-wrapper/GraphObjects.md index 184fc5137..840ddf824 100644 --- a/packages/mermaid/src/dagre-wrapper/GraphObjects.md +++ b/packages/mermaid/src/dagre-wrapper/GraphObjects.md @@ -1,6 +1,6 @@ # Cluster handling -Dagre does not support edges between nodes and clusters or between clusters to other clusters. In order to remedy this shortcoming the dagre wrapper implements a few work-arounds. +Dagre does not support edges between nodes and clusters or between clusters to other clusters. In order to remedy this shortcoming the dagre wrapper implements a few workarounds. In the diagram below there are two clusters and there are no edges to nodes outside the own cluster. @@ -73,7 +73,7 @@ Sample object: } ``` -This is set by the renderer of the diagram and insert the data that the wrapper neds for rendering. +This is set by the renderer of the diagram and insert the data that the wrapper needs for rendering. | property | description | | ---------- | ------------------------------------------------------------------------------------------------ | @@ -114,7 +114,7 @@ Required edgeData for proper rendering: | label | overlap between label and labelText? | | labelPos | | | labelType | overlap between label and labelText? | -| thickness | Sets the thinkess of the edge. Can be \['normal', 'thick'\] | +| thickness | Sets the thickness of the edge. Can be \['normal', 'thick'\] | | pattern | Sets the pattern of the edge. Can be \['solid', 'dotted', 'dashed'\] | # Markers diff --git a/packages/mermaid/src/dagre-wrapper/clusters.js b/packages/mermaid/src/dagre-wrapper/clusters.js index 57c3ff513..1ce716689 100644 --- a/packages/mermaid/src/dagre-wrapper/clusters.js +++ b/packages/mermaid/src/dagre-wrapper/clusters.js @@ -1,12 +1,13 @@ -import intersectRect from './intersect/intersect-rect'; -import { log } from '../logger'; -import createLabel from './createLabel'; +import intersectRect from './intersect/intersect-rect.js'; +import { log } from '../logger.js'; +import createLabel from './createLabel.js'; +import { createText } from '../rendering-util/createText.js'; import { select } from 'd3'; -import { getConfig } from '../config'; -import { evaluate } from '../diagrams/common/common'; +import { getConfig } from '../config.js'; +import { evaluate } from '../diagrams/common/common.js'; const rect = (parent, node) => { - log.trace('Creating subgraph rect for ', node.id, node); + log.info('Creating subgraph rect for ', node.id, node); // Add outer g element const shapeSvg = parent @@ -17,12 +18,18 @@ const rect = (parent, node) => { // add the rect const rect = shapeSvg.insert('rect', ':first-child'); + const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); + // Create the label and insert it after the rect const label = shapeSvg.insert('g').attr('class', 'cluster-label'); - const text = label - .node() - .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true)); + // const text = label + // .node() + // .appendChild(createLabel(node.labelText, node.labelStyle, undefined, true)); + const text = + node.labelType === 'markdown' + ? createText(label, node.labelText, { style: node.labelStyle, useHtmlLabels }) + : label.node().appendChild(createLabel(node.labelText, node.labelStyle, undefined, true)); // Get the size of the label let bbox = text.getBBox(); @@ -56,13 +63,20 @@ const rect = (parent, node) => { .attr('width', width) .attr('height', node.height + padding); + if (useHtmlLabels) { + label.attr( + 'transform', + // This puts the labal on top of the box instead of inside it + 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2) + ')' + ); + } else { + label.attr( + 'transform', + // This puts the labal on top of the box instead of inside it + 'translate(' + node.x + ', ' + (node.y - node.height / 2) + ')' + ); + } // Center the label - label.attr( - 'transform', - // This puts the labal on top of the box instead of inside it - // 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2 - bbox.height) + ')' - 'translate(' + (node.x - bbox.width / 2) + ', ' + (node.y - node.height / 2) + ')' - ); const rectBox = rect.node().getBBox(); node.width = rectBox.width; diff --git a/packages/mermaid/src/dagre-wrapper/createLabel.js b/packages/mermaid/src/dagre-wrapper/createLabel.js index af5032096..a8351c812 100644 --- a/packages/mermaid/src/dagre-wrapper/createLabel.js +++ b/packages/mermaid/src/dagre-wrapper/createLabel.js @@ -1,8 +1,8 @@ import { select } from 'd3'; -import { log } from '../logger'; -import { getConfig } from '../config'; -import { evaluate } from '../diagrams/common/common'; -import { decodeEntities } from '../mermaidAPI'; +import { log } from '../logger.js'; +import { getConfig } from '../config.js'; +import { evaluate } from '../diagrams/common/common.js'; +import { decodeEntities } from '../mermaidAPI.js'; /** * @param dom @@ -41,7 +41,13 @@ function addHtmlLabel(node) { 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 = (_vertexText, style, isTitle, isNode) => { let vertexText = _vertexText || ''; if (typeof vertexText === 'object') { diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js index 71183eab5..f89b4422b 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.js +++ b/packages/mermaid/src/dagre-wrapper/edges.js @@ -1,9 +1,10 @@ -import { log } from '../logger'; -import createLabel from './createLabel'; +import { log } from '../logger.js'; +import createLabel from './createLabel.js'; +import { createText } from '../rendering-util/createText.js'; import { line, curveBasis, select } from 'd3'; -import { getConfig } from '../config'; -import utils from '../utils'; -import { evaluate } from '../diagrams/common/common'; +import { getConfig } from '../config.js'; +import utils from '../utils.js'; +import { evaluate } from '../diagrams/common/common.js'; let edgeLabels = {}; let terminalLabels = {}; @@ -14,8 +15,17 @@ export const clear = () => { }; export const insertEdgeLabel = (elem, edge) => { + const useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); // Create the actual text element - const labelElement = createLabel(edge.label, edge.labelStyle); + const labelElement = + edge.labelType === 'markdown' + ? createText(elem, edge.label, { + style: edge.labelStyle, + useHtmlLabels, + addSvgBackground: true, + }) + : createLabel(edge.label, edge.labelStyle); + 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'); @@ -26,7 +36,7 @@ export const insertEdgeLabel = (elem, edge) => { // Center the label let bbox = labelElement.getBBox(); - if (evaluate(getConfig().flowchart.htmlLabels)) { + if (useHtmlLabels) { const div = labelElement.children[0]; const dv = select(labelElement); bbox = div.getBoundingClientRect(); @@ -358,7 +368,20 @@ const cutPathAtIntersect = (_points, boundryNode) => { return points; }; -//(edgePaths, e, edge, clusterDb, diagramtype, graph) +/** + * Calculate the deltas and angle between two points + * @param {{x: number, y:number}} point1 + * @param {{x: number, y:number}} point2 + * @returns {{angle: number, deltaX: number, deltaY: number}} + */ +function calculateDeltaAndAngle(point1, point2) { + const [x1, y1] = [point1.x, point1.y]; + const [x2, y2] = [point2.x, point2.y]; + const deltaX = x2 - x1; + const deltaY = y2 - y1; + return { angle: Math.atan(deltaY / deltaX), deltaX, deltaY }; +} + export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph) { let points = edge.points; let pointsHasChanged = false; @@ -425,22 +448,62 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph const lineData = points.filter((p) => !Number.isNaN(p.y)); // This is the accessor function we talked about above - let curve; + let curve = curveBasis; // Currently only flowcharts get the curve from the settings, perhaps this should // be expanded to a common setting? Restricting it for now in order not to cause side-effects that // have not been thought through - if (diagramType === 'graph' || diagramType === 'flowchart') { - curve = edge.curve || curveBasis; - } else { - curve = curveBasis; + if (edge.curve && (diagramType === 'graph' || diagramType === 'flowchart')) { + curve = edge.curve; } - // curve = curveLinear; + + // We need to draw the lines a bit shorter to avoid drawing + // under any transparent markers. + // The offsets are calculated from the markers' dimensions. + const markerOffsets = { + aggregation: 18, + extension: 18, + composition: 18, + dependency: 6, + lollipop: 13.5, + arrow_point: 5.3, + }; + const lineFunction = line() - .x(function (d) { - return d.x; + .x(function (d, i, data) { + let offset = 0; + 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] * Math.cos(angle) * (deltaX >= 0 ? 1 : -1) || 0; + } 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] + ); + offset = markerOffsets[edge.arrowTypeEnd] * Math.cos(angle) * (deltaX >= 0 ? 1 : -1) || 0; + } + return d.x + offset; }) - .y(function (d) { - return d.y; + .y(function (d, i, data) { + // Same handling as X above + let offset = 0; + if (i === 0 && Object.hasOwn(markerOffsets, edge.arrowTypeStart)) { + const { angle, deltaY } = calculateDeltaAndAngle(data[0], data[1]); + offset = + markerOffsets[edge.arrowTypeStart] * Math.abs(Math.sin(angle)) * (deltaY >= 0 ? 1 : -1); + } else if (i === data.length - 1 && Object.hasOwn(markerOffsets, edge.arrowTypeEnd)) { + const { angle, deltaY } = calculateDeltaAndAngle( + data[data.length - 1], + data[data.length - 2] + ); + offset = + markerOffsets[edge.arrowTypeEnd] * Math.abs(Math.sin(angle)) * (deltaY >= 0 ? 1 : -1); + } + return d.y + offset; }) .curve(curve); @@ -453,6 +516,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph case 'thick': strokeClasses = 'edge-thickness-thick'; break; + case 'invisible': + strokeClasses = 'edge-thickness-thick'; + break; default: strokeClasses = ''; } diff --git a/packages/mermaid/src/dagre-wrapper/edges.spec.js b/packages/mermaid/src/dagre-wrapper/edges.spec.js index 627691a8e..9b2772ecd 100644 --- a/packages/mermaid/src/dagre-wrapper/edges.spec.js +++ b/packages/mermaid/src/dagre-wrapper/edges.spec.js @@ -1,5 +1,5 @@ -import { intersection } from './edges'; -import { setLogLevel } from '../logger'; +import { intersection } from './edges.js'; +import { setLogLevel } from '../logger.js'; describe('Graphlib decorations', () => { let node; diff --git a/packages/mermaid/src/dagre-wrapper/index.js b/packages/mermaid/src/dagre-wrapper/index.js index ce3ef6014..279c5d9dd 100644 --- a/packages/mermaid/src/dagre-wrapper/index.js +++ b/packages/mermaid/src/dagre-wrapper/index.js @@ -1,20 +1,20 @@ import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js'; import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js'; -import insertMarkers from './markers'; -import { updateNodeBounds } from './shapes/util'; +import insertMarkers from './markers.js'; +import { updateNodeBounds } from './shapes/util.js'; import { clear as clearGraphlib, clusterDb, adjustClustersAndEdges, findNonClusterChild, sortNodesByHierarchy, -} from './mermaid-graphlib'; -import { insertNode, positionNode, clear as clearNodes, setNodeElem } from './nodes'; -import { insertCluster, clear as clearClusters } from './clusters'; -import { insertEdgeLabel, positionEdgeLabel, insertEdge, clear as clearEdges } from './edges'; -import { log } from '../logger'; +} from './mermaid-graphlib.js'; +import { insertNode, positionNode, clear as clearNodes, setNodeElem } from './nodes.js'; +import { insertCluster, clear as clearClusters } from './clusters.js'; +import { insertEdgeLabel, positionEdgeLabel, insertEdge, clear as clearEdges } from './edges.js'; +import { log } from '../logger.js'; -const recursiveRender = (_elem, graph, diagramtype, parentCluster) => { +const recursiveRender = async (_elem, graph, diagramtype, parentCluster) => { log.info('Graph in recursive render: XXX', graphlibJson.write(graph), parentCluster); const dir = graph.graph().rankdir; log.trace('Dir in recursive render - dir:', dir); @@ -35,44 +35,46 @@ const recursiveRender = (_elem, graph, diagramtype, parentCluster) => { // 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 - graph.nodes().forEach(function (v) { - const node = graph.node(v); - if (parentCluster !== undefined) { - const data = JSON.parse(JSON.stringify(parentCluster.clusterData)); - // data.clusterPositioning = true; - log.info('Setting data for cluster XXX (', v, ') ', data, parentCluster); - graph.setNode(parentCluster.id, data); - if (!graph.parent(v)) { - log.trace('Setting parent', v, parentCluster.id); - graph.setParent(v, parentCluster.id, data); + 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.info('Setting data for cluster XXX (', v, ') ', data, parentCluster); + 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 && node.clusterNode) { - // const children = graph.children(v); - log.info('Cluster identified', v, node.width, graph.node(v)); - const o = recursiveRender(nodes, node.graph, diagramtype, graph.node(v)); - const newEl = o.elem; - updateNodeBounds(node, newEl); - node.diff = o.diff || 0; - log.info('Node bounds (abc123)', v, node, node.width, node.x, node.y); - setNodeElem(newEl, node); + log.info('(Insert) Node XXX' + v + ': ' + JSON.stringify(graph.node(v))); + if (node && node.clusterNode) { + // const children = graph.children(v); + log.info('Cluster identified', v, node.width, graph.node(v)); + const o = await recursiveRender(nodes, node.graph, diagramtype, graph.node(v)); + const newEl = o.elem; + updateNodeBounds(node, newEl); + node.diff = o.diff || 0; + log.info('Node bounds (abc123)', v, node, node.width, node.x, node.y); + setNodeElem(newEl, node); - log.warn('Recursive render complete ', newEl, node); - } else { - if (graph.children(v).length > 0) { - // This is a cluster but not to be rendered recursively - // Render as before - log.info('Cluster - the non recursive path XXX', v, node.id, node, graph); - log.info(findNonClusterChild(node.id, graph)); - clusterDb[node.id] = { id: findNonClusterChild(node.id, graph), node }; - // insertCluster(clusters, graph.node(v)); + log.warn('Recursive render complete ', newEl, node); } else { - log.info('Node - the non recursive path', v, node.id, node); - insertNode(nodes, graph.node(v), dir); + if (graph.children(v).length > 0) { + // This is a cluster but not to be rendered recursively + // Render as before + log.info('Cluster - the non recursive path XXX', v, node.id, node, graph); + log.info(findNonClusterChild(node.id, graph)); + clusterDb[node.id] = { id: findNonClusterChild(node.id, graph), node }; + // insertCluster(clusters, graph.node(v)); + } else { + log.info('Node - the non recursive path', v, node.id, node); + await insertNode(nodes, graph.node(v), dir); + } } - } - }); + }) + ); // Insert labels, this will insert them into the dom so that the width can be calculated // Also figure out which edges point to/from clusters and adjust them accordingly @@ -146,18 +148,18 @@ const recursiveRender = (_elem, graph, diagramtype, parentCluster) => { return { elem, diff }; }; -export const render = (elem, graph, markers, diagramtype, id) => { +export const render = async (elem, graph, markers, diagramtype, id) => { insertMarkers(elem, markers, diagramtype, id); clearNodes(); clearEdges(); clearClusters(); clearGraphlib(); - log.warn('Graph at first:', graphlibJson.write(graph)); + log.warn('Graph at first:', JSON.stringify(graphlibJson.write(graph))); adjustClustersAndEdges(graph); - log.warn('Graph after:', graphlibJson.write(graph)); + log.warn('Graph after:', JSON.stringify(graphlibJson.write(graph))); // log.warn('Graph ever after:', graphlibJson.write(graph.node('A').graph)); - recursiveRender(elem, graph, diagramtype); + await recursiveRender(elem, graph, diagramtype); }; // const shapeDefinitions = {}; diff --git a/packages/mermaid/src/dagre-wrapper/intersect/intersect-circle.js b/packages/mermaid/src/dagre-wrapper/intersect/intersect-circle.js index c4d320426..8f5ba72df 100644 --- a/packages/mermaid/src/dagre-wrapper/intersect/intersect-circle.js +++ b/packages/mermaid/src/dagre-wrapper/intersect/intersect-circle.js @@ -1,4 +1,4 @@ -import intersectEllipse from './intersect-ellipse'; +import intersectEllipse from './intersect-ellipse.js'; /** * @param node diff --git a/packages/mermaid/src/dagre-wrapper/intersect/intersect-polygon.js b/packages/mermaid/src/dagre-wrapper/intersect/intersect-polygon.js index cd124150f..6941372c7 100644 --- a/packages/mermaid/src/dagre-wrapper/intersect/intersect-polygon.js +++ b/packages/mermaid/src/dagre-wrapper/intersect/intersect-polygon.js @@ -1,6 +1,6 @@ /* eslint "no-console": off */ -import intersectLine from './intersect-line'; +import intersectLine from './intersect-line.js'; export default intersectPolygon; diff --git a/packages/mermaid/src/dagre-wrapper/markers.js b/packages/mermaid/src/dagre-wrapper/markers.js index 1a3f74bee..051c987f6 100644 --- a/packages/mermaid/src/dagre-wrapper/markers.js +++ b/packages/mermaid/src/dagre-wrapper/markers.js @@ -1,6 +1,6 @@ /** Setup arrow head and define the marker. The result is appended to the svg. */ -import { log } from '../logger'; +import { log } from '../logger.js'; // Only add the number of markers that the diagram needs const insertMarkers = (elem, markerArray, type, id) => { @@ -16,7 +16,7 @@ const extension = (elem, type, id) => { .append('marker') .attr('id', type + '-extensionStart') .attr('class', 'marker extension ' + type) - .attr('refX', 0) + .attr('refX', 18) .attr('refY', 7) .attr('markerWidth', 190) .attr('markerHeight', 240) @@ -29,7 +29,7 @@ const extension = (elem, type, id) => { .append('marker') .attr('id', type + '-extensionEnd') .attr('class', 'marker extension ' + type) - .attr('refX', 19) + .attr('refX', 1) .attr('refY', 7) .attr('markerWidth', 20) .attr('markerHeight', 28) @@ -44,7 +44,7 @@ const composition = (elem, type) => { .append('marker') .attr('id', type + '-compositionStart') .attr('class', 'marker composition ' + type) - .attr('refX', 0) + .attr('refX', 18) .attr('refY', 7) .attr('markerWidth', 190) .attr('markerHeight', 240) @@ -57,7 +57,7 @@ const composition = (elem, type) => { .append('marker') .attr('id', type + '-compositionEnd') .attr('class', 'marker composition ' + type) - .attr('refX', 19) + .attr('refX', 1) .attr('refY', 7) .attr('markerWidth', 20) .attr('markerHeight', 28) @@ -71,7 +71,7 @@ const aggregation = (elem, type) => { .append('marker') .attr('id', type + '-aggregationStart') .attr('class', 'marker aggregation ' + type) - .attr('refX', 0) + .attr('refX', 18) .attr('refY', 7) .attr('markerWidth', 190) .attr('markerHeight', 240) @@ -84,7 +84,7 @@ const aggregation = (elem, type) => { .append('marker') .attr('id', type + '-aggregationEnd') .attr('class', 'marker aggregation ' + type) - .attr('refX', 19) + .attr('refX', 1) .attr('refY', 7) .attr('markerWidth', 20) .attr('markerHeight', 28) @@ -98,7 +98,7 @@ const dependency = (elem, type) => { .append('marker') .attr('id', type + '-dependencyStart') .attr('class', 'marker dependency ' + type) - .attr('refX', 0) + .attr('refX', 6) .attr('refY', 7) .attr('markerWidth', 190) .attr('markerHeight', 240) @@ -111,7 +111,7 @@ const dependency = (elem, type) => { .append('marker') .attr('id', type + '-dependencyEnd') .attr('class', 'marker dependency ' + type) - .attr('refX', 19) + .attr('refX', 13) .attr('refY', 7) .attr('markerWidth', 20) .attr('markerHeight', 28) @@ -125,15 +125,32 @@ const lollipop = (elem, type) => { .append('marker') .attr('id', type + '-lollipopStart') .attr('class', 'marker lollipop ' + type) - .attr('refX', 0) + .attr('refX', 13) .attr('refY', 7) .attr('markerWidth', 190) .attr('markerHeight', 240) .attr('orient', 'auto') .append('circle') .attr('stroke', 'black') - .attr('fill', 'white') - .attr('cx', 6) + .attr('fill', 'transparent') + .attr('cx', 7) + .attr('cy', 7) + .attr('r', 6); + + elem + .append('defs') + .append('marker') + .attr('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); }; @@ -142,8 +159,8 @@ const point = (elem, type) => { .append('marker') .attr('id', type + '-pointEnd') .attr('class', 'marker ' + type) - .attr('viewBox', '0 0 12 20') - .attr('refX', 10) + .attr('viewBox', '0 0 10 10') + .attr('refX', 6) .attr('refY', 5) .attr('markerUnits', 'userSpaceOnUse') .attr('markerWidth', 12) diff --git a/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js b/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js index 875ac4def..1e376054d 100644 --- a/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js +++ b/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.js @@ -1,5 +1,5 @@ /** Decorates with functions required by mermaids dagre-wrapper. */ -import { log } from '../logger'; +import { log } from '../logger.js'; import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; @@ -291,8 +291,8 @@ export const adjustClustersAndEdges = (graph, depth) => { shape: 'labelRect', style: '', }); - const edge1 = JSON.parse(JSON.stringify(edge)); - const edge2 = JSON.parse(JSON.stringify(edge)); + const edge1 = structuredClone(edge); + const edge2 = structuredClone(edge); edge1.label = ''; edge1.arrowTypeEnd = 'none'; edge2.label = ''; diff --git a/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.spec.js b/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.spec.js index 25fb75d64..1444a82c4 100644 --- a/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.spec.js +++ b/packages/mermaid/src/dagre-wrapper/mermaid-graphlib.spec.js @@ -5,8 +5,8 @@ import { adjustClustersAndEdges, extractDescendants, sortNodesByHierarchy, -} from './mermaid-graphlib'; -import { setLogLevel, log } from '../logger'; +} from './mermaid-graphlib.js'; +import { setLogLevel, log } from '../logger.js'; describe('Graphlib decorations', () => { let g; diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js index 5bd18d077..51ff9ef11 100644 --- a/packages/mermaid/src/dagre-wrapper/nodes.js +++ b/packages/mermaid/src/dagre-wrapper/nodes.js @@ -1,15 +1,31 @@ import { select } from 'd3'; -import { log } from '../logger'; -import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util'; -import { getConfig } from '../config'; +import { log } from '../logger.js'; +import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util.js'; +import { getConfig } from '../config.js'; import intersect from './intersect/index.js'; -import createLabel from './createLabel'; -import note from './shapes/note'; -import { parseMember } from '../diagrams/class/svgDraw'; -import { evaluate } from '../diagrams/common/common'; +import createLabel from './createLabel.js'; +import note from './shapes/note.js'; +import { evaluate } from '../diagrams/common/common.js'; -const question = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const formatClass = (str) => { + if (str) { + return ' ' + str; + } + return ''; +}; +const getClassesFromNode = (node, otherClasses) => { + return `${otherClasses ? otherClasses : 'node default'}${formatClass(node.classes)} ${formatClass( + node.class + )}`; +}; + +const question = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -69,8 +85,13 @@ const choice = (parent, node) => { return shapeSvg; }; -const hexagon = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const hexagon = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const f = 4; const h = bbox.height + node.padding; @@ -96,8 +117,13 @@ const hexagon = (parent, node) => { return shapeSvg; }; -const rect_left_inv_arrow = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const rect_left_inv_arrow = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -122,8 +148,8 @@ const rect_left_inv_arrow = (parent, node) => { return shapeSvg; }; -const lean_right = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const lean_right = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper(parent, node, getClassesFromNode(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -145,8 +171,13 @@ const lean_right = (parent, node) => { return shapeSvg; }; -const lean_left = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const lean_left = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -168,8 +199,13 @@ const lean_left = (parent, node) => { return shapeSvg; }; -const trapezoid = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const trapezoid = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -191,8 +227,13 @@ const trapezoid = (parent, node) => { return shapeSvg; }; -const inv_trapezoid = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const inv_trapezoid = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -214,8 +255,13 @@ const inv_trapezoid = (parent, node) => { return shapeSvg; }; -const rect_right_inv_arrow = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const rect_right_inv_arrow = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -238,8 +284,13 @@ const rect_right_inv_arrow = (parent, node) => { return shapeSvg; }; -const cylinder = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const cylinder = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const rx = w / 2; @@ -310,13 +361,19 @@ const cylinder = (parent, node) => { return shapeSvg; }; -const rect = (parent, node) => { - const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes, true); +const rect = async (parent, node) => { + const { shapeSvg, bbox, halfPadding } = await labelHelper( + parent, + node, + 'node ' + node.classes + ' ' + node.class, + true + ); - log.trace('Classes = ', node.classes); // add the rect const rect = shapeSvg.insert('rect', ':first-child'); + // const totalWidth = bbox.width + node.padding * 2; + // const totalHeight = bbox.height + node.padding * 2; const totalWidth = bbox.width + node.padding; const totalHeight = bbox.height + node.padding; rect @@ -324,6 +381,8 @@ const rect = (parent, node) => { .attr('style', node.style) .attr('rx', node.rx) .attr('ry', node.ry) + // .attr('x', -bbox.width / 2 - node.padding) + // .attr('y', -bbox.height / 2 - node.padding) .attr('x', -bbox.width / 2 - halfPadding) .attr('y', -bbox.height / 2 - halfPadding) .attr('width', totalWidth) @@ -349,10 +408,10 @@ const rect = (parent, node) => { return shapeSvg; }; -const labelRect = (parent, node) => { - const { shapeSvg } = labelHelper(parent, node, 'label', true); +const labelRect = async (parent, node) => { + const { shapeSvg } = await labelHelper(parent, node, 'label', true); - log.trace('Classes = ', node.classes); + log.trace('Classes = ', node.class); // add the rect const rect = shapeSvg.insert('rect', ':first-child'); @@ -536,8 +595,13 @@ const rectWithTitle = (parent, node) => { return shapeSvg; }; -const stadium = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const stadium = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const h = bbox.height + node.padding; const w = bbox.width + h / 4 + node.padding; @@ -562,8 +626,13 @@ const stadium = (parent, node) => { return shapeSvg; }; -const circle = (parent, node) => { - const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, undefined, true); +const circle = async (parent, node) => { + const { shapeSvg, bbox, halfPadding } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const circle = shapeSvg.insert('circle', ':first-child'); // center the circle around its coordinate @@ -587,13 +656,20 @@ const circle = (parent, node) => { return shapeSvg; }; -const doublecircle = (parent, node) => { - const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, undefined, true); +const doublecircle = async (parent, node) => { + const { shapeSvg, bbox, halfPadding } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const gap = 5; const circleGroup = shapeSvg.insert('g', ':first-child'); const outerCircle = circleGroup.insert('circle'); const innerCircle = circleGroup.insert('circle'); + circleGroup.attr('class', node.class); + // center the circle around its coordinate outerCircle .attr('style', node.style) @@ -623,8 +699,13 @@ const doublecircle = (parent, node) => { return shapeSvg; }; -const subroutine = (parent, node) => { - const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); +const subroutine = async (parent, node) => { + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -772,7 +853,7 @@ const class_box = (parent, node) => { maxWidth += interfaceBBox.width; } - let classTitleString = node.classData.id; + let classTitleString = node.classData.label; if (node.classData.type !== undefined && node.classData.type !== '') { if (getConfig().flowchart.htmlLabels) { @@ -798,8 +879,8 @@ const class_box = (parent, node) => { maxWidth = classTitleBBox.width; } const classAttributes = []; - node.classData.members.forEach((str) => { - const parsedInfo = parseMember(str); + node.classData.members.forEach((member) => { + const parsedInfo = member.getDisplayDetails(); let parsedText = parsedInfo.displayText; if (getConfig().flowchart.htmlLabels) { parsedText = parsedText.replace(//g, '>'); @@ -832,8 +913,8 @@ const class_box = (parent, node) => { maxHeight += lineHeight; const classMethods = []; - node.classData.methods.forEach((str) => { - const parsedInfo = parseMember(str); + node.classData.methods.forEach((member) => { + const parsedInfo = member.getDisplayDetails(); let displayText = parsedInfo.displayText; if (getConfig().flowchart.htmlLabels) { displayText = displayText.replace(//g, '>'); @@ -907,7 +988,9 @@ const class_box = (parent, node) => { ((-1 * maxHeight) / 2 + verticalPos + lineHeight / 2) + ')' ); - verticalPos += classTitleBBox.height + rowPadding; + //get the height of the bounding box of each member if exists + const memberBBox = lbl?.getBBox(); + verticalPos += (memberBBox?.height ?? 0) + rowPadding; }); verticalPos += lineHeight; @@ -925,63 +1008,9 @@ const class_box = (parent, node) => { 'transform', 'translate( ' + -maxWidth / 2 + ', ' + ((-1 * maxHeight) / 2 + verticalPos) + ')' ); - verticalPos += classTitleBBox.height + rowPadding; + const memberBBox = lbl?.getBBox(); + verticalPos += (memberBBox?.height ?? 0) + rowPadding; }); - // - // let bbox; - // if (evaluate(getConfig().flowchart.htmlLabels)) { - // const div = interfaceLabel.children[0]; - // const dv = select(interfaceLabel); - // bbox = div.getBoundingClientRect(); - // dv.attr('width', bbox.width); - // dv.attr('height', bbox.height); - // } - // bbox = labelContainer.getBBox(); - - // log.info('Text 2', text2); - // const textRows = text2.slice(1, text2.length); - // let titleBox = text.getBBox(); - // const descr = label - // .node() - // .appendChild(createLabel(textRows.join('
'), 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); - // } - // // bbox = label.getBBox(); - // // log.info(descr); - // select(descr).attr( - // 'transform', - // 'translate( ' + - // // (titleBox.width - bbox.width) / 2 + - // (bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) + - // ', ' + - // (titleBox.height + halfPadding + 5) + - // ')' - // ); - // select(text).attr( - // 'transform', - // 'translate( ' + - // // (titleBox.width - bbox.width) / 2 + - // (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) + ')' - // ); rect .attr('class', 'outer title-state') @@ -990,13 +1019,6 @@ const class_box = (parent, node) => { .attr('width', maxWidth + node.padding) .attr('height', maxHeight + node.padding); - // 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) { @@ -1035,7 +1057,7 @@ const shapes = { let nodeElems = {}; -export const insertNode = (elem, node, dir) => { +export const insertNode = async (elem, node, dir) => { let newEl; let el; @@ -1048,9 +1070,9 @@ export const insertNode = (elem, node, dir) => { target = node.linkTarget || '_blank'; } newEl = elem.insert('svg:a').attr('xlink:href', node.link).attr('target', target); - el = shapes[node.shape](newEl, node, dir); + el = await shapes[node.shape](newEl, node, dir); } else { - el = shapes[node.shape](elem, node, dir); + el = await shapes[node.shape](elem, node, dir); newEl = el; } if (node.tooltip) { @@ -1076,6 +1098,7 @@ export const clear = () => { export const positionNode = (node) => { const el = nodeElems[node.id]; + log.trace( 'Transforming node', node.diff, diff --git a/packages/mermaid/src/dagre-wrapper/patterns.js b/packages/mermaid/src/dagre-wrapper/patterns.js index 75afa8bcc..3025f8ef9 100644 --- a/packages/mermaid/src/dagre-wrapper/patterns.js +++ b/packages/mermaid/src/dagre-wrapper/patterns.js @@ -1,6 +1,6 @@ /** Setup arrow head and define the marker. The result is appended to the svg. */ -// import { log } from '../logger'; +// import { log } from '../logger.js'; // Only add the number of markers that the diagram needs const insertPatterns = (elem, patternArray, type, id) => { diff --git a/packages/mermaid/src/dagre-wrapper/shapes/note.js b/packages/mermaid/src/dagre-wrapper/shapes/note.js index 6b693fdf6..17661e169 100644 --- a/packages/mermaid/src/dagre-wrapper/shapes/note.js +++ b/packages/mermaid/src/dagre-wrapper/shapes/note.js @@ -1,9 +1,19 @@ -import { updateNodeBounds, labelHelper } from './util'; -import { log } from '../../logger'; +import { updateNodeBounds, labelHelper } from './util.js'; +import { log } from '../../logger.js'; +import { getConfig } from '../../config.js'; import intersect from '../intersect/index.js'; -const note = (parent, node) => { - const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes, true); +const note = async (parent, node) => { + const useHtmlLabels = node.useHtmlLabels || getConfig().flowchart.htmlLabels; + if (!useHtmlLabels) { + node.centerLabel = true; + } + const { shapeSvg, bbox, halfPadding } = await labelHelper( + parent, + node, + 'node ' + node.classes, + true + ); log.info('Classes = ', node.classes); // add the rect diff --git a/packages/mermaid/src/dagre-wrapper/shapes/util.js b/packages/mermaid/src/dagre-wrapper/shapes/util.js index 6de0da638..95b82ddc0 100644 --- a/packages/mermaid/src/dagre-wrapper/shapes/util.js +++ b/packages/mermaid/src/dagre-wrapper/shapes/util.js @@ -1,15 +1,19 @@ -import createLabel from '../createLabel'; -import { getConfig } from '../../config'; -import { decodeEntities } from '../../mermaidAPI'; +import createLabel from '../createLabel.js'; +import { createText } from '../../rendering-util/createText.js'; +import { getConfig } from '../../config.js'; +import { decodeEntities } from '../../mermaidAPI.js'; import { select } from 'd3'; -import { evaluate, sanitizeText } from '../../diagrams/common/common'; -export const labelHelper = (parent, node, _classes, isNode) => { +import { evaluate, sanitizeText } from '../../diagrams/common/common.js'; + +export const labelHelper = async (parent, node, _classes, isNode) => { let classes; + const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig().flowchart.htmlLabels); if (!_classes) { classes = 'node default'; } else { classes = _classes; } + // Add outer g element const shapeSvg = parent .insert('g') @@ -27,9 +31,17 @@ export const labelHelper = (parent, node, _classes, isNode) => { labelText = typeof node.labelText === 'string' ? node.labelText : node.labelText[0]; } - const text = label - .node() - .appendChild( + const textNode = label.node(); + let text; + if (node.labelType === 'markdown') { + // text = textNode; + text = createText(label, sanitizeText(decodeEntities(labelText), getConfig()), { + useHtmlLabels, + width: node.width || getConfig().flowchart.wrappingWidth, + classes: 'markdown-node-label', + }); + } else { + text = textNode.appendChild( createLabel( sanitizeText(decodeEntities(labelText), getConfig()), node.labelStyle, @@ -37,23 +49,70 @@ export const labelHelper = (parent, node, _classes, isNode) => { isNode ) ); - + } // Get the size of the label let bbox = text.getBBox(); + const halfPadding = node.padding / 2; if (evaluate(getConfig().flowchart.htmlLabels)) { 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 = labelText.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; + img.style.width = parseInt(bodyFontSize, 10) * enlargingFactor + 'px'; + } 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); } - const halfPadding = node.padding / 2; - // Center the label - label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); - + if (useHtmlLabels) { + label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + } else { + label.attr('transform', 'translate(' + 0 + ', ' + -bbox.height / 2 + ')'); + } + if (node.centerLabel) { + label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')'); + } + label.insert('rect', ':first-child'); return { shapeSvg, bbox, halfPadding, label }; }; diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index ec741e908..f8bd9b0b5 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -1,547 +1,31 @@ -import theme from './themes'; -import { MermaidConfig } from './config.type'; +import type { RequiredDeep } from 'type-fest'; + +import theme from './themes/index.js'; +import type { MermaidConfig } from './config.type.js'; + +// Uses our custom Vite jsonSchemaPlugin to load only the default values from +// our JSON Schema +// @ts-expect-error This file is automatically generated via a custom Vite plugin +import defaultConfigJson from './schemas/config.schema.yaml?only-defaults=true'; + /** - * **Configuration methods in Mermaid version 8.6.0 have been updated, to learn more[[click - * here](8.6.0_docs.md)].** + * Default mermaid configuration options. * - * ## **What follows are config instructions for older versions** - * - * These are the default options which can be overridden with the initialization call like so: - * - * **Example 1:** - * - * ```js - * mermaid.initialize({ flowchart:{ htmlLabels: false } }); - * ``` - * - * **Example 2:** - * - * ```html - * - * ``` - * - * A summary of all options and their defaults is found [here](#mermaidapi-configuration-defaults). - * A description of each option follows below. + * Please see the Mermaid config JSON Schema for the default JSON values. + * Non-JSON JS default values are listed in this file, e.g. functions, or + * `undefined` (explicitly set so that `configKeys` finds them). */ -const config: Partial = { - /** - * Theme , the CSS style sheet - * - * | Parameter | Description | Type | Required | Values | - * | --------- | --------------- | ------ | -------- | ---------------------------------------------- | - * | theme | Built in Themes | string | Optional | 'default', 'forest', 'dark', 'neutral', 'null' | - * - * **Notes:** To disable any pre-defined mermaid theme, use "null". - * - * @example - * - * ```js - * { - * "theme": "forest", - * "themeCSS": ".node rect { fill: red; }" - * } - * ``` - */ - theme: 'default', - themeVariables: theme['default'].getThemeVariables(), - themeCSS: undefined, - /* **maxTextSize** - The maximum allowed size of the users text diagram */ - maxTextSize: 50000, - darkMode: false, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | ------------------------------------------------------ | ------ | -------- | --------------------------- | - * | fontFamily | specifies the font to be used in the rendered diagrams | string | Required | Any Possible CSS FontFamily | - * - * **Notes:** Default value: '"trebuchet ms", verdana, arial, sans-serif;'. - */ - fontFamily: '"trebuchet ms", verdana, arial, sans-serif;', - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ----------------------------------------------------- | ---------------- | -------- | --------------------------------------------- | - * | logLevel | This option decides the amount of logging to be used. | string \| number | Required | 'trace','debug','info','warn','error','fatal' | - * - * **Notes:** - * - * - Trace: 0 - * - Debug: 1 - * - Info: 2 - * - Warn: 3 - * - Error: 4 - * - Fatal: 5 (default) - */ - logLevel: 5, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ | - * | securityLevel | Level of trust for parsed diagram | string | Required | 'sandbox', 'strict', 'loose', 'antiscript' | - * - * **Notes**: - * - * - **strict**: (**default**) tags in text are encoded, click functionality is disabled - * - **loose**: tags in text are allowed, click functionality is enabled - * - **antiscript**: html tags in text are allowed, (only script element is removed), click - * functionality is enabled - * - **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This - * prevent any JavaScript from running in the context. This may hinder interactive functionality - * of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc. - */ - securityLevel: 'strict', - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | -------------------------------------------- | ------- | -------- | ----------- | - * | startOnLoad | Dictates whether mermaid starts on Page load | boolean | Required | true, false | - * - * **Notes:** Default value: true - */ - startOnLoad: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------------- | ---------------------------------------------------------------------------- | ------- | -------- | ----------- | - * | arrowMarkerAbsolute | Controls whether or arrow markers in html code are absolute paths or anchors | boolean | Required | true, false | - * - * **Notes**: - * - * This matters if you are using base tag settings. - * - * Default value: false - */ - arrowMarkerAbsolute: false, - - /** - * 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. This prevents malicious graph directives from - * overriding a site's default security. - * - * **Notes**: - * - * Default value: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'] - */ - secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'], - /** - * This option controls if the generated ids of nodes in the SVG are generated randomly or based - * on a seed. If set to false, the IDs are generated based on the current date and thus are not - * deterministic. This is the default behavior. - * - * **Notes**: - * - * This matters if your files are checked into source control e.g. git and should not change unless - * content is changed. - * - * Default value: false - */ - deterministicIds: false, - - /** - * This option is the optional seed for deterministic ids. if set to undefined but - * deterministicIds is true, a simple number iterator is used. You can set this attribute to base - * the seed on a static string. - */ +const config: RequiredDeep = { + ...defaultConfigJson, + // 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, + themeCSS: undefined, - /** The object containing configurations specific for flowcharts */ - flowchart: { - /** - * ### titleTopMargin - * - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | - * | titleTopMargin | Margin top for the text over the flowchart | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 25 - */ - titleTopMargin: 25, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ----------------------------------------------- | ------- | -------- | ------------------ | - * | diagramPadding | Amount of padding around the diagram as a whole | Integer | Required | Any Positive Value | - * - * **Notes:** - * - * The amount of padding around the diagram as a whole so that embedded diagrams have margins, - * expressed in pixels - * - * Default value: 8 - */ - diagramPadding: 8, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | -------------------------------------------------------------------------------------------- | ------- | -------- | ----------- | - * | htmlLabels | Flag for setting whether or not a html tag should be used for rendering labels on the edges. | boolean | Required | true, false | - * - * **Notes:** Default value: true. - */ - htmlLabels: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | --------------------------------------------------- | ------- | -------- | ------------------- | - * | nodeSpacing | Defines the spacing between nodes on the same level | Integer | Required | Any positive Number | - * - * **Notes:** - * - * 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.** - * - * Default value: 50 - */ - nodeSpacing: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------------------------------------------------- | ------- | -------- | ------------------- | - * | rankSpacing | Defines the spacing between nodes on different levels | Integer | Required | Any Positive Number | - * - * **Notes**: - * - * Pertains to vertical spacing for TB (top to bottom) or BT (bottom to top), and the horizontal - * spacing for LR as well as RL graphs. - * - * Default value 50 - */ - rankSpacing: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | -------------------------------------------------- | ------ | -------- | ----------------------------- | - * | curve | Defines how mermaid renders curves for flowcharts. | string | Required | 'basis', 'linear', 'cardinal' | - * - * **Notes:** - * - * Default Value: 'basis' - */ - curve: 'basis', - // Only used in new experimental rendering - // represents the padding between the labels and the shape - padding: 15, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See notes | boolean | 4 | true, false | - * - * **Notes:** - * - * When this flag is set the height and width is set to 100% and is then scaling with the - * available space if not the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ----------- | ------- | -------- | ----------------------- | - * | defaultRenderer | See notes | boolean | 4 | dagre-d3, dagre-wrapper, elk | - * - * **Notes:** - * - * Decides which rendering engine that is to be used for the rendering. Legal values are: - * dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid, elk for layout using - * elkjs - * - * Default value: 'dagre-wrapper' - */ - defaultRenderer: 'dagre-wrapper', - }, - - /** The object containing configurations specific for sequence diagrams */ + // add non-JSON default config values + themeVariables: theme['default'].getThemeVariables(), sequence: { - hideUnusedParticipants: false, - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ---------------------------- | ------- | -------- | ------------------ | - * | activationWidth | Width of the activation rect | Integer | Required | Any Positive Value | - * - * **Notes:** Default value :10 - */ - activationWidth: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginX | Margin to the right and left of the sequence diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - diagramMarginX: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ------------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginY | Margin to the over and under the sequence diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - diagramMarginY: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | --------------------- | ------- | -------- | ------------------ | - * | actorMargin | Margin between actors | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - actorMargin: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | -------------------- | ------- | -------- | ------------------ | - * | width | Width of actor boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 150 - */ - width: 150, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | --------------------- | ------- | -------- | ------------------ | - * | height | Height of actor boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 65 - */ - height: 65, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ------------------------ | ------- | -------- | ------------------ | - * | boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - boxMargin: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | -------------------------------------------- | ------- | -------- | ------------------ | - * | boxTextMargin | Margin around the text in loop/alt/opt boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 5 - */ - boxTextMargin: 5, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | ------------------- | ------- | -------- | ------------------ | - * | noteMargin | margin around notes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - noteMargin: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | ---------------------- | ------- | -------- | ------------------ | - * | messageMargin | Space between messages | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 35 - */ - messageMargin: 35, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | --------------------------- | ------ | -------- | ------------------------- | - * | messageAlign | Multiline message alignment | string | Required | 'left', 'center', 'right' | - * - * **Notes:** Default value: 'center' - */ - messageAlign: 'center', - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | --------------------------- | ------- | -------- | ----------- | - * | mirrorActors | Mirror actors under diagram | boolean | Required | true, false | - * - * **Notes:** Default value: true - */ - mirrorActors: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | ----------------------------------------------------------------------- | ------- | -------- | ----------- | - * | forceMenus | forces actor popup menus to always be visible (to support E2E testing). | Boolean | Required | True, False | - * - * **Notes:** - * - * Default value: false. - */ - forceMenus: false, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ------------------------------------------ | ------- | -------- | ------------------ | - * | bottomMarginAdj | Prolongs the edge of the diagram downwards | Integer | Required | Any Positive Value | - * - * **Notes:** - * - * Depending on css styling this might need adjustment. - * - * Default value: 1 - */ - bottomMarginAdj: 1, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See Notes | boolean | Required | true, false | - * - * **Notes:** When this flag is set to true, the height and width is set to 100% and is then - * scaling with the available space. If set to false, the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ------------------------------------ | ------- | -------- | ----------- | - * | rightAngles | display curve arrows as right angles | boolean | Required | true, false | - * - * **Notes:** - * - * This will display arrows that start and begin at the same node as right angles, rather than a - * curve - * - * Default value: false - */ - rightAngles: false, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------------- | ------------------------------- | ------- | -------- | ----------- | - * | showSequenceNumbers | This will show the node numbers | boolean | Required | true, false | - * - * **Notes:** Default value: false - */ - showSequenceNumbers: false, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | -------------------------------------------------- | ------- | -------- | ------------------ | - * | actorFontSize | This sets the font size of the actor's description | Integer | Require | Any Positive Value | - * - * **Notes:** **Default value 14**.. - */ - actorFontSize: 14, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ---------------------------------------------------- | ------ | -------- | --------------------------- | - * | actorFontFamily | This sets the font family of the actor's description | string | Required | Any Possible CSS FontFamily | - * - * **Notes:** Default value: "'Open Sans", sans-serif' - */ - actorFontFamily: '"Open Sans", sans-serif', - - /** - * This sets the font weight of the actor's description - * - * **Notes:** Default value: 400. - */ - actorFontWeight: 400, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | ----------------------------------------------- | ------- | -------- | ------------------ | - * | noteFontSize | This sets the font size of actor-attached notes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 14 - */ - noteFontSize: 14, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | -------------------------------------------------- | ------ | -------- | --------------------------- | - * | noteFontFamily | This sets the font family of actor-attached notes. | string | Required | Any Possible CSS FontFamily | - * - * **Notes:** Default value: ''"trebuchet ms", verdana, arial, sans-serif' - */ - noteFontFamily: '"trebuchet ms", verdana, arial, sans-serif', - - /** - * This sets the font weight of the note's description - * - * **Notes:** Default value: 400 - */ - noteFontWeight: 400, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ---------------------------------------------------- | ------ | -------- | ------------------------- | - * | noteAlign | This sets the text alignment of actor-attached notes | string | required | 'left', 'center', 'right' | - * - * **Notes:** Default value: 'center' - */ - noteAlign: 'center', - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ----------------------------------------- | ------- | -------- | ------------------- | - * | messageFontSize | This sets the font size of actor messages | Integer | Required | Any Positive Number | - * - * **Notes:** Default value: 16 - */ - messageFontSize: 16, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------------- | ------------------------------------------- | ------ | -------- | --------------------------- | - * | messageFontFamily | This sets the font family of actor messages | string | Required | Any Possible CSS FontFamily | - * - * **Notes:** Default value: '"trebuchet ms", verdana, arial, sans-serif' - */ - messageFontFamily: '"trebuchet ms", verdana, arial, sans-serif', - - /** - * This sets the font weight of the message's description - * - * **Notes:** Default value: 400. - */ - messageFontWeight: 400, - - /** - * This sets the auto-wrap state for the diagram - * - * **Notes:** Default value: false. - */ - wrap: false, - - /** - * This sets the auto-wrap padding for the diagram (sides only) - * - * **Notes:** Default value: 0. - */ - wrapPadding: 10, - - /** - * This sets the width of the loop-box (loop, alt, opt, par) - * - * **Notes:** Default value: 50. - */ - labelBoxWidth: 50, - - /** - * This sets the height of the loop-box (loop, alt, opt, par) - * - * **Notes:** Default value: 20. - */ - labelBoxHeight: 20, - + ...defaultConfigJson.sequence, messageFont: function () { return { fontFamily: this.messageFontFamily, @@ -564,1279 +48,14 @@ const config: Partial = { }; }, }, - - /** The object containing configurations specific for gantt diagrams */ gantt: { - /** - * ### titleTopMargin - * - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | - * | titleTopMargin | Margin top for the text over the gantt diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 25 - */ - titleTopMargin: 25, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ----------------------------------- | ------- | -------- | ------------------ | - * | barHeight | The height of the bars in the graph | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 20 - */ - barHeight: 20, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ---------------------------------------------------------------- | ------- | -------- | ------------------ | - * | barGap | The margin between the different activities in the gantt diagram | Integer | Optional | Any Positive Value | - * - * **Notes:** Default value: 4 - */ - barGap: 4, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | -------------------------------------------------------------------------- | ------- | -------- | ------------------ | - * | topPadding | Margin between title and gantt diagram and between axis and gantt diagram. | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - topPadding: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | ----------------------------------------------------------------------- | ------- | -------- | ------------------ | - * | rightPadding | The space allocated for the section name to the right of the activities | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 75 - */ - rightPadding: 75, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ---------------------------------------------------------------------- | ------- | -------- | ------------------ | - * | leftPadding | The space allocated for the section name to the left of the activities | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 75 - */ - leftPadding: 75, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------------- | -------------------------------------------- | ------- | -------- | ------------------ | - * | gridLineStartPadding | Vertical starting position of the grid lines | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 35 - */ - gridLineStartPadding: 35, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ----------- | ------- | -------- | ------------------ | - * | fontSize | Font size | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 11 - */ - fontSize: 11, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ---------------------- | ------- | -------- | ------------------ | - * | sectionFontSize | Font size for sections | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 11 - */ - sectionFontSize: 11, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------------- | ---------------------------------------- | ------- | -------- | ------------------ | - * | numberSectionStyles | The number of alternating section styles | Integer | 4 | Any Positive Value | - * - * **Notes:** Default value: 4 - */ - numberSectionStyles: 4, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | ---------------------------- | ---- | -------- | ---------------- | - * | axisFormat | Date/time format of the axis | 3 | Required | Date in yy-mm-dd | - * - * **Notes:** - * - * This might need adjustment to match your locale and preferences - * - * Default value: '%Y-%m-%d'. - */ - axisFormat: '%Y-%m-%d', - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | ------------| ------ | -------- | ------- | - * | tickInterval | axis ticks | string | Optional | string | - * - * **Notes:** - * - * Pattern is /^([1-9][0-9]*)(minute|hour|day|week|month)$/ - * - * Default value: undefined - */ + ...defaultConfigJson.gantt, tickInterval: undefined, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See notes | boolean | 4 | true, false | - * - * **Notes:** - * - * When this flag is set the height and width is set to 100% and is then scaling with the - * available space if not the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ----------- | ------- | -------- | ----------- | - * | topAxis | See notes | Boolean | 4 | True, False | - * - * **Notes:** when this flag is set date labels will be added to the top of the chart - * - * **Default value false**. - */ - topAxis: false, - - useWidth: undefined, + useWidth: undefined, // can probably be removed since `configKeys` already includes this }, - - /** The object containing configurations specific for journey diagrams */ - journey: { - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginX | Margin to the right and left of the sequence diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - diagramMarginX: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | -------------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginY | Margin to the over and under the sequence diagram. | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - diagramMarginY: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | --------------------- | ------- | -------- | ------------------ | - * | actorMargin | Margin between actors | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - leftMargin: 150, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | -------------------- | ------- | -------- | ------------------ | - * | width | Width of actor boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 150 - */ - width: 150, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | --------------------- | ------- | -------- | ------------------ | - * | height | Height of actor boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 65 - */ - height: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ------------------------ | ------- | -------- | ------------------ | - * | boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - boxMargin: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | -------------------------------------------- | ------- | -------- | ------------------ | - * | boxTextMargin | Margin around the text in loop/alt/opt boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 5 - */ - boxTextMargin: 5, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | ------------------- | ------- | -------- | ------------------ | - * | noteMargin | Margin around notes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - noteMargin: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | ----------------------- | ------- | -------- | ------------------ | - * | messageMargin | Space between messages. | Integer | Required | Any Positive Value | - * - * **Notes:** - * - * Space between messages. - * - * Default value: 35 - */ - messageMargin: 35, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | --------------------------- | ---- | -------- | ------------------------- | - * | messageAlign | Multiline message alignment | 3 | 4 | 'left', 'center', 'right' | - * - * **Notes:** Default value: 'center' - */ - messageAlign: 'center', - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ------------------------------------------ | ------- | -------- | ------------------ | - * | bottomMarginAdj | Prolongs the edge of the diagram downwards | Integer | 4 | Any Positive Value | - * - * **Notes:** - * - * Depending on css styling this might need adjustment. - * - * Default value: 1 - */ - bottomMarginAdj: 1, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See notes | boolean | 4 | true, false | - * - * **Notes:** - * - * When this flag is set the height and width is set to 100% and is then scaling with the - * available space if not the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | --------------------------------- | ---- | -------- | ----------- | - * | rightAngles | Curved Arrows become Right Angles | 3 | 4 | true, false | - * - * **Notes:** - * - * This will display arrows that start and begin at the same node as right angles, rather than a - * curves - * - * Default value: false - */ - rightAngles: false, - taskFontSize: 14, - taskFontFamily: '"Open Sans", sans-serif', - taskMargin: 50, - // width of activation box - activationWidth: 10, - - // text placement as: tspan | fo | old only text as before - textPlacement: 'fo', - actorColours: ['#8FBC8F', '#7CFC00', '#00FFFF', '#20B2AA', '#B0E0E6', '#FFFFE0'], - - sectionFills: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'], - sectionColours: ['#fff'], - }, - /** The object containing configurations specific for timeline diagrams */ - timeline: { - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginX | Margin to the right and left of the sequence diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - diagramMarginX: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | -------------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginY | Margin to the over and under the sequence diagram. | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - diagramMarginY: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | --------------------- | ------- | -------- | ------------------ | - * | actorMargin | Margin between actors | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - leftMargin: 150, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | -------------------- | ------- | -------- | ------------------ | - * | width | Width of actor boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 150 - */ - width: 150, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | --------------------- | ------- | -------- | ------------------ | - * | height | Height of actor boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 65 - */ - height: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ------------------------ | ------- | -------- | ------------------ | - * | boxMargin | Margin around loop boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - boxMargin: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | -------------------------------------------- | ------- | -------- | ------------------ | - * | boxTextMargin | Margin around the text in loop/alt/opt boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 5 - */ - boxTextMargin: 5, - - /** - * | Parameter | Description | Type | Required | Values | - * | ---------- | ------------------- | ------- | -------- | ------------------ | - * | noteMargin | Margin around notes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - noteMargin: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | ----------------------- | ------- | -------- | ------------------ | - * | messageMargin | Space between messages. | Integer | Required | Any Positive Value | - * - * **Notes:** - * - * Space between messages. - * - * Default value: 35 - */ - messageMargin: 35, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | --------------------------- | ---- | -------- | ------------------------- | - * | messageAlign | Multiline message alignment | 3 | 4 | 'left', 'center', 'right' | - * - * **Notes:** Default value: 'center' - */ - messageAlign: 'center', - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ------------------------------------------ | ------- | -------- | ------------------ | - * | bottomMarginAdj | Prolongs the edge of the diagram downwards | Integer | 4 | Any Positive Value | - * - * **Notes:** - * - * Depending on css styling this might need adjustment. - * - * Default value: 1 - */ - bottomMarginAdj: 1, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See notes | boolean | 4 | true, false | - * - * **Notes:** - * - * When this flag is set the height and width is set to 100% and is then scaling with the - * available space if not the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | --------------------------------- | ---- | -------- | ----------- | - * | rightAngles | Curved Arrows become Right Angles | 3 | 4 | true, false | - * - * **Notes:** - * - * This will display arrows that start and begin at the same node as right angles, rather than a - * curves - * - * Default value: false - */ - rightAngles: false, - taskFontSize: 14, - taskFontFamily: '"Open Sans", sans-serif', - taskMargin: 50, - // width of activation box - activationWidth: 10, - - // text placement as: tspan | fo | old only text as before - textPlacement: 'fo', - actorColours: ['#8FBC8F', '#7CFC00', '#00FFFF', '#20B2AA', '#B0E0E6', '#FFFFE0'], - - sectionFills: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'], - sectionColours: ['#fff'], - disableMulticolor: false, - }, - class: { - /** - * ### titleTopMargin - * - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | - * | titleTopMargin | Margin top for the text over the class diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 25 - */ - titleTopMargin: 25, - arrowMarkerAbsolute: false, - dividerMargin: 10, - padding: 5, - textHeight: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See notes | boolean | 4 | true, false | - * - * **Notes:** - * - * When this flag is set the height and width is set to 100% and is then scaling with the - * available space if not the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ----------- | ------- | -------- | ----------------------- | - * | defaultRenderer | See notes | boolean | 4 | dagre-d3, dagre-wrapper | - * - * **Notes**: - * - * Decides which rendering engine that is to be used for the rendering. Legal values are: - * dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid - * - * Default value: 'dagre-d3' - */ - defaultRenderer: 'dagre-wrapper', - }, - state: { - /** - * ### titleTopMargin - * - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | - * | titleTopMargin | Margin top for the text over the state diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 25 - */ - titleTopMargin: 25, - dividerMargin: 10, - sizeUnit: 5, - padding: 8, - textHeight: 10, - titleShift: -15, - noteMargin: 10, - forkWidth: 70, - forkHeight: 7, - // Used - miniPadding: 2, - // 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: 5.02, - fontSize: 24, - labelHeight: 16, - edgeLengthFactor: '20', - compositTitleSize: 35, - radius: 5, - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See notes | boolean | 4 | true, false | - * - * **Notes:** - * - * When this flag is set the height and width is set to 100% and is then scaling with the - * available space if not the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ----------- | ------- | -------- | ----------------------- | - * | defaultRenderer | See notes | boolean | 4 | dagre-d3, dagre-wrapper | - * - * **Notes:** - * - * Decides which rendering engine that is to be used for the rendering. Legal values are: - * dagre-d3 dagre-wrapper - wrapper for dagre implemented in mermaid - * - * Default value: 'dagre-d3' - */ - defaultRenderer: 'dagre-wrapper', - }, - - /** The object containing configurations specific for entity relationship diagrams */ - er: { - /** - * ### titleTopMargin - * - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | - * | titleTopMargin | Margin top for the text over the diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 25 - */ - titleTopMargin: 25, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ----------------------------------------------- | ------- | -------- | ------------------ | - * | diagramPadding | Amount of padding around the diagram as a whole | Integer | Required | Any Positive Value | - * - * **Notes:** - * - * The amount of padding around the diagram as a whole so that embedded diagrams have margins, - * expressed in pixels - * - * Default value: 20 - */ - diagramPadding: 20, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ---------------------------------------- | ------ | -------- | ---------------------- | - * | layoutDirection | Directional bias for layout of entities. | string | Required | "TB", "BT", "LR", "RL" | - * - * **Notes:** - * - * 'TB' for Top-Bottom, 'BT'for Bottom-Top, 'LR' for Left-Right, or 'RL' for Right to Left. - * - * T = top, B = bottom, L = left, and R = right. - * - * Default value: 'TB' - */ - layoutDirection: 'TB', - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------- | ------- | -------- | ------------------ | - * | minEntityWidth | The minimum width of an entity box | Integer | Required | Any Positive Value | - * - * **Notes:** Expressed in pixels. Default value: 100 - */ - minEntityWidth: 100, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ----------------------------------- | ------- | -------- | ------------------ | - * | minEntityHeight | The minimum height of an entity box | Integer | 4 | Any Positive Value | - * - * **Notes:** Expressed in pixels Default value: 75 - */ - minEntityHeight: 75, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | ------------------------------------------------------------ | ------- | -------- | ------------------ | - * | entityPadding | Minimum internal padding between text in box and box borders | Integer | 4 | Any Positive Value | - * - * **Notes:** - * - * The minimum internal padding between text in an entity box and the enclosing box borders, - * expressed in pixels. - * - * Default value: 15 - */ - entityPadding: 15, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ----------------------------------- | ------ | -------- | -------------------- | - * | stroke | Stroke color of box edges and lines | string | 4 | Any recognized color | - * - * **Notes:** Default value: 'gray' - */ - stroke: 'gray', - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | -------------------------- | ------ | -------- | -------------------- | - * | fill | Fill color of entity boxes | string | 4 | Any recognized color | - * - * **Notes:** Default value: 'honeydew' - */ - fill: 'honeydew', - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ------------------- | ------- | -------- | ------------------ | - * | fontSize | Font Size in pixels | Integer | | Any Positive Value | - * - * **Notes:** - * - * Font size (expressed as an integer representing a number of pixels) Default value: 12 - */ - fontSize: 12, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See Notes | boolean | Required | true, false | - * - * **Notes:** - * - * When this flag is set to true, the diagram width is locked to 100% and scaled based on - * available space. If set to false, the diagram reserves its absolute width. - * - * Default value: true - */ - useMaxWidth: true, - }, - - /** The object containing configurations specific for pie diagrams */ - pie: { - useWidth: undefined, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See Notes | boolean | Required | true, false | - * - * **Notes:** - * - * When this flag is set to true, the diagram width is locked to 100% and scaled based on - * available space. If set to false, the diagram reserves its absolute width. - * - * Default value: true - */ - useMaxWidth: true, - }, - - /** The object containing configurations specific for req diagrams */ - requirement: { - useWidth: undefined, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See Notes | boolean | Required | true, false | - * - * **Notes:** - * - * When this flag is set to true, the diagram width is locked to 100% and scaled based on - * available space. If set to false, the diagram reserves its absolute width. - * - * Default value: true - */ - useMaxWidth: true, - - rect_fill: '#f9f9f9', - text_color: '#333', - rect_border_size: '0.5px', - rect_border_color: '#bbb', - rect_min_width: 200, - rect_min_height: 200, - fontSize: 14, - rect_padding: 10, - line_height: 20, - }, - gitGraph: { - /** - * ### titleTopMargin - * - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | - * | titleTopMargin | Margin top for the text over the Git diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 25 - */ - titleTopMargin: 25, - diagramPadding: 8, - nodeLabel: { - width: 75, - height: 100, - x: -25, - y: 0, - }, - mainBranchName: 'main', - mainBranchOrder: 0, - showCommitLabel: true, - showBranches: true, - rotateCommitLabel: true, - }, - - /** The object containing configurations specific for c4 diagrams */ c4: { + ...defaultConfigJson.c4, useWidth: undefined, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginX | Margin to the right and left of the c4 diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - diagramMarginX: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ------------------------------------------- | ------- | -------- | ------------------ | - * | diagramMarginY | Margin to the over and under the c4 diagram | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - diagramMarginY: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------- | --------------------- | ------- | -------- | ------------------ | - * | c4ShapeMargin | Margin between shapes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 50 - */ - c4ShapeMargin: 50, - - /** - * | Parameter | Description | Type | Required | Values | - * | -------------- | ---------------------- | ------- | -------- | ------------------ | - * | c4ShapePadding | Padding between shapes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 20 - */ - c4ShapePadding: 20, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | --------------------- | ------- | -------- | ------------------ | - * | width | Width of person boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 216 - */ - width: 216, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ---------------------- | ------- | -------- | ------------------ | - * | height | Height of person boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 60 - */ - height: 60, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------- | ------------------- | ------- | -------- | ------------------ | - * | boxMargin | Margin around boxes | Integer | Required | Any Positive Value | - * - * **Notes:** Default value: 10 - */ - boxMargin: 10, - - /** - * | Parameter | Description | Type | Required | Values | - * | ----------- | ----------- | ------- | -------- | ----------- | - * | useMaxWidth | See Notes | boolean | Required | true, false | - * - * **Notes:** When this flag is set to true, the height and width is set to 100% and is then - * scaling with the available space. If set to false, the absolute space required is used. - * - * Default value: true - */ - useMaxWidth: true, - - /** - * | Parameter | Description | Type | Required | Values | - * | ------------ | ----------- | ------- | -------- | ------------------ | - * | c4ShapeInRow | See Notes | Integer | Required | Any Positive Value | - * - * **Notes:** How many shapes to place in each row. - * - * Default value: 4 - */ - c4ShapeInRow: 4, - - nextLinePaddingX: 0, - - /** - * | Parameter | Description | Type | Required | Values | - * | --------------- | ----------- | ------- | -------- | ------------------ | - * | c4BoundaryInRow | See Notes | Integer | Required | Any Positive Value | - * - * **Notes:** How many boundaries to place in each row. - * - * Default value: 2 - */ - c4BoundaryInRow: 2, - - /** - * This sets the font size of Person shape for the diagram - * - * **Notes:** Default value: 14. - */ - personFontSize: 14, - /** - * This sets the font family of Person shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - personFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Person shape for the diagram - * - * **Notes:** Default value: normal. - */ - personFontWeight: 'normal', - - /** - * This sets the font size of External Person shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_personFontSize: 14, - /** - * This sets the font family of External Person shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_personFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External Person shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_personFontWeight: 'normal', - - /** - * This sets the font size of System shape for the diagram - * - * **Notes:** Default value: 14. - */ - systemFontSize: 14, - /** - * This sets the font family of System shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - systemFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of System shape for the diagram - * - * **Notes:** Default value: normal. - */ - systemFontWeight: 'normal', - - /** - * This sets the font size of External System shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_systemFontSize: 14, - /** - * This sets the font family of External System shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_systemFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External System shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_systemFontWeight: 'normal', - - /** - * This sets the font size of System DB shape for the diagram - * - * **Notes:** Default value: 14. - */ - system_dbFontSize: 14, - /** - * This sets the font family of System DB shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - system_dbFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of System DB shape for the diagram - * - * **Notes:** Default value: normal. - */ - system_dbFontWeight: 'normal', - - /** - * This sets the font size of External System DB shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_system_dbFontSize: 14, - /** - * This sets the font family of External System DB shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_system_dbFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External System DB shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_system_dbFontWeight: 'normal', - - /** - * This sets the font size of System Queue shape for the diagram - * - * **Notes:** Default value: 14. - */ - system_queueFontSize: 14, - /** - * This sets the font family of System Queue shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - system_queueFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of System Queue shape for the diagram - * - * **Notes:** Default value: normal. - */ - system_queueFontWeight: 'normal', - - /** - * This sets the font size of External System Queue shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_system_queueFontSize: 14, - /** - * This sets the font family of External System Queue shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_system_queueFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External System Queue shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_system_queueFontWeight: 'normal', - - /** - * This sets the font size of Boundary shape for the diagram - * - * **Notes:** Default value: 14. - */ - boundaryFontSize: 14, - /** - * This sets the font family of Boundary shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - boundaryFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Boundary shape for the diagram - * - * **Notes:** Default value: normal. - */ - boundaryFontWeight: 'normal', - - /** - * This sets the font size of Message shape for the diagram - * - * **Notes:** Default value: 12. - */ - messageFontSize: 12, - /** - * This sets the font family of Message shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - messageFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Message shape for the diagram - * - * **Notes:** Default value: normal. - */ - messageFontWeight: 'normal', - - /** - * This sets the font size of Container shape for the diagram - * - * **Notes:** Default value: 14. - */ - containerFontSize: 14, - /** - * This sets the font family of Container shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - containerFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Container shape for the diagram - * - * **Notes:** Default value: normal. - */ - containerFontWeight: 'normal', - - /** - * This sets the font size of External Container shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_containerFontSize: 14, - /** - * This sets the font family of External Container shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_containerFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External Container shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_containerFontWeight: 'normal', - - /** - * This sets the font size of Container DB shape for the diagram - * - * **Notes:** Default value: 14. - */ - container_dbFontSize: 14, - /** - * This sets the font family of Container DB shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - container_dbFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Container DB shape for the diagram - * - * **Notes:** Default value: normal. - */ - container_dbFontWeight: 'normal', - - /** - * This sets the font size of External Container DB shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_container_dbFontSize: 14, - /** - * This sets the font family of External Container DB shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_container_dbFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External Container DB shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_container_dbFontWeight: 'normal', - - /** - * This sets the font size of Container Queue shape for the diagram - * - * **Notes:** Default value: 14. - */ - container_queueFontSize: 14, - /** - * This sets the font family of Container Queue shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - container_queueFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Container Queue shape for the diagram - * - * **Notes:** Default value: normal. - */ - container_queueFontWeight: 'normal', - - /** - * This sets the font size of External Container Queue shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_container_queueFontSize: 14, - /** - * This sets the font family of External Container Queue shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_container_queueFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External Container Queue shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_container_queueFontWeight: 'normal', - - /** - * This sets the font size of Component shape for the diagram - * - * **Notes:** Default value: 14. - */ - componentFontSize: 14, - /** - * This sets the font family of Component shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - componentFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Component shape for the diagram - * - * **Notes:** Default value: normal. - */ - componentFontWeight: 'normal', - - /** - * This sets the font size of External Component shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_componentFontSize: 14, - /** - * This sets the font family of External Component shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_componentFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External Component shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_componentFontWeight: 'normal', - - /** - * This sets the font size of Component DB shape for the diagram - * - * **Notes:** Default value: 14. - */ - component_dbFontSize: 14, - /** - * This sets the font family of Component DB shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - component_dbFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Component DB shape for the diagram - * - * **Notes:** Default value: normal. - */ - component_dbFontWeight: 'normal', - - /** - * This sets the font size of External Component DB shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_component_dbFontSize: 14, - /** - * This sets the font family of External Component DB shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_component_dbFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External Component DB shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_component_dbFontWeight: 'normal', - - /** - * This sets the font size of Component Queue shape for the diagram - * - * **Notes:** Default value: 14. - */ - component_queueFontSize: 14, - /** - * This sets the font family of Component Queue shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - component_queueFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of Component Queue shape for the diagram - * - * **Notes:** Default value: normal. - */ - component_queueFontWeight: 'normal', - - /** - * This sets the font size of External Component Queue shape for the diagram - * - * **Notes:** Default value: 14. - */ - external_component_queueFontSize: 14, - /** - * This sets the font family of External Component Queue shape for the diagram - * - * **Notes:** Default value: "Open Sans", sans-serif. - */ - external_component_queueFontFamily: '"Open Sans", sans-serif', - /** - * This sets the font weight of External Component Queue shape for the diagram - * - * **Notes:** Default value: normal. - */ - external_component_queueFontWeight: 'normal', - - /** - * This sets the auto-wrap state for the diagram - * - * **Notes:** Default value: true. - */ - wrap: true, - - /** - * This sets the auto-wrap padding for the diagram (sides only) - * - * **Notes:** Default value: 0. - */ - wrapPadding: 10, - personFont: function () { return { fontFamily: this.personFontFamily, @@ -2012,65 +231,30 @@ const config: Partial = { fontWeight: this.messageFontWeight, }; }, - - // ' Colors - // ' ################################## - person_bg_color: '#08427B', - person_border_color: '#073B6F', - external_person_bg_color: '#686868', - external_person_border_color: '#8A8A8A', - system_bg_color: '#1168BD', - system_border_color: '#3C7FC0', - system_db_bg_color: '#1168BD', - system_db_border_color: '#3C7FC0', - system_queue_bg_color: '#1168BD', - system_queue_border_color: '#3C7FC0', - external_system_bg_color: '#999999', - external_system_border_color: '#8A8A8A', - external_system_db_bg_color: '#999999', - external_system_db_border_color: '#8A8A8A', - external_system_queue_bg_color: '#999999', - external_system_queue_border_color: '#8A8A8A', - container_bg_color: '#438DD5', - container_border_color: '#3C7FC0', - container_db_bg_color: '#438DD5', - container_db_border_color: '#3C7FC0', - container_queue_bg_color: '#438DD5', - container_queue_border_color: '#3C7FC0', - external_container_bg_color: '#B3B3B3', - external_container_border_color: '#A6A6A6', - external_container_db_bg_color: '#B3B3B3', - external_container_db_border_color: '#A6A6A6', - external_container_queue_bg_color: '#B3B3B3', - external_container_queue_border_color: '#A6A6A6', - component_bg_color: '#85BBF0', - component_border_color: '#78A8D8', - component_db_bg_color: '#85BBF0', - component_db_border_color: '#78A8D8', - component_queue_bg_color: '#85BBF0', - component_queue_border_color: '#78A8D8', - external_component_bg_color: '#CCCCCC', - external_component_border_color: '#BFBFBF', - external_component_db_bg_color: '#CCCCCC', - external_component_db_border_color: '#BFBFBF', - external_component_queue_bg_color: '#CCCCCC', - external_component_queue_border_color: '#BFBFBF', }, - mindmap: { - useMaxWidth: true, - padding: 10, - maxNodeWidth: 200, + pie: { + ...defaultConfigJson.pie, + useWidth: 984, + }, + requirement: { + ...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, }, - fontSize: 16, }; -if (config.class) { - config.class.arrowMarkerAbsolute = config.arrowMarkerAbsolute; -} -if (config.gitGraph) { - config.gitGraph.arrowMarkerAbsolute = config.arrowMarkerAbsolute; -} - const keyify = (obj: any, prefix = ''): string[] => Object.keys(obj).reduce((res: string[], el): string[] => { if (Array.isArray(obj[el])) { @@ -2081,5 +265,5 @@ const keyify = (obj: any, prefix = ''): string[] => return [...res, prefix + el]; }, []); -export const configKeys: string[] = keyify(config, ''); +export const configKeys: Set = new Set(keyify(config, '')); export default config; diff --git a/packages/mermaid/src/diagram-api/comments.spec.ts b/packages/mermaid/src/diagram-api/comments.spec.ts new file mode 100644 index 000000000..57a7d4a34 --- /dev/null +++ b/packages/mermaid/src/diagram-api/comments.spec.ts @@ -0,0 +1,94 @@ +// tests to check that comments are removed + +import { cleanupComments } from './comments.js'; +import { describe, it, expect } from 'vitest'; + +describe('comments', () => { + it('should remove comments', () => { + const text = ` + +%% This is a comment +%% This is another comment +graph TD + A-->B +%% This is a comment +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + "graph TD + A-->B + " + `); + }); + + it('should keep init statements when removing comments', () => { + const text = ` +%% This is a comment + +%% This is another comment +%%{init: {'theme': 'forest'}}%% +%%{ init: {'theme': 'space before init'}}%% +%%{init: {'theme': 'space after ending'}}%% +graph TD + A-->B + + B-->C +%% This is a comment +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + "%%{init: {'theme': 'forest'}}%% + %%{ init: {'theme': 'space before init'}}%% + %%{init: {'theme': 'space after ending'}}%% + graph TD + A-->B + + B-->C + " + `); + }); + + it('should remove indented comments', () => { + const text = ` +%% This is a comment +graph TD + A-->B + %% This is a comment + C-->D +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + "graph TD + A-->B + C-->D + " + `); + }); + + it('should remove empty newlines from start', () => { + const text = ` + + + + +%% This is a comment +graph TD + A-->B +`; + expect(cleanupComments(text)).toMatchInlineSnapshot(` + "graph TD + A-->B + " + `); + }); + + it('should remove comments at end of text with no newline', () => { + const text = ` +graph TD + A-->B +%% This is a comment`; + + expect(cleanupComments(text)).toMatchInlineSnapshot(` + "graph TD + A-->B + " + `); + }); +}); diff --git a/packages/mermaid/src/diagram-api/comments.ts b/packages/mermaid/src/diagram-api/comments.ts new file mode 100644 index 000000000..be39b0a0f --- /dev/null +++ b/packages/mermaid/src/diagram-api/comments.ts @@ -0,0 +1,8 @@ +/** + * Remove all lines starting with `%%` from the text that don't contain a `%%{` + * @param text - The text to remove comments from + * @returns cleaned text + */ +export const cleanupComments = (text: string): string => { + return text.trimStart().replace(/^\s*%%(?!{)[^\n]+\n?/gm, ''); +}; diff --git a/packages/mermaid/src/diagram-api/detectType.ts b/packages/mermaid/src/diagram-api/detectType.ts index 3c9237e5b..ba78dbe55 100644 --- a/packages/mermaid/src/diagram-api/detectType.ts +++ b/packages/mermaid/src/diagram-api/detectType.ts @@ -1,18 +1,15 @@ -import { MermaidConfig } from '../config.type'; -import { log } from '../logger'; +import type { MermaidConfig } from '../config.type.js'; +import { log } from '../logger.js'; import type { DetectorRecord, DiagramDetector, DiagramLoader, ExternalDiagramDefinition, -} from './types'; -import { frontMatterRegex } from './frontmatter'; -import { UnknownDiagramError } from '../errors'; +} from './types.js'; +import { anyCommentRegex, directiveRegex, frontMatterRegex } from './regexes.js'; +import { UnknownDiagramError } from '../errors.js'; -const directive = /%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi; -const anyComment = /\s*%%.*\n/gm; - -const detectors: Record = {}; +export const detectors: Record = {}; /** * Detects the type of the graph text. @@ -37,7 +34,10 @@ const detectors: Record = {}; * @returns A graph definition key */ export const detectType = function (text: string, config?: MermaidConfig): string { - text = text.replace(frontMatterRegex, '').replace(directive, '').replace(anyComment, '\n'); + text = text + .replace(frontMatterRegex, '') + .replace(directiveRegex, '') + .replace(anyCommentRegex, '\n'); for (const [key, { detector }] of Object.entries(detectors)) { const diagram = detector(text, config); if (diagram) { @@ -45,9 +45,24 @@ export const detectType = function (text: string, config?: MermaidConfig): strin } } - throw new UnknownDiagramError(`No diagram type detected for text: ${text}`); + throw new UnknownDiagramError( + `No diagram type detected matching given configuration for text: ${text}` + ); }; +/** + * Registers lazy-loaded diagrams to Mermaid. + * + * The diagram function is loaded asynchronously, so that diagrams are only loaded + * if the diagram is detected. + * + * @remarks + * Please note that the order of diagram detectors is important. + * The first detector to return `true` is the diagram that will be loaded + * and used, so put more specific detectors at the beginning! + * + * @param diagrams - Diagrams to lazy load, and their detectors, in order of importance. + */ export const registerLazyLoadedDiagrams = (...diagrams: ExternalDiagramDefinition[]) => { for (const { id, detector, loader } of diagrams) { addDetector(id, detector, loader); @@ -63,4 +78,6 @@ export const addDetector = (key: string, detector: DiagramDetector, loader?: Dia log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`); }; -export const getDiagramLoader = (key: string) => detectors[key].loader; +export const getDiagramLoader = (key: string) => { + return detectors[key].loader; +}; diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.spec.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.spec.ts new file mode 100644 index 000000000..d6c6b3046 --- /dev/null +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.spec.ts @@ -0,0 +1,82 @@ +import { it, describe, expect } from 'vitest'; +import { detectType } from './detectType.js'; +import { addDiagrams } from './diagram-orchestration.js'; + +describe('diagram-orchestration', () => { + it('should register diagrams', () => { + expect(() => detectType('graph TD; A-->B')).toThrow(); + addDiagrams(); + expect(detectType('graph TD; A-->B')).toBe('flowchart'); + }); + + describe('proper diagram types should be detetced', () => { + beforeAll(() => { + addDiagrams(); + }); + + it.each([ + { text: 'graph TD;', expected: 'flowchart' }, + { text: 'flowchart TD;', expected: 'flowchart-v2' }, + { text: 'flowchart-v2 TD;', expected: 'flowchart-v2' }, + { text: 'flowchart-elk TD;', expected: 'flowchart-elk' }, + { text: 'error', expected: 'error' }, + { text: 'C4Context;', expected: 'c4' }, + { text: 'classDiagram', expected: 'class' }, + { text: 'classDiagram-v2', expected: 'classDiagram' }, + { text: 'erDiagram', expected: 'er' }, + { text: 'journey', expected: 'journey' }, + { text: 'gantt', expected: 'gantt' }, + { text: 'pie', expected: 'pie' }, + { text: 'requirementDiagram', expected: 'requirement' }, + { text: 'info', expected: 'info' }, + { text: 'sequenceDiagram', expected: 'sequence' }, + { text: 'mindmap', expected: 'mindmap' }, + { text: 'timeline', expected: 'timeline' }, + { text: 'gitGraph', expected: 'gitGraph' }, + { text: 'stateDiagram', expected: 'state' }, + { text: 'stateDiagram-v2', expected: 'stateDiagram' }, + ])( + 'should $text be detected as $expected', + ({ text, expected }: { text: string; expected: string }) => { + expect(detectType(text)).toBe(expected); + } + ); + + it('should detect proper flowchart type based on config', () => { + // graph & dagre-d3 => flowchart + expect(detectType('graph TD; A-->B')).toBe('flowchart'); + // graph & dagre-d3 => flowchart + expect(detectType('graph TD; A-->B', { flowchart: { defaultRenderer: 'dagre-d3' } })).toBe( + 'flowchart' + ); + // flowchart & dagre-d3 => error + expect(() => + detectType('flowchart TD; A-->B', { flowchart: { defaultRenderer: 'dagre-d3' } }) + ).toThrowErrorMatchingInlineSnapshot( + '"No diagram type detected matching given configuration for text: flowchart TD; A-->B"' + ); + + // graph & dagre-wrapper => flowchart-v2 + expect( + detectType('graph TD; A-->B', { flowchart: { defaultRenderer: 'dagre-wrapper' } }) + ).toBe('flowchart-v2'); + // flowchart ==> flowchart-v2 + expect(detectType('flowchart TD; A-->B')).toBe('flowchart-v2'); + // flowchart && dagre-wrapper ==> flowchart-v2 + expect( + detectType('flowchart TD; A-->B', { flowchart: { defaultRenderer: 'dagre-wrapper' } }) + ).toBe('flowchart-v2'); + // flowchart && elk ==> flowchart-elk + expect(detectType('flowchart TD; A-->B', { flowchart: { defaultRenderer: 'elk' } })).toBe( + 'flowchart-elk' + ); + }); + + it('should not detect flowchart if pie contains flowchart', () => { + expect( + detectType(`pie title: "flowchart" + flowchart: 1 "pie" pie: 2 "pie"`) + ).toBe('pie'); + }); + }); +}); diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts index a68e99dd0..80665cfa2 100644 --- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts @@ -1,104 +1,26 @@ -import { registerDiagram } from './diagramAPI'; -// @ts-ignore: TODO Fix ts errors -import gitGraphParser from '../diagrams/git/parser/gitGraph'; -import { gitGraphDetector } from '../diagrams/git/gitGraphDetector'; -import gitGraphDb from '../diagrams/git/gitGraphAst'; -import gitGraphRenderer from '../diagrams/git/gitGraphRenderer'; -import gitGraphStyles from '../diagrams/git/styles'; - -// @ts-ignore: TODO Fix ts errors -import c4Parser from '../diagrams/c4/parser/c4Diagram'; -import { c4Detector } from '../diagrams/c4/c4Detector'; -import c4Db from '../diagrams/c4/c4Db'; -import c4Renderer from '../diagrams/c4/c4Renderer'; -import c4Styles from '../diagrams/c4/styles'; - -// @ts-ignore: TODO Fix ts errors -import classParser from '../diagrams/class/parser/classDiagram'; -import { classDetector } from '../diagrams/class/classDetector'; -import { classDetectorV2 } from '../diagrams/class/classDetector-V2'; -import classDb from '../diagrams/class/classDb'; -import classRenderer from '../diagrams/class/classRenderer'; -import classRendererV2 from '../diagrams/class/classRenderer-v2'; -import classStyles from '../diagrams/class/styles'; - -// @ts-ignore: TODO Fix ts errors -import erParser from '../diagrams/er/parser/erDiagram'; -import { erDetector } from '../diagrams/er/erDetector'; -import erDb from '../diagrams/er/erDb'; -import erRenderer from '../diagrams/er/erRenderer'; -import erStyles from '../diagrams/er/styles'; - -// @ts-ignore: TODO Fix ts errors -import flowParser from '../diagrams/flowchart/parser/flow'; -import { flowDetector } from '../diagrams/flowchart/flowDetector'; -import { flowDetectorV2 } from '../diagrams/flowchart/flowDetector-v2'; -import flowDb from '../diagrams/flowchart/flowDb'; -import flowRenderer from '../diagrams/flowchart/flowRenderer'; -import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; -import flowStyles from '../diagrams/flowchart/styles'; - -// @ts-ignore: TODO Fix ts errors -import ganttParser from '../diagrams/gantt/parser/gantt'; -import { ganttDetector } from '../diagrams/gantt/ganttDetector'; -import ganttDb from '../diagrams/gantt/ganttDb'; -import ganttRenderer from '../diagrams/gantt/ganttRenderer'; -import ganttStyles from '../diagrams/gantt/styles'; - -// @ts-ignore: TODO Fix ts errors -import infoParser from '../diagrams/info/parser/info'; -import infoDb from '../diagrams/info/infoDb'; -import infoRenderer from '../diagrams/info/infoRenderer'; -import { infoDetector } from '../diagrams/info/infoDetector'; -import infoStyles from '../diagrams/info/styles'; - -// @ts-ignore: TODO Fix ts errors -import pieParser from '../diagrams/pie/parser/pie'; -import { pieDetector } from '../diagrams/pie/pieDetector'; -import pieDb from '../diagrams/pie/pieDb'; -import pieRenderer from '../diagrams/pie/pieRenderer'; -import pieStyles from '../diagrams/pie/styles'; - -// @ts-ignore: TODO Fix ts errors -import requirementParser from '../diagrams/requirement/parser/requirementDiagram'; -import { requirementDetector } from '../diagrams/requirement/requirementDetector'; -import requirementDb from '../diagrams/requirement/requirementDb'; -import requirementRenderer from '../diagrams/requirement/requirementRenderer'; -import requirementStyles from '../diagrams/requirement/styles'; - -// @ts-ignore: TODO Fix ts errors -import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram'; -import { sequenceDetector } from '../diagrams/sequence/sequenceDetector'; -import sequenceDb from '../diagrams/sequence/sequenceDb'; -import sequenceRenderer from '../diagrams/sequence/sequenceRenderer'; -import sequenceStyles from '../diagrams/sequence/styles'; - -// @ts-ignore: TODO Fix ts errors -import stateParser from '../diagrams/state/parser/stateDiagram'; -import { stateDetector } from '../diagrams/state/stateDetector'; -import { stateDetectorV2 } from '../diagrams/state/stateDetector-V2'; -import stateDb from '../diagrams/state/stateDb'; -import stateRenderer from '../diagrams/state/stateRenderer'; -import stateRendererV2 from '../diagrams/state/stateRenderer-v2'; -import stateStyles from '../diagrams/state/styles'; - -// @ts-ignore: TODO Fix ts errors -import journeyParser from '../diagrams/user-journey/parser/journey'; -import { journeyDetector } from '../diagrams/user-journey/journeyDetector'; -import journeyDb from '../diagrams/user-journey/journeyDb'; -import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; -import journeyStyles from '../diagrams/user-journey/styles'; -import { setConfig } from '../config'; - -import errorRenderer from '../diagrams/error/errorRenderer'; -import errorStyles from '../diagrams/error/styles'; - -import flowchartElk from '../diagrams/flowchart/elk/detector'; -import { registerLazyLoadedDiagrams } from './detectType'; - -// Lazy loaded diagrams -import timelineDetector from '../diagrams/timeline/detector'; -import mindmapDetector from '../diagrams/mindmap/detector'; +import c4 from '../diagrams/c4/c4Detector.js'; +import flowchart from '../diagrams/flowchart/flowDetector.js'; +import flowchartV2 from '../diagrams/flowchart/flowDetector-v2.js'; +import er from '../diagrams/er/erDetector.js'; +import git from '../diagrams/git/gitGraphDetector.js'; +import gantt from '../diagrams/gantt/ganttDetector.js'; +import { info } from '../diagrams/info/infoDetector.js'; +import { pie } from '../diagrams/pie/pieDetector.js'; +import quadrantChart from '../diagrams/quadrant-chart/quadrantDetector.js'; +import requirement from '../diagrams/requirement/requirementDetector.js'; +import sequence from '../diagrams/sequence/sequenceDetector.js'; +import classDiagram from '../diagrams/class/classDetector.js'; +import classDiagramV2 from '../diagrams/class/classDetector-V2.js'; +import state from '../diagrams/state/stateDetector.js'; +import stateV2 from '../diagrams/state/stateDetector-V2.js'; +import journey from '../diagrams/user-journey/journeyDetector.js'; +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 sankey from '../diagrams/sankey/sankeyDetector.js'; +import { registerLazyLoadedDiagrams } from './detectType.js'; +import { registerDiagram } from './diagramAPI.js'; let hasLoadedDiagrams = false; export const addDiagrams = () => { @@ -108,31 +30,9 @@ export const addDiagrams = () => { // This is added here to avoid race-conditions. // We could optimize the loading logic somehow. hasLoadedDiagrams = true; - registerLazyLoadedDiagrams(flowchartElk, timelineDetector, mindmapDetector); - - registerDiagram( - 'error', - // Special diagram with error messages but setup as a regular diagram - { - db: { - clear: () => { - // Quite ok, clear needs to be there for error to work as a regular diagram - }, - }, - styles: errorStyles, - renderer: errorRenderer, - parser: { - parser: { yy: {} }, - parse: () => { - // no op - }, - }, - init: () => { - // no op - }, - }, - (text) => text.toLowerCase().trim() === 'error' - ); + registerDiagram('error', errorDiagram, (text) => { + return text.toLowerCase().trim() === 'error'; + }); registerDiagram( '---', // --- diagram type may appear if YAML front-matter is not parsed correctly @@ -142,15 +42,15 @@ export const addDiagrams = () => { // Quite ok, clear needs to be there for --- to work as a regular diagram }, }, - styles: errorStyles, // should never be used - renderer: errorRenderer, // should never be used + styles: {}, // should never be used + renderer: {}, // should never be used parser: { parser: { yy: {} }, parse: () => { throw new Error( 'Diagrams beginning with --- are not valid. ' + 'If you were trying to use a YAML front-matter, please ensure that ' + - "you've correctly opened and closed the YAML front-matter with unindented `---` blocks" + "you've correctly opened and closed the YAML front-matter with un-indented `---` blocks" ); }, }, @@ -160,220 +60,27 @@ export const addDiagrams = () => { return text.toLowerCase().trimStart().startsWith('---'); } ); - - registerDiagram( - 'c4', - { - parser: c4Parser, - db: c4Db, - renderer: c4Renderer, - styles: c4Styles, - init: (cnf) => { - c4Renderer.setConf(cnf.c4); - }, - }, - c4Detector - ); - registerDiagram( - 'class', - { - parser: classParser, - db: classDb, - renderer: classRenderer, - styles: classStyles, - init: (cnf) => { - if (!cnf.class) { - cnf.class = {}; - } - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - classDb.clear(); - }, - }, - classDetector - ); - registerDiagram( - 'classDiagram', - { - parser: classParser, - db: classDb, - renderer: classRendererV2, - styles: classStyles, - init: (cnf) => { - if (!cnf.class) { - cnf.class = {}; - } - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - classDb.clear(); - }, - }, - classDetectorV2 - ); - registerDiagram( - 'er', - { - parser: erParser, - db: erDb, - renderer: erRenderer, - styles: erStyles, - }, - erDetector - ); - registerDiagram( - 'gantt', - { - parser: ganttParser, - db: ganttDb, - renderer: ganttRenderer, - styles: ganttStyles, - }, - ganttDetector - ); - registerDiagram( - 'info', - { - parser: infoParser, - db: infoDb, - renderer: infoRenderer, - styles: infoStyles, - }, - infoDetector - ); - registerDiagram( - 'pie', - { - parser: pieParser, - db: pieDb, - renderer: pieRenderer, - styles: pieStyles, - }, - pieDetector - ); - registerDiagram( - 'requirement', - { - parser: requirementParser, - db: requirementDb, - renderer: requirementRenderer, - styles: requirementStyles, - }, - requirementDetector - ); - registerDiagram( - 'sequence', - { - parser: sequenceParser, - db: sequenceDb, - renderer: sequenceRenderer, - styles: sequenceStyles, - init: (cnf) => { - if (!cnf.sequence) { - cnf.sequence = {}; - } - cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - if ('sequenceDiagram' in cnf) { - throw new Error( - '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' - ); - } - sequenceDb.setWrap(cnf.wrap); - sequenceRenderer.setConf(cnf.sequence); - }, - }, - sequenceDetector - ); - registerDiagram( - 'state', - { - parser: stateParser, - db: stateDb, - renderer: stateRenderer, - styles: stateStyles, - init: (cnf) => { - if (!cnf.state) { - cnf.state = {}; - } - cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - stateDb.clear(); - }, - }, - stateDetector - ); - registerDiagram( - 'stateDiagram', - { - parser: stateParser, - db: stateDb, - renderer: stateRendererV2, - styles: stateStyles, - init: (cnf) => { - if (!cnf.state) { - cnf.state = {}; - } - cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - stateDb.clear(); - }, - }, - stateDetectorV2 - ); - registerDiagram( - 'journey', - { - parser: journeyParser, - db: journeyDb, - renderer: journeyRenderer, - styles: journeyStyles, - init: (cnf) => { - journeyRenderer.setConf(cnf.journey); - journeyDb.clear(); - }, - }, - journeyDetector - ); - - registerDiagram( - 'flowchart', - { - parser: flowParser, - db: flowDb, - renderer: flowRendererV2, - styles: flowStyles, - init: (cnf) => { - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - // TODO, broken as of 2022-09-14 (13809b50251845475e6dca65cc395761be38fbd2) - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowRenderer.setConf(cnf.flowchart); - flowDb.clear(); - flowDb.setGen('gen-1'); - }, - }, - flowDetector - ); - registerDiagram( - 'flowchart-v2', - { - parser: flowParser, - db: flowDb, - renderer: flowRendererV2, - styles: flowStyles, - init: (cnf) => { - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - // flowchart-v2 uses dagre-wrapper, which doesn't have access to flowchart cnf - setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } }); - flowRendererV2.setConf(cnf.flowchart); - flowDb.clear(); - flowDb.setGen('gen-2'); - }, - }, - flowDetectorV2 - ); - registerDiagram( - 'gitGraph', - { parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles }, - gitGraphDetector + // Ordering of detectors is important. The first one to return true will be used. + registerLazyLoadedDiagrams( + c4, + classDiagramV2, + classDiagram, + er, + gantt, + info, + pie, + requirement, + sequence, + flowchartElk, + flowchartV2, + flowchart, + mindmap, + timeline, + git, + stateV2, + state, + journey, + quadrantChart, + sankey ); }; diff --git a/packages/mermaid/src/diagram-api/diagramAPI.spec.ts b/packages/mermaid/src/diagram-api/diagramAPI.spec.ts index ea546fbb6..b82011f8d 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.spec.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.spec.ts @@ -1,9 +1,14 @@ -import { detectType } from './detectType'; -import { getDiagram, registerDiagram } from './diagramAPI'; -import { addDiagrams } from './diagram-orchestration'; -import { DiagramDetector } from './types'; +import { detectType } from './detectType.js'; +import { getDiagram, registerDiagram } from './diagramAPI.js'; +import { addDiagrams } from './diagram-orchestration.js'; +import type { DiagramDetector } from './types.js'; +import { getDiagramFromText } from '../Diagram.js'; +import { it, describe, expect, beforeAll } from 'vitest'; addDiagrams(); +beforeAll(async () => { + await getDiagramFromText('sequenceDiagram'); +}); describe('DiagramAPI', () => { it('should return default diagrams', () => { @@ -11,13 +16,17 @@ describe('DiagramAPI', () => { }); it('should throw error if diagram is not defined', () => { - expect(() => getDiagram('loki')).toThrow(); + expect(() => getDiagram('loki')).toThrowErrorMatchingInlineSnapshot( + '"Diagram loki not found."' + ); }); it('should handle diagram registrations', () => { - expect(() => getDiagram('loki')).toThrow(); - expect(() => detectType('loki diagram')).toThrow( - 'No diagram type detected for text: loki diagram' + expect(() => getDiagram('loki')).toThrowErrorMatchingInlineSnapshot( + '"Diagram loki not found."' + ); + expect(() => detectType('loki diagram')).toThrowErrorMatchingInlineSnapshot( + '"No diagram type detected matching given configuration for text: loki diagram"' ); const detector: DiagramDetector = (str: string) => { return str.match('loki') !== null; @@ -26,7 +35,12 @@ describe('DiagramAPI', () => { 'loki', { db: {}, - parser: {}, + parser: { + parse: (_text) => { + return; + }, + parser: { yy: {} }, + }, renderer: {}, styles: {}, }, diff --git a/packages/mermaid/src/diagram-api/diagramAPI.ts b/packages/mermaid/src/diagram-api/diagramAPI.ts index 936e43efd..6f1421527 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.ts @@ -1,12 +1,12 @@ -import { addDetector } from './detectType'; -import { log as _log, setLogLevel as _setLogLevel } from '../logger'; -import { getConfig as _getConfig } from '../config'; -import { sanitizeText as _sanitizeText } from '../diagrams/common/common'; -import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox'; -import { addStylesForDiagram } from '../styles'; -import { DiagramDefinition, DiagramDetector } from './types'; -import * as _commonDb from '../commonDb'; -import { parseDirective as _parseDirective } from '../directiveUtils'; +import { addDetector } from './detectType.js'; +import { log as _log, setLogLevel as _setLogLevel } from '../logger.js'; +import { getConfig as _getConfig } from '../config.js'; +import { sanitizeText as _sanitizeText } from '../diagrams/common/common.js'; +import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox.js'; +import { addStylesForDiagram } from '../styles.js'; +import type { DiagramDefinition, DiagramDetector } from './types.js'; +import * as _commonDb from '../diagrams/common/commonDb.js'; +import { parseDirective as _parseDirective } from '../directiveUtils.js'; /* Packaging and exposing resources for external diagrams so that they can import @@ -69,5 +69,11 @@ export const getDiagram = (name: string): DiagramDefinition => { if (name in diagrams) { return diagrams[name]; } - throw new Error(`Diagram ${name} not found.`); + throw new DiagramNotFoundError(name); }; + +export class DiagramNotFoundError extends Error { + constructor(name: string) { + super(`Diagram ${name} not found.`); + } +} diff --git a/packages/mermaid/src/diagram-api/frontmatter.spec.ts b/packages/mermaid/src/diagram-api/frontmatter.spec.ts index 4eb9789e2..03d46c300 100644 --- a/packages/mermaid/src/diagram-api/frontmatter.spec.ts +++ b/packages/mermaid/src/diagram-api/frontmatter.spec.ts @@ -1,9 +1,14 @@ import { vi } from 'vitest'; -import { extractFrontMatter } from './frontmatter'; +import { extractFrontMatter } from './frontmatter.js'; const dbMock = () => ({ setDiagramTitle: vi.fn() }); +const setConfigMock = vi.fn(); describe('extractFrontmatter', () => { + beforeEach(() => { + setConfigMock.mockClear(); + }); + it('returns text unchanged if no frontmatter', () => { expect(extractFrontMatter('diagram', dbMock())).toEqual('diagram'); }); @@ -75,4 +80,21 @@ describe('extractFrontmatter', () => { 'tag suffix cannot contain exclamation marks' ); }); + + it('handles frontmatter with config', () => { + const text = `--- +title: hello +config: + graph: + string: hello + number: 14 + boolean: false + array: [1, 2, 3] +--- +diagram`; + expect(extractFrontMatter(text, {}, setConfigMock)).toEqual('diagram'); + expect(setConfigMock).toHaveBeenCalledWith({ + graph: { string: 'hello', number: 14, boolean: false, array: [1, 2, 3] }, + }); + }); }); diff --git a/packages/mermaid/src/diagram-api/frontmatter.ts b/packages/mermaid/src/diagram-api/frontmatter.ts index d6811388c..0fd2917ea 100644 --- a/packages/mermaid/src/diagram-api/frontmatter.ts +++ b/packages/mermaid/src/diagram-api/frontmatter.ts @@ -1,40 +1,53 @@ -import { DiagramDb } from './types'; +import type { MermaidConfig } from '../config.type.js'; +import { frontMatterRegex } from './regexes.js'; +import type { DiagramDB } from './types.js'; // The "* as yaml" part is necessary for tree-shaking import * as yaml from 'js-yaml'; -// Match Jekyll-style front matter blocks (https://jekyllrb.com/docs/front-matter/). -// Based on regex used by Jekyll: https://github.com/jekyll/jekyll/blob/6dd3cc21c40b98054851846425af06c64f9fb466/lib/jekyll/document.rb#L10 -// Note that JS doesn't support the "\A" anchor, which means we can't use -// multiline mode. -// Relevant YAML spec: https://yaml.org/spec/1.2.2/#914-explicit-documents -export const frontMatterRegex = /^-{3}\s*[\n\r](.*?)[\n\r]-{3}\s*[\n\r]+/s; - -type FrontMatterMetadata = { +interface FrontMatterMetadata { title?: string; -}; + // Allows custom display modes. Currently used for compact mode in gantt charts. + displayMode?: string; + config?: MermaidConfig; +} /** * Extract and parse frontmatter from text, if present, and sets appropriate * properties in the provided db. * @param text - The text that may have a YAML frontmatter. * @param db - Diagram database, could be of any diagram. + * @param setDiagramConfig - Optional function to set diagram config. * @returns text with frontmatter stripped out */ -export function extractFrontMatter(text: string, db: DiagramDb): string { +export function extractFrontMatter( + text: string, + db: DiagramDB, + setDiagramConfig?: (config: MermaidConfig) => void +): string { const matches = text.match(frontMatterRegex); - if (matches) { - const parsed: FrontMatterMetadata = yaml.load(matches[1], { - // To keep things simple, only allow strings, arrays, and plain objects. - // https://www.yaml.org/spec/1.2/spec.html#id2802346 - schema: yaml.FAILSAFE_SCHEMA, - }) as FrontMatterMetadata; - - if (parsed?.title) { - db.setDiagramTitle?.(parsed.title); - } - - return text.slice(matches[0].length); - } else { + if (!matches) { return text; } + + const parsed: FrontMatterMetadata = yaml.load(matches[1], { + // To support config, we need JSON schema. + // https://www.yaml.org/spec/1.2/spec.html#id2803231 + schema: yaml.JSON_SCHEMA, + }) as FrontMatterMetadata; + + if (parsed?.title) { + // toString() is necessary because YAML could parse the title as a number/boolean + db.setDiagramTitle?.(parsed.title.toString()); + } + + if (parsed?.displayMode) { + // toString() is necessary because YAML could parse the title as a number/boolean + db.setDisplayMode?.(parsed.displayMode.toString()); + } + + if (parsed?.config) { + setDiagramConfig?.(parsed.config); + } + + return text.slice(matches[0].length); } diff --git a/packages/mermaid/src/diagram-api/loadDiagram.ts b/packages/mermaid/src/diagram-api/loadDiagram.ts new file mode 100644 index 000000000..c1b445bf6 --- /dev/null +++ b/packages/mermaid/src/diagram-api/loadDiagram.ts @@ -0,0 +1,36 @@ +import { log } from '../logger.js'; +import { detectors } from './detectType.js'; +import { getDiagram, registerDiagram } from './diagramAPI.js'; + +export const loadRegisteredDiagrams = async () => { + log.debug(`Loading registered diagrams`); + // Load all lazy loaded diagrams in parallel + const results = await Promise.allSettled( + Object.entries(detectors).map(async ([key, { detector, loader }]) => { + if (loader) { + try { + getDiagram(key); + } catch (error) { + try { + // Register diagram if it is not already registered + const { diagram, id } = await loader(); + registerDiagram(id, diagram, detector); + } catch (err) { + // Remove failed diagram from detectors + log.error(`Failed to load external diagram with key ${key}. Removing from detectors.`); + delete detectors[key]; + throw err; + } + } + } + }) + ); + const failed = results.filter((result) => result.status === 'rejected'); + if (failed.length > 0) { + log.error(`Failed to load ${failed.length} external diagrams`); + for (const res of failed) { + log.error(res); + } + throw new Error(`Failed to load ${failed.length} external diagrams`); + } +}; diff --git a/packages/mermaid/src/diagram-api/regexes.ts b/packages/mermaid/src/diagram-api/regexes.ts new file mode 100644 index 000000000..bb688b9c2 --- /dev/null +++ b/packages/mermaid/src/diagram-api/regexes.ts @@ -0,0 +1,11 @@ +// Match Jekyll-style front matter blocks (https://jekyllrb.com/docs/front-matter/). +// Based on regex used by Jekyll: https://github.com/jekyll/jekyll/blob/6dd3cc21c40b98054851846425af06c64f9fb466/lib/jekyll/document.rb#L10 +// Note that JS doesn't support the "\A" anchor, which means we can't use +// multiline mode. +// Relevant YAML spec: https://yaml.org/spec/1.2.2/#914-explicit-documents +export const frontMatterRegex = /^-{3}\s*[\n\r](.*?)[\n\r]-{3}\s*[\n\r]+/s; + +export const directiveRegex = + /%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi; + +export const anyCommentRegex = /\s*%%.*\n/gm; diff --git a/packages/mermaid/src/diagram-api/types.ts b/packages/mermaid/src/diagram-api/types.ts index 081136563..2ac7fba12 100644 --- a/packages/mermaid/src/diagram-api/types.ts +++ b/packages/mermaid/src/diagram-api/types.ts @@ -1,4 +1,6 @@ -import { MermaidConfig } from '../config.type'; +import type { Diagram } from '../Diagram.js'; +import type { BaseDiagramConfig, MermaidConfig } from '../config.type.js'; +import type * as d3 from 'd3'; export interface InjectUtils { _log: any; @@ -13,19 +15,28 @@ export interface InjectUtils { /** * Generic Diagram DB that may apply to any diagram type. */ -export interface DiagramDb { +export interface DiagramDB { + // config + getConfig?: () => BaseDiagramConfig | undefined; + + // db clear?: () => void; setDiagramTitle?: (title: string) => void; + getDiagramTitle?: () => string; + setAccTitle?: (title: string) => void; getAccTitle?: () => string; + setAccDescription?: (describetion: string) => void; getAccDescription?: () => string; + + setDisplayMode?: (title: string) => void; bindFunctions?: (element: Element) => void; } export interface DiagramDefinition { - db: DiagramDb; + db: DiagramDB; renderer: any; - parser: any; - styles: any; + parser: ParserDefinition; + styles?: any; init?: (config: MermaidConfig) => void; injectUtils?: ( _log: InjectUtils['_log'], @@ -51,3 +62,40 @@ export interface ExternalDiagramDefinition { export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean; export type DiagramLoader = () => Promise<{ id: string; diagram: DiagramDefinition }>; + +/** + * Type for function draws diagram in the tag with id: id based on the graph definition in text. + * + * @param text - The text of the diagram. + * @param id - The id of the diagram which will be used as a DOM element id. + * @param version - MermaidJS version from package.json. + * @param diagramObject - A standard diagram containing the DB and the text and type etc of the diagram. + */ +export type DrawDefinition = ( + text: string, + id: string, + version: string, + diagramObject: Diagram +) => void; + +export interface ParserDefinition { + parse: (text: string) => void; + parser: { yy: DiagramDB }; +} + +/** + * Type for function parse directive from diagram code. + * + * @param statement - + * @param context - + * @param type - + */ +export type ParseDirectiveDefinition = (statement: string, context: string, type: string) => void; + +export type HTML = d3.Selection; + +export type SVG = d3.Selection; + +export type Group = 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 a862c7936..99ce4e2c6 100644 --- a/packages/mermaid/src/diagram.spec.ts +++ b/packages/mermaid/src/diagram.spec.ts @@ -1,7 +1,7 @@ import { describe, test, expect } from 'vitest'; -import { Diagram, getDiagramFromText } from './Diagram'; -import { addDetector } from './diagram-api/detectType'; -import { addDiagrams } from './diagram-api/diagram-orchestration'; +import { Diagram, getDiagramFromText } from './Diagram.js'; +import { addDetector } from './diagram-api/detectType.js'; +import { addDiagrams } from './diagram-api/diagram-orchestration.js'; addDiagrams(); @@ -49,7 +49,7 @@ describe('diagram detection', () => { "Parse error on line 2: graph TD; A--> --------------^ - Expecting 'AMP', 'ALPHA', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'MINUS', 'BRKT', 'DOT', 'PUNCTUATION', 'UNICODE_TEXT', 'PLUS', 'EQUALS', 'MULT', 'UNDERSCORE', got 'EOF'" + Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'EOF'" `); await expect(getDiagramFromText('sequenceDiagram; A-->B')).rejects .toThrowErrorMatchingInlineSnapshot(` @@ -61,8 +61,8 @@ Expecting 'TXT', got 'NEWLINE'" }); test('should throw the right error for unregistered diagrams', async () => { - await expect(getDiagramFromText('thor TD; A-->B')).rejects.toThrowError( - 'No diagram type detected for text: thor TD; A-->B' + await expect(getDiagramFromText('thor TD; A-->B')).rejects.toThrowErrorMatchingInlineSnapshot( + '"No diagram type detected matching given configuration for text: thor TD; A-->B"' ); }); }); diff --git a/packages/mermaid/src/diagrams/c4/c4Db.js b/packages/mermaid/src/diagrams/c4/c4Db.js index d337b15c0..7c450940f 100644 --- a/packages/mermaid/src/diagrams/c4/c4Db.js +++ b/packages/mermaid/src/diagrams/c4/c4Db.js @@ -1,7 +1,12 @@ -import mermaidAPI from '../../mermaidAPI'; -import * as configApi from '../../config'; -import { sanitizeText } from '../common/common'; -import { setAccTitle, getAccTitle, getAccDescription, setAccDescription } from '../../commonDb'; +import mermaidAPI from '../../mermaidAPI.js'; +import * as configApi from '../../config.js'; +import { sanitizeText } from '../common/common.js'; +import { + setAccTitle, + getAccTitle, + getAccDescription, + setAccDescription, +} from '../common/commonDb.js'; let c4ShapeArray = []; let boundaryParseStack = ['']; diff --git a/packages/mermaid/src/diagrams/c4/c4Detector.ts b/packages/mermaid/src/diagrams/c4/c4Detector.ts index 49ba95b8e..b06ab6cb1 100644 --- a/packages/mermaid/src/diagrams/c4/c4Detector.ts +++ b/packages/mermaid/src/diagrams/c4/c4Detector.ts @@ -1,5 +1,24 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const c4Detector: DiagramDetector = (txt) => { - return txt.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/) !== null; +const id = 'c4'; + +const detector: DiagramDetector = (txt) => { + return /^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./c4Diagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/c4/c4Diagram.ts b/packages/mermaid/src/diagrams/c4/c4Diagram.ts new file mode 100644 index 000000000..4c578b624 --- /dev/null +++ b/packages/mermaid/src/diagrams/c4/c4Diagram.ts @@ -0,0 +1,17 @@ +// @ts-ignore: JISON doesn't support types +import c4Parser from './parser/c4Diagram.jison'; +import c4Db from './c4Db.js'; +import c4Renderer from './c4Renderer.js'; +import c4Styles from './styles.js'; +import type { MermaidConfig } from '../../config.type.js'; +import type { DiagramDefinition } from '../../diagram-api/types.js'; + +export const diagram: DiagramDefinition = { + parser: c4Parser, + db: c4Db, + renderer: c4Renderer, + styles: c4Styles, + init: (cnf: MermaidConfig) => { + c4Renderer.setConf(cnf.c4); + }, +}; diff --git a/packages/mermaid/src/diagrams/c4/c4Renderer.js b/packages/mermaid/src/diagrams/c4/c4Renderer.js index a51fe0b6a..e60e58f21 100644 --- a/packages/mermaid/src/diagrams/c4/c4Renderer.js +++ b/packages/mermaid/src/diagrams/c4/c4Renderer.js @@ -1,13 +1,13 @@ import { select } from 'd3'; -import svgDraw from './svgDraw'; -import { log } from '../../logger'; -import { parser } from './parser/c4Diagram'; -import common from '../common/common'; -import c4Db from './c4Db'; -import * as configApi from '../../config'; -import assignWithDepth from '../../assignWithDepth'; -import { wrapLabel, calculateTextWidth, calculateTextHeight } from '../../utils'; -import { configureSvgSize } from '../../setupGraphViewbox'; +import svgDraw from './svgDraw.js'; +import { log } from '../../logger.js'; +import { parser } from './parser/c4Diagram.jison'; +import common from '../common/common.js'; +import c4Db from './c4Db.js'; +import * as configApi from '../../config.js'; +import assignWithDepth from '../../assignWithDepth.js'; +import { wrapLabel, calculateTextWidth, calculateTextHeight } from '../../utils.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; let globalBoundaryMaxX = 0, globalBoundaryMaxY = 0; @@ -220,7 +220,7 @@ export const drawC4ShapeArray = function (currentBounds, diagram, c4ShapeArray, let c4ShapeTypeConf = c4ShapeFont(conf, c4Shape.typeC4Shape.text); c4ShapeTypeConf.fontSize = c4ShapeTypeConf.fontSize - 2; c4Shape.typeC4Shape.width = calculateTextWidth( - '<<' + c4Shape.typeC4Shape.text + '>>', + '«' + c4Shape.typeC4Shape.text + '»', c4ShapeTypeConf ); c4Shape.typeC4Shape.height = c4ShapeTypeConf.fontSize + 2; diff --git a/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js b/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js index c7130f557..f43f00748 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js +++ b/packages/mermaid/src/diagrams/c4/parser/c4Boundary.spec.js @@ -1,6 +1,6 @@ -import c4Db from '../c4Db'; +import c4Db from '../c4Db.js'; import c4 from './c4Diagram.jison'; -import { setConfig } from '../../../config'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/c4/parser/c4Container.spec.js b/packages/mermaid/src/diagrams/c4/parser/c4Container.spec.js new file mode 100644 index 000000000..76dca3bc2 --- /dev/null +++ b/packages/mermaid/src/diagrams/c4/parser/c4Container.spec.js @@ -0,0 +1,135 @@ +import c4Db from '../c4Db.js'; +import c4 from './c4Diagram.jison'; +import { setConfig } from '../../../config.js'; + +setConfig({ + securityLevel: 'strict', +}); + +describe.each([ + ['Container', 'container'], + ['ContainerDb', 'container_db'], + ['ContainerQueue', 'container_queue'], + ['Container_Ext', 'external_container'], + ['ContainerDb_Ext', 'external_container_db'], + ['ContainerQueue_Ext', 'external_container_queue'], +])('parsing a C4 %s', function (macroName, elementName) { + beforeEach(function () { + c4.parser.yy = c4Db; + c4.parser.yy.clear(); + }); + + it('should parse a C4 diagram with one Container correctly', function () { + c4.parser.parse(`C4Context +title Container diagram for Internet Banking Container +${macroName}(ContainerAA, "Internet Banking Container", "Technology", "Allows customers to view information about their bank accounts, and make payments.")`); + + const yy = c4.parser.yy; + + const shapes = yy.getC4ShapeArray(); + expect(shapes.length).toBe(1); + const onlyShape = shapes[0]; + + expect(onlyShape).toEqual({ + alias: 'ContainerAA', + descr: { + text: 'Allows customers to view information about their bank accounts, and make payments.', + }, + label: { + text: 'Internet Banking Container', + }, + link: undefined, + sprite: undefined, + tags: undefined, + parentBoundary: 'global', + typeC4Shape: { + text: elementName, + }, + techn: { + text: 'Technology', + }, + wrap: false, + }); + }); + + it('should parse the alias', function () { + c4.parser.parse(`C4Context +${macroName}(ContainerAA, "Internet Banking Container")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + alias: 'ContainerAA', + }); + }); + + it('should parse the label', function () { + c4.parser.parse(`C4Context +${macroName}(ContainerAA, "Internet Banking Container")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: 'Internet Banking Container', + }, + }); + }); + + it('should parse the technology', function () { + c4.parser.parse(`C4Context +${macroName}(ContainerAA, "", "Java")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + techn: { + text: 'Java', + }, + }); + }); + + it('should parse the description', function () { + c4.parser.parse(`C4Context +${macroName}(ContainerAA, "", "", "Allows customers to view information about their bank accounts, and make payments.")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + descr: { + text: 'Allows customers to view information about their bank accounts, and make payments.', + }, + }); + }); + + it('should parse a sprite', function () { + c4.parser.parse(`C4Context +${macroName}(ContainerAA, $sprite="users")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + sprite: 'users', + }, + }, + }); + }); + + it('should parse a link', function () { + c4.parser.parse(`C4Context +${macroName}(ContainerAA, $link="https://github.com/mermaidjs")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).toMatchObject({ + label: { + text: { + link: 'https://github.com/mermaidjs', + }, + }, + }); + }); + + it('should parse tags', function () { + c4.parser.parse(`C4Context +${macroName}(ContainerAA, $tags="tag1,tag2")`); + + expect(c4.parser.yy.getC4ShapeArray()[0]).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 03b851458..1dfa69ef1 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4Diagram.jison +++ b/packages/mermaid/src/diagrams/c4/parser/c4Diagram.jison @@ -150,27 +150,27 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} "Node_R" { this.begin("node_r"); return 'NODE_R';} -"Rel" { this.begin("rel"); return 'REL';} -"BiRel" { this.begin("birel"); return 'BIREL';} -"Rel_Up" { this.begin("rel_u"); return 'REL_U';} -"Rel_U" { this.begin("rel_u"); return 'REL_U';} -"Rel_Down" { this.begin("rel_d"); return 'REL_D';} -"Rel_D" { this.begin("rel_d"); return 'REL_D';} -"Rel_Left" { this.begin("rel_l"); return 'REL_L';} -"Rel_L" { this.begin("rel_l"); return 'REL_L';} -"Rel_Right" { this.begin("rel_r"); return 'REL_R';} -"Rel_R" { this.begin("rel_r"); return 'REL_R';} -"Rel_Back" { this.begin("rel_b"); return 'REL_B';} -"RelIndex" { this.begin("rel_index"); return 'REL_INDEX';} +"Rel" { this.begin("rel"); return 'REL';} +"BiRel" { this.begin("birel"); return 'BIREL';} +"Rel_Up" { this.begin("rel_u"); return 'REL_U';} +"Rel_U" { this.begin("rel_u"); return 'REL_U';} +"Rel_Down" { this.begin("rel_d"); return 'REL_D';} +"Rel_D" { this.begin("rel_d"); return 'REL_D';} +"Rel_Left" { this.begin("rel_l"); return 'REL_L';} +"Rel_L" { this.begin("rel_l"); return 'REL_L';} +"Rel_Right" { this.begin("rel_r"); return 'REL_R';} +"Rel_R" { this.begin("rel_r"); return 'REL_R';} +"Rel_Back" { this.begin("rel_b"); return 'REL_B';} +"RelIndex" { this.begin("rel_index"); return 'REL_INDEX';} -"UpdateElementStyle" { this.begin("update_el_style"); return 'UPDATE_EL_STYLE';} -"UpdateRelStyle" { this.begin("update_rel_style"); return 'UPDATE_REL_STYLE';} -"UpdateLayoutConfig" { this.begin("update_layout_config"); return 'UPDATE_LAYOUT_CONFIG';} +"UpdateElementStyle" { this.begin("update_el_style"); return 'UPDATE_EL_STYLE';} +"UpdateRelStyle" { this.begin("update_rel_style"); return 'UPDATE_REL_STYLE';} +"UpdateLayoutConfig" { this.begin("update_layout_config"); return 'UPDATE_LAYOUT_CONFIG';} -<> return "EOF_IN_STRUCT"; -[(][ ]*[,] { this.begin("attribute"); return "ATTRIBUTE_EMPTY";} -[(] { this.begin("attribute"); } -[)] { this.popState();this.popState();} +<> return "EOF_IN_STRUCT"; +[(][ ]*[,] { this.begin("attribute"); return "ATTRIBUTE_EMPTY";} +[(] { this.begin("attribute"); } +[)] { this.popState();this.popState();} ",," { return 'ATTRIBUTE_EMPTY';} "," { } @@ -189,7 +189,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} '{' { /* this.begin("lbrace"); */ return "LBRACE";} '}' { /* this.popState(); */ return "RBRACE";} - + [\s]+ return 'SPACE'; [\n\r]+ return 'EOL'; <> return 'EOF'; @@ -257,7 +257,7 @@ graphConfig statements : otherStatements | diagramStatements - | otherStatements diagramStatements + | otherStatements diagramStatements ; otherStatements @@ -268,10 +268,10 @@ otherStatements otherStatement : title {yy.setTitle($1.substring(6));$$=$1.substring(6);} - | accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);} + | accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);} | acc_title acc_title_value { $$=$2.trim();yy.setTitle($$); } | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } - | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } + | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } ; boundaryStatement @@ -301,7 +301,7 @@ boundaryStopStatement diagramStatements : diagramStatement | diagramStatement NEWLINE - | diagramStatement NEWLINE statements + | diagramStatement NEWLINE statements ; diagramStatement @@ -312,19 +312,19 @@ diagramStatement | SYSTEM_QUEUE attributes {yy.addPersonOrSystem('system_queue', ...$2); $$=$2;} | SYSTEM_EXT attributes {yy.addPersonOrSystem('external_system', ...$2); $$=$2;} | SYSTEM_EXT_DB attributes {yy.addPersonOrSystem('external_system_db', ...$2); $$=$2;} - | SYSTEM_EXT_QUEUE attributes {yy.addPersonOrSystem('external_system_queue', ...$2); $$=$2;} + | SYSTEM_EXT_QUEUE attributes {yy.addPersonOrSystem('external_system_queue', ...$2); $$=$2;} | CONTAINER attributes {yy.addContainer('container', ...$2); $$=$2;} | CONTAINER_DB attributes {yy.addContainer('container_db', ...$2); $$=$2;} | CONTAINER_QUEUE attributes {yy.addContainer('container_queue', ...$2); $$=$2;} | CONTAINER_EXT attributes {yy.addContainer('external_container', ...$2); $$=$2;} | CONTAINER_EXT_DB attributes {yy.addContainer('external_container_db', ...$2); $$=$2;} - | CONTAINER_EXT_QUEUE attributes {yy.addContainer('external_container_queue', ...$2); $$=$2;} + | CONTAINER_EXT_QUEUE attributes {yy.addContainer('external_container_queue', ...$2); $$=$2;} | COMPONENT attributes {yy.addComponent('component', ...$2); $$=$2;} | COMPONENT_DB attributes {yy.addComponent('component_db', ...$2); $$=$2;} | COMPONENT_QUEUE attributes {yy.addComponent('component_queue', ...$2); $$=$2;} | COMPONENT_EXT attributes {yy.addComponent('external_component', ...$2); $$=$2;} | COMPONENT_EXT_DB attributes {yy.addComponent('external_component_db', ...$2); $$=$2;} - | COMPONENT_EXT_QUEUE attributes {yy.addComponent('external_component_queue', ...$2); $$=$2;} + | COMPONENT_EXT_QUEUE attributes {yy.addComponent('external_component_queue', ...$2); $$=$2;} | boundaryStatement | REL attributes {yy.addRel('rel', ...$2); $$=$2;} | BIREL attributes {yy.addRel('birel', ...$2); $$=$2;} diff --git a/packages/mermaid/src/diagrams/c4/parser/c4Diagram.spec.js b/packages/mermaid/src/diagrams/c4/parser/c4Diagram.spec.js index b79934b84..543e87a21 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4Diagram.spec.js +++ b/packages/mermaid/src/diagrams/c4/parser/c4Diagram.spec.js @@ -1,6 +1,6 @@ -import c4Db from '../c4Db'; +import c4Db from '../c4Db.js'; import c4 from './c4Diagram.jison'; -import { setConfig } from '../../../config'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/c4/parser/c4Person.spec.js b/packages/mermaid/src/diagrams/c4/parser/c4Person.spec.js index b504c0384..4eff0047c 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4Person.spec.js +++ b/packages/mermaid/src/diagrams/c4/parser/c4Person.spec.js @@ -1,6 +1,6 @@ -import c4Db from '../c4Db'; +import c4Db from '../c4Db.js'; import c4 from './c4Diagram.jison'; -import { setConfig } from '../../../config'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/c4/parser/c4PersonExt.spec.js b/packages/mermaid/src/diagrams/c4/parser/c4PersonExt.spec.js index 76547600a..f4b824e88 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4PersonExt.spec.js +++ b/packages/mermaid/src/diagrams/c4/parser/c4PersonExt.spec.js @@ -1,6 +1,6 @@ -import c4Db from '../c4Db'; +import c4Db from '../c4Db.js'; import c4 from './c4Diagram.jison'; -import { setConfig } from '../../../config'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/c4/parser/c4System.spec.js b/packages/mermaid/src/diagrams/c4/parser/c4System.spec.js index 6d81c7379..e2c2b26f7 100644 --- a/packages/mermaid/src/diagrams/c4/parser/c4System.spec.js +++ b/packages/mermaid/src/diagrams/c4/parser/c4System.spec.js @@ -1,6 +1,6 @@ -import c4Db from '../c4Db'; +import c4Db from '../c4Db.js'; import c4 from './c4Diagram.jison'; -import { setConfig } from '../../../config'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/c4/svgDraw.js b/packages/mermaid/src/diagrams/c4/svgDraw.js index 690dd26ad..9ec742261 100644 --- a/packages/mermaid/src/diagrams/c4/svgDraw.js +++ b/packages/mermaid/src/diagrams/c4/svgDraw.js @@ -1,28 +1,9 @@ -import common from '../common/common'; +import common from '../common/common.js'; +import * as svgDrawCommon from '../common/svgDrawCommon.js'; import { sanitizeUrl } from '@braintree/sanitize-url'; export const drawRect = function (elem, rectData) { - const rectElem = elem.append('rect'); - rectElem.attr('x', rectData.x); - rectElem.attr('y', rectData.y); - rectElem.attr('fill', rectData.fill); - rectElem.attr('stroke', rectData.stroke); - rectElem.attr('width', rectData.width); - rectElem.attr('height', rectData.height); - rectElem.attr('rx', rectData.rx); - rectElem.attr('ry', rectData.ry); - - if (rectData.attrs !== 'undefined' && rectData.attrs !== null) { - for (let attrKey in rectData.attrs) { - rectElem.attr(attrKey, rectData.attrs[attrKey]); - } - } - - if (rectData.class !== 'undefined') { - rectElem.attr('class', rectData.class); - } - - return rectElem; + return svgDrawCommon.drawRect(elem, rectData); }; export const drawImage = function (elem, width, height, x, y, link) { @@ -236,7 +217,8 @@ export const drawC4Shape = function (elem, c4Shape, conf) { // // draw rect of c4Shape - const rect = getNoteRect(); + const rect = svgDrawCommon.getNoteRect(); + switch (c4Shape.typeC4Shape.text) { case 'person': case 'external_person': @@ -479,6 +461,7 @@ export const insertArrowHead = function (elem) { .append('path') .attr('d', 'M 0 0 L 10 5 L 0 10 z'); // this is actual shape for arrowhead }; + export const insertArrowEnd = function (elem) { elem .append('defs') @@ -493,6 +476,7 @@ export const insertArrowEnd = function (elem) { .append('path') .attr('d', 'M 10 0 L 0 5 L 10 10 z'); // this is actual shape for arrowhead }; + /** * Setup arrow head and define the marker. The result is appended to the svg. * @@ -511,6 +495,7 @@ export const insertArrowFilledHead = function (elem) { .append('path') .attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z'); }; + /** * Setup node number. The result is appended to the svg. * @@ -532,6 +517,7 @@ export const insertDynamicNumber = function (elem) { .attr('r', 6); // .style("fill", '#f00'); }; + /** * Setup arrow head and define the marker. The result is appended to the svg. * @@ -568,20 +554,6 @@ export const insertArrowCrossHead = function (elem) { // this is actual shape for arrowhead }; -export const getNoteRect = function () { - return { - x: 0, - y: 0, - fill: '#EDF2AE', - stroke: '#666', - width: 100, - anchor: 'start', - height: 100, - rx: 0, - ry: 0, - }; -}; - const getC4ShapeFont = (cnf, typeC4Shape) => { return { fontFamily: cnf[typeC4Shape + 'FontFamily'], @@ -714,6 +686,4 @@ export default { insertDatabaseIcon, insertComputerIcon, insertClockIcon, - getNoteRect, - sanitizeUrl, // TODO why is this exported? }; diff --git a/packages/mermaid/src/diagrams/class/classDb.js b/packages/mermaid/src/diagrams/class/classDb.ts similarity index 54% rename from packages/mermaid/src/diagrams/class/classDb.js rename to packages/mermaid/src/diagrams/class/classDb.ts index 2c6690e39..c9a202aa4 100644 --- a/packages/mermaid/src/diagrams/class/classDb.js +++ b/packages/mermaid/src/diagrams/class/classDb.ts @@ -1,9 +1,10 @@ +import type { Selection } from 'd3'; import { select } from 'd3'; -import { log } from '../../logger'; -import * as configApi from '../../config'; -import common from '../common/common'; -import utils from '../../utils'; -import mermaidAPI from '../../mermaidAPI'; +import { log } from '../../logger.js'; +import * as configApi from '../../config.js'; +import common from '../common/common.js'; +import utils from '../../utils.js'; +import mermaidAPI from '../../mermaidAPI.js'; import { setAccTitle, getAccTitle, @@ -12,59 +13,80 @@ import { clear as commonClear, setDiagramTitle, getDiagramTitle, -} from '../../commonDb'; +} from '../common/commonDb.js'; +import { ClassMember } from './classTypes.js'; +import type { + ClassRelation, + ClassNode, + ClassNote, + ClassMap, + NamespaceMap, + NamespaceNode, +} from './classTypes.js'; -const MERMAID_DOM_ID_PREFIX = 'classid-'; +const MERMAID_DOM_ID_PREFIX = 'classId-'; -let relations = []; -let classes = {}; -let notes = []; +let relations: ClassRelation[] = []; +let classes: ClassMap = {}; +let notes: ClassNote[] = []; let classCounter = 0; +let namespaces: NamespaceMap = {}; +let namespaceCounter = 0; -let funs = []; +let functions: any[] = []; -const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig()); +const sanitizeText = (txt: string) => common.sanitizeText(txt, configApi.getConfig()); -export const parseDirective = function (statement, context, type) { +export const parseDirective = function (statement: string, context: string, type: string) { + // @ts-ignore Don't wanna mess it up mermaidAPI.parseDirective(this, statement, context, type); }; -const splitClassNameAndType = function (id) { +const splitClassNameAndType = function (id: string) { let genericType = ''; let className = id; if (id.indexOf('~') > 0) { - let split = id.split('~'); - className = split[0]; - - genericType = common.sanitizeText(split[1], configApi.getConfig()); + const split = id.split('~'); + className = sanitizeText(split[0]); + genericType = sanitizeText(split[1]); } return { className: className, type: genericType }; }; +export const setClassLabel = function (id: string, label: string) { + 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 + * @param id - Id of the class to add * @public */ -export const addClass = function (id) { - let classId = splitClassNameAndType(id); +export const addClass = function (id: string) { + const { className, type } = splitClassNameAndType(id); // Only add class if not exists - if (classes[classId.className] !== undefined) { + if (Object.hasOwn(classes, className)) { return; } - classes[classId.className] = { - id: classId.className, - type: classId.type, + classes[className] = { + id: className, + type: type, + label: className, cssClasses: [], methods: [], members: [], annotations: [], - domId: MERMAID_DOM_ID_PREFIX + classId.className + '-' + classCounter, - }; + domId: MERMAID_DOM_ID_PREFIX + className + '-' + classCounter, + } as ClassNode; classCounter++; }; @@ -72,35 +94,36 @@ export const addClass = function (id) { /** * Function to lookup domId from id in the graph definition. * - * @param id + * @param id - class ID to lookup * @public */ -export const lookUpDomId = function (id) { - const classKeys = Object.keys(classes); - for (const classKey of classKeys) { - if (classes[classKey].id === id) { - return classes[classKey].domId; - } +export const lookUpDomId = function (id: string): string { + if (id in classes) { + return classes[id].domId; } + throw new Error('Class not found: ' + id); }; export const clear = function () { relations = []; classes = {}; notes = []; - funs = []; - funs.push(setupToolTips); + functions = []; + functions.push(setupToolTips); + namespaces = {}; + namespaceCounter = 0; commonClear(); }; -export const getClass = function (id) { +export const getClass = function (id: string): ClassNode { return classes[id]; }; -export const getClasses = function () { + +export const getClasses = function (): ClassMap { return classes; }; -export const getRelations = function () { +export const getRelations = function (): ClassRelation[] { return relations; }; @@ -108,7 +131,7 @@ export const getNotes = function () { return notes; }; -export const addRelation = function (relation) { +export const addRelation = function (relation: ClassRelation) { log.debug('Adding relation: ' + JSON.stringify(relation)); addClass(relation.id1); addClass(relation.id2); @@ -133,11 +156,11 @@ export const addRelation = function (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 + * @param className - The class name + * @param annotation - The name of the annotation without any brackets * @public */ -export const addAnnotation = function (className, annotation) { +export const addAnnotation = function (className: string, annotation: string) { const validatedClassName = splitClassNameAndType(className).className; classes[validatedClassName].annotations.push(annotation); }; @@ -145,13 +168,15 @@ export const addAnnotation = function (className, 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 + * @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, member) { +export const addMember = function (className: string, member: string) { + addClass(className); + const validatedClassName = splitClassNameAndType(className).className; const theClass = classes[validatedClassName]; @@ -160,25 +185,25 @@ export const addMember = function (className, member) { const memberString = member.trim(); if (memberString.startsWith('<<') && memberString.endsWith('>>')) { - // Remove leading and trailing brackets - // theClass.annotations.push(memberString.substring(2, memberString.length - 2)); + // its an annotation theClass.annotations.push(sanitizeText(memberString.substring(2, memberString.length - 2))); } else if (memberString.indexOf(')') > 0) { - theClass.methods.push(sanitizeText(memberString)); + //its a method + theClass.methods.push(new ClassMember(memberString, 'method')); } else if (memberString) { - theClass.members.push(sanitizeText(memberString)); + theClass.members.push(new ClassMember(memberString, 'attribute')); } } }; -export const addMembers = function (className, members) { +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, className) { +export const addNote = function (text: string, className: string) { const note = { id: `note${notes.length}`, class: className, @@ -187,21 +212,20 @@ export const addNote = function (text, className) { notes.push(note); }; -export const cleanupLabel = function (label) { - if (label.substring(0, 1) === ':') { - return common.sanitizeText(label.substr(1).trim(), configApi.getConfig()); - } else { - return sanitizeText(label.trim()); +export const cleanupLabel = function (label: string) { + if (label.startsWith(':')) { + label = label.substring(1); } + return sanitizeText(label.trim()); }; /** * Called by parser when a special node is found, e.g. a clickable element. * - * @param ids Comma separated list of ids - * @param className Class to add + * @param ids - Comma separated list of ids + * @param className - Class to add */ -export const setCssClass = function (ids, className) { +export const setCssClass = function (ids: string, className: string) { ids.split(',').forEach(function (_id) { let id = _id; if (_id[0].match(/\d/)) { @@ -216,28 +240,33 @@ export const setCssClass = function (ids, 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 + * @param ids - Comma separated list of ids + * @param tooltip - Tooltip to add */ -const setTooltip = function (ids, tooltip) { - const config = configApi.getConfig(); +const setTooltip = function (ids: string, tooltip?: string) { ids.split(',').forEach(function (id) { if (tooltip !== undefined) { - classes[id].tooltip = common.sanitizeText(tooltip, config); + classes[id].tooltip = sanitizeText(tooltip); } }); }; -export const getTooltip = function (id) { + +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 + * @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, linkStr, target) { +export const setLink = function (ids: string, linkStr: string, target: string) { const config = configApi.getConfig(); ids.split(',').forEach(function (_id) { let id = _id; @@ -261,11 +290,11 @@ export const setLink = function (ids, linkStr, target) { /** * 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 + * @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, functionName, functionArgs) { +export const setClickEvent = function (ids: string, functionName: string, functionArgs: string) { ids.split(',').forEach(function (id) { setClickFunc(id, functionName, functionArgs); classes[id].haveCallback = true; @@ -273,19 +302,19 @@ export const setClickEvent = function (ids, functionName, functionArgs) { setCssClass(ids, 'clickable'); }; -const setClickFunc = function (domId, functionName, functionArgs) { +const setClickFunc = function (domId: string, functionName: string, functionArgs: string) { const config = configApi.getConfig(); - let id = domId; - let elemId = lookUpDomId(id); - if (config.securityLevel !== 'loose') { return; } if (functionName === undefined) { return; } + + const id = domId; if (classes[id] !== undefined) { - let argList = []; + const elemId = lookUpDomId(id); + let argList: string[] = []; if (typeof functionArgs === 'string') { /* Splits functionArgs by ',', ignoring all ',' in double quoted strings */ argList = functionArgs.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/); @@ -305,7 +334,7 @@ const setClickFunc = function (domId, functionName, functionArgs) { argList.push(elemId); } - funs.push(function () { + functions.push(function () { const elem = document.querySelector(`[id="${elemId}"]`); if (elem !== null) { elem.addEventListener( @@ -320,8 +349,8 @@ const setClickFunc = function (domId, functionName, functionArgs) { } }; -export const bindFunctions = function (element) { - funs.forEach(function (fun) { +export const bindFunctions = function (element: Element) { + functions.forEach(function (fun) { fun(element); }); }; @@ -339,8 +368,10 @@ export const relationType = { LOLLIPOP: 4, }; -const setupToolTips = function (element) { - let tooltipElem = select('.mermaidTooltip'); +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); } @@ -352,12 +383,14 @@ const setupToolTips = function (element) { .on('mouseover', function () { const el = select(this); const title = el.attr('title'); - // Dont try to draw a tooltip if no data is provided + // 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')) @@ -367,19 +400,65 @@ const setupToolTips = function (element) { 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); }); }; -funs.push(setupToolTips); +functions.push(setupToolTips); let direction = 'TB'; const getDirection = () => direction; -const setDirection = (dir) => { +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; + } + + namespaces[id] = { + id: id, + classes: {}, + children: {}, + domId: MERMAID_DOM_ID_PREFIX + id + '-' + namespaceCounter, + } as NamespaceNode; + + 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) { + classNames.map((className) => { + classes[className].parent = id; + namespaces[id].classes[className] = classes[className]; + }); + } +}; + export default { parseDirective, setAccTitle, @@ -412,4 +491,9 @@ export default { lookUpDomId, setDiagramTitle, getDiagramTitle, + setClassLabel, + addNamespace, + addClassesToNamespace, + getNamespace, + getNamespaces, }; diff --git a/packages/mermaid/src/diagrams/class/classDetector-V2.ts b/packages/mermaid/src/diagrams/class/classDetector-V2.ts index 7100f6c66..1823ad002 100644 --- a/packages/mermaid/src/diagrams/class/classDetector-V2.ts +++ b/packages/mermaid/src/diagrams/class/classDetector-V2.ts @@ -1,13 +1,29 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const classDetectorV2: DiagramDetector = (txt, config) => { +const id = 'classDiagram'; + +const detector: DiagramDetector = (txt, config) => { // If we have configured to use dagre-wrapper then we should return true in this function for classDiagram code thus making it use the new class diagram - if ( - txt.match(/^\s*classDiagram/) !== null && - config?.class?.defaultRenderer === 'dagre-wrapper' - ) { + if (/^\s*classDiagram/.test(txt) && config?.class?.defaultRenderer === 'dagre-wrapper') { return true; } // We have not opted to use the new renderer so we should return true if we detect a class diagram - return txt.match(/^\s*classDiagram-v2/) !== null; + return /^\s*classDiagram-v2/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./classDiagram-v2.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/class/classDetector.ts b/packages/mermaid/src/diagrams/class/classDetector.ts index c3833ed28..d814003cb 100644 --- a/packages/mermaid/src/diagrams/class/classDetector.ts +++ b/packages/mermaid/src/diagrams/class/classDetector.ts @@ -1,10 +1,29 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const classDetector: DiagramDetector = (txt, config) => { +const id = 'class'; + +const detector: DiagramDetector = (txt, config) => { // If we have configured to use dagre-wrapper then we should never return true in this function if (config?.class?.defaultRenderer === 'dagre-wrapper') { return false; } // We have not opted to use the new renderer so we should return true if we detect a class diagram - return txt.match(/^\s*classDiagram/) !== null; + return /^\s*classDiagram/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./classDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js b/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js index 702fa3ac3..a693fbbea 100644 --- a/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js +++ b/packages/mermaid/src/diagrams/class/classDiagram-styles.spec.js @@ -1,5 +1,5 @@ -import { parser } from './parser/classDiagram'; -import classDb from './classDb'; +import { parser } from './parser/classDiagram.jison'; +import classDb from './classDb.js'; describe('class diagram, ', function () { describe('when parsing data from a classDiagram it', function () { diff --git a/packages/mermaid/src/diagrams/class/classDiagram-v2.ts b/packages/mermaid/src/diagrams/class/classDiagram-v2.ts new file mode 100644 index 000000000..ec5398d29 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classDiagram-v2.ts @@ -0,0 +1,20 @@ +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 styles from './styles.js'; +import renderer from './classRenderer-v2.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/class/classDiagram.spec.js b/packages/mermaid/src/diagrams/class/classDiagram.spec.js deleted file mode 100644 index 04a8e9bf3..000000000 --- a/packages/mermaid/src/diagrams/class/classDiagram.spec.js +++ /dev/null @@ -1,949 +0,0 @@ -import { parser } from './parser/classDiagram'; -import classDb from './classDb'; -import { vi } from 'vitest'; -const spyOn = vi.spyOn; - -describe('class diagram, ', function () { - describe('when parsing an info graph it', function () { - beforeEach(function () { - parser.yy = classDb; - }); - - it('should handle backquoted class names', function () { - const str = 'classDiagram\n' + 'class `Car`'; - - parser.parse(str); - }); - it.skip('should handle a leading newline axa', function () { - const str = '\nclassDiagram\n' + 'class Car'; - - try { - parser.parse(str); - // Fail test if above expression doesn't throw anything. - } catch (e) { - expect(true).toBe(false); - } - }); - it('should handle relation definitions', function () { - const str = - 'classDiagram\n' + - 'Class01 <|-- Class02\n' + - 'Class03 *-- Class04\n' + - 'Class05 o-- Class06\n' + - 'Class07 .. Class08\n' + - 'Class09 -- Class1'; - - parser.parse(str); - }); - - it('should handle backquoted relation definitions', function () { - const str = - 'classDiagram\n' + - '`Class01` <|-- Class02\n' + - 'Class03 *-- Class04\n' + - 'Class05 o-- Class06\n' + - 'Class07 .. Class08\n' + - 'Class09 -- Class1'; - - parser.parse(str); - }); - - it('should handle relation definition of different types and directions', function () { - const str = - 'classDiagram\n' + - 'Class11 <|.. Class12\n' + - 'Class13 --> Class14\n' + - 'Class15 ..> Class16\n' + - 'Class17 ..|> Class18\n' + - 'Class19 <--* Class20'; - - parser.parse(str); - }); - - it('should handle cardinality and labels', function () { - const str = - 'classDiagram\n' + - 'Class01 "1" *-- "many" Class02 : contains\n' + - 'Class03 o-- Class04 : aggregation\n' + - 'Class05 --> "1" Class06'; - - parser.parse(str); - }); - - it('should handle visibility for methods and members', function () { - const str = - 'classDiagram\n' + - 'class TestClass\n' + - 'TestClass : -int privateMember\n' + - 'TestClass : +int publicMember\n' + - 'TestClass : #int protectedMember\n' + - 'TestClass : -privateMethod()\n' + - 'TestClass : +publicMethod()\n' + - 'TestClass : #protectedMethod()\n'; - - parser.parse(str); - }); - - it('should handle generic class', function () { - const str = - 'classDiagram\n' + - 'class Car~T~\n' + - 'Driver -- Car : drives >\n' + - 'Car *-- Wheel : have 4 >\n' + - 'Car -- Person : < owns'; - - parser.parse(str); - }); - - it('should handle generic class with a literal name', function () { - const str = - 'classDiagram\n' + - 'class `Car`~T~\n' + - 'Driver -- `Car` : drives >\n' + - '`Car` *-- Wheel : have 4 >\n' + - '`Car` -- Person : < owns'; - - parser.parse(str); - }); - - it('should break when another `{`is encountered before closing the first one while defining generic class with brackets', function () { - const str = - 'classDiagram\n' + - 'class Dummy_Class~T~ {\n' + - 'String data\n' + - ' void methods()\n' + - '}\n' + - '\n' + - 'class Dummy_Class {\n' + - 'class Flight {\n' + - ' flightNumber : Integer\n' + - ' departureTime : Date\n' + - '}'; - let testPassed = false; - try { - parser.parse(str); - } catch (error) { - testPassed = true; - } - expect(testPassed).toBe(true); - }); - - it('should break when EOF is encountered before closing the first `{` while defining generic class with brackets', function () { - const str = - 'classDiagram\n' + - 'class Dummy_Class~T~ {\n' + - 'String data\n' + - ' void methods()\n' + - '}\n' + - '\n' + - 'class Dummy_Class {\n'; - let testPassed = false; - try { - parser.parse(str); - } catch (error) { - testPassed = true; - } - expect(testPassed).toBe(true); - }); - - it('should handle generic class with brackets', function () { - const str = - 'classDiagram\n' + - 'class Dummy_Class~T~ {\n' + - 'String data\n' + - ' void methods()\n' + - '}\n' + - '\n' + - 'class Flight {\n' + - ' flightNumber : Integer\n' + - ' departureTime : Date\n' + - '}'; - - parser.parse(str); - }); - - it('should handle generic class with brackets and a literal name', function () { - const str = - 'classDiagram\n' + - 'class `Dummy_Class`~T~ {\n' + - 'String data\n' + - ' void methods()\n' + - '}\n' + - '\n' + - 'class Flight {\n' + - ' flightNumber : Integer\n' + - ' departureTime : Date\n' + - '}'; - - parser.parse(str); - }); - - it('should handle class definitions', function () { - const str = - 'classDiagram\n' + - 'class Car\n' + - 'Driver -- Car : drives >\n' + - 'Car *-- Wheel : have 4 >\n' + - 'Car -- Person : < owns'; - - parser.parse(str); - }); - - it('should handle method statements', function () { - const str = - 'classDiagram\n' + - 'Object <|-- ArrayList\n' + - 'Object : equals()\n' + - 'ArrayList : Object[] elementData\n' + - 'ArrayList : size()'; - - parser.parse(str); - }); - - it('should handle parsing of method statements grouped by brackets', function () { - const str = - 'classDiagram\n' + - 'class Dummy_Class {\n' + - 'String data\n' + - ' void methods()\n' + - '}\n' + - '\n' + - 'class Flight {\n' + - ' flightNumber : Integer\n' + - ' departureTime : Date\n' + - '}'; - - parser.parse(str); - }); - - it('should handle return types on methods', function () { - const str = - 'classDiagram\n' + - 'Object <|-- ArrayList\n' + - 'Object : equals()\n' + - 'Object : -Object[] objects\n' + - 'Object : +getObjects() Object[]\n' + - 'ArrayList : Dummy elementData\n' + - 'ArrayList : getDummy() Dummy'; - - parser.parse(str); - }); - - it('should handle return types on methods grouped by brackets', function () { - const str = - 'classDiagram\n' + - 'class Dummy_Class {\n' + - 'string data\n' + - 'getDummy() Dummy\n' + - '}\n' + - '\n' + - 'class Flight {\n' + - ' int flightNumber\n' + - ' datetime departureTime\n' + - ' getDepartureTime() datetime\n' + - '}'; - - parser.parse(str); - }); - - it('should handle parsing of separators', function () { - const str = - 'classDiagram\n' + - 'class Foo1 {\n' + - ' You can use\n' + - ' several lines\n' + - '..\n' + - 'as you want\n' + - 'and group\n' + - '==\n' + - 'things together.\n' + - '__\n' + - 'You can have as many groups\n' + - 'as you want\n' + - '--\n' + - 'End of class\n' + - '}\n' + - '\n' + - 'class User {\n' + - '.. Simple Getter ..\n' + - '+ getName()\n' + - '+ getAddress()\n' + - '.. Some setter ..\n' + - '+ setName()\n' + - '__ private data __\n' + - 'int age\n' + - '-- encrypted --\n' + - 'String password\n' + - '}'; - - parser.parse(str); - }); - - it('should handle a comment', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}'; - - parser.parse(str); - }); - - it('should handle comments at the start', function () { - const str = `%% Comment - classDiagram - class Class1 { - int : test - string : foo - test() - foo() - }`; - parser.parse(str); - }); - - it('should handle comments at the end', function () { - const str = `classDiagram -class Class1 { -int : test -string : foo -test() -foo() - -} -%% Comment -`; - - parser.parse(str); - }); - - it('should handle comments at the end no trailing newline', function () { - const str = `classDiagram -class Class1 { -int : test -string : foo -test() -foo() -} -%% Comment`; - - parser.parse(str); - }); - - it('should handle a comment with multiple line feeds', function () { - const str = `classDiagram - - -%% Comment - -class Class1 { -int : test -string : foo -test() -foo() -}`; - - parser.parse(str); - }); - - it('should handle a comment with mermaid class diagram code in them', function () { - const str = `classDiagram -%% Comment Class01 <|-- Class02 -class Class1 { -int : test -string : foo -test() -foo() -}`; - - parser.parse(str); - }); - - it('should handle a comment inside brackets', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}'; - - parser.parse(str); - }); - - it('should handle click statement with link', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'link Class01 "google.com" '; - - parser.parse(str); - }); - - it('should handle click statement with click and href link', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'click Class01 href "google.com" '; - - parser.parse(str); - }); - - it('should handle click statement with link and tooltip', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'link Class01 "google.com" "A Tooltip" '; - - parser.parse(str); - }); - - it('should handle click statement with click and href link and tooltip', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'click Class01 href "google.com" "A Tooltip" '; - - parser.parse(str); - }); - - it('should handle click statement with callback', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'callback Class01 "functionCall" '; - - parser.parse(str); - }); - - it('should handle click statement with click and call callback', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'click Class01 call functionCall() '; - - parser.parse(str); - }); - - it('should handle click statement with callback and tooltip', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'callback Class01 "functionCall" "A Tooltip" '; - - parser.parse(str); - }); - - it('should handle click statement with click and call callback and tooltip', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '%% Comment Class01 <|-- Class02\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}\n' + - 'click Class01 call functionCall() "A Tooltip" '; - - parser.parse(str); - }); - - it('should handle dashed relation definition of different types and directions', function () { - const str = - 'classDiagram\n' + - 'Class11 <|.. Class12\n' + - 'Class13 <.. Class14\n' + - 'Class15 ..|> Class16\n' + - 'Class17 ..> Class18\n' + - 'Class19 .. Class20'; - parser.parse(str); - }); - - it('should handle generic types in members', function () { - const str = - 'classDiagram\n' + - 'class Car~T~\n' + - 'Car : -List~Wheel~ wheels\n' + - 'Car : +setWheels(List~Wheel~ wheels)\n' + - 'Car : +getWheels() List~Wheel~'; - - parser.parse(str); - }); - - it('should handle generic types in members in class with brackets', function () { - const str = - 'classDiagram\n' + - 'class Car {\n' + - 'List~Wheel~ wheels\n' + - 'setWheels(List~Wheel~ wheels)\n' + - '+getWheels() List~Wheel~\n' + - '}'; - - parser.parse(str); - }); - - it('should handle "note for"', function () { - const str = 'classDiagram\n' + 'Class11 <|.. Class12\n' + 'note for Class11 "test"\n'; - parser.parse(str); - }); - - it('should handle "note"', function () { - const str = 'classDiagram\n' + 'note "test"\n'; - parser.parse(str); - }); - }); - - describe('when fetching data from a classDiagram graph it', function () { - beforeEach(function () { - parser.yy = classDb; - parser.yy.clear(); - }); - it('should handle relation definitions EXTENSION', function () { - const str = 'classDiagram\n' + 'Class01 <|-- Class02'; - - parser.parse(str); - - const relations = parser.yy.getRelations(); - - expect(parser.yy.getClass('Class01').id).toBe('Class01'); - expect(parser.yy.getClass('Class02').id).toBe('Class02'); - expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION); - expect(relations[0].relation.type2).toBe('none'); - expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); - }); - - it('should handle accTitle and accDescr', function () { - const str = `classDiagram - accTitle: My Title - accDescr: My Description - - Class01 <|-- Class02 - `; - - parser.parse(str); - expect(parser.yy.getAccTitle()).toBe('My Title'); - expect(parser.yy.getAccDescription()).toBe('My Description'); - }); - it('should handle accTitle and multiline accDescr', function () { - const str = `classDiagram - accTitle: My Title - accDescr { - This is mu multi - line description - } - - Class01 <|-- Class02 - `; - - parser.parse(str); - expect(parser.yy.getAccTitle()).toBe('My Title'); - expect(parser.yy.getAccDescription()).toBe('This is mu multi\nline description'); - }); - - it('should handle relation definitions AGGREGATION and dotted line', function () { - const str = 'classDiagram\n' + 'Class01 o.. Class02'; - - parser.parse(str); - - const relations = parser.yy.getRelations(); - - expect(parser.yy.getClass('Class01').id).toBe('Class01'); - expect(parser.yy.getClass('Class02').id).toBe('Class02'); - expect(relations[0].relation.type1).toBe(classDb.relationType.AGGREGATION); - expect(relations[0].relation.type2).toBe('none'); - expect(relations[0].relation.lineType).toBe(classDb.lineType.DOTTED_LINE); - }); - - it('should handle relation definitions COMPOSITION on both sides', function () { - const str = 'classDiagram\n' + 'Class01 *--* Class02'; - - parser.parse(str); - - const relations = parser.yy.getRelations(); - - expect(parser.yy.getClass('Class01').id).toBe('Class01'); - expect(parser.yy.getClass('Class02').id).toBe('Class02'); - expect(relations[0].relation.type1).toBe(classDb.relationType.COMPOSITION); - expect(relations[0].relation.type2).toBe(classDb.relationType.COMPOSITION); - expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); - }); - - it('should handle relation definitions no types', function () { - const str = 'classDiagram\n' + 'Class01 -- Class02'; - - parser.parse(str); - - const relations = parser.yy.getRelations(); - - expect(parser.yy.getClass('Class01').id).toBe('Class01'); - expect(parser.yy.getClass('Class02').id).toBe('Class02'); - expect(relations[0].relation.type1).toBe('none'); - expect(relations[0].relation.type2).toBe('none'); - expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); - }); - - it('should handle relation definitions with type only on right side', function () { - const str = 'classDiagram\n' + 'Class01 --|> Class02'; - - parser.parse(str); - - const relations = parser.yy.getRelations(); - - expect(parser.yy.getClass('Class01').id).toBe('Class01'); - expect(parser.yy.getClass('Class02').id).toBe('Class02'); - expect(relations[0].relation.type1).toBe('none'); - expect(relations[0].relation.type2).toBe(classDb.relationType.EXTENSION); - expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); - }); - - it('should handle multiple classes and relation definitions', function () { - const str = - 'classDiagram\n' + - 'Class01 <|-- Class02\n' + - 'Class03 *-- Class04\n' + - 'Class05 o-- Class06\n' + - 'Class07 .. Class08\n' + - 'Class09 -- Class10'; - - parser.parse(str); - - const relations = parser.yy.getRelations(); - - expect(parser.yy.getClass('Class01').id).toBe('Class01'); - expect(parser.yy.getClass('Class10').id).toBe('Class10'); - - expect(relations.length).toBe(5); - - expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION); - expect(relations[0].relation.type2).toBe('none'); - expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); - expect(relations[3].relation.type1).toBe('none'); - expect(relations[3].relation.type2).toBe('none'); - expect(relations[3].relation.lineType).toBe(classDb.lineType.DOTTED_LINE); - }); - - it('should handle generic class with relation definitions', function () { - const str = 'classDiagram\n' + 'Class01~T~ <|-- Class02'; - - parser.parse(str); - - const relations = parser.yy.getRelations(); - - expect(parser.yy.getClass('Class01').id).toBe('Class01'); - expect(parser.yy.getClass('Class01').type).toBe('T'); - expect(parser.yy.getClass('Class02').id).toBe('Class02'); - expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION); - expect(relations[0].relation.type2).toBe('none'); - expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); - }); - - it('should handle class annotations', function () { - const str = 'classDiagram\n' + 'class Class1\n' + '<> Class1'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.annotations.length).toBe(1); - expect(testClass.members.length).toBe(0); - expect(testClass.methods.length).toBe(0); - expect(testClass.annotations[0]).toBe('interface'); - }); - - it('should handle class annotations with members and methods', function () { - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : int test\n' + - 'Class1 : test()\n' + - '<> Class1'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.annotations.length).toBe(1); - expect(testClass.members.length).toBe(1); - expect(testClass.methods.length).toBe(1); - expect(testClass.annotations[0]).toBe('interface'); - }); - - it('should handle class annotations in brackets', function () { - const str = 'classDiagram\n' + 'class Class1 {\n' + '<>\n' + '}'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.annotations.length).toBe(1); - expect(testClass.members.length).toBe(0); - expect(testClass.methods.length).toBe(0); - expect(testClass.annotations[0]).toBe('interface'); - }); - - it('should handle class annotations in brackets with members and methods', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - '<>\n' + - 'int : test\n' + - 'test()\n' + - '}'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.annotations.length).toBe(1); - expect(testClass.members.length).toBe(1); - expect(testClass.methods.length).toBe(1); - expect(testClass.annotations[0]).toBe('interface'); - }); - - it('should add bracket members in right order', function () { - const str = - 'classDiagram\n' + - 'class Class1 {\n' + - 'int : test\n' + - 'string : foo\n' + - 'test()\n' + - 'foo()\n' + - '}'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.members.length).toBe(2); - expect(testClass.methods.length).toBe(2); - expect(testClass.members[0]).toBe('int : test'); - expect(testClass.members[1]).toBe('string : foo'); - expect(testClass.methods[0]).toBe('test()'); - expect(testClass.methods[1]).toBe('foo()'); - }); - - it('should handle abstract methods', function () { - const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()*'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.annotations.length).toBe(0); - expect(testClass.members.length).toBe(0); - expect(testClass.methods.length).toBe(1); - expect(testClass.methods[0]).toBe('someMethod()*'); - }); - - it('should handle static methods', function () { - const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()$'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.annotations.length).toBe(0); - expect(testClass.members.length).toBe(0); - expect(testClass.methods.length).toBe(1); - expect(testClass.methods[0]).toBe('someMethod()$'); - }); - - it('should associate link and css appropriately', function () { - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'link Class1 "google.com"'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.link).toBe('google.com'); - expect(testClass.cssClasses.length).toBe(1); - expect(testClass.cssClasses[0]).toBe('clickable'); - }); - - it('should associate click and href link and css appropriately', function () { - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 href "google.com"'; - parser.parse(str); - - const testClass = parser.yy.getClass('Class1'); - expect(testClass.link).toBe('google.com'); - expect(testClass.cssClasses.length).toBe(1); - expect(testClass.cssClasses[0]).toBe('clickable'); - }); - - it('should associate link with tooltip', function () { - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'link Class1 "google.com" "A tooltip"'; - parser.parse(str); - - 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'); - }); - - it('should associate click and href link with tooltip', function () { - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 href "google.com" "A tooltip"'; - parser.parse(str); - - 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'); - }); - - it('should associate click and href link with tooltip and target appropriately', function () { - spyOn(classDb, 'setLink'); - spyOn(classDb, 'setTooltip'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 href "google.com" "A tooltip" _self'; - parser.parse(str); - - expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self'); - expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip'); - }); - - it('should associate click and href link appropriately', function () { - spyOn(classDb, 'setLink'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 href "google.com"'; - parser.parse(str); - - expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com'); - }); - - it('should associate click and href link with target appropriately', function () { - spyOn(classDb, 'setLink'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 href "google.com" _self'; - parser.parse(str); - - expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self'); - }); - - it('should associate link appropriately', function () { - spyOn(classDb, 'setLink'); - spyOn(classDb, 'setTooltip'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'link Class1 "google.com" "A tooltip" _self'; - parser.parse(str); - - expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self'); - expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip'); - }); - - it('should associate callback appropriately', function () { - spyOn(classDb, 'setClickEvent'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'callback Class1 "functionCall"'; - parser.parse(str); - - expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); - }); - - it('should associate click and call callback appropriately', function () { - spyOn(classDb, 'setClickEvent'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 call functionCall()'; - parser.parse(str); - - expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); - }); - - it('should associate callback appropriately with an arbitrary number of args', function () { - spyOn(classDb, 'setClickEvent'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 call functionCall("test0", test1, test2)'; - parser.parse(str); - - expect(classDb.setClickEvent).toHaveBeenCalledWith( - 'Class1', - 'functionCall', - '"test0", test1, test2' - ); - }); - - it('should associate callback with tooltip', function () { - spyOn(classDb, 'setClickEvent'); - spyOn(classDb, 'setTooltip'); - const str = - 'classDiagram\n' + - 'class Class1\n' + - 'Class1 : someMethod()\n' + - 'click Class1 call functionCall() "A tooltip"'; - parser.parse(str); - - expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); - expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip'); - }); - }); -}); diff --git a/packages/mermaid/src/diagrams/class/classDiagram.spec.ts b/packages/mermaid/src/diagrams/class/classDiagram.spec.ts new file mode 100644 index 000000000..532c8aaa7 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classDiagram.spec.ts @@ -0,0 +1,1777 @@ +// @ts-expect-error Jison doesn't export types +import { parser } from './parser/classDiagram.jison'; +import classDb from './classDb.js'; +import { vi, describe, it, expect } from 'vitest'; +const spyOn = vi.spyOn; + +const staticCssStyle = 'text-decoration:underline;'; +const abstractCssStyle = 'font-style:italic;'; + +describe('given a basic class diagram, ', function () { + describe('when parsing class definition', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + it('should handle accTitle and accDescr', function () { + const str = `classDiagram + accTitle: My Title + accDescr: My Description`; + + parser.parse(str); + expect(parser.yy.getAccTitle()).toBe('My Title'); + expect(parser.yy.getAccDescription()).toBe('My Description'); + }); + + it('should handle accTitle and multiline accDescr', function () { + const str = `classDiagram + accTitle: My Title + accDescr { + This is my multi + line description + }`; + + parser.parse(str); + expect(parser.yy.getAccTitle()).toBe('My Title'); + expect(parser.yy.getAccDescription()).toBe('This is my multi\nline description'); + }); + + it.skip('should handle a leading newline', function () { + const str = '\nclassDiagram\n' + 'class Car'; + + try { + parser.parse(str); + // Fail test if above expression doesn't throw anything. + } catch (e) { + expect(true).toBe(false); + } + }); + + it('should handle backquoted class names', function () { + const str = 'classDiagram\n' + 'class `Car`'; + + parser.parse(str); + }); + + it('should handle class names with dash', function () { + const str = 'classDiagram\n' + 'class Ca-r'; + + parser.parse(str); + const actual = classDb.getClass('Ca-r'); + expect(actual.label).toBe('Ca-r'); + }); + + it('should handle class names with underscore', function () { + const str = 'classDiagram\n' + 'class `A_Car`'; + + parser.parse(str); + }); + + it('should handle parsing of separators', function () { + const str = + 'classDiagram\n' + + 'class Foo1 {\n' + + ' You can use\n' + + ' several lines\n' + + '..\n' + + 'as you want\n' + + 'and group\n' + + '==\n' + + 'things together.\n' + + '__\n' + + 'You can have as many groups\n' + + 'as you want\n' + + '--\n' + + 'End of class\n' + + '}\n' + + '\n' + + 'class User {\n' + + '.. Simple Getter ..\n' + + '+ getName()\n' + + '+ getAddress()\n' + + '.. Some setter ..\n' + + '+ setName()\n' + + '__ private data __\n' + + 'int age\n' + + '-- encrypted --\n' + + 'String password\n' + + '}'; + + parser.parse(str); + }); + + it('should parse a class with a text label', () => { + const str = 'classDiagram\n' + 'class C1["Class 1 with text label"]'; + + parser.parse(str); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + }); + + it('should parse two classes with text labels', function () { + const str = + 'classDiagram\n' + + 'class C1["Class 1 with text label"]\n' + + 'class C2["Class 2 with chars @?"]\n'; + + parser.parse(str); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('Class 2 with chars @?'); + }); + + it('should parse a class with a text label and member', () => { + const str = 'classDiagram\n' + 'class C1["Class 1 with text label"]\n' + 'C1: member1'; + + parser.parse(str); + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.members.length).toBe(1); + expect(c1.members[0].getDisplayDetails().displayText).toBe('member1'); + }); + + it('should parse a class with a text label, member and annotation', () => { + const str = + 'classDiagram\n' + + 'class C1["Class 1 with text label"]\n' + + '<> C1\n' + + 'C1 : int member1'; + + parser.parse(str); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.members.length).toBe(1); + expect(c1.members[0].getDisplayDetails().displayText).toBe('int member1'); + expect(c1.annotations.length).toBe(1); + expect(c1.annotations[0]).toBe('interface'); + }); + + it('should parse a class with text label and css class shorthand', () => { + const str = 'classDiagram\n' + 'class C1["Class 1 with text label"]:::styleClass'; + + parser.parse(str); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.cssClasses[0]).toBe('styleClass'); + }); + + it('should parse a class with text label and css class', () => { + const str = + 'classDiagram\n' + + 'class C1["Class 1 with text label"]\n' + + 'C1 : int member1\n' + + 'cssClass "C1" styleClass'; + + parser.parse(str); + + 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'); + }); + + it('should parse two classes with text labels and css classes', () => { + const str = + 'classDiagram\n' + + 'class C1["Class 1 with text label"]\n' + + 'C1 : int member1\n' + + 'class C2["Long long long long long long long long long long label"]\n' + + 'cssClass "C1,C2" styleClass'; + + parser.parse(str); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.cssClasses[0]).toBe('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'); + }); + + it('should parse two classes with text labels and css class shorthands', () => { + const str = + 'classDiagram\n' + + 'class C1["Class 1 with text label"]:::styleClass1\n' + + 'class C2["Class 2 !@#$%^&*() label"]:::styleClass2'; + + parser.parse(str); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.cssClasses[0]).toBe('styleClass1'); + + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('Class 2 !@#$%^&*() label'); + expect(c2.cssClasses[0]).toBe('styleClass2'); + }); + + it('should parse multiple classes with same text labels', () => { + parser.parse(`classDiagram +class C1["Class with text label"] +class C2["Class with text label"] +class C3["Class with text label"]`); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class with text label'); + + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('Class with text label'); + + const c3 = classDb.getClass('C3'); + expect(c3.label).toBe('Class with text label'); + }); + + it('should parse classes with different text labels', () => { + parser.parse(`classDiagram +class C1["OneWord"] +class C2["With, Comma"] +class C3["With (Brackets)"] +class C4["With [Brackets]"] +class C5["With {Brackets}"] +class C6[" "] +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"] +`); + expect(classDb.getClass('C1').label).toBe('OneWord'); + expect(classDb.getClass('C2').label).toBe('With, Comma'); + expect(classDb.getClass('C3').label).toBe('With (Brackets)'); + expect(classDb.getClass('C4').label).toBe('With [Brackets]'); + expect(classDb.getClass('C5').label).toBe('With {Brackets}'); + expect(classDb.getClass('C6').label).toBe(' '); + expect(classDb.getClass('C7').label).toBe('With 1 number'); + expect(classDb.getClass('C8').label).toBe('With . period...'); + expect(classDb.getClass('C9').label).toBe('With - dash'); + expect(classDb.getClass('C10').label).toBe('With _ underscore'); + expect(classDb.getClass('C11').label).toBe("With ' single quote"); + expect(classDb.getClass('C12').label).toBe('With ~!@#$%^&*()_+=-/?'); + expect(classDb.getClass('C13').label).toBe('With Città foreign language'); + }); + + it('should handle "note for"', function () { + const str = 'classDiagram\n' + 'Class11 <|.. Class12\n' + 'note for Class11 "test"\n'; + parser.parse(str); + }); + + it('should handle "note"', function () { + const str = 'classDiagram\n' + 'note "test"\n'; + parser.parse(str); + }); + + const keywords = [ + 'direction', + 'classDiagram', + 'classDiagram-v2', + 'namespace', + '{}', + '{', + '}', + '()', + '(', + ')', + '[]', + '[', + ']', + 'class', + '\n', + 'cssClass', + 'callback', + 'link', + 'click', + 'note', + 'note for', + '<<', + '>>', + 'call ', + '~', + '~Generic~', + '_self', + '_blank', + '_parent', + '_top', + '<|', + '|>', + '>', + '<', + '*', + 'o', + '\\', + '--', + '..', + '-->', + '--|>', + ': label', + ':::', + '.', + '+', + 'alphaNum', + '!', + '0123', + 'function()', + 'function(arg1, arg2)', + ]; + + it.each(keywords)('should handle a note with %s in it', function (keyword: string) { + const str = `classDiagram + note "This is a keyword: ${keyword}. It truly is." + `; + parser.parse(str); + expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`); + }); + + it.each(keywords)( + 'should handle note with %s at beginning of string', + function (keyword: string) { + const str = `classDiagram + note "${keyword}"`; + + parser.parse(str); + expect(classDb.getNotes()[0].text).toEqual(`${keyword}`); + } + ); + + it.each(keywords)('should handle a "note for" with a %s in it', function (keyword: string) { + const str = `classDiagram + class Something { + int id + string name + } + note for Something "This is a keyword: ${keyword}. It truly is." + `; + + parser.parse(str); + expect(classDb.getNotes()[0].text).toEqual(`This is a keyword: ${keyword}. It truly is.`); + }); + + it.each(keywords)( + 'should handle a "note for" with a %s at beginning of string', + function (keyword: string) { + const str = `classDiagram + class Something { + int id + string name + } + note for Something "${keyword}" + `; + + parser.parse(str); + expect(classDb.getNotes()[0].text).toEqual(`${keyword}`); + } + ); + + it.each(keywords)('should elicit error for %s after NOTE token', function (keyword: string) { + const str = `classDiagram + note ${keyword}`; + expect(() => parser.parse(str)).toThrowError(/(Expecting\s'STR'|Unrecognized\stext)/); + }); + + it('should parse diagram with direction', () => { + parser.parse(`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`); + + expect(Object.keys(classDb.getClasses()).length).toBe(3); + expect(classDb.getClasses().Student).toMatchInlineSnapshot(` + { + "annotations": [], + "cssClasses": [], + "domId": "classId-Student-134", + "id": "Student", + "label": "Student", + "members": [ + ClassMember { + "classifier": "", + "id": "idCard : IdCard", + "memberType": "attribute", + "visibility": "-", + }, + ], + "methods": [], + "type": "", + } + `); + expect(classDb.getRelations().length).toBe(2); + expect(classDb.getRelations()).toMatchInlineSnapshot(` + [ + { + "id1": "Student", + "id2": "IdCard", + "relation": { + "lineType": 0, + "type1": "none", + "type2": 0, + }, + "relationTitle1": "1", + "relationTitle2": "1", + "title": "carries", + }, + { + "id1": "Student", + "id2": "Bike", + "relation": { + "lineType": 0, + "type1": "none", + "type2": 0, + }, + "relationTitle1": "1", + "relationTitle2": "1", + "title": "rides", + }, + ] + `); + }); + }); + + describe('when parsing class defined in brackets', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + + it('should handle member definitions', function () { + const str = 'classDiagram\n' + 'class Car{\n' + '+int wheels\n' + '}'; + + parser.parse(str); + }); + + it('should handle method definitions', function () { + const str = 'classDiagram\n' + 'class Car{\n' + '+size()\n' + '}'; + + parser.parse(str); + }); + + it('should handle a mix of members defined in and outside of brackets', function () { + const str = + 'classDiagram\n' + 'class Car{\n' + '+int wheels\n' + '}\n' + 'Car : +ArrayList size()\n'; + + parser.parse(str); + }); + + it('should handle member and method definitions', () => { + const str = + 'classDiagram\n' + 'class Dummy_Class {\n' + 'String data\n' + 'void methods()\n' + '}'; + + parser.parse(str); + }); + + it('should handle return types on methods', () => { + const str = + 'classDiagram\n' + + 'class Flight {\n' + + 'int flightNumber\n' + + 'datetime departureTime\n' + + 'getDepartureTime() datetime\n' + + '}'; + + parser.parse(str); + }); + + it('should add bracket members in right order', () => { + const str = + 'classDiagram\n' + + 'class Class1 {\n' + + 'int testMember\n' + + 'test()\n' + + 'string fooMember\n' + + 'foo()\n' + + '}'; + parser.parse(str); + + const actual = parser.yy.getClass('Class1'); + expect(actual.members.length).toBe(2); + expect(actual.methods.length).toBe(2); + expect(actual.members[0].getDisplayDetails().displayText).toBe('int testMember'); + expect(actual.members[1].getDisplayDetails().displayText).toBe('string fooMember'); + expect(actual.methods[0].getDisplayDetails().displayText).toBe('test()'); + expect(actual.methods[1].getDisplayDetails().displayText).toBe('foo()'); + }); + + it('should parse a class with a text label and members', () => { + const str = 'classDiagram\n' + 'class C1["Class 1 with text label"] {\n' + '+member1\n' + '}'; + + parser.parse(str); + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.members.length).toBe(1); + expect(c1.members[0].getDisplayDetails().displayText).toBe('+member1'); + }); + + it('should parse a class with a text label, members and annotation', () => { + const str = + 'classDiagram\n' + + 'class C1["Class 1 with text label"] {\n' + + '<>\n' + + '+member1\n' + + '}'; + + parser.parse(str); + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.members.length).toBe(1); + expect(c1.members[0].getDisplayDetails().displayText).toBe('+member1'); + expect(c1.annotations.length).toBe(1); + expect(c1.annotations[0]).toBe('interface'); + }); + }); + + describe('when parsing comments', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + + it('should handle comments at the start', function () { + const str = `%% Comment + classDiagram + class Class1 { + int : test + string : foo + test() + foo() + }`; + parser.parse(str); + }); + + it('should handle comments at the end', function () { + const str = `classDiagram +class Class1 { +int : test +string : foo +test() +foo() + +} +%% Comment +`; + + parser.parse(str); + }); + + it('should handle comments at the end no trailing newline', function () { + const str = `classDiagram +class Class1 { +int : test +string : foo +test() +foo() +} +%% Comment`; + + parser.parse(str); + }); + + it('should handle a comment with multiple line feeds', function () { + const str = `classDiagram + + +%% Comment + +class Class1 { +int : test +string : foo +test() +foo() +}`; + + parser.parse(str); + }); + + it('should handle a comment with mermaid class diagram code in them', function () { + const str = `classDiagram +%% Comment Class1 <|-- Class02 +class Class1 { +int : test +string : foo +test() +foo() +}`; + + parser.parse(str); + }); + + it('should handle a comment inside brackets', function () { + const str = + 'classDiagram\n' + + 'class Class1 {\n' + + '%% Comment Class1 <|-- Class02\n' + + 'int : test\n' + + 'string : foo\n' + + 'test()\n' + + 'foo()\n' + + '}'; + + parser.parse(str); + }); + }); + + describe('when parsing click statements', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + it('should handle href link', function () { + spyOn(classDb, 'setLink'); + const str = 'classDiagram\n' + 'class Class1 \n' + 'click Class1 href "google.com" '; + + parser.parse(str); + + expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com'); + + const actual = parser.yy.getClass('Class1'); + expect(actual.link).toBe('google.com'); + expect(actual.cssClasses[0]).toBe('clickable'); + }); + + it('should handle href link with tooltip', function () { + spyOn(classDb, 'setLink'); + spyOn(classDb, 'setTooltip'); + const str = + 'classDiagram\n' + 'class Class1 \n' + 'click Class1 href "google.com" "A Tooltip" '; + + parser.parse(str); + + expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com'); + + const actual = parser.yy.getClass('Class1'); + expect(actual.link).toBe('google.com'); + expect(actual.tooltip).toBe('A Tooltip'); + expect(actual.cssClasses[0]).toBe('clickable'); + }); + + it('should handle href link with tooltip and target', function () { + spyOn(classDb, 'setLink'); + spyOn(classDb, 'setTooltip'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 href "google.com" "A tooltip" _self'; + parser.parse(str); + + expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self'); + expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip'); + + const actual = parser.yy.getClass('Class1'); + expect(actual.link).toBe('google.com'); + expect(actual.tooltip).toBe('A tooltip'); + expect(actual.cssClasses[0]).toBe('clickable'); + }); + + it('should handle function call', function () { + spyOn(classDb, 'setClickEvent'); + + const str = 'classDiagram\n' + 'class Class1 \n' + 'click Class1 call functionCall() '; + + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); + }); + + it('should handle function call with tooltip', function () { + spyOn(classDb, 'setClickEvent'); + spyOn(classDb, 'setTooltip'); + + const str = + 'classDiagram\n' + 'class Class1 \n' + 'click Class1 call functionCall() "A Tooltip" '; + + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); + expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A Tooltip'); + }); + + it('should handle function call with an arbitrary number of args', function () { + spyOn(classDb, 'setClickEvent'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 call functionCall(test, test1, test2)'; + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith( + 'Class1', + 'functionCall', + 'test, test1, test2' + ); + }); + + it('should handle function call with an arbitrary number of args and tooltip', function () { + spyOn(classDb, 'setClickEvent'); + spyOn(classDb, 'setTooltip'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 call functionCall("test0", test1, test2) "A Tooltip"'; + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith( + 'Class1', + 'functionCall', + '"test0", test1, test2' + ); + expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A Tooltip'); + }); + }); + + describe('when parsing annotations', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + + it('should handle class annotations', function () { + const str = 'classDiagram\n' + 'class Class1\n' + '<> Class1'; + parser.parse(str); + + const actual = parser.yy.getClass('Class1'); + expect(actual.annotations.length).toBe(1); + expect(actual.members.length).toBe(0); + expect(actual.methods.length).toBe(0); + expect(actual.annotations[0]).toBe('interface'); + }); + + it('should handle class annotations with members and methods', function () { + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : int test\n' + + 'Class1 : test()\n' + + '<> Class1'; + parser.parse(str); + + const actual = parser.yy.getClass('Class1'); + expect(actual.annotations.length).toBe(1); + expect(actual.members.length).toBe(1); + expect(actual.methods.length).toBe(1); + expect(actual.annotations[0]).toBe('interface'); + }); + + it('should handle class annotations in brackets', function () { + const str = 'classDiagram\n' + 'class Class1 {\n' + '<>\n' + '}'; + parser.parse(str); + + const actual = parser.yy.getClass('Class1'); + expect(actual.annotations.length).toBe(1); + expect(actual.members.length).toBe(0); + expect(actual.methods.length).toBe(0); + expect(actual.annotations[0]).toBe('interface'); + }); + + it('should handle class annotations in brackets with members and methods', function () { + const str = + 'classDiagram\n' + + 'class Class1 {\n' + + '<>\n' + + 'int : test\n' + + 'test()\n' + + '}'; + parser.parse(str); + + const actual = parser.yy.getClass('Class1'); + expect(actual.annotations.length).toBe(1); + expect(actual.members.length).toBe(1); + expect(actual.methods.length).toBe(1); + expect(actual.annotations[0]).toBe('interface'); + }); + }); +}); + +describe('given a class diagram with members and methods ', function () { + describe('when parsing members', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + + it('should handle simple member declaration', function () { + const str = 'classDiagram\n' + 'class Car\n' + 'Car : wheels'; + + parser.parse(str); + }); + + it('should handle direct member declaration', function () { + parser.parse('classDiagram\n' + 'Car : wheels'); + const car = classDb.getClass('Car'); + expect(car.members.length).toBe(1); + expect(car.members[0].id).toBe('wheels'); + }); + + it('should handle direct member declaration with type', function () { + parser.parse('classDiagram\n' + 'Car : int wheels'); + const car = classDb.getClass('Car'); + expect(car.members.length).toBe(1); + expect(car.members[0].id).toBe('int wheels'); + }); + + it('should handle simple member declaration with type', function () { + const str = 'classDiagram\n' + 'class Car\n' + 'Car : int wheels'; + + parser.parse(str); + }); + + it('should handle visibility', function () { + const str = + 'classDiagram\n' + + 'class actual\n' + + 'actual : -int privateMember\n' + + 'actual : +int publicMember\n' + + 'actual : #int protectedMember\n' + + 'actual : ~int privatePackage'; + + parser.parse(str); + + const actual = parser.yy.getClass('actual'); + expect(actual.members.length).toBe(4); + expect(actual.methods.length).toBe(0); + expect(actual.members[0].getDisplayDetails().displayText).toBe('-int privateMember'); + expect(actual.members[1].getDisplayDetails().displayText).toBe('+int publicMember'); + expect(actual.members[2].getDisplayDetails().displayText).toBe('#int protectedMember'); + expect(actual.members[3].getDisplayDetails().displayText).toBe('~int privatePackage'); + }); + + it('should handle generic types', function () { + const str = 'classDiagram\n' + 'class Car\n' + 'Car : -List~Wheel~ wheels'; + + parser.parse(str); + }); + }); + + describe('when parsing method definition', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + + it('should handle method definition', function () { + const str = 'classDiagram\n' + 'class Car\n' + 'Car : GetSize()'; + + parser.parse(str); + }); + + it('should handle simple return types', function () { + const str = 'classDiagram\n' + 'class Object\n' + 'Object : getObject() Object'; + + parser.parse(str); + }); + + it('should handle return types as array', function () { + const str = 'classDiagram\n' + 'class Object\n' + 'Object : getObjects() Object[]'; + + parser.parse(str); + }); + + it('should handle visibility', function () { + const str = + 'classDiagram\n' + + 'class actual\n' + + 'actual : -privateMethod()\n' + + 'actual : +publicMethod()\n' + + 'actual : #protectedMethod()\n'; + + parser.parse(str); + }); + + it('should handle abstract methods', function () { + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()*'; + parser.parse(str); + + const actual = parser.yy.getClass('Class1'); + expect(actual.annotations.length).toBe(0); + expect(actual.members.length).toBe(0); + expect(actual.methods.length).toBe(1); + const method = actual.methods[0]; + expect(method.getDisplayDetails().displayText).toBe('someMethod()'); + expect(method.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + + it('should handle static methods', function () { + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()$'; + parser.parse(str); + + const actual = parser.yy.getClass('Class1'); + expect(actual.annotations.length).toBe(0); + expect(actual.members.length).toBe(0); + expect(actual.methods.length).toBe(1); + const method = actual.methods[0]; + expect(method.getDisplayDetails().displayText).toBe('someMethod()'); + expect(method.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should handle generic types in arguments', function () { + const str = 'classDiagram\n' + 'class Car\n' + 'Car : +setWheels(List~Wheel~ wheels)'; + parser.parse(str); + }); + + it('should handle generic return types', function () { + const str = 'classDiagram\n' + 'class Car\n' + 'Car : +getWheels() List~Wheel~'; + + parser.parse(str); + }); + + it('should handle generic types in members in class with brackets', function () { + const str = + 'classDiagram\n' + + 'class Car {\n' + + 'List~Wheel~ wheels\n' + + 'setWheels(List~Wheel~ wheels)\n' + + '+getWheels() List~Wheel~\n' + + '}'; + + parser.parse(str); + }); + }); +}); + +describe('given a class diagram with generics, ', function () { + describe('when parsing valid generic classes', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + + it('should handle generic class', function () { + const str = 'classDiagram\n' + 'class Car~T~'; + + parser.parse(str); + }); + + it('should handle generic class with relationships', function () { + const str = + 'classDiagram\n' + + 'class Car~T~\n' + + 'Driver -- Car : drives >\n' + + 'Car *-- Wheel : have 4 >\n' + + 'Car -- Person : < owns'; + + parser.parse(str); + }); + + it('should handle generic class with a literal name', function () { + const str = + 'classDiagram\n' + + 'class `Car`~T~\n' + + 'Driver -- `Car` : drives >\n' + + '`Car` *-- Wheel : have 4 >\n' + + '`Car` -- Person : < owns'; + + parser.parse(str); + }); + + it('should handle generic class with brackets', function () { + const str = + 'classDiagram\n' + + 'class Dummy_Class~T~ {\n' + + 'String data\n' + + 'void methods()\n' + + '}\n' + + '\n' + + 'class Flight {\n' + + 'Integer flightNumber\n' + + 'Date departureTime\n' + + '}'; + + parser.parse(str); + }); + + it('should handle generic class with brackets and a literal name', function () { + const str = + 'classDiagram\n' + + 'class `Dummy_Class`~T~ {\n' + + 'String data\n' + + ' void methods()\n' + + '}\n' + + '\n' + + 'class Flight {\n' + + ' flightNumber : Integer\n' + + ' departureTime : Date\n' + + '}'; + + parser.parse(str); + }); + + it('should handle "namespace"', function () { + const str = `classDiagram +namespace Namespace1 { class Class1 } +namespace Namespace2 { class Class1 +} +namespace Namespace3 { +class Class1 { +int : test +string : foo +test() +foo() +} +} +namespace Namespace4 { +class Class1 { +int : test +string : foo +test() +foo() +} +class Class2 { +int : test +string : foo +test() +foo() +} +} +`; + parser.parse(str); + }); + }); +}); + +describe('given a class diagram with relationships, ', function () { + describe('when parsing basic relationships', function () { + beforeEach(function () { + classDb.clear(); + parser.yy = classDb; + }); + + it('should handle all basic relationships', function () { + const str = + 'classDiagram\n' + + 'Class1 <|-- Class02\n' + + 'Class03 *-- Class04\n' + + 'Class05 o-- Class06\n' + + 'Class07 .. Class08\n' + + 'Class09 -- Class1'; + + parser.parse(str); + }); + + it('should handle backquoted class name', function () { + const str = + 'classDiagram\n' + + '`Class1` <|-- Class02\n' + + 'Class03 *-- Class04\n' + + 'Class05 o-- Class06\n' + + 'Class07 .. Class08\n' + + 'Class09 -- Class1'; + + parser.parse(str); + }); + + it('should handle generics', function () { + const str = 'classDiagram\n' + 'Class1~T~ <|-- Class02'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class1').id).toBe('Class1'); + expect(parser.yy.getClass('Class1').type).toBe('T'); + expect(parser.yy.getClass('Class02').id).toBe('Class02'); + expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION); + expect(relations[0].relation.type2).toBe('none'); + expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); + }); + + it('should handle relationships with labels', function () { + const str = + 'classDiagram\n' + + 'class Car\n' + + 'Driver -- Car : drives >\n' + + 'Car *-- Wheel : have 4 >\n' + + 'Car -- Person : < owns'; + + parser.parse(str); + }); + + it('should handle relation definitions EXTENSION', function () { + const str = 'classDiagram\n' + 'Class1 <|-- Class02'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class1').id).toBe('Class1'); + expect(parser.yy.getClass('Class02').id).toBe('Class02'); + expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION); + expect(relations[0].relation.type2).toBe('none'); + expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); + }); + + it('should handle relation definition of different types and directions', function () { + const str = + 'classDiagram\n' + + 'Class11 <|.. Class12\n' + + 'Class13 --> Class14\n' + + 'Class15 ..> Class16\n' + + 'Class17 ..|> Class18\n' + + 'Class19 <--* Class20'; + + parser.parse(str); + }); + + it('should handle cardinality and labels', function () { + const str = + 'classDiagram\n' + + 'Class1 "1" *-- "many" Class02 : contains\n' + + 'Class03 o-- Class04 : aggregation\n' + + 'Class05 --> "1" Class06'; + + parser.parse(str); + }); + + it('should handle dashed relation definition of different types and directions', function () { + const str = + 'classDiagram\n' + + 'Class11 <|.. Class12\n' + + 'Class13 <.. Class14\n' + + 'Class15 ..|> Class16\n' + + 'Class17 ..> Class18\n' + + 'Class19 .. Class20'; + parser.parse(str); + }); + + it('should handle relation definitions AGGREGATION and dotted line', function () { + const str = 'classDiagram\n' + 'Class1 o.. Class02'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class1').id).toBe('Class1'); + expect(parser.yy.getClass('Class02').id).toBe('Class02'); + expect(relations[0].relation.type1).toBe(classDb.relationType.AGGREGATION); + expect(relations[0].relation.type2).toBe('none'); + expect(relations[0].relation.lineType).toBe(classDb.lineType.DOTTED_LINE); + }); + + it('should handle relation definitions COMPOSITION on both sides', function () { + const str = 'classDiagram\n' + 'Class1 *--* Class02'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class1').id).toBe('Class1'); + expect(parser.yy.getClass('Class02').id).toBe('Class02'); + expect(relations[0].relation.type1).toBe(classDb.relationType.COMPOSITION); + expect(relations[0].relation.type2).toBe(classDb.relationType.COMPOSITION); + expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); + }); + + it('should handle relation definitions with no types', function () { + const str = 'classDiagram\n' + 'Class1 -- Class02'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class1').id).toBe('Class1'); + expect(parser.yy.getClass('Class02').id).toBe('Class02'); + expect(relations[0].relation.type1).toBe('none'); + expect(relations[0].relation.type2).toBe('none'); + expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); + }); + + it('should handle relation definitions with type only on right side', function () { + const str = 'classDiagram\n' + 'Class1 --|> Class02'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class1').id).toBe('Class1'); + expect(parser.yy.getClass('Class02').id).toBe('Class02'); + expect(relations[0].relation.type1).toBe('none'); + expect(relations[0].relation.type2).toBe(classDb.relationType.EXTENSION); + expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); + }); + + it('should handle multiple classes and relation definitions', function () { + const str = + 'classDiagram\n' + + 'Class1 <|-- Class02\n' + + 'Class03 *-- Class04\n' + + 'Class05 o-- Class06\n' + + 'Class07 .. Class08\n' + + 'Class09 -- Class10'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class1').id).toBe('Class1'); + expect(parser.yy.getClass('Class10').id).toBe('Class10'); + + expect(relations.length).toBe(5); + + expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION); + expect(relations[0].relation.type2).toBe('none'); + expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); + expect(relations[3].relation.type1).toBe('none'); + expect(relations[3].relation.type2).toBe('none'); + expect(relations[3].relation.lineType).toBe(classDb.lineType.DOTTED_LINE); + }); + + it('should handle generic class with relation definitions', function () { + const str = 'classDiagram\n' + 'Class01~T~ <|-- Class02'; + + parser.parse(str); + + const relations = parser.yy.getRelations(); + + expect(parser.yy.getClass('Class01').id).toBe('Class01'); + expect(parser.yy.getClass('Class01').type).toBe('T'); + expect(parser.yy.getClass('Class02').id).toBe('Class02'); + expect(relations[0].relation.type1).toBe(classDb.relationType.EXTENSION); + expect(relations[0].relation.type2).toBe('none'); + expect(relations[0].relation.lineType).toBe(classDb.lineType.LINE); + }); + + it('should handle class annotations', function () { + const str = 'classDiagram\n' + 'class Class1\n' + '<> Class1'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(1); + expect(testClass.members.length).toBe(0); + expect(testClass.methods.length).toBe(0); + expect(testClass.annotations[0]).toBe('interface'); + }); + + it('should handle class annotations with members and methods', function () { + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : int test\n' + + 'Class1 : test()\n' + + '<> Class1'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(1); + expect(testClass.members.length).toBe(1); + expect(testClass.methods.length).toBe(1); + expect(testClass.annotations[0]).toBe('interface'); + }); + + it('should handle class annotations in brackets', function () { + const str = 'classDiagram\n' + 'class Class1 {\n' + '<>\n' + '}'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(1); + expect(testClass.members.length).toBe(0); + expect(testClass.methods.length).toBe(0); + expect(testClass.annotations[0]).toBe('interface'); + }); + + it('should handle class annotations in brackets with members and methods', function () { + const str = + 'classDiagram\n' + + 'class Class1 {\n' + + '<>\n' + + 'int : test\n' + + 'test()\n' + + '}'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(1); + expect(testClass.members.length).toBe(1); + expect(testClass.methods.length).toBe(1); + expect(testClass.annotations[0]).toBe('interface'); + }); + + it('should add bracket members in right order', function () { + const str = + 'classDiagram\n' + + 'class Class1 {\n' + + 'int : test\n' + + 'string : foo\n' + + 'test()\n' + + 'foo()\n' + + '}'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.members.length).toBe(2); + expect(testClass.methods.length).toBe(2); + expect(testClass.members[0].getDisplayDetails().displayText).toBe('int : test'); + expect(testClass.members[1].getDisplayDetails().displayText).toBe('string : foo'); + expect(testClass.methods[0].getDisplayDetails().displayText).toBe('test()'); + expect(testClass.methods[1].getDisplayDetails().displayText).toBe('foo()'); + }); + + it('should handle abstract methods', function () { + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()*'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(0); + expect(testClass.members.length).toBe(0); + expect(testClass.methods.length).toBe(1); + const method = testClass.methods[0]; + expect(method.getDisplayDetails().displayText).toBe('someMethod()'); + expect(method.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + + it('should handle static methods', function () { + const str = 'classDiagram\n' + 'class Class1\n' + 'Class1 : someMethod()$'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.annotations.length).toBe(0); + expect(testClass.members.length).toBe(0); + expect(testClass.methods.length).toBe(1); + const method = testClass.methods[0]; + expect(method.getDisplayDetails().displayText).toBe('someMethod()'); + expect(method.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should associate link and css appropriately', function () { + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'link Class1 "google.com"'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.link).toBe('google.com'); + expect(testClass.cssClasses.length).toBe(1); + expect(testClass.cssClasses[0]).toBe('clickable'); + }); + + it('should associate click and href link and css appropriately', function () { + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 href "google.com"'; + parser.parse(str); + + const testClass = parser.yy.getClass('Class1'); + expect(testClass.link).toBe('google.com'); + expect(testClass.cssClasses.length).toBe(1); + expect(testClass.cssClasses[0]).toBe('clickable'); + }); + + it('should associate link with tooltip', function () { + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'link Class1 "google.com" "A tooltip"'; + parser.parse(str); + + 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'); + }); + + it('should associate click and href link with tooltip', function () { + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 href "google.com" "A tooltip"'; + parser.parse(str); + + 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'); + }); + + it('should associate click and href link with tooltip and target appropriately', function () { + spyOn(classDb, 'setLink'); + spyOn(classDb, 'setTooltip'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 href "google.com" "A tooltip" _self'; + parser.parse(str); + + expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self'); + expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip'); + }); + + it('should associate click and href link appropriately', function () { + spyOn(classDb, 'setLink'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 href "google.com"'; + parser.parse(str); + + expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com'); + }); + + it('should associate click and href link with target appropriately', function () { + spyOn(classDb, 'setLink'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 href "google.com" _self'; + parser.parse(str); + + expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self'); + }); + + it('should associate link appropriately', function () { + spyOn(classDb, 'setLink'); + spyOn(classDb, 'setTooltip'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'link Class1 "google.com" "A tooltip" _self'; + parser.parse(str); + + expect(classDb.setLink).toHaveBeenCalledWith('Class1', 'google.com', '_self'); + expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip'); + }); + + it('should associate callback appropriately', function () { + spyOn(classDb, 'setClickEvent'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'callback Class1 "functionCall"'; + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); + }); + + it('should associate click and call callback appropriately', function () { + spyOn(classDb, 'setClickEvent'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 call functionCall()'; + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); + }); + + it('should associate callback appropriately with an arbitrary number of args', function () { + spyOn(classDb, 'setClickEvent'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 call functionCall("test0", test1, test2)'; + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith( + 'Class1', + 'functionCall', + '"test0", test1, test2' + ); + }); + + it('should associate callback with tooltip', function () { + spyOn(classDb, 'setClickEvent'); + spyOn(classDb, 'setTooltip'); + const str = + 'classDiagram\n' + + 'class Class1\n' + + 'Class1 : someMethod()\n' + + 'click Class1 call functionCall() "A tooltip"'; + parser.parse(str); + + expect(classDb.setClickEvent).toHaveBeenCalledWith('Class1', 'functionCall'); + expect(classDb.setTooltip).toHaveBeenCalledWith('Class1', 'A tooltip'); + }); + + it('should add classes namespaces', function () { + const str = `classDiagram +namespace Namespace1 { +class Class1 { +int : test +string : foo +test() +foo() +} +class Class2 +}`; + parser.parse(str); + + const testNamespace = parser.yy.getNamespace('Namespace1'); + const testClasses = parser.yy.getClasses(); + expect(Object.keys(testNamespace.classes).length).toBe(2); + expect(Object.keys(testNamespace.children).length).toBe(0); + expect(testNamespace.classes['Class1'].id).toBe('Class1'); + expect(Object.keys(testClasses).length).toBe(2); + }); + + it('should add relations between classes of different namespaces', function () { + const str = `classDiagram + A1 --> B1 + namespace A { + class A1 { + +foo : string + } + class A2 { + +bar : int + } + } + namespace B { + class B1 { + +foo : bool + } + class B2 { + +bar : float + } + } + A2 --> B2`; + + parser.parse(str); + const testNamespaceA = parser.yy.getNamespace('A'); + 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( + '+foo : string' + ); + expect(testNamespaceA.classes['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( + '+foo : bool' + ); + expect(testNamespaceB.classes['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(testRelations[0].id1).toBe('A1'); + expect(testRelations[0].id2).toBe('B1'); + expect(testRelations[1].id1).toBe('A2'); + expect(testRelations[1].id2).toBe('B2'); + }); + }); + + describe('when parsing classDiagram with text labels', () => { + beforeEach(function () { + parser.yy = classDb; + parser.yy.clear(); + }); + + it('should parse a class with a text label', () => { + parser.parse(`classDiagram + class C1["Class 1 with text label"] + C1 --> C2 + `); + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('C2'); + }); + + it('should parse two classes with text labels', () => { + parser.parse(`classDiagram + class C1["Class 1 with text label"] + class C2["Class 2 with chars @?"] + C1 --> C2 + `); + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('Class 2 with chars @?'); + }); + + it('should parse a class with a text label and members', () => { + parser.parse(`classDiagram + class C1["Class 1 with text label"] { + +member1 + } + C1 --> C2 + `); + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.members.length).toBe(1); + const member = c1.members[0]; + expect(member.getDisplayDetails().displayText).toBe('+member1'); + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('C2'); + }); + + it('should parse a class with a text label, members and annotation', () => { + parser.parse(`classDiagram + class C1["Class 1 with text label"] { + <> + +member1 + } + C1 --> C2 + `); + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class 1 with text label'); + expect(c1.members.length).toBe(1); + expect(c1.annotations.length).toBe(1); + expect(c1.annotations[0]).toBe('interface'); + const member = c1.members[0]; + expect(member.getDisplayDetails().displayText).toBe('+member1'); + + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('C2'); + }); + + it('should parse a class with text label and css class shorthand', () => { + parser.parse(`classDiagram +class C1["Class 1 with text label"]:::styleClass { + +member1 +} +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'); + const member = c1.members[0]; + expect(member.getDisplayDetails().displayText).toBe('+member1'); + }); + + it('should parse a class with text label and css class', () => { + parser.parse(`classDiagram +class C1["Class 1 with text label"] { + +member1 +} +C1 --> C2 +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'); + const member = c1.members[0]; + expect(member.getDisplayDetails().displayText).toBe('+member1'); + }); + + it('should parse two classes with text labels and css classes', () => { + parser.parse(`classDiagram +class C1["Class 1 with text label"] { + +member1 +} +class C2["Long long long long long long long long long long label"] +C1 --> C2 +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'); + + 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'); + }); + + it('should parse two classes with text labels and css class shorthands', () => { + parser.parse(`classDiagram +class C1["Class 1 with text label"]:::styleClass1 { + +member1 +} +class C2["Class 2 !@#$%^&*() label"]:::styleClass2 +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'); + + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('Class 2 !@#$%^&*() label'); + expect(c2.cssClasses.length).toBe(1); + expect(c2.cssClasses[0]).toBe('styleClass2'); + }); + + it('should parse multiple classes with same text labels', () => { + parser.parse(`classDiagram +class C1["Class with text label"] +class C2["Class with text label"] +class C3["Class with text label"] +C1 --> C2 +C3 ..> C2 + `); + + const c1 = classDb.getClass('C1'); + expect(c1.label).toBe('Class with text label'); + + const c2 = classDb.getClass('C2'); + expect(c2.label).toBe('Class with text label'); + + const c3 = classDb.getClass('C3'); + expect(c3.label).toBe('Class with text label'); + }); + + it('should parse classes with different text labels', () => { + parser.parse(`classDiagram +class C1["OneWord"] +class C2["With, Comma"] +class C3["With (Brackets)"] +class C4["With [Brackets]"] +class C5["With {Brackets}"] +class C6[" "] +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"] +`); + expect(classDb.getClass('C1').label).toBe('OneWord'); + expect(classDb.getClass('C2').label).toBe('With, Comma'); + expect(classDb.getClass('C3').label).toBe('With (Brackets)'); + expect(classDb.getClass('C4').label).toBe('With [Brackets]'); + expect(classDb.getClass('C5').label).toBe('With {Brackets}'); + expect(classDb.getClass('C6').label).toBe(' '); + expect(classDb.getClass('C7').label).toBe('With 1 number'); + expect(classDb.getClass('C8').label).toBe('With . period...'); + expect(classDb.getClass('C9').label).toBe('With - dash'); + expect(classDb.getClass('C10').label).toBe('With _ underscore'); + expect(classDb.getClass('C11').label).toBe("With ' single quote"); + expect(classDb.getClass('C12').label).toBe('With ~!@#$%^&*()_+=-/?'); + expect(classDb.getClass('C13').label).toBe('With Città foreign language'); + }); + }); +}); diff --git a/packages/mermaid/src/diagrams/class/classDiagram.ts b/packages/mermaid/src/diagrams/class/classDiagram.ts new file mode 100644 index 000000000..7f027c186 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classDiagram.ts @@ -0,0 +1,20 @@ +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 styles from './styles.js'; +import renderer from './classRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/class/classDiagramGrammar.spec.js b/packages/mermaid/src/diagrams/class/classDiagramGrammar.spec.js deleted file mode 100644 index 4e9e99c70..000000000 --- a/packages/mermaid/src/diagrams/class/classDiagramGrammar.spec.js +++ /dev/null @@ -1,13 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-var-requires -const fs = require('fs'); - -import { LALRGenerator } from 'jison'; - -describe('class diagram grammar', function () { - it('should introduce no new conflicts', function () { - const file = require.resolve('./parser/classDiagram.jison'); - const grammarSource = fs.readFileSync(file, 'utf8'); - const grammarParser = new LALRGenerator(grammarSource, {}); - expect(grammarParser.conflicts < 16).toBe(true); - }); -}); diff --git a/packages/mermaid/src/diagrams/class/classRenderer-v2.js b/packages/mermaid/src/diagrams/class/classRenderer-v2.js deleted file mode 100644 index b7e538583..000000000 --- a/packages/mermaid/src/diagrams/class/classRenderer-v2.js +++ /dev/null @@ -1,499 +0,0 @@ -import { select } from 'd3'; -import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; -import { log } from '../../logger'; -import { getConfig } from '../../config'; -import { render } from '../../dagre-wrapper/index.js'; -import utils from '../../utils'; -import { curveLinear } from 'd3'; -import { interpolateToCurve, getStylesFromArray } from '../../utils'; -import { setupGraphViewbox } from '../../setupGraphViewbox'; -import common from '../common/common'; - -const sanitizeText = (txt) => common.sanitizeText(txt, getConfig()); - -let conf = { - dividerMargin: 10, - padding: 5, - textHeight: 10, -}; - -/** - * Function that adds the vertices found during parsing to the graph to be rendered. - * - * @param {Object< - * string, - * { cssClasses: string[]; text: string; id: string; type: string; domId: string } - * >} classes - * Object containing the vertices. - * @param {SVGGElement} g The graph that is to be drawn. - * @param _id - * @param diagObj - */ -export const addClasses = function (classes, g, _id, diagObj) { - // const svg = select(`[id="${svgId}"]`); - const keys = Object.keys(classes); - log.info('keys:', keys); - log.info(classes); - - // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition - keys.forEach(function (id) { - const vertex = classes[id]; - - /** - * Variable for storing the classes for the vertex - * - * @type {string} - */ - let cssClassStr = ''; - if (vertex.cssClasses.length > 0) { - cssClassStr = cssClassStr + ' ' + vertex.cssClasses.join(' '); - } - // if (vertex.classes.length > 0) { - // classStr = vertex.classes.join(' '); - // } - - const styles = { labelStyle: '' }; //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; - // if (evaluate(getConfig().flowchart.htmlLabels)) { - // const node = { - // label: vertexText.replace( - // eslint-disable-next-line @cspell/spellchecker - // /fa[lrsb]?:fa-[\w-]+/g, - // s => `` - // ) - // }; - // vertexNode = addHtmlLabel(svg, node).node(); - // vertexNode.parentNode.removeChild(vertexNode); - // } else { - // const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text'); - // svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); - - // const rows = vertexText.split(common.lineBreakRegex); - - // for (let j = 0; j < rows.length; j++) { - // 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', '1'); - // tspan.textContent = rows[j]; - // svgLabel.appendChild(tspan); - // } - // vertexNode = svgLabel; - // } - - let radious = 0; - let _shape = ''; - // Set the shape based parameters - switch (vertex.type) { - case 'class': - _shape = 'class_box'; - break; - default: - _shape = 'class_box'; - } - // Add the node - g.setNode(vertex.id, { - labelStyle: styles.labelStyle, - shape: _shape, - labelText: sanitizeText(vertexText), - classData: vertex, - rx: radious, - ry: radious, - class: cssClassStr, - style: styles.style, - id: vertex.id, - domId: vertex.domId, - tooltip: diagObj.db.getTooltip(vertex.id) || '', - haveCallback: vertex.haveCallback, - link: vertex.link, - width: vertex.type === 'group' ? 500 : undefined, - type: vertex.type, - padding: getConfig().flowchart.padding, - }); - - log.info('setNode', { - labelStyle: styles.labelStyle, - shape: _shape, - labelText: vertexText, - rx: radious, - ry: radious, - class: cssClassStr, - style: styles.style, - id: vertex.id, - width: vertex.type === 'group' ? 500 : undefined, - type: vertex.type, - padding: getConfig().flowchart.padding, - }); - }); -}; - -/** - * Function that adds the additional vertices (notes) found during parsing to the graph to be rendered. - * - * @param {{text: string; class: string; placement: number}[]} notes - * Object containing the additional vertices (notes). - * @param {SVGGElement} g The graph that is to be drawn. - * @param {number} startEdgeId starting index for note edge - * @param classes - */ -export const addNotes = function (notes, g, startEdgeId, classes) { - log.info(notes); - - // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition - notes.forEach(function (note, i) { - const vertex = note; - - /** - * Variable for storing the classes for the vertex - * - * @type {string} - */ - let cssNoteStr = ''; - - const styles = { labelStyle: '', style: '' }; - - // Use vertex id as text in the box if no text is provided by the graph definition - let vertexText = vertex.text; - - let radious = 0; - let _shape = 'note'; - // Add the node - g.setNode(vertex.id, { - labelStyle: styles.labelStyle, - shape: _shape, - labelText: sanitizeText(vertexText), - noteData: vertex, - rx: radious, - ry: radious, - class: cssNoteStr, - style: styles.style, - id: vertex.id, - domId: vertex.id, - tooltip: '', - type: 'note', - padding: getConfig().flowchart.padding, - }); - - log.info('setNode', { - labelStyle: styles.labelStyle, - shape: _shape, - labelText: vertexText, - rx: radious, - ry: radious, - style: styles.style, - id: vertex.id, - type: 'note', - padding: getConfig().flowchart.padding, - }); - - if (!vertex.class || !(vertex.class in classes)) { - return; - } - const edgeId = startEdgeId + i; - const edgeData = {}; - //Set relationship style and line type - edgeData.classes = 'relation'; - edgeData.pattern = 'dotted'; - - edgeData.id = `edgeNote${edgeId}`; - // Set link type for rendering - edgeData.arrowhead = 'none'; - - log.info(`Note edge: ${JSON.stringify(edgeData)}, ${JSON.stringify(vertex)}`); - //Set edge extra labels - edgeData.startLabelRight = ''; - edgeData.endLabelLeft = ''; - - //Set relation arrow types - edgeData.arrowTypeStart = 'none'; - edgeData.arrowTypeEnd = 'none'; - let style = 'fill:none'; - let labelStyle = ''; - - edgeData.style = style; - edgeData.labelStyle = labelStyle; - - edgeData.curve = interpolateToCurve(conf.curve, curveLinear); - - // Add the edge to the graph - g.setEdge(vertex.id, vertex.class, edgeData, edgeId); - }); -}; - -/** - * Add edges to graph based on parsed graph definition - * - * @param relations - * @param {object} g The graph object - */ -export const addRelations = function (relations, g) { - const conf = getConfig().flowchart; - let cnt = 0; - - let defaultStyle; - let defaultLabelStyle; - - // if (typeof relations.defaultStyle !== 'undefined') { - // const defaultStyles = getStylesFromArray(relations.defaultStyle); - // defaultStyle = defaultStyles.style; - // defaultLabelStyle = defaultStyles.labelStyle; - // } - - relations.forEach(function (edge) { - cnt++; - const edgeData = {}; - //Set relationship style and line type - edgeData.classes = 'relation'; - edgeData.pattern = edge.relation.lineType == 1 ? 'dashed' : 'solid'; - - edgeData.id = 'id' + cnt; - // Set link type for rendering - if (edge.type === 'arrow_open') { - edgeData.arrowhead = 'none'; - } else { - edgeData.arrowhead = 'normal'; - } - - log.info(edgeData, edge); - //Set edge extra labels - //edgeData.startLabelLeft = edge.relationTitle1; - edgeData.startLabelRight = edge.relationTitle1 === 'none' ? '' : edge.relationTitle1; - edgeData.endLabelLeft = edge.relationTitle2 === 'none' ? '' : edge.relationTitle2; - //edgeData.endLabelRight = edge.relationTitle2; - - //Set relation arrow types - edgeData.arrowTypeStart = getArrowMarker(edge.relation.type1); - edgeData.arrowTypeEnd = getArrowMarker(edge.relation.type2); - let style = ''; - let labelStyle = ''; - - if (edge.style !== undefined) { - const styles = getStylesFromArray(edge.style); - style = styles.style; - labelStyle = styles.labelStyle; - } else { - style = 'fill:none'; - if (defaultStyle !== undefined) { - style = defaultStyle; - } - if (defaultLabelStyle !== undefined) { - labelStyle = defaultLabelStyle; - } - } - - edgeData.style = style; - edgeData.labelStyle = labelStyle; - - if (edge.interpolate !== undefined) { - edgeData.curve = interpolateToCurve(edge.interpolate, curveLinear); - } else if (relations.defaultInterpolate !== undefined) { - edgeData.curve = interpolateToCurve(relations.defaultInterpolate, curveLinear); - } else { - edgeData.curve = interpolateToCurve(conf.curve, curveLinear); - } - - edge.text = edge.title; - if (edge.text === undefined) { - if (edge.style !== undefined) { - edgeData.arrowheadStyle = 'fill: #333'; - } - } else { - edgeData.arrowheadStyle = 'fill: #333'; - edgeData.labelpos = 'c'; - - if (getConfig().flowchart.htmlLabels) { - edgeData.labelType = 'html'; - edgeData.label = '' + edge.text + ''; - } else { - edgeData.labelType = 'text'; - 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:'); - } - } - // Add the edge to the graph - g.setEdge(edge.id1, edge.id2, edgeData, cnt); - }); -}; - -/** - * Merges the value of `conf` with the passed `cnf` - * - * @param {object} cnf Config to merge - */ -export const setConf = function (cnf) { - const keys = Object.keys(cnf); - - keys.forEach(function (key) { - conf[key] = cnf[key]; - }); -}; - -/** - * Draws a flowchart in the tag with id: id based on the graph definition in text. - * - * @param {string} text - * @param {string} id - * @param _version - * @param diagObj - */ -export const draw = function (text, id, _version, diagObj) { - log.info('Drawing class - ', id); - - const conf = getConfig().flowchart; - const securityLevel = getConfig().securityLevel; - log.info('config:', conf); - const nodeSpacing = conf.nodeSpacing || 50; - const rankSpacing = conf.rankSpacing || 50; - - // Create the input mermaid.graph - const g = new graphlib.Graph({ - multigraph: true, - compound: true, - }) - .setGraph({ - rankdir: diagObj.db.getDirection(), - nodesep: nodeSpacing, - ranksep: rankSpacing, - marginx: 8, - marginy: 8, - }) - .setDefaultEdgeLabel(function () { - return {}; - }); - - // Fetch the vertices/nodes and edges/links from the parsed graph definition - const classes = diagObj.db.getClasses(); - const relations = diagObj.db.getRelations(); - const notes = diagObj.db.getNotes(); - - log.info(relations); - addClasses(classes, g, id, diagObj); - addRelations(relations, g); - addNotes(notes, g, relations.length + 1, classes); - - // Add custom shapes - // flowChartShapes.addToRenderV2(addShape); - - // Set up an SVG group so that we can translate the final graph. - 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. - const element = root.select('#' + id + ' g'); - render( - element, - g, - ['aggregation', 'extension', 'composition', 'dependency', 'lollipop'], - 'classDiagram', - id - ); - - utils.insertTitle(svg, 'classTitleText', conf.titleTopMargin, diagObj.db.getDiagramTitle()); - - setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth); - - // Add label rects for non html labels - if (!conf.htmlLabels) { - 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 - const dim = label.getBBox(); - - const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect'); - rect.setAttribute('rx', 0); - rect.setAttribute('ry', 0); - rect.setAttribute('width', dim.width); - rect.setAttribute('height', dim.height); - // rect.setAttribute('style', 'fill:#e8e8e8;'); - - label.insertBefore(rect, label.firstChild); - } - } - - // If node has a link, wrap it in an anchor SVG object. - // const keys = Object.keys(classes); - // keys.forEach(function(key) { - // const vertex = classes[key]; - - // if (vertex.link) { - // const node = select('#' + id + ' [id="' + key + '"]'); - // if (node) { - // const link = document.createElementNS('http://www.w3.org/2000/svg', 'a'); - // link.setAttributeNS('http://www.w3.org/2000/svg', 'class', vertex.classes.join(' ')); - // link.setAttributeNS('http://www.w3.org/2000/svg', 'href', vertex.link); - // link.setAttributeNS('http://www.w3.org/2000/svg', 'rel', 'noopener'); - - // const linkNode = node.insert(function() { - // return link; - // }, ':first-child'); - - // const shape = node.select('.label-container'); - // if (shape) { - // linkNode.append(function() { - // return shape.node(); - // }); - // } - - // const label = node.select('.label'); - // if (label) { - // linkNode.append(function() { - // return label.node(); - // }); - // } - // } - // } - // }); -}; - -/** - * Gets the arrow marker for a type index - * - * @param {number} type The type to look for - * @returns {'aggregation' | 'extension' | 'composition' | 'dependency'} The arrow marker - */ -function getArrowMarker(type) { - 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; -} - -export default { - setConf, - draw, -}; diff --git a/packages/mermaid/src/diagrams/class/classRenderer-v2.ts b/packages/mermaid/src/diagrams/class/classRenderer-v2.ts new file mode 100644 index 000000000..b581252bf --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classRenderer-v2.ts @@ -0,0 +1,418 @@ +// @ts-nocheck - don't check until handle it +import { select, curveLinear } from 'd3'; +import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; +import { log } from '../../logger.js'; +import { getConfig } from '../../config.js'; +import { render } from '../../dagre-wrapper/index.js'; +import utils from '../../utils.js'; +import { interpolateToCurve, getStylesFromArray } from '../../utils.js'; +import { setupGraphViewbox } from '../../setupGraphViewbox.js'; +import common from '../common/common.js'; +import type { ClassRelation, ClassNote, ClassMap, EdgeData, NamespaceMap } from './classTypes.js'; + +const sanitizeText = (txt: string) => common.sanitizeText(txt, getConfig()); + +let conf = { + dividerMargin: 10, + padding: 5, + textHeight: 10, + curve: undefined, +}; + +interface RectParameters { + id: string; + shape: 'rect'; + labelStyle: string; + domId: string; + labelText: string; + padding: number | undefined; + style?: string; +} + +/** + * Function that adds the vertices found during parsing to the graph to be rendered. + * + * @param namespaces - Object containing the vertices. + * @param g - The graph that is to be drawn. + * @param _id - id of the graph + * @param diagObj - The diagram object + */ +export const addNamespaces = function ( + namespaces: NamespaceMap, + g: graphlib.Graph, + _id: string, + diagObj: any +) { + const keys = Object.keys(namespaces); + log.info('keys:', 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]; + + // parent node must be one of [rect, roundedWithTitle, noteGroup, divider] + const shape = 'rect'; + + const node: RectParameters = { + shape: shape, + id: vertex.id, + domId: vertex.domId, + labelText: sanitizeText(vertex.id), + labelStyle: '', + style: 'fill: none; stroke: black', + // TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release + padding: getConfig().flowchart?.padding ?? getConfig().class?.padding, + }; + + g.setNode(vertex.id, node); + addClasses(vertex.classes, g, _id, diagObj, vertex.id); + + log.info('setNode', node); + }); +}; + +/** + * Function that adds the vertices found during parsing to the graph to be rendered. + * + * @param classes - Object containing the vertices. + * @param g - The graph that is to be drawn. + * @param _id - id of the graph + * @param diagObj - The diagram object + * @param parent - id of the parent namespace, if it exists + */ +export const addClasses = function ( + classes: ClassMap, + g: graphlib.Graph, + _id: string, + diagObj: any, + parent?: string +) { + const keys = Object.keys(classes); + log.info('keys:', 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]; + + /** + * Variable for storing the classes for the vertex + */ + const cssClassStr = vertex.cssClasses.join(' '); + + const styles = { labelStyle: '', style: '' }; //getStylesFromArray(vertex.styles); + + // Use vertex id as text in the box if no text is provided by the graph definition + const vertexText = vertex.label ?? vertex.id; + const radius = 0; + const shape = 'class_box'; + + // Add the node + const node = { + labelStyle: styles.labelStyle, + shape: shape, + labelText: sanitizeText(vertexText), + classData: vertex, + rx: radius, + ry: radius, + class: cssClassStr, + style: styles.style, + id: vertex.id, + domId: vertex.domId, + tooltip: diagObj.db.getTooltip(vertex.id, parent) || '', + haveCallback: vertex.haveCallback, + link: vertex.link, + width: vertex.type === 'group' ? 500 : undefined, + type: vertex.type, + // TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release + padding: getConfig().flowchart?.padding ?? getConfig().class?.padding, + }; + g.setNode(vertex.id, node); + + if (parent) { + g.setParent(vertex.id, parent); + } + + log.info('setNode', node); + }); +}; + +/** + * Function that adds the additional vertices (notes) found during parsing to the graph to be rendered. + * + * @param notes - Object containing the additional vertices (notes). + * @param g - The graph that is to be drawn. + * @param startEdgeId - starting index for note edge + * @param classes - Classes + */ +export const addNotes = function ( + notes: ClassNote[], + g: graphlib.Graph, + startEdgeId: number, + classes: ClassMap +) { + log.info(notes); + + notes.forEach(function (note, i) { + const vertex = note; + + const cssNoteStr = ''; + + const styles = { labelStyle: '', style: '' }; + + const vertexText = vertex.text; + + const radius = 0; + const shape = 'note'; + const node = { + labelStyle: styles.labelStyle, + shape: shape, + labelText: sanitizeText(vertexText), + noteData: vertex, + rx: radius, + ry: radius, + class: cssNoteStr, + style: styles.style, + id: vertex.id, + domId: vertex.id, + tooltip: '', + type: 'note', + // TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release + padding: getConfig().flowchart?.padding ?? getConfig().class?.padding, + }; + g.setNode(vertex.id, node); + log.info('setNode', node); + + if (!vertex.class || !(vertex.class in classes)) { + return; + } + const edgeId = startEdgeId + i; + + const edgeData: EdgeData = { + id: `edgeNote${edgeId}`, + //Set relationship style and line type + classes: 'relation', + pattern: 'dotted', + // Set link type for rendering + arrowhead: 'none', + //Set edge extra labels + startLabelRight: '', + endLabelLeft: '', + //Set relation arrow types + arrowTypeStart: 'none', + arrowTypeEnd: 'none', + style: 'fill:none', + labelStyle: '', + curve: interpolateToCurve(conf.curve, curveLinear), + }; + + // Add the edge to the graph + g.setEdge(vertex.id, vertex.class, edgeData, edgeId); + }); +}; + +/** + * Add edges to graph based on parsed graph definition + * + * @param relations - + * @param g - The graph object + */ +export const addRelations = function (relations: ClassRelation[], g: graphlib.Graph) { + const conf = getConfig().flowchart; + let cnt = 0; + + relations.forEach(function (edge) { + cnt++; + const edgeData: EdgeData = { + //Set relationship style and line type + classes: 'relation', + pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid', + id: 'id' + cnt, + // Set link type for rendering + arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal', + //Set edge extra labels + startLabelRight: edge.relationTitle1 === 'none' ? '' : edge.relationTitle1, + endLabelLeft: edge.relationTitle2 === 'none' ? '' : edge.relationTitle2, + //Set relation arrow types + arrowTypeStart: getArrowMarker(edge.relation.type1), + arrowTypeEnd: getArrowMarker(edge.relation.type2), + style: 'fill:none', + labelStyle: '', + curve: interpolateToCurve(conf?.curve, curveLinear), + }; + + log.info(edgeData, edge); + + if (edge.style !== undefined) { + const styles = getStylesFromArray(edge.style); + edgeData.style = styles.style; + edgeData.labelStyle = styles.labelStyle; + } + + edge.text = edge.title; + if (edge.text === undefined) { + if (edge.style !== undefined) { + edgeData.arrowheadStyle = 'fill: #333'; + } + } else { + edgeData.arrowheadStyle = 'fill: #333'; + edgeData.labelpos = 'c'; + + // TODO V10: Flowchart ? Keeping flowchart for backwards compatibility. Remove in next major release + if (getConfig().flowchart?.htmlLabels ?? getConfig().htmlLabels) { + edgeData.labelType = 'html'; + edgeData.label = '' + edge.text + ''; + } else { + edgeData.labelType = 'text'; + 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:'); + } + } + // Add the edge to the graph + g.setEdge(edge.id1, edge.id2, edgeData, cnt); + }); +}; + +/** + * Merges the value of `conf` with the passed `cnf` + * + * @param cnf - Config to merge + */ +export const setConf = function (cnf: any) { + conf = { + ...conf, + ...cnf, + }; +}; + +/** + * Draws a class diagram in the tag with id: id based on the definition in text. + * + * @param text - + * @param id - + * @param _version - + * @param diagObj - + */ +export const draw = async function (text: string, id: string, _version: string, diagObj: any) { + log.info('Drawing class - ', id); + + // TODO V10: Why flowchart? Might be a mistake when copying. + const conf = getConfig().flowchart ?? getConfig().class; + const securityLevel = getConfig().securityLevel; + log.info('config:', conf); + const nodeSpacing = conf?.nodeSpacing ?? 50; + const rankSpacing = conf?.rankSpacing ?? 50; + + // Create the input mermaid.graph + const g: graphlib.Graph = new graphlib.Graph({ + multigraph: true, + compound: true, + }) + .setGraph({ + rankdir: diagObj.db.getDirection(), + nodesep: nodeSpacing, + ranksep: rankSpacing, + marginx: 8, + marginy: 8, + }) + .setDefaultEdgeLabel(function () { + return {}; + }); + + // Fetch the vertices/nodes and edges/links from the parsed graph definition + const namespaces: NamespaceMap = diagObj.db.getNamespaces(); + const classes: ClassMap = diagObj.db.getClasses(); + const relations: ClassRelation[] = diagObj.db.getRelations(); + const notes: ClassNote[] = diagObj.db.getNotes(); + log.info(relations); + addNamespaces(namespaces, g, id, diagObj); + addClasses(classes, g, id, diagObj); + addRelations(relations, g); + addNotes(notes, g, relations.length + 1, classes); + + // Set up an SVG group so that we can translate the final graph. + 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. + const element = root.select('#' + id + ' g'); + await render( + element, + g, + ['aggregation', 'extension', 'composition', 'dependency', 'lollipop'], + 'classDiagram', + id + ); + + utils.insertTitle(svg, 'classTitleText', conf?.titleTopMargin ?? 5, diagObj.db.getDiagramTitle()); + + setupGraphViewbox(g, svg, conf?.diagramPadding, conf?.useMaxWidth); + + // Add label rects for non html labels + if (!conf?.htmlLabels) { + 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 + const dim = label.getBBox(); + + const rect = doc.createElementNS('http://www.w3.org/2000/svg', 'rect'); + rect.setAttribute('rx', 0); + rect.setAttribute('ry', 0); + rect.setAttribute('width', dim.width); + rect.setAttribute('height', dim.height); + + label.insertBefore(rect, label.firstChild); + } + } +}; + +/** + * Gets the arrow marker for a type index + * + * @param type - The type to look for + * @returns The arrow marker + */ +function 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; +} + +export default { + setConf, + draw, +}; diff --git a/packages/mermaid/src/diagrams/class/classRenderer.js b/packages/mermaid/src/diagrams/class/classRenderer.js index 80a7f26e4..58def16c2 100644 --- a/packages/mermaid/src/diagrams/class/classRenderer.js +++ b/packages/mermaid/src/diagrams/class/classRenderer.js @@ -1,10 +1,10 @@ import { select } from 'd3'; import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; -import { log } from '../../logger'; -import svgDraw from './svgDraw'; -import { configureSvgSize } from '../../setupGraphViewbox'; -import { getConfig } from '../../config'; +import { log } from '../../logger.js'; +import svgDraw from './svgDraw.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import { getConfig } from '../../config.js'; let idCache = {}; const padding = 20; @@ -141,8 +141,6 @@ const insertMarkers = function (elem) { export const draw = function (text, id, _version, diagObj) { const conf = getConfig().class; idCache = {}; - // diagObj.db.clear(); - // diagObj.parser.parse(text); log.info('Rendering diagram ' + text); diff --git a/packages/mermaid/src/diagrams/class/classTypes.spec.ts b/packages/mermaid/src/diagrams/class/classTypes.spec.ts new file mode 100644 index 000000000..2b360d447 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classTypes.spec.ts @@ -0,0 +1,683 @@ +import { ClassMember } from './classTypes.js'; +import { vi, describe, it, expect } from 'vitest'; +const spyOn = vi.spyOn; + +const staticCssStyle = 'text-decoration:underline;'; +const abstractCssStyle = 'font-style:italic;'; + +describe('given text representing a method, ', function () { + describe('when method has no parameters', function () { + it('should parse correctly', function () { + const str = `getTime()`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle public visibility', function () { + const str = `+getTime()`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTime()'); + }); + + it('should handle private visibility', function () { + const str = `-getTime()`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTime()'); + }); + + it('should handle protected visibility', function () { + const str = `#getTime()`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTime()'); + }); + + it('should handle internal visibility', function () { + const str = `~getTime()`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTime()'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTime()$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime()'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTime()*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime()'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method has single parameter value', function () { + it('should parse correctly', function () { + const str = `getTime(int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle public visibility', function () { + const str = `+getTime(int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTime(int)'); + }); + + it('should handle private visibility', function () { + const str = `-getTime(int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTime(int)'); + }); + + it('should handle protected visibility', function () { + const str = `#getTime(int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTime(int)'); + }); + + it('should handle internal visibility', function () { + const str = `~getTime(int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTime(int)'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTime(int)$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(int)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTime(int)*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(int)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method has single parameter type and name (type first)', function () { + it('should parse correctly', function () { + const str = `getTime(int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle public visibility', function () { + const str = `+getTime(int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTime(int count)'); + }); + + it('should handle private visibility', function () { + const str = `-getTime(int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTime(int count)'); + }); + + it('should handle protected visibility', function () { + const str = `#getTime(int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTime(int count)'); + }); + + it('should handle internal visibility', function () { + const str = `~getTime(int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTime(int count)'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTime(int count)$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(int count)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTime(int count)*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(int count)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method has single parameter type and name (name first)', function () { + it('should parse correctly', function () { + const str = `getTime(count int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle public visibility', function () { + const str = `+getTime(count int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTime(count int)'); + }); + + it('should handle private visibility', function () { + const str = `-getTime(count int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTime(count int)'); + }); + + it('should handle protected visibility', function () { + const str = `#getTime(count int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTime(count int)'); + }); + + it('should handle internal visibility', function () { + const str = `~getTime(count int)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTime(count int)'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTime(count int)$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(count int)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTime(count int)*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(count int)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method has multiple parameters', function () { + it('should parse correctly', function () { + const str = `getTime(string text, int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle public visibility', function () { + const str = `+getTime(string text, int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle private visibility', function () { + const str = `-getTime(string text, int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle protected visibility', function () { + const str = `#getTime(string text, int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should handle internal visibility', function () { + const str = `~getTime(string text, int count)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(str); + }); + + it('should return correct css for static classifier', function () { + const str = `getTime(string text, int count)$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(string text, int count)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTime(string text, int count)*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime(string text, int count)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method has return type', function () { + it('should parse correctly', function () { + const str = `getTime() DateTime`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime() : DateTime'); + }); + + it('should handle public visibility', function () { + const str = `+getTime() DateTime`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTime() : DateTime'); + }); + + it('should handle private visibility', function () { + const str = `-getTime() DateTime`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTime() : DateTime'); + }); + + it('should handle protected visibility', function () { + const str = `#getTime() DateTime`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTime() : DateTime'); + }); + + it('should handle internal visibility', function () { + const str = `~getTime() DateTime`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTime() : DateTime'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTime() DateTime$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime() : DateTime'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTime() DateTime*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTime() : DateTime'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method parameter is generic', function () { + it('should parse correctly', function () { + const str = `getTimes(List~T~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes(List)'); + }); + + it('should handle public visibility', function () { + const str = `+getTimes(List~T~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTimes(List)'); + }); + + it('should handle private visibility', function () { + const str = `-getTimes(List~T~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTimes(List)'); + }); + + it('should handle protected visibility', function () { + const str = `#getTimes(List~T~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTimes(List)'); + }); + + it('should handle internal visibility', function () { + const str = `~getTimes(List~T~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTimes(List)'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTimes(List~T~)$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes(List)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTimes(List~T~)*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes(List)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method parameter contains two generic', function () { + it('should parse correctly', function () { + const str = `getTimes(List~T~, List~OT~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes(List, List)'); + }); + + it('should handle public visibility', function () { + const str = `+getTimes(List~T~, List~OT~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTimes(List, List)'); + }); + + it('should handle private visibility', function () { + const str = `-getTimes(List~T~, List~OT~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTimes(List, List)'); + }); + + it('should handle protected visibility', function () { + const str = `#getTimes(List~T~, List~OT~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTimes(List, List)'); + }); + + it('should handle internal visibility', function () { + const str = `~getTimes(List~T~, List~OT~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTimes(List, List)'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTimes(List~T~, List~OT~)$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes(List, List)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTimes(List~T~, List~OT~)*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes(List, List)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method parameter is a nested generic', function () { + it('should parse correctly', function () { + const str = `getTimetableList(List~List~T~~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimetableList(List>)'); + }); + + it('should handle public visibility', function () { + const str = `+getTimetableList(List~List~T~~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTimetableList(List>)'); + }); + + it('should handle private visibility', function () { + const str = `-getTimetableList(List~List~T~~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTimetableList(List>)'); + }); + + it('should handle protected visibility', function () { + const str = `#getTimetableList(List~List~T~~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTimetableList(List>)'); + }); + + it('should handle internal visibility', function () { + const str = `~getTimetableList(List~List~T~~)`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTimetableList(List>)'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTimetableList(List~List~T~~)$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimetableList(List>)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTimetableList(List~List~T~~)*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimetableList(List>)'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method parameter is a composite generic', function () { + const methodNameAndParameters = 'getTimes(List~K, V~)'; + const expectedMethodNameAndParameters = 'getTimes(List)'; + it('should parse correctly', function () { + const str = methodNameAndParameters; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(expectedMethodNameAndParameters); + }); + + it('should handle public visibility', function () { + const str = '+' + methodNameAndParameters; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '+' + expectedMethodNameAndParameters + ); + }); + + it('should handle private visibility', function () { + const str = '-' + methodNameAndParameters; + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '-' + expectedMethodNameAndParameters + ); + }); + + it('should handle protected visibility', function () { + const str = '#' + methodNameAndParameters; + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '#' + expectedMethodNameAndParameters + ); + }); + + it('should handle internal visibility', function () { + const str = '~' + methodNameAndParameters; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '~' + expectedMethodNameAndParameters + ); + }); + + it('should return correct css for static classifier', function () { + const str = methodNameAndParameters + '$'; + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(expectedMethodNameAndParameters); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = methodNameAndParameters + '*'; + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe(expectedMethodNameAndParameters); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method return type is generic', function () { + it('should parse correctly', function () { + const str = `getTimes() List~T~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes() : List'); + }); + + it('should handle public visibility', function () { + const str = `+getTimes() List~T~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('+getTimes() : List'); + }); + + it('should handle private visibility', function () { + const str = `-getTimes() List~T~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('-getTimes() : List'); + }); + + it('should handle protected visibility', function () { + const str = `#getTimes() List~T~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('#getTimes() : List'); + }); + + it('should handle internal visibility', function () { + const str = `~getTimes() List~T~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('~getTimes() : List'); + }); + + it('should return correct css for static classifier', function () { + const str = `getTimes() List~T~$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes() : List'); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTimes() List~T~*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe('getTimes() : List'); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('when method return type is a nested generic', function () { + it('should parse correctly', function () { + const str = `getTimetableList() List~List~T~~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + 'getTimetableList() : List>' + ); + }); + + it('should handle public visibility', function () { + const str = `+getTimetableList() List~List~T~~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '+getTimetableList() : List>' + ); + }); + + it('should handle private visibility', function () { + const str = `-getTimetableList() List~List~T~~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '-getTimetableList() : List>' + ); + }); + + it('should handle protected visibility', function () { + const str = `#getTimetableList() List~List~T~~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '#getTimetableList() : List>' + ); + }); + + it('should handle internal visibility', function () { + const str = `~getTimetableList() List~List~T~~`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + '~getTimetableList() : List>' + ); + }); + + it('should return correct css for static classifier', function () { + const str = `getTimetableList() List~List~T~~$`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + 'getTimetableList() : List>' + ); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + + it('should return correct css for abstract classifier', function () { + const str = `getTimetableList() List~List~T~~*`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + 'getTimetableList() : List>' + ); + expect(classMember.getDisplayDetails().cssStyle).toBe(abstractCssStyle); + }); + }); + + describe('--uncategorized tests--', function () { + it('member name should handle double colons', function () { + const str = `std::map ~int,string~ pMap;`; + + const classMember = new ClassMember(str, 'attribute'); + expect(classMember.getDisplayDetails().displayText).toBe('std::map pMap;'); + }); + + it('member name should handle generic type', function () { + const str = `getTime~T~(this T, int seconds)$ DateTime`; + + const classMember = new ClassMember(str, 'method'); + expect(classMember.getDisplayDetails().displayText).toBe( + 'getTime(this T, int seconds) : DateTime' + ); + expect(classMember.getDisplayDetails().cssStyle).toBe(staticCssStyle); + }); + }); +}); diff --git a/packages/mermaid/src/diagrams/class/classTypes.ts b/packages/mermaid/src/diagrams/class/classTypes.ts new file mode 100644 index 000000000..aa5ec7b70 --- /dev/null +++ b/packages/mermaid/src/diagrams/class/classTypes.ts @@ -0,0 +1,182 @@ +import { getConfig } from '../../config.js'; +import { parseGenericTypes, sanitizeText } from '../common/common.js'; + +export interface ClassNode { + id: string; + type: string; + label: string; + cssClasses: string[]; + methods: ClassMember[]; + members: ClassMember[]; + annotations: string[]; + domId: string; + parent?: string; + link?: string; + linkTarget?: string; + haveCallback?: boolean; + tooltip?: string; +} + +export type Visibility = '#' | '+' | '~' | '-' | ''; +export const visibilityValues = ['#', '+', '~', '-', '']; + +/** + * Parses and stores class diagram member variables/methods. + * + */ +export class ClassMember { + id!: string; + cssStyle!: string; + memberType!: 'method' | 'attribute'; + visibility!: Visibility; + /** + * denote if static or to determine which css class to apply to the node + * @defaultValue '' + */ + classifier!: string; + /** + * parameters for method + * @defaultValue '' + */ + parameters!: string; + /** + * return type for method + * @defaultValue '' + */ + returnType!: string; + + constructor(input: string, memberType: 'method' | 'attribute') { + this.memberType = memberType; + this.visibility = ''; + this.classifier = ''; + const sanitizedInput = sanitizeText(input, getConfig()); + this.parseMember(sanitizedInput); + } + + getDisplayDetails() { + let displayText = this.visibility + parseGenericTypes(this.id); + if (this.memberType === 'method') { + displayText += `(${parseGenericTypes(this.parameters.trim())})`; + if (this.returnType) { + displayText += ' : ' + parseGenericTypes(this.returnType); + } + } + + displayText = displayText.trim(); + const cssStyle = this.parseClassifier(); + + return { + displayText, + cssStyle, + }; + } + + parseMember(input: string) { + let potentialClassifier = ''; + + if (this.memberType === 'method') { + const methodRegEx = /([#+~-])?(.+)\((.*)\)([\s$*])?(.*)([$*])?/; + const match = input.match(methodRegEx); + if (match) { + const detectedVisibility = match[1] ? match[1].trim() : ''; + + if (visibilityValues.includes(detectedVisibility)) { + this.visibility = detectedVisibility as Visibility; + } + + this.id = match[2].trim(); + 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(/[$*]/)) { + potentialClassifier = lastChar; + this.returnType = this.returnType.substring(0, this.returnType.length - 1); + } + } + } + } else { + const length = input.length; + const firstChar = input.substring(0, 1); + const lastChar = input.substring(length - 1); + + if (visibilityValues.includes(firstChar)) { + this.visibility = firstChar as Visibility; + } + + if (lastChar.match(/[*?]/)) { + potentialClassifier = lastChar; + } + + this.id = input.substring( + this.visibility === '' ? 0 : 1, + potentialClassifier === '' ? length : length - 1 + ); + } + + this.classifier = potentialClassifier; + } + + parseClassifier() { + switch (this.classifier) { + case '*': + return 'font-style:italic;'; + case '$': + return 'text-decoration:underline;'; + default: + return ''; + } + } +} + +export interface ClassNote { + id: string; + class: string; + text: string; +} + +export interface EdgeData { + arrowheadStyle?: string; + labelpos?: string; + labelType?: string; + label?: string; + classes: string; + pattern: string; + id: string; + arrowhead: string; + startLabelRight: string; + endLabelLeft: string; + arrowTypeStart: string; + arrowTypeEnd: string; + style: string; + labelStyle: string; + curve: any; +} + +export type ClassRelation = { + id1: string; + id2: string; + relationTitle1: string; + relationTitle2: string; + type: string; + title: string; + text: string; + style: string[]; + relation: { + type1: number; + type2: number; + lineType: number; + }; +}; + +export interface NamespaceNode { + id: string; + domId: string; + classes: ClassMap; + children: NamespaceMap; +} + +export type ClassMap = Record; +export type NamespaceMap = Record; diff --git a/packages/mermaid/src/diagrams/class/parser/classDiagram.jison b/packages/mermaid/src/diagrams/class/parser/classDiagram.jison index 157e3d7d8..9c67e306e 100644 --- a/packages/mermaid/src/diagrams/class/parser/classDiagram.jison +++ b/packages/mermaid/src/diagrams/class/parser/classDiagram.jison @@ -19,67 +19,36 @@ %x acc_title %x acc_descr %x acc_descr_multiline +%x class +%x class-body +%x namespace +%x namespace-body %% -\%\%\{ { this.begin('open_directive'); return 'open_directive'; } -.*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'; -((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } -":" { this.popState(); this.begin('arg_directive'); return ':'; } -\}\%\% { this.popState(); this.popState(); return 'close_directive'; } -((?:(?!\}\%\%).|\n)*) return 'arg_directive'; -\%\%(?!\{)*[^\n]*(\r?\n?)+ /* skip comments */ -\%\%[^\n]*(\r?\n)* /* skip comments */ -accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } -(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } -accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } -(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } -accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} -[\}] { this.popState(); } -[^\}]* return "acc_descr_multiline_value"; +\%\%\{ { this.begin('open_directive'); return 'open_directive'; } +.*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'; +((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } +":" { this.popState(); this.begin('arg_directive'); return ':'; } +\}\%\% { this.popState(); this.popState(); return 'close_directive'; } +((?:(?!\}\%\%).|\n)*) return 'arg_directive'; +\%\%(?!\{)*[^\n]*(\r?\n?)+ /* skip comments */ +\%\%[^\n]*(\r?\n)* /* skip comments */ +accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } +accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } +accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} +[\}] { this.popState(); } +[^\}]* return "acc_descr_multiline_value"; -\s*(\r?\n)+ return 'NEWLINE'; -\s+ /* skip whitespace */ -"classDiagram-v2" return 'CLASS_DIAGRAM'; -"classDiagram" return 'CLASS_DIAGRAM'; -[{] { this.begin("struct"); /*console.log('Starting struct');*/ return 'STRUCT_START';} -"[*]" { /*console.log('EDGE_STATE=',yytext);*/ return 'EDGE_STATE';} -<> return "EOF_IN_STRUCT"; -[{] return "OPEN_IN_STRUCT"; -[}] { /*console.log('Ending struct');*/this.popState(); return 'STRUCT_STOP';}} -[\n] /* nothing */ -[^{}\n]* { /*console.log('lex-member: ' + yytext);*/ return "MEMBER";} +\s*(\r?\n)+ return 'NEWLINE'; +\s+ /* skip whitespace */ -"class" return 'CLASS'; -"cssClass" return 'CSSCLASS'; -"callback" return 'CALLBACK'; -"link" return 'LINK'; -"click" return 'CLICK'; -"note for" return 'NOTE_FOR'; -"note" return 'NOTE'; -"<<" return 'ANNOTATION_START'; -">>" return 'ANNOTATION_END'; -[~] this.begin("generic"); -[~] this.popState(); -[^~]* return "GENERICTYPE"; -["] this.begin("string"); -["] this.popState(); -[^"]* return "STR"; - -[`] this.begin("bqstring"); -[`] this.popState(); -[^`]+ return "BQUOTE_STR"; - -/* ----interactivity command--- -'href' adds a link to the specified node. 'href' can only be specified when the -line was introduced with 'click'. -'href ""' attaches the specified link to the node that was specified by 'click'. -*/ -"href"[\s]+["] this.begin("href"); -["] this.popState(); -[^"]* return 'HREF'; +"classDiagram-v2" return 'CLASS_DIAGRAM'; +"classDiagram" return 'CLASS_DIAGRAM'; +"[*]" return 'EDGE_STATE'; /* ---interactivity command--- @@ -89,39 +58,92 @@ the line was introduced with 'click'. arguments to the node that was specified by 'click'. Function arguments are optional: 'call ()' simply executes 'callback_name' without any arguments. */ -"call"[\s]+ this.begin("callback_name"); -\([\s]*\) this.popState(); -\( this.popState(); this.begin("callback_args"); -[^(]* return 'CALLBACK_NAME'; -\) this.popState(); -[^)]* return 'CALLBACK_ARGS'; +"call"[\s]+ this.begin("callback_name"); +\([\s]*\) this.popState(); +\( this.popState(); this.begin("callback_args"); +[^(]* return 'CALLBACK_NAME'; +\) this.popState(); +[^)]* return 'CALLBACK_ARGS'; -"_self" return 'LINK_TARGET'; -"_blank" return 'LINK_TARGET'; -"_parent" return 'LINK_TARGET'; -"_top" return 'LINK_TARGET'; +["] this.popState(); +[^"]* return "STR"; +<*>["] this.begin("string"); -\s*\<\| return 'EXTENSION'; -\s*\|\> return 'EXTENSION'; -\s*\> return 'DEPENDENCY'; -\s*\< return 'DEPENDENCY'; -\s*\* return 'COMPOSITION'; -\s*o return 'AGGREGATION'; -\s*\(\) return 'LOLLIPOP'; -\-\- return 'LINE'; -\.\. return 'DOTTED_LINE'; -":"{1}[^:\n;]+ return 'LABEL'; -":"{3} return 'STYLE_SEPARATOR'; -\- return 'MINUS'; -"." return 'DOT'; -\+ return 'PLUS'; -\% return 'PCT'; -"=" return 'EQUALS'; -\= return 'EQUALS'; -\w+ return 'ALPHA'; -[!"#$%&'*+,-.`?\\/] return 'PUNCTUATION'; -[0-9]+ return 'NUM'; -[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]| +"namespace" { this.begin('namespace'); return 'NAMESPACE'; } +\s*(\r?\n)+ { this.popState(); return 'NEWLINE'; } +\s+ /* skip whitespace */ +[{] { this.begin("namespace-body"); return 'STRUCT_START';} +[}] { this.popState(); return 'STRUCT_STOP'; } +<> return "EOF_IN_STRUCT"; +\s*(\r?\n)+ return 'NEWLINE'; +\s+ /* skip whitespace */ +"[*]" return 'EDGE_STATE'; + +"class" { this.begin('class'); return 'CLASS';} +\s*(\r?\n)+ { this.popState(); return 'NEWLINE'; } +\s+ /* skip whitespace */ +[}] { this.popState(); this.popState(); return 'STRUCT_STOP';} +[{] { this.begin("class-body"); return 'STRUCT_START';} +[}] { this.popState(); return 'STRUCT_STOP'; } +<> return "EOF_IN_STRUCT"; +"[*]" { return 'EDGE_STATE';} +[{] return "OPEN_IN_STRUCT"; +[\n] /* nothing */ +[^{}\n]* { return "MEMBER";} + +<*>"cssClass" return 'CSSCLASS'; +<*>"callback" return 'CALLBACK'; +<*>"link" return 'LINK'; +<*>"click" return 'CLICK'; +<*>"note for" return 'NOTE_FOR'; +<*>"note" return 'NOTE'; +<*>"<<" return 'ANNOTATION_START'; +<*>">>" return 'ANNOTATION_END'; + +/* +---interactivity command--- +'href' adds a link to the specified node. 'href' can only be specified when the +line was introduced with 'click'. +'href ""' attaches the specified link to the node that was specified by 'click'. +*/ +<*>"href" return 'HREF'; + +[~] this.popState(); +[^~]* return "GENERICTYPE"; +<*>"~" this.begin("generic"); + +[`] this.popState(); +[^`]+ return "BQUOTE_STR"; +<*>[`] this.begin("bqstring"); + +<*>"_self" return 'LINK_TARGET'; +<*>"_blank" return 'LINK_TARGET'; +<*>"_parent" return 'LINK_TARGET'; +<*>"_top" return 'LINK_TARGET'; + +<*>\s*\<\| return 'EXTENSION'; +<*>\s*\|\> return 'EXTENSION'; +<*>\s*\> return 'DEPENDENCY'; +<*>\s*\< return 'DEPENDENCY'; +<*>\s*\* return 'COMPOSITION'; +<*>\s*o return 'AGGREGATION'; +<*>\s*\(\) return 'LOLLIPOP'; +<*>\-\- return 'LINE'; +<*>\.\. return 'DOTTED_LINE'; +<*>":"{1}[^:\n;]+ return 'LABEL'; +<*>":"{3} return 'STYLE_SEPARATOR'; +<*>\- return 'MINUS'; +<*>"." return 'DOT'; +<*>\+ return 'PLUS'; +<*>\% return 'PCT'; +<*>"=" return 'EQUALS'; +<*>\= return 'EQUALS'; +<*>\w+ return 'ALPHA'; +<*>"[" return 'SQS'; +<*>"]" return 'SQE'; +<*>[!"#$%&'*+,-.`?\\/] return 'PUNCTUATION'; +<*>[0-9]+ return 'NUM'; +<*>[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]| [\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]| [\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]| [\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]| @@ -182,9 +204,9 @@ Function arguments are optional: 'call ()' simply executes 'callb [\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]| [\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]| [\uFFD2-\uFFD7\uFFDA-\uFFDC] - return 'UNICODE_TEXT'; -\s return 'SPACE'; -<> return 'EOF'; + return 'UNICODE_TEXT'; +<*>\s return 'SPACE'; +<*><> return 'EOF'; /lex @@ -198,26 +220,18 @@ Function arguments are optional: 'call ()' simply executes 'callb start : mermaidDoc - | statments - | direction | directive start - ; - -direction - : direction_tb - { yy.setDirection('TB');} - | direction_bt - { yy.setDirection('BT');} - | direction_rl - { yy.setDirection('RL');} - | direction_lr - { yy.setDirection('LR');} + | statements ; mermaidDoc : graphConfig ; +graphConfig + : CLASS_DIAGRAM NEWLINE statements EOF + ; + directive : openDirective typeDirective closeDirective NEWLINE | openDirective typeDirective ':' argDirective closeDirective NEWLINE @@ -239,45 +253,70 @@ closeDirective : close_directive { yy.parseDirective('}%%', 'close_directive', 'class'); } ; -graphConfig - : CLASS_DIAGRAM NEWLINE statements EOF - ; - statements : statement | statement NEWLINE | statement NEWLINE statements ; +classLabel + : SQS STR SQE { $$=$2; } + ; + +namespaceName + : alphaNumToken { $$=$1; } + | alphaNumToken namespaceName { $$=$1+$2; } + ; + className : alphaNumToken { $$=$1; } | classLiteralName { $$=$1; } | alphaNumToken className { $$=$1+$2; } - | alphaNumToken GENERICTYPE { $$=$1+'~'+$2; } - | classLiteralName GENERICTYPE { $$=$1+'~'+$2; } + | alphaNumToken GENERICTYPE { $$=$1+'~'+$2+'~'; } + | classLiteralName GENERICTYPE { $$=$1+'~'+$2+'~'; } ; statement : relationStatement { yy.addRelation($1); } | relationStatement LABEL { $1.title = yy.cleanupLabel($2); yy.addRelation($1); } + | namespaceStatement | classStatement - | methodStatement + | memberStatement | annotationStatement | clickStatement | cssClassStatement | noteStatement - | directive | direction | acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); } | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } ; +namespaceStatement + : 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);} + ; + +classStatements + : classStatement {$$=[$1]} + | classStatement NEWLINE {$$=[$1]} + | classStatement NEWLINE classStatements {$3.unshift($1); $$=$3} + ; + classStatement - : CLASS className {yy.addClass($2);} - | CLASS className STYLE_SEPARATOR alphaNumToken {yy.addClass($2);yy.setCssClass($2, $4);} - | CLASS className STRUCT_START members STRUCT_STOP {/*console.log($2,JSON.stringify($4));*/yy.addClass($2);yy.addMembers($2,$4);} - | CLASS className STYLE_SEPARATOR alphaNumToken STRUCT_START members STRUCT_STOP {yy.addClass($2);yy.setCssClass($2, $4);yy.addMembers($2,$6);} + : classIdentifier + | classIdentifier STYLE_SEPARATOR alphaNumToken {yy.setCssClass($1, $3);} + | classIdentifier STRUCT_START members STRUCT_STOP {yy.addMembers($1,$3);} + | classIdentifier STYLE_SEPARATOR alphaNumToken STRUCT_START members STRUCT_STOP {yy.setCssClass($1, $3);yy.addMembers($1,$5);} + ; + +classIdentifier + : CLASS className {$$=$2; yy.addClass($2);} + | CLASS className classLabel {$$=$2; yy.addClass($2);yy.setClassLabel($2, $3);} ; annotationStatement @@ -289,7 +328,7 @@ members | MEMBER members { $2.push($1);$$=$2;} ; -methodStatement +memberStatement : className {/*console.log('Rel found',$1);*/} | className LABEL {yy.addMember($1,yy.cleanupLabel($2));} | MEMBER {/*console.warn('Member',$1);*/} @@ -308,6 +347,17 @@ noteStatement | NOTE noteText { yy.addNote($2); } ; +direction + : direction_tb + { yy.setDirection('TB');} + | direction_bt + { yy.setDirection('BT');} + | direction_rl + { yy.setDirection('RL');} + | direction_lr + { yy.setDirection('LR');} + ; + relation : relationType lineType relationType { $$={type1:$1,type2:$3,lineType:$2}; } | lineType relationType { $$={type1:'none',type2:$2,lineType:$1}; } @@ -339,10 +389,10 @@ clickStatement | CLICK className CALLBACK_NAME STR {$$ = $1;yy.setClickEvent($2, $3);yy.setTooltip($2, $4);} | CLICK className CALLBACK_NAME CALLBACK_ARGS {$$ = $1;yy.setClickEvent($2, $3, $4);} | CLICK className CALLBACK_NAME CALLBACK_ARGS STR {$$ = $1;yy.setClickEvent($2, $3, $4);yy.setTooltip($2, $5);} - | CLICK className HREF {$$ = $1;yy.setLink($2, $3);} - | CLICK className HREF LINK_TARGET {$$ = $1;yy.setLink($2, $3, $4);} - | CLICK className HREF STR {$$ = $1;yy.setLink($2, $3);yy.setTooltip($2, $4);} - | CLICK className HREF STR LINK_TARGET {$$ = $1;yy.setLink($2, $3, $5);yy.setTooltip($2, $4);} + | CLICK className HREF STR {$$ = $1;yy.setLink($2, $4);} + | CLICK className HREF STR LINK_TARGET {$$ = $1;yy.setLink($2, $4, $5);} + | CLICK className HREF STR STR {$$ = $1;yy.setLink($2, $4);yy.setTooltip($2, $5);} + | CLICK className HREF STR STR LINK_TARGET {$$ = $1;yy.setLink($2, $4, $6);yy.setTooltip($2, $5);} ; cssClassStatement @@ -355,7 +405,7 @@ textToken : textNoTagsToken | TAGSTART | TAGEND | '==' | '--' | PCT | DEFA textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ; -alphaNumToken : UNICODE_TEXT | NUM | ALPHA; +alphaNumToken : UNICODE_TEXT | NUM | ALPHA | MINUS; classLiteralName : BQUOTE_STR; diff --git a/packages/mermaid/src/diagrams/class/styles.js b/packages/mermaid/src/diagrams/class/styles.js index 981cd7b73..f12f609f9 100644 --- a/packages/mermaid/src/diagrams/class/styles.js +++ b/packages/mermaid/src/diagrams/class/styles.js @@ -41,7 +41,7 @@ const getStyles = (options) => .divider { stroke: ${options.nodeBorder}; - stroke: 1; + stroke-width: 1; } g.clickable { @@ -109,25 +109,25 @@ g.classGroup line { } #extensionStart, .extension { - fill: ${options.mainBkg} !important; + fill: transparent !important; stroke: ${options.lineColor} !important; stroke-width: 1; } #extensionEnd, .extension { - fill: ${options.mainBkg} !important; + fill: transparent !important; stroke: ${options.lineColor} !important; stroke-width: 1; } #aggregationStart, .aggregation { - fill: ${options.mainBkg} !important; + fill: transparent !important; stroke: ${options.lineColor} !important; stroke-width: 1; } #aggregationEnd, .aggregation { - fill: ${options.mainBkg} !important; + fill: transparent !important; stroke: ${options.lineColor} !important; stroke-width: 1; } diff --git a/packages/mermaid/src/diagrams/class/svgDraw.js b/packages/mermaid/src/diagrams/class/svgDraw.js index cc6909280..d6ed7bca4 100644 --- a/packages/mermaid/src/diagrams/class/svgDraw.js +++ b/packages/mermaid/src/diagrams/class/svgDraw.js @@ -1,7 +1,7 @@ import { line, curveBasis } from 'd3'; -import utils from '../../utils'; -import { log } from '../../logger'; -import { parseGenericTypes } from '../common/common'; +import utils from '../../utils.js'; +import { log } from '../../logger.js'; +import { parseGenericTypes } from '../common/common.js'; let edgeCount = 0; export const drawEdge = function (elem, path, relation, conf, diagObj) { @@ -172,7 +172,6 @@ export const drawClass = function (elem, classDef, conf, diagObj) { // add class group const g = elem.append('g').attr('id', diagObj.db.lookUpDomId(id)).attr('class', 'classGroup'); - // add title let title; if (classDef.link) { title = g @@ -199,11 +198,7 @@ export const drawClass = function (elem, classDef, conf, diagObj) { isFirst = false; }); - let classTitleString = classDef.id; - - if (classDef.type !== undefined && classDef.type !== '') { - classTitleString += '<' + classDef.type + '>'; - } + let classTitleString = getClassTitleString(classDef); const classTitle = title.append('tspan').text(classTitleString).attr('class', 'title'); @@ -213,47 +208,56 @@ export const drawClass = function (elem, classDef, conf, diagObj) { } const titleHeight = title.node().getBBox().height; + let membersLine; + let membersBox; + let methodsLine; - const membersLine = g - .append('line') // text label for the x axis - .attr('x1', 0) - .attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2) - .attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2); + // don't draw box if no members + if (classDef.members.length > 0) { + membersLine = g + .append('line') // text label for the x axis + .attr('x1', 0) + .attr('y1', conf.padding + titleHeight + conf.dividerMargin / 2) + .attr('y2', conf.padding + titleHeight + conf.dividerMargin / 2); - const members = g - .append('text') // text label for the x axis - .attr('x', conf.padding) - .attr('y', titleHeight + conf.dividerMargin + conf.textHeight) - .attr('fill', 'white') - .attr('class', 'classText'); + const members = g + .append('text') // text label for the x axis + .attr('x', conf.padding) + .attr('y', titleHeight + conf.dividerMargin + conf.textHeight) + .attr('fill', 'white') + .attr('class', 'classText'); - isFirst = true; - classDef.members.forEach(function (member) { - addTspan(members, member, isFirst, conf); - isFirst = false; - }); + isFirst = true; + classDef.members.forEach(function (member) { + addTspan(members, member, isFirst, conf); + isFirst = false; + }); - const membersBox = members.node().getBBox(); + membersBox = members.node().getBBox(); + } - const methodsLine = g - .append('line') // text label for the x axis - .attr('x1', 0) - .attr('y1', conf.padding + titleHeight + conf.dividerMargin + membersBox.height) - .attr('y2', conf.padding + titleHeight + conf.dividerMargin + membersBox.height); + // don't draw box if no methods + if (classDef.methods.length > 0) { + methodsLine = g + .append('line') // text label for the x axis + .attr('x1', 0) + .attr('y1', conf.padding + titleHeight + conf.dividerMargin + membersBox.height) + .attr('y2', conf.padding + titleHeight + conf.dividerMargin + membersBox.height); - const methods = g - .append('text') // text label for the x axis - .attr('x', conf.padding) - .attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight) - .attr('fill', 'white') - .attr('class', 'classText'); + const methods = g + .append('text') // text label for the x axis + .attr('x', conf.padding) + .attr('y', titleHeight + 2 * conf.dividerMargin + membersBox.height + conf.textHeight) + .attr('fill', 'white') + .attr('class', 'classText'); - isFirst = true; + isFirst = true; - classDef.methods.forEach(function (method) { - addTspan(methods, method, isFirst, conf); - isFirst = false; - }); + classDef.methods.forEach(function (method) { + addTspan(methods, method, isFirst, conf); + isFirst = false; + }); + } const classBox = g.node().getBBox(); var cssClassStr = ' '; @@ -282,8 +286,12 @@ export const drawClass = function (elem, classDef, conf, diagObj) { title.insert('title').text(classDef.tooltip); } - membersLine.attr('x2', rectWidth); - methodsLine.attr('x2', rectWidth); + if (membersLine) { + membersLine.attr('x2', rectWidth); + } + if (methodsLine) { + methodsLine.attr('x2', rectWidth); + } classInfo.width = rectWidth; classInfo.height = classBox.height + conf.padding + 0.5 * conf.dividerMargin; @@ -291,6 +299,16 @@ export const drawClass = function (elem, classDef, conf, diagObj) { return classInfo; }; +export const getClassTitleString = function (classDef) { + let classTitleString = classDef.id; + + if (classDef.type) { + classTitleString += '<' + parseGenericTypes(classDef.type) + '>'; + } + + return classTitleString; +}; + /** * Renders a note diagram * @@ -354,128 +372,19 @@ export const drawNote = function (elem, note, conf, diagObj) { return noteInfo; }; -export const parseMember = function (text) { - const fieldRegEx = /^([#+~-])?(\w+)(~\w+~|\[])?\s+(\w+) *([$*])?$/; - const methodRegEx = /^([#+|~-])?(\w+) *\( *(.*)\) *([$*])? *(\w*[[\]|~]*\s*\w*~?)$/; - - let fieldMatch = text.match(fieldRegEx); - let methodMatch = text.match(methodRegEx); - - if (fieldMatch && !methodMatch) { - return buildFieldDisplay(fieldMatch); - } else if (methodMatch) { - return buildMethodDisplay(methodMatch); - } else { - return buildLegacyDisplay(text); - } -}; - -const buildFieldDisplay = function (parsedText) { - let cssStyle = ''; - let displayText = ''; - - try { - let visibility = parsedText[1] ? parsedText[1].trim() : ''; - let fieldType = parsedText[2] ? parsedText[2].trim() : ''; - let genericType = parsedText[3] ? parseGenericTypes(parsedText[3].trim()) : ''; - let fieldName = parsedText[4] ? parsedText[4].trim() : ''; - let classifier = parsedText[5] ? parsedText[5].trim() : ''; - - displayText = visibility + fieldType + genericType + ' ' + fieldName; - cssStyle = parseClassifier(classifier); - } catch (err) { - displayText = parsedText; - } - - return { - displayText: displayText, - cssStyle: cssStyle, - }; -}; - -const buildMethodDisplay = function (parsedText) { - let cssStyle = ''; - let displayText = ''; - - try { - let visibility = parsedText[1] ? parsedText[1].trim() : ''; - let methodName = parsedText[2] ? parsedText[2].trim() : ''; - let parameters = parsedText[3] ? parseGenericTypes(parsedText[3].trim()) : ''; - let classifier = parsedText[4] ? parsedText[4].trim() : ''; - let returnType = parsedText[5] ? ' : ' + parseGenericTypes(parsedText[5]).trim() : ''; - - displayText = visibility + methodName + '(' + parameters + ')' + returnType; - cssStyle = parseClassifier(classifier); - } catch (err) { - displayText = parsedText; - } - - return { - displayText: displayText, - cssStyle: cssStyle, - }; -}; - -const buildLegacyDisplay = function (text) { - // if for some reason we don't have any match, use old format to parse text - let displayText = ''; - let cssStyle = ''; - let returnType = ''; - let methodStart = text.indexOf('('); - let methodEnd = text.indexOf(')'); - - if (methodStart > 1 && methodEnd > methodStart && methodEnd <= text.length) { - let visibility = ''; - let methodName = ''; - - let firstChar = text.substring(0, 1); - if (firstChar.match(/\w/)) { - methodName = text.substring(0, methodStart).trim(); - } else { - if (firstChar.match(/[#+~-]/)) { - visibility = firstChar; - } - - methodName = text.substring(1, methodStart).trim(); - } - - const parameters = text.substring(methodStart + 1, methodEnd); - const classifier = text.substring(methodEnd + 1, 1); - cssStyle = parseClassifier(text.substring(methodEnd + 1, methodEnd + 2)); - - displayText = visibility + methodName + '(' + parseGenericTypes(parameters.trim()) + ')'; - - if (methodEnd < text.length) { - returnType = text.substring(methodEnd + 2).trim(); - if (returnType !== '') { - returnType = ' : ' + parseGenericTypes(returnType); - displayText += returnType; - } - } - } else { - // finally - if all else fails, just send the text back as written (other than parsing for generic types) - displayText = parseGenericTypes(text); - } - - return { - displayText, - cssStyle, - }; -}; /** * Adds a for a member in a diagram * * @param {SVGElement} textEl The element to append to - * @param {string} txt The member + * @param {string} member The member * @param {boolean} isFirst * @param {{ padding: string; textHeight: string }} conf The configuration for the member */ -const addTspan = function (textEl, txt, isFirst, conf) { - let member = parseMember(txt); +const addTspan = function (textEl, member, isFirst, conf) { + const { displayText, cssStyle } = member.getDisplayDetails(); + const tSpan = textEl.append('tspan').attr('x', conf.padding).text(displayText); - const tSpan = textEl.append('tspan').attr('x', conf.padding).text(member.displayText); - - if (member.cssStyle !== '') { + if (cssStyle !== '') { tSpan.attr('style', member.cssStyle); } @@ -484,26 +393,9 @@ const addTspan = function (textEl, txt, isFirst, conf) { } }; -/** - * Gives the styles for a classifier - * - * @param {'+' | '-' | '#' | '~' | '*' | '$'} classifier The classifier string - * @returns {string} Styling for the classifier - */ -const parseClassifier = function (classifier) { - switch (classifier) { - case '*': - return 'font-style:italic;'; - case '$': - return 'text-decoration:underline;'; - default: - return ''; - } -}; - export default { + getClassTitleString, drawClass, drawEdge, drawNote, - parseMember, }; diff --git a/packages/mermaid/src/diagrams/class/svgDraw.spec.js b/packages/mermaid/src/diagrams/class/svgDraw.spec.js index ec8785559..f068f8d62 100644 --- a/packages/mermaid/src/diagrams/class/svgDraw.spec.js +++ b/packages/mermaid/src/diagrams/class/svgDraw.spec.js @@ -1,175 +1,27 @@ -import svgDraw from './svgDraw'; +import svgDraw from './svgDraw.js'; +import { JSDOM } from 'jsdom'; -describe('class member Renderer, ', function () { - describe('when parsing text to build method display string', function () { - it('should handle simple method declaration', function () { - const str = 'foo()'; - let actual = svgDraw.parseMember(str); +describe('given a string representing a class, ', function () { + describe('when class name includes generic, ', function () { + it('should return correct text for generic', function () { + const classDef = { + id: 'Car', + type: 'T', + label: 'Car', + }; - expect(actual.displayText).toBe('foo()'); - expect(actual.cssStyle).toBe(''); + let actual = svgDraw.getClassTitleString(classDef); + expect(actual).toBe('Car'); }); + it('should return correct text for nested generics', function () { + const classDef = { + id: 'Car', + type: 'T~T~', + label: 'Car', + }; - it('should handle public visibility', function () { - const str = '+foo()'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('+foo()'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle private visibility', function () { - const str = '-foo()'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('-foo()'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle protected visibility', function () { - const str = '#foo()'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('#foo()'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle package/internal visibility', function () { - const str = '~foo()'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('~foo()'); - expect(actual.cssStyle).toBe(''); - }); - - it('should ignore unknown character for visibility', function () { - const str = '!foo()'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo()'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle abstract method classifier', function () { - const str = 'foo()*'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo()'); - expect(actual.cssStyle).toBe('font-style:italic;'); - }); - - it('should handle static method classifier', function () { - const str = 'foo()$'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo()'); - expect(actual.cssStyle).toBe('text-decoration:underline;'); - }); - - it('should ignore unknown character for classifier', function () { - const str = 'foo()!'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo()'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle simple method declaration with parameters', function () { - const str = 'foo(int id)'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo(int id)'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle simple method declaration with multiple parameters', function () { - const str = 'foo(int id, object thing)'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo(int id, object thing)'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle simple method declaration with single item in parameters', function () { - const str = 'foo(id)'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo(id)'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle simple method declaration with single item in parameters with extra spaces', function () { - const str = ' foo ( id) '; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo(id)'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle method declaration with return value', function () { - const str = 'foo(id) int'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo(id) : int'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle method declaration with generic return value', function () { - const str = 'foo(id) List~int~'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo(id) : List'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle method declaration with generic parameter', function () { - const str = 'foo(List~int~)'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('foo(List)'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle method declaration with all possible markup', function () { - const str = '+foo ( List~int~ ids )* List~Item~'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('+foo(List ids) : List'); - expect(actual.cssStyle).toBe('font-style:italic;'); - }); - - it('should handle method declaration with nested markup', function () { - const str = '+foo ( List~List~int~~ ids )* List~List~Item~~'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('+foo(List> ids) : List>'); - expect(actual.cssStyle).toBe('font-style:italic;'); - }); - }); - - describe('when parsing text to build field display string', function () { - it('should handle simple field declaration', function () { - const str = 'int[] ids'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('int[] ids'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle field declaration with generic type', function () { - const str = 'List~int~ ids'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('List ids'); - expect(actual.cssStyle).toBe(''); - }); - - it('should handle static field classifier', function () { - const str = 'String foo$'; - let actual = svgDraw.parseMember(str); - - expect(actual.displayText).toBe('String foo'); - expect(actual.cssStyle).toBe('text-decoration:underline;'); + let actual = svgDraw.getClassTitleString(classDef); + expect(actual).toBe('Car>'); }); }); }); diff --git a/packages/mermaid/src/diagrams/common/common.spec.js b/packages/mermaid/src/diagrams/common/common.spec.js deleted file mode 100644 index 8fd6229da..000000000 --- a/packages/mermaid/src/diagrams/common/common.spec.js +++ /dev/null @@ -1,74 +0,0 @@ -import { sanitizeText, removeScript, parseGenericTypes } from './common'; - -describe('when securityLevel is antiscript, all script must be removed', function () { - /** - * @param {string} original The original text - * @param {string} result The expected sanitized text - */ - function compareRemoveScript(original, result) { - expect(removeScript(original).trim()).toEqual(result); - } - - it('should remove all script block, script inline.', function () { - const labelString = `1 - Act1: Hello 11 - Act2: - 11 - 1`; - const exactlyString = `1 - Act1: Hello 11 - Act2: - 11 - 1`; - compareRemoveScript(labelString, exactlyString); - }); - - it('should remove all javascript urls', function () { - compareRemoveScript( - `This is a clean link + clean link - and me too`, - `This is a clean link + clean link - and me too` - ); - }); - - it('should detect malicious images', function () { - compareRemoveScript(``, ``); - }); - - it('should detect iframes', function () { - compareRemoveScript( - ` - `, - '' - ); - }); -}); - -describe('Sanitize text', function () { - it('should remove script tag', function () { - const maliciousStr = 'javajavascript:script:alert(1)'; - const result = sanitizeText(maliciousStr, { - securityLevel: 'strict', - flowchart: { htmlLabels: true }, - }); - expect(result).not.toContain('javascript:alert(1)'); - }); -}); - -describe('generic parser', function () { - it('should parse generic types', function () { - expect(parseGenericTypes('test~T~')).toEqual('test'); - expect(parseGenericTypes('test~Array~Array~string~~~')).toEqual('test>>'); - expect(parseGenericTypes('test~Array~Array~string[]~~~')).toEqual( - 'test>>' - ); - expect(parseGenericTypes('test ~Array~Array~string[]~~~')).toEqual( - 'test >>' - ); - expect(parseGenericTypes('~test')).toEqual('~test'); - expect(parseGenericTypes('~test Array~string~')).toEqual('~test Array'); - }); -}); diff --git a/packages/mermaid/src/diagrams/common/common.spec.ts b/packages/mermaid/src/diagrams/common/common.spec.ts new file mode 100644 index 000000000..4dac5b33c --- /dev/null +++ b/packages/mermaid/src/diagrams/common/common.spec.ts @@ -0,0 +1,87 @@ +import { sanitizeText, removeScript, parseGenericTypes, countOccurrence } from './common.js'; + +describe('when securityLevel is antiscript, all script must be removed', () => { + /** + * @param original - The original text + * @param result - The expected sanitized text + */ + function compareRemoveScript(original: string, result: string) { + expect(removeScript(original).trim()).toEqual(result); + } + + it('should remove all script block, script inline.', () => { + const labelString = `1 + Act1: Hello 11 + Act2: + 11 + 1`; + const exactlyString = `1 + Act1: Hello 11 + Act2: + 11 + 1`; + compareRemoveScript(labelString, exactlyString); + }); + + it('should remove all javascript urls', () => { + compareRemoveScript( + `This is a clean link + clean link + and me too`, + `This is a clean link + clean link + and me too` + ); + }); + + it('should detect malicious images', () => { + compareRemoveScript(``, ``); + }); + + it('should detect iframes', () => { + compareRemoveScript( + ` + `, + '' + ); + }); +}); + +describe('Sanitize text', () => { + it('should remove script tag', () => { + const maliciousStr = 'javajavascript:script:alert(1)'; + const result = sanitizeText(maliciousStr, { + securityLevel: 'strict', + flowchart: { htmlLabels: true }, + }); + expect(result).not.toContain('javascript:alert(1)'); + }); +}); + +describe('generic parser', () => { + it.each([ + ['test~T~', 'test'], + ['test~Array~Array~string~~~', 'test>>'], + ['test~Array~Array~string[]~~~', 'test>>'], + ['test ~Array~Array~string[]~~~', 'test >>'], + ['~test', '~test'], + ['~test~T~', '~test'], + ])('should parse generic types: %s to %s', (input: string, expected: string) => { + expect(parseGenericTypes(input)).toEqual(expected); + }); +}); + +it.each([ + ['', '', 0], + ['', 'x', 0], + ['test', 'x', 0], + ['test', 't', 2], + ['test', 'te', 1], + ['test~T~', '~', 2], + ['test~Array~Array~string~~~', '~', 6], +])( + 'should count `%s` to contain occurrences of `%s` to be `%i`', + (str: string, substring: string, count: number) => { + expect(countOccurrence(str, substring)).toEqual(count); + } +); diff --git a/packages/mermaid/src/diagrams/common/common.ts b/packages/mermaid/src/diagrams/common/common.ts index d34a2df68..e0ca2929d 100644 --- a/packages/mermaid/src/diagrams/common/common.ts +++ b/packages/mermaid/src/diagrams/common/common.ts @@ -1,5 +1,8 @@ import DOMPurify from 'dompurify'; -import { MermaidConfig } from '../../config.type'; +import type { MermaidConfig } from '../../config.type.js'; + +// Remove and ignore br:s +export const lineBreakRegex = //gi; /** * Gets the rows of lines in a string @@ -65,8 +68,6 @@ export const sanitizeTextOrArray = ( return a.flat().map((x: string) => sanitizeText(x, config)); }; -export const lineBreakRegex = //gi; - /** * Whether or not a text has any line breaks * @@ -138,6 +139,32 @@ const getUrl = (useAbsolute: boolean): string => { export const evaluate = (val?: string | boolean): boolean => val === false || ['false', 'null', '0'].includes(String(val).trim().toLowerCase()) ? false : true; +/** + * Wrapper around Math.max which removes non-numeric values + * Returns the larger of a set of supplied numeric expressions. + * @param values - Numeric expressions to be evaluated + * @returns The smaller value + */ +export const getMax = function (...values: number[]): number { + const newValues: number[] = values.filter((value) => { + return !isNaN(value); + }); + return Math.max(...newValues); +}; + +/** + * Wrapper around Math.min which removes non-numeric values + * Returns the smaller of a set of supplied numeric expressions. + * @param values - Numeric expressions to be evaluated + * @returns The smaller value + */ +export const getMin = function (...values: number[]): number { + const newValues: number[] = values.filter((value) => { + return !isNaN(value); + }); + return Math.min(...newValues); +}; + /** * Makes generics in typescript syntax * @@ -151,23 +178,80 @@ export const evaluate = (val?: string | boolean): boolean => * @param text - The text to convert * @returns The converted string */ -export const parseGenericTypes = function (text: string): string { - let cleanedText = text; +export const parseGenericTypes = function (input: string): string { + const inputSets = input.split(/(,)/); + const output = []; - if (text.split('~').length - 1 >= 2) { - let newCleanedText = cleanedText; + for (let i = 0; i < inputSets.length; i++) { + let thisSet = inputSets[i]; - // use a do...while loop instead of replaceAll to detect recursion - // e.g. Array~Array~T~~ - do { - cleanedText = newCleanedText; - newCleanedText = cleanedText.replace(/~([^\s,:;]+)~/, '<$1>'); - } while (newCleanedText != cleanedText); + // if the original input included a value such as "~K, V~"", these will be split into + // an array of ["~K",","," V~"]. + // This means that on each call of processSet, there will only be 1 ~ present + // To account for this, if we encounter a ",", we are checking the previous and next sets in the array + // to see if they contain matching ~'s + // in which case we are assuming that they should be rejoined and sent to be processed + if (thisSet === ',' && i > 0 && i + 1 < inputSets.length) { + const previousSet = inputSets[i - 1]; + const nextSet = inputSets[i + 1]; - return parseGenericTypes(newCleanedText); - } else { - return cleanedText; + if (shouldCombineSets(previousSet, nextSet)) { + thisSet = previousSet + ',' + nextSet; + i++; // Move the index forward to skip the next iteration since we're combining sets + output.pop(); + } + } + + output.push(processSet(thisSet)); } + + return output.join(''); +}; + +export const countOccurrence = (string: string, substring: string): number => { + return Math.max(0, string.split(substring).length - 1); +}; + +const shouldCombineSets = (previousSet: string, nextSet: string): boolean => { + const prevCount = countOccurrence(previousSet, '~'); + const nextCount = countOccurrence(nextSet, '~'); + + return prevCount === 1 && nextCount === 1; +}; + +const processSet = (input: string): string => { + const tildeCount = countOccurrence(input, '~'); + let hasStartingTilde = false; + + if (tildeCount <= 1) { + return input; + } + + // If there is an odd number of tildes, and the input starts with a tilde, we need to remove it and add it back in later + if (tildeCount % 2 !== 0 && input.startsWith('~')) { + input = input.substring(1); + hasStartingTilde = true; + } + + const chars = [...input]; + + let first = chars.indexOf('~'); + let last = chars.lastIndexOf('~'); + + while (first !== -1 && last !== -1 && first !== last) { + chars[first] = '<'; + chars[last] = '>'; + + first = chars.indexOf('~'); + last = chars.lastIndexOf('~'); + } + + // Add the starting tilde back in if we removed it + if (hasStartingTilde) { + chars.unshift('~'); + } + + return chars.join(''); }; export default { @@ -180,4 +264,6 @@ export default { removeScript, getUrl, evaluate, + getMax, + getMin, }; diff --git a/packages/mermaid/src/diagrams/common/commonDb.ts b/packages/mermaid/src/diagrams/common/commonDb.ts new file mode 100644 index 000000000..e4b9c3539 --- /dev/null +++ b/packages/mermaid/src/diagrams/common/commonDb.ts @@ -0,0 +1,32 @@ +import { sanitizeText as _sanitizeText } from './common.js'; +import { getConfig } from '../../config.js'; + +let accTitle = ''; +let diagramTitle = ''; +let accDescription = ''; + +const sanitizeText = (txt: string): string => _sanitizeText(txt, getConfig()); + +export const clear = (): void => { + accTitle = ''; + accDescription = ''; + diagramTitle = ''; +}; + +export const setAccTitle = (txt: string): void => { + accTitle = sanitizeText(txt).replace(/^\s+/g, ''); +}; + +export const getAccTitle = (): string => accTitle; + +export const setAccDescription = (txt: string): void => { + accDescription = sanitizeText(txt).replace(/\n\s+/g, '\n'); +}; + +export const getAccDescription = (): string => accDescription; + +export const setDiagramTitle = (txt: string): void => { + diagramTitle = sanitizeText(txt); +}; + +export const getDiagramTitle = (): string => diagramTitle; diff --git a/packages/mermaid/src/diagrams/common/commonTypes.ts b/packages/mermaid/src/diagrams/common/commonTypes.ts new file mode 100644 index 000000000..84c26db6e --- /dev/null +++ b/packages/mermaid/src/diagrams/common/commonTypes.ts @@ -0,0 +1,58 @@ +export interface RectData { + x: number; + y: number; + fill: string; + width: number; + height: number; + stroke: string; + class?: string; + color?: string; + rx?: number; + ry?: number; + attrs?: Record; + anchor?: string; +} + +export interface Bound { + startx: number; + stopx: number; + starty: number; + stopy: number; + fill: string; + stroke: string; +} + +export interface TextData { + x: number; + y: number; + anchor: string; + text: string; + textMargin: number; + class?: string; +} + +export interface TextObject { + x: number; + y: number; + width: number; + height: number; + fill?: string; + anchor?: string; + 'text-anchor': string; + style: string; + textMargin: number; + rx: number; + ry: number; + tspan: boolean; + valign?: string; +} + +export type D3RectElement = d3.Selection; + +export type D3UseElement = d3.Selection; + +export type D3ImageElement = d3.Selection; + +export type D3TextElement = d3.Selection; + +export type D3TSpanElement = d3.Selection; diff --git a/packages/mermaid/src/diagrams/common/svgDrawCommon.ts b/packages/mermaid/src/diagrams/common/svgDrawCommon.ts new file mode 100644 index 000000000..706d43ab9 --- /dev/null +++ b/packages/mermaid/src/diagrams/common/svgDrawCommon.ts @@ -0,0 +1,126 @@ +import { sanitizeUrl } from '@braintree/sanitize-url'; +import type { Group, SVG } from '../../diagram-api/types.js'; +import type { + Bound, + D3ImageElement, + D3RectElement, + D3TSpanElement, + D3TextElement, + D3UseElement, + RectData, + TextData, + TextObject, +} from './commonTypes.js'; +import { lineBreakRegex } from './common.js'; + +export const drawRect = (element: SVG | Group, rectData: RectData): D3RectElement => { + const rectElement: D3RectElement = element.append('rect'); + rectElement.attr('x', rectData.x); + rectElement.attr('y', rectData.y); + rectElement.attr('fill', rectData.fill); + rectElement.attr('stroke', rectData.stroke); + rectElement.attr('width', rectData.width); + rectElement.attr('height', rectData.height); + rectData.rx !== undefined && rectElement.attr('rx', rectData.rx); + rectData.ry !== undefined && rectElement.attr('ry', rectData.ry); + + if (rectData.attrs !== undefined) { + for (const attrKey in rectData.attrs) { + rectElement.attr(attrKey, rectData.attrs[attrKey]); + } + } + + rectData.class !== undefined && rectElement.attr('class', rectData.class); + + return rectElement; +}; + +/** + * Draws a background rectangle + * + * @param element - Diagram (reference for bounds) + * @param bounds - Shape of the rectangle + */ +export const drawBackgroundRect = (element: SVG | Group, bounds: Bound): void => { + const rectData: RectData = { + x: bounds.startx, + y: bounds.starty, + width: bounds.stopx - bounds.startx, + height: bounds.stopy - bounds.starty, + fill: bounds.fill, + stroke: bounds.stroke, + class: 'rect', + }; + const rectElement: D3RectElement = drawRect(element, rectData); + rectElement.lower(); +}; + +export const drawText = (element: SVG | Group, textData: TextData): D3TextElement => { + const nText: string = textData.text.replace(lineBreakRegex, ' '); + + const textElem: D3TextElement = element.append('text'); + textElem.attr('x', textData.x); + textElem.attr('y', textData.y); + textElem.attr('class', 'legend'); + + textElem.style('text-anchor', textData.anchor); + textData.class !== undefined && textElem.attr('class', textData.class); + + const tspan: D3TSpanElement = textElem.append('tspan'); + tspan.attr('x', textData.x + textData.textMargin * 2); + tspan.text(nText); + + return textElem; +}; + +export const drawImage = (elem: SVG | Group, x: number, y: number, link: string): void => { + const imageElement: D3ImageElement = elem.append('image'); + imageElement.attr('x', x); + imageElement.attr('y', y); + const sanitizedLink: string = sanitizeUrl(link); + imageElement.attr('xlink:href', sanitizedLink); +}; + +export const drawEmbeddedImage = ( + element: SVG | Group, + x: number, + y: number, + link: string +): void => { + const imageElement: D3UseElement = element.append('use'); + imageElement.attr('x', x); + imageElement.attr('y', y); + const sanitizedLink: string = sanitizeUrl(link); + imageElement.attr('xlink:href', `#${sanitizedLink}`); +}; + +export const getNoteRect = (): RectData => { + const noteRectData: RectData = { + x: 0, + y: 0, + width: 100, + height: 100, + fill: '#EDF2AE', + stroke: '#666', + anchor: 'start', + rx: 0, + ry: 0, + }; + return noteRectData; +}; + +export const getTextObj = (): TextObject => { + const testObject: TextObject = { + x: 0, + y: 0, + width: 100, + height: 100, + 'text-anchor': 'start', + style: '#666', + textMargin: 0, + rx: 0, + ry: 0, + tspan: true, + }; + return testObject; +}; diff --git a/packages/mermaid/src/diagrams/er/erDb.js b/packages/mermaid/src/diagrams/er/erDb.js index 026e08420..01bbb585c 100644 --- a/packages/mermaid/src/diagrams/er/erDb.js +++ b/packages/mermaid/src/diagrams/er/erDb.js @@ -1,6 +1,6 @@ -import { log } from '../../logger'; -import mermaidAPI from '../../mermaidAPI'; -import * as configApi from '../../config'; +import { log } from '../../logger.js'; +import mermaidAPI from '../../mermaidAPI.js'; +import * as configApi from '../../config.js'; import { setAccTitle, @@ -10,7 +10,7 @@ import { clear as commonClear, setDiagramTitle, getDiagramTitle, -} from '../../commonDb'; +} from '../common/commonDb.js'; let entities = {}; let relationships = []; @@ -20,6 +20,7 @@ const Cardinality = { ZERO_OR_MORE: 'ZERO_OR_MORE', ONE_OR_MORE: 'ONE_OR_MORE', ONLY_ONE: 'ONLY_ONE', + MD_PARENT: 'MD_PARENT', }; const Identification = { @@ -31,10 +32,13 @@ export const parseDirective = function (statement, context, type) { mermaidAPI.parseDirective(this, statement, context, type); }; -const addEntity = function (name) { +const addEntity = function (name, alias = undefined) { if (entities[name] === undefined) { - entities[name] = { attributes: [] }; + 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]; diff --git a/packages/mermaid/src/diagrams/er/erDetector.ts b/packages/mermaid/src/diagrams/er/erDetector.ts index 5a87a949e..7da6804e0 100644 --- a/packages/mermaid/src/diagrams/er/erDetector.ts +++ b/packages/mermaid/src/diagrams/er/erDetector.ts @@ -1,5 +1,24 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const erDetector: DiagramDetector = (txt) => { - return txt.match(/^\s*erDiagram/) !== null; +const id = 'er'; + +const detector: DiagramDetector = (txt) => { + return /^\s*erDiagram/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./erDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/er/erDiagram.ts b/packages/mermaid/src/diagrams/er/erDiagram.ts new file mode 100644 index 000000000..adfa525fc --- /dev/null +++ b/packages/mermaid/src/diagrams/er/erDiagram.ts @@ -0,0 +1,12 @@ +// @ts-ignore: TODO: Fix ts errors +import erParser from './parser/erDiagram.jison'; +import erDb from './erDb.js'; +import erRenderer from './erRenderer.js'; +import erStyles from './styles.js'; + +export const diagram = { + parser: erParser, + db: erDb, + renderer: erRenderer, + styles: erStyles, +}; diff --git a/packages/mermaid/src/diagrams/er/erMarkers.js b/packages/mermaid/src/diagrams/er/erMarkers.js index 948411772..48cafae65 100644 --- a/packages/mermaid/src/diagrams/er/erMarkers.js +++ b/packages/mermaid/src/diagrams/er/erMarkers.js @@ -7,6 +7,8 @@ const ERMarkers = { ONE_OR_MORE_END: 'ONE_OR_MORE_END', ZERO_OR_MORE_START: 'ZERO_OR_MORE_START', ZERO_OR_MORE_END: 'ZERO_OR_MORE_END', + MD_PARENT_END: 'MD_PARENT_END', + MD_PARENT_START: 'MD_PARENT_START', }; /** @@ -18,6 +20,30 @@ const ERMarkers = { const insertMarkers = function (elem, conf) { let marker; + elem + .append('defs') + .append('marker') + .attr('id', ERMarkers.MD_PARENT_START) + .attr('refX', 0) + .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', ERMarkers.MD_PARENT_END) + .attr('refX', 19) + .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'); + elem .append('defs') .append('marker') diff --git a/packages/mermaid/src/diagrams/er/erRenderer.js b/packages/mermaid/src/diagrams/er/erRenderer.js index 5dd5024bb..0c19d491b 100644 --- a/packages/mermaid/src/diagrams/er/erRenderer.js +++ b/packages/mermaid/src/diagrams/er/erRenderer.js @@ -1,12 +1,12 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import { line, curveBasis, select } from 'd3'; import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js'; -import { getConfig } from '../../config'; -import { log } from '../../logger'; -import utils from '../../utils'; -import erMarkers from './erMarkers'; -import { configureSvgSize } from '../../setupGraphViewbox'; -import { parseGenericTypes } from '../common/common'; +import { getConfig } from '../../config.js'; +import { log } from '../../logger.js'; +import utils from '../../utils.js'; +import erMarkers from './erMarkers.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import { parseGenericTypes } from '../common/common.js'; import { v5 as uuid5 } from 'uuid'; /** Regex used to remove chars from the entity name so the result can be used in an id */ @@ -326,7 +326,7 @@ const drawEntities = function (svgNode, entities, graph) { .style('text-anchor', 'middle') .style('font-family', getConfig().fontFamily) .style('font-size', conf.fontSize + 'px') - .text(entityName); + .text(entities[entityName].alias ?? entityName); const { width: entityWidth, height: entityHeight } = drawAttributes( groupNode, @@ -478,6 +478,9 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) { case diagObj.db.Cardinality.ONLY_ONE: svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_END + ')'); break; + case diagObj.db.Cardinality.MD_PARENT: + svgPath.attr('marker-end', 'url(' + url + '#' + erMarkers.ERMarkers.MD_PARENT_END + ')'); + break; } switch (rel.relSpec.cardB) { @@ -502,6 +505,9 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) { case diagObj.db.Cardinality.ONLY_ONE: svgPath.attr('marker-start', 'url(' + url + '#' + erMarkers.ERMarkers.ONLY_ONE_START + ')'); break; + case diagObj.db.Cardinality.MD_PARENT: + svgPath.attr('marker-start', 'url(' + url + '#' + erMarkers.ERMarkers.MD_PARENT_START + ')'); + break; } // Now label the relationship @@ -549,7 +555,6 @@ const drawRelationshipFromLayout = function (svg, rel, g, insert, diagObj) { export const draw = function (text, id, _version, diagObj) { conf = getConfig().er; log.info('Drawing ER diagram'); - // diag.db.clear(); const securityLevel = getConfig().securityLevel; // Handle root and Document for when rendering in sandbox mode let sandboxElement; @@ -562,13 +567,6 @@ export const draw = function (text, id, _version, diagObj) { : select('body'); // const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; - // Parse the text to populate erDb - // try { - // parser.parse(text); - // } catch (err) { - // log.debug('Parsing failed'); - // } - // Get a reference to the svg node that contains the text const svg = root.select(`[id='${id}']`); diff --git a/packages/mermaid/src/diagrams/er/erRenderer.spec.ts b/packages/mermaid/src/diagrams/er/erRenderer.spec.ts index ca0f62bd2..0cba06b56 100644 --- a/packages/mermaid/src/diagrams/er/erRenderer.spec.ts +++ b/packages/mermaid/src/diagrams/er/erRenderer.spec.ts @@ -1,4 +1,4 @@ -import { generateId } from './erRenderer'; +import { generateId } from './erRenderer.js'; describe('erRenderer', () => { describe('generateId', () => { diff --git a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison index 1e3972a3b..f39134607 100644 --- a/packages/mermaid/src/diagrams/er/parser/erDiagram.jison +++ b/packages/mermaid/src/diagrams/er/parser/erDiagram.jison @@ -19,8 +19,6 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili ":" { this.popState(); this.begin('arg_directive'); return ':'; } \}\%\% { this.popState(); this.popState(); return 'close_directive'; } ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; -\%%(?!\{)[^\n]* /* skip comments */ -[^\}]\%\%[^\n]* /* skip comments */ [\n]+ return 'NEWLINE'; \s+ /* skip whitespace */ [\s]+ return 'SPACE'; @@ -32,11 +30,13 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili \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' +[\*A-Za-z_][A-Za-z0-9\-_\[\]\(\)]* return 'ATTRIBUTE_WORD' \"[^"]*\" return 'COMMENT'; [\n]+ /* nothing */ "}" { this.popState(); return 'BLOCK_STOP'; } . return yytext[0]; +"[" return 'SQS'; +"]" return 'SQE'; "one or zero" return 'ZERO_OR_ONE'; "one or more" return 'ONE_OR_MORE'; @@ -59,13 +59,14 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili o\| return 'ZERO_OR_ONE'; o\{ return 'ZERO_OR_MORE'; \|\{ return 'ONE_OR_MORE'; +\s*u return 'MD_PARENT'; \.\. return 'NON_IDENTIFYING'; \-\- return 'IDENTIFYING'; "to" return 'IDENTIFYING'; "optionally to" return 'NON_IDENTIFYING'; \.\- return 'NON_IDENTIFYING'; \-\. return 'NON_IDENTIFYING'; -[A-Za-z][A-Za-z0-9\-_]* return 'ALPHANUM'; +[A-Za-z_][A-Za-z0-9\-_]* return 'ALPHANUM'; . return yytext[0]; <> return 'EOF'; @@ -81,7 +82,7 @@ start document : /* empty */ { $$ = [] } - | document line {$1.push($2);$$ = $1} + | document line {$1.push($2);$$ = $1} ; line @@ -103,17 +104,21 @@ statement yy.addEntity($1); yy.addEntity($3); yy.addRelationship($1, $5, $3, $2); - /*console.log($1 + $2 + $3 + ':' + $5);*/ } | entityName BLOCK_START attributes BLOCK_STOP { - /* console.log('detected block'); */ yy.addEntity($1); yy.addAttributes($1, $3); - /* console.log('handled block'); */ } | entityName BLOCK_START BLOCK_STOP { yy.addEntity($1); } | entityName { yy.addEntity($1); } + | entityName SQS entityName SQE BLOCK_START attributes BLOCK_STOP + { + yy.addEntity($1, $3); + yy.addAttributes($1, $6); + } + | entityName SQS entityName SQE BLOCK_START BLOCK_STOP { yy.addEntity($1, $3); } + | entityName SQS entityName SQE { yy.addEntity($1, $3); } | title title_value { $$=$2.trim();yy.setAccTitle($$); } | acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); } | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } @@ -172,6 +177,7 @@ cardinality | 'ZERO_OR_MORE' { $$ = yy.Cardinality.ZERO_OR_MORE; } | 'ONE_OR_MORE' { $$ = yy.Cardinality.ONE_OR_MORE; } | 'ONLY_ONE' { $$ = yy.Cardinality.ONLY_ONE; } + | 'MD_PARENT' { $$ = yy.Cardinality.MD_PARENT; } ; relType diff --git a/packages/mermaid/src/diagrams/er/parser/erDiagram.spec.js b/packages/mermaid/src/diagrams/er/parser/erDiagram.spec.js index ca497a2ac..825af737a 100644 --- a/packages/mermaid/src/diagrams/er/parser/erDiagram.spec.js +++ b/packages/mermaid/src/diagrams/er/parser/erDiagram.spec.js @@ -1,6 +1,6 @@ -import { setConfig } from '../../../config'; -import erDb from '../erDb'; -import erDiagram from './erDiagram'; // jison file +import { setConfig } from '../../../config.js'; +import erDb from '../erDb.js'; +import erDiagram from './erDiagram.jison'; // jison file setConfig({ securityLevel: 'strict', @@ -33,7 +33,7 @@ describe('when parsing ER diagram it...', function () { describe('has non A-Za-z0-9_- chars', function () { // these were entered using the Mac keyboard utility. const chars = - "~ ` ! @ # $ ^ & * ( ) - _ = + [ ] { } | / ; : ' . ? ¡ ⁄ ™ € £ ‹ ¢ › ∞ fi § ‡ • ° ª · º ‚ ≠ ± œ Œ ∑ „ ® † ˇ ¥ Á ¨ ˆ ˆ Ø π ∏ “ « » å Å ß Í ∂ Î ƒ Ï © ˙ Ó ∆ Ô ˚  ¬ Ò … Ú æ Æ Ω ¸ ≈ π ˛ ç Ç √ ◊ ∫ ı ˜ µ  ≤ ¯ ≥ ˘ ÷ ¿"; + "~ ` ! @ # $ ^ & * ( ) - = + [ ] { } | / ; : ' . ? ¡ ⁄ ™ € £ ‹ ¢ › ∞ fi § ‡ • ° ª · º ‚ ≠ ± œ Œ ∑ „ ® † ˇ ¥ Á ¨ ˆ ˆ Ø π ∏ “ « » å Å ß Í ∂ Î ƒ Ï © ˙ Ó ∆ Ô ˚  ¬ Ò … Ú æ Æ Ω ¸ ≈ π ˛ ç Ç √ ◊ ∫ ı ˜ µ  ≤ ¯ ≥ ˘ ÷ ¿"; const allowed = chars.split(' '); allowed.forEach((allowedChar) => { @@ -133,6 +133,50 @@ describe('when parsing ER diagram it...', function () { const entities = erDb.getEntities(); expect(entities.hasOwnProperty(hyphensUnderscore)).toBe(true); }); + + it('can have an alias', function () { + const entity = 'foo'; + const alias = 'bar'; + erDiagram.parser.parse(`erDiagram\n${entity}["${alias}"]\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(entity)).toBe(true); + expect(entities[entity].alias).toBe(alias); + }); + + it('can have an alias even if the relationship is defined before class', function () { + const firstEntity = 'foo'; + const secondEntity = 'bar'; + const alias = 'batman'; + erDiagram.parser.parse( + `erDiagram\n${firstEntity} ||--o| ${secondEntity} : rel\nclass ${firstEntity}["${alias}"]\n` + ); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(firstEntity)).toBe(true); + expect(entities.hasOwnProperty(secondEntity)).toBe(true); + expect(entities[firstEntity].alias).toBe(alias); + expect(entities[secondEntity].alias).toBeUndefined(); + }); + + it('can have an alias even if the relationship is defined after class', function () { + const firstEntity = 'foo'; + const secondEntity = 'bar'; + const alias = 'batman'; + erDiagram.parser.parse( + `erDiagram\nclass ${firstEntity}["${alias}"]\n${firstEntity} ||--o| ${secondEntity} : rel\n` + ); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(firstEntity)).toBe(true); + expect(entities.hasOwnProperty(secondEntity)).toBe(true); + expect(entities[firstEntity].alias).toBe(alias); + expect(entities[secondEntity].alias).toBeUndefined(); + }); + + it('can start with an underscore', function () { + const entity = '_foo'; + erDiagram.parser.parse(`erDiagram\n${entity}\n`); + const entities = erDb.getEntities(); + expect(entities.hasOwnProperty(entity)).toBe(true); + }); }); describe('attribute name', () => { @@ -154,6 +198,26 @@ describe('when parsing ER diagram it...', function () { expect(entities[entity].attributes[2].attributeName).toBe('author-ref[name](1)'); }); + it('should allow asterisk at the start of attribute name', function () { + const entity = 'BOOK'; + const attribute = 'string *title'; + + erDiagram.parser.parse(`erDiagram\n${entity}{\n${attribute}}`); + const entities = erDb.getEntities(); + expect(Object.keys(entities).length).toBe(1); + expect(entities[entity].attributes.length).toBe(1); + }); + + it('should allow asterisks at the start of attribute declared with type and name', () => { + const entity = 'BOOK'; + const attribute = 'id *the_Primary_Key'; + + erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute}}`); + const entities = erDb.getEntities(); + expect(Object.keys(entities).length).toBe(1); + expect(entities[entity].attributes.length).toBe(1); + }); + it('should not allow leading numbers, dashes or brackets', function () { const entity = 'BOOK'; const nonLeadingChars = '0-[]()'; @@ -718,5 +782,14 @@ describe('when parsing ER diagram it...', function () { const rels = erDb.getRelationships(); expect(rels[0].roleA).toBe('places'); }); + + it('should represent parent-child relationship correctly', function () { + erDiagram.parser.parse('erDiagram\nPROJECT u--o{ TEAM_MEMBER : "parent"'); + const rels = erDb.getRelationships(); + expect(Object.keys(erDb.getEntities()).length).toBe(2); + expect(rels.length).toBe(1); + expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.MD_PARENT); + expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE); + }); }); }); diff --git a/packages/mermaid/src/diagrams/er/styles.js b/packages/mermaid/src/diagrams/er/styles.js index 42dbcebde..08ea2e851 100644 --- a/packages/mermaid/src/diagrams/er/styles.js +++ b/packages/mermaid/src/diagrams/er/styles.js @@ -33,6 +33,17 @@ const getStyles = (options) => font-size: 18px; fill: ${options.textColor}; } + #MD_PARENT_START { + fill: #f5f5f5 !important; + stroke: ${options.lineColor} !important; + stroke-width: 1; + } + #MD_PARENT_END { + fill: #f5f5f5 !important; + stroke: ${options.lineColor} !important; + stroke-width: 1; + } + `; export default getStyles; diff --git a/packages/mermaid/src/diagrams/error/errorDiagram.ts b/packages/mermaid/src/diagrams/error/errorDiagram.ts new file mode 100644 index 000000000..284dfd744 --- /dev/null +++ b/packages/mermaid/src/diagrams/error/errorDiagram.ts @@ -0,0 +1,15 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +import { renderer } from './errorRenderer.js'; + +const diagram: DiagramDefinition = { + db: {}, + renderer, + parser: { + parser: { yy: {} }, + parse: (): void => { + return; + }, + }, +}; + +export default diagram; diff --git a/packages/mermaid/src/diagrams/error/errorRenderer.ts b/packages/mermaid/src/diagrams/error/errorRenderer.ts index 60877cb8d..a8e738e5f 100644 --- a/packages/mermaid/src/diagrams/error/errorRenderer.ts +++ b/packages/mermaid/src/diagrams/error/errorRenderer.ts @@ -1,102 +1,81 @@ -/** Created by knut on 14-12-11. */ -// @ts-ignore TODO: Investigate D3 issue -import { select } from 'd3'; -import { log } from '../../logger'; -import { getErrorMessage } from '../../utils'; - -let conf = {}; - -/** - * Merges the value of `conf` with the passed `cnf` - * - * @param cnf - Config to merge - */ -export const setConf = function (cnf: any) { - conf = { ...conf, ...cnf }; -}; +import { log } from '../../logger.js'; +import type { Group, SVG } from '../../diagram-api/types.js'; +import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; /** * Draws a an info picture in the tag with id: id based on the graph definition in text. * * @param _text - Mermaid graph definition. * @param id - The text for the error - * @param mermaidVersion - The version + * @param version - The version */ -export const draw = (_text: string, id: string, mermaidVersion: string) => { - try { - log.debug('Renering svg for syntax error\n'); +export const draw = (_text: string, id: string, version: string) => { + log.debug('renering svg for syntax error\n'); - const svg = select('#' + id); + const svg: SVG = selectSvgElement(id); + svg.attr('viewBox', '0 0 2412 512'); + configureSvgSize(svg, 100, 512, true); - const g = svg.append('g'); + const g: Group = svg.append('g'); + g.append('path') + .attr('class', 'error-icon') + .attr( + 'd', + 'm411.313,123.313c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32-9.375,9.375-20.688-20.688c-12.484-12.5-32.766-12.5-45.25,0l-16,16c-1.261,1.261-2.304,2.648-3.31,4.051-21.739-8.561-45.324-13.426-70.065-13.426-105.867,0-192,86.133-192,192s86.133,192 192,192 192-86.133 192-192c0-24.741-4.864-48.327-13.426-70.065 1.402-1.007 2.79-2.049 4.051-3.31l16-16c12.5-12.492 12.5-32.758 0-45.25l-20.688-20.688 9.375-9.375 32.001-31.999zm-219.313,100.687c-52.938,0-96,43.063-96,96 0,8.836-7.164,16-16,16s-16-7.164-16-16c0-70.578 57.422-128 128-128 8.836,0 16,7.164 16,16s-7.164,16-16,16z' + ); - g.append('path') - .attr('class', 'error-icon') - .attr( - 'd', - 'm411.313,123.313c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32-9.375,9.375-20.688-20.688c-12.484-12.5-32.766-12.5-45.25,0l-16,16c-1.261,1.261-2.304,2.648-3.31,4.051-21.739-8.561-45.324-13.426-70.065-13.426-105.867,0-192,86.133-192,192s86.133,192 192,192 192-86.133 192-192c0-24.741-4.864-48.327-13.426-70.065 1.402-1.007 2.79-2.049 4.051-3.31l16-16c12.5-12.492 12.5-32.758 0-45.25l-20.688-20.688 9.375-9.375 32.001-31.999zm-219.313,100.687c-52.938,0-96,43.063-96,96 0,8.836-7.164,16-16,16s-16-7.164-16-16c0-70.578 57.422-128 128-128 8.836,0 16,7.164 16,16s-7.164,16-16,16z' - ); + g.append('path') + .attr('class', 'error-icon') + .attr( + 'd', + 'm459.02,148.98c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l16,16c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16.001-16z' + ); - g.append('path') - .attr('class', 'error-icon') - .attr( - 'd', - 'm459.02,148.98c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l16,16c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16.001-16z' - ); + g.append('path') + .attr('class', 'error-icon') + .attr( + 'd', + 'm340.395,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16-16c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l15.999,16z' + ); - g.append('path') - .attr('class', 'error-icon') - .attr( - 'd', - 'm340.395,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16-16c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l15.999,16z' - ); + g.append('path') + .attr('class', 'error-icon') + .attr( + 'd', + 'm400,64c8.844,0 16-7.164 16-16v-32c0-8.836-7.156-16-16-16-8.844,0-16,7.164-16,16v32c0,8.836 7.156,16 16,16z' + ); - g.append('path') - .attr('class', 'error-icon') - .attr( - 'd', - 'm400,64c8.844,0 16-7.164 16-16v-32c0-8.836-7.156-16-16-16-8.844,0-16,7.164-16,16v32c0,8.836 7.156,16 16,16z' - ); + g.append('path') + .attr('class', 'error-icon') + .attr( + 'd', + 'm496,96.586h-32c-8.844,0-16,7.164-16,16 0,8.836 7.156,16 16,16h32c8.844,0 16-7.164 16-16 0-8.836-7.156-16-16-16z' + ); - g.append('path') - .attr('class', 'error-icon') - .attr( - 'd', - 'm496,96.586h-32c-8.844,0-16,7.164-16,16 0,8.836 7.156,16 16,16h32c8.844,0 16-7.164 16-16 0-8.836-7.156-16-16-16z' - ); + g.append('path') + .attr('class', 'error-icon') + .attr( + 'd', + 'm436.98,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688l32-32c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32c-6.251,6.25-6.251,16.375-0.001,22.625z' + ); - g.append('path') - .attr('class', 'error-icon') - .attr( - 'd', - 'm436.98,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688l32-32c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32c-6.251,6.25-6.251,16.375-0.001,22.625z' - ); - - g.append('text') // text label for the x axis - .attr('class', 'error-text') - .attr('x', 1440) - .attr('y', 250) - .attr('font-size', '150px') - .style('text-anchor', 'middle') - .text('Syntax error in graph'); - g.append('text') // text label for the x axis - .attr('class', 'error-text') - .attr('x', 1250) - .attr('y', 400) - .attr('font-size', '100px') - .style('text-anchor', 'middle') - .text('mermaid version ' + mermaidVersion); - - svg.attr('height', 100); - svg.attr('width', 500); - svg.attr('viewBox', '768 0 912 512'); - } catch (e) { - log.error('Error while rendering info diagram'); - log.error(getErrorMessage(e)); - } + g.append('text') // text label for the x axis + .attr('class', 'error-text') + .attr('x', 1440) + .attr('y', 250) + .attr('font-size', '150px') + .style('text-anchor', 'middle') + .text('Syntax error in text'); + g.append('text') // text label for the x axis + .attr('class', 'error-text') + .attr('x', 1250) + .attr('y', 400) + .attr('font-size', '100px') + .style('text-anchor', 'middle') + .text(`mermaid version ${version}`); }; -export default { - setConf, - draw, -}; +export const renderer = { draw }; + +export default renderer; diff --git a/packages/mermaid/src/diagrams/error/styles.js b/packages/mermaid/src/diagrams/error/styles.js deleted file mode 100644 index 0b0729813..000000000 --- a/packages/mermaid/src/diagrams/error/styles.js +++ /dev/null @@ -1,3 +0,0 @@ -const getStyles = () => ``; - -export default getStyles; diff --git a/packages/mermaid/src/diagrams/flowchart/elk/detector.spec.ts b/packages/mermaid/src/diagrams/flowchart/elk/detector.spec.ts index 17cd5c0ea..6e949c57b 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/detector.spec.ts +++ b/packages/mermaid/src/diagrams/flowchart/elk/detector.spec.ts @@ -1,4 +1,4 @@ -import plugin from './detector'; +import plugin from './detector.js'; import { describe, it } from 'vitest'; const { detector } = plugin; diff --git a/packages/mermaid/src/diagrams/flowchart/elk/detector.ts b/packages/mermaid/src/diagrams/flowchart/elk/detector.ts index c6fa77957..6cfcf2619 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/detector.ts +++ b/packages/mermaid/src/diagrams/flowchart/elk/detector.ts @@ -1,21 +1,24 @@ -import type { MermaidConfig } from '../../../config.type'; -import type { ExternalDiagramDefinition, DiagramDetector } from '../../../diagram-api/types'; +import type { + ExternalDiagramDefinition, + DiagramDetector, + DiagramLoader, +} from '../../../diagram-api/types.js'; const id = 'flowchart-elk'; -const detector: DiagramDetector = (txt: string, config?: MermaidConfig): boolean => { +const detector: DiagramDetector = (txt, config): boolean => { if ( // If diagram explicitly states flowchart-elk - txt.match(/^\s*flowchart-elk/) || + /^\s*flowchart-elk/.test(txt) || // If a flowchart/graph diagram has their default renderer set to elk - (txt.match(/^\s*flowchart|graph/) && config?.flowchart?.defaultRenderer === 'elk') + (/^\s*flowchart|graph/.test(txt) && config?.flowchart?.defaultRenderer === 'elk') ) { return true; } return false; }; -const loader = async () => { +const loader: DiagramLoader = async () => { const { diagram } = await import('./flowchart-elk-definition.js'); return { id, diagram }; }; diff --git a/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js b/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js index b8458efeb..c7bfdf524 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js +++ b/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js @@ -2,17 +2,18 @@ import { select, line, curveLinear } from 'd3'; import { insertNode } from '../../../dagre-wrapper/nodes.js'; import insertMarkers from '../../../dagre-wrapper/markers.js'; import { insertEdgeLabel } from '../../../dagre-wrapper/edges.js'; -import { findCommonAncestor } from './render-utils'; +import { findCommonAncestor } from './render-utils.js'; +import { labelHelper } from '../../../dagre-wrapper/shapes/util.js'; import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; -import { getConfig } from '../../../config'; -import { log } from '../../../logger'; -import { setupGraphViewbox } from '../../../setupGraphViewbox'; -import common, { evaluate } from '../../common/common'; -import { interpolateToCurve, getStylesFromArray } from '../../../utils'; +import { getConfig } from '../../../config.js'; +import { log } from '../../../logger.js'; +import { setupGraphViewbox } from '../../../setupGraphViewbox.js'; +import common, { evaluate } from '../../common/common.js'; +import { interpolateToCurve, getStylesFromArray } from '../../../utils.js'; +import ELK from 'elkjs/lib/elk.bundled.js'; +const elk = new ELK(); -let elk; - -const portPos = {}; +let portPos = {}; const conf = {}; export const setConf = function (cnf) { @@ -34,238 +35,231 @@ let nodeDb = {}; // * @param doc // * @param diagObj // */ -export const addVertices = function (vert, svgId, root, doc, diagObj, parentLookupDb, graph) { +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 - keys.forEach(function (id) { - const vertex = vert[id]; + 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(' '); - } - - 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 }; - if (evaluate(getConfig().flowchart.htmlLabels)) { - // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const node = { - label: vertexText.replace( - /fa[blrs]?:fa-[\w-]+/g, - (s) => `` - ), - }; - vertexNode = addHtmlLabel(svg, node).node(); - const bbox = vertexNode.getBBox(); - labelData.width = bbox.width; - labelData.height = bbox.height; - labelData.labelNode = vertexNode; - vertexNode.parentNode.removeChild(vertexNode); - } 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); + /** + * Variable for storing the classes for the vertex + * + * @type {string} + */ + let classStr = 'default'; + if (vertex.classes.length > 0) { + classStr = vertex.classes.join(' '); } - vertexNode = svgLabel; - const bbox = vertexNode.getBBox(); - labelData.width = bbox.width; - labelData.height = bbox.height; - labelData.labelNode = vertexNode; - } + classStr = classStr + ' flowchart-label'; + const styles = getStylesFromArray(vertex.styles); - 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', - }, - }, - ]; + // 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; - let radious = 0; - let _shape = ''; - let layoutOptions = {}; - // Set the shape based parameters - switch (vertex.type) { - case 'round': - radious = 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, - rx: radious, - ry: radious, - 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; - if (node.type !== 'group') { - nodeEl = insertNode(nodes, node, vertex.dir); - boundingBox = nodeEl.node().getBBox(); - } + // We create a SVG label, either by delegating to addHtmlLabel or manually + let vertexNode; + const labelData = { width: 0, height: 0 }; - 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], - // }); - }); + 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 radious = 0; + let _shape = ''; + let layoutOptions = {}; + // Set the shape based parameters + switch (vertex.type) { + case 'round': + radious = 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: radious, + ry: radious, + 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; }; @@ -371,6 +365,10 @@ 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]; @@ -387,7 +385,7 @@ const getEdgeStartEndPoint = (edge, dir) => { } // Add the edge to the graph - return { source, target }; + return { source, target, sourceId, targetId }; }; /** @@ -416,7 +414,7 @@ export const addEdges = function (edges, diagObj, graph, svg) { edges.forEach(function (edge) { // Identify Link - var linkIdBase = 'L-' + edge.start + '-' + edge.end; + 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; @@ -427,8 +425,8 @@ export const addEdges = function (edges, diagObj, graph, svg) { } let linkId = linkIdBase + '-' + linkIdCnt[linkIdBase]; log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]); - var linkNameStart = 'LS-' + edge.start; - var linkNameEnd = 'LE-' + edge.end; + const linkNameStart = 'LS-' + edge.start; + const linkNameEnd = 'LE-' + edge.end; const edgeData = { style: '', labelStyle: '' }; edgeData.minlen = edge.length || 1; @@ -516,7 +514,7 @@ export const addEdges = function (edges, diagObj, graph, svg) { edgeData.labelpos = 'c'; } - edgeData.labelType = 'text'; + edgeData.labelType = edge.labelType; edgeData.label = edge.text.replace(common.lineBreakRegex, '\n'); if (edge.style === undefined) { @@ -530,14 +528,17 @@ export const addEdges = function (edges, diagObj, graph, svg) { const labelEl = insertEdgeLabel(labelsEl, edgeData); - // calculate start and end points of the edge - const { source, target } = getEdgeStartEndPoint(edge, dir); + // 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: [ { @@ -654,14 +655,7 @@ const addMarkersToEdge = function (svgPath, edgeData, diagramType, arrowMarkerAb */ export const getClasses = function (text, diagObj) { log.info('Extracting classes'); - diagObj.db.clear('ver-2'); - try { - // Parse the graph definition - diagObj.parse(text); - return diagObj.db.getClasses(); - } catch (e) { - return {}; - } + return diagObj.db.getClasses(); }; const addSubGraphs = function (db) { @@ -698,7 +692,7 @@ const calcOffset = function (src, dest, parentLookupDb) { }; const insertEdge = function (edgesEl, edge, edgeData, diagObj, parentLookupDb) { - const offset = calcOffset(edge.sources[0], edge.targets[0], parentLookupDb); + const offset = calcOffset(edge.sourceId, edge.targetId, parentLookupDb); const src = edge.sections[0].startPoint; const dest = edge.sections[0].endPoint; @@ -716,7 +710,7 @@ const insertEdge = function (edgesEl, edge, edgeData, diagObj, parentLookupDb) { const edgePath = edgesEl .insert('path') .attr('d', curve(points)) - .attr('class', 'path') + .attr('class', 'path ' + edgeData.classes) .attr('fill', 'none'); const edgeG = edgesEl.insert('g').attr('class', 'edgeLabel'); const edgeWithLabel = select(edgeG.node().appendChild(edge.labelEl)); @@ -765,17 +759,8 @@ const insertChildren = (nodeArray, parentLookupDb) => { */ export const draw = async function (text, id, _version, diagObj) { - if (!elk) { - const ELK = (await import('elkjs/lib/elk.bundled.js')).default; - elk = new ELK(); - } - // Add temporary render element - diagObj.db.clear(); nodeDb = {}; - diagObj.db.setGen('gen-2'); - // Parse the graph definition - diagObj.parser.parse(text); - + portPos = {}; const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy'); let graph = { id: 'root', @@ -842,9 +827,17 @@ export const draw = async function (text, id, _version, diagObj) { log.info('Subgraphs - ', subGraphs); for (let i = subGraphs.length - 1; i >= 0; i--) { subG = subGraphs[i]; - diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir); + 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'); @@ -857,7 +850,7 @@ export const draw = async function (text, id, _version, diagObj) { // 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 = addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph); + 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'); @@ -884,6 +877,8 @@ export const draw = async function (text, id, _version, diagObj) { }, width: node.labelData.width, height: node.labelData.height, + // width: 100, + // height: 100, }, ]; delete node.x; @@ -892,6 +887,7 @@ export const draw = async function (text, id, _version, diagObj) { delete node.height; } }); + insertChildren(graph.children, parentLookupDb); log.info('after layout', JSON.stringify(graph, null, 2)); const g = await elk.layout(graph); @@ -927,9 +923,12 @@ const drawNodes = (relX, relY, nodeArray, svg, subgraphsEl, diagObj, depth) => { .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}, ${node.labels[0].y + relY + node.y})` + `translate(${node.labels[0].x + relX + node.x + labelCentering}, ${ + node.labels[0].y + relY + node.y + 3 + })` ); label.node().appendChild(node.labelData.labelNode); diff --git a/packages/mermaid/src/diagrams/flowchart/elk/flowchart-elk-definition.ts b/packages/mermaid/src/diagrams/flowchart/elk/flowchart-elk-definition.ts index c45873238..9855c7389 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/flowchart-elk-definition.ts +++ b/packages/mermaid/src/diagrams/flowchart/elk/flowchart-elk-definition.ts @@ -1,9 +1,9 @@ // @ts-ignore: JISON typing missing -import parser from '../parser/flow'; +import parser from '../parser/flow.jison'; -import * as db from '../flowDb'; -import renderer from './flowRenderer-elk'; -import styles from './styles'; +import * as db from '../flowDb.js'; +import renderer from './flowRenderer-elk.js'; +import styles from './styles.js'; export const diagram = { db, diff --git a/packages/mermaid/src/diagrams/flowchart/elk/render-utils.spec.ts b/packages/mermaid/src/diagrams/flowchart/elk/render-utils.spec.ts index d845fa697..046ed43c1 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/render-utils.spec.ts +++ b/packages/mermaid/src/diagrams/flowchart/elk/render-utils.spec.ts @@ -1,4 +1,5 @@ -import { findCommonAncestor, TreeData } from './render-utils'; +import type { TreeData } from './render-utils.js'; +import { findCommonAncestor } from './render-utils.js'; describe('when rendering a flowchart using elk ', () => { let lookupDb: TreeData; beforeEach(() => { diff --git a/packages/mermaid/src/diagrams/flowchart/elk/styles.ts b/packages/mermaid/src/diagrams/flowchart/elk/styles.ts index e8e7065a0..60659df45 100644 --- a/packages/mermaid/src/diagrams/flowchart/elk/styles.ts +++ b/packages/mermaid/src/diagrams/flowchart/elk/styles.ts @@ -81,7 +81,7 @@ const getStyles = (options: FlowChartStyleOptions) => .edgeLabel { background-color: ${options.edgeLabelBackground}; rect { - opacity: 0.5; + opacity: 0.85; background-color: ${options.edgeLabelBackground}; fill: ${options.edgeLabelBackground}; } @@ -132,6 +132,11 @@ const getStyles = (options: FlowChartStyleOptions) => // fill:#ccc; // // stroke:black; // } + + .flowchart-label text { + text-anchor: middle; + } + ${genSections(options)} `; diff --git a/packages/mermaid/src/diagrams/flowchart/flowChartShapes.spec.js b/packages/mermaid/src/diagrams/flowchart/flowChartShapes.spec.js index e7e535056..96e6f6fd7 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowChartShapes.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/flowChartShapes.spec.js @@ -1,4 +1,4 @@ -import { addToRender } from './flowChartShapes'; +import { addToRender } from './flowChartShapes.js'; describe('flowchart shapes', function () { // rect-based shapes diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.js b/packages/mermaid/src/diagrams/flowchart/flowDb.js index 2e6b840b5..2bb50abee 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.js +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.js @@ -1,9 +1,9 @@ import { select } from 'd3'; -import utils from '../../utils'; -import * as configApi from '../../config'; -import common from '../common/common'; -import mermaidAPI from '../../mermaidAPI'; -import { log } from '../../logger'; +import utils from '../../utils.js'; +import * as configApi from '../../config.js'; +import common from '../common/common.js'; +import mermaidAPI from '../../mermaidAPI.js'; +import { log } from '../../logger.js'; import { setAccTitle, getAccTitle, @@ -12,7 +12,7 @@ import { clear as commonClear, setDiagramTitle, getDiagramTitle, -} from '../../commonDb'; +} from '../common/commonDb.js'; const MERMAID_DOM_ID_PREFIX = 'flowchart-'; let vertexCounter = 0; @@ -59,13 +59,14 @@ export const lookUpDomId = function (id) { * * @param _id * @param text + * @param textObj * @param type * @param style * @param classes * @param dir * @param props */ -export const addVertex = function (_id, text, type, style, classes, dir, props = {}) { +export const addVertex = function (_id, textObj, type, style, classes, dir, props = {}) { let txt; let id = _id; if (id === undefined) { @@ -80,16 +81,17 @@ export const addVertex = function (_id, text, type, style, classes, dir, props = if (vertices[id] === undefined) { vertices[id] = { id: id, + labelType: 'text', domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter, styles: [], classes: [], }; } vertexCounter++; - if (text !== undefined) { + if (textObj !== undefined) { config = configApi.getConfig(); - txt = sanitizeText(text.trim()); - + txt = sanitizeText(textObj.text.trim()); + vertices[id].labelType = textObj.type; // strip quotes if string starts and ends with a quote if (txt[0] === '"' && txt[txt.length - 1] === '"') { txt = txt.substring(1, txt.length - 1); @@ -131,24 +133,27 @@ export const addVertex = function (_id, text, type, style, classes, dir, props = * @param _end * @param type * @param linkText + * @param linkTextObj */ -export const addSingleLink = function (_start, _end, type, linkText) { +export const addSingleLink = function (_start, _end, type) { let start = _start; let end = _end; // if (start[0].match(/\d/)) start = MERMAID_DOM_ID_PREFIX + start; // if (end[0].match(/\d/)) end = MERMAID_DOM_ID_PREFIX + end; // log.info('Got edge...', start, end); - const edge = { start: start, end: end, type: undefined, text: '' }; - linkText = type.text; + const edge = { start: start, end: end, type: undefined, text: '', labelType: 'text' }; + log.info('abc78 Got edge...', edge); + const linkTextObj = type.text; - if (linkText !== undefined) { - edge.text = sanitizeText(linkText.trim()); + if (linkTextObj !== undefined) { + edge.text = sanitizeText(linkTextObj.text.trim()); // strip quotes if string starts and ends with a quote if (edge.text[0] === '"' && edge.text[edge.text.length - 1] === '"') { edge.text = edge.text.substring(1, edge.text.length - 1); } + edge.labelType = linkTextObj.type; } if (type !== undefined) { @@ -158,11 +163,12 @@ export const addSingleLink = function (_start, _end, type, linkText) { } edges.push(edge); }; -export const addLink = function (_start, _end, type, linktext) { +export const addLink = function (_start, _end, type) { + log.info('addLink (abc78)', _start, _end, type); let i, j; for (i = 0; i < _start.length; i++) { for (j = 0; j < _end.length; j++) { - addSingleLink(_start[i], _end[j], type, linktext); + addSingleLink(_start[i], _end[j], type); } } }; @@ -202,21 +208,22 @@ export const updateLink = function (positions, style) { }); }; -export const addClass = function (id, style) { - if (classes[id] === undefined) { - classes[id] = { id: id, styles: [], textStyles: [] }; - } +export const addClass = function (ids, style) { + ids.split(',').forEach(function (id) { + if (classes[id] === undefined) { + classes[id] = { id, styles: [], textStyles: [] }; + } - if (style !== undefined && style !== null) { - style.forEach(function (s) { - if (s.match('color')) { - const newStyle1 = s.replace('fill', 'bgFill'); - const newStyle2 = newStyle1.replace('color', 'fill'); - classes[id].textStyles.push(newStyle2); - } - classes[id].styles.push(s); - }); - } + if (style !== undefined && style !== null) { + style.forEach(function (s) { + if (s.match('color')) { + const newStyle = s.replace('fill', 'bgFill').replace('color', 'fill'); + classes[id].textStyles.push(newStyle); + } + classes[id].styles.push(s); + }); + } + }); }; /** @@ -335,7 +342,10 @@ export const setLink = function (ids, linkStr, target) { setClass(ids, 'clickable'); }; export const getTooltip = function (id) { - return tooltips[id]; + if (tooltips.hasOwnProperty(id)) { + return tooltips[id]; + } + return undefined; }; /** @@ -436,7 +446,7 @@ export const clear = function (ver = 'gen-1') { subGraphs = []; subGraphLookup = {}; subCount = 0; - tooltips = []; + tooltips = {}; firstGraphFlag = true; version = ver; commonClear(); @@ -457,10 +467,9 @@ export const defaultStyle = function () { * @param _title */ export const addSubGraph = function (_id, list, _title) { - // console.log('addSubGraph', _id, list, _title); - let id = _id.trim(); - let title = _title; - if (_id === _title && _title.match(/\s/)) { + let id = _id.text.trim(); + let title = _title.text; + if (_id === _title && _title.text.match(/\s/)) { id = undefined; } /** @param a */ @@ -502,7 +511,14 @@ export const addSubGraph = function (_id, list, _title) { title = title || ''; title = sanitizeText(title); subCount = subCount + 1; - const subGraph = { id: id, nodes: nodeList, title: title.trim(), classes: [], dir }; + const subGraph = { + id: id, + nodes: nodeList, + title: title.trim(), + classes: [], + dir, + labelType: _title.type, + }; log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir); @@ -677,6 +693,10 @@ const destructEndLink = (_str) => { stroke = 'thick'; } + if (line[0] === '~') { + stroke = 'invisible'; + } + let dots = countChar('.', line); if (dots) { diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.spec.js b/packages/mermaid/src/diagrams/flowchart/flowDb.spec.js index c1aa640fc..6f04ca70a 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.spec.js @@ -1,4 +1,4 @@ -import flowDb from './flowDb'; +import flowDb from './flowDb.js'; describe('flow db subgraphs', () => { let subgraphs; @@ -41,3 +41,26 @@ describe('flow db subgraphs', () => { }); }); }); + +describe('flow db addClass', () => { + beforeEach(() => { + flowDb.clear(); + }); + it('should detect many classes', () => { + flowDb.addClass('a,b', ['stroke-width: 8px']); + const classes = flowDb.getClasses(); + + expect(classes.hasOwnProperty('a')).toBe(true); + expect(classes.hasOwnProperty('b')).toBe(true); + expect(classes['a']['styles']).toEqual(['stroke-width: 8px']); + expect(classes['b']['styles']).toEqual(['stroke-width: 8px']); + }); + + it('should detect single class', () => { + flowDb.addClass('a', ['stroke-width: 8px']); + const classes = flowDb.getClasses(); + + expect(classes.hasOwnProperty('a')).toBe(true); + expect(classes['a']['styles']).toEqual(['stroke-width: 8px']); + }); +}); diff --git a/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts b/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts index 3916325de..dda5a67f0 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts @@ -1,16 +1,32 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, DiagramLoader } from '../../diagram-api/types.js'; +import type { ExternalDiagramDefinition } from '../../diagram-api/types.js'; -export const flowDetectorV2: DiagramDetector = (txt, config) => { - if (config?.flowchart?.defaultRenderer === 'dagre-d3') { - return false; - } - if (config?.flowchart?.defaultRenderer === 'elk') { +const id = 'flowchart-v2'; + +const detector: DiagramDetector = (txt, config) => { + if ( + config?.flowchart?.defaultRenderer === 'dagre-d3' || + config?.flowchart?.defaultRenderer === 'elk' + ) { return false; } // If we have configured to use dagre-wrapper then we should return true in this function for graph code thus making it use the new flowchart diagram - if (txt.match(/^\s*graph/) !== null) { + if (/^\s*graph/.test(txt) && config?.flowchart?.defaultRenderer === 'dagre-wrapper') { return true; } - return txt.match(/^\s*flowchart/) !== null; + return /^\s*flowchart/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./flowDiagram-v2.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDetector.ts b/packages/mermaid/src/diagrams/flowchart/flowDetector.ts index d46b7d8f5..8859ca883 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDetector.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDetector.ts @@ -1,13 +1,32 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const flowDetector: DiagramDetector = (txt, config) => { +const id = 'flowchart'; + +const detector: DiagramDetector = (txt, config) => { // If we have conferred to only use new flow charts this function should always return false // as in not signalling true for a legacy flowchart - if (config?.flowchart?.defaultRenderer === 'dagre-wrapper') { + if ( + config?.flowchart?.defaultRenderer === 'dagre-wrapper' || + config?.flowchart?.defaultRenderer === 'elk' + ) { return false; } - if (config?.flowchart?.defaultRenderer === 'elk') { - return false; - } - return txt.match(/^\s*graph/) !== null; + return /^\s*graph/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./flowDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts b/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts new file mode 100644 index 000000000..c3de4b685 --- /dev/null +++ b/packages/mermaid/src/diagrams/flowchart/flowDiagram-v2.ts @@ -0,0 +1,25 @@ +// @ts-ignore: JISON doesn't support types +import flowParser from './parser/flow.jison'; +import flowDb from './flowDb.js'; +import flowRendererV2 from './flowRenderer-v2.js'; +import flowStyles from './styles.js'; +import type { MermaidConfig } from '../../config.type.js'; +import { setConfig } from '../../config.js'; + +export const diagram = { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf: MermaidConfig) => { + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + // flowchart-v2 uses dagre-wrapper, which doesn't have access to flowchart cnf + setConfig({ flowchart: { arrowMarkerAbsolute: cnf.arrowMarkerAbsolute } }); + flowRendererV2.setConf(cnf.flowchart); + flowDb.clear(); + flowDb.setGen('gen-2'); + }, +}; diff --git a/packages/mermaid/src/diagrams/flowchart/flowDiagram.ts b/packages/mermaid/src/diagrams/flowchart/flowDiagram.ts new file mode 100644 index 000000000..ca4f8fba8 --- /dev/null +++ b/packages/mermaid/src/diagrams/flowchart/flowDiagram.ts @@ -0,0 +1,24 @@ +// @ts-ignore: JISON doesn't support types +import flowParser from './parser/flow.jison'; +import flowDb from './flowDb.js'; +import flowRenderer from './flowRenderer.js'; +import flowRendererV2 from './flowRenderer-v2.js'; +import flowStyles from './styles.js'; +import type { MermaidConfig } from '../../config.type.js'; + +export const diagram = { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf: MermaidConfig) => { + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + // TODO, broken as of 2022-09-14 (13809b50251845475e6dca65cc395761be38fbd2) + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowRenderer.setConf(cnf.flowchart); + flowDb.clear(); + flowDb.setGen('gen-1'); + }, +}; diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js index 03bda7611..4a3b7a8ce 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js @@ -1,16 +1,13 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import { select, curveLinear, selectAll } from 'd3'; - -import flowDb from './flowDb'; -import { getConfig } from '../../config'; -import utils from '../../utils'; - +import { getConfig } from '../../config.js'; +import utils from '../../utils.js'; import { render } from '../../dagre-wrapper/index.js'; import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; -import { log } from '../../logger'; -import common, { evaluate } from '../common/common'; -import { interpolateToCurve, getStylesFromArray } from '../../utils'; -import { setupGraphViewbox } from '../../setupGraphViewbox'; +import { log } from '../../logger.js'; +import common, { evaluate } from '../common/common.js'; +import { interpolateToCurve, getStylesFromArray } from '../../utils.js'; +import { setupGraphViewbox } from '../../setupGraphViewbox.js'; const conf = {}; export const setConf = function (cnf) { @@ -47,7 +44,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { 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 @@ -55,31 +52,36 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { // We create a SVG label, either by delegating to addHtmlLabel or manually let vertexNode; - if (evaluate(getConfig().flowchart.htmlLabels)) { - // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? - const node = { - label: vertexText.replace( - /fa[blrs]?:fa-[\w-]+/g, - (s) => `` - ), - }; - vertexNode = addHtmlLabel(svg, node).node(); - vertexNode.parentNode.removeChild(vertexNode); + log.info('vertex', vertex, vertex.labelType); + if (vertex.labelType === 'markdown') { + log.info('vertex', vertex, vertex.labelType); } else { - const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); - svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); + if (evaluate(getConfig().flowchart.htmlLabels)) { + // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? + const node = { + label: vertexText.replace( + /fa[blrs]?:fa-[\w-]+/g, + (s) => `` + ), + }; + vertexNode = addHtmlLabel(svg, node).node(); + vertexNode.parentNode.removeChild(vertexNode); + } 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); + 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); + 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; } - vertexNode = svgLabel; } let radious = 0; @@ -146,6 +148,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { labelStyle: styles.labelStyle, shape: _shape, labelText: vertexText, + labelType: vertex.labelType, rx: radious, ry: radious, class: classStr, @@ -165,6 +168,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) { log.info('setNode', { labelStyle: styles.labelStyle, + labelType: vertex.labelType, shape: _shape, labelText: vertexText, rx: radious, @@ -207,7 +211,7 @@ export const addEdges = function (edges, g, diagObj) { cnt++; // Identify Link - var linkIdBase = 'L-' + edge.start + '-' + edge.end; + 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; @@ -218,8 +222,8 @@ export const addEdges = function (edges, g, diagObj) { } let linkId = linkIdBase + '-' + linkIdCnt[linkIdBase]; log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]); - var linkNameStart = 'LS-' + edge.start; - var linkNameEnd = 'LE-' + edge.end; + const linkNameStart = 'LS-' + edge.start; + const linkNameEnd = 'LE-' + edge.end; const edgeData = { style: '', labelStyle: '' }; edgeData.minlen = edge.length || 1; @@ -280,6 +284,11 @@ export const addEdges = function (edges, g, diagObj) { edgeData.pattern = 'solid'; edgeData.style = 'stroke-width: 3.5px;fill:none;'; break; + case 'invisible': + edgeData.thickness = 'invisible'; + edgeData.pattern = 'solid'; + edgeData.style = 'stroke-width: 0;fill:none;'; + break; } if (edge.style !== undefined) { const styles = getStylesFromArray(edge.style); @@ -307,7 +316,7 @@ export const addEdges = function (edges, g, diagObj) { edgeData.labelpos = 'c'; } - edgeData.labelType = 'text'; + edgeData.labelType = edge.labelType; edgeData.label = edge.text.replace(common.lineBreakRegex, '\n'); if (edge.style === undefined) { @@ -332,15 +341,7 @@ export const addEdges = function (edges, g, diagObj) { * @returns {object} ClassDef styles */ export const getClasses = function (text, diagObj) { - log.info('Extracting classes'); - diagObj.db.clear(); - try { - // Parse the graph definition - diagObj.parse(text); - return diagObj.db.getClasses(); - } catch (e) { - return; - } + return diagObj.db.getClasses(); }; /** @@ -350,12 +351,8 @@ export const getClasses = function (text, diagObj) { * @param id */ -export const draw = function (text, id, _version, diagObj) { +export const draw = async function (text, id, _version, diagObj) { log.info('Drawing flowchart'); - diagObj.db.clear(); - flowDb.setGen('gen-2'); - // Parse the graph definition - diagObj.parser.parse(text); // Fetch the default direction, use TD if none was found let dir = diagObj.db.getDirection(); @@ -400,7 +397,14 @@ export const draw = function (text, id, _version, diagObj) { for (let i = subGraphs.length - 1; i >= 0; i--) { subG = subGraphs[i]; log.info('Subgraph - ', subG); - diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir); + diagObj.db.addVertex( + subG.id, + { text: subG.title, type: subG.labelType }, + 'group', + undefined, + subG.classes, + subG.dir + ); } // Fetch the vertices/nodes and edges/links from the parsed graph definition @@ -432,7 +436,7 @@ export const draw = function (text, id, _version, diagObj) { // Run the renderer. This is what draws the final graph. const element = root.select('#' + id + ' g'); - render(element, g, ['point', 'circle', 'cross'], 'flowchart', id); + await render(element, g, ['point', 'circle', 'cross'], 'flowchart', id); utils.insertTitle(svg, 'flowchartTitleText', conf.titleTopMargin, diagObj.db.getDiagramTitle()); diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js index 01b6163cb..4b7fe272d 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer.addEdges.spec.js @@ -1,21 +1,24 @@ -import flowDb from './flowDb'; -import flowParser from './parser/flow'; -import flowRenderer from './flowRenderer'; -import { Diagram } from '../../Diagram'; -import { addDiagrams } from '../../diagram-api/diagram-orchestration'; +import flowDb from './flowDb.js'; +import { parser } from './parser/flow.jison'; +import flowRenderer from './flowRenderer.js'; +import { addDiagrams } from '../../diagram-api/diagram-orchestration.js'; + +const diag = { + db: flowDb, +}; addDiagrams(); describe('when using mermaid and ', function () { describe('when calling addEdges ', function () { beforeEach(function () { - flowParser.parser.yy = flowDb; + parser.yy = flowDb; flowDb.clear(); flowDb.setGen('gen-2'); }); - it('should handle edges with text', function () { - const diag = new Diagram('graph TD;A-->|text ex|B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should handle edges with text', () => { + parser.parse('graph TD;A-->|text ex|B;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -29,10 +32,10 @@ describe('when using mermaid and ', function () { flowRenderer.addEdges(edges, mockG, diag); }); - it('should handle edges without text', function () { - const diag = new Diagram('graph TD;A-->B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should handle edges without text', async function () { + parser.parse('graph TD;A-->B;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -45,10 +48,10 @@ describe('when using mermaid and ', function () { flowRenderer.addEdges(edges, mockG, diag); }); - it('should handle open-ended edges', function () { - const diag = new Diagram('graph TD;A---B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should handle open-ended edges', () => { + parser.parse('graph TD;A---B;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -61,10 +64,10 @@ describe('when using mermaid and ', function () { flowRenderer.addEdges(edges, mockG, diag); }); - it('should handle edges with styles defined', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should handle edges with styles defined', () => { + parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -77,10 +80,10 @@ describe('when using mermaid and ', function () { flowRenderer.addEdges(edges, mockG, diag); }); - it('should handle edges with interpolation defined', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 interpolate basis'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should handle edges with interpolation defined', () => { + parser.parse('graph TD;A---B; linkStyle 0 interpolate basis'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -93,12 +96,10 @@ describe('when using mermaid and ', function () { flowRenderer.addEdges(edges, mockG, diag); }); - it('should handle edges with text and styles defined', function () { - const diag = new Diagram( - 'graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;' - ); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should handle edges with text and styles defined', () => { + parser.parse('graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -113,10 +114,10 @@ describe('when using mermaid and ', function () { flowRenderer.addEdges(edges, mockG, diag); }); - it('should set fill to "none" by default when handling edges', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should set fill to "none" by default when handling edges', () => { + parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { @@ -130,12 +131,10 @@ describe('when using mermaid and ', function () { flowRenderer.addEdges(edges, mockG, diag); }); - it('should not set fill to none if fill is set in linkStyle', function () { - const diag = new Diagram( - 'graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;' - ); - diag.db.getVertices(); - const edges = diag.db.getEdges(); + it('should not set fill to none if fill is set in linkStyle', () => { + parser.parse('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;'); + flowDb.getVertices(); + const edges = flowDb.getEdges(); const mockG = { setEdge: function (start, end, options) { expect(start).toContain('flowchart-A-'); diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer.js index 63234b57c..fc06cacd4 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer.js @@ -1,14 +1,14 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import { select, curveLinear, selectAll } from 'd3'; -import { getConfig } from '../../config'; +import { getConfig } from '../../config.js'; import { render as Render } from 'dagre-d3-es'; import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js'; import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; -import { log } from '../../logger'; -import common, { evaluate } from '../common/common'; -import { interpolateToCurve, getStylesFromArray } from '../../utils'; -import { setupGraphViewbox } from '../../setupGraphViewbox'; -import flowChartShapes from './flowChartShapes'; +import { log } from '../../logger.js'; +import common, { evaluate } from '../common/common.js'; +import { interpolateToCurve, getStylesFromArray } from '../../utils.js'; +import { setupGraphViewbox } from '../../setupGraphViewbox.js'; +import flowChartShapes from './flowChartShapes.js'; const conf = {}; export const setConf = function (cnf) { @@ -176,9 +176,9 @@ export const addEdges = function (edges, g, diagObj) { cnt++; // Identify Link - var linkId = 'L-' + edge.start + '-' + edge.end; - var linkNameStart = 'LS-' + edge.start; - var linkNameEnd = 'LE-' + edge.end; + const linkId = 'L-' + edge.start + '-' + edge.end; + const linkNameStart = 'LS-' + edge.start; + const linkNameEnd = 'LE-' + edge.end; const edgeData = {}; @@ -273,15 +273,7 @@ export const addEdges = function (edges, g, diagObj) { */ export const getClasses = function (text, diagObj) { log.info('Extracting classes'); - diagObj.db.clear(); - try { - // Parse the graph definition - diagObj.parse(text); - return diagObj.db.getClasses(); - } catch (e) { - log.error(e); - return {}; - } + return diagObj.db.getClasses(); }; /** @@ -294,7 +286,6 @@ export const getClasses = function (text, diagObj) { */ export const draw = function (text, id, _version, diagObj) { log.info('Drawing flowchart'); - diagObj.db.clear(); const { securityLevel, flowchart: conf } = getConfig(); let sandboxElement; if (securityLevel === 'sandbox') { @@ -306,13 +297,6 @@ export const draw = function (text, id, _version, diagObj) { : select('body'); const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; - // Parse the graph definition - try { - diagObj.parser.parse(text); - } catch (err) { - log.debug('Parsing failed'); - } - // Fetch the default direction, use TD if none was found let dir = diagObj.db.getDirection(); if (dir === undefined) { diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer.spec.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer.spec.js index 4e1ce1019..0e9e8c0de 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer.spec.js @@ -1,5 +1,5 @@ -import { addVertices, addEdges } from './flowRenderer'; -import { setConfig } from '../../config'; +import { addVertices, addEdges } from './flowRenderer.js'; +import { setConfig } from '../../config.js'; setConfig({ flowchart: { diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-arrows.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-arrows.spec.js index 594e7220b..699aa333d 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-arrows.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-arrows.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js index 7aeed304c..4b0b0c830 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-comments.spec.js @@ -1,6 +1,7 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; +import { cleanupComments } from '../../../diagram-api/comments.js'; setConfig({ securityLevel: 'strict', @@ -13,7 +14,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments', function () { - const res = flow.parser.parse('graph TD;\n%% Comment\n A-->B;'); + const res = flow.parser.parse(cleanupComments('graph TD;\n%% Comment\n A-->B;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -28,7 +29,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the start', function () { - const res = flow.parser.parse('%% Comment\ngraph TD;\n A-->B;'); + const res = flow.parser.parse(cleanupComments('%% Comment\ngraph TD;\n A-->B;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -43,7 +44,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the end', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n %% Comment at the end\n'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n %% Comment at the end\n')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -58,7 +59,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the end no trailing newline', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n%% Comment'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -73,7 +74,7 @@ describe('[Comments] when parsing', () => { }); it('should handle comments at the end many trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n%% Comment\n\n\n'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n%% Comment\n\n\n')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -88,7 +89,7 @@ describe('[Comments] when parsing', () => { }); it('should handle no trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -103,7 +104,7 @@ describe('[Comments] when parsing', () => { }); it('should handle many trailing newlines', function () { - const res = flow.parser.parse('graph TD;\n A-->B\n\n'); + const res = flow.parser.parse(cleanupComments('graph TD;\n A-->B\n\n')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -118,7 +119,7 @@ describe('[Comments] when parsing', () => { }); it('should handle a comment with blank rows in-between', function () { - const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B;'); + const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); @@ -134,7 +135,9 @@ describe('[Comments] when parsing', () => { it('should handle a comment with mermaid flowchart code in them', function () { const res = flow.parser.parse( - 'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line
edge comment|ro;\n A-->B;' + cleanupComments( + 'graph TD;\n\n\n %% Test od>Odd shape]-->|Two line
edge comment|ro;\n A-->B;' + ) ); const vert = flow.parser.yy.getVertices(); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-direction.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-direction.spec.js index 7726ce0f7..ce6b0b0c4 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-direction.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-direction.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-edges.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-edges.spec.js index e2ecec4d5..21f3a4355 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-edges.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-edges.spec.js @@ -1,11 +1,45 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', }); +const keywords = [ + 'graph', + 'flowchart', + 'flowchart-elk', + 'style', + 'default', + 'linkStyle', + 'interpolate', + 'classDef', + 'class', + 'href', + 'call', + 'click', + '_self', + '_blank', + '_parent', + '_top', + 'end', + 'subgraph', + 'kitty', +]; + +const doubleEndedEdges = [ + { edgeStart: 'x--', edgeEnd: '--x', stroke: 'normal', type: 'double_arrow_cross' }, + { edgeStart: 'x==', edgeEnd: '==x', stroke: 'thick', type: 'double_arrow_cross' }, + { edgeStart: 'x-.', edgeEnd: '.-x', stroke: 'dotted', type: 'double_arrow_cross' }, + { edgeStart: 'o--', edgeEnd: '--o', stroke: 'normal', type: 'double_arrow_circle' }, + { edgeStart: 'o==', edgeEnd: '==o', stroke: 'thick', type: 'double_arrow_circle' }, + { edgeStart: 'o-.', edgeEnd: '.-o', stroke: 'dotted', type: 'double_arrow_circle' }, + { edgeStart: '<--', edgeEnd: '-->', stroke: 'normal', type: 'double_arrow_point' }, + { edgeStart: '<==', edgeEnd: '==>', stroke: 'thick', type: 'double_arrow_point' }, + { edgeStart: '<-.', edgeEnd: '.->', stroke: 'dotted', type: 'double_arrow_point' }, +]; + describe('[Edges] when parsing', () => { beforeEach(function () { flow.parser.yy = flowDb; @@ -39,211 +73,62 @@ describe('[Edges] when parsing', () => { expect(edges[0].type).toBe('arrow_circle'); }); - describe('cross', function () { - it('should handle double edged nodes and edges', function () { - const res = flow.parser.parse('graph TD;\nA x--x B;'); + describe('edges', function () { + doubleEndedEdges.forEach((edgeType) => { + it(`should handle ${edgeType.stroke} ${edgeType.type} with no text`, function () { + const res = flow.parser.parse(`graph TD;\nA ${edgeType.edgeStart}${edgeType.edgeEnd} B;`); - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_cross'); - expect(edges[0].text).toBe(''); - expect(edges[0].stroke).toBe('normal'); - expect(edges[0].length).toBe(1); - }); + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe(`${edgeType.type}`); + expect(edges[0].text).toBe(''); + expect(edges[0].stroke).toBe(`${edgeType.stroke}`); + }); - it('should handle double edged nodes with text', function () { - const res = flow.parser.parse('graph TD;\nA x-- text --x B;'); + it(`should handle ${edgeType.stroke} ${edgeType.type} with text`, function () { + const res = flow.parser.parse( + `graph TD;\nA ${edgeType.edgeStart} text ${edgeType.edgeEnd} B;` + ); - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_cross'); - expect(edges[0].text).toBe('text'); - expect(edges[0].stroke).toBe('normal'); - expect(edges[0].length).toBe(1); - }); + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe(`${edgeType.type}`); + expect(edges[0].text).toBe('text'); + expect(edges[0].stroke).toBe(`${edgeType.stroke}`); + }); - it('should handle double edged nodes and edges on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA x==x B;'); + it.each(keywords)( + `should handle ${edgeType.stroke} ${edgeType.type} with %s text`, + function (keyword) { + const res = flow.parser.parse( + `graph TD;\nA ${edgeType.edgeStart} ${keyword} ${edgeType.edgeEnd} B;` + ); - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_cross'); - expect(edges[0].text).toBe(''); - expect(edges[0].stroke).toBe('thick'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes with text on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA x== text ==x B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_cross'); - expect(edges[0].text).toBe('text'); - expect(edges[0].stroke).toBe('thick'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes and edges on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA x-.-x B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_cross'); - expect(edges[0].text).toBe(''); - expect(edges[0].stroke).toBe('dotted'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes with text on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA x-. text .-x B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_cross'); - expect(edges[0].text).toBe('text'); - expect(edges[0].stroke).toBe('dotted'); - expect(edges[0].length).toBe(1); - }); - }); - - describe('circle', function () { - it('should handle double edged nodes and edges', function () { - const res = flow.parser.parse('graph TD;\nA o--o B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_circle'); - expect(edges[0].text).toBe(''); - expect(edges[0].stroke).toBe('normal'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes with text', function () { - const res = flow.parser.parse('graph TD;\nA o-- text --o B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_circle'); - expect(edges[0].text).toBe('text'); - expect(edges[0].stroke).toBe('normal'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes and edges on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA o==o B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_circle'); - expect(edges[0].text).toBe(''); - expect(edges[0].stroke).toBe('thick'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes with text on thick arrows', function () { - const res = flow.parser.parse('graph TD;\nA o== text ==o B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_circle'); - expect(edges[0].text).toBe('text'); - expect(edges[0].stroke).toBe('thick'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes and edges on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA o-.-o B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_circle'); - expect(edges[0].text).toBe(''); - expect(edges[0].stroke).toBe('dotted'); - expect(edges[0].length).toBe(1); - }); - - it('should handle double edged nodes with text on dotted arrows', function () { - const res = flow.parser.parse('graph TD;\nA o-. text .-o B;'); - - const vert = flow.parser.yy.getVertices(); - const edges = flow.parser.yy.getEdges(); - - expect(vert['A'].id).toBe('A'); - expect(vert['B'].id).toBe('B'); - expect(edges.length).toBe(1); - expect(edges[0].start).toBe('A'); - expect(edges[0].end).toBe('B'); - expect(edges[0].type).toBe('double_arrow_circle'); - expect(edges[0].text).toBe('text'); - expect(edges[0].stroke).toBe('dotted'); - expect(edges[0].length).toBe(1); + expect(vert['A'].id).toBe('A'); + expect(vert['B'].id).toBe('B'); + expect(edges.length).toBe(1); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe(`${edgeType.type}`); + expect(edges[0].text).toBe(`${keyword}`); + expect(edges[0].stroke).toBe(`${edgeType.stroke}`); + } + ); }); }); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-huge.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-huge.spec.js index 9097c49e3..48fc2be16 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-huge.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-huge.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-interactions.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-interactions.spec.js index 7d3e3ed04..cb3f48cca 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-interactions.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-interactions.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; import { vi } from 'vitest'; const spyOn = vi.spyOn; diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-lines.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-lines.spec.js index 0fd1e9e9c..ec157e646 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-lines.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-lines.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-md-string.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-md-string.spec.js new file mode 100644 index 000000000..13cb262e3 --- /dev/null +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-md-string.spec.js @@ -0,0 +1,64 @@ +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; + +setConfig({ + securityLevel: 'strict', +}); + +describe('parsing a flow chart with markdown strings', function () { + beforeEach(function () { + flow.parser.yy = flowDb; + flow.parser.yy.clear(); + }); + + it('mardown formatting in nodes and labels', function () { + const res = flow.parser.parse(`flowchart +A["\`The cat in **the** hat\`"]-- "\`The *bat* in the chat\`" -->B["The dog in the hog"] -- "The rat in the mat" -->C;`); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + + expect(vert['A'].id).toBe('A'); + expect(vert['A'].text).toBe('The cat in **the** hat'); + expect(vert['A'].labelType).toBe('markdown'); + expect(vert['B'].id).toBe('B'); + expect(vert['B'].text).toBe('The dog in the hog'); + expect(vert['B'].labelType).toBe('string'); + expect(edges.length).toBe(2); + expect(edges[0].start).toBe('A'); + expect(edges[0].end).toBe('B'); + expect(edges[0].type).toBe('arrow_point'); + expect(edges[0].text).toBe('The *bat* in the chat'); + expect(edges[0].labelType).toBe('markdown'); + expect(edges[1].start).toBe('B'); + expect(edges[1].end).toBe('C'); + expect(edges[1].type).toBe('arrow_point'); + expect(edges[1].text).toBe('The rat in the mat'); + expect(edges[1].labelType).toBe('string'); + }); + it('mardown formatting in subgraphs', function () { + const res = flow.parser.parse(`flowchart LR +subgraph "One" + a("\`The **cat** + in the hat\`") -- "1o" --> b{{"\`The **dog** in the hog\`"}} +end +subgraph "\`**Two**\`" + c("\`The **cat** + in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") +end`); + + const subgraphs = flow.parser.yy.getSubGraphs(); + expect(subgraphs.length).toBe(2); + const subgraph = subgraphs[0]; + + expect(subgraph.nodes.length).toBe(2); + expect(subgraph.title).toBe('One'); + expect(subgraph.labelType).toBe('text'); + + const subgraph2 = subgraphs[1]; + expect(subgraph2.nodes.length).toBe(2); + expect(subgraph2.title).toBe('**Two**'); + expect(subgraph2.labelType).toBe('markdown'); + }); +}); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-singlenode.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-singlenode.spec.js index ee41a5c39..59336d8d4 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-singlenode.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-singlenode.spec.js @@ -1,11 +1,34 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', }); +const keywords = [ + 'graph', + 'flowchart', + 'flowchart-elk', + 'style', + 'default', + 'linkStyle', + 'interpolate', + 'classDef', + 'class', + 'href', + 'call', + 'click', + '_self', + '_blank', + '_parent', + '_top', + 'end', + 'subgraph', +]; + +const specialChars = ['#', ':', '0', '&', ',', '*', '.', '\\', 'v', '-', '/', '_']; + describe('[Singlenodes] when parsing', () => { beforeEach(function () { flow.parser.yy = flowDb; @@ -259,4 +282,90 @@ describe('[Singlenodes] when parsing', () => { expect(edges.length).toBe(0); expect(vert['i_d'].styles.length).toBe(0); }); + + it.each(keywords)('should handle keywords between dashes "-"', function (keyword) { + const res = flow.parser.parse(`graph TD;a-${keyword}-node;`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`a-${keyword}-node`].text).toBe(`a-${keyword}-node`); + }); + + it.each(keywords)('should handle keywords between periods "."', function (keyword) { + const res = flow.parser.parse(`graph TD;a.${keyword}.node;`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`a.${keyword}.node`].text).toBe(`a.${keyword}.node`); + }); + + it.each(keywords)('should handle keywords between underscores "_"', function (keyword) { + const res = flow.parser.parse(`graph TD;a_${keyword}_node;`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`a_${keyword}_node`].text).toBe(`a_${keyword}_node`); + }); + + it.each(keywords)('should handle nodes ending in %s', function (keyword) { + const res = flow.parser.parse(`graph TD;node_${keyword};node.${keyword};node-${keyword};`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`node_${keyword}`].text).toBe(`node_${keyword}`); + expect(vert[`node.${keyword}`].text).toBe(`node.${keyword}`); + expect(vert[`node-${keyword}`].text).toBe(`node-${keyword}`); + }); + + const errorKeywords = [ + 'graph', + 'flowchart', + 'flowchart-elk', + 'style', + 'linkStyle', + 'interpolate', + 'classDef', + 'class', + '_self', + '_blank', + '_parent', + '_top', + 'end', + 'subgraph', + ]; + it.each(errorKeywords)('should throw error at nodes beginning with %s', function (keyword) { + const str = `graph TD;${keyword}.node;${keyword}-node;${keyword}/node`; + const vert = flow.parser.yy.getVertices(); + + expect(() => flow.parser.parse(str)).toThrowError(); + }); + + const workingKeywords = ['default', 'href', 'click', 'call']; + + it.each(workingKeywords)('should parse node beginning with %s', function (keyword) { + flow.parser.parse(`graph TD; ${keyword}.node;${keyword}-node;${keyword}/node;`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`${keyword}.node`].text).toBe(`${keyword}.node`); + expect(vert[`${keyword}-node`].text).toBe(`${keyword}-node`); + expect(vert[`${keyword}/node`].text).toBe(`${keyword}/node`); + }); + + it.each(specialChars)( + 'should allow node ids of single special characters', + function (specialChar) { + flow.parser.parse(`graph TD; ${specialChar} --> A`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`${specialChar}`].text).toBe(`${specialChar}`); + } + ); + + it.each(specialChars)( + 'should allow node ids with special characters at start of id', + function (specialChar) { + flow.parser.parse(`graph TD; ${specialChar}node --> A`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`${specialChar}node`].text).toBe(`${specialChar}node`); + } + ); + + it.each(specialChars)( + 'should allow node ids with special characters at end of id', + function (specialChar) { + flow.parser.parse(`graph TD; node${specialChar} --> A`); + const vert = flow.parser.yy.getVertices(); + expect(vert[`node${specialChar}`].text).toBe(`node${specialChar}`); + } + ); }); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-style.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-style.spec.js index 050d64f91..1ab754308 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-style.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-style.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', @@ -26,15 +26,6 @@ describe('[Style] when parsing', () => { expect(vert['Q'].styles[0]).toBe('background:#fff'); }); - // log.debug(flow.parser.parse('graph TD;style Q background:#fff;')); - it('should handle styles for edges', function () { - const res = flow.parser.parse('graph TD;a-->b;\nstyle #0 stroke: #f66;'); - - const edges = flow.parser.yy.getEdges(); - - expect(edges.length).toBe(1); - }); - it('should handle multiple styles for a vortex', function () { const res = flow.parser.parse('graph TD;style R background:#fff,border:1px solid red;'); @@ -113,6 +104,22 @@ describe('[Style] when parsing', () => { expect(classes['exClass'].styles[1]).toBe('border:1px solid red'); }); + it('should be possible to declare multiple classes', function () { + const res = flow.parser.parse( + 'graph TD;classDef firstClass,secondClass background:#bbb,border:1px solid red;' + ); + + const classes = flow.parser.yy.getClasses(); + + expect(classes['firstClass'].styles.length).toBe(2); + expect(classes['firstClass'].styles[0]).toBe('background:#bbb'); + expect(classes['firstClass'].styles[1]).toBe('border:1px solid red'); + + expect(classes['secondClass'].styles.length).toBe(2); + expect(classes['secondClass'].styles[0]).toBe('background:#bbb'); + expect(classes['secondClass'].styles[1]).toBe('border:1px solid red'); + }); + it('should be possible to declare a class with a dot in the style', function () { const res = flow.parser.parse( 'graph TD;classDef exClass background:#bbb,border:1.5px solid red;' @@ -322,4 +329,20 @@ describe('[Style] when parsing', () => { expect(edges[0].type).toBe('arrow_point'); }); + + it('should handle multiple vertices with style', function () { + const res = flow.parser.parse(` + graph TD + classDef C1 stroke-dasharray:4 + classDef C2 stroke-dasharray:6 + A & B:::C1 & D:::C1 --> E:::C2 + `); + + const vert = flow.parser.yy.getVertices(); + + expect(vert['A'].classes.length).toBe(0); + expect(vert['B'].classes[0]).toBe('C1'); + expect(vert['D'].classes[0]).toBe('C1'); + expect(vert['E'].classes[0]).toBe('C2'); + }); }); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-text.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-text.spec.js index e990f41b4..b127e1b65 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-text.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-text.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', @@ -305,6 +305,95 @@ describe('[Text] when parsing', () => { expect(vert['C'].type).toBe('round'); expect(vert['C'].text).toBe('Chimpansen hoppar'); }); + + const keywords = [ + 'graph', + 'flowchart', + 'flowchart-elk', + 'style', + 'default', + 'linkStyle', + 'interpolate', + 'classDef', + 'class', + 'href', + 'call', + 'click', + '_self', + '_blank', + '_parent', + '_top', + 'end', + 'subgraph', + 'kitty', + ]; + + const shapes = [ + { start: '[', end: ']', name: 'square' }, + { start: '(', end: ')', name: 'round' }, + { start: '{', end: '}', name: 'diamond' }, + { start: '(-', end: '-)', name: 'ellipse' }, + { start: '([', end: '])', name: 'stadium' }, + { start: '>', end: ']', name: 'odd' }, + { start: '[(', end: ')]', name: 'cylinder' }, + { start: '(((', end: ')))', name: 'doublecircle' }, + { start: '[/', end: '\\]', name: 'trapezoid' }, + { start: '[\\', end: '/]', name: 'inv_trapezoid' }, + { start: '[/', end: '/]', name: 'lean_right' }, + { start: '[\\', end: '\\]', name: 'lean_left' }, + { start: '[[', end: ']]', name: 'subroutine' }, + { start: '{{', end: '}}', name: 'hexagon' }, + ]; + + shapes.forEach((shape) => { + it.each(keywords)(`should handle %s keyword in ${shape.name} vertex`, function (keyword) { + const rest = flow.parser.parse( + `graph TD;A_${keyword}_node-->B${shape.start}This node has a ${keyword} as text${shape.end};` + ); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + expect(vert['B'].type).toBe(`${shape.name}`); + expect(vert['B'].text).toBe(`This node has a ${keyword} as text`); + }); + }); + + it.each(keywords)('should handle %s keyword in rect vertex', function (keyword) { + const rest = flow.parser.parse( + `graph TD;A_${keyword}_node-->B[|borders:lt|This node has a ${keyword} as text];` + ); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + expect(vert['B'].type).toBe('rect'); + expect(vert['B'].text).toBe(`This node has a ${keyword} as text`); + }); + + it('should handle edge case for odd vertex with node id ending with minus', function () { + const res = flow.parser.parse('graph TD;A_node-->odd->Vertex Text];'); + const vert = flow.parser.yy.getVertices(); + + expect(vert['odd-'].type).toBe('odd'); + expect(vert['odd-'].text).toBe('Vertex Text'); + }); + it('should allow forward slashes in lean_right vertices', function () { + const rest = flow.parser.parse(`graph TD;A_node-->B[/This node has a / as text/];`); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + expect(vert['B'].type).toBe('lean_right'); + expect(vert['B'].text).toBe(`This node has a / as text`); + }); + + it('should allow back slashes in lean_left vertices', function () { + const rest = flow.parser.parse(`graph TD;A_node-->B[\\This node has a \\ as text\\];`); + + const vert = flow.parser.yy.getVertices(); + const edges = flow.parser.yy.getEdges(); + expect(vert['B'].type).toBe('lean_left'); + expect(vert['B'].text).toBe(`This node has a \\ as text`); + }); + it('should handle åäö and minus', function () { const res = flow.parser.parse('graph TD;A-->C{Chimpansen hoppar åäö-ÅÄÖ};'); @@ -484,4 +573,33 @@ describe('[Text] when parsing', () => { expect(vert['A'].text).toBe(',.?!+-*'); expect(edges[0].text).toBe(',.?!+-*'); }); + + it('should throw error at nested set of brackets', function () { + const str = 'graph TD; A[This is a () in text];'; + expect(() => flow.parser.parse(str)).toThrowError("got 'PS'"); + }); + + it('should throw error for strings and text at the same time', function () { + const str = 'graph TD;A(this node has "string" and text)-->|this link has "string" and text|C;'; + + expect(() => flow.parser.parse(str)).toThrowError("got 'STR'"); + }); + + it('should throw error for escaping quotes in text state', function () { + //prettier-ignore + const str = 'graph TD; A[This is a \"()\" in text];'; //eslint-disable-line no-useless-escape + + expect(() => flow.parser.parse(str)).toThrowError("got 'STR'"); + }); + + it('should throw error for nested quoatation marks', function () { + const str = 'graph TD; A["This is a "()" in text"];'; + + expect(() => flow.parser.parse(str)).toThrowError("Expecting 'SQE'"); + }); + + it('should throw error', function () { + const str = `graph TD; node[hello ) world] --> works`; + expect(() => flow.parser.parse(str)).toThrowError("got 'PE'"); + }); }); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js index 36aaae767..3f1078030 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow-vertice-chaining.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison index 05473b4a0..8d746f808 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison @@ -7,11 +7,18 @@ /* lexical grammar */ %lex %x string +%x md_string %x acc_title %x acc_descr %x acc_descr_multiline %x dir %x vertex +%x text +%x ellipseText +%x trapText +%x edgeText +%x thickEdgeText +%x dottedEdgeText %x click %x href %x callbackname @@ -22,40 +29,19 @@ %x close_directive %% -\%\%\{ { this.begin('open_directive'); return 'open_directive'; } -((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } -":" { this.popState(); this.begin('arg_directive'); return ':'; } -\}\%\% { this.popState(); this.popState(); return 'close_directive'; } -((?:(?!\}\%\%).|\n)*) return 'arg_directive'; -\%\%(?!\{)[^\n]* /* skip comments */ -[^\}]\%\%[^\n]* /* skip comments */ -accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } -(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } -accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } -(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } -accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} +\%\%\{ { this.begin('open_directive'); return 'open_directive'; } +((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } +":" { this.popState(); this.begin('arg_directive'); return ':'; } +\}\%\% { this.popState(); this.popState(); return 'close_directive'; } +((?:(?!\}\%\%).|\n)*) return 'arg_directive'; +accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } +accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } +accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} [\}] { this.popState(); } [^\}]* return "acc_descr_multiline_value"; -// .*[^\n]* { return "acc_descr_line"} -["] this.begin("string"); -["] this.popState(); -[^"]* return "STR"; -"style" return 'STYLE'; -"default" return 'DEFAULT'; -"linkStyle" return 'LINKSTYLE'; -"interpolate" return 'INTERPOLATE'; -"classDef" return 'CLASSDEF'; -"class" return 'CLASS'; - -/* ----interactivity command--- -'href' adds a link to the specified node. 'href' can only be specified when the -line was introduced with 'click'. -'href ""' attaches the specified link to the node that was specified by 'click'. -*/ -"href"[\s]+["] this.begin("href"); -["] this.popState(); -[^"]* return 'HREF'; +// .*[^\n]* { return "acc_descr_line"} /* ---interactivity command--- @@ -72,87 +58,128 @@ Function arguments are optional: 'call ()' simply executes 'callba \) this.popState(); [^)]* return 'CALLBACKARGS'; +[^`"]+ { return "MD_STR";} +[`]["] { this.popState();} +<*>["][`] { this.begin("md_string");} +[^"]+ return "STR"; +["] this.popState(); +<*>["] this.pushState("string"); +"style" return 'STYLE'; +"default" return 'DEFAULT'; +"linkStyle" return 'LINKSTYLE'; +"interpolate" return 'INTERPOLATE'; +"classDef" return 'CLASSDEF'; +"class" return 'CLASS'; + +/* +---interactivity command--- +'href' adds a link to the specified node. 'href' can only be specified when the +line was introduced with 'click'. +'href ""' attaches the specified link to the node that was specified by 'click'. +*/ +"href"[\s] return 'HREF'; + + /* 'click' is the keyword to introduce a line that contains interactivity commands. 'click' must be followed by an existing node-id. All commands are attached to that id. 'click ' can be followed by href or call commands in any desired order */ -"click"[\s]+ this.begin("click"); -[\s\n] this.popState(); -[^\s\n]* return 'CLICK'; +"click"[\s]+ this.begin("click"); +[\s\n] this.popState(); +[^\s\n]* return 'CLICK'; -"flowchart-elk" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} -"graph" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} -"flowchart" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} -"subgraph" return 'subgraph'; -"end"\b\s* return 'end'; +"flowchart-elk" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} +"graph" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} +"flowchart" {if(yy.lex.firstGraph()){this.begin("dir");} return 'GRAPH';} +"subgraph" return 'subgraph'; +"end"\b\s* return 'end'; -"_self" return 'LINK_TARGET'; -"_blank" return 'LINK_TARGET'; -"_parent" return 'LINK_TARGET'; -"_top" return 'LINK_TARGET'; +"_self" return 'LINK_TARGET'; +"_blank" return 'LINK_TARGET'; +"_parent" return 'LINK_TARGET'; +"_top" return 'LINK_TARGET'; -

(\r?\n)*\s*\n { this.popState(); return 'NODIR'; } -\s*"LR" { this.popState(); return 'DIR'; } -\s*"RL" { this.popState(); return 'DIR'; } -\s*"TB" { this.popState(); return 'DIR'; } -\s*"BT" { this.popState(); return 'DIR'; } -\s*"TD" { this.popState(); return 'DIR'; } -\s*"BR" { this.popState(); return 'DIR'; } -\s*"<" { this.popState(); return 'DIR'; } -\s*">" { this.popState(); return 'DIR'; } -\s*"^" { this.popState(); return 'DIR'; } -\s*"v" { this.popState(); return 'DIR'; } +(\r?\n)*\s*\n { this.popState(); return 'NODIR'; } +\s*"LR" { this.popState(); return 'DIR'; } +\s*"RL" { this.popState(); return 'DIR'; } +\s*"TB" { this.popState(); return 'DIR'; } +\s*"BT" { this.popState(); return 'DIR'; } +\s*"TD" { this.popState(); return 'DIR'; } +\s*"BR" { this.popState(); return 'DIR'; } +\s*"<" { this.popState(); return 'DIR'; } +\s*">" { this.popState(); return 'DIR'; } +\s*"^" { this.popState(); return 'DIR'; } +\s*"v" { this.popState(); return 'DIR'; } + +.*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'; + +[0-9]+ return 'NUM'; +\# return 'BRKT'; +":::" return 'STYLE_SEPARATOR'; +":" return 'COLON'; +"&" return 'AMP'; +";" return 'SEMI'; +"," return 'COMMA'; +"*" return 'MULT'; + +\s*[xo<]?\-\-+[-xo>]\s* { this.popState(); return 'LINK'; } +\s*[xo<]?\-\-\s* { this.pushState("edgeText"); return 'START_LINK'; } +[^-]|\-(?!\-)+ return 'EDGE_TEXT'; + +\s*[xo<]?\=\=+[=xo>]\s* { this.popState(); return 'LINK'; } +\s*[xo<]?\=\=\s* { this.pushState("thickEdgeText"); return 'START_LINK'; } +[^=]|\=(?!=) return 'EDGE_TEXT'; + +\s*[xo<]?\-?\.+\-[xo>]?\s* { this.popState(); return 'LINK'; } +\s*[xo<]?\-\.\s* { this.pushState("dottedEdgeText"); return 'START_LINK'; } +[^\.]|\.(?!-) return 'EDGE_TEXT'; + + +<*>\s*\~\~[\~]+\s* return 'LINK'; + +[-/\)][\)] { this.popState(); return '-)'; } +[^\(\)\[\]\{\}]|-/!\)+ return "TEXT" +<*>"(-" { this.pushState("ellipseText"); return '(-'; } + +"])" { this.popState(); return 'STADIUMEND'; } +<*>"([" { this.pushState("text"); return 'STADIUMSTART'; } + +"]]" { this.popState(); return 'SUBROUTINEEND'; } +<*>"[[" { this.pushState("text"); return 'SUBROUTINESTART'; } + +"[|" { return 'VERTEX_WITH_PROPS_START'; } + +\> { this.pushState("text"); return 'TAGEND'; } + +")]" { this.popState(); return 'CYLINDEREND'; } +<*>"[(" { this.pushState("text") ;return 'CYLINDERSTART'; } + +")))" { this.popState(); return 'DOUBLECIRCLEEND'; } +<*>"(((" { this.pushState("text"); return 'DOUBLECIRCLESTART'; } + +[\\(?=\])][\]] { this.popState(); return 'TRAPEND'; } +\/(?=\])\] { this.popState(); return 'INVTRAPEND'; } +\/(?!\])|\\(?!\])|[^\\\[\]\(\)\{\}\/]+ return 'TEXT'; +<*>"[/" { this.pushState("trapText"); return 'TRAPSTART'; } + +<*>"[\\" { this.pushState("trapText"); return 'INVTRAPSTART'; } -.*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'; -[0-9]+ { return 'NUM';} -\# return 'BRKT'; -":::" return 'STYLE_SEPARATOR'; -":" return 'COLON'; -"&" return 'AMP'; -";" return 'SEMI'; -"," return 'COMMA'; -"*" return 'MULT'; -\s*[xo<]?\-\-+[-xo>]\s* return 'LINK'; -\s*[xo<]?\=\=+[=xo>]\s* return 'LINK'; -\s*[xo<]?\-?\.+\-[xo>]?\s* return 'LINK'; -\s*[xo<]?\-\-\s* return 'START_LINK'; -\s*[xo<]?\=\=\s* return 'START_LINK'; -\s*[xo<]?\-\.\s* return 'START_LINK'; -"(-" return '(-'; -"-)" return '-)'; -"([" return 'STADIUMSTART'; -"])" return 'STADIUMEND'; -"[[" return 'SUBROUTINESTART'; -"]]" return 'SUBROUTINEEND'; -"[|" return 'VERTEX_WITH_PROPS_START'; -"[(" return 'CYLINDERSTART'; -")]" return 'CYLINDEREND'; -"(((" return 'DOUBLECIRCLESTART'; -")))" return 'DOUBLECIRCLEEND'; -\- return 'MINUS'; -"." return 'DOT'; -[\_] return 'UNDERSCORE'; -\+ return 'PLUS'; -\% return 'PCT'; -"=" return 'EQUALS'; -\= return 'EQUALS'; "<" return 'TAGSTART'; ">" return 'TAGEND'; "^" return 'UP'; "\|" return 'SEP'; "v" return 'DOWN'; -[A-Za-z]+ return 'ALPHA'; -"\\]" return 'TRAPEND'; -"[/" return 'TRAPSTART'; -"/]" return 'INVTRAPEND'; -"[\\" return 'INVTRAPSTART'; -[!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION'; +"*" return 'MULT'; +"#" return 'BRKT'; +"&" return 'AMP'; +([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|\-(?=[^\>\-\.])|=(?!=))+ return 'NODE_STRING'; +"-" return 'MINUS' [\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]| [\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]| [\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]| @@ -215,13 +242,20 @@ that id. [\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]| [\uFFD2-\uFFD7\uFFDA-\uFFDC] return 'UNICODE_TEXT'; -"|" return 'PIPE'; -"(" return 'PS'; -")" return 'PE'; -"[" return 'SQS'; -"]" return 'SQE'; -"{" return 'DIAMOND_START' -"}" return 'DIAMOND_STOP' + +"|" { this.popState(); return 'PIPE'; } +<*>"|" { this.pushState("text"); return 'PIPE'; } + +")" { this.popState(); return 'PE'; } +<*>"(" { this.pushState("text"); return 'PS'; } + +"]" { this.popState(); return 'SQE'; } +<*>"[" { this.pushState("text"); return 'SQS'; } + +(\}) { this.popState(); return 'DIAMOND_STOP' } +<*>"{" { this.pushState("text"); return 'DIAMOND_START' } +[^\[\]\(\)\{\}\|\"]+ return "TEXT"; + "\"" return 'QUOTE'; (\r?\n)+ return 'NEWLINE'; \s return 'SPACE'; @@ -252,11 +286,11 @@ openDirective ; typeDirective - : type_directive { yy.parseDirective($1, 'type_directive'); } + : type_directive { yy.parseDirective($type_directive, 'type_directive'); } ; argDirective - : arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); } + : arg_directive { $arg_directive = $arg_directive.trim().replace(/'/g, '"'); yy.parseDirective($arg_directive, 'arg_directive'); } ; closeDirective @@ -272,15 +306,15 @@ document { $$ = [];} | document line { - if(!Array.isArray($2) || $2.length > 0){ - $1.push($2); + if(!Array.isArray($line) || $line.length > 0){ + $document.push($line); } - $$=$1;} + $$=$document;} ; line : statement - {$$=$1;} + {$$=$statement;} | SEMI | NEWLINE | SPACE @@ -293,15 +327,15 @@ graphConfig | GRAPH NODIR { yy.setDirection('TB');$$ = 'TB';} | GRAPH DIR FirstStmtSeperator - { yy.setDirection($2);$$ = $2;} + { yy.setDirection($DIR);$$ = $DIR;} // | GRAPH SPACE TAGEND FirstStmtSeperator - // { yy.setDirection("LR");$$ = $3;} + // { yy.setDirection("LR");$$ = $TAGEND;} // | GRAPH SPACE TAGSTART FirstStmtSeperator - // { yy.setDirection("RL");$$ = $3;} + // { yy.setDirection("RL");$$ = $TAGSTART;} // | GRAPH SPACE UP FirstStmtSeperator - // { yy.setDirection("BT");$$ = $3;} + // { yy.setDirection("BT");$$ = $UP;} // | GRAPH SPACE DOWN FirstStmtSeperator - // { yy.setDirection("TB");$$ = $3;} + // { yy.setDirection("TB");$$ = $DOWN;} ; ending: endToken ending @@ -329,7 +363,7 @@ spaceList statement : verticeStatement separator - { /* console.warn('finat vs', $1.nodes); */ $$=$1.nodes} + { /* console.warn('finat vs', $verticeStatement.nodes); */ $$=$verticeStatement.nodes} | styleStatement separator {$$=[];} | linkStyleStatement separator @@ -340,104 +374,121 @@ statement {$$=[];} | clickStatement separator {$$=[];} - | subgraph SPACE text SQS text SQE separator document end - {$$=yy.addSubGraph($3,$8,$5);} - | subgraph SPACE text separator document end - {$$=yy.addSubGraph($3,$5,$3);} - // | subgraph SPACE text separator document end - // {$$=yy.addSubGraph($3,$5,$3);} + | subgraph SPACE textNoTags SQS text SQE separator document end + {$$=yy.addSubGraph($textNoTags,$document,$text);} + | subgraph SPACE textNoTags separator document end + {$$=yy.addSubGraph($textNoTags,$document,$textNoTags);} + // | subgraph SPACE textNoTags separator document end + // {$$=yy.addSubGraph($textNoTags,$document,$textNoTags);} | subgraph separator document end - {$$=yy.addSubGraph(undefined,$3,undefined);} + {$$=yy.addSubGraph(undefined,$document,undefined);} | direction - | acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); } - | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } - | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } + | acc_title acc_title_value { $$=$acc_title_value.trim();yy.setAccTitle($$); } + | acc_descr acc_descr_value { $$=$acc_descr_value.trim();yy.setAccDescription($$); } + | acc_descr_multiline_value { $$=$acc_descr_multiline_value.trim();yy.setAccDescription($$); } ; separator: NEWLINE | SEMI | EOF ; verticeStatement: verticeStatement link node - { /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } } + { /* console.warn('vs',$verticeStatement.stmt,$node); */ yy.addLink($verticeStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($verticeStatement.nodes) } } | verticeStatement link node spaceList - { /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } } - |node spaceList {/*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }} - |node { /*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }} + { /* console.warn('vs',$verticeStatement.stmt,$node); */ yy.addLink($verticeStatement.stmt,$node,$link); $$ = { stmt: $node, nodes: $node.concat($verticeStatement.nodes) } } + |node spaceList {/*console.warn('noda', $node);*/ $$ = {stmt: $node, nodes:$node }} + |node { /*console.warn('noda', $node);*/ $$ = {stmt: $node, nodes:$node }} ; -node: vertex - { /* console.warn('nod', $1); */ $$ = [$1];} - | node spaceList AMP spaceList vertex - { $$ = $1.concat($5); /* console.warn('pip', $1[0], $5, $$); */ } +node: styledVertex + { /* console.warn('nod', $styledVertex); */ $$ = [$styledVertex];} + | node spaceList AMP spaceList styledVertex + { $$ = $node.concat($styledVertex); /* console.warn('pip', $node[0], $styledVertex, $$); */ } + ; + +styledVertex: vertex + { /* console.warn('nod', $vertex); */ $$ = $vertex;} | vertex STYLE_SEPARATOR idString - {$$ = [$1];yy.setClass($1,$3)} + {$$ = $vertex;yy.setClass($vertex,$idString)} ; vertex: idString SQS text SQE - {$$ = $1;yy.addVertex($1,$3,'square');} + {$$ = $idString;yy.addVertex($idString,$text,'square');} | idString DOUBLECIRCLESTART text DOUBLECIRCLEEND - {$$ = $1;yy.addVertex($1,$3,'doublecircle');} + {$$ = $idString;yy.addVertex($idString,$text,'doublecircle');} | idString PS PS text PE PE - {$$ = $1;yy.addVertex($1,$4,'circle');} + {$$ = $idString;yy.addVertex($idString,$text,'circle');} | idString '(-' text '-)' - {$$ = $1;yy.addVertex($1,$3,'ellipse');} + {$$ = $idString;yy.addVertex($idString,$text,'ellipse');} | idString STADIUMSTART text STADIUMEND - {$$ = $1;yy.addVertex($1,$3,'stadium');} + {$$ = $idString;yy.addVertex($idString,$text,'stadium');} | idString SUBROUTINESTART text SUBROUTINEEND - {$$ = $1;yy.addVertex($1,$3,'subroutine');} - | idString VERTEX_WITH_PROPS_START ALPHA COLON ALPHA PIPE text SQE - {$$ = $1;yy.addVertex($1,$7,'rect',undefined,undefined,undefined, Object.fromEntries([[$3, $5]]));} + {$$ = $idString;yy.addVertex($idString,$text,'subroutine');} + | idString VERTEX_WITH_PROPS_START NODE_STRING\[field] COLON NODE_STRING\[value] PIPE text SQE + {$$ = $idString;yy.addVertex($idString,$text,'rect',undefined,undefined,undefined, Object.fromEntries([[$field, $value]]));} | idString CYLINDERSTART text CYLINDEREND - {$$ = $1;yy.addVertex($1,$3,'cylinder');} + {$$ = $idString;yy.addVertex($idString,$text,'cylinder');} | idString PS text PE - {$$ = $1;yy.addVertex($1,$3,'round');} + {$$ = $idString;yy.addVertex($idString,$text,'round');} | idString DIAMOND_START text DIAMOND_STOP - {$$ = $1;yy.addVertex($1,$3,'diamond');} + {$$ = $idString;yy.addVertex($idString,$text,'diamond');} | idString DIAMOND_START DIAMOND_START text DIAMOND_STOP DIAMOND_STOP - {$$ = $1;yy.addVertex($1,$4,'hexagon');} + {$$ = $idString;yy.addVertex($idString,$text,'hexagon');} | idString TAGEND text SQE - {$$ = $1;yy.addVertex($1,$3,'odd');} + {$$ = $idString;yy.addVertex($idString,$text,'odd');} | idString TRAPSTART text TRAPEND - {$$ = $1;yy.addVertex($1,$3,'trapezoid');} + {$$ = $idString;yy.addVertex($idString,$text,'trapezoid');} | idString INVTRAPSTART text INVTRAPEND - {$$ = $1;yy.addVertex($1,$3,'inv_trapezoid');} + {$$ = $idString;yy.addVertex($idString,$text,'inv_trapezoid');} | idString TRAPSTART text INVTRAPEND - {$$ = $1;yy.addVertex($1,$3,'lean_right');} + {$$ = $idString;yy.addVertex($idString,$text,'lean_right');} | idString INVTRAPSTART text TRAPEND - {$$ = $1;yy.addVertex($1,$3,'lean_left');} + {$$ = $idString;yy.addVertex($idString,$text,'lean_left');} | idString - { /*console.warn('h: ', $1);*/$$ = $1;yy.addVertex($1);} + { /*console.warn('h: ', $idString);*/$$ = $idString;yy.addVertex($idString);} ; link: linkStatement arrowText - {$1.text = $2;$$ = $1;} + {$linkStatement.text = $arrowText;$$ = $linkStatement;} | linkStatement TESTSTR SPACE - {$1.text = $2;$$ = $1;} + {$linkStatement.text = $TESTSTR;$$ = $linkStatement;} | linkStatement arrowText SPACE - {$1.text = $2;$$ = $1;} + {$linkStatement.text = $arrowText;$$ = $linkStatement;} | linkStatement - {$$ = $1;} - | START_LINK text LINK - {var inf = yy.destructLink($3, $1); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$2};} + {$$ = $linkStatement;} + | START_LINK edgeText LINK + {var inf = yy.destructLink($LINK, $START_LINK); $$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length,"text":$edgeText};} ; +edgeText: edgeTextToken + {$$={text:$edgeTextToken, type:'text'};} + | edgeText edgeTextToken + {$$={text:$edgeText.text+''+$edgeTextToken, type:$edgeText.type};} + |STR + {$$={text: $STR, type: 'string'};} + | MD_STR + {$$={text:$MD_STR, type:'markdown'};} + ; + + linkStatement: LINK - {var inf = yy.destructLink($1);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};} + {var inf = yy.destructLink($LINK);$$ = {"type":inf.type,"stroke":inf.stroke,"length":inf.length};} ; arrowText: PIPE text PIPE - {$$ = $2;} + {$$ = $text;} ; text: textToken - {$$=$1;} + { $$={text:$textToken, type: 'text'};} | text textToken - {$$=$1+''+$2;} + { $$={text:$text.text+''+$textToken, type: $text.type};} | STR - {$$=$1;} + { $$ = {text: $STR, type: 'string'};} + | MD_STR + { $$={text: $MD_STR, type: 'markdown'};} ; @@ -447,109 +498,104 @@ keywords textNoTags: textNoTagsToken - {$$=$1;} + {$$={text:$textNoTagsToken, type: 'text'};} | textNoTags textNoTagsToken - {$$=$1+''+$2;} + {$$={text:$textNoTags.text+''+$textNoTagsToken, type: $textNoTags.type};} + | STR + { $$={text: $STR, type: 'text'};} + | MD_STR + { $$={text: $MD_STR, type: 'markdown'};} ; -classDefStatement:CLASSDEF SPACE DEFAULT SPACE stylesOpt - {$$ = $1;yy.addClass($3,$5);} - | CLASSDEF SPACE alphaNum SPACE stylesOpt - {$$ = $1;yy.addClass($3,$5);} +classDefStatement:CLASSDEF SPACE idString SPACE stylesOpt + {$$ = $CLASSDEF;yy.addClass($idString,$stylesOpt);} ; -classStatement:CLASS SPACE alphaNum SPACE alphaNum - {$$ = $1;yy.setClass($3, $5);} +classStatement:CLASS SPACE idString\[vertex] SPACE idString\[class] + {$$ = $CLASS;yy.setClass($vertex, $class);} ; clickStatement - : CLICK CALLBACKNAME {$$ = $1;yy.setClickEvent($1, $2);} - | CLICK CALLBACKNAME SPACE STR {$$ = $1;yy.setClickEvent($1, $2);yy.setTooltip($1, $4);} - | CLICK CALLBACKNAME CALLBACKARGS {$$ = $1;yy.setClickEvent($1, $2, $3);} - | CLICK CALLBACKNAME CALLBACKARGS SPACE STR {$$ = $1;yy.setClickEvent($1, $2, $3);yy.setTooltip($1, $5);} - | CLICK HREF {$$ = $1;yy.setLink($1, $2);} - | CLICK HREF SPACE STR {$$ = $1;yy.setLink($1, $2);yy.setTooltip($1, $4);} - | CLICK HREF SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $4);} - | CLICK HREF SPACE STR SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $6);yy.setTooltip($1, $4);} - | CLICK alphaNum {$$ = $1;yy.setClickEvent($1, $2);} - | CLICK alphaNum SPACE STR {$$ = $1;yy.setClickEvent($1, $2);yy.setTooltip($1, $4);} - | CLICK STR {$$ = $1;yy.setLink($1, $2);} - | CLICK STR SPACE STR {$$ = $1;yy.setLink($1, $2);yy.setTooltip($1, $4);} - | CLICK STR SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $4);} - | CLICK STR SPACE STR SPACE LINK_TARGET {$$ = $1;yy.setLink($1, $2, $6);yy.setTooltip($1, $4);} + : CLICK CALLBACKNAME {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME);} + | CLICK CALLBACKNAME SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME);yy.setTooltip($CLICK, $STR);} + | CLICK CALLBACKNAME CALLBACKARGS {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME, $CALLBACKARGS);} + | CLICK CALLBACKNAME CALLBACKARGS SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $CALLBACKNAME, $CALLBACKARGS);yy.setTooltip($CLICK, $STR);} + | CLICK HREF STR {$$ = $CLICK;yy.setLink($CLICK, $STR);} + | CLICK HREF STR SPACE STR {$$ = $CLICK;yy.setLink($CLICK, $STR1);yy.setTooltip($CLICK, $STR2);} + | CLICK HREF STR SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $STR, $LINK_TARGET);} + | CLICK HREF STR\[link] SPACE STR\[tooltip] SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $link, $LINK_TARGET);yy.setTooltip($CLICK, $tooltip);} + | CLICK alphaNum {$$ = $CLICK;yy.setClickEvent($CLICK, $alphaNum);} + | CLICK alphaNum SPACE STR {$$ = $CLICK;yy.setClickEvent($CLICK, $alphaNum);yy.setTooltip($CLICK, $STR);} + | CLICK STR {$$ = $CLICK;yy.setLink($CLICK, $STR);} + | CLICK STR\[link] SPACE STR\[tooltip] {$$ = $CLICK;yy.setLink($CLICK, $link);yy.setTooltip($CLICK, $tooltip);} + | CLICK STR SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $STR, $LINK_TARGET);} + | CLICK STR\[link] SPACE STR\[tooltip] SPACE LINK_TARGET {$$ = $CLICK;yy.setLink($CLICK, $link, $LINK_TARGET);yy.setTooltip($CLICK, $tooltip);} ; -styleStatement:STYLE SPACE alphaNum SPACE stylesOpt - {$$ = $1;yy.addVertex($3,undefined,undefined,$5);} - | STYLE SPACE HEX SPACE stylesOpt - {$$ = $1;yy.updateLink($3,$5);} +styleStatement:STYLE SPACE idString SPACE stylesOpt + {$$ = $STYLE;yy.addVertex($idString,undefined,undefined,$stylesOpt);} ; linkStyleStatement : LINKSTYLE SPACE DEFAULT SPACE stylesOpt - {$$ = $1;yy.updateLink([$3],$5);} + {$$ = $LINKSTYLE;yy.updateLink([$DEFAULT],$stylesOpt);} | LINKSTYLE SPACE numList SPACE stylesOpt - {$$ = $1;yy.updateLink($3,$5);} + {$$ = $LINKSTYLE;yy.updateLink($numList,$stylesOpt);} | LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt - {$$ = $1;yy.updateLinkInterpolate([$3],$7);yy.updateLink([$3],$9);} + {$$ = $LINKSTYLE;yy.updateLinkInterpolate([$DEFAULT],$alphaNum);yy.updateLink([$DEFAULT],$stylesOpt);} | LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum SPACE stylesOpt - {$$ = $1;yy.updateLinkInterpolate($3,$7);yy.updateLink($3,$9);} + {$$ = $LINKSTYLE;yy.updateLinkInterpolate($numList,$alphaNum);yy.updateLink($numList,$stylesOpt);} | LINKSTYLE SPACE DEFAULT SPACE INTERPOLATE SPACE alphaNum - {$$ = $1;yy.updateLinkInterpolate([$3],$7);} + {$$ = $LINKSTYLE;yy.updateLinkInterpolate([$DEFAULT],$alphaNum);} | LINKSTYLE SPACE numList SPACE INTERPOLATE SPACE alphaNum - {$$ = $1;yy.updateLinkInterpolate($3,$7);} + {$$ = $LINKSTYLE;yy.updateLinkInterpolate($numList,$alphaNum);} ; numList: NUM - {$$ = [$1]} + {$$ = [$NUM]} | numList COMMA NUM - {$1.push($3);$$ = $1;} + {$numList.push($NUM);$$ = $numList;} ; stylesOpt: style - {$$ = [$1]} + {$$ = [$style]} | stylesOpt COMMA style - {$1.push($3);$$ = $1;} + {$stylesOpt.push($style);$$ = $stylesOpt;} ; style: styleComponent |style styleComponent - {$$ = $1 + $2;} + {$$ = $style + $styleComponent;} ; -styleComponent: ALPHA | COLON | MINUS | NUM | UNIT | SPACE | HEX | BRKT | DOT | STYLE | PCT ; +styleComponent: NUM | NODE_STRING| COLON | UNIT | SPACE | BRKT | STYLE | PCT ; /* Token lists */ +idStringToken : NUM | NODE_STRING | DOWN | MINUS | DEFAULT | COMMA | COLON | AMP | BRKT | MULT | UNICODE_TEXT; -textToken : textNoTagsToken | TAGSTART | TAGEND | START_LINK | PCT | DEFAULT; +textToken : TEXT | TAGSTART | TAGEND | UNICODE_TEXT; -textNoTagsToken: alphaNumToken | SPACE | MINUS | keywords ; +textNoTagsToken: NUM | NODE_STRING | SPACE | MINUS | AMP | UNICODE_TEXT | COLON | MULT | BRKT | keywords | START_LINK ; + +edgeTextToken : EDGE_TEXT | UNICODE_TEXT ; + +alphaNumToken : NUM | UNICODE_TEXT | NODE_STRING | DIR | DOWN | MINUS | COMMA | COLON | AMP | BRKT | MULT; idString :idStringToken - {$$=$1} + {$$=$idStringToken} | idString idStringToken - {$$=$1+''+$2} + {$$=$idString+''+$idStringToken} ; alphaNum - : alphaNumStatement - {$$=$1;} - | alphaNum alphaNumStatement - {$$=$1+''+$2;} + : alphaNumToken + {$$=$alphaNumToken;} + | alphaNum alphaNumToken + {$$=$alphaNum+''+$alphaNumToken;} ; -alphaNumStatement - : DIR - {$$=$1;} - | alphaNumToken - {$$=$1;} - | DOWN - {$$='v';} - | MINUS - {$$='-';} - ; direction : direction_tb @@ -562,9 +608,4 @@ direction { $$={stmt:'dir', value:'LR'};} ; -alphaNumToken : PUNCTUATION | AMP | UNICODE_TEXT | NUM| ALPHA | COLON | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ; - -idStringToken : ALPHA|UNDERSCORE |UNICODE_TEXT | NUM| COLON | COMMA | PLUS | MINUS | DOWN |EQUALS | MULT | BRKT | DOT | PUNCTUATION | AMP | DEFAULT; - -graphCodeTokens: STADIUMSTART | STADIUMEND | SUBROUTINESTART | SUBROUTINEEND | VERTEX_WITH_PROPS_START | CYLINDERSTART | CYLINDEREND | TRAPSTART | TRAPEND | INVTRAPSTART | INVTRAPEND | PIPE | PS | PE | SQS | SQE | DIAMOND_START | DIAMOND_STOP | TAGSTART | TAGEND | ARROW_CROSS | ARROW_POINT | ARROW_CIRCLE | ARROW_OPEN | QUOTE | SEMI; %% diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js index 6b440da79..3852c4f92 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js @@ -1,6 +1,7 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; +import { cleanupComments } from '../../../diagram-api/comments.js'; setConfig({ securityLevel: 'strict', @@ -13,7 +14,7 @@ describe('parsing a flow chart', function () { }); it('should handle a trailing whitespaces after statements', function () { - const res = flow.parser.parse('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;'); + const res = flow.parser.parse(cleanupComments('graph TD;\n\n\n %% Comment\n A-->B; \n B-->C;')); const vert = flow.parser.yy.getVertices(); const edges = flow.parser.yy.getEdges(); diff --git a/packages/mermaid/src/diagrams/flowchart/parser/subgraph.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/subgraph.spec.js index ae6f178b8..12b2e4a39 100644 --- a/packages/mermaid/src/diagrams/flowchart/parser/subgraph.spec.js +++ b/packages/mermaid/src/diagrams/flowchart/parser/subgraph.spec.js @@ -1,6 +1,6 @@ -import flowDb from '../flowDb'; -import flow from './flow'; -import { setConfig } from '../../../config'; +import flowDb from '../flowDb.js'; +import flow from './flow.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/flowchart/styles.ts b/packages/mermaid/src/diagrams/flowchart/styles.ts index a89d33d3d..d0c3c77c6 100644 --- a/packages/mermaid/src/diagrams/flowchart/styles.ts +++ b/packages/mermaid/src/diagrams/flowchart/styles.ts @@ -1,3 +1,6 @@ +// import khroma from 'khroma'; +import * as khroma from 'khroma'; + /** Returns the styles given options */ export interface FlowChartStyleOptions { arrowheadColor: string; @@ -15,6 +18,18 @@ export interface FlowChartStyleOptions { titleColor: string; } +const fade = (color: string, opacity: number) => { + // @ts-ignore TODO: incorrect types from khroma + const channel = khroma.channel; + + const r = channel(color, 'r'); + const g = channel(color, 'g'); + const b = channel(color, 'b'); + + // @ts-ignore incorrect types from khroma + return khroma.rgba(r, g, b, opacity); +}; + const getStyles = (options: FlowChartStyleOptions) => `.label { font-family: ${options.fontFamily}; @@ -23,11 +38,11 @@ const getStyles = (options: FlowChartStyleOptions) => .cluster-label text { fill: ${options.titleColor}; } - .cluster-label span { + .cluster-label span,p { color: ${options.titleColor}; } - .label text,span { + .label text,span,p { fill: ${options.nodeTextColor || options.textColor}; color: ${options.nodeTextColor || options.textColor}; } @@ -41,6 +56,15 @@ const getStyles = (options: FlowChartStyleOptions) => stroke: ${options.nodeBorder}; stroke-width: 1px; } + .flowchart-label text { + text-anchor: middle; + } + // .flowchart-label .text-outer-tspan { + // text-anchor: middle; + // } + // .flowchart-label .text-inner-tspan { + // text-anchor: start; + // } .node .label { text-align: center; @@ -73,6 +97,12 @@ const getStyles = (options: FlowChartStyleOptions) => text-align: center; } + /* For html labels only */ + .labelBkg { + background-color: ${fade(options.edgeLabelBackground, 0.5)}; + // background-color: + } + .cluster rect { fill: ${options.clusterBkg}; stroke: ${options.clusterBorder}; @@ -83,7 +113,7 @@ const getStyles = (options: FlowChartStyleOptions) => fill: ${options.titleColor}; } - .cluster span { + .cluster span,p { color: ${options.titleColor}; } /* .cluster div { diff --git a/packages/mermaid/src/diagrams/gantt/ganttDb.js b/packages/mermaid/src/diagrams/gantt/ganttDb.js index a1c74dd62..3ff7955f8 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttDb.js +++ b/packages/mermaid/src/diagrams/gantt/ganttDb.js @@ -1,9 +1,12 @@ -import moment from 'moment-mini'; import { sanitizeUrl } from '@braintree/sanitize-url'; -import { log } from '../../logger'; -import * as configApi from '../../config'; -import utils from '../../utils'; -import mermaidAPI from '../../mermaidAPI'; +import dayjs from 'dayjs'; +import dayjsIsoWeek from 'dayjs/plugin/isoWeek.js'; +import dayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js'; +import dayjsAdvancedFormat from 'dayjs/plugin/advancedFormat.js'; +import { log } from '../../logger.js'; +import * as configApi from '../../config.js'; +import utils from '../../utils.js'; +import mermaidAPI from '../../mermaidAPI.js'; import { setAccTitle, @@ -13,7 +16,11 @@ import { clear as commonClear, setDiagramTitle, getDiagramTitle, -} from '../../commonDb'; +} from '../common/commonDb.js'; + +dayjs.extend(dayjsIsoWeek); +dayjs.extend(dayjsCustomParseFormat); +dayjs.extend(dayjsAdvancedFormat); let dateFormat = ''; let axisFormat = ''; @@ -25,10 +32,12 @@ let links = {}; let sections = []; let tasks = []; let currentSection = ''; +let displayMode = ''; const tags = ['active', 'done', 'crit', 'milestone']; let funs = []; let inclusiveEndDates = false; let topAxis = false; +let weekday = 'sunday'; // The serial order of the task in the script let lastOrder = 0; @@ -48,6 +57,7 @@ export const clear = function () { rawTasks = []; dateFormat = ''; axisFormat = ''; + displayMode = ''; tickInterval = undefined; todayMarker = ''; includes = []; @@ -57,6 +67,7 @@ export const clear = function () { lastOrder = 0; links = {}; commonClear(); + weekday = 'sunday'; }; export const setAxisFormat = function (txt) { @@ -103,6 +114,14 @@ export const topAxisEnabled = function () { return topAxis; }; +export const setDisplayMode = function (txt) { + displayMode = txt; +}; + +export const getDisplayMode = function () { + return displayMode; +}; + export const getDateFormat = function () { return dateFormat; }; @@ -136,11 +155,11 @@ export const getSections = function () { }; export const getTasks = function () { - let allItemsPricessed = compileTasks(); + let allItemsProcessed = compileTasks(); const maxDepth = 10; let iterationCount = 0; - while (!allItemsPricessed && iterationCount < maxDepth) { - allItemsPricessed = compileTasks(); + while (!allItemsProcessed && iterationCount < maxDepth) { + allItemsProcessed = compileTasks(); iterationCount++; } @@ -162,18 +181,66 @@ export const isInvalidDate = function (date, dateFormat, excludes, includes) { return excludes.includes(date.format(dateFormat.trim())); }; +export const setWeekday = function (txt) { + weekday = txt; +}; + +export const getWeekday = function () { + return weekday; +}; + +/** + * TODO: fully document what this function does and what types it accepts + * + * @param {object} task - The task to check. + * @param {string | Date} task.startTime - Might be a `Date` or a `string`. + * TODO: is this always a Date? + * @param {string | Date} task.endTime - Might be a `Date` or a `string`. + * TODO: is this always a Date? + * @param {string} dateFormat - Dayjs date format string. + * @param {*} excludes + * @param {*} includes + */ const checkTaskDates = function (task, dateFormat, excludes, includes) { if (!excludes.length || task.manualEndTime) { return; } - let startTime = moment(task.startTime, dateFormat, true); - startTime.add(1, 'd'); - let endTime = moment(task.endTime, dateFormat, true); - let renderEndTime = fixTaskDates(startTime, endTime, dateFormat, excludes, includes); - task.endTime = endTime.toDate(); + let startTime; + if (task.startTime instanceof Date) { + startTime = dayjs(task.startTime); + } else { + startTime = dayjs(task.startTime, dateFormat, true); + } + startTime = startTime.add(1, 'd'); + + let originalEndTime; + if (task.endTime instanceof Date) { + originalEndTime = dayjs(task.endTime); + } else { + originalEndTime = dayjs(task.endTime, dateFormat, true); + } + const [fixedEndTime, renderEndTime] = fixTaskDates( + startTime, + originalEndTime, + dateFormat, + excludes, + includes + ); + task.endTime = fixedEndTime.toDate(); task.renderEndTime = renderEndTime; }; +/** + * TODO: what does this function do? + * + * @param {dayjs.Dayjs} startTime - The start time. + * @param {dayjs.Dayjs} endTime - The original end time (will return a different end time if it's invalid). + * @param {string} dateFormat - Dayjs date format string. + * @param {*} excludes + * @param {*} includes + * @returns {[endTime: dayjs.Dayjs, renderEndTime: Date | null]} The new `endTime`, and the end time to render. + * `renderEndTime` may be `null` if `startTime` is newer than `endTime`. + */ const fixTaskDates = function (startTime, endTime, dateFormat, excludes, includes) { let invalid = false; let renderEndTime = null; @@ -183,11 +250,11 @@ const fixTaskDates = function (startTime, endTime, dateFormat, excludes, include } invalid = isInvalidDate(startTime, dateFormat, excludes, includes); if (invalid) { - endTime.add(1, 'd'); + endTime = endTime.add(1, 'd'); } - startTime.add(1, 'd'); + startTime = startTime.add(1, 'd'); } - return renderEndTime; + return [endTime, renderEndTime]; }; const getStartDate = function (prevTime, dateFormat, str) { @@ -223,14 +290,24 @@ const getStartDate = function (prevTime, dateFormat, str) { } // Check for actual date set - let mDate = moment(str, dateFormat.trim(), true); + let mDate = dayjs(str, dateFormat.trim(), true); if (mDate.isValid()) { return mDate.toDate(); } else { log.debug('Invalid date:' + str); log.debug('With date format:' + dateFormat.trim()); const d = new Date(str); - if (d === undefined || isNaN(d.getTime())) { + if ( + d === undefined || + isNaN(d.getTime()) || + // WebKit browsers can mis-parse invalid dates to be ridiculously + // huge numbers, e.g. new Date('202304') gets parsed as January 1, 202304. + // This can cause virtually infinite loops while rendering, so for the + // purposes of Gantt charts we'll just treat any date beyond 10,000 AD/BC as + // invalid. + d.getFullYear() < -10000 || + d.getFullYear() > 10000 + ) { throw new Error('Invalid date:' + str); } return d; @@ -238,11 +315,14 @@ const getStartDate = function (prevTime, dateFormat, str) { }; /** - * Parse a string as a moment duration. + * Parse a string into the args for `dayjs.add()`. * * The string have to be compound by a value and a shorthand duration unit. For example `5d` * represents 5 days. * + * Please be aware that 1 day may be 23 or 25 hours, if the user lives in an area + * that has daylight savings time (or even 23.5/24.5 hours in Lord Howe Island!) + * * Shorthand unit supported are: * * - `y` for years @@ -254,33 +334,36 @@ const getStartDate = function (prevTime, dateFormat, str) { * - `ms` for milliseconds * * @param {string} str - A string representing the duration. - * @returns {moment.Duration} A moment duration, including an invalid moment for invalid input - * string. + * @returns {[value: number, unit: dayjs.ManipulateType]} Arguments to pass to `dayjs.add()` */ const parseDuration = function (str) { const statement = /^(\d+(?:\.\d+)?)([Mdhmswy]|ms)$/.exec(str.trim()); if (statement !== null) { - return moment.duration(Number.parseFloat(statement[1]), statement[2]); + return [Number.parseFloat(statement[1]), statement[2]]; } - return moment.duration.invalid(); + // NaN means an invalid duration + return [NaN, 'ms']; }; const getEndDate = function (prevTime, dateFormat, str, inclusive = false) { str = str.trim(); // Check for actual date - let mDate = moment(str, dateFormat.trim(), true); + let mDate = dayjs(str, dateFormat.trim(), true); if (mDate.isValid()) { if (inclusive) { - mDate.add(1, 'd'); + mDate = mDate.add(1, 'd'); } return mDate.toDate(); } - const endTime = moment(prevTime); - const duration = parseDuration(str); - if (duration.isValid()) { - endTime.add(duration); + let endTime = dayjs(prevTime); + const [durationValue, durationUnit] = parseDuration(str); + if (!Number.isNaN(durationValue)) { + const newEndTime = endTime.add(durationValue, durationUnit); + if (newEndTime.isValid()) { + endTime = newEndTime; + } } return endTime.toDate(); }; @@ -346,7 +429,7 @@ const compileData = function (prevTask, dataStr) { if (endTimeData) { task.endTime = getEndDate(task.startTime, dateFormat, endTimeData, inclusiveEndDates); - task.manualEndTime = moment(endTimeData, 'YYYY-MM-DD', true).isValid(); + task.manualEndTime = dayjs(endTimeData, 'YYYY-MM-DD', true).isValid(); checkTaskDates(task, dateFormat, excludes, includes); } @@ -496,7 +579,7 @@ const compileTasks = function () { ); if (rawTasks[pos].endTime) { rawTasks[pos].processed = true; - rawTasks[pos].manualEndTime = moment( + rawTasks[pos].manualEndTime = dayjs( rawTasks[pos].raw.endTime.data, 'YYYY-MM-DD', true @@ -666,6 +749,8 @@ export default { getAccTitle, setDiagramTitle, getDiagramTitle, + setDisplayMode, + getDisplayMode, setAccDescription, getAccDescription, addSection, @@ -684,6 +769,8 @@ export default { bindFunctions, parseDuration, isInvalidDate, + setWeekday, + getWeekday, }; /** diff --git a/packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts b/packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts index 09df96f12..416368e8f 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts +++ b/packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts @@ -1,7 +1,7 @@ // @ts-nocheck TODO: Fix TS -import moment from 'moment-mini'; -import ganttDb from './ganttDb'; -import { convert } from '../../tests/util'; +import dayjs from 'dayjs'; +import ganttDb from './ganttDb.js'; +import { convert } from '../../tests/util.js'; describe('when using the ganttDb', function () { beforeEach(function () { @@ -9,7 +9,7 @@ describe('when using the ganttDb', function () { }); describe('when using duration', function () { - it.each([{ str: '1d', expected: moment.duration(1, 'd') }])( + it.each([{ str: '1d', expected: [1, 'd'] }])( 'should %s resulting in $o duration', ({ str, expected }) => { expect(ganttDb.parseDuration(str)).toEqual(expected); @@ -19,11 +19,11 @@ describe('when using the ganttDb', function () { it.each( convert` str | expected - ${'1d'} | ${moment.duration(1, 'd')} - ${'2w'} | ${moment.duration(2, 'w')} - ${'1ms'} | ${moment.duration(1, 'ms')} - ${'0.1s'} | ${moment.duration(100, 'ms')} - ${'1f'} | ${moment.duration.invalid()} + ${'1d'} | ${[1, 'd']} + ${'2w'} | ${[2, 'w']} + ${'1ms'} | ${[1, 'ms']} + ${'0.1s'} | ${[0.1, 's']} + ${'1f'} | ${[NaN, 'ms']} ` )('should $str resulting in $expected duration', ({ str, expected }) => { expect(ganttDb.parseDuration(str)).toEqual(expected); @@ -34,6 +34,7 @@ describe('when using the ganttDb', function () { beforeEach(function () { ganttDb.setDateFormat('YYYY-MM-DD'); ganttDb.enableInclusiveEndDates(); + ganttDb.setDisplayMode('compact'); ganttDb.setTodayMarker('off'); ganttDb.setExcludes('weekends 2019-02-06,friday'); ganttDb.addSection('weekends skip test'); @@ -53,6 +54,7 @@ describe('when using the ganttDb', function () { ${'getExcludes'} | ${[]} ${'getSections'} | ${[]} ${'endDatesAreInclusive'} | ${false} + ${'getDisplayMode'} | ${''} `)('should clear $fn', ({ fn, expected }) => { expect(ganttDb[fn]()).toEqual(expected); }); @@ -171,44 +173,44 @@ describe('when using the ganttDb', function () { const tasks = ganttDb.getTasks(); - expect(tasks[0].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate()); - expect(tasks[0].endTime).toEqual(moment('2019-02-04', 'YYYY-MM-DD').toDate()); - expect(tasks[0].renderEndTime).toEqual(moment('2019-02-02', 'YYYY-MM-DD').toDate()); + expect(tasks[0].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate()); + expect(tasks[0].endTime).toEqual(dayjs('2019-02-04', 'YYYY-MM-DD').toDate()); + expect(tasks[0].renderEndTime).toEqual(dayjs('2019-02-02', 'YYYY-MM-DD').toDate()); expect(tasks[0].id).toEqual('id1'); expect(tasks[0].task).toEqual('test1'); - expect(tasks[1].startTime).toEqual(moment('2019-02-04', 'YYYY-MM-DD').toDate()); - expect(tasks[1].endTime).toEqual(moment('2019-02-07', 'YYYY-MM-DD').toDate()); - expect(tasks[1].renderEndTime).toEqual(moment('2019-02-06', 'YYYY-MM-DD').toDate()); + expect(tasks[1].startTime).toEqual(dayjs('2019-02-04', 'YYYY-MM-DD').toDate()); + expect(tasks[1].endTime).toEqual(dayjs('2019-02-07', 'YYYY-MM-DD').toDate()); + expect(tasks[1].renderEndTime).toEqual(dayjs('2019-02-06', 'YYYY-MM-DD').toDate()); expect(tasks[1].id).toEqual('id2'); expect(tasks[1].task).toEqual('test2'); - expect(tasks[2].startTime).toEqual(moment('2019-02-07', 'YYYY-MM-DD').toDate()); - expect(tasks[2].endTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate()); - expect(tasks[2].renderEndTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate()); + expect(tasks[2].startTime).toEqual(dayjs('2019-02-07', 'YYYY-MM-DD').toDate()); + expect(tasks[2].endTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate()); + expect(tasks[2].renderEndTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate()); expect(tasks[2].id).toEqual('id3'); expect(tasks[2].task).toEqual('test3'); - expect(tasks[3].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate()); - expect(tasks[3].endTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate()); + expect(tasks[3].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate()); + expect(tasks[3].endTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate()); expect(tasks[3].renderEndTime).toBeNull(); // Fixed end expect(tasks[3].id).toEqual('id4'); expect(tasks[3].task).toEqual('test4'); - expect(tasks[4].startTime).toEqual(moment('2019-02-20', 'YYYY-MM-DD').toDate()); - expect(tasks[4].endTime).toEqual(moment('2019-02-21', 'YYYY-MM-DD').toDate()); - expect(tasks[4].renderEndTime).toEqual(moment('2019-02-21', 'YYYY-MM-DD').toDate()); + expect(tasks[4].startTime).toEqual(dayjs('2019-02-20', 'YYYY-MM-DD').toDate()); + expect(tasks[4].endTime).toEqual(dayjs('2019-02-21', 'YYYY-MM-DD').toDate()); + expect(tasks[4].renderEndTime).toEqual(dayjs('2019-02-21', 'YYYY-MM-DD').toDate()); expect(tasks[4].id).toEqual('id5'); expect(tasks[4].task).toEqual('test5'); - expect(tasks[5].startTime).toEqual(moment('2019-02-13', 'YYYY-MM-DD').toDate()); - expect(tasks[5].endTime).toEqual(moment('2019-02-18', 'YYYY-MM-DD').toDate()); - expect(tasks[5].renderEndTime).toEqual(moment('2019-02-15', 'YYYY-MM-DD').toDate()); + expect(tasks[5].startTime).toEqual(dayjs('2019-02-13', 'YYYY-MM-DD').toDate()); + expect(tasks[5].endTime).toEqual(dayjs('2019-02-18', 'YYYY-MM-DD').toDate()); + expect(tasks[5].renderEndTime).toEqual(dayjs('2019-02-15', 'YYYY-MM-DD').toDate()); expect(tasks[5].id).toEqual('id6'); expect(tasks[5].task).toEqual('test6'); - expect(tasks[6].startTime).toEqual(moment('2019-02-18', 'YYYY-MM-DD').toDate()); - expect(tasks[6].endTime).toEqual(moment('2019-02-19', 'YYYY-MM-DD').toDate()); + expect(tasks[6].startTime).toEqual(dayjs('2019-02-18', 'YYYY-MM-DD').toDate()); + expect(tasks[6].endTime).toEqual(dayjs('2019-02-19', 'YYYY-MM-DD').toDate()); expect(tasks[6].id).toEqual('id7'); expect(tasks[6].task).toEqual('test7'); }); @@ -243,109 +245,103 @@ describe('when using the ganttDb', function () { const tasks = ganttDb.getTasks(); // Section - A section - expect(tasks[0].startTime).toEqual(moment('2014-01-06', 'YYYY-MM-DD').toDate()); - expect(tasks[0].endTime).toEqual(moment('2014-01-08', 'YYYY-MM-DD').toDate()); + expect(tasks[0].startTime).toEqual(dayjs('2014-01-06', 'YYYY-MM-DD').toDate()); + expect(tasks[0].endTime).toEqual(dayjs('2014-01-08', 'YYYY-MM-DD').toDate()); expect(tasks[0].order).toEqual(0); expect(tasks[0].id).toEqual('des1'); expect(tasks[0].task).toEqual('Completed task'); - expect(tasks[1].startTime).toEqual(moment('2014-01-09', 'YYYY-MM-DD').toDate()); - expect(tasks[1].endTime).toEqual(moment('2014-01-12', 'YYYY-MM-DD').toDate()); + expect(tasks[1].startTime).toEqual(dayjs('2014-01-09', 'YYYY-MM-DD').toDate()); + expect(tasks[1].endTime).toEqual(dayjs('2014-01-12', 'YYYY-MM-DD').toDate()); expect(tasks[1].order).toEqual(1); expect(tasks[1].id).toEqual('des2'); expect(tasks[1].task).toEqual('Active task'); - expect(tasks[2].startTime).toEqual(moment('2014-01-12', 'YYYY-MM-DD').toDate()); - expect(tasks[2].endTime).toEqual(moment('2014-01-17', 'YYYY-MM-DD').toDate()); + expect(tasks[2].startTime).toEqual(dayjs('2014-01-12', 'YYYY-MM-DD').toDate()); + expect(tasks[2].endTime).toEqual(dayjs('2014-01-17', 'YYYY-MM-DD').toDate()); expect(tasks[2].order).toEqual(2); expect(tasks[2].id).toEqual('des3'); expect(tasks[2].task).toEqual('Future task'); - expect(tasks[3].startTime).toEqual(moment('2014-01-17', 'YYYY-MM-DD').toDate()); - expect(tasks[3].endTime).toEqual(moment('2014-01-22', 'YYYY-MM-DD').toDate()); + expect(tasks[3].startTime).toEqual(dayjs('2014-01-17', 'YYYY-MM-DD').toDate()); + expect(tasks[3].endTime).toEqual(dayjs('2014-01-22', 'YYYY-MM-DD').toDate()); expect(tasks[3].order).toEqual(3); expect(tasks[3].id).toEqual('des4'); expect(tasks[3].task).toEqual('Future task2'); // Section - Critical tasks - expect(tasks[4].startTime).toEqual(moment('2014-01-06', 'YYYY-MM-DD').toDate()); - expect(tasks[4].endTime).toEqual(moment('2014-01-07', 'YYYY-MM-DD').toDate()); + expect(tasks[4].startTime).toEqual(dayjs('2014-01-06', 'YYYY-MM-DD').toDate()); + expect(tasks[4].endTime).toEqual(dayjs('2014-01-07', 'YYYY-MM-DD').toDate()); expect(tasks[4].order).toEqual(4); expect(tasks[4].id).toEqual('task1'); expect(tasks[4].task).toEqual('Completed task in the critical line'); - expect(tasks[5].startTime).toEqual(moment('2014-01-08', 'YYYY-MM-DD').toDate()); - expect(tasks[5].endTime).toEqual(moment('2014-01-10', 'YYYY-MM-DD').toDate()); + expect(tasks[5].startTime).toEqual(dayjs('2014-01-08', 'YYYY-MM-DD').toDate()); + expect(tasks[5].endTime).toEqual(dayjs('2014-01-10', 'YYYY-MM-DD').toDate()); expect(tasks[5].order).toEqual(5); expect(tasks[5].id).toEqual('task2'); expect(tasks[5].task).toEqual('Implement parser and jison'); - expect(tasks[6].startTime).toEqual(moment('2014-01-10', 'YYYY-MM-DD').toDate()); - expect(tasks[6].endTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[6].startTime).toEqual(dayjs('2014-01-10', 'YYYY-MM-DD').toDate()); + expect(tasks[6].endTime).toEqual(dayjs('2014-01-13', 'YYYY-MM-DD').toDate()); expect(tasks[6].order).toEqual(6); expect(tasks[6].id).toEqual('task3'); expect(tasks[6].task).toEqual('Create tests for parser'); - expect(tasks[7].startTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); - expect(tasks[7].endTime).toEqual(moment('2014-01-18', 'YYYY-MM-DD').toDate()); + expect(tasks[7].startTime).toEqual(dayjs('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[7].endTime).toEqual(dayjs('2014-01-18', 'YYYY-MM-DD').toDate()); expect(tasks[7].order).toEqual(7); expect(tasks[7].id).toEqual('task4'); expect(tasks[7].task).toEqual('Future task in critical line'); - expect(tasks[8].startTime).toEqual(moment('2014-01-18', 'YYYY-MM-DD').toDate()); - expect(tasks[8].endTime).toEqual(moment('2014-01-20', 'YYYY-MM-DD').toDate()); + expect(tasks[8].startTime).toEqual(dayjs('2014-01-18', 'YYYY-MM-DD').toDate()); + expect(tasks[8].endTime).toEqual(dayjs('2014-01-20', 'YYYY-MM-DD').toDate()); expect(tasks[8].order).toEqual(8); expect(tasks[8].id).toEqual('task5'); expect(tasks[8].task).toEqual('Create tests for renderer'); - expect(tasks[9].startTime).toEqual(moment('2014-01-20', 'YYYY-MM-DD').toDate()); - expect(tasks[9].endTime).toEqual(moment('2014-01-21', 'YYYY-MM-DD').toDate()); + expect(tasks[9].startTime).toEqual(dayjs('2014-01-20', 'YYYY-MM-DD').toDate()); + expect(tasks[9].endTime).toEqual(dayjs('2014-01-21', 'YYYY-MM-DD').toDate()); expect(tasks[9].order).toEqual(9); expect(tasks[9].id).toEqual('task6'); expect(tasks[9].task).toEqual('Add to mermaid'); // Section - Documentation - expect(tasks[10].startTime).toEqual(moment('2014-01-08', 'YYYY-MM-DD').toDate()); - expect(tasks[10].endTime).toEqual(moment('2014-01-11', 'YYYY-MM-DD').toDate()); + expect(tasks[10].startTime).toEqual(dayjs('2014-01-08', 'YYYY-MM-DD').toDate()); + expect(tasks[10].endTime).toEqual(dayjs('2014-01-11', 'YYYY-MM-DD').toDate()); expect(tasks[10].order).toEqual(10); expect(tasks[10].id).toEqual('a1'); expect(tasks[10].task).toEqual('Describe gantt syntax'); - expect(tasks[11].startTime).toEqual(moment('2014-01-11', 'YYYY-MM-DD').toDate()); - expect(tasks[11].endTime).toEqual( - moment('2014-01-11 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate() - ); + expect(tasks[11].startTime).toEqual(dayjs('2014-01-11', 'YYYY-MM-DD').toDate()); + expect(tasks[11].endTime).toEqual(dayjs('2014-01-11 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()); expect(tasks[11].order).toEqual(11); expect(tasks[11].id).toEqual('task7'); expect(tasks[11].task).toEqual('Add gantt diagram to demo page'); - expect(tasks[12].startTime).toEqual(moment('2014-01-11', 'YYYY-MM-DD').toDate()); - expect(tasks[12].endTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[12].startTime).toEqual(dayjs('2014-01-11', 'YYYY-MM-DD').toDate()); + expect(tasks[12].endTime).toEqual(dayjs('2014-01-13', 'YYYY-MM-DD').toDate()); expect(tasks[12].order).toEqual(12); expect(tasks[12].id).toEqual('doc1'); expect(tasks[12].task).toEqual('Add another diagram to demo page'); // Section - Last section - expect(tasks[13].startTime).toEqual(moment('2014-01-13', 'YYYY-MM-DD').toDate()); - expect(tasks[13].endTime).toEqual(moment('2014-01-16', 'YYYY-MM-DD').toDate()); + expect(tasks[13].startTime).toEqual(dayjs('2014-01-13', 'YYYY-MM-DD').toDate()); + expect(tasks[13].endTime).toEqual(dayjs('2014-01-16', 'YYYY-MM-DD').toDate()); expect(tasks[13].order).toEqual(13); expect(tasks[13].id).toEqual('task8'); expect(tasks[13].task).toEqual('Describe gantt syntax'); - expect(tasks[14].startTime).toEqual(moment('2014-01-16', 'YYYY-MM-DD').toDate()); - expect(tasks[14].endTime).toEqual( - moment('2014-01-16 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate() - ); + expect(tasks[14].startTime).toEqual(dayjs('2014-01-16', 'YYYY-MM-DD').toDate()); + expect(tasks[14].endTime).toEqual(dayjs('2014-01-16 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()); expect(tasks[14].order).toEqual(14); expect(tasks[14].id).toEqual('task9'); expect(tasks[14].task).toEqual('Add gantt diagram to demo page'); expect(tasks[15].startTime).toEqual( - moment('2014-01-16 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate() - ); - expect(tasks[15].endTime).toEqual( - moment('2014-01-18 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate() + dayjs('2014-01-16 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate() ); + expect(tasks[15].endTime).toEqual(dayjs('2014-01-18 20:00:00', 'YYYY-MM-DD HH:mm:ss').toDate()); expect(tasks[15].order).toEqual(15); expect(tasks[15].id).toEqual('task10'); expect(tasks[15].task).toEqual('Add another diagram to demo page'); @@ -358,19 +354,53 @@ describe('when using the ganttDb', function () { ganttDb.addTask('test2', 'id2,after id1,20d'); const tasks = ganttDb.getTasks(); - expect(tasks[0].startTime).toEqual(moment('2019-09-30', 'YYYY-MM-DD').toDate()); - expect(tasks[0].endTime).toEqual(moment('2019-10-11', 'YYYY-MM-DD').toDate()); + expect(tasks[0].startTime).toEqual(dayjs('2019-09-30', 'YYYY-MM-DD').toDate()); + expect(tasks[0].endTime).toEqual(dayjs('2019-10-11', 'YYYY-MM-DD').toDate()); expect(tasks[1].renderEndTime).toBeNull(); // Fixed end expect(tasks[0].id).toEqual('id1'); expect(tasks[0].task).toEqual('test1'); - expect(tasks[1].startTime).toEqual(moment('2019-10-11', 'YYYY-MM-DD').toDate()); - expect(tasks[1].endTime).toEqual(moment('2019-10-31', 'YYYY-MM-DD').toDate()); + expect(tasks[1].startTime).toEqual(dayjs('2019-10-11', 'YYYY-MM-DD').toDate()); + expect(tasks[1].endTime).toEqual(dayjs('2019-10-31', 'YYYY-MM-DD').toDate()); expect(tasks[1].renderEndTime).toBeNull(); // Fixed end expect(tasks[1].id).toEqual('id2'); expect(tasks[1].task).toEqual('test2'); }); + /** + * Unfortunately, Vitest has no way of modifying the timezone at runtime, so + * in order to test this, please run this test with + * + * ```bash + * TZ='America/Los_Angeles' pnpm exec vitest run ganttDb + * ``` + */ + /* c8 ignore start */ // tell code-coverage to ignore this block of code + describe.skipIf(process.env.TZ != 'America/Los_Angeles')( + 'when using a timezone with daylight savings (only run if TZ="America/Los_Angeles")', + () => { + it('should add 1 day even on days with 25 hours', function () { + const startTime = new Date(2020, 10, 1); + expect(startTime.toISOString()).toBe('2020-11-01T07:00:00.000Z'); + + const endTime = new Date(2020, 10, 2); + expect(endTime.toISOString()).toBe('2020-11-02T08:00:00.000Z'); + + ganttDb.setDateFormat('YYYY-MM-DD'); + ganttDb.addSection('Task handles 25 hour day'); + ganttDb.addTask('daylight savings day', 'id1,2020-11-01,1d'); + const tasks = ganttDb.getTasks(); + expect(tasks[0].startTime).toEqual(startTime); + expect(tasks[0].endTime).toEqual(endTime); + + // In USA states that use daylight savings, 2020-11-01 had 25 hours + const millisecondsIn25Hours = 25 * 60 * 60 * 1000; + expect(endTime - startTime).toEqual(millisecondsIn25Hours); + }); + } + ); + /* c8 ignore stop */ + describe('when setting inclusive end dates', function () { beforeEach(function () { ganttDb.setDateFormat('YYYY-MM-DD'); @@ -380,13 +410,13 @@ describe('when using the ganttDb', function () { }); it('should automatically add one day to all end dates', function () { const tasks = ganttDb.getTasks(); - expect(tasks[0].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate()); - expect(tasks[0].endTime).toEqual(moment('2019-02-02', 'YYYY-MM-DD').toDate()); + expect(tasks[0].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate()); + expect(tasks[0].endTime).toEqual(dayjs('2019-02-02', 'YYYY-MM-DD').toDate()); expect(tasks[0].id).toEqual('id1'); expect(tasks[0].task).toEqual('test1'); - expect(tasks[1].startTime).toEqual(moment('2019-02-01', 'YYYY-MM-DD').toDate()); - expect(tasks[1].endTime).toEqual(moment('2019-02-04', 'YYYY-MM-DD').toDate()); + expect(tasks[1].startTime).toEqual(dayjs('2019-02-01', 'YYYY-MM-DD').toDate()); + expect(tasks[1].endTime).toEqual(dayjs('2019-02-04', 'YYYY-MM-DD').toDate()); expect(tasks[1].renderEndTime).toBeNull(); // Fixed end expect(tasks[1].manualEndTime).toBeTruthy(); expect(tasks[1].id).toEqual('id2'); @@ -402,4 +432,10 @@ describe('when using the ganttDb', function () { ganttDb.setTodayMarker(expected); expect(ganttDb.getTodayMarker()).toEqual(expected); }); + + it('should reject dates with ridiculous years', function () { + ganttDb.setDateFormat('YYYYMMDD'); + ganttDb.addTask('test1', 'id1,202304,1d'); + expect(() => ganttDb.getTasks()).toThrowError('Invalid date:202304'); + }); }); diff --git a/packages/mermaid/src/diagrams/gantt/ganttDetector.ts b/packages/mermaid/src/diagrams/gantt/ganttDetector.ts index 5de167010..e2f2a9784 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttDetector.ts +++ b/packages/mermaid/src/diagrams/gantt/ganttDetector.ts @@ -1,5 +1,24 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const ganttDetector: DiagramDetector = (txt) => { - return txt.match(/^\s*gantt/) !== null; +const id = 'gantt'; + +const detector: DiagramDetector = (txt) => { + return /^\s*gantt/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./ganttDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/gantt/ganttDiagram.ts b/packages/mermaid/src/diagrams/gantt/ganttDiagram.ts new file mode 100644 index 000000000..a9ebfdb93 --- /dev/null +++ b/packages/mermaid/src/diagrams/gantt/ganttDiagram.ts @@ -0,0 +1,13 @@ +// @ts-ignore: JISON doesn't support types +import ganttParser from './parser/gantt.jison'; +import ganttDb from './ganttDb.js'; +import ganttRenderer from './ganttRenderer.js'; +import ganttStyles from './styles.js'; +import type { DiagramDefinition } from '../../diagram-api/types.js'; + +export const diagram: DiagramDefinition = { + parser: ganttParser, + db: ganttDb, + renderer: ganttRenderer, + styles: ganttStyles, +}; diff --git a/packages/mermaid/src/diagrams/gantt/ganttRenderer.js b/packages/mermaid/src/diagrams/gantt/ganttRenderer.js index faec35a86..935ecc928 100644 --- a/packages/mermaid/src/diagrams/gantt/ganttRenderer.js +++ b/packages/mermaid/src/diagrams/gantt/ganttRenderer.js @@ -1,5 +1,5 @@ -import moment from 'moment-mini'; -import { log } from '../../logger'; +import dayjs from 'dayjs'; +import { log } from '../../logger.js'; import { select, scaleTime, @@ -10,25 +10,76 @@ import { axisBottom, axisTop, timeFormat, + timeMillisecond, + timeSecond, timeMinute, timeHour, timeDay, - timeWeek, + timeMonday, + timeTuesday, + timeWednesday, + timeThursday, + timeFriday, + timeSaturday, + timeSunday, timeMonth, } from 'd3'; -import common from '../common/common'; -import { getConfig } from '../../config'; -import { configureSvgSize } from '../../setupGraphViewbox'; +import common from '../common/common.js'; +import { getConfig } from '../../config.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; export const setConf = function () { log.debug('Something is calling, setConf, remove the call'); }; +/** + * This will map any day of the week that can be set in the `weekday` option to + * the corresponding d3-time function that is used to calculate the ticks. + */ +const mapWeekdayToTimeFunction = { + monday: timeMonday, + tuesday: timeTuesday, + wednesday: timeWednesday, + thursday: timeThursday, + friday: timeFriday, + saturday: timeSaturday, + sunday: timeSunday, +}; + +/** + * For this issue: + * https://github.com/mermaid-js/mermaid/issues/1618 + * + * Finds the number of intersections between tasks that happen at any point in time. + * Used to figure out how many rows are needed to display the tasks when the display + * mode is set to 'compact'. + * + * @param tasks + * @param orderOffset + */ +const getMaxIntersections = (tasks, orderOffset) => { + let timeline = [...tasks].map(() => -Infinity); + let sorted = [...tasks].sort((a, b) => a.startTime - b.startTime || a.order - b.order); + let maxIntersections = 0; + for (const element of sorted) { + for (let j = 0; j < timeline.length; j++) { + if (element.startTime >= timeline[j]) { + timeline[j] = element.endTime; + element.order = j + orderOffset; + if (j > maxIntersections) { + maxIntersections = j; + } + break; + } + } + } + + return maxIntersections; +}; + let w; export const draw = function (text, id, version, diagObj) { const conf = getConfig().gantt; - // diagObj.db.clear(); - // parser.parse(text); const securityLevel = getConfig().securityLevel; // Handle root and Document for when rendering in sandbox mode @@ -56,7 +107,40 @@ export const draw = function (text, id, version, diagObj) { const taskArray = diagObj.db.getTasks(); // Set height based on number of tasks - const h = taskArray.length * (conf.barHeight + conf.barGap) + 2 * conf.topPadding; + + let categories = []; + + for (const element of taskArray) { + categories.push(element.type); + } + + categories = checkUnique(categories); + const categoryHeights = {}; + + let h = 2 * conf.topPadding; + if (diagObj.db.getDisplayMode() === 'compact' || conf.displayMode === 'compact') { + const categoryElements = {}; + for (const element of taskArray) { + if (categoryElements[element.section] === undefined) { + categoryElements[element.section] = [element]; + } else { + categoryElements[element.section].push(element); + } + } + + let intersections = 0; + for (const category of Object.keys(categoryElements)) { + const categoryHeight = getMaxIntersections(categoryElements[category], intersections) + 1; + intersections += categoryHeight; + h += categoryHeight * (conf.barHeight + conf.barGap); + categoryHeights[category] = categoryHeight; + } + } else { + h += taskArray.length * (conf.barHeight + conf.barGap); + for (const category of categories) { + categoryHeights[category] = taskArray.filter((task) => task.type === category).length; + } + } // Set viewBox elem.setAttribute('viewBox', '0 0 ' + w + ' ' + h); @@ -74,16 +158,6 @@ export const draw = function (text, id, version, diagObj) { ]) .rangeRound([0, w - conf.leftPadding - conf.rightPadding]); - let categories = []; - - for (const element of taskArray) { - categories.push(element.type); - } - - const catsUnfiltered = categories; // for vert labels - - categories = checkUnique(categories); - /** * @param a * @param b @@ -157,11 +231,15 @@ export const draw = function (text, id, version, diagObj) { * @param w */ function drawRects(theArray, theGap, theTopPad, theSidePad, theBarHeight, theColorScale, w) { + // Get unique task orders. Required to draw the background rects when display mode is compact. + const uniqueTaskOrderIds = [...new Set(theArray.map((item) => item.order))]; + const uniqueTasks = uniqueTaskOrderIds.map((id) => theArray.find((item) => item.order === id)); + // Draw background rects covering the entire width of the graph, these form the section rows. svg .append('g') .selectAll('rect') - .data(theArray) + .data(uniqueTasks) .enter() .append('rect') .attr('x', 0) @@ -435,16 +513,16 @@ export const draw = function (text, id, version, diagObj) { const excludeRanges = []; let range = null; - let d = moment(minTime); + let d = dayjs(minTime); while (d.valueOf() <= maxTime) { if (diagObj.db.isInvalidDate(d, dateFormat, excludes, includes)) { if (!range) { range = { - start: d.clone(), - end: d.clone(), + start: d, + end: d, }; } else { - range.end = d.clone(); + range.end = d; } } else { if (range) { @@ -452,7 +530,7 @@ export const draw = function (text, id, version, diagObj) { range = null; } } - d.add(1, 'd'); + d = d.add(1, 'd'); } const rectangles = svg.append('g').selectAll('rect').data(excludeRanges).enter(); @@ -467,7 +545,7 @@ export const draw = function (text, id, version, diagObj) { }) .attr('y', conf.gridLineStartPadding) .attr('width', function (d) { - const renderEnd = d.end.clone().add(1, 'day'); + const renderEnd = d.end.add(1, 'day'); return timeScale(renderEnd) - timeScale(d.start); }) .attr('height', h - theTopPad - conf.gridLineStartPadding) @@ -497,7 +575,7 @@ export const draw = function (text, id, version, diagObj) { .tickSize(-h + theTopPad + conf.gridLineStartPadding) .tickFormat(timeFormat(diagObj.db.getAxisFormat() || conf.axisFormat || '%Y-%m-%d')); - const reTickInterval = /^([1-9]\d*)(minute|hour|day|week|month)$/; + const reTickInterval = /^([1-9]\d*)(millisecond|second|minute|hour|day|week|month)$/; const resultTickInterval = reTickInterval.exec( diagObj.db.getTickInterval() || conf.tickInterval ); @@ -505,7 +583,15 @@ export const draw = function (text, id, version, diagObj) { if (resultTickInterval !== null) { const every = resultTickInterval[1]; const interval = resultTickInterval[2]; + const weekday = diagObj.db.getWeekday() || conf.weekday; + switch (interval) { + case 'millisecond': + bottomXAxis.ticks(timeMillisecond.every(every)); + break; + case 'second': + bottomXAxis.ticks(timeSecond.every(every)); + break; case 'minute': bottomXAxis.ticks(timeMinute.every(every)); break; @@ -516,7 +602,7 @@ export const draw = function (text, id, version, diagObj) { bottomXAxis.ticks(timeDay.every(every)); break; case 'week': - bottomXAxis.ticks(timeWeek.every(every)); + bottomXAxis.ticks(mapWeekdayToTimeFunction[weekday].every(every)); break; case 'month': bottomXAxis.ticks(timeMonth.every(every)); @@ -544,7 +630,15 @@ export const draw = function (text, id, version, diagObj) { if (resultTickInterval !== null) { const every = resultTickInterval[1]; const interval = resultTickInterval[2]; + const weekday = diagObj.db.getWeekday() || conf.weekday; + switch (interval) { + case 'millisecond': + topXAxis.ticks(timeMillisecond.every(every)); + break; + case 'second': + topXAxis.ticks(timeSecond.every(every)); + break; case 'minute': topXAxis.ticks(timeMinute.every(every)); break; @@ -555,7 +649,7 @@ export const draw = function (text, id, version, diagObj) { topXAxis.ticks(timeDay.every(every)); break; case 'week': - topXAxis.ticks(timeWeek.every(every)); + topXAxis.ticks(mapWeekdayToTimeFunction[weekday].every(every)); break; case 'month': topXAxis.ticks(timeMonth.every(every)); @@ -582,12 +676,9 @@ export const draw = function (text, id, version, diagObj) { * @param theTopPad */ function vertLabels(theGap, theTopPad) { - const numOccurances = []; let prevGap = 0; - for (const [i, category] of categories.entries()) { - numOccurances[i] = [category, getCount(category, catsUnfiltered)]; - } + const numOccurances = Object.keys(categoryHeights).map((d) => [d, categoryHeights[d]]); svg .append('g') // without doing this, impossible to put grid lines behind text @@ -625,7 +716,6 @@ export const draw = function (text, id, version, diagObj) { } }) .attr('font-size', conf.sectionFontSize) - .attr('font-size', conf.sectionFontSize) .attr('class', function (d) { for (const [i, category] of categories.entries()) { if (d[0] === category) { @@ -682,31 +772,6 @@ export const draw = function (text, id, version, diagObj) { } return result; } - - /** - * From this stack exchange question: - * http://stackoverflow.com/questions/14227981/count-how-many-strings-in-an-array-have-duplicates-in-the-same-array - * - * @param arr - */ - function getCounts(arr) { - let i = arr.length; // const to loop over - const obj = {}; // obj to store results - while (i) { - obj[arr[--i]] = (obj[arr[i]] || 0) + 1; // count occurrences - } - return obj; - } - - /** - * Get specific from everything - * - * @param word - * @param arr - */ - function getCount(word, arr) { - return getCounts(arr)[word] || 0; - } }; export default { diff --git a/packages/mermaid/src/diagrams/gantt/parser/gantt.jison b/packages/mermaid/src/diagrams/gantt/parser/gantt.jison index 2223aa378..f7fd40c1b 100644 --- a/packages/mermaid/src/diagrams/gantt/parser/gantt.jison +++ b/packages/mermaid/src/diagrams/gantt/parser/gantt.jison @@ -77,24 +77,31 @@ that id. [\s\n] this.popState(); [^\s\n]* return 'click'; -"gantt" return 'gantt'; -"dateFormat"\s[^#\n;]+ return 'dateFormat'; -"inclusiveEndDates" return 'inclusiveEndDates'; -"topAxis" return 'topAxis'; -"axisFormat"\s[^#\n;]+ return 'axisFormat'; -"tickInterval"\s[^#\n;]+ return 'tickInterval'; -"includes"\s[^#\n;]+ return 'includes'; -"excludes"\s[^#\n;]+ return 'excludes'; -"todayMarker"\s[^\n;]+ return 'todayMarker'; -\d\d\d\d"-"\d\d"-"\d\d return 'date'; -"title"\s[^#\n;]+ return 'title'; -"accDescription"\s[^#\n;]+ return 'accDescription' -"section"\s[^#:\n;]+ return 'section'; -[^#:\n;]+ return 'taskTxt'; -":"[^#\n;]+ return 'taskData'; -":" return ':'; -<> return 'EOF'; -. return 'INVALID'; +"gantt" return 'gantt'; +"dateFormat"\s[^#\n;]+ return 'dateFormat'; +"inclusiveEndDates" return 'inclusiveEndDates'; +"topAxis" return 'topAxis'; +"axisFormat"\s[^#\n;]+ return 'axisFormat'; +"tickInterval"\s[^#\n;]+ return 'tickInterval'; +"includes"\s[^#\n;]+ return 'includes'; +"excludes"\s[^#\n;]+ return 'excludes'; +"todayMarker"\s[^\n;]+ return 'todayMarker'; +weekday\s+monday return 'weekday_monday' +weekday\s+tuesday return 'weekday_tuesday' +weekday\s+wednesday return 'weekday_wednesday' +weekday\s+thursday return 'weekday_thursday' +weekday\s+friday return 'weekday_friday' +weekday\s+saturday return 'weekday_saturday' +weekday\s+sunday return 'weekday_sunday' +\d\d\d\d"-"\d\d"-"\d\d return 'date'; +"title"\s[^#\n;]+ return 'title'; +"accDescription"\s[^#\n;]+ return 'accDescription' +"section"\s[^#:\n;]+ return 'section'; +[^#:\n;]+ return 'taskTxt'; +":"[^#\n;]+ return 'taskData'; +":" return ':'; +<> return 'EOF'; +. return 'INVALID'; /lex @@ -121,6 +128,16 @@ line | EOF { $$=[];} ; +weekday + : weekday_monday { yy.setWeekday("monday");} + | weekday_tuesday { yy.setWeekday("tuesday");} + | weekday_wednesday { yy.setWeekday("wednesday");} + | weekday_thursday { yy.setWeekday("thursday");} + | weekday_friday { yy.setWeekday("friday");} + | weekday_saturday { yy.setWeekday("saturday");} + | weekday_sunday { yy.setWeekday("sunday");} + ; + statement : dateFormat {yy.setDateFormat($1.substr(11));$$=$1.substr(11);} | inclusiveEndDates {yy.enableInclusiveEndDates();$$=$1.substr(18);} @@ -130,10 +147,12 @@ statement | excludes {yy.setExcludes($1.substr(9));$$=$1.substr(9);} | includes {yy.setIncludes($1.substr(9));$$=$1.substr(9);} | todayMarker {yy.setTodayMarker($1.substr(12));$$=$1.substr(12);} + | weekday | title {yy.setDiagramTitle($1.substr(6));$$=$1.substr(6);} - | acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); } - | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } - | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } | section {yy.addSection($1.substr(8));$$=$1.substr(8);} + | acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); } + | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } + | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } + | section { yy.addSection($1.substr(8));$$=$1.substr(8); } | clickStatement | taskTxt taskData {yy.addTask($1,$2);$$='task';} | directive diff --git a/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js b/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js index 9a1401cad..e7ce1ffa4 100644 --- a/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js +++ b/packages/mermaid/src/diagrams/gantt/parser/gantt.spec.js @@ -1,6 +1,6 @@ -import { parser } from './gantt'; -import ganttDb from '../ganttDb'; -import { convert } from '../../../tests/util'; +import { parser } from './gantt.jison'; +import ganttDb from '../ganttDb.js'; +import { convert } from '../../../tests/util.js'; import { vi } from 'vitest'; const spyOn = vi.spyOn; const parserFnConstructor = (str) => { @@ -180,4 +180,12 @@ row2`; expect(ganttDb.getAccTitle()).toBe(expectedTitle); expect(ganttDb.getAccDescription()).toBe(expectedAccDescription); }); + + it.each(['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'])( + 'should allow for setting the starting weekday to %s for tick interval', + (day) => { + parser.parse(`gantt\nweekday ${day}`); + expect(ganttDb.getWeekday()).toBe(day); + } + ); }); diff --git a/packages/mermaid/src/diagrams/git/gitGraphAst.js b/packages/mermaid/src/diagrams/git/gitGraphAst.js index dded48efa..dc9c32da9 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphAst.js +++ b/packages/mermaid/src/diagrams/git/gitGraphAst.js @@ -1,9 +1,9 @@ -import { log } from '../../logger'; -import { random } from '../../utils'; -import mermaidAPI from '../../mermaidAPI'; -import * as configApi from '../../config'; -import { getConfig } from '../../config'; -import common from '../common/common'; +import { log } from '../../logger.js'; +import { random } from '../../utils.js'; +import mermaidAPI from '../../mermaidAPI.js'; +import * as configApi from '../../config.js'; +import { getConfig } from '../../config.js'; +import common from '../common/common.js'; import { setAccTitle, getAccTitle, @@ -12,7 +12,7 @@ import { clear as commonClear, setDiagramTitle, getDiagramTitle, -} from '../../commonDb'; +} from '../common/commonDb.js'; let mainBranchName = getConfig().gitGraph.mainBranchName; let mainBranchOrder = getConfig().gitGraph.mainBranchOrder; diff --git a/packages/mermaid/src/diagrams/git/gitGraphDetector.ts b/packages/mermaid/src/diagrams/git/gitGraphDetector.ts index f890501a5..ded434a65 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphDetector.ts +++ b/packages/mermaid/src/diagrams/git/gitGraphDetector.ts @@ -1,5 +1,21 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { DiagramDetector, DiagramLoader } from '../../diagram-api/types.js'; +import type { ExternalDiagramDefinition } from '../../diagram-api/types.js'; -export const gitGraphDetector: DiagramDetector = (txt) => { - return txt.match(/^\s*gitGraph/) !== null; +const id = 'gitGraph'; + +const detector: DiagramDetector = (txt) => { + return /^\s*gitGraph/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./gitGraphDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/git/gitGraphDiagram.ts b/packages/mermaid/src/diagrams/git/gitGraphDiagram.ts new file mode 100644 index 000000000..2a9efdb59 --- /dev/null +++ b/packages/mermaid/src/diagrams/git/gitGraphDiagram.ts @@ -0,0 +1,13 @@ +// @ts-ignore: JISON doesn't support types +import gitGraphParser from './parser/gitGraph.jison'; +import gitGraphDb from './gitGraphAst.js'; +import gitGraphRenderer from './gitGraphRenderer.js'; +import gitGraphStyles from './styles.js'; +import type { DiagramDefinition } from '../../diagram-api/types.js'; + +export const diagram: DiagramDefinition = { + parser: gitGraphParser, + db: gitGraphDb, + renderer: gitGraphRenderer, + styles: gitGraphStyles, +}; diff --git a/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js b/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js index cad44ea1f..764fbb214 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js +++ b/packages/mermaid/src/diagrams/git/gitGraphParserV2.spec.js @@ -1,7 +1,7 @@ /* eslint-env jasmine */ // Todo reintroduce without cryptoRandomString -import gitGraphAst from './gitGraphAst'; -import { parser } from './parser/gitGraph'; +import gitGraphAst from './gitGraphAst.js'; +import { parser } from './parser/gitGraph.jison'; //import randomString from 'crypto-random-string'; //import cryptoRandomString from 'crypto-random-string'; diff --git a/packages/mermaid/src/diagrams/git/gitGraphRenderer-old.js b/packages/mermaid/src/diagrams/git/gitGraphRenderer-old.js index ca288bfae..a3b05ad79 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphRenderer-old.js +++ b/packages/mermaid/src/diagrams/git/gitGraphRenderer-old.js @@ -1,9 +1,8 @@ import { curveBasis, line, select } from 'd3'; -import db from './gitGraphAst'; -import gitGraphParser from './parser/gitGraph'; -import { logger } from '../../logger'; -import { interpolateToCurve } from '../../utils'; +import db from './gitGraphAst.js'; +import { logger } from '../../logger.js'; +import { interpolateToCurve } from '../../utils.js'; let allCommitsDict = {}; let branchNum; @@ -328,13 +327,7 @@ function renderLines(svg, commit, direction, branchColor = 0) { export const draw = function (txt, id, ver) { try { - const parser = gitGraphParser.parser; - parser.yy = db; - parser.yy.clear(); - logger.debug('in gitgraph renderer', txt + '\n', 'id:', id, ver); - // Parse the graph definition - parser.parse(txt + '\n'); config = Object.assign(config, apiConfig, db.getOptions()); logger.debug('effective options', config); diff --git a/packages/mermaid/src/diagrams/git/gitGraphRenderer.js b/packages/mermaid/src/diagrams/git/gitGraphRenderer.js index 787eb2490..2b88cfe7e 100644 --- a/packages/mermaid/src/diagrams/git/gitGraphRenderer.js +++ b/packages/mermaid/src/diagrams/git/gitGraphRenderer.js @@ -1,7 +1,7 @@ import { select } from 'd3'; -import { getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI'; -import { log } from '../../logger'; -import utils from '../../utils'; +import { getConfig, setupGraphViewbox } from '../../diagram-api/diagramAPI.js'; +import { log } from '../../logger.js'; +import utils from '../../utils.js'; let allCommitsDict = {}; @@ -19,12 +19,14 @@ let branchPos = {}; let commitPos = {}; let lanes = []; let maxPos = 0; +let dir = 'LR'; const clear = () => { branchPos = {}; commitPos = {}; allCommitsDict = {}; maxPos = 0; lanes = []; + dir = 'LR'; }; /** @@ -77,6 +79,10 @@ const drawCommits = (svg, commits, modifyGraph) => { const gLabels = svg.append('g').attr('class', 'commit-labels'); let pos = 0; + if (dir === 'TB') { + pos = 30; + } + const keys = Object.keys(commits); const sortedKeys = keys.sort((a, b) => { return commits[a].seq - commits[b].seq; @@ -84,8 +90,9 @@ const drawCommits = (svg, commits, modifyGraph) => { sortedKeys.forEach((key) => { const commit = commits[key]; - const y = branchPos[commit.branch].pos; - const x = pos + 10; + const y = dir === 'TB' ? pos + 10 : branchPos[commit.branch].pos; + const x = dir === 'TB' ? branchPos[commit.branch].pos : pos + 10; + // Don't draw the commits now but calculate the positioning which is used by the branch lines etc. if (modifyGraph) { let typeClass; @@ -208,7 +215,11 @@ const drawCommits = (svg, commits, modifyGraph) => { } } } - commitPos[commit.id] = { x: pos + 10, y: y }; + if (dir === 'TB') { + commitPos[commit.id] = { x: x, y: pos + 10 }; + } else { + commitPos[commit.id] = { x: pos + 10, y: y }; + } // The first iteration over the commits are for positioning purposes, this // is required for drawing the lines. The circles and labels is drawn after the labels @@ -240,14 +251,27 @@ const drawCommits = (svg, commits, modifyGraph) => { .attr('y', y + 13.5) .attr('width', bbox.width + 2 * py) .attr('height', bbox.height + 2 * py); - text.attr('x', pos + 10 - bbox.width / 2); + + if (dir === 'TB') { + labelBkg.attr('x', x - (bbox.width + 4 * px + 5)).attr('y', y - 12); + text.attr('x', x - (bbox.width + 4 * px)).attr('y', y + bbox.height - 12); + } + + if (dir !== 'TB') { + text.attr('x', pos + 10 - bbox.width / 2); + } if (gitGraphConfig.rotateCommitLabel) { - let r_x = -7.5 - ((bbox.width + 10) / 25) * 9.5; - let r_y = 10 + (bbox.width / 25) * 8.5; - wrapper.attr( - 'transform', - 'translate(' + r_x + ', ' + r_y + ') rotate(' + -45 + ', ' + pos + ', ' + y + ')' - ); + if (dir === 'TB') { + text.attr('transform', 'rotate(' + -45 + ', ' + x + ', ' + y + ')'); + labelBkg.attr('transform', 'rotate(' + -45 + ', ' + x + ', ' + y + ')'); + } else { + let r_x = -7.5 - ((bbox.width + 10) / 25) * 9.5; + let r_y = 10 + (bbox.width / 25) * 8.5; + wrapper.attr( + 'transform', + 'translate(' + r_x + ', ' + r_y + ') rotate(' + -45 + ', ' + pos + ', ' + y + ')' + ); + } } } if (commit.tag) { @@ -280,6 +304,30 @@ const drawCommits = (svg, commits, modifyGraph) => { .attr('cy', ly) .attr('r', 1.5) .attr('class', 'tag-hole'); + + if (dir === 'TB') { + rect + .attr('class', 'tag-label-bkg') + .attr( + 'points', + ` + ${x},${pos + py} + ${x},${pos - py} + ${x + 10},${pos - h2 - py} + ${x + 10 + tagBbox.width + px},${pos - h2 - py} + ${x + 10 + tagBbox.width + px},${pos + h2 + py} + ${x + 10},${pos + h2 + py}` + ) + .attr('transform', 'translate(12,12) rotate(45, ' + x + ',' + pos + ')'); + hole + .attr('cx', x + px / 2) + .attr('cy', pos) + .attr('transform', 'translate(12,12) rotate(45, ' + x + ',' + pos + ')'); + tag + .attr('x', x + 5) + .attr('y', pos + 3) + .attr('transform', 'translate(14,14) rotate(45, ' + x + ',' + pos + ')'); + } } } pos += 50; @@ -365,46 +413,94 @@ const drawArrow = (svg, commit1, commit2, allCommits) => { colorClassNum = branchPos[commit2.branch].index; const lineY = p1.y < p2.y ? findLane(p1.y, p2.y) : findLane(p2.y, p1.y); + const lineX = p1.x < p2.x ? findLane(p1.x, p2.x) : findLane(p2.x, p1.x); - if (p1.y < p2.y) { - lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY - radius} ${arc} ${p1.x + offset} ${lineY} L ${ - p2.x - radius - } ${lineY} ${arc2} ${p2.x} ${lineY + offset} L ${p2.x} ${p2.y}`; + if (dir === 'TB') { + if (p1.x < p2.x) { + lineDef = `M ${p1.x} ${p1.y} L ${lineX - radius} ${p1.y} ${arc2} ${lineX} ${ + p1.y + offset + } L ${lineX} ${p2.y - radius} ${arc} ${lineX + offset} ${p2.y} L ${p2.x} ${p2.y}`; + } else { + lineDef = `M ${p1.x} ${p1.y} L ${lineX + radius} ${p1.y} ${arc} ${lineX} ${ + p1.y + offset + } L ${lineX} ${p2.y - radius} ${arc2} ${lineX - offset} ${p2.y} L ${p2.x} ${p2.y}`; + } } else { - lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY + radius} ${arc2} ${ - p1.x + offset - } ${lineY} L ${p2.x - radius} ${lineY} ${arc} ${p2.x} ${lineY - offset} L ${p2.x} ${p2.y}`; + if (p1.y < p2.y) { + lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY - radius} ${arc} ${ + p1.x + offset + } ${lineY} L ${p2.x - radius} ${lineY} ${arc2} ${p2.x} ${lineY + offset} L ${p2.x} ${p2.y}`; + } else { + lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${lineY + radius} ${arc2} ${ + p1.x + offset + } ${lineY} L ${p2.x - radius} ${lineY} ${arc} ${p2.x} ${lineY - offset} L ${p2.x} ${p2.y}`; + } } } else { - if (p1.y < p2.y) { - arc = 'A 20 20, 0, 0, 0,'; - radius = 20; - offset = 20; + if (dir === 'TB') { + if (p1.x < p2.x) { + arc = 'A 20 20, 0, 0, 0,'; + arc2 = 'A 20 20, 0, 0, 1,'; + radius = 20; + offset = 20; - // Figure out the color of the arrow,arrows going down take the color from the destination branch - colorClassNum = branchPos[commit2.branch].index; + // Figure out the color of the arrow,arrows going down take the color from the destination branch + colorClassNum = branchPos[commit2.branch].index; - lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc} ${p1.x + offset} ${p2.y} L ${ - p2.x - } ${p2.y}`; - } - if (p1.y > p2.y) { - arc = 'A 20 20, 0, 0, 0,'; - radius = 20; - offset = 20; + lineDef = `M ${p1.x} ${p1.y} L ${p2.x - radius} ${p1.y} ${arc2} ${p2.x} ${ + p1.y + offset + } L ${p2.x} ${p2.y}`; + } + if (p1.x > p2.x) { + arc = 'A 20 20, 0, 0, 0,'; + arc2 = 'A 20 20, 0, 0, 1,'; + radius = 20; + offset = 20; - // Arrows going up take the color from the source branch - colorClassNum = branchPos[commit1.branch].index; - lineDef = `M ${p1.x} ${p1.y} L ${p2.x - radius} ${p1.y} ${arc} ${p2.x} ${p1.y - offset} L ${ - p2.x - } ${p2.y}`; - } + // Arrows going up take the color from the source branch + colorClassNum = branchPos[commit1.branch].index; + lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc2} ${p1.x - offset} ${ + p2.y + } L ${p2.x} ${p2.y}`; + } - if (p1.y === p2.y) { - colorClassNum = branchPos[commit1.branch].index; - lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc} ${p1.x + offset} ${p2.y} L ${ - p2.x - } ${p2.y}`; + if (p1.x === p2.x) { + colorClassNum = branchPos[commit1.branch].index; + lineDef = `M ${p1.x} ${p1.y} L ${p1.x + radius} ${p1.y} ${arc} ${p1.x + offset} ${ + p2.y + radius + } L ${p2.x} ${p2.y}`; + } + } else { + if (p1.y < p2.y) { + arc = 'A 20 20, 0, 0, 0,'; + radius = 20; + offset = 20; + + // Figure out the color of the arrow,arrows going down take the color from the destination branch + colorClassNum = branchPos[commit2.branch].index; + + lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc} ${p1.x + offset} ${p2.y} L ${ + p2.x + } ${p2.y}`; + } + if (p1.y > p2.y) { + arc = 'A 20 20, 0, 0, 0,'; + radius = 20; + offset = 20; + + // Arrows going up take the color from the source branch + colorClassNum = branchPos[commit1.branch].index; + lineDef = `M ${p1.x} ${p1.y} L ${p2.x - radius} ${p1.y} ${arc} ${p2.x} ${p1.y - offset} L ${ + p2.x + } ${p2.y}`; + } + + if (p1.y === p2.y) { + colorClassNum = branchPos[commit1.branch].index; + lineDef = `M ${p1.x} ${p1.y} L ${p1.x} ${p2.y - radius} ${arc} ${p1.x + offset} ${p2.y} L ${ + p2.x + } ${p2.y}`; + } } } svg @@ -445,6 +541,13 @@ const drawBranches = (svg, branches) => { line.attr('y2', pos); line.attr('class', 'branch branch' + adjustIndexForTheme); + if (dir === 'TB') { + line.attr('y1', 30); + line.attr('x1', pos); + line.attr('y2', maxPos); + line.attr('x2', pos); + } + lanes.push(pos); let name = branch.name; @@ -467,7 +570,6 @@ const drawBranches = (svg, branches) => { .attr('y', -bbox.height / 2 + 8) .attr('width', bbox.width + 18) .attr('height', bbox.height + 4); - label.attr( 'transform', 'translate(' + @@ -476,7 +578,13 @@ const drawBranches = (svg, branches) => { (pos - bbox.height / 2 - 1) + ')' ); - bkg.attr('transform', 'translate(' + -19 + ', ' + (pos - bbox.height / 2) + ')'); + if (dir === 'TB') { + bkg.attr('x', pos - bbox.width / 2 - 10).attr('y', 0); + label.attr('transform', 'translate(' + (pos - bbox.width / 2 - 5) + ', ' + 0 + ')'); + } + if (dir !== 'TB') { + bkg.attr('transform', 'translate(' + -19 + ', ' + (pos - bbox.height / 2) + ')'); + } }); }; @@ -495,15 +603,24 @@ export const draw = function (txt, id, ver, diagObj) { allCommitsDict = diagObj.db.getCommits(); const branches = diagObj.db.getBranchesAsObjArray(); - - // Position branches vertically + dir = diagObj.db.getDirection(); + const diagram = select(`[id="${id}"]`); + // Position branches let pos = 0; branches.forEach((branch, index) => { - branchPos[branch.name] = { pos, index }; - pos += 50 + (gitGraphConfig.rotateCommitLabel ? 40 : 0); - }); + const labelElement = drawText(branch.name); + const g = diagram.append('g'); + const branchLabel = g.insert('g').attr('class', 'branchLabel'); + const label = branchLabel.insert('g').attr('class', 'label branch-label'); + label.node().appendChild(labelElement); + let bbox = labelElement.getBBox(); - const diagram = select(`[id="${id}"]`); + branchPos[branch.name] = { pos, index }; + pos += 50 + (gitGraphConfig.rotateCommitLabel ? 40 : 0) + (dir === 'TB' ? bbox.width / 2 : 0); + label.remove(); + branchLabel.remove(); + g.remove(); + }); drawCommits(diagram, allCommitsDict, false); if (gitGraphConfig.showBranches) { diff --git a/packages/mermaid/src/diagrams/git/layout.js b/packages/mermaid/src/diagrams/git/layout.js index de866a72b..0dbe57765 100644 --- a/packages/mermaid/src/diagrams/git/layout.js +++ b/packages/mermaid/src/diagrams/git/layout.js @@ -1,4 +1,4 @@ -import { getConfig } from '../../config'; +import { getConfig } from '../../config.js'; export default (dir, _branches) => { const config = getConfig().gitGraph; diff --git a/packages/mermaid/src/diagrams/git/parser/gitGraph.jison b/packages/mermaid/src/diagrams/git/parser/gitGraph.jison index 1c87f3bf3..9ff5623f8 100644 --- a/packages/mermaid/src/diagrams/git/parser/gitGraph.jison +++ b/packages/mermaid/src/diagrams/git/parser/gitGraph.jison @@ -51,7 +51,7 @@ cherry\-pick(?=\s|$) return 'CHERRY_PICK'; // "reset" return 'RESET'; checkout(?=\s|$) return 'CHECKOUT'; "LR" return 'DIR'; -"BT" return 'DIR'; +"TB" return 'DIR'; ":" return ':'; "^" return 'CARET' "options"\r?\n this.begin("options"); // diff --git a/packages/mermaid/src/diagrams/git/styles.js b/packages/mermaid/src/diagrams/git/styles.js index 741760235..1836e9dff 100644 --- a/packages/mermaid/src/diagrams/git/styles.js +++ b/packages/mermaid/src/diagrams/git/styles.js @@ -56,7 +56,6 @@ const getStyles = (options) => font-size: 18px; fill: ${options.textColor}; } - } `; export default getStyles; diff --git a/packages/mermaid/src/diagrams/info/info.spec.js b/packages/mermaid/src/diagrams/info/info.spec.js deleted file mode 100644 index 8bcce51d4..000000000 --- a/packages/mermaid/src/diagrams/info/info.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -import { parser } from './parser/info'; -import infoDb from './infoDb'; -describe('when parsing an info graph it', function () { - let ex; - beforeEach(function () { - ex = parser; - ex.yy = infoDb; - }); - - it('should handle an info definition', function () { - let str = `info - showInfo`; - - ex.parse(str); - }); -}); diff --git a/packages/mermaid/src/diagrams/info/info.spec.ts b/packages/mermaid/src/diagrams/info/info.spec.ts new file mode 100644 index 000000000..076f04f69 --- /dev/null +++ b/packages/mermaid/src/diagrams/info/info.spec.ts @@ -0,0 +1,24 @@ +// @ts-ignore - jison doesn't export types +import { parser } from './parser/info.jison'; +import { db } from './infoDb.js'; + +describe('info diagram', () => { + beforeEach(() => { + parser.yy = db; + parser.yy.clear(); + }); + + it('should handle an info definition', () => { + const str = `info`; + parser.parse(str); + + expect(db.getInfo()).toBeFalsy(); + }); + + it('should handle an info definition with showInfo', () => { + const str = `info showInfo`; + parser.parse(str); + + expect(db.getInfo()).toBeTruthy(); + }); +}); diff --git a/packages/mermaid/src/diagrams/info/infoDb.js b/packages/mermaid/src/diagrams/info/infoDb.js deleted file mode 100644 index 2a04f1633..000000000 --- a/packages/mermaid/src/diagrams/info/infoDb.js +++ /dev/null @@ -1,36 +0,0 @@ -/** Created by knut on 15-01-14. */ -import { log } from '../../logger'; -import { clear } from '../../commonDb'; - -var message = ''; -var info = false; - -export const setMessage = (txt) => { - log.debug('Setting message to: ' + txt); - message = txt; -}; - -export const getMessage = () => { - return message; -}; - -export const setInfo = (inf) => { - info = inf; -}; - -export const getInfo = () => { - return info; -}; - -// export const parseError = (err, hash) => { -// global.mermaidAPI.parseError(err, hash) -// } - -export default { - setMessage, - getMessage, - setInfo, - getInfo, - clear, - // parseError -}; diff --git a/packages/mermaid/src/diagrams/info/infoDb.ts b/packages/mermaid/src/diagrams/info/infoDb.ts new file mode 100644 index 000000000..ff4bfcae0 --- /dev/null +++ b/packages/mermaid/src/diagrams/info/infoDb.ts @@ -0,0 +1,23 @@ +import type { InfoFields, InfoDB } from './infoTypes.js'; + +export const DEFAULT_INFO_DB: InfoFields = { + info: false, +} as const; + +let info: boolean = DEFAULT_INFO_DB.info; + +export const setInfo = (toggle: boolean): void => { + info = toggle; +}; + +export const getInfo = (): boolean => info; + +const clear = (): void => { + info = DEFAULT_INFO_DB.info; +}; + +export const db: InfoDB = { + clear, + setInfo, + getInfo, +}; diff --git a/packages/mermaid/src/diagrams/info/infoDetector.ts b/packages/mermaid/src/diagrams/info/infoDetector.ts index 8bccb578f..04d2677ef 100644 --- a/packages/mermaid/src/diagrams/info/infoDetector.ts +++ b/packages/mermaid/src/diagrams/info/infoDetector.ts @@ -1,5 +1,22 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const infoDetector: DiagramDetector = (txt) => { - return txt.match(/^\s*info/) !== null; +const id = 'info'; + +const detector: DiagramDetector = (txt) => { + return /^\s*info/.test(txt); +}; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./infoDiagram.js'); + return { id, diagram }; +}; + +export const info: ExternalDiagramDefinition = { + id, + detector, + loader, }; diff --git a/packages/mermaid/src/diagrams/info/infoDiagram.ts b/packages/mermaid/src/diagrams/info/infoDiagram.ts new file mode 100644 index 000000000..b21827b5f --- /dev/null +++ b/packages/mermaid/src/diagrams/info/infoDiagram.ts @@ -0,0 +1,11 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore - jison doesn't export types +import parser from './parser/info.jison'; +import { db } from './infoDb.js'; +import { renderer } from './infoRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, +}; diff --git a/packages/mermaid/src/diagrams/info/infoRenderer.js b/packages/mermaid/src/diagrams/info/infoRenderer.js deleted file mode 100644 index 1caa7222c..000000000 --- a/packages/mermaid/src/diagrams/info/infoRenderer.js +++ /dev/null @@ -1,57 +0,0 @@ -/** Created by knut on 14-12-11. */ -import { select } from 'd3'; -import { log } from '../../logger'; -import { getConfig } from '../../config'; - -/** - * Draws a an info picture in the tag with id: id based on the graph definition in text. - * - * @param {any} text - * @param {any} id - * @param {any} version - */ -export const draw = (text, id, version) => { - try { - // const parser = infoParser.parser; - // parser.yy = db; - log.debug('Rendering info diagram\n' + text); - - const securityLevel = getConfig().securityLevel; - // 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'); - - // Parse the graph definition - // parser.parse(text); - // log.debug('Parsed info diagram'); - // Fetch the default direction, use TD if none was found - const svg = root.select('#' + id); - - const g = svg.append('g'); - - g.append('text') // text label for the x axis - .attr('x', 100) - .attr('y', 40) - .attr('class', 'version') - .attr('font-size', '32px') - .style('text-anchor', 'middle') - .text('v ' + version); - - svg.attr('height', 100); - svg.attr('width', 400); - // svg.attr('viewBox', '0 0 300 150'); - } catch (e) { - log.error('Error while rendering info diagram'); - log.error(e.message); - } -}; - -export default { - draw, -}; diff --git a/packages/mermaid/src/diagrams/info/infoRenderer.ts b/packages/mermaid/src/diagrams/info/infoRenderer.ts new file mode 100644 index 000000000..25ae72fce --- /dev/null +++ b/packages/mermaid/src/diagrams/info/infoRenderer.ts @@ -0,0 +1,30 @@ +import { log } from '../../logger.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js'; +import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; + +/** + * Draws a an info picture in the tag with id: id based on the graph definition in text. + * + * @param text - The text of the diagram. + * @param id - The id of the diagram which will be used as a DOM element id. + * @param version - MermaidJS version. + */ +const draw: DrawDefinition = (text, id, version) => { + log.debug('rendering info diagram\n' + text); + + const svg: SVG = selectSvgElement(id); + configureSvgSize(svg, 100, 400, true); + + const group: Group = svg.append('g'); + group + .append('text') + .attr('x', 100) + .attr('y', 40) + .attr('class', 'version') + .attr('font-size', 32) + .style('text-anchor', 'middle') + .text(`v${version}`); +}; + +export const renderer = { draw }; diff --git a/packages/mermaid/src/diagrams/info/infoTypes.ts b/packages/mermaid/src/diagrams/info/infoTypes.ts new file mode 100644 index 000000000..239f8fdda --- /dev/null +++ b/packages/mermaid/src/diagrams/info/infoTypes.ts @@ -0,0 +1,11 @@ +import type { DiagramDB } from '../../diagram-api/types.js'; + +export interface InfoFields { + info: boolean; +} + +export interface InfoDB extends DiagramDB { + clear: () => void; + setInfo: (info: boolean) => void; + getInfo: () => boolean; +} diff --git a/packages/mermaid/src/diagrams/info/styles.js b/packages/mermaid/src/diagrams/info/styles.js deleted file mode 100644 index 0b0729813..000000000 --- a/packages/mermaid/src/diagrams/info/styles.js +++ /dev/null @@ -1,3 +0,0 @@ -const getStyles = () => ``; - -export default getStyles; diff --git a/packages/mermaid/src/diagrams/mindmap/detector.ts b/packages/mermaid/src/diagrams/mindmap/detector.ts index 2e2b1c7d6..2b31fc5e8 100644 --- a/packages/mermaid/src/diagrams/mindmap/detector.ts +++ b/packages/mermaid/src/diagrams/mindmap/detector.ts @@ -1,11 +1,15 @@ -import type { ExternalDiagramDefinition } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; const id = 'mindmap'; -const detector = (txt: string) => { - return txt.match(/^\s*mindmap/) !== null; +const detector: DiagramDetector = (txt) => { + return /^\s*mindmap/.test(txt); }; -const loader = async () => { +const loader: DiagramLoader = async () => { const { diagram } = await import('./mindmap-definition.js'); return { id, diagram }; }; diff --git a/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts b/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts index 61b41d347..b35214435 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts @@ -1,8 +1,8 @@ -// @ts-ignore: TODO Fix ts errors -import mindmapParser from './parser/mindmap'; -import * as mindmapDb from './mindmapDb'; -import mindmapRenderer from './mindmapRenderer'; -import mindmapStyles from './styles'; +// @ts-ignore: JISON doesn't support types +import mindmapParser from './parser/mindmap.jison'; +import * as mindmapDb from './mindmapDb.js'; +import mindmapRenderer from './mindmapRenderer.js'; +import mindmapStyles from './styles.js'; export const diagram = { db: mindmapDb, diff --git a/packages/mermaid/src/diagrams/mindmap/mindmap.spec.js b/packages/mermaid/src/diagrams/mindmap/mindmap.spec.js index e8793e86a..845205f9b 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmap.spec.js +++ b/packages/mermaid/src/diagrams/mindmap/mindmap.spec.js @@ -1,7 +1,7 @@ -import { parser as mindmap } from './parser/mindmap'; -import * as mindmapDB from './mindmapDb'; +import { parser as mindmap } from './parser/mindmap.jison'; +import * as mindmapDB from './mindmapDb.js'; // Todo fix utils functions for tests -import { setLogLevel } from '../../diagram-api/diagramAPI'; +import { setLogLevel } from '../../diagram-api/diagramAPI.js'; describe('when parsing a mindmap ', function () { beforeEach(function () { diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.js b/packages/mermaid/src/diagrams/mindmap/mindmapDb.js index 71aa449d9..9413581d6 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapDb.js +++ b/packages/mermaid/src/diagrams/mindmap/mindmapDb.js @@ -1,6 +1,6 @@ -import { getConfig } from '../../config'; -import { sanitizeText as _sanitizeText } from '../../diagrams/common/common'; -import { log } from '../../logger'; +import { getConfig } from '../../config.js'; +import { sanitizeText as _sanitizeText } from '../../diagrams/common/common.js'; +import { log } from '../../logger.js'; export const sanitizeText = (text) => _sanitizeText(text, getConfig()); diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js index 0d814212e..7e741657b 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js +++ b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js @@ -1,12 +1,16 @@ /** Created by knut on 14-12-11. */ import { select } from 'd3'; -import { log } from '../../logger'; -import { getConfig } from '../../config'; -import { setupGraphViewbox } from '../../setupGraphViewbox'; -import svgDraw from './svgDraw'; -import * as db from './mindmapDb'; +import { log } from '../../logger.js'; +import { getConfig } from '../../config.js'; +import { setupGraphViewbox } from '../../setupGraphViewbox.js'; +import svgDraw from './svgDraw.js'; +import cytoscape from 'cytoscape/dist/cytoscape.umd.js'; +import coseBilkent from 'cytoscape-cose-bilkent'; +import * as db from './mindmapDb.js'; + +// Inject the layout algorithm into cytoscape +cytoscape.use(coseBilkent); -let cytoscape; /** * @param {any} svg The svg element to draw the diagram onto * @param {object} mindmap The mindmap data and hierarchy @@ -89,14 +93,7 @@ function addNodes(mindmap, cy, conf, level) { * @param conf * @param cy */ -async function layoutMindmap(node, conf) { - if (!cytoscape) { - cytoscape = (await import('cytoscape')).default; - const coseBilkent = (await import('cytoscape-cose-bilkent')).default; - // Inject the layout algorithm into cytoscape - cytoscape.use(coseBilkent); - } - +function layoutMindmap(node, conf) { return new Promise((resolve) => { // Add temporary render element const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none'); @@ -170,12 +167,9 @@ function positionNodes(cy) { export const draw = async (text, id, version, diagObj) => { const conf = getConfig(); - // This is done only for throwing the error if the text is not valid. - diagObj.db.clear(); - // Parse the graph definition - diagObj.parser.parse(text); + conf.htmlLabels = false; - log.debug('Renering info diagram\n' + text); + log.debug('Rendering mindmap diagram\n' + text, diagObj.parser); const securityLevel = getConfig().securityLevel; // Handle root and Document for when rendering in sandbox mode diff --git a/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison b/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison index d2f6bbf1a..afd5e2300 100644 --- a/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison +++ b/packages/mermaid/src/diagrams/mindmap/parser/mindmap.jison @@ -12,12 +12,13 @@ %} %x NODE %x NSTR +%x NSTR2 %x ICON %x CLASS %% -\s*\%\%.* {yy.getLogger().trace('Found comment',yytext);} +\s*\%\%.* {yy.getLogger().trace('Found comment',yytext); return 'SPACELINE';} // \%\%[^\n]*\n /* skip comments */ "mindmap" return 'MINDMAP'; ":::" { this.begin('CLASS'); } @@ -39,8 +40,11 @@ "[" { this.begin('NODE');return 'NODE_DSTART'; } [\s]+ return 'SPACELIST' /* skip all whitespace */ ; // !(-\() return 'NODE_ID'; -[^\(\[\n\-\)\{\}]+ return 'NODE_ID'; +[^\(\[\n\)\{\}]+ return 'NODE_ID'; <> return 'EOF'; +["][`] { this.begin("NSTR2");} +[^`"]+ { return "NODE_DESCR";} +[`]["] { this.popState();} ["] { yy.getLogger().trace('Starting NSTR');this.begin("NSTR");} [^"]+ { yy.getLogger().trace('description:', yytext); return "NODE_DESCR";} ["] {this.popState();} diff --git a/packages/mermaid/src/diagrams/mindmap/styles.js b/packages/mermaid/src/diagrams/mindmap/styles.js index 986a04514..863522fdf 100644 --- a/packages/mermaid/src/diagrams/mindmap/styles.js +++ b/packages/mermaid/src/diagrams/mindmap/styles.js @@ -70,5 +70,12 @@ const getStyles = (options) => .edge { fill: none; } + .mindmap-node-label { + dy: 1em; + alignment-baseline: middle; + text-anchor: middle; + dominant-baseline: middle; + text-align: center; + } `; export default getStyles; diff --git a/packages/mermaid/src/diagrams/mindmap/svgDraw.js b/packages/mermaid/src/diagrams/mindmap/svgDraw.js index 2b1aa021e..2a4fc4b67 100644 --- a/packages/mermaid/src/diagrams/mindmap/svgDraw.js +++ b/packages/mermaid/src/diagrams/mindmap/svgDraw.js @@ -1,5 +1,6 @@ import { select } from 'd3'; -import * as db from './mindmapDb'; +import * as db from './mindmapDb.js'; +import { createText } from '../../rendering-util/createText.js'; const MAX_SECTIONS = 12; /** @@ -11,7 +12,7 @@ function wrap(text, width) { var text = select(this), words = text .text() - .split(/(\s+|
)/) + .split(/(\s+|)/) .reverse(), word, line = [], @@ -28,10 +29,10 @@ function wrap(text, width) { word = words[words.length - 1 - j]; line.push(word); tspan.text(line.join(' ').trim()); - if (tspan.node().getComputedTextLength() > width || word === '
') { + if (tspan.node().getComputedTextLength() > width || word === '
') { line.pop(); tspan.text(line.join(' ').trim()); - if (word === '
') { + if (word === '
') { line = ['']; } else { line = [word]; @@ -69,6 +70,7 @@ const defaultBkg = function (elem, node, section) { .attr('x2', node.width) .attr('y2', node.height); }; + const rectBkg = function (elem, node) { elem .append('rect') @@ -77,6 +79,7 @@ const rectBkg = function (elem, node) { .attr('height', node.height) .attr('width', node.width); }; + const cloudBkg = function (elem, node) { const w = node.width; const h = node.height; @@ -107,6 +110,7 @@ const cloudBkg = function (elem, node) { H0 V0 Z` ); }; + const bangBkg = function (elem, node) { const w = node.width; const h = node.height; @@ -138,6 +142,7 @@ const bangBkg = function (elem, node) { H0 V0 Z` ); }; + const circleBkg = function (elem, node) { elem .append('circle') @@ -203,6 +208,7 @@ const roundedRectBkg = function (elem, node) { * @returns {number} The height nodes dom element */ export const drawNode = function (elem, node, fullSection, conf) { + const htmlLabels = conf.htmlLabels; const section = fullSection % (MAX_SECTIONS - 1); const nodeElem = elem.append('g'); node.section = section; @@ -215,15 +221,22 @@ export const drawNode = function (elem, node, fullSection, conf) { // Create the wrapped text element const textElem = nodeElem.append('g'); - const txt = textElem - .append('text') - .text(node.descr) - .attr('dy', '1em') - .attr('alignment-baseline', 'middle') - .attr('dominant-baseline', 'middle') - .attr('text-anchor', 'middle') - .call(wrap, node.width); - const bbox = txt.node().getBBox(); + const description = node.descr.replace(/()/g, '\n'); + const newEl = createText(textElem, description, { + useHtmlLabels: htmlLabels, + width: node.width, + classes: 'mindmap-node-label', + }); + + if (!htmlLabels) { + textElem + .attr('dy', '1em') + .attr('alignment-baseline', 'middle') + .attr('dominant-baseline', 'middle') + .attr('text-anchor', 'middle'); + } + // .call(wrap, node.width); + const bbox = textElem.node().getBBox(); const fontSize = conf.fontSize.replace ? conf.fontSize.replace('px', '') : conf.fontSize; node.height = bbox.height + fontSize * 1.1 * 0.5 + node.padding; node.width = bbox.width + 2 * node.padding; @@ -267,7 +280,16 @@ export const drawNode = function (elem, node, fullSection, conf) { ); } } else { - textElem.attr('transform', 'translate(' + node.width / 2 + ', ' + node.padding / 2 + ')'); + if (!htmlLabels) { + const dx = node.width / 2; + const dy = node.padding / 2; + textElem.attr('transform', 'translate(' + dx + ', ' + dy + ')'); + // textElem.attr('transform', 'translate(' + node.width / 2 + ', ' + node.padding / 2 + ')'); + } else { + const dx = (node.width - bbox.width) / 2; + const dy = (node.height - bbox.height) / 2; + textElem.attr('transform', 'translate(' + dx + ', ' + dy + ')'); + } } switch (node.type) { diff --git a/packages/mermaid/src/diagrams/pie/amonts.csv b/packages/mermaid/src/diagrams/pie/amonts.csv deleted file mode 100644 index 25cf919dd..000000000 --- a/packages/mermaid/src/diagrams/pie/amonts.csv +++ /dev/null @@ -1,10 +0,0 @@ -name,amounts -Foo, 33 -Rishab, 12 -Alexis, 41 -Tom, 16 -Courtney, 59 -Christina, 38 -Jack, 21 -Mickey, 25 -Paul, 30 diff --git a/packages/mermaid/src/diagrams/pie/parser/pie.spec.js b/packages/mermaid/src/diagrams/pie/parser/pie.spec.js deleted file mode 100644 index 21523dde4..000000000 --- a/packages/mermaid/src/diagrams/pie/parser/pie.spec.js +++ /dev/null @@ -1,132 +0,0 @@ -import pieDb from '../pieDb'; -import pie from './pie'; -import { setConfig } from '../../../config'; - -setConfig({ - securityLevel: 'strict', -}); - -describe('when parsing pie', function () { - beforeEach(function () { - pie.parser.yy = pieDb; - pie.parser.yy.clear(); - }); - it('should handle very simple pie', function () { - const res = pie.parser.parse(`pie -"ash" : 100 -`); - const sections = pieDb.getSections(); - const section1 = sections['ash']; - expect(section1).toBe(100); - }); - it('should handle simple pie', function () { - const res = pie.parser.parse(`pie -"ash" : 60 -"bat" : 40 -`); - const sections = pieDb.getSections(); - const section1 = sections['ash']; - expect(section1).toBe(60); - }); - it('should handle simple pie with comments', function () { - const res = pie.parser.parse(`pie - %% comments -"ash" : 60 -"bat" : 40 -`); - const sections = pieDb.getSections(); - const section1 = sections['ash']; - expect(section1).toBe(60); - }); - - it('should handle simple pie with a directive', function () { - const res = pie.parser.parse(`%%{init: {'logLevel':0}}%% -pie -"ash" : 60 -"bat" : 40 -`); - const sections = pieDb.getSections(); - const section1 = sections['ash']; - expect(section1).toBe(60); - }); - - it('should handle simple pie with a title', function () { - const res = pie.parser.parse(`pie title a 60/40 pie -"ash" : 60 -"bat" : 40 -`); - const sections = pieDb.getSections(); - const title = pieDb.getDiagramTitle(); - const section1 = sections['ash']; - expect(section1).toBe(60); - expect(title).toBe('a 60/40 pie'); - }); - - it('should handle simple pie without an acc description (accDescr)', function () { - const res = pie.parser.parse(`pie title a neat chart -"ash" : 60 -"bat" : 40 -`); - - const sections = pieDb.getSections(); - const title = pieDb.getDiagramTitle(); - const description = pieDb.getAccDescription(); - const section1 = sections['ash']; - expect(section1).toBe(60); - expect(title).toBe('a neat chart'); - expect(description).toBe(''); - }); - - it('should handle simple pie with an acc description (accDescr)', function () { - const res = pie.parser.parse(`pie title a neat chart - accDescr: a neat description -"ash" : 60 -"bat" : 40 -`); - - const sections = pieDb.getSections(); - const title = pieDb.getDiagramTitle(); - const description = pieDb.getAccDescription(); - const section1 = sections['ash']; - expect(section1).toBe(60); - expect(title).toBe('a neat chart'); - expect(description).toBe('a neat description'); - }); - it('should handle simple pie with a multiline acc description (accDescr)', function () { - const res = pie.parser.parse(`pie title a neat chart - accDescr { - a neat description - on multiple lines - } -"ash" : 60 -"bat" : 40 -`); - - const sections = pieDb.getSections(); - const title = pieDb.getDiagramTitle(); - const description = pieDb.getAccDescription(); - const section1 = sections['ash']; - expect(section1).toBe(60); - expect(title).toBe('a neat chart'); - expect(description).toBe('a neat description\non multiple lines'); - }); - - it('should handle simple pie with positive decimal', function () { - const res = pie.parser.parse(`pie -"ash" : 60.67 -"bat" : 40 -`); - const sections = pieDb.getSections(); - const section1 = sections['ash']; - expect(section1).toBe(60.67); - }); - - it('should handle simple pie with negative decimal', function () { - expect(() => { - pie.parser.parse(`pie -"ash" : 60.67 -"bat" : 40..12 -`); - }).toThrowError(); - }); -}); diff --git a/packages/mermaid/src/diagrams/pie/pie.spec.ts b/packages/mermaid/src/diagrams/pie/pie.spec.ts new file mode 100644 index 000000000..7c8e0809a --- /dev/null +++ b/packages/mermaid/src/diagrams/pie/pie.spec.ts @@ -0,0 +1,180 @@ +// @ts-ignore: JISON doesn't support types +import { parser } from './parser/pie.jison'; +import { DEFAULT_PIE_DB, db } from './pieDb.js'; +import { setConfig } from '../../config.js'; + +setConfig({ + securityLevel: 'strict', +}); + +describe('pie', () => { + beforeAll(() => { + parser.yy = db; + }); + + beforeEach(() => { + parser.yy.clear(); + }); + + describe('parse', () => { + it('should handle very simple pie', () => { + parser.parse(`pie + "ash": 100 + `); + + const sections = db.getSections(); + expect(sections['ash']).toBe(100); + }); + + it('should handle simple pie', () => { + parser.parse(`pie + "ash" : 60 + "bat" : 40 + `); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with showData', () => { + parser.parse(`pie showData + "ash" : 60 + "bat" : 40 + `); + + expect(db.getShowData()).toBeTruthy(); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with comments', () => { + parser.parse(`pie + %% comments + "ash" : 60 + "bat" : 40 + `); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with a directive', () => { + parser.parse(`%%{init: {'logLevel':0}}%% + pie + "ash" : 60 + "bat" : 40 + `); + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with a title', () => { + parser.parse(`pie title a 60/40 pie + "ash" : 60 + "bat" : 40 + `); + + expect(db.getDiagramTitle()).toBe('a 60/40 pie'); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with an acc title (accTitle)', () => { + parser.parse(`pie title a neat chart + accTitle: a neat acc title + "ash" : 60 + "bat" : 40 + `); + + expect(db.getDiagramTitle()).toBe('a neat chart'); + + expect(db.getAccTitle()).toBe('a neat acc title'); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with an acc description (accDescr)', () => { + parser.parse(`pie title a neat chart + accDescr: a neat description + "ash" : 60 + "bat" : 40 + `); + + expect(db.getDiagramTitle()).toBe('a neat chart'); + + expect(db.getAccDescription()).toBe('a neat description'); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with a multiline acc description (accDescr)', () => { + parser.parse(`pie title a neat chart + accDescr { + a neat description + on multiple lines + } + "ash" : 60 + "bat" : 40 + `); + + expect(db.getDiagramTitle()).toBe('a neat chart'); + + expect(db.getAccDescription()).toBe('a neat description\non multiple lines'); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with positive decimal', () => { + parser.parse(`pie + "ash" : 60.67 + "bat" : 40 + `); + + const sections = db.getSections(); + expect(sections['ash']).toBe(60.67); + expect(sections['bat']).toBe(40); + }); + + it('should handle simple pie with negative decimal', () => { + expect(() => { + parser.parse(`pie + "ash" : -60.67 + "bat" : 40.12 + `); + }).toThrowError(); + }); + }); + + describe('config', () => { + it.todo('setConfig', () => { + // db.setConfig({ useWidth: 850, useMaxWidth: undefined }); + + const config = db.getConfig(); + expect(config.useWidth).toBe(850); + expect(config.useMaxWidth).toBeTruthy(); + }); + + it('getConfig', () => { + expect(db.getConfig()).toStrictEqual(DEFAULT_PIE_DB.config); + }); + + it.todo('resetConfig', () => { + // db.setConfig({ textPosition: 0 }); + // db.resetConfig(); + expect(db.getConfig().textPosition).toStrictEqual(DEFAULT_PIE_DB.config.textPosition); + }); + }); +}); diff --git a/packages/mermaid/src/diagrams/pie/pieDb.js b/packages/mermaid/src/diagrams/pie/pieDb.js deleted file mode 100644 index 5ccf6d29e..000000000 --- a/packages/mermaid/src/diagrams/pie/pieDb.js +++ /dev/null @@ -1,69 +0,0 @@ -import { log } from '../../logger'; -import mermaidAPI from '../../mermaidAPI'; -import * as configApi from '../../config'; -import common from '../common/common'; -import { - setAccTitle, - getAccTitle, - setDiagramTitle, - getDiagramTitle, - getAccDescription, - setAccDescription, - clear as commonClear, -} from '../../commonDb'; - -let sections = {}; -let showData = false; - -export const parseDirective = function (statement, context, type) { - mermaidAPI.parseDirective(this, statement, context, type); -}; - -const addSection = function (id, value) { - id = common.sanitizeText(id, configApi.getConfig()); - if (sections[id] === undefined) { - sections[id] = value; - log.debug('Added new section :', id); - } -}; -const getSections = () => sections; - -const setShowData = function (toggle) { - showData = toggle; -}; - -const getShowData = function () { - return showData; -}; - -const cleanupValue = function (value) { - if (value.substring(0, 1) === ':') { - value = value.substring(1).trim(); - return Number(value.trim()); - } else { - return Number(value.trim()); - } -}; - -const clear = function () { - sections = {}; - showData = false; - commonClear(); -}; - -export default { - parseDirective, - getConfig: () => configApi.getConfig().pie, - addSection, - getSections, - cleanupValue, - clear, - setAccTitle, - getAccTitle, - setDiagramTitle, - getDiagramTitle, - setShowData, - getShowData, - getAccDescription, - setAccDescription, -}; diff --git a/packages/mermaid/src/diagrams/pie/pieDb.ts b/packages/mermaid/src/diagrams/pie/pieDb.ts new file mode 100644 index 000000000..7f209de46 --- /dev/null +++ b/packages/mermaid/src/diagrams/pie/pieDb.ts @@ -0,0 +1,84 @@ +import { log } from '../../logger.js'; +import { parseDirective as _parseDirective } from '../../directiveUtils.js'; +import { getConfig as commonGetConfig } from '../../config.js'; +import { sanitizeText } from '../common/common.js'; +import { + setAccTitle, + getAccTitle, + setDiagramTitle, + getDiagramTitle, + getAccDescription, + setAccDescription, + clear as commonClear, +} from '../common/commonDb.js'; +import type { ParseDirectiveDefinition } from '../../diagram-api/types.js'; +import type { PieFields, PieDB, Sections } from './pieTypes.js'; +import type { RequiredDeep } from 'type-fest'; +import type { PieDiagramConfig } from '../../config.type.js'; +import DEFAULT_CONFIG from '../../defaultConfig.js'; + +export const DEFAULT_PIE_CONFIG: Required = DEFAULT_CONFIG.pie; + +export const DEFAULT_PIE_DB: RequiredDeep = { + sections: {}, + showData: false, + config: DEFAULT_PIE_CONFIG, +} as const; + +let sections: Sections = DEFAULT_PIE_DB.sections; +let showData: boolean = DEFAULT_PIE_DB.showData; +const config: Required = structuredClone(DEFAULT_PIE_CONFIG); + +const getConfig = (): Required => structuredClone(config); + +const parseDirective: ParseDirectiveDefinition = (statement, context, type) => { + _parseDirective(this, statement, context, type); +}; + +const clear = (): void => { + sections = structuredClone(DEFAULT_PIE_DB.sections); + showData = DEFAULT_PIE_DB.showData; + commonClear(); +}; + +const addSection = (label: string, value: number): void => { + label = sanitizeText(label, commonGetConfig()); + if (sections[label] === undefined) { + sections[label] = value; + log.debug(`added new section: ${label}, with value: ${value}`); + } +}; + +const getSections = (): Sections => sections; + +const cleanupValue = (value: string): number => { + if (value.substring(0, 1) === ':') { + value = value.substring(1).trim(); + } + return Number(value.trim()); +}; + +const setShowData = (toggle: boolean): void => { + showData = toggle; +}; + +const getShowData = (): boolean => showData; + +export const db: PieDB = { + getConfig, + + parseDirective, + clear, + setDiagramTitle, + getDiagramTitle, + setAccTitle, + getAccTitle, + setAccDescription, + getAccDescription, + + addSection, + getSections, + cleanupValue, + setShowData, + getShowData, +}; diff --git a/packages/mermaid/src/diagrams/pie/pieDetector.ts b/packages/mermaid/src/diagrams/pie/pieDetector.ts index e267c710a..f5acd1aa0 100644 --- a/packages/mermaid/src/diagrams/pie/pieDetector.ts +++ b/packages/mermaid/src/diagrams/pie/pieDetector.ts @@ -1,6 +1,22 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const pieDetector: DiagramDetector = (txt) => { - const logOutput = txt.match(/^\s*pie/) !== null || txt.match(/^\s*bar/) !== null; - return logOutput; +const id = 'pie'; + +const detector: DiagramDetector = (txt) => { + return /^\s*pie/.test(txt); +}; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./pieDiagram.js'); + return { id, diagram }; +}; + +export const pie: ExternalDiagramDefinition = { + id, + detector, + loader, }; diff --git a/packages/mermaid/src/diagrams/pie/pieDiagram.ts b/packages/mermaid/src/diagrams/pie/pieDiagram.ts new file mode 100644 index 000000000..f0aa19b41 --- /dev/null +++ b/packages/mermaid/src/diagrams/pie/pieDiagram.ts @@ -0,0 +1,13 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: JISON doesn't support types +import parser from './parser/pie.jison'; +import { db } from './pieDb.js'; +import styles from './pieStyles.js'; +import { renderer } from './pieRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/pie/pieRenderer.js b/packages/mermaid/src/diagrams/pie/pieRenderer.js deleted file mode 100644 index 83f301207..000000000 --- a/packages/mermaid/src/diagrams/pie/pieRenderer.js +++ /dev/null @@ -1,192 +0,0 @@ -/** Created by AshishJ on 11-09-2019. */ -import { select, scaleOrdinal, pie as d3pie, arc } from 'd3'; -import { log } from '../../logger'; -import { configureSvgSize } from '../../setupGraphViewbox'; -import * as configApi from '../../config'; - -let conf = configApi.getConfig(); - -/** - * Draws a Pie Chart with the data given in text. - * - * @param text - * @param id - */ -let width; -const height = 450; -export const draw = (txt, id, _version, diagObj) => { - try { - conf = configApi.getConfig(); - log.debug('Rendering info diagram\n' + txt); - - const securityLevel = configApi.getConfig().securityLevel; - // 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; - - // Parse the Pie Chart definition - diagObj.db.clear(); - diagObj.parser.parse(txt); - log.debug('Parsed info diagram'); - const elem = doc.getElementById(id); - width = elem.parentElement.offsetWidth; - - if (width === undefined) { - width = 1200; - } - - if (conf.useWidth !== undefined) { - width = conf.useWidth; - } - if (conf.pie.useWidth !== undefined) { - width = conf.pie.useWidth; - } - - const diagram = root.select('#' + id); - configureSvgSize(diagram, height, width, conf.pie.useMaxWidth); - - // Set viewBox - elem.setAttribute('viewBox', '0 0 ' + width + ' ' + height); - - // Fetch the default direction, use TD if none was found - var margin = 40; - var legendRectSize = 18; - var legendSpacing = 4; - - var radius = Math.min(width, height) / 2 - margin; - - var svg = diagram - .append('g') - .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); - - var data = diagObj.db.getSections(); - var sum = 0; - Object.keys(data).forEach(function (key) { - sum += data[key]; - }); - - const themeVariables = conf.themeVariables; - var myGeneratedColors = [ - themeVariables.pie1, - themeVariables.pie2, - themeVariables.pie3, - themeVariables.pie4, - themeVariables.pie5, - themeVariables.pie6, - themeVariables.pie7, - themeVariables.pie8, - themeVariables.pie9, - themeVariables.pie10, - themeVariables.pie11, - themeVariables.pie12, - ]; - - // Set the color scale - var color = scaleOrdinal().range(myGeneratedColors); - - // Compute the position of each group on the pie: - var pieData = Object.entries(data).map(function (el, idx) { - return { - order: idx, - name: el[0], - value: el[1], - }; - }); - var pie = d3pie() - .value(function (d) { - return d.value; - }) - .sort(function (a, b) { - // Sort slices in clockwise direction - return a.order - b.order; - }); - var dataReady = pie(pieData); - - // Shape helper to build arcs: - var arcGenerator = arc().innerRadius(0).outerRadius(radius); - - // Build the pie chart: each part of the pie is a path that we build using the arc function. - svg - .selectAll('mySlices') - .data(dataReady) - .enter() - .append('path') - .attr('d', arcGenerator) - .attr('fill', function (d) { - return color(d.data.name); - }) - .attr('class', 'pieCircle'); - - // Now add the percentage. - // Use the centroid method to get the best coordinates. - svg - .selectAll('mySlices') - .data(dataReady) - .enter() - .append('text') - .text(function (d) { - return ((d.data.value / sum) * 100).toFixed(0) + '%'; - }) - .attr('transform', function (d) { - return 'translate(' + arcGenerator.centroid(d) + ')'; - }) - .style('text-anchor', 'middle') - .attr('class', 'slice'); - - svg - .append('text') - .text(diagObj.db.getDiagramTitle()) - .attr('x', 0) - .attr('y', -(height - 50) / 2) - .attr('class', 'pieTitleText'); - - // Add the legends/annotations for each section - var legend = svg - .selectAll('.legend') - .data(color.domain()) - .enter() - .append('g') - .attr('class', 'legend') - .attr('transform', function (d, i) { - const height = legendRectSize + legendSpacing; - const offset = (height * color.domain().length) / 2; - const horizontal = 12 * legendRectSize; - const vertical = i * height - offset; - return 'translate(' + horizontal + ',' + vertical + ')'; - }); - - legend - .append('rect') - .attr('width', legendRectSize) - .attr('height', legendRectSize) - .style('fill', color) - .style('stroke', color); - - legend - .data(dataReady) - .append('text') - .attr('x', legendRectSize + legendSpacing) - .attr('y', legendRectSize - legendSpacing) - .text(function (d) { - if (diagObj.db.getShowData() || conf.showData || conf.pie.showData) { - return d.data.name + ' [' + d.data.value + ']'; - } else { - return d.data.name; - } - }); - } catch (e) { - log.error('Error while rendering info diagram'); - log.error(e); - } -}; - -export default { - draw, -}; diff --git a/packages/mermaid/src/diagrams/pie/pieRenderer.ts b/packages/mermaid/src/diagrams/pie/pieRenderer.ts new file mode 100644 index 000000000..80f4f0a5a --- /dev/null +++ b/packages/mermaid/src/diagrams/pie/pieRenderer.ts @@ -0,0 +1,182 @@ +import type d3 from 'd3'; +import { scaleOrdinal, pie as d3pie, arc } from 'd3'; + +import { log } from '../../logger.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import { getConfig } from '../../config.js'; +import { cleanAndMerge, parseFontSize } from '../../utils.js'; +import type { DrawDefinition, Group, SVG } from '../../diagram-api/types.js'; +import type { D3Sections, PieDB, Sections } from './pieTypes.js'; +import type { MermaidConfig, PieDiagramConfig } from '../../config.type.js'; +import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; + +const createPieArcs = (sections: Sections): d3.PieArcDatum[] => { + // Compute the position of each group on the pie: + const pieData: D3Sections[] = Object.entries(sections) + .map((element: [string, number]): D3Sections => { + return { + label: element[0], + value: element[1], + }; + }) + .sort((a: D3Sections, b: D3Sections): number => { + return b.value - a.value; + }); + const pie: d3.Pie = d3pie().value( + (d3Section: D3Sections): number => d3Section.value + ); + return pie(pieData); +}; + +/** + * Draws a Pie Chart with the data given in text. + * + * @param text - pie chart code + * @param id - diagram id + * @param _version - MermaidJS version from package.json. + * @param diagObj - A standard diagram containing the DB and the text and type etc of the diagram. + */ +export const draw: DrawDefinition = (text, id, _version, diagObj) => { + log.debug('rendering pie chart\n' + text); + + const db = diagObj.db as PieDB; + const globalConfig: MermaidConfig = getConfig(); + const pieConfig: Required = cleanAndMerge(db.getConfig(), globalConfig.pie); + + const height = 450; + // TODO: remove document width + const width: number = + document.getElementById(id)?.parentElement?.offsetWidth ?? pieConfig.useWidth; + const svg: SVG = selectSvgElement(id); + // Set viewBox + svg.attr('viewBox', `0 0 ${width} ${height}`); + configureSvgSize(svg, height, width, pieConfig.useMaxWidth); + + const MARGIN = 40; + const LEGEND_RECT_SIZE = 18; + const LEGEND_SPACING = 4; + + const group: Group = svg.append('g'); + group.attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')'); + + const { themeVariables } = globalConfig; + let [outerStrokeWidth] = parseFontSize(themeVariables.pieOuterStrokeWidth); + outerStrokeWidth ??= 2; + + const textPosition: number = pieConfig.textPosition; + const radius: number = Math.min(width, height) / 2 - MARGIN; + // Shape helper to build arcs: + const arcGenerator: d3.Arc> = arc< + d3.PieArcDatum + >() + .innerRadius(0) + .outerRadius(radius); + const labelArcGenerator: d3.Arc> = arc< + d3.PieArcDatum + >() + .innerRadius(radius * textPosition) + .outerRadius(radius * textPosition); + + group + .append('circle') + .attr('cx', 0) + .attr('cy', 0) + .attr('r', radius + outerStrokeWidth / 2) + .attr('class', 'pieOuterCircle'); + + const sections: Sections = db.getSections(); + const arcs: d3.PieArcDatum[] = createPieArcs(sections); + + const myGeneratedColors = [ + themeVariables.pie1, + themeVariables.pie2, + themeVariables.pie3, + themeVariables.pie4, + themeVariables.pie5, + themeVariables.pie6, + themeVariables.pie7, + themeVariables.pie8, + themeVariables.pie9, + themeVariables.pie10, + themeVariables.pie11, + themeVariables.pie12, + ]; + // Set the color scale + const color: d3.ScaleOrdinal = scaleOrdinal(myGeneratedColors); + + // Build the pie chart: each part of the pie is a path that we build using the arc function. + group + .selectAll('mySlices') + .data(arcs) + .enter() + .append('path') + .attr('d', arcGenerator) + .attr('fill', (datum: d3.PieArcDatum) => { + return color(datum.data.label); + }) + .attr('class', 'pieCircle'); + + let sum = 0; + Object.keys(sections).forEach((key: string): void => { + sum += sections[key]; + }); + // Now add the percentage. + // Use the centroid method to get the best coordinates. + group + .selectAll('mySlices') + .data(arcs) + .enter() + .append('text') + .text((datum: d3.PieArcDatum): string => { + return ((datum.data.value / sum) * 100).toFixed(0) + '%'; + }) + .attr('transform', (datum: d3.PieArcDatum): string => { + return 'translate(' + labelArcGenerator.centroid(datum) + ')'; + }) + .style('text-anchor', 'middle') + .attr('class', 'slice'); + + group + .append('text') + .text(db.getDiagramTitle()) + .attr('x', 0) + .attr('y', -(height - 50) / 2) + .attr('class', 'pieTitleText'); + + // Add the legends/annotations for each section + const legend = group + .selectAll('.legend') + .data(color.domain()) + .enter() + .append('g') + .attr('class', 'legend') + .attr('transform', (_datum, index: number): string => { + const height = LEGEND_RECT_SIZE + LEGEND_SPACING; + const offset = (height * color.domain().length) / 2; + const horizontal = 12 * LEGEND_RECT_SIZE; + const vertical = index * height - offset; + return 'translate(' + horizontal + ',' + vertical + ')'; + }); + + legend + .append('rect') + .attr('width', LEGEND_RECT_SIZE) + .attr('height', LEGEND_RECT_SIZE) + .style('fill', color) + .style('stroke', color); + + legend + .data(arcs) + .append('text') + .attr('x', LEGEND_RECT_SIZE + LEGEND_SPACING) + .attr('y', LEGEND_RECT_SIZE - LEGEND_SPACING) + .text((datum: d3.PieArcDatum): string => { + const { label, value } = datum.data; + if (db.getShowData()) { + return `${label} [${value}]`; + } + return label; + }); +}; + +export const renderer = { draw }; diff --git a/packages/mermaid/src/diagrams/pie/styles.js b/packages/mermaid/src/diagrams/pie/pieStyles.ts similarity index 66% rename from packages/mermaid/src/diagrams/pie/styles.js rename to packages/mermaid/src/diagrams/pie/pieStyles.ts index 8544501a3..39a7f21d5 100644 --- a/packages/mermaid/src/diagrams/pie/styles.js +++ b/packages/mermaid/src/diagrams/pie/pieStyles.ts @@ -1,10 +1,18 @@ -const getStyles = (options) => +import type { DiagramStylesProvider } from '../../diagram-api/types.js'; +import type { PieStyleOptions } from './pieTypes.js'; + +const getStyles: DiagramStylesProvider = (options: PieStyleOptions) => ` .pieCircle{ stroke: ${options.pieStrokeColor}; stroke-width : ${options.pieStrokeWidth}; opacity : ${options.pieOpacity}; } + .pieOuterCircle{ + stroke: ${options.pieOuterStrokeColor}; + stroke-width: ${options.pieOuterStrokeWidth}; + fill: none; + } .pieTitleText { text-anchor: middle; font-size: ${options.pieTitleTextSize}; diff --git a/packages/mermaid/src/diagrams/pie/pieTypes.ts b/packages/mermaid/src/diagrams/pie/pieTypes.ts new file mode 100644 index 000000000..67fb1dca2 --- /dev/null +++ b/packages/mermaid/src/diagrams/pie/pieTypes.ts @@ -0,0 +1,64 @@ +import type { PieDiagramConfig } from '../../config.type.js'; +import type { DiagramDB, ParseDirectiveDefinition } from '../../diagram-api/types.js'; + +export interface PieFields { + sections: Sections; + showData: boolean; + config: PieDiagramConfig; +} + +export interface PieStyleOptions { + fontFamily: string; + pie1: string; + pie2: string; + pie3: string; + pie4: string; + pie5: string; + pie6: string; + pie7: string; + pie8: string; + pie9: string; + pie10: string; + pie11: string; + pie12: string; + pieTitleTextSize: string; + pieTitleTextColor: string; + pieSectionTextSize: string; + pieSectionTextColor: string; + pieLegendTextSize: string; + pieLegendTextColor: string; + pieStrokeColor: string; + pieStrokeWidth: string; + pieOuterStrokeWidth: string; + pieOuterStrokeColor: string; + pieOpacity: string; +} + +export type Sections = Record; + +export interface D3Sections { + label: string; + value: number; +} + +export interface PieDB extends DiagramDB { + // config + getConfig: () => Required; + + // common db + parseDirective: ParseDirectiveDefinition; + clear: () => void; + setDiagramTitle: (title: string) => void; + getDiagramTitle: () => string; + setAccTitle: (title: string) => void; + getAccTitle: () => string; + setAccDescription: (describetion: string) => void; + getAccDescription: () => string; + + // diagram db + addSection: (label: string, value: number) => void; + getSections: () => Sections; + cleanupValue: (value: string) => number; + setShowData: (toggle: boolean) => void; + getShowData: () => boolean; +} diff --git a/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison b/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison new file mode 100644 index 000000000..00c125294 --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison @@ -0,0 +1,185 @@ +%lex +%options case-insensitive + +%x string +%x string +%x md_string +%x title +%x open_directive +%x type_directive +%x arg_directive +%x close_directive +%x acc_title +%x acc_descr +%x acc_descr_multiline +%x point_start +%x point_x +%x point_y +%% +\%\%\{ { this.begin('open_directive'); return 'open_directive'; } +((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } +":" { this.popState(); this.begin('arg_directive'); return ':'; } +\}\%\% { this.popState(); this.popState(); return 'close_directive'; } +((?:(?!\}\%\%).|\n)*) return 'arg_directive'; +\%\%(?!\{)[^\n]* /* skip comments */ +[^\}]\%\%[^\n]* /* skip comments */ +[\n\r]+ return 'NEWLINE'; +\%\%[^\n]* /* do nothing */ + +title { this.begin("title");return 'title'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; } + +accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } +<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } +accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } +<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } +accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} +<acc_descr_multiline>[\}] { this.popState(); } +<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value"; + +" "*"x-axis"" "* return 'X-AXIS'; +" "*"y-axis"" "* return 'Y-AXIS'; +" "*\-\-+\>" "* return 'AXIS-TEXT-DELIMITER' +" "*"quadrant-1"" "* return 'QUADRANT_1'; +" "*"quadrant-2"" "* return 'QUADRANT_2'; +" "*"quadrant-3"" "* return 'QUADRANT_3'; +" "*"quadrant-4"" "* return 'QUADRANT_4'; + +["][`] { this.begin("md_string");} +<md_string>[^`"]+ { return "MD_STR";} +<md_string>[`]["] { this.popState();} +["] this.begin("string"); +<string>["] this.popState(); +<string>[^"]* return "STR"; + +\s*\:\s*\[\s* {this.begin("point_start"); return 'point_start';} +<point_start>(1)|(0(.\d+)?) {this.begin('point_x'); return 'point_x';} +<point_start>\s*\]" "* {this.popState();} +<point_x>\s*\,\s* {this.popState(); this.begin('point_y');} +<point_y>(1)|(0(.\d+)?) {this.popState(); return 'point_y';} + +" "*"quadrantChart"" "* return 'QUADRANT'; + +[A-Za-z]+ return 'ALPHA'; +":" return 'COLON'; +\+ return 'PLUS'; +"," return 'COMMA'; +"=" return 'EQUALS'; +\= return 'EQUALS'; +"*" return 'MULT'; +\# return 'BRKT'; +[\_] return 'UNDERSCORE'; +"." return 'DOT'; +"&" return 'AMP'; +\- return 'MINUS'; +[0-9]+ return 'NUM'; +\s return 'SPACE'; +";" return 'SEMI'; +[!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION'; +<<EOF>> return 'EOF'; + +/lex + +%start start + +%% /* language grammar */ + +start + : eol start + | SPACE start + | directive start + | QUADRANT document + ; + +document + : /* empty */ + | document line + ; + +line + : statement eol + ; + +statement + : + | SPACE statement + | axisDetails + | quadrantDetails + | points + | title title_value { $$=$2.trim();yy.setDiagramTitle($$); } + | acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); } + | acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); } + | acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); } | section {yy.addSection($1.substr(8));$$=$1.substr(8);} + | directive + ; + +points + : text point_start point_x point_y {yy.addPoint($1, $3, $4);} + ; + +axisDetails + : X-AXIS text AXIS-TEXT-DELIMITER text {yy.setXAxisLeftText($2); yy.setXAxisRightText($4);} + | X-AXIS text AXIS-TEXT-DELIMITER {$2.text += " ⟶ "; yy.setXAxisLeftText($2);} + | X-AXIS text {yy.setXAxisLeftText($2);} + | Y-AXIS text AXIS-TEXT-DELIMITER text {yy.setYAxisBottomText($2); yy.setYAxisTopText($4);} + | Y-AXIS text AXIS-TEXT-DELIMITER {$2.text += " ⟶ "; yy.setYAxisBottomText($2);} + | Y-AXIS text {yy.setYAxisBottomText($2);} + ; + +quadrantDetails + : QUADRANT_1 text {yy.setQuadrant1Text($2)} + | QUADRANT_2 text {yy.setQuadrant2Text($2)} + | QUADRANT_3 text {yy.setQuadrant3Text($2)} + | QUADRANT_4 text {yy.setQuadrant4Text($2)} + ; + +directive + : openDirective typeDirective closeDirective + | openDirective typeDirective ':' argDirective closeDirective + ; + +eol + : NEWLINE + | SEMI + | EOF + ; + +openDirective + : open_directive { yy.parseDirective('%%{', 'open_directive'); } + ; + +typeDirective + : type_directive { yy.parseDirective($1, 'type_directive'); } + ; + +argDirective + : arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); } + ; + +closeDirective + : close_directive { yy.parseDirective('}%%', 'close_directive', 'quadrantChart'); } + ; + +text: alphaNumToken + { $$={text:$1, type: 'text'};} + | text textNoTagsToken + { $$={text:$1.text+''+$2, type: $1.type};} + | STR + { $$={text: $1, type: 'text'};} + | MD_STR + { $$={text: $1, type: 'markdown'};} + ; + +alphaNum + : alphaNumToken + {$$=$1;} + | alphaNum alphaNumToken + {$$=$1+''+$2;} + ; + + +alphaNumToken : PUNCTUATION | AMP | NUM| ALPHA | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ; + +textNoTagsToken: alphaNumToken | SPACE | MINUS; + +%% diff --git a/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison.spec.ts b/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison.spec.ts new file mode 100644 index 000000000..faa9281f0 --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison.spec.ts @@ -0,0 +1,299 @@ +// @ts-ignore: JISON doesn't support types +import { parser } from './quadrant.jison'; +import type { Mock } from 'vitest'; +import { vi } from 'vitest'; + +const parserFnConstructor = (str: string) => { + return () => { + parser.parse(str); + }; +}; + +const mockDB: Record<string, Mock<any, any>> = { + setQuadrant1Text: vi.fn(), + setQuadrant2Text: vi.fn(), + setQuadrant3Text: vi.fn(), + setQuadrant4Text: vi.fn(), + setXAxisLeftText: vi.fn(), + setXAxisRightText: vi.fn(), + setYAxisTopText: vi.fn(), + setYAxisBottomText: vi.fn(), + setDiagramTitle: vi.fn(), + parseDirective: vi.fn(), + addPoint: vi.fn(), +}; + +function clearMocks() { + for (const key in mockDB) { + mockDB[key].mockRestore(); + } +} + +describe('Testing quadrantChart jison file', () => { + beforeEach(() => { + parser.yy = mockDB; + clearMocks(); + }); + + it('should throw error if quadrantChart text is not there', () => { + const str = 'quadrant-1 do'; + expect(parserFnConstructor(str)).toThrow(); + }); + + it('should not throw error if only quadrantChart is there', () => { + const str = 'quadrantChart'; + expect(parserFnConstructor(str)).not.toThrow(); + }); + + it('should be able to parse directive', () => { + const str = + '%%{init: {"quadrantChart": {"chartWidth": 600, "chartHeight": 600} } }%% \n quadrantChart'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.parseDirective.mock.calls[0]).toEqual(['%%{', 'open_directive']); + expect(mockDB.parseDirective.mock.calls[1]).toEqual(['init', 'type_directive']); + expect(mockDB.parseDirective.mock.calls[2]).toEqual([ + '{"quadrantChart": {"chartWidth": 600, "chartHeight": 600} }', + 'arg_directive', + ]); + expect(mockDB.parseDirective.mock.calls[3]).toEqual([ + '}%%', + 'close_directive', + 'quadrantChart', + ]); + }); + + it('should be able to parse xAxis text', () => { + let str = 'quadrantChart\nx-axis urgent --> not urgent'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({ text: 'urgent', type: 'text' }); + expect(mockDB.setXAxisRightText).toHaveBeenCalledWith({ text: 'not urgent', type: 'text' }); + + clearMocks(); + str = 'quadrantChart\n x-AxIs Urgent --> Not Urgent \n'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({ text: 'Urgent', type: 'text' }); + expect(mockDB.setXAxisRightText).toHaveBeenCalledWith({ text: 'Not Urgent ', type: 'text' }); + + clearMocks(); + str = + 'quadrantChart\n x-AxIs "Urgent(* +=[❤" --> "Not Urgent (* +=[❤"\n '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({ text: 'Urgent(* +=[❤', type: 'text' }); + expect(mockDB.setXAxisRightText).toHaveBeenCalledWith({ + text: 'Not Urgent (* +=[❤', + type: 'text', + }); + + clearMocks(); + str = 'quadrantChart\n x-AxIs "Urgent(* +=[❤"'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({ text: 'Urgent(* +=[❤', type: 'text' }); + expect(mockDB.setXAxisRightText).not.toHaveBeenCalled(); + + clearMocks(); + str = 'quadrantChart\n x-AxIs "Urgent(* +=[❤" --> '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({ + text: 'Urgent(* +=[❤ ⟶ ', + type: 'text', + }); + expect(mockDB.setXAxisRightText).not.toHaveBeenCalled(); + }); + + it('should be able to parse yAxis text', () => { + let str = 'quadrantChart\ny-axis urgent --> not urgent'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({ text: 'urgent', type: 'text' }); + expect(mockDB.setYAxisTopText).toHaveBeenCalledWith({ text: 'not urgent', type: 'text' }); + + clearMocks(); + str = 'quadrantChart\n y-AxIs Urgent --> Not Urgent \n'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({ text: 'Urgent', type: 'text' }); + expect(mockDB.setYAxisTopText).toHaveBeenCalledWith({ text: 'Not Urgent ', type: 'text' }); + + clearMocks(); + str = + 'quadrantChart\n Y-AxIs "Urgent(* +=[❤" --> "Not Urgent (* +=[❤"\n '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({ text: 'Urgent(* +=[❤', type: 'text' }); + expect(mockDB.setYAxisTopText).toHaveBeenCalledWith({ + text: 'Not Urgent (* +=[❤', + type: 'text', + }); + + clearMocks(); + str = 'quadrantChart\n y-AxIs "Urgent(* +=[❤"'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({ text: 'Urgent(* +=[❤', type: 'text' }); + expect(mockDB.setYAxisTopText).not.toHaveBeenCalled(); + + clearMocks(); + str = 'quadrantChart\n y-AxIs "Urgent(* +=[❤" --> '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({ + text: 'Urgent(* +=[❤ ⟶ ', + type: 'text', + }); + expect(mockDB.setYAxisTopText).not.toHaveBeenCalled(); + }); + + it('should be able to parse quadrant1 text', () => { + let str = 'quadrantChart\nquadrant-1 Plan'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant1Text).toHaveBeenCalledWith({ text: 'Plan', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-1 Plan '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant1Text).toHaveBeenCalledWith({ text: 'Plan ', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-1 "Plan(* +=[❤"'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant1Text).toHaveBeenCalledWith({ text: 'Plan(* +=[❤', type: 'text' }); + }); + + it('should be able to parse quadrant2 text', () => { + let str = 'quadrantChart\nquadrant-2 do'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant2Text).toHaveBeenCalledWith({ text: 'do', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-2 Do '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant2Text).toHaveBeenCalledWith({ text: 'Do ', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-2 "Do(* +=[❤"'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant2Text).toHaveBeenCalledWith({ text: 'Do(* +=[❤', type: 'text' }); + }); + + it('should be able to parse quadrant3 text', () => { + let str = 'quadrantChart\nquadrant-3 deligate'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant3Text).toHaveBeenCalledWith({ text: 'deligate', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-3 Deligate '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant3Text).toHaveBeenCalledWith({ text: 'Deligate ', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-3 "Deligate(* +=[❤"'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant3Text).toHaveBeenCalledWith({ text: 'Deligate(* +=[❤', type: 'text' }); + }); + + it('should be able to parse quadrant4 text', () => { + let str = 'quadrantChart\nquadrant-4 delete'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant4Text).toHaveBeenCalledWith({ text: 'delete', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-4 Delete '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant4Text).toHaveBeenCalledWith({ text: 'Delete ', type: 'text' }); + + clearMocks(); + str = 'QuadRantChart \n QuaDrant-4 "Delete(* +=[❤"'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setQuadrant4Text).toHaveBeenCalledWith({ text: 'Delete(* +=[❤', type: 'text' }); + }); + + it('should be able to parse title', () => { + let str = 'quadrantChart\ntitle this is title'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setDiagramTitle).toHaveBeenCalledWith('this is title'); + + clearMocks(); + str = 'QuadRantChart \n TiTle this Is title '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setDiagramTitle).toHaveBeenCalledWith('this Is title'); + + clearMocks(); + str = 'QuadRantChart \n title "this is title (* +=[❤"'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setDiagramTitle).toHaveBeenCalledWith('"this is title (* +=[❤"'); + }); + + it('should be able to parse points', () => { + let str = 'quadrantChart\npoint1: [0.1, 0.4]'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.addPoint).toHaveBeenCalledWith({ text: 'point1', type: 'text' }, '0.1', '0.4'); + + clearMocks(); + str = 'QuadRantChart \n Point1 : [0.1, 0.4] '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.addPoint).toHaveBeenCalledWith({ text: 'Point1', type: 'text' }, '0.1', '0.4'); + + clearMocks(); + str = 'QuadRantChart \n "Point1 : (* +=[❤": [1, 0] '; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.addPoint).toHaveBeenCalledWith( + { text: 'Point1 : (* +=[❤', type: 'text' }, + '1', + '0' + ); + + clearMocks(); + str = 'QuadRantChart \n Point1 : [1.2, 0.4] '; + expect(parserFnConstructor(str)).toThrow(); + }); + + it('should be able to parse the whole chart', () => { + const str = `%%{init: {"quadrantChart": {"chartWidth": 600, "chartHeight": 600} } }%% + quadrantChart + title Analytics and Business Intelligence Platforms + x-axis "Completeness of Vision ❤" --> "x-axis-2" + y-axis Ability to Execute --> "y-axis-2" + quadrant-1 Leaders + quadrant-2 Challengers + quadrant-3 Niche + quadrant-4 Visionaries + Microsoft: [0.75, 0.75] + Salesforce: [0.55, 0.60] + IBM: [0.51, 0.40] + Incorta: [0.20, 0.30]`; + + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.parseDirective.mock.calls[0]).toEqual(['%%{', 'open_directive']); + expect(mockDB.parseDirective.mock.calls[1]).toEqual(['init', 'type_directive']); + expect(mockDB.parseDirective.mock.calls[2]).toEqual([ + '{"quadrantChart": {"chartWidth": 600, "chartHeight": 600} }', + 'arg_directive', + ]); + expect(mockDB.parseDirective.mock.calls[3]).toEqual([ + '}%%', + 'close_directive', + 'quadrantChart', + ]); + expect(mockDB.setXAxisLeftText).toHaveBeenCalledWith({ + text: 'Completeness of Vision ❤', + type: 'text', + }); + expect(mockDB.setXAxisRightText).toHaveBeenCalledWith({ text: 'x-axis-2', type: 'text' }); + expect(mockDB.setYAxisTopText).toHaveBeenCalledWith({ text: 'y-axis-2', type: 'text' }); + expect(mockDB.setYAxisBottomText).toHaveBeenCalledWith({ + text: 'Ability to Execute', + type: 'text', + }); + expect(mockDB.setQuadrant1Text).toHaveBeenCalledWith({ text: 'Leaders', type: 'text' }); + expect(mockDB.setQuadrant2Text).toHaveBeenCalledWith({ text: 'Challengers', type: 'text' }); + expect(mockDB.setQuadrant3Text).toHaveBeenCalledWith({ text: 'Niche', type: 'text' }); + expect(mockDB.setQuadrant4Text).toHaveBeenCalledWith({ text: 'Visionaries', type: 'text' }); + expect(mockDB.addPoint).toHaveBeenCalledWith( + { text: 'Microsoft', type: 'text' }, + '0.75', + '0.75' + ); + expect(mockDB.addPoint).toHaveBeenCalledWith( + { text: 'Salesforce', type: 'text' }, + '0.55', + '0.60' + ); + expect(mockDB.addPoint).toHaveBeenCalledWith({ text: 'IBM', type: 'text' }, '0.51', '0.40'); + expect(mockDB.addPoint).toHaveBeenCalledWith({ text: 'Incorta', type: 'text' }, '0.20', '0.30'); + }); +}); diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts new file mode 100644 index 000000000..9c1162762 --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts @@ -0,0 +1,602 @@ +// @ts-ignore: TODO Fix ts errors +import { scaleLinear } from 'd3'; +import { log } from '../../logger.js'; +import type { BaseDiagramConfig, QuadrantChartConfig } from '../../config.type.js'; +import defaultConfig from '../../defaultConfig.js'; +import { getThemeVariables } from '../../themes/theme-default.js'; + +const defaultThemeVariables = getThemeVariables(); + +export type TextVerticalPos = 'left' | 'center' | 'right'; +export type TextHorizontalPos = 'top' | 'middle' | 'bottom'; + +export interface Point { + x: number; + y: number; +} + +export interface QuadrantPointInputType extends Point { + text: string; +} + +export interface QuadrantTextType extends Point { + text: string; + fill: string; + verticalPos: TextVerticalPos; + horizontalPos: TextHorizontalPos; + fontSize: number; + rotation: number; +} + +export interface QuadrantPointType extends Point { + fill: string; + radius: number; + text: QuadrantTextType; +} + +export interface QuadrantQuadrantsType extends Point { + text: QuadrantTextType; + width: number; + height: number; + fill: string; +} + +export interface QuadrantLineType { + strokeWidth: number; + strokeFill: string; + x1: number; + y1: number; + x2: number; + y2: number; +} + +export interface QuadrantBuildType { + points: QuadrantPointType[]; + quadrants: QuadrantQuadrantsType[]; + axisLabels: QuadrantTextType[]; + title?: QuadrantTextType; + borderLines?: QuadrantLineType[]; +} + +export interface quadrantBuilderData { + titleText: string; + quadrant1Text: string; + quadrant2Text: string; + quadrant3Text: string; + quadrant4Text: string; + xAxisLeftText: string; + xAxisRightText: string; + yAxisBottomText: string; + yAxisTopText: string; + points: QuadrantPointInputType[]; +} + +export interface QuadrantBuilderConfig + extends Required<Omit<QuadrantChartConfig, keyof BaseDiagramConfig>> { + showXAxis: boolean; + showYAxis: boolean; + showTitle: boolean; +} + +export interface QuadrantBuilderThemeConfig { + quadrantTitleFill: string; + quadrant1Fill: string; + quadrant2Fill: string; + quadrant3Fill: string; + quadrant4Fill: string; + quadrant1TextFill: string; + quadrant2TextFill: string; + quadrant3TextFill: string; + quadrant4TextFill: string; + quadrantPointFill: string; + quadrantPointTextFill: string; + quadrantXAxisTextFill: string; + quadrantYAxisTextFill: string; + quadrantInternalBorderStrokeFill: string; + quadrantExternalBorderStrokeFill: string; +} + +interface CalculateSpaceData { + xAxisSpace: { + top: number; + bottom: number; + }; + yAxisSpace: { + left: number; + right: number; + }; + titleSpace: { + top: number; + }; + quadrantSpace: { + quadrantLeft: number; + quadrantTop: number; + quadrantWidth: number; + quadrantHalfWidth: number; + quadrantHeight: number; + quadrantHalfHeight: number; + }; +} + +export class QuadrantBuilder { + private config: QuadrantBuilderConfig; + private themeConfig: QuadrantBuilderThemeConfig; + private data: quadrantBuilderData; + + constructor() { + this.config = this.getDefaultConfig(); + this.themeConfig = this.getDefaultThemeConfig(); + this.data = this.getDefaultData(); + } + + getDefaultData(): quadrantBuilderData { + return { + titleText: '', + quadrant1Text: '', + quadrant2Text: '', + quadrant3Text: '', + quadrant4Text: '', + xAxisLeftText: '', + xAxisRightText: '', + yAxisBottomText: '', + yAxisTopText: '', + points: [], + }; + } + + getDefaultConfig(): QuadrantBuilderConfig { + return { + showXAxis: true, + showYAxis: true, + showTitle: true, + chartHeight: defaultConfig.quadrantChart?.chartWidth || 500, + chartWidth: defaultConfig.quadrantChart?.chartHeight || 500, + titlePadding: defaultConfig.quadrantChart?.titlePadding || 10, + titleFontSize: defaultConfig.quadrantChart?.titleFontSize || 20, + quadrantPadding: defaultConfig.quadrantChart?.quadrantPadding || 5, + xAxisLabelPadding: defaultConfig.quadrantChart?.xAxisLabelPadding || 5, + yAxisLabelPadding: defaultConfig.quadrantChart?.yAxisLabelPadding || 5, + xAxisLabelFontSize: defaultConfig.quadrantChart?.xAxisLabelFontSize || 16, + yAxisLabelFontSize: defaultConfig.quadrantChart?.yAxisLabelFontSize || 16, + quadrantLabelFontSize: defaultConfig.quadrantChart?.quadrantLabelFontSize || 16, + quadrantTextTopPadding: defaultConfig.quadrantChart?.quadrantTextTopPadding || 5, + pointTextPadding: defaultConfig.quadrantChart?.pointTextPadding || 5, + pointLabelFontSize: defaultConfig.quadrantChart?.pointLabelFontSize || 12, + pointRadius: defaultConfig.quadrantChart?.pointRadius || 5, + xAxisPosition: defaultConfig.quadrantChart?.xAxisPosition || 'top', + yAxisPosition: defaultConfig.quadrantChart?.yAxisPosition || 'left', + quadrantInternalBorderStrokeWidth: + defaultConfig.quadrantChart?.quadrantInternalBorderStrokeWidth || 1, + quadrantExternalBorderStrokeWidth: + defaultConfig.quadrantChart?.quadrantExternalBorderStrokeWidth || 2, + }; + } + + getDefaultThemeConfig(): QuadrantBuilderThemeConfig { + return { + quadrant1Fill: defaultThemeVariables.quadrant1Fill, + quadrant2Fill: defaultThemeVariables.quadrant2Fill, + quadrant3Fill: defaultThemeVariables.quadrant3Fill, + quadrant4Fill: defaultThemeVariables.quadrant4Fill, + quadrant1TextFill: defaultThemeVariables.quadrant1TextFill, + quadrant2TextFill: defaultThemeVariables.quadrant2TextFill, + quadrant3TextFill: defaultThemeVariables.quadrant3TextFill, + quadrant4TextFill: defaultThemeVariables.quadrant4TextFill, + quadrantPointFill: defaultThemeVariables.quadrantPointFill, + quadrantPointTextFill: defaultThemeVariables.quadrantPointTextFill, + quadrantXAxisTextFill: defaultThemeVariables.quadrantXAxisTextFill, + quadrantYAxisTextFill: defaultThemeVariables.quadrantYAxisTextFill, + quadrantTitleFill: defaultThemeVariables.quadrantTitleFill, + quadrantInternalBorderStrokeFill: defaultThemeVariables.quadrantInternalBorderStrokeFill, + quadrantExternalBorderStrokeFill: defaultThemeVariables.quadrantExternalBorderStrokeFill, + }; + } + + clear() { + this.config = this.getDefaultConfig(); + this.themeConfig = this.getDefaultThemeConfig(); + this.data = this.getDefaultData(); + log.info('clear called'); + } + + setData(data: Partial<quadrantBuilderData>) { + this.data = { ...this.data, ...data }; + } + + addPoints(points: QuadrantPointInputType[]) { + this.data.points = [...points, ...this.data.points]; + } + + setConfig(config: Partial<QuadrantBuilderConfig>) { + log.trace('setConfig called with: ', config); + this.config = { ...this.config, ...config }; + } + + setThemeConfig(themeConfig: Partial<QuadrantBuilderThemeConfig>) { + log.trace('setThemeConfig called with: ', themeConfig); + this.themeConfig = { ...this.themeConfig, ...themeConfig }; + } + + calculateSpace( + xAxisPosition: typeof this.config.xAxisPosition, + showXAxis: boolean, + showYAxis: boolean, + showTitle: boolean + ): CalculateSpaceData { + const xAxisSpaceCalculation = + this.config.xAxisLabelPadding * 2 + this.config.xAxisLabelFontSize; + const xAxisSpace = { + top: xAxisPosition === 'top' && showXAxis ? xAxisSpaceCalculation : 0, + bottom: xAxisPosition === 'bottom' && showXAxis ? xAxisSpaceCalculation : 0, + }; + + const yAxisSpaceCalculation = + this.config.yAxisLabelPadding * 2 + this.config.yAxisLabelFontSize; + const yAxisSpace = { + left: this.config.yAxisPosition === 'left' && showYAxis ? yAxisSpaceCalculation : 0, + right: this.config.yAxisPosition === 'right' && showYAxis ? yAxisSpaceCalculation : 0, + }; + + const titleSpaceCalculation = this.config.titleFontSize + this.config.titlePadding * 2; + const titleSpace = { + top: showTitle ? titleSpaceCalculation : 0, + }; + + const quadrantLeft = this.config.quadrantPadding + yAxisSpace.left; + const quadrantTop = this.config.quadrantPadding + xAxisSpace.top + titleSpace.top; + const quadrantWidth = + this.config.chartWidth - this.config.quadrantPadding * 2 - yAxisSpace.left - yAxisSpace.right; + const quadrantHeight = + this.config.chartHeight - + this.config.quadrantPadding * 2 - + xAxisSpace.top - + xAxisSpace.bottom - + titleSpace.top; + + const quadrantHalfWidth = quadrantWidth / 2; + const quadrantHalfHeight = quadrantHeight / 2; + const quadrantSpace = { + quadrantLeft, + quadrantTop, + quadrantWidth, + quadrantHalfWidth, + quadrantHeight, + quadrantHalfHeight, + }; + + return { + xAxisSpace, + yAxisSpace, + titleSpace, + quadrantSpace, + }; + } + + getAxisLabels( + xAxisPosition: typeof this.config.xAxisPosition, + showXAxis: boolean, + showYAxis: boolean, + spaceData: CalculateSpaceData + ): QuadrantTextType[] { + const { quadrantSpace, titleSpace } = spaceData; + const { + quadrantHalfHeight, + quadrantHeight, + quadrantLeft, + quadrantHalfWidth, + quadrantTop, + quadrantWidth, + } = quadrantSpace; + const drawAxisLabelInMiddle = this.data.points.length === 0; + const axisLabels: QuadrantTextType[] = []; + + if (this.data.xAxisLeftText && showXAxis) { + axisLabels.push({ + text: this.data.xAxisLeftText, + fill: this.themeConfig.quadrantXAxisTextFill, + x: quadrantLeft + (drawAxisLabelInMiddle ? quadrantHalfWidth / 2 : 0), + y: + xAxisPosition === 'top' + ? this.config.xAxisLabelPadding + titleSpace.top + : this.config.xAxisLabelPadding + + quadrantTop + + quadrantHeight + + this.config.quadrantPadding, + fontSize: this.config.xAxisLabelFontSize, + verticalPos: drawAxisLabelInMiddle ? 'center' : 'left', + horizontalPos: 'top', + rotation: 0, + }); + } + if (this.data.xAxisRightText && showXAxis) { + axisLabels.push({ + text: this.data.xAxisRightText, + fill: this.themeConfig.quadrantXAxisTextFill, + x: quadrantLeft + quadrantHalfWidth + (drawAxisLabelInMiddle ? quadrantHalfWidth / 2 : 0), + y: + xAxisPosition === 'top' + ? this.config.xAxisLabelPadding + titleSpace.top + : this.config.xAxisLabelPadding + + quadrantTop + + quadrantHeight + + this.config.quadrantPadding, + fontSize: this.config.xAxisLabelFontSize, + verticalPos: drawAxisLabelInMiddle ? 'center' : 'left', + horizontalPos: 'top', + rotation: 0, + }); + } + + if (this.data.yAxisBottomText && showYAxis) { + axisLabels.push({ + text: this.data.yAxisBottomText, + fill: this.themeConfig.quadrantYAxisTextFill, + x: + this.config.yAxisPosition === 'left' + ? this.config.yAxisLabelPadding + : this.config.yAxisLabelPadding + + quadrantLeft + + quadrantWidth + + this.config.quadrantPadding, + y: quadrantTop + quadrantHeight - (drawAxisLabelInMiddle ? quadrantHalfHeight / 2 : 0), + fontSize: this.config.yAxisLabelFontSize, + verticalPos: drawAxisLabelInMiddle ? 'center' : 'left', + horizontalPos: 'top', + rotation: -90, + }); + } + if (this.data.yAxisTopText && showYAxis) { + axisLabels.push({ + text: this.data.yAxisTopText, + fill: this.themeConfig.quadrantYAxisTextFill, + x: + this.config.yAxisPosition === 'left' + ? this.config.yAxisLabelPadding + : this.config.yAxisLabelPadding + + quadrantLeft + + quadrantWidth + + this.config.quadrantPadding, + y: quadrantTop + quadrantHalfHeight - (drawAxisLabelInMiddle ? quadrantHalfHeight / 2 : 0), + fontSize: this.config.yAxisLabelFontSize, + verticalPos: drawAxisLabelInMiddle ? 'center' : 'left', + horizontalPos: 'top', + rotation: -90, + }); + } + return axisLabels; + } + + getQuadrants(spaceData: CalculateSpaceData): QuadrantQuadrantsType[] { + const { quadrantSpace } = spaceData; + + const { quadrantHalfHeight, quadrantLeft, quadrantHalfWidth, quadrantTop } = quadrantSpace; + + const quadrants: QuadrantQuadrantsType[] = [ + { + text: { + text: this.data.quadrant1Text, + fill: this.themeConfig.quadrant1TextFill, + x: 0, + y: 0, + fontSize: this.config.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft + quadrantHalfWidth, + y: quadrantTop, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.themeConfig.quadrant1Fill, + }, + { + text: { + text: this.data.quadrant2Text, + fill: this.themeConfig.quadrant2TextFill, + x: 0, + y: 0, + fontSize: this.config.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft, + y: quadrantTop, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.themeConfig.quadrant2Fill, + }, + { + text: { + text: this.data.quadrant3Text, + fill: this.themeConfig.quadrant3TextFill, + x: 0, + y: 0, + fontSize: this.config.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft, + y: quadrantTop + quadrantHalfHeight, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.themeConfig.quadrant3Fill, + }, + { + text: { + text: this.data.quadrant4Text, + fill: this.themeConfig.quadrant4TextFill, + x: 0, + y: 0, + fontSize: this.config.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft + quadrantHalfWidth, + y: quadrantTop + quadrantHalfHeight, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.themeConfig.quadrant4Fill, + }, + ]; + for (const quadrant of quadrants) { + quadrant.text.x = quadrant.x + quadrant.width / 2; + // place the text in the center of the box + if (this.data.points.length === 0) { + quadrant.text.y = quadrant.y + quadrant.height / 2; + quadrant.text.horizontalPos = 'middle'; + // place the text top of the quadrant square + } else { + quadrant.text.y = quadrant.y + this.config.quadrantTextTopPadding; + quadrant.text.horizontalPos = 'top'; + } + } + + return quadrants; + } + + getQuadrantPoints(spaceData: CalculateSpaceData): QuadrantPointType[] { + const { quadrantSpace } = spaceData; + + const { quadrantHeight, quadrantLeft, quadrantTop, quadrantWidth } = quadrantSpace; + + const xAxis = scaleLinear() + .domain([0, 1]) + .range([quadrantLeft, quadrantWidth + quadrantLeft]); + + const yAxis = scaleLinear() + .domain([0, 1]) + .range([quadrantHeight + quadrantTop, quadrantTop]); + + const points: QuadrantPointType[] = this.data.points.map((point) => { + const props: QuadrantPointType = { + x: xAxis(point.x), + y: yAxis(point.y), + fill: this.themeConfig.quadrantPointFill, + radius: this.config.pointRadius, + text: { + text: point.text, + fill: this.themeConfig.quadrantPointTextFill, + x: xAxis(point.x), + y: yAxis(point.y) + this.config.pointTextPadding, + verticalPos: 'center', + horizontalPos: 'top', + fontSize: this.config.pointLabelFontSize, + rotation: 0, + }, + }; + return props; + }); + return points; + } + + getBorders(spaceData: CalculateSpaceData): QuadrantLineType[] { + const halfExternalBorderWidth = this.config.quadrantExternalBorderStrokeWidth / 2; + const { quadrantSpace } = spaceData; + + const { + quadrantHalfHeight, + quadrantHeight, + quadrantLeft, + quadrantHalfWidth, + quadrantTop, + quadrantWidth, + } = quadrantSpace; + + const borderLines: QuadrantLineType[] = [ + // top border + { + strokeFill: this.themeConfig.quadrantExternalBorderStrokeFill, + strokeWidth: this.config.quadrantExternalBorderStrokeWidth, + x1: quadrantLeft - halfExternalBorderWidth, + y1: quadrantTop, + x2: quadrantLeft + quadrantWidth + halfExternalBorderWidth, + y2: quadrantTop, + }, + // right border + { + strokeFill: this.themeConfig.quadrantExternalBorderStrokeFill, + strokeWidth: this.config.quadrantExternalBorderStrokeWidth, + x1: quadrantLeft + quadrantWidth, + y1: quadrantTop + halfExternalBorderWidth, + x2: quadrantLeft + quadrantWidth, + y2: quadrantTop + quadrantHeight - halfExternalBorderWidth, + }, + // bottom border + { + strokeFill: this.themeConfig.quadrantExternalBorderStrokeFill, + strokeWidth: this.config.quadrantExternalBorderStrokeWidth, + x1: quadrantLeft - halfExternalBorderWidth, + y1: quadrantTop + quadrantHeight, + x2: quadrantLeft + quadrantWidth + halfExternalBorderWidth, + y2: quadrantTop + quadrantHeight, + }, + // left border + { + strokeFill: this.themeConfig.quadrantExternalBorderStrokeFill, + strokeWidth: this.config.quadrantExternalBorderStrokeWidth, + x1: quadrantLeft, + y1: quadrantTop + halfExternalBorderWidth, + x2: quadrantLeft, + y2: quadrantTop + quadrantHeight - halfExternalBorderWidth, + }, + // vertical inner border + { + strokeFill: this.themeConfig.quadrantInternalBorderStrokeFill, + strokeWidth: this.config.quadrantInternalBorderStrokeWidth, + x1: quadrantLeft + quadrantHalfWidth, + y1: quadrantTop + halfExternalBorderWidth, + x2: quadrantLeft + quadrantHalfWidth, + y2: quadrantTop + quadrantHeight - halfExternalBorderWidth, + }, + // horizontal inner border + { + strokeFill: this.themeConfig.quadrantInternalBorderStrokeFill, + strokeWidth: this.config.quadrantInternalBorderStrokeWidth, + x1: quadrantLeft + halfExternalBorderWidth, + y1: quadrantTop + quadrantHalfHeight, + x2: quadrantLeft + quadrantWidth - halfExternalBorderWidth, + y2: quadrantTop + quadrantHalfHeight, + }, + ]; + return borderLines; + } + + getTitle(showTitle: boolean): QuadrantTextType | undefined { + if (showTitle) { + return { + text: this.data.titleText, + fill: this.themeConfig.quadrantTitleFill, + fontSize: this.config.titleFontSize, + horizontalPos: 'top', + verticalPos: 'center', + rotation: 0, + y: this.config.titlePadding, + x: this.config.chartWidth / 2, + }; + } + return; + } + + build(): QuadrantBuildType { + const showXAxis = + this.config.showXAxis && !!(this.data.xAxisLeftText || this.data.xAxisRightText); + const showYAxis = + this.config.showYAxis && !!(this.data.yAxisTopText || this.data.yAxisBottomText); + const showTitle = this.config.showTitle && !!this.data.titleText; + + const xAxisPosition = this.data.points.length > 0 ? 'bottom' : this.config.xAxisPosition; + + const calculatedSpace = this.calculateSpace(xAxisPosition, showXAxis, showYAxis, showTitle); + + return { + points: this.getQuadrantPoints(calculatedSpace), + quadrants: this.getQuadrants(calculatedSpace), + axisLabels: this.getAxisLabels(xAxisPosition, showXAxis, showYAxis, calculatedSpace), + borderLines: this.getBorders(calculatedSpace), + title: this.getTitle(showTitle), + }; + } +} diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts new file mode 100644 index 000000000..0dc87a2d4 --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts @@ -0,0 +1,128 @@ +import { log } from '../../logger.js'; +import mermaidAPI from '../../mermaidAPI.js'; +import * as configApi from '../../config.js'; +import { sanitizeText } from '../common/common.js'; +import { + setAccTitle, + getAccTitle, + setDiagramTitle, + getDiagramTitle, + getAccDescription, + setAccDescription, + clear as commonClear, +} from '../common/commonDb.js'; +import { QuadrantBuilder } from './quadrantBuilder.js'; + +const config = configApi.getConfig(); + +function textSanitizer(text: string) { + return sanitizeText(text.trim(), config); +} + +type LexTextObj = { text: string; type: 'text' | 'markdown' }; + +const quadrantBuilder = new QuadrantBuilder(); + +function setQuadrant1Text(textObj: LexTextObj) { + quadrantBuilder.setData({ quadrant1Text: textSanitizer(textObj.text) }); +} + +function setQuadrant2Text(textObj: LexTextObj) { + quadrantBuilder.setData({ quadrant2Text: textSanitizer(textObj.text) }); +} + +function setQuadrant3Text(textObj: LexTextObj) { + quadrantBuilder.setData({ quadrant3Text: textSanitizer(textObj.text) }); +} + +function setQuadrant4Text(textObj: LexTextObj) { + quadrantBuilder.setData({ quadrant4Text: textSanitizer(textObj.text) }); +} + +function setXAxisLeftText(textObj: LexTextObj) { + quadrantBuilder.setData({ xAxisLeftText: textSanitizer(textObj.text) }); +} + +function setXAxisRightText(textObj: LexTextObj) { + quadrantBuilder.setData({ xAxisRightText: textSanitizer(textObj.text) }); +} + +function setYAxisTopText(textObj: LexTextObj) { + quadrantBuilder.setData({ yAxisTopText: textSanitizer(textObj.text) }); +} + +function setYAxisBottomText(textObj: LexTextObj) { + quadrantBuilder.setData({ yAxisBottomText: textSanitizer(textObj.text) }); +} + +function addPoint(textObj: LexTextObj, x: number, y: number) { + quadrantBuilder.addPoints([{ x, y, text: textSanitizer(textObj.text) }]); +} + +function setWidth(width: number) { + quadrantBuilder.setConfig({ chartWidth: width }); +} + +function setHeight(height: number) { + quadrantBuilder.setConfig({ chartHeight: height }); +} + +function getQuadrantData() { + const config = configApi.getConfig(); + const { themeVariables, quadrantChart: quadrantChartConfig } = config; + if (quadrantChartConfig) { + quadrantBuilder.setConfig(quadrantChartConfig); + } + quadrantBuilder.setThemeConfig({ + quadrant1Fill: themeVariables.quadrant1Fill, + quadrant2Fill: themeVariables.quadrant2Fill, + quadrant3Fill: themeVariables.quadrant3Fill, + quadrant4Fill: themeVariables.quadrant4Fill, + quadrant1TextFill: themeVariables.quadrant1TextFill, + quadrant2TextFill: themeVariables.quadrant2TextFill, + quadrant3TextFill: themeVariables.quadrant3TextFill, + quadrant4TextFill: themeVariables.quadrant4TextFill, + quadrantPointFill: themeVariables.quadrantPointFill, + quadrantPointTextFill: themeVariables.quadrantPointTextFill, + quadrantXAxisTextFill: themeVariables.quadrantXAxisTextFill, + quadrantYAxisTextFill: themeVariables.quadrantYAxisTextFill, + quadrantExternalBorderStrokeFill: themeVariables.quadrantExternalBorderStrokeFill, + quadrantInternalBorderStrokeFill: themeVariables.quadrantInternalBorderStrokeFill, + quadrantTitleFill: themeVariables.quadrantTitleFill, + }); + quadrantBuilder.setData({ titleText: getDiagramTitle() }); + return quadrantBuilder.build(); +} + +export const parseDirective = function (statement: string, context: string, type: string) { + // @ts-ignore: TODO Fix ts errors + mermaidAPI.parseDirective(this, statement, context, type); +}; + +const clear = function () { + quadrantBuilder.clear(); + commonClear(); +}; + +export default { + setWidth, + setHeight, + setQuadrant1Text, + setQuadrant2Text, + setQuadrant3Text, + setQuadrant4Text, + setXAxisLeftText, + setXAxisRightText, + setYAxisTopText, + setYAxisBottomText, + addPoint, + getQuadrantData, + parseDirective, + clear, + setAccTitle, + getAccTitle, + setDiagramTitle, + getDiagramTitle, + getAccDescription, + setAccDescription, +}; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDetector.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDetector.ts new file mode 100644 index 000000000..9a77ca43a --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDetector.ts @@ -0,0 +1,24 @@ +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; + +const id = 'quadrantChart'; + +const detector: DiagramDetector = (txt) => { + return /^\s*quadrantChart/.test(txt); +}; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./quadrantDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts new file mode 100644 index 000000000..a9e822d0e --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts @@ -0,0 +1,12 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: JISON doesn't support types +import parser from './parser/quadrant.jison'; +import db from './quadrantDb.js'; +import renderer from './quadrantRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles: () => '', +}; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts new file mode 100644 index 000000000..9dd309b53 --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts @@ -0,0 +1,173 @@ +// @ts-nocheck - don't check until handle it +import { select } from 'd3'; +import * as configApi from '../../config.js'; +import { log } from '../../logger.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import type { Diagram } from '../../Diagram.js'; +import type { + QuadrantBuildType, + QuadrantLineType, + QuadrantPointType, + QuadrantQuadrantsType, + QuadrantTextType, + TextHorizontalPos, + TextVerticalPos, +} from './quadrantBuilder.js'; + +export const draw = (txt: string, id: string, _version: string, diagObj: Diagram) => { + function getDominantBaseLine(horizontalPos: TextHorizontalPos) { + return horizontalPos === 'top' ? 'hanging' : 'middle'; + } + + function getTextAnchor(verticalPos: TextVerticalPos) { + return verticalPos === 'left' ? 'start' : 'middle'; + } + + function getTransformation(data: { x: number; y: number; rotation: number }) { + return `translate(${data.x}, ${data.y}) rotate(${data.rotation || 0})`; + } + + const conf = configApi.getConfig(); + + log.debug('Rendering quadrant chart\n' + txt); + + const securityLevel = conf.securityLevel; + // 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 svg = root.select(`[id="${id}"]`); + + const group = svg.append('g').attr('class', 'main'); + + const width = conf.quadrantChart?.chartWidth || 500; + const height = conf.quadrantChart?.chartHeight || 500; + + configureSvgSize(svg, height, width, conf.quadrantChart?.useMaxWidth || true); + + svg.attr('viewBox', '0 0 ' + width + ' ' + height); + + // @ts-ignore: TODO Fix ts errors + diagObj.db.setHeight(height); + // @ts-ignore: TODO Fix ts errors + diagObj.db.setWidth(width); + + // @ts-ignore: TODO Fix ts errors + const quadrantData: QuadrantBuildType = diagObj.db.getQuadrantData(); + + const quadrantsGroup = group.append('g').attr('class', 'quadrants'); + const borderGroup = group.append('g').attr('class', 'border'); + const dataPointGroup = group.append('g').attr('class', 'data-points'); + const labelGroup = group.append('g').attr('class', 'labels'); + const titleGroup = group.append('g').attr('class', 'title'); + + if (quadrantData.title) { + titleGroup + .append('text') + .attr('x', 0) + .attr('y', 0) + .attr('fill', quadrantData.title.fill) + .attr('font-size', quadrantData.title.fontSize) + .attr('dominant-baseline', getDominantBaseLine(quadrantData.title.horizontalPos)) + .attr('text-anchor', getTextAnchor(quadrantData.title.verticalPos)) + .attr('transform', getTransformation(quadrantData.title)) + .text(quadrantData.title.text); + } + + if (quadrantData.borderLines) { + borderGroup + .selectAll('line') + .data(quadrantData.borderLines) + .enter() + .append('line') + .attr('x1', (data: QuadrantLineType) => data.x1) + .attr('y1', (data: QuadrantLineType) => data.y1) + .attr('x2', (data: QuadrantLineType) => data.x2) + .attr('y2', (data: QuadrantLineType) => data.y2) + .style('stroke', (data: QuadrantLineType) => data.strokeFill) + .style('stroke-width', (data: QuadrantLineType) => data.strokeWidth); + } + + const quadrants = quadrantsGroup + .selectAll('g.quadrant') + .data(quadrantData.quadrants) + .enter() + .append('g') + .attr('class', 'quadrant'); + + quadrants + .append('rect') + .attr('x', (data: QuadrantQuadrantsType) => data.x) + .attr('y', (data: QuadrantQuadrantsType) => data.y) + .attr('width', (data: QuadrantQuadrantsType) => data.width) + .attr('height', (data: QuadrantQuadrantsType) => data.height) + .attr('fill', (data: QuadrantQuadrantsType) => data.fill); + + quadrants + .append('text') + .attr('x', 0) + .attr('y', 0) + .attr('fill', (data: QuadrantQuadrantsType) => data.text.fill) + .attr('font-size', (data: QuadrantQuadrantsType) => data.text.fontSize) + .attr('dominant-baseline', (data: QuadrantQuadrantsType) => + getDominantBaseLine(data.text.horizontalPos) + ) + .attr('text-anchor', (data: QuadrantQuadrantsType) => getTextAnchor(data.text.verticalPos)) + .attr('transform', (data: QuadrantQuadrantsType) => getTransformation(data.text)) + .text((data: QuadrantQuadrantsType) => data.text.text); + + const labels = labelGroup + .selectAll('g.label') + .data(quadrantData.axisLabels) + .enter() + .append('g') + .attr('class', 'label'); + + labels + .append('text') + .attr('x', 0) + .attr('y', 0) + .text((data: QuadrantTextType) => data.text) + .attr('fill', (data: QuadrantTextType) => data.fill) + .attr('font-size', (data: QuadrantTextType) => data.fontSize) + .attr('dominant-baseline', (data: QuadrantTextType) => getDominantBaseLine(data.horizontalPos)) + .attr('text-anchor', (data: QuadrantTextType) => getTextAnchor(data.verticalPos)) + .attr('transform', (data: QuadrantTextType) => getTransformation(data)); + + const dataPoints = dataPointGroup + .selectAll('g.data-point') + .data(quadrantData.points) + .enter() + .append('g') + .attr('class', 'data-point'); + + dataPoints + .append('circle') + .attr('cx', (data: QuadrantPointType) => data.x) + .attr('cy', (data: QuadrantPointType) => data.y) + .attr('r', (data: QuadrantPointType) => data.radius) + .attr('fill', (data: QuadrantPointType) => data.fill); + + dataPoints + .append('text') + .attr('x', 0) + .attr('y', 0) + .text((data: QuadrantPointType) => data.text.text) + .attr('fill', (data: QuadrantPointType) => data.text.fill) + .attr('font-size', (data: QuadrantPointType) => data.text.fontSize) + .attr('dominant-baseline', (data: QuadrantPointType) => + getDominantBaseLine(data.text.horizontalPos) + ) + .attr('text-anchor', (data: QuadrantPointType) => getTextAnchor(data.text.verticalPos)) + .attr('transform', (data: QuadrantPointType) => getTransformation(data.text)); +}; + +export default { + draw, +}; diff --git a/packages/mermaid/src/diagrams/requirement/parser/requirementDiagram.spec.js b/packages/mermaid/src/diagrams/requirement/parser/requirementDiagram.spec.js index 4857a37ef..1b4c5da31 100644 --- a/packages/mermaid/src/diagrams/requirement/parser/requirementDiagram.spec.js +++ b/packages/mermaid/src/diagrams/requirement/parser/requirementDiagram.spec.js @@ -1,6 +1,6 @@ -import { setConfig } from '../../../config'; -import requirementDb from '../requirementDb'; -import reqDiagram from './requirementDiagram'; +import { setConfig } from '../../../config.js'; +import requirementDb from '../requirementDb.js'; +import reqDiagram from './requirementDiagram.jison'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/requirement/requirementDb.js b/packages/mermaid/src/diagrams/requirement/requirementDb.js index df5eb0ab9..c56c4ca16 100644 --- a/packages/mermaid/src/diagrams/requirement/requirementDb.js +++ b/packages/mermaid/src/diagrams/requirement/requirementDb.js @@ -1,6 +1,6 @@ -import * as configApi from '../../config'; -import { log } from '../../logger'; -import mermaidAPI from '../../mermaidAPI'; +import * as configApi from '../../config.js'; +import { log } from '../../logger.js'; +import mermaidAPI from '../../mermaidAPI.js'; import { setAccTitle, @@ -8,7 +8,7 @@ import { getAccDescription, setAccDescription, clear as commonClear, -} from '../../commonDb'; +} from '../common/commonDb.js'; let relations = []; let latestRequirement = {}; diff --git a/packages/mermaid/src/diagrams/requirement/requirementDetector.ts b/packages/mermaid/src/diagrams/requirement/requirementDetector.ts index 164da6c1a..f8fd33640 100644 --- a/packages/mermaid/src/diagrams/requirement/requirementDetector.ts +++ b/packages/mermaid/src/diagrams/requirement/requirementDetector.ts @@ -1,5 +1,24 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const requirementDetector: DiagramDetector = (txt) => { - return txt.match(/^\s*requirement(Diagram)?/) !== null; +const id = 'requirement'; + +const detector: DiagramDetector = (txt) => { + return /^\s*requirement(Diagram)?/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./requirementDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/requirement/requirementDiagram.ts b/packages/mermaid/src/diagrams/requirement/requirementDiagram.ts new file mode 100644 index 000000000..619f5b052 --- /dev/null +++ b/packages/mermaid/src/diagrams/requirement/requirementDiagram.ts @@ -0,0 +1,13 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: JISON doesn't support types +import parser from './parser/requirementDiagram.jison'; +import db from './requirementDb.js'; +import styles from './styles.js'; +import renderer from './requirementRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/requirement/requirementRenderer.js b/packages/mermaid/src/diagrams/requirement/requirementRenderer.js index 9fd746bd1..49b782865 100644 --- a/packages/mermaid/src/diagrams/requirement/requirementRenderer.js +++ b/packages/mermaid/src/diagrams/requirement/requirementRenderer.js @@ -1,11 +1,11 @@ import { line, select } from 'd3'; import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; -import { log } from '../../logger'; -import { configureSvgSize } from '../../setupGraphViewbox'; -import common from '../common/common'; -import markers from './requirementMarkers'; -import { getConfig } from '../../config'; +import { log } from '../../logger.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import common from '../common/common.js'; +import markers from './requirementMarkers.js'; +import { getConfig } from '../../config.js'; let conf = {}; let relCnt = 0; @@ -306,8 +306,6 @@ const elementString = (str) => { export const draw = (text, id, _version, diagObj) => { conf = getConfig().requirement; - diagObj.db.clear(); - diagObj.parser.parse(text); const securityLevel = conf.securityLevel; // Handle root and Document for when rendering in sandbox mode diff --git a/packages/mermaid/src/diagrams/requirement/styles.js b/packages/mermaid/src/diagrams/requirement/styles.js index d0579d204..9db0fa00a 100644 --- a/packages/mermaid/src/diagrams/requirement/styles.js +++ b/packages/mermaid/src/diagrams/requirement/styles.js @@ -16,7 +16,7 @@ const getStyles = (options) => ` .reqBox { fill: ${options.requirementBackground}; - fill-opacity: 100%; + fill-opacity: 1.0; stroke: ${options.requirementBorderColor}; stroke-width: ${options.requirementBorderSize}; } @@ -26,7 +26,7 @@ const getStyles = (options) => ` } .reqLabelBox { fill: ${options.relationLabelBackground}; - fill-opacity: 100%; + fill-opacity: 1.0; } .req-title-line { diff --git a/packages/mermaid/src/diagrams/sankey/parser/energy.csv b/packages/mermaid/src/diagrams/sankey/parser/energy.csv new file mode 100644 index 000000000..d9a8fac9a --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/parser/energy.csv @@ -0,0 +1,99 @@ +%% There are leading and trailing spaces, do not crop + Agricultural 'waste',Bio-conversion,124.729 +%% line with a comment + +%% Normal line +Bio-conversion,Liquid,0.597 + +%% Line with unquoted sankey keyword +sankey,target,10 + +%% Quoted sankey keyword +"sankey",target,10 + +%% Another normal line +Bio-conversion,Losses,26.862 + +%% Line with integer amount +Bio-conversion,Solid,280 + +%% Some blank lines in the middle of CSV + + +%% Another normal line +Bio-conversion,Gas,81.144 + +%% Quoted line +"Biofuel imports",Liquid,35 + +%% Quoted line with escaped quotes inside +"""Biomass imports""",Solid,35 + +%% Lines containing commas inside +%% Quoted and unquoted values should be equal in terms of graph +"District heating","Heating and cooling, commercial",22.505 +District heating,"Heating and cooling, homes",46.184 + +%% A bunch of lines, normal CSV +Coal imports,Coal,11.606 +Coal reserves,Coal,63.965 +Coal,Solid,75.571 +District heating,Industry,10.639 +Electricity grid,Over generation / exports,104.453 +Electricity grid,Heating and cooling - homes,113.726 +Electricity grid,H2 conversion,27.14 +Electricity grid,Industry,342.165 +Electricity grid,Road transport,37.797 +Electricity grid,Agriculture,4.412 +Electricity grid,Heating and cooling - commercial,40.858 +Electricity grid,Losses,56.691 +Electricity grid,Rail transport,7.863 +Electricity grid,Lighting & appliances - commercial,90.008 +Electricity grid,Lighting & appliances - homes,93.494 +Gas imports,Ngas,40.719 +Gas reserves,Ngas,82.233 +Gas,Heating and cooling - commercial,0.129 +Gas,Losses,1.401 +Gas,Thermal generation,151.891 +Gas,Agriculture,2.096 +Gas,Industry,48.58 +Geothermal,Electricity grid,7.013 +H2 conversion,H2,20.897 +H2 conversion,Losses,6.242 +H2,Road transport,20.897 +Hydro,Electricity grid,6.995 +Liquid,Industry,121.066 +Liquid,International shipping,128.69 +Liquid,Road transport,135.835 +Liquid,Domestic aviation,14.458 +Liquid,International aviation,206.267 +Liquid,Agriculture,3.64 +Liquid,National navigation,33.218 +Liquid,Rail transport,4.413 +Marine algae,Bio-conversion,4.375 +Ngas,Gas,122.952 +Nuclear,Thermal generation,839.978 +Oil imports,Oil,504.287 +Oil reserves,Oil,107.703 +Oil,Liquid,611.99 +Other waste,Solid,56.587 +Other waste,Bio-conversion,77.81 +Pumped heat,Heating and cooling - homes,193.026 +Pumped heat,Heating and cooling - commercial,70.672 +Solar PV,Electricity grid,59.901 +Solar Thermal,Heating and cooling - homes,19.263 +Solar,Solar Thermal,19.263 +Solar,Solar PV,59.901 +Solid,Agriculture,0.882 +Solid,Thermal generation,400.12 +Solid,Industry,46.477 +Thermal generation,Electricity grid,525.531 +Thermal generation,Losses,787.129 +Thermal generation,District heating,79.329 +Tidal,Electricity grid,9.452 +UK land based bioenergy,Bio-conversion,182.01 +"""Wave""",Electricity grid,19.013 +"""Wind""",Electricity grid,289.366 + +%% lines at the end, do not remove + diff --git a/packages/mermaid/src/diagrams/sankey/parser/sankey.jison b/packages/mermaid/src/diagrams/sankey/parser/sankey.jison new file mode 100644 index 000000000..b11f8a87b --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/parser/sankey.jison @@ -0,0 +1,69 @@ +/** mermaid */ + +//--------------------------------------------------------- +// We support csv format as defined here: +// https://www.ietf.org/rfc/rfc4180.txt +// There are some minor changes for compliance with jison +// We also parse only 3 columns: source,target,value +// And allow blank lines for visual purposes +//--------------------------------------------------------- + +%lex + +%options case-insensitive +%options easy_keword_rules + +%x escaped_text +%x csv + +// as per section 6.1 of RFC 2234 [2] +COMMA \u002C +CR \u000D +LF \u000A +CRLF \u000D\u000A +ESCAPED_QUOTE \u0022 +DQUOTE \u0022 +TEXTDATA [\u0020-\u0021\u0023-\u002B\u002D-\u007E] + +%% + +<INITIAL>"sankey-beta" { this.pushState('csv'); return 'SANKEY'; } +<INITIAL,csv><<EOF>> { return 'EOF' } // match end of file +<INITIAL,csv>({CRLF}|{LF}) { return 'NEWLINE' } +<INITIAL,csv>{COMMA} { return 'COMMA' } +<INITIAL,csv>{DQUOTE} { this.pushState('escaped_text'); return 'DQUOTE'; } +<INITIAL,csv>{TEXTDATA}* { return 'NON_ESCAPED_TEXT' } +<INITIAL,csv,escaped_text>{DQUOTE}(?!{DQUOTE}) {this.popState('escaped_text'); return 'DQUOTE'; } // unescaped DQUOTE closes string +<INITIAL,csv,escaped_text>({TEXTDATA}|{COMMA}|{CR}|{LF}|{DQUOTE}{DQUOTE})* { return 'ESCAPED_TEXT'; } + +/lex + +%start start + +%% // language grammar + +start: SANKEY NEWLINE csv opt_eof; + +csv: record csv_tail; +csv_tail: NEWLINE csv | ; +opt_eof: EOF | ; + +record + : field\[source] COMMA field\[target] COMMA field\[value] { + const source = yy.findOrCreateNode($source.trim().replaceAll('""', '"')); + const target = yy.findOrCreateNode($target.trim().replaceAll('""', '"')); + const value = parseFloat($value.trim()); + yy.addLink(source,target,value); + } // parse only 3 fields, this is not part of CSV standard + ; + +field + : escaped { $$=$escaped; } + | non_escaped { $$=$non_escaped; } + ; + +escaped: DQUOTE ESCAPED_TEXT DQUOTE { $$=$ESCAPED_TEXT; }; + +non_escaped: NON_ESCAPED_TEXT { $$=$NON_ESCAPED_TEXT; }; + + diff --git a/packages/mermaid/src/diagrams/sankey/parser/sankey.spec.ts b/packages/mermaid/src/diagrams/sankey/parser/sankey.spec.ts new file mode 100644 index 000000000..4517ca01f --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/parser/sankey.spec.ts @@ -0,0 +1,24 @@ +// @ts-ignore: jison doesn't export types +import sankey from './sankey.jison'; +import db from '../sankeyDB.js'; +import { cleanupComments } from '../../../diagram-api/comments.js'; +import { prepareTextForParsing } from '../sankeyUtils.js'; +import * as fs from 'fs'; +import * as path from 'path'; + +describe('Sankey diagram', function () { + describe('when parsing an info graph it', function () { + beforeEach(function () { + sankey.parser.yy = db; + sankey.parser.yy.clear(); + }); + + it('parses csv', async () => { + const csv = path.resolve(__dirname, './energy.csv'); + const data = fs.readFileSync(csv, 'utf8'); + const graphDefinition = prepareTextForParsing(cleanupComments('sankey-beta\n\n ' + data)); + + sankey.parser.parse(graphDefinition); + }); + }); +}); diff --git a/packages/mermaid/src/diagrams/sankey/sankeyDB.ts b/packages/mermaid/src/diagrams/sankey/sankeyDB.ts new file mode 100644 index 000000000..8b3a22c5a --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/sankeyDB.ts @@ -0,0 +1,81 @@ +import * as configApi from '../../config.js'; +import common from '../common/common.js'; +import { + setAccTitle, + getAccTitle, + getAccDescription, + setAccDescription, + setDiagramTitle, + getDiagramTitle, + clear as commonClear, +} from '../common/commonDb.js'; + +// Sankey diagram represented by nodes and links between those nodes +let links: SankeyLink[] = []; +// Array of nodes guarantees their order +let nodes: SankeyNode[] = []; +// We also have to track nodes uniqueness (by ID) +let nodesMap: Record<string, SankeyNode> = {}; + +const clear = (): void => { + links = []; + nodes = []; + nodesMap = {}; + commonClear(); +}; + +class SankeyLink { + constructor(public source: SankeyNode, public target: SankeyNode, public value: number = 0) {} +} + +/** + * @param source - Node where the link starts + * @param target - Node where the link ends + * @param value - Describes the amount to be passed + */ +const addLink = (source: SankeyNode, target: SankeyNode, value: number): void => { + links.push(new SankeyLink(source, target, value)); +}; + +class SankeyNode { + constructor(public ID: string) {} +} + +const findOrCreateNode = (ID: string): SankeyNode => { + ID = common.sanitizeText(ID, configApi.getConfig()); + + if (!nodesMap[ID]) { + nodesMap[ID] = new SankeyNode(ID); + nodes.push(nodesMap[ID]); + } + return nodesMap[ID]; +}; + +const getNodes = () => nodes; +const getLinks = () => links; + +const getGraph = () => ({ + nodes: nodes.map((node) => ({ id: node.ID })), + links: links.map((link) => ({ + source: link.source.ID, + target: link.target.ID, + value: link.value, + })), +}); + +export default { + nodesMap, + getConfig: () => configApi.getConfig().sankey, + getNodes, + getLinks, + getGraph, + addLink, + findOrCreateNode, + getAccTitle, + setAccTitle, + getAccDescription, + setAccDescription, + getDiagramTitle, + setDiagramTitle, + clear, +}; diff --git a/packages/mermaid/src/diagrams/sankey/sankeyDetector.ts b/packages/mermaid/src/diagrams/sankey/sankeyDetector.ts new file mode 100644 index 000000000..73c4d1428 --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/sankeyDetector.ts @@ -0,0 +1,20 @@ +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js'; + +const id = 'sankey'; + +const detector: DiagramDetector = (txt) => { + return /^\s*sankey-beta/.test(txt); +}; + +const loader = async () => { + const { diagram } = await import('./sankeyDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/sankey/sankeyDiagram.ts b/packages/mermaid/src/diagrams/sankey/sankeyDiagram.ts new file mode 100644 index 000000000..6fed435ac --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/sankeyDiagram.ts @@ -0,0 +1,15 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: jison doesn't export types +import parser from './parser/sankey.jison'; +import db from './sankeyDB.js'; +import renderer from './sankeyRenderer.js'; +import { prepareTextForParsing } from './sankeyUtils.js'; + +const originalParse = parser.parse.bind(parser); +parser.parse = (text: string) => originalParse(prepareTextForParsing(text)); + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, +}; diff --git a/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts new file mode 100644 index 000000000..9f5b3c172 --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts @@ -0,0 +1,215 @@ +import type { Diagram } from '../../Diagram.js'; +import * as configApi from '../../config.js'; + +import { + select as d3select, + scaleOrdinal as d3scaleOrdinal, + schemeTableau10 as d3schemeTableau10, +} from 'd3'; + +import type { SankeyNode as d3SankeyNode } from 'd3-sankey'; +import { + sankey as d3Sankey, + sankeyLinkHorizontal as d3SankeyLinkHorizontal, + sankeyLeft as d3SankeyLeft, + sankeyRight as d3SankeyRight, + sankeyCenter as d3SankeyCenter, + sankeyJustify as d3SankeyJustify, +} from 'd3-sankey'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import { Uid } from '../../rendering-util/uid.js'; +import type { SankeyNodeAlignment } from '../../config.type.js'; + +// Map config options to alignment functions +const alignmentsMap: Record< + SankeyNodeAlignment, + (node: d3SankeyNode<object, object>, n: number) => number +> = { + left: d3SankeyLeft, + right: d3SankeyRight, + center: d3SankeyCenter, + justify: d3SankeyJustify, +}; + +/** + * Draws Sankey diagram. + * + * @param text - The text of the diagram + * @param id - The id of the diagram which will be used as a DOM element id¨ + * @param _version - Mermaid version from package.json + * @param diagObj - A standard diagram containing the db and the text and type etc of the diagram + */ +export const draw = function (text: string, id: string, _version: string, diagObj: Diagram): void { + // Get Sankey config + const { securityLevel, sankey: conf } = configApi.getConfig(); + const defaultSankeyConfig = configApi!.defaultConfig!.sankey!; + + // TODO: + // This code repeats for every diagram + // Figure out what is happening there, probably it should be separated + // The main thing is svg object that is a d3 wrapper for svg operations + // + let sandboxElement: any; + if (securityLevel === 'sandbox') { + sandboxElement = d3select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? d3select(sandboxElement.nodes()[0].contentDocument.body) + : d3select('body'); + // @ts-ignore TODO root.select is not callable + const svg = securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : d3select(`[id="${id}"]`); + + // Establish svg dimensions and get width and height + // + const width = conf?.width ?? defaultSankeyConfig.width!; + const height = conf?.height ?? defaultSankeyConfig.width!; + const useMaxWidth = conf?.useMaxWidth ?? defaultSankeyConfig.useMaxWidth!; + const nodeAlignment = conf?.nodeAlignment ?? defaultSankeyConfig.nodeAlignment!; + const prefix = conf?.prefix ?? defaultSankeyConfig.prefix!; + const suffix = conf?.suffix ?? defaultSankeyConfig.suffix!; + const showValues = conf?.showValues ?? defaultSankeyConfig.showValues!; + + // FIX: using max width prevents height from being set, is it intended? + // to add height directly one can use `svg.attr('height', height)` + // + // @ts-ignore TODO: svg type vs selection mismatch + configureSvgSize(svg, height, width, useMaxWidth); + + // Prepare data for construction based on diagObj.db + // This must be a mutable object with `nodes` and `links` properties: + // + // { + // "nodes": [ { "id": "Alice" }, { "id": "Bob" }, { "id": "Carol" } ], + // "links": [ { "source": "Alice", "target": "Bob", "value": 23 }, { "source": "Bob", "target": "Carol", "value": 43 } ] + // } + // + // @ts-ignore TODO: db should be coerced to sankey DB type + const graph = diagObj.db.getGraph(); + + // Get alignment function + const nodeAlign = alignmentsMap[nodeAlignment]; + + // Construct and configure a Sankey generator + // That will be a function that calculates nodes and links dimensions + // + const nodeWidth = 10; + const sankey = d3Sankey() + .nodeId((d: any) => d.id) // we use 'id' property to identify node + .nodeWidth(nodeWidth) + .nodePadding(10 + (showValues ? 15 : 0)) + .nodeAlign(nodeAlign) + .extent([ + [0, 0], + [width, height], + ]); + + // Compute the Sankey layout: calculate nodes and links positions + // Our `graph` object will be mutated by this and enriched with other properties + // + sankey(graph); + + // Get color scheme for the graph + const colorScheme = d3scaleOrdinal(d3schemeTableau10); + + // Create rectangles for nodes + svg + .append('g') + .attr('class', 'nodes') + .selectAll('.node') + .data(graph.nodes) + .join('g') + .attr('class', 'node') + .attr('id', (d: any) => (d.uid = Uid.next('node-')).id) + .attr('transform', function (d: any) { + return 'translate(' + d.x0 + ',' + d.y0 + ')'; + }) + .attr('x', (d: any) => d.x0) + .attr('y', (d: any) => d.y0) + .append('rect') + .attr('height', (d: any) => { + return d.y1 - d.y0; + }) + .attr('width', (d: any) => d.x1 - d.x0) + .attr('fill', (d: any) => colorScheme(d.id)); + + const getText = ({ id, value }: { id: string; value: number }) => { + if (!showValues) { + return id; + } + return `${id}\n${prefix}${Math.round(value * 100) / 100}${suffix}`; + }; + + // Create labels for nodes + svg + .append('g') + .attr('class', 'node-labels') + .attr('font-family', 'sans-serif') + .attr('font-size', 14) + .selectAll('text') + .data(graph.nodes) + .join('text') + .attr('x', (d: any) => (d.x0 < width / 2 ? d.x1 + 6 : d.x0 - 6)) + .attr('y', (d: any) => (d.y1 + d.y0) / 2) + .attr('dy', `${showValues ? '0' : '0.35'}em`) + .attr('text-anchor', (d: any) => (d.x0 < width / 2 ? 'start' : 'end')) + .text(getText); + + // Creates the paths that represent the links. + const link = svg + .append('g') + .attr('class', 'links') + .attr('fill', 'none') + .attr('stroke-opacity', 0.5) + .selectAll('.link') + .data(graph.links) + .join('g') + .attr('class', 'link') + .style('mix-blend-mode', 'multiply'); + + const linkColor = conf?.linkColor || 'gradient'; + + if (linkColor === 'gradient') { + const gradient = link + .append('linearGradient') + .attr('id', (d: any) => (d.uid = Uid.next('linearGradient-')).id) + .attr('gradientUnits', 'userSpaceOnUse') + .attr('x1', (d: any) => d.source.x1) + .attr('x2', (d: any) => d.target.x0); + + gradient + .append('stop') + .attr('offset', '0%') + .attr('stop-color', (d: any) => colorScheme(d.source.id)); + + gradient + .append('stop') + .attr('offset', '100%') + .attr('stop-color', (d: any) => colorScheme(d.target.id)); + } + + let coloring: any; + switch (linkColor) { + case 'gradient': + coloring = (d: any) => d.uid; + break; + case 'source': + coloring = (d: any) => colorScheme(d.source.id); + break; + case 'target': + coloring = (d: any) => colorScheme(d.target.id); + break; + default: + coloring = linkColor; + } + + link + .append('path') + .attr('d', d3SankeyLinkHorizontal()) + .attr('stroke', coloring) + .attr('stroke-width', (d: any) => Math.max(1, d.width)); +}; + +export default { + draw, +}; diff --git a/packages/mermaid/src/diagrams/sankey/sankeyUtils.ts b/packages/mermaid/src/diagrams/sankey/sankeyUtils.ts new file mode 100644 index 000000000..45ecf21dd --- /dev/null +++ b/packages/mermaid/src/diagrams/sankey/sankeyUtils.ts @@ -0,0 +1,8 @@ +export const prepareTextForParsing = (text: string): string => { + const textToParse = text + .replaceAll(/^[^\S\n\r]+|[^\S\n\r]+$/g, '') // remove all trailing spaces for each row + .replaceAll(/([\n\r])+/g, '\n') // remove empty lines duplicated + .trim(); + + return textToParse; +}; diff --git a/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison b/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison index bbc72adcb..4e971d989 100644 --- a/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison +++ b/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison @@ -38,6 +38,8 @@ "box" { this.begin('LINE'); return 'box'; } "participant" { this.begin('ID'); return 'participant'; } "actor" { this.begin('ID'); return 'participant_actor'; } +"create" return 'create'; +"destroy" { this.begin('ID'); return 'destroy'; } <ID>[^\->:\n,;]+?([\-]*[^\->:\n,;]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; } <ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; } <ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; } @@ -47,6 +49,7 @@ "alt" { this.begin('LINE'); return 'alt'; } "else" { this.begin('LINE'); return 'else'; } "par" { this.begin('LINE'); return 'par'; } +"par_over" { this.begin('LINE'); return 'par_over'; } "and" { this.begin('LINE'); return 'and'; } "critical" { this.begin('LINE'); return 'critical'; } "option" { this.begin('LINE'); return 'option'; } @@ -137,6 +140,7 @@ directive statement : participant_statement + | 'create' participant_statement {$2.type='createParticipant'; $$=$2;} | 'box' restOfLine box_section end { $3.unshift({type: 'boxStart', boxData:yy.parseBoxData($2) }); @@ -190,6 +194,14 @@ statement // End $3.push({type: 'parEnd', signalType: yy.LINETYPE.PAR_END}); $$=$3;} + | par_over restOfLine par_sections end + { + // Parallel (overlapped) start + $3.unshift({type: 'parStart', parText:yy.parseMessage($2), signalType: yy.LINETYPE.PAR_OVER_START}); + // Content in par is already in $3 + // End + $3.push({type: 'parEnd', signalType: yy.LINETYPE.PAR_END}); + $$=$3;} | critical restOfLine option_sections end { // critical start @@ -225,10 +237,11 @@ else_sections ; participant_statement - : 'participant' actor 'AS' restOfLine 'NEWLINE' {$2.type='addParticipant';$2.description=yy.parseMessage($4); $$=$2;} - | 'participant' actor 'NEWLINE' {$2.type='addParticipant';$$=$2;} - | 'participant_actor' actor 'AS' restOfLine 'NEWLINE' {$2.type='addActor';$2.description=yy.parseMessage($4); $$=$2;} - | 'participant_actor' actor 'NEWLINE' {$2.type='addActor'; $$=$2;} + : 'participant' actor 'AS' restOfLine 'NEWLINE' {$2.draw='participant'; $2.type='addParticipant';$2.description=yy.parseMessage($4); $$=$2;} + | 'participant' actor 'NEWLINE' {$2.draw='participant'; $2.type='addParticipant';$$=$2;} + | 'participant_actor' actor 'AS' restOfLine 'NEWLINE' {$2.draw='actor'; $2.type='addParticipant';$2.description=yy.parseMessage($4); $$=$2;} + | 'participant_actor' actor 'NEWLINE' {$2.draw='actor'; $2.type='addParticipant'; $$=$2;} + | 'destroy' actor 'NEWLINE' {$2.type='destroyParticipant'; $$=$2;} ; note_statement @@ -288,7 +301,7 @@ placement signal : actor signaltype '+' actor text2 - { $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5}, + { $$ = [$1,$4,{type: 'addMessage', from:$1.actor, to:$4.actor, signalType:$2, msg:$5, activate: true}, {type: 'activeStart', signalType: yy.LINETYPE.ACTIVE_START, actor: $4} ]} | actor signaltype '-' actor text2 diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDb.js b/packages/mermaid/src/diagrams/sequence/sequenceDb.js index 5c5554c72..813d9e127 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDb.js +++ b/packages/mermaid/src/diagrams/sequence/sequenceDb.js @@ -1,7 +1,7 @@ -import mermaidAPI from '../../mermaidAPI'; -import * as configApi from '../../config'; -import { log } from '../../logger'; -import { sanitizeText } from '../common/common'; +import mermaidAPI from '../../mermaidAPI.js'; +import * as configApi from '../../config.js'; +import { log } from '../../logger.js'; +import { sanitizeText } from '../common/common.js'; import { setAccTitle, getAccTitle, @@ -10,16 +10,20 @@ import { getAccDescription, setAccDescription, clear as commonClear, -} from '../../commonDb'; +} from '../common/commonDb.js'; let prevActor = undefined; let actors = {}; +let createdActors = {}; +let destroyedActors = {}; let boxes = []; let messages = []; const notes = []; let sequenceNumbersEnabled = false; let wrapEnabled; let currentBox = undefined; +let lastCreated = undefined; +let lastDestroyed = undefined; export const parseDirective = function (statement, context, type) { mermaidAPI.parseDirective(this, statement, context, type); @@ -120,7 +124,8 @@ export const addSignal = function ( idFrom, idTo, message = { text: undefined, wrap: undefined }, - messageType + messageType, + activate = false ) { if (messageType === LINETYPE.ACTIVE_END) { const cnt = activationCount(idFrom.actor); @@ -143,6 +148,7 @@ export const addSignal = function ( message: message.text, wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap, type: messageType, + activate, }); return true; }; @@ -165,6 +171,12 @@ export const getBoxes = function () { export const getActors = function () { return actors; }; +export const getCreatedActors = function () { + return createdActors; +}; +export const getDestroyedActors = function () { + return destroyedActors; +}; export const getActor = function (id) { return actors[id]; }; @@ -194,6 +206,8 @@ export const autoWrap = () => { export const clear = function () { actors = {}; + createdActors = {}; + destroyedActors = {}; boxes = []; messages = []; sequenceNumbersEnabled = false; @@ -286,6 +300,7 @@ export const LINETYPE = { CRITICAL_END: 29, BREAK_START: 30, BREAK_END: 31, + PAR_OVER_START: 32, }; export const ARROWTYPE = { @@ -437,6 +452,19 @@ export const getActorProperty = function (actor, key) { return undefined; }; +/** + * @typedef {object} AddMessageParams A message from one actor to another. + * @property {string} from - The id of the actor sending the message. + * @property {string} to - The id of the actor receiving the message. + * @property {string} msg - The message text. + * @property {number} signalType - The type of signal. + * @property {"addMessage"} type - Set to `"addMessage"` if this is an `AddMessageParams`. + * @property {boolean} [activate] - If `true`, this signal starts an activation. + */ + +/** + * @param {object | object[] | AddMessageParams} param - Object of parameters. + */ export const apply = function (param) { if (Array.isArray(param)) { param.forEach(function (item) { @@ -458,10 +486,21 @@ export const apply = function (param) { }); break; case 'addParticipant': - addActor(param.actor, param.actor, param.description, 'participant'); + addActor(param.actor, param.actor, param.description, param.draw); break; - case 'addActor': - addActor(param.actor, param.actor, param.description, 'actor'); + case 'createParticipant': + if (actors[param.actor]) { + throw new Error( + "It is not possible to have actors with the same id, even if one is destroyed before the next is created. Use 'AS' aliases to simulate the behavior" + ); + } + lastCreated = param.actor; + addActor(param.actor, param.actor, param.description, param.draw); + createdActors[param.actor] = messages.length; + break; + case 'destroyParticipant': + lastDestroyed = param.actor; + destroyedActors[param.actor] = messages.length; break; case 'activeStart': addSignal(param.actor, undefined, undefined, param.signalType); @@ -485,7 +524,28 @@ export const apply = function (param) { addDetails(param.actor, param.text); break; case 'addMessage': - addSignal(param.from, param.to, param.msg, param.signalType); + if (lastCreated) { + if (param.to !== lastCreated) { + throw new Error( + 'The created participant ' + + lastCreated + + ' does not have an associated creating message after its declaration. Please check the sequence diagram.' + ); + } else { + lastCreated = undefined; + } + } else if (lastDestroyed) { + if (param.to !== lastDestroyed && param.from !== lastDestroyed) { + throw new Error( + 'The destroyed participant ' + + lastDestroyed + + ' does not have an associated destroying message after its declaration. Please check the sequence diagram.' + ); + } else { + lastDestroyed = undefined; + } + } + addSignal(param.from, param.to, param.msg, param.signalType, param.activate); break; case 'boxStart': addBox(param.boxData); @@ -565,6 +625,8 @@ export default { showSequenceNumbers, getMessages, getActors, + getCreatedActors, + getDestroyedActors, getActor, getActorKeys, getActorProperty, diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts b/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts index 52640b134..c1df22130 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDetector.ts @@ -1,5 +1,24 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const sequenceDetector: DiagramDetector = (txt) => { - return txt.match(/^\s*sequenceDiagram/) !== null; +const id = 'sequence'; + +const detector: DiagramDetector = (txt) => { + return /^\s*sequenceDiagram/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./sequenceDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js index 72daca932..ed6f07300 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js @@ -1,9 +1,14 @@ import { vi } from 'vitest'; -import * as configApi from '../../config'; -import mermaidAPI from '../../mermaidAPI'; -import { Diagram } from '../../Diagram'; -import { addDiagrams } from '../../diagram-api/diagram-orchestration'; +import * as configApi from '../../config.js'; +import mermaidAPI from '../../mermaidAPI.js'; +import { Diagram, getDiagramFromText } from '../../Diagram.js'; +import { addDiagrams } from '../../diagram-api/diagram-orchestration.js'; + +beforeAll(async () => { + // Is required to load the sequence diagram + await getDiagramFromText('sequenceDiagram'); +}); /** * Sequence diagrams require their own very special version of a mocked d3 module @@ -99,6 +104,7 @@ describe('more than one sequence diagram', () => { expect(diagram1.db.getMessages()).toMatchInlineSnapshot(` [ { + "activate": false, "from": "Alice", "message": "Hello Bob, how are you?", "to": "Bob", @@ -106,6 +112,7 @@ describe('more than one sequence diagram', () => { "wrap": false, }, { + "activate": false, "from": "Bob", "message": "I am good thanks!", "to": "Alice", @@ -122,6 +129,7 @@ describe('more than one sequence diagram', () => { expect(diagram2.db.getMessages()).toMatchInlineSnapshot(` [ { + "activate": false, "from": "Alice", "message": "Hello Bob, how are you?", "to": "Bob", @@ -129,6 +137,7 @@ describe('more than one sequence diagram', () => { "wrap": false, }, { + "activate": false, "from": "Bob", "message": "I am good thanks!", "to": "Alice", @@ -147,6 +156,7 @@ describe('more than one sequence diagram', () => { expect(diagram3.db.getMessages()).toMatchInlineSnapshot(` [ { + "activate": false, "from": "Alice", "message": "Hello John, how are you?", "to": "John", @@ -154,6 +164,7 @@ describe('more than one sequence diagram', () => { "wrap": false, }, { + "activate": false, "from": "John", "message": "I am good thanks!", "to": "Alice", @@ -167,14 +178,11 @@ describe('more than one sequence diagram', () => { describe('when parsing a sequenceDiagram', function () { beforeEach(function () { - // diagram.db = sequenceDb; - // diagram.db.clear(); diagram = new Diagram(` sequenceDiagram Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); - diagram.db.clear(); }); it('should handle a sequenceDiagram definition', async function () { const str = ` @@ -183,7 +191,7 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - await mermaidAPI.parse(str, diagram); + await mermaidAPI.parse(str); const actors = diagram.db.getActors(); expect(actors.Alice.description).toBe('Alice'); actors.Bob.description = 'Bob'; @@ -546,6 +554,7 @@ deactivate Bob`; expect(messages.length).toBe(4); expect(messages[0].type).toBe(diagram.db.LINETYPE.DOTTED); + expect(messages[0].activate).toBeTruthy(); expect(messages[1].type).toBe(diagram.db.LINETYPE.ACTIVE_START); expect(messages[1].from.actor).toBe('Bob'); expect(messages[2].type).toBe(diagram.db.LINETYPE.DOTTED); @@ -1121,6 +1130,29 @@ end`; expect(messages[1].from).toBe('Alice'); expect(messages[2].from).toBe('Bob'); }); + it('it should handle par_over statements', async () => { + const str = ` +sequenceDiagram +par_over Parallel overlap +Alice ->> Bob: Message +Note left of Alice: Alice note +Note right of Bob: Bob note +end`; + + await mermaidAPI.parse(str); + const actors = diagram.db.getActors(); + + expect(actors.Alice.description).toBe('Alice'); + expect(actors.Bob.description).toBe('Bob'); + + const messages = diagram.db.getMessages(); + + expect(messages.length).toBe(5); + expect(messages[0].message).toBe('Parallel overlap'); + expect(messages[1].from).toBe('Alice'); + expect(messages[2].from).toBe('Alice'); + expect(messages[3].from).toBe('Bob'); + }); it('should handle special characters in signals', async () => { const str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment'; @@ -1376,6 +1408,62 @@ link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com expect(boxes[0].actorKeys).toEqual(['a', 'b']); expect(boxes[0].fill).toEqual('Aqua'); }); + + it('should handle simple actor creation', async () => { + const str = ` + sequenceDiagram + participant a as Alice + a ->>b: Hello Bob? + create participant c + b-->>c: Hello c! + c ->> b: Hello b? + create actor d as Donald + a ->> d: Hello Donald? + `; + await mermaidAPI.parse(str); + const actors = diagram.db.getActors(); + const createdActors = diagram.db.getCreatedActors(); + expect(actors['c'].name).toEqual('c'); + expect(actors['c'].description).toEqual('c'); + expect(actors['c'].type).toEqual('participant'); + expect(createdActors['c']).toEqual(1); + expect(actors['d'].name).toEqual('d'); + expect(actors['d'].description).toEqual('Donald'); + expect(actors['d'].type).toEqual('actor'); + expect(createdActors['d']).toEqual(3); + }); + it('should handle simple actor destruction', async () => { + const str = ` + sequenceDiagram + participant a as Alice + a ->>b: Hello Bob? + destroy a + b-->>a: Hello Alice! + b ->> c: Where is Alice? + destroy c + b ->> c: Where are you? + `; + await mermaidAPI.parse(str); + const destroyedActors = diagram.db.getDestroyedActors(); + expect(destroyedActors['a']).toEqual(1); + expect(destroyedActors['c']).toEqual(3); + }); + it('should handle the creation and destruction of the same actor', async () => { + const str = ` + sequenceDiagram + a ->>b: Hello Bob? + create participant c + b ->>c: Hello c! + c ->> b: Hello b? + destroy c + b ->> c : Bye c ! + `; + await mermaidAPI.parse(str); + const createdActors = diagram.db.getCreatedActors(); + const destroyedActors = diagram.db.getDestroyedActors(); + expect(createdActors['c']).toEqual(1); + expect(destroyedActors['c']).toEqual(3); + }); }); describe('when checking the bounds in a sequenceDiagram', function () { beforeAll(() => { @@ -1398,8 +1486,6 @@ describe('when checking the bounds in a sequenceDiagram', function () { let conf; beforeEach(function () { mermaidAPI.reset(); - // diagram.db = sequenceDb; - // diagram.db.clear(); diagram.renderer.bounds.init(); conf = diagram.db.getConfig(); }); @@ -1551,7 +1637,6 @@ sequenceDiagram Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`); - diagram.db.clear(); }); ['tspan', 'fo', 'old', undefined].forEach(function (textPlacement) { it(` @@ -1925,8 +2010,6 @@ describe('when rendering a sequenceDiagram with actor mirror activated', () => { let conf; beforeEach(function () { mermaidAPI.reset(); - // diagram.db = sequenceDb; - diagram.db.clear(); conf = diagram.db.getConfig(); diagram.renderer.bounds.init(); }); @@ -1945,7 +2028,9 @@ participant Alice`; expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopx).toBe(conf.width); - expect(bounds.stopy).toBe(models.lastActor().y + models.lastActor().height + conf.boxMargin); + expect(bounds.stopy).toBe( + models.lastActor().stopy + models.lastActor().height + conf.boxMargin + ); }); }); }); @@ -1966,12 +2051,8 @@ describe('when rendering a sequenceDiagram with directives', () => { mermaidAPI.initialize({ sequence: conf }); }); - let conf; beforeEach(function () { mermaidAPI.reset(); - // diagram.db = sequenceDb; - diagram.db.clear(); - conf = diagram.db.getConfig(); diagram.renderer.bounds.init(); }); @@ -1983,10 +2064,7 @@ sequenceDiagram participant Alice `; diagram = new Diagram(str); - diagram.renderer.bounds.init(); - await mermaidAPI.parse(str); - diagram.renderer.draw(str, 'tst', '1.2.3', diagram); const { bounds, models } = diagram.renderer.bounds.getBounds(); @@ -1997,7 +2075,7 @@ participant Alice expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopy).toBe( - models.lastActor().y + models.lastActor().height + mermaid.sequence.boxMargin + models.lastActor().stopy + models.lastActor().height + mermaid.sequence.boxMargin ); }); it('should handle one actor, when logLevel is 3 (dfg0)', async () => { @@ -2007,7 +2085,7 @@ sequenceDiagram participant Alice `; - diagram.parse(str); + diagram = new Diagram(str); diagram.renderer.draw(str, 'tst', '1.2.3', diagram); const { bounds, models } = diagram.renderer.bounds.getBounds(); @@ -2017,7 +2095,7 @@ participant Alice expect(bounds.startx).toBe(0); expect(bounds.starty).toBe(0); expect(bounds.stopy).toBe( - models.lastActor().y + models.lastActor().height + mermaid.sequence.boxMargin + models.lastActor().stopy + models.lastActor().height + mermaid.sequence.boxMargin ); }); it('should hide sequence numbers when autonumber is removed when autonumber is enabled', async () => { @@ -2028,7 +2106,7 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - await mermaidAPI.parse(str1); + diagram = new Diagram(str1); diagram.renderer.draw(str1, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers expect(diagram.db.showSequenceNumbers()).toBe(true); @@ -2038,7 +2116,7 @@ Alice->Bob:Hello Bob, how are you? Note right of Bob: Bob thinks Bob-->Alice: I am good thanks!`; - await mermaidAPI.parse(str2); + diagram = new Diagram(str2); diagram.renderer.draw(str2, 'tst', '1.2.3', diagram); expect(diagram.db.showSequenceNumbers()).toBe(false); }); diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts new file mode 100644 index 000000000..8779b9cc4 --- /dev/null +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.ts @@ -0,0 +1,13 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: JISON doesn't support types +import parser from './parser/sequenceDiagram.jison'; +import db from './sequenceDb.js'; +import styles from './styles.js'; +import renderer from './sequenceRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, +}; diff --git a/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts b/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts index acee7bbe5..a596a3a02 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts @@ -1,13 +1,14 @@ // @ts-nocheck TODO: fix file -import { select, selectAll } from 'd3'; -import svgDraw, { drawText, fixLifeLineHeights } from './svgDraw'; -import { log } from '../../logger'; -import common from '../common/common'; -import * as configApi from '../../config'; -import assignWithDepth from '../../assignWithDepth'; -import utils from '../../utils'; -import { configureSvgSize } from '../../setupGraphViewbox'; -import { Diagram } from '../../Diagram'; +import { select } from 'd3'; +import svgDraw, { ACTOR_TYPE_WIDTH, drawText, fixLifeLineHeights } from './svgDraw.js'; +import { log } from '../../logger.js'; +import common from '../common/common.js'; +import * as svgDrawCommon from '../common/svgDrawCommon.js'; +import * as configApi from '../../config.js'; +import assignWithDepth from '../../assignWithDepth.js'; +import utils from '../../utils.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import type { Diagram } from '../../Diagram.js'; let conf = {}; @@ -130,10 +131,10 @@ export const bounds = { this.activations.forEach(updateFn('activation')); }, insert: function (startx, starty, stopx, stopy) { - const _startx = Math.min(startx, stopx); - const _stopx = Math.max(startx, stopx); - const _starty = Math.min(starty, stopy); - const _stopy = Math.max(starty, stopy); + const _startx = common.getMin(startx, stopx); + const _stopx = common.getMax(startx, stopx); + const _starty = common.getMin(starty, stopy); + const _stopy = common.getMax(starty, stopy); this.updateVal(bounds.data, 'startx', _startx, Math.min); this.updateVal(bounds.data, 'starty', _starty, Math.min); @@ -183,6 +184,11 @@ export const bounds = { endLoop: function () { return this.sequenceItems.pop(); }, + isLoopOverlap: function () { + return this.sequenceItems.length + ? this.sequenceItems[this.sequenceItems.length - 1].overlap + : false; + }, addSectionToLoop: function (message) { const loop = this.sequenceItems.pop(); loop.sections = loop.sections || []; @@ -191,9 +197,19 @@ export const bounds = { loop.sectionTitles.push(message); this.sequenceItems.push(loop); }, + saveVerticalPos: function () { + if (this.isLoopOverlap()) { + this.savedVerticalPos = this.verticalPos; + } + }, + resetVerticalPos: function () { + if (this.isLoopOverlap()) { + this.verticalPos = this.savedVerticalPos; + } + }, bumpVerticalPos: function (bump) { this.verticalPos = this.verticalPos + bump; - this.data.stopy = this.verticalPos; + this.data.stopy = common.getMax(this.data.stopy, this.verticalPos); }, getVerticalPos: function () { return this.verticalPos; @@ -225,7 +241,7 @@ const drawNote = function (elem: any, noteModel: NoteModel) { bounds.bumpVerticalPos(conf.boxMargin); noteModel.height = conf.boxMargin; noteModel.starty = bounds.getVerticalPos(); - const rect = svgDraw.getNoteRect(); + const rect = svgDrawCommon.getNoteRect(); rect.x = noteModel.startx; rect.y = noteModel.starty; rect.width = noteModel.width || conf.width; @@ -233,7 +249,7 @@ const drawNote = function (elem: any, noteModel: NoteModel) { const g = elem.append('g'); const rectElem = svgDraw.drawRect(g, rect); - const textObj = svgDraw.getTextObj(); + const textObj = svgDrawCommon.getTextObj(); textObj.x = noteModel.startx; textObj.y = noteModel.starty; textObj.width = rect.width; @@ -316,7 +332,7 @@ function boundMessage(_diagram, msgModel): number { lineStartY = bounds.getVerticalPos() + totalOffset; } totalOffset += 30; - const dx = Math.max(textWidth / 2, conf.width / 2); + const dx = common.getMax(textWidth / 2, conf.width / 2); bounds.insert( startx - dx, bounds.getVerticalPos() - 10 + totalOffset, @@ -347,7 +363,7 @@ function boundMessage(_diagram, msgModel): number { const drawMessage = function (diagram, msgModel, lineStartY: number, diagObj: Diagram) { const { startx, stopx, starty, message, type, sequenceIndex, sequenceVisible } = msgModel; const textDims = utils.calculateTextDimensions(message, messageFont(conf)); - const textObj = svgDraw.getTextObj(); + const textObj = svgDrawCommon.getTextObj(); textObj.x = startx; textObj.y = starty + 10; textObj.width = stopx - startx; @@ -373,9 +389,9 @@ const drawMessage = function (diagram, msgModel, lineStartY: number, diagObj: Di .append('path') .attr( 'd', - `M ${startx},${lineStartY} H ${startx + Math.max(conf.width / 2, textWidth / 2)} V ${ - lineStartY + 25 - } H ${startx}` + `M ${startx},${lineStartY} H ${ + startx + common.getMax(conf.width / 2, textWidth / 2) + } V ${lineStartY + 25} H ${startx}` ); } else { line = diagram @@ -462,29 +478,19 @@ const drawMessage = function (diagram, msgModel, lineStartY: number, diagObj: Di } }; -export const drawActors = function ( +const addActorRenderingData = function ( diagram, actors, + createdActors, actorKeys, verticalPos, - configuration, messages, isFooter ) { - if (configuration.hideUnusedParticipants === true) { - const newActors = new Set(); - messages.forEach((message) => { - newActors.add(message.from); - newActors.add(message.to); - }); - actorKeys = actorKeys.filter((actorKey) => newActors.has(actorKey)); - } - - // Draw the actors let prevWidth = 0; let prevMargin = 0; - let maxHeight = 0; let prevBox = undefined; + let maxHeight = 0; for (const actorKey of actorKeys) { const actor = actors[actorKey]; @@ -509,15 +515,19 @@ export const drawActors = function ( // Add some rendering data to the object actor.width = actor.width || conf.width; - actor.height = Math.max(actor.height || conf.height, conf.height); + actor.height = common.getMax(actor.height || conf.height, conf.height); actor.margin = actor.margin || conf.actorMargin; - actor.x = prevWidth + prevMargin; - actor.y = bounds.getVerticalPos(); + maxHeight = common.getMax(maxHeight, actor.height); + + // if the actor is created by a message, widen margin + if (createdActors[actor.name]) { + prevMargin += actor.width / 2; + } + + actor.x = prevWidth + prevMargin; + actor.starty = bounds.getVerticalPos(); - // Draw the box with the attached line - const height = svgDraw.drawActor(diagram, actor, conf, isFooter); - maxHeight = Math.max(maxHeight, height); bounds.insert(actor.x, verticalPos, actor.x + actor.width, actor.height); prevWidth += actor.width + prevMargin; @@ -538,6 +548,28 @@ export const drawActors = function ( bounds.bumpVerticalPos(maxHeight); }; +export const drawActors = function (diagram, actors, actorKeys, isFooter) { + if (!isFooter) { + for (const actorKey of actorKeys) { + const actor = actors[actorKey]; + // Draw the box with the attached line + svgDraw.drawActor(diagram, actor, conf, false); + } + } else { + let maxHeight = 0; + bounds.bumpVerticalPos(conf.boxMargin * 2); + for (const actorKey of actorKeys) { + const actor = actors[actorKey]; + if (!actor.stopy) { + actor.stopy = bounds.getVerticalPos(); + } + const height = svgDraw.drawActor(diagram, actor, conf, true); + maxHeight = common.getMax(maxHeight, height); + } + bounds.bumpVerticalPos(maxHeight + conf.boxMargin); + } +}; + export const drawActorsPopup = function (diagram, actors, actorKeys, doc) { let maxHeight = 0; let maxWidth = 0; @@ -589,11 +621,11 @@ const activationBounds = function (actor, actors) { const activations = actorActivations(actor); const left = activations.reduce(function (acc, activation) { - return Math.min(acc, activation.startx); - }, actorObj.x + actorObj.width / 2); + return common.getMin(acc, activation.startx); + }, actorObj.x + actorObj.width / 2 - 1); const right = activations.reduce(function (acc, activation) { - return Math.max(acc, activation.stopx); - }, actorObj.x + actorObj.width / 2); + return common.getMax(acc, activation.stopx); + }, actorObj.x + actorObj.width / 2 + 1); return [left, right]; }; @@ -609,7 +641,7 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop // const lines = common.splitBreaks(msg.message).length; const textDims = utils.calculateTextDimensions(msg.message, textConf); - const totalOffset = Math.max(textDims.height, conf.labelBoxHeight); + const totalOffset = common.getMax(textDims.height, conf.labelBoxHeight); heightAdjust = postMargin + totalOffset; log.debug(`${totalOffset} - ${msg.message}`); } @@ -617,6 +649,95 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop bounds.bumpVerticalPos(heightAdjust); } +/** + * Adjust the msgModel and the actor for the rendering in case the latter is created or destroyed by the msg + * @param msg - the potentially creating or destroying message + * @param msgModel - the model associated with the message + * @param lineStartY - the y position of the message line + * @param index - the index of the current actor under consideration + * @param actors - the array of all actors + * @param createdActors - the array of actors created in the diagram + * @param destroyedActors - the array of actors destroyed in the diagram + */ +function adjustCreatedDestroyedData( + msg, + msgModel, + lineStartY, + index, + actors, + createdActors, + destroyedActors +) { + function receiverAdjustment(actor, adjustment) { + if (actor.x < actors[msg.from].x) { + bounds.insert( + msgModel.stopx - adjustment, + msgModel.starty, + msgModel.startx, + msgModel.stopy + actor.height / 2 + conf.noteMargin + ); + msgModel.stopx = msgModel.stopx + adjustment; + } else { + bounds.insert( + msgModel.startx, + msgModel.starty, + msgModel.stopx + adjustment, + msgModel.stopy + actor.height / 2 + conf.noteMargin + ); + msgModel.stopx = msgModel.stopx - adjustment; + } + } + + function senderAdjustment(actor, adjustment) { + if (actor.x < actors[msg.to].x) { + bounds.insert( + msgModel.startx - adjustment, + msgModel.starty, + msgModel.stopx, + msgModel.stopy + actor.height / 2 + conf.noteMargin + ); + msgModel.startx = msgModel.startx + adjustment; + } else { + bounds.insert( + msgModel.stopx, + msgModel.starty, + msgModel.startx + adjustment, + msgModel.stopy + actor.height / 2 + conf.noteMargin + ); + msgModel.startx = msgModel.startx - adjustment; + } + } + + // if it is a create message + if (createdActors[msg.to] == index) { + const actor = actors[msg.to]; + const adjustment = actor.type == 'actor' ? ACTOR_TYPE_WIDTH / 2 + 3 : actor.width / 2 + 3; + receiverAdjustment(actor, adjustment); + actor.starty = lineStartY - actor.height / 2; + bounds.bumpVerticalPos(actor.height / 2); + } + // if it is a destroy sender message + else if (destroyedActors[msg.from] == index) { + const actor = actors[msg.from]; + if (conf.mirrorActors) { + const adjustment = actor.type == 'actor' ? ACTOR_TYPE_WIDTH / 2 : actor.width / 2; + senderAdjustment(actor, adjustment); + } + actor.stopy = lineStartY - actor.height / 2; + bounds.bumpVerticalPos(actor.height / 2); + } + // if it is a destroy receiver message + else if (destroyedActors[msg.to] == index) { + const actor = actors[msg.to]; + if (conf.mirrorActors) { + const adjustment = actor.type == 'actor' ? ACTOR_TYPE_WIDTH / 2 + 3 : actor.width / 2 + 3; + receiverAdjustment(actor, adjustment); + } + actor.stopy = lineStartY - actor.height / 2; + bounds.bumpVerticalPos(actor.height / 2); + } +} + /** * Draws a sequenceDiagram in the tag with id: id based on the graph definition in text. * @@ -628,9 +749,6 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop export const draw = function (_text: string, id: string, _version: string, diagObj: Diagram) { const { securityLevel, sequence } = configApi.getConfig(); conf = sequence; - diagObj.db.clear(); - // Parse the graph definition - diagObj.parser.parse(_text); // Handle root and Document for when rendering in sandbox mode let sandboxElement; if (securityLevel === 'sandbox') { @@ -650,8 +768,10 @@ export const draw = function (_text: string, id: string, _version: string, diagO // Fetch data from the parsing const actors = diagObj.db.getActors(); + const createdActors = diagObj.db.getCreatedActors(); + const destroyedActors = diagObj.db.getDestroyedActors(); const boxes = diagObj.db.getBoxes(); - const actorKeys = diagObj.db.getActorKeys(); + let actorKeys = diagObj.db.getActorKeys(); const messages = diagObj.db.getMessages(); const title = diagObj.db.getDiagramTitle(); const hasBoxes = diagObj.db.hasAtLeastOneBox(); @@ -670,7 +790,16 @@ export const draw = function (_text: string, id: string, _version: string, diagO } } - drawActors(diagram, actors, actorKeys, 0, conf, messages, false); + if (conf.hideUnusedParticipants === true) { + const newActors = new Set(); + messages.forEach((message) => { + newActors.add(message.from); + newActors.add(message.to); + }); + actorKeys = actorKeys.filter((actorKey) => newActors.has(actorKey)); + } + + addActorRenderingData(diagram, actors, createdActors, actorKeys, 0, messages, false); const loopWidths = calculateLoopBounds(messages, actors, maxMessageWidthPerActor, diagObj); // The arrow head definition is attached to the svg once @@ -704,11 +833,13 @@ export const draw = function (_text: string, id: string, _version: string, diagO let sequenceIndex = 1; let sequenceIndexStep = 1; const messagesToDraw = []; - messages.forEach(function (msg) { + const backgrounds = []; + messages.forEach(function (msg, index) { let loopModel, noteModel, msgModel; switch (msg.type) { case diagObj.db.LINETYPE.NOTE: + bounds.resetVerticalPos(); noteModel = msg.noteModel; drawNote(diagram, noteModel); break; @@ -740,7 +871,7 @@ export const draw = function (_text: string, id: string, _version: string, diagO break; case diagObj.db.LINETYPE.RECT_END: loopModel = bounds.endLoop(); - svgDraw.drawBackgroundRect(diagram, loopModel); + backgrounds.push(loopModel); bounds.models.addLoop(loopModel); bounds.bumpVerticalPos(loopModel.stopy - bounds.getVerticalPos()); break; @@ -784,6 +915,7 @@ export const draw = function (_text: string, id: string, _version: string, diagO bounds.models.addLoop(loopModel); break; case diagObj.db.LINETYPE.PAR_START: + case diagObj.db.LINETYPE.PAR_OVER_START: adjustLoopHeightForWrap( loopWidths, msg, @@ -791,6 +923,7 @@ export const draw = function (_text: string, id: string, _version: string, diagO conf.boxMargin + conf.boxTextMargin, (message) => bounds.newLoop(message) ); + bounds.saveVerticalPos(); break; case diagObj.db.LINETYPE.PAR_AND: adjustLoopHeightForWrap( @@ -857,12 +990,20 @@ export const draw = function (_text: string, id: string, _version: string, diagO break; default: try { - // lastMsg = msg msgModel = msg.msgModel; msgModel.starty = bounds.getVerticalPos(); msgModel.sequenceIndex = sequenceIndex; msgModel.sequenceVisible = diagObj.db.showSequenceNumbers(); const lineStartY = boundMessage(diagram, msgModel); + adjustCreatedDestroyedData( + msg, + msgModel, + lineStartY, + index, + actors, + createdActors, + destroyedActors + ); messagesToDraw.push({ messageModel: msgModel, lineStartY: lineStartY }); bounds.models.addMessage(msgModel); } catch (e) { @@ -887,15 +1028,16 @@ export const draw = function (_text: string, id: string, _version: string, diagO } }); - messagesToDraw.forEach((e) => drawMessage(diagram, e.messageModel, e.lineStartY, diagObj)); + log.debug('createdActors', createdActors); + log.debug('destroyedActors', destroyedActors); + drawActors(diagram, actors, actorKeys, false); + messagesToDraw.forEach((e) => drawMessage(diagram, e.messageModel, e.lineStartY, diagObj)); if (conf.mirrorActors) { - // Draw actors below diagram - bounds.bumpVerticalPos(conf.boxMargin * 2); - drawActors(diagram, actors, actorKeys, bounds.getVerticalPos(), conf, messages, true); - bounds.bumpVerticalPos(conf.boxMargin); - fixLifeLineHeights(diagram, bounds.getVerticalPos()); + drawActors(diagram, actors, actorKeys, true); } + backgrounds.forEach((e) => svgDraw.drawBackgroundRect(diagram, e)); + fixLifeLineHeights(diagram, actors, actorKeys, conf); bounds.models.boxes.forEach(function (box) { box.height = bounds.getVerticalPos() - box.y; @@ -917,11 +1059,6 @@ export const draw = function (_text: string, id: string, _version: string, diagO const { bounds: box } = bounds.getBounds(); - // Adjust line height of actor lines now that the height of the diagram is known - log.debug('For line height fix Querying: #' + id + ' .actor-line'); - const actorLines = selectAll('#' + id + ' .actor-line'); - actorLines.attr('y2', box.stopy); - // Make sure the height of the diagram supports long menus. let boxHeight = box.stopy - box.starty; if (boxHeight < requiredBoxSize.maxHeight) { @@ -1025,45 +1162,45 @@ function getMaxMessageWidthPerActor( * margin */ if (isMessage && msg.from === actor.nextActor) { - maxMessageWidthPerActor[msg.to] = Math.max( + maxMessageWidthPerActor[msg.to] = common.getMax( maxMessageWidthPerActor[msg.to] || 0, messageWidth ); } else if (isMessage && msg.from === actor.prevActor) { - maxMessageWidthPerActor[msg.from] = Math.max( + maxMessageWidthPerActor[msg.from] = common.getMax( maxMessageWidthPerActor[msg.from] || 0, messageWidth ); } else if (isMessage && msg.from === msg.to) { - maxMessageWidthPerActor[msg.from] = Math.max( + maxMessageWidthPerActor[msg.from] = common.getMax( maxMessageWidthPerActor[msg.from] || 0, messageWidth / 2 ); - maxMessageWidthPerActor[msg.to] = Math.max( + maxMessageWidthPerActor[msg.to] = common.getMax( maxMessageWidthPerActor[msg.to] || 0, messageWidth / 2 ); } else if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) { - maxMessageWidthPerActor[msg.from] = Math.max( + maxMessageWidthPerActor[msg.from] = common.getMax( maxMessageWidthPerActor[msg.from] || 0, messageWidth ); } else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) { - maxMessageWidthPerActor[actor.prevActor] = Math.max( + maxMessageWidthPerActor[actor.prevActor] = common.getMax( maxMessageWidthPerActor[actor.prevActor] || 0, messageWidth ); } else if (msg.placement === diagObj.db.PLACEMENT.OVER) { if (actor.prevActor) { - maxMessageWidthPerActor[actor.prevActor] = Math.max( + maxMessageWidthPerActor[actor.prevActor] = common.getMax( maxMessageWidthPerActor[actor.prevActor] || 0, messageWidth / 2 ); } if (actor.nextActor) { - maxMessageWidthPerActor[msg.from] = Math.max( + maxMessageWidthPerActor[msg.from] = common.getMax( maxMessageWidthPerActor[msg.from] || 0, messageWidth / 2 ); @@ -1119,10 +1256,10 @@ function calculateActorMargins( const actDims = utils.calculateTextDimensions(actor.description, actorFont(conf)); actor.width = actor.wrap ? conf.width - : Math.max(conf.width, actDims.width + 2 * conf.wrapPadding); + : common.getMax(conf.width, actDims.width + 2 * conf.wrapPadding); - actor.height = actor.wrap ? Math.max(actDims.height, conf.height) : conf.height; - maxHeight = Math.max(maxHeight, actor.height); + actor.height = actor.wrap ? common.getMax(actDims.height, conf.height) : conf.height; + maxHeight = common.getMax(maxHeight, actor.height); }); for (const actorKey in actorToMessageWidth) { @@ -1138,14 +1275,14 @@ function calculateActorMargins( if (!nextActor) { const messageWidth = actorToMessageWidth[actorKey]; const actorWidth = messageWidth + conf.actorMargin - actor.width / 2; - actor.margin = Math.max(actorWidth, conf.actorMargin); + actor.margin = common.getMax(actorWidth, conf.actorMargin); continue; } const messageWidth = actorToMessageWidth[actorKey]; const actorWidth = messageWidth + conf.actorMargin - actor.width / 2 - nextActor.width / 2; - actor.margin = Math.max(actorWidth, conf.actorMargin); + actor.margin = common.getMax(actorWidth, conf.actorMargin); } let maxBoxHeight = 0; @@ -1161,8 +1298,8 @@ function calculateActorMargins( } const boxMsgDimensions = utils.calculateTextDimensions(box.name, textFont); - maxBoxHeight = Math.max(boxMsgDimensions.height, maxBoxHeight); - const minWidth = Math.max(totalWidth, boxMsgDimensions.width + 2 * conf.wrapPadding); + maxBoxHeight = common.getMax(boxMsgDimensions.height, maxBoxHeight); + const minWidth = common.getMax(totalWidth, boxMsgDimensions.width + 2 * conf.wrapPadding); box.margin = conf.boxTextMargin; if (totalWidth < minWidth) { const missing = (minWidth - totalWidth) / 2; @@ -1171,7 +1308,7 @@ function calculateActorMargins( }); boxes.forEach((box) => (box.textMaxHeight = maxBoxHeight)); - return Math.max(maxHeight, conf.height); + return common.getMax(maxHeight, conf.height); } const buildNoteModel = function (msg, actors, diagObj) { @@ -1186,7 +1323,7 @@ const buildNoteModel = function (msg, actors, diagObj) { const noteModel = { width: shouldWrap ? conf.width - : Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin), + : common.getMax(conf.width, textDimensions.width + 2 * conf.noteMargin), height: 0, startx: actors[msg.from].x, stopx: 0, @@ -1196,16 +1333,16 @@ const buildNoteModel = function (msg, actors, diagObj) { }; if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) { noteModel.width = shouldWrap - ? Math.max(conf.width, textDimensions.width) - : Math.max( + ? common.getMax(conf.width, textDimensions.width) + : common.getMax( actors[msg.from].width / 2 + actors[msg.to].width / 2, textDimensions.width + 2 * conf.noteMargin ); noteModel.startx = startx + (actors[msg.from].width + conf.actorMargin) / 2; } else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) { noteModel.width = shouldWrap - ? Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin) - : Math.max( + ? common.getMax(conf.width, textDimensions.width + 2 * conf.noteMargin) + : common.getMax( actors[msg.from].width / 2 + actors[msg.to].width / 2, textDimensions.width + 2 * conf.noteMargin ); @@ -1213,13 +1350,21 @@ const buildNoteModel = function (msg, actors, diagObj) { } else if (msg.to === msg.from) { textDimensions = utils.calculateTextDimensions( shouldWrap - ? utils.wrapLabel(msg.message, Math.max(conf.width, actors[msg.from].width), noteFont(conf)) + ? utils.wrapLabel( + msg.message, + common.getMax(conf.width, actors[msg.from].width), + noteFont(conf) + ) : msg.message, noteFont(conf) ); noteModel.width = shouldWrap - ? Math.max(conf.width, actors[msg.from].width) - : Math.max(actors[msg.from].width, conf.width, textDimensions.width + 2 * conf.noteMargin); + ? common.getMax(conf.width, actors[msg.from].width) + : common.getMax( + actors[msg.from].width, + conf.width, + textDimensions.width + 2 * conf.noteMargin + ); noteModel.startx = startx + (actors[msg.from].width - noteModel.width) / 2; } else { noteModel.width = @@ -1244,9 +1389,8 @@ const buildNoteModel = function (msg, actors, diagObj) { }; const buildMessageModel = function (msg, actors, diagObj) { - let process = false; if ( - [ + ![ diagObj.db.LINETYPE.SOLID_OPEN, diagObj.db.LINETYPE.DOTTED_OPEN, diagObj.db.LINETYPE.SOLID, @@ -1257,35 +1401,65 @@ const buildMessageModel = function (msg, actors, diagObj) { diagObj.db.LINETYPE.DOTTED_POINT, ].includes(msg.type) ) { - process = true; - } - if (!process) { return {}; } - const fromBounds = activationBounds(msg.from, actors); - const toBounds = activationBounds(msg.to, actors); - const fromIdx = fromBounds[0] <= toBounds[0] ? 1 : 0; - const toIdx = fromBounds[0] < toBounds[0] ? 0 : 1; - const allBounds = [...fromBounds, ...toBounds]; - const boundedWidth = Math.abs(toBounds[toIdx] - fromBounds[fromIdx]); + const [fromLeft, fromRight] = activationBounds(msg.from, actors); + const [toLeft, toRight] = activationBounds(msg.to, actors); + const isArrowToRight = fromLeft <= toLeft; + const startx = isArrowToRight ? fromRight : fromLeft; + let stopx = isArrowToRight ? toLeft : toRight; + + // As the line width is considered, the left and right values will be off by 2. + const isArrowToActivation = Math.abs(toLeft - toRight) > 2; + + /** + * Adjust the value based on the arrow direction + * @param value - The value to adjust + * @returns The adjustment with correct sign to be added to the actual value. + */ + const adjustValue = (value: number) => { + return isArrowToRight ? -value : value; + }; + + /** + * This is an edge case for the first activation. + * Proper fix would require significant changes. + * So, we set an activate flag in the message, and cross check that with isToActivation + * In cases where the message is to an activation that was properly detected, we don't want to move the arrow head + * The activation will not be detected on the first message, so we need to move the arrow head + */ + if (msg.activate && !isArrowToActivation) { + stopx += adjustValue(conf.activationWidth / 2 - 1); + } + + /** + * Shorten the length of arrow at the end and move the marker forward (using refX) to have a clean arrowhead + * This is not required for open arrows that don't have arrowheads + */ + if (![diagObj.db.LINETYPE.SOLID_OPEN, diagObj.db.LINETYPE.DOTTED_OPEN].includes(msg.type)) { + stopx += adjustValue(3); + } + + const allBounds = [fromLeft, fromRight, toLeft, toRight]; + const boundedWidth = Math.abs(startx - stopx); if (msg.wrap && msg.message) { msg.message = utils.wrapLabel( msg.message, - Math.max(boundedWidth + 2 * conf.wrapPadding, conf.width), + common.getMax(boundedWidth + 2 * conf.wrapPadding, conf.width), messageFont(conf) ); } const msgDims = utils.calculateTextDimensions(msg.message, messageFont(conf)); return { - width: Math.max( + width: common.getMax( msg.wrap ? 0 : msgDims.width + 2 * conf.wrapPadding, boundedWidth + 2 * conf.wrapPadding, conf.width ), height: 0, - startx: fromBounds[fromIdx], - stopx: toBounds[toIdx], + startx, + stopx, starty: 0, stopy: 0, message: msg.message, @@ -1308,6 +1482,7 @@ const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagO case diagObj.db.LINETYPE.ALT_START: case diagObj.db.LINETYPE.OPT_START: case diagObj.db.LINETYPE.PAR_START: + case diagObj.db.LINETYPE.PAR_OVER_START: case diagObj.db.LINETYPE.CRITICAL_START: case diagObj.db.LINETYPE.BREAK_START: stack.push({ @@ -1367,10 +1542,10 @@ const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagO msg.noteModel = noteModel; stack.forEach((stk) => { current = stk; - current.from = Math.min(current.from, noteModel.startx); - current.to = Math.max(current.to, noteModel.startx + noteModel.width); + current.from = common.getMin(current.from, noteModel.startx); + current.to = common.getMax(current.to, noteModel.startx + noteModel.width); current.width = - Math.max(current.width, Math.abs(current.from - current.to)) - conf.labelBoxWidth; + common.getMax(current.width, Math.abs(current.from - current.to)) - conf.labelBoxWidth; }); } else { msgModel = buildMessageModel(msg, actors, diagObj); @@ -1381,18 +1556,23 @@ const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagO if (msgModel.startx === msgModel.stopx) { const from = actors[msg.from]; const to = actors[msg.to]; - current.from = Math.min( + current.from = common.getMin( from.x - msgModel.width / 2, from.x - from.width / 2, current.from ); - current.to = Math.max(to.x + msgModel.width / 2, to.x + from.width / 2, current.to); + current.to = common.getMax( + to.x + msgModel.width / 2, + to.x + from.width / 2, + current.to + ); current.width = - Math.max(current.width, Math.abs(current.to - current.from)) - conf.labelBoxWidth; + common.getMax(current.width, Math.abs(current.to - current.from)) - + conf.labelBoxWidth; } else { - current.from = Math.min(msgModel.startx, current.from); - current.to = Math.max(msgModel.stopx, current.to); - current.width = Math.max(current.width, msgModel.width) - conf.labelBoxWidth; + current.from = common.getMin(msgModel.startx, current.from); + current.to = common.getMax(msgModel.stopx, current.to); + current.width = common.getMax(current.width, msgModel.width) - conf.labelBoxWidth; } }); } diff --git a/packages/mermaid/src/diagrams/sequence/svgDraw.js b/packages/mermaid/src/diagrams/sequence/svgDraw.js index be34daf4b..f81147c10 100644 --- a/packages/mermaid/src/diagrams/sequence/svgDraw.js +++ b/packages/mermaid/src/diagrams/sequence/svgDraw.js @@ -1,33 +1,15 @@ -import common from '../common/common'; -import { addFunction } from '../../interactionDb'; -import { parseFontSize } from '../../utils'; +import common from '../common/common.js'; +import * as svgDrawCommon from '../common/svgDrawCommon.js'; +import { addFunction } from '../../interactionDb.js'; +import { ZERO_WIDTH_SPACE, parseFontSize } from '../../utils.js'; import { sanitizeUrl } from '@braintree/sanitize-url'; +export const ACTOR_TYPE_WIDTH = 18 * 2; + export const drawRect = function (elem, rectData) { - const rectElem = elem.append('rect'); - rectElem.attr('x', rectData.x); - rectElem.attr('y', rectData.y); - rectElem.attr('fill', rectData.fill); - rectElem.attr('stroke', rectData.stroke); - rectElem.attr('width', rectData.width); - rectElem.attr('height', rectData.height); - rectElem.attr('rx', rectData.rx); - rectElem.attr('ry', rectData.ry); - - if (rectData.class !== undefined) { - rectElem.attr('class', rectData.class); - } - - return rectElem; + return svgDrawCommon.drawRect(elem, rectData); }; -// const sanitizeUrl = function (s) { -// return s -// .replace(/&/g, '&') -// .replace(/</g, '<') -// .replace(/javascript:/g, ''); -// }; - const addPopupInteraction = (id, actorCnt) => { addFunction(() => { const arr = document.querySelectorAll(id); @@ -43,6 +25,7 @@ const addPopupInteraction = (id, actorCnt) => { }); }); }; + export const drawPopup = function (elem, actor, minMenuWidth, textAttrs, forceMenus) { if (actor.links === undefined || actor.links === null || Object.keys(actor.links).length === 0) { return { height: 0, width: 0 }; @@ -107,22 +90,6 @@ export const drawPopup = function (elem, actor, minMenuWidth, textAttrs, forceMe return { height: rectData.height + linkY, width: menuWidth }; }; -export const drawImage = function (elem, x, y, link) { - const imageElem = elem.append('image'); - imageElem.attr('x', x); - imageElem.attr('y', y); - var sanitizedLink = sanitizeUrl(link); - imageElem.attr('xlink:href', sanitizedLink); -}; - -export const drawEmbeddedImage = function (elem, x, y, link) { - const imageElem = elem.append('use'); - imageElem.attr('x', x); - imageElem.attr('y', y); - var sanitizedLink = sanitizeUrl(link); - imageElem.attr('xlink:href', '#' + sanitizedLink); -}; - export const popupMenu = function (popid) { return ( "var pu = document.getElementById('" + @@ -152,9 +119,10 @@ const popupMenuDownFunc = function (popupId) { pu.style.display = 'none'; } }; + export const drawText = function (elem, textData) { - let prevTextHeight = 0, - textHeight = 0; + let prevTextHeight = 0; + let textHeight = 0; const lines = textData.text.split(common.lineBreakRegex); const [_textFontSize, _textFontSizePx] = parseFontSize(textData.fontSize); @@ -188,6 +156,7 @@ export const drawText = function (elem, textData) { break; } } + if ( textData.anchor !== undefined && textData.textMargin !== undefined && @@ -217,6 +186,7 @@ export const drawText = function (elem, textData) { break; } } + for (let [i, line] of lines.entries()) { if ( textData.textMargin !== undefined && @@ -256,15 +226,16 @@ export const drawText = function (elem, textData) { textElem.attr('dy', dy); } + const text = line || ZERO_WIDTH_SPACE; if (textData.tspan) { const span = textElem.append('tspan'); span.attr('x', textData.x); if (textData.fill !== undefined) { span.attr('fill', textData.fill); } - span.text(line); + span.text(text); } else { - textElem.text(line); + textElem.text(text); } if ( textData.valign !== undefined && @@ -325,14 +296,19 @@ export const drawLabel = function (elem, txtObject) { let actorCnt = -1; -export const fixLifeLineHeights = (diagram, bounds) => { - if (!diagram.selectAll) { +export const fixLifeLineHeights = (diagram, actors, actorKeys, conf) => { + if (!diagram.select) { return; } - diagram - .selectAll('.actor-line') - .attr('class', '200') - .attr('y2', bounds - 55); + actorKeys.forEach((actorKey) => { + const actor = actors[actorKey]; + const actorDOM = diagram.select('#actor' + actor.actorCnt); + if (!conf.mirrorActors && actor.stopy) { + actorDOM.attr('y2', actor.stopy + actor.height / 2); + } else if (conf.mirrorActors) { + actorDOM.attr('y2', actor.stopy); + } + }); }; /** @@ -344,10 +320,11 @@ export const fixLifeLineHeights = (diagram, bounds) => { * @param {boolean} isFooter - If the actor is the footer one */ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) { + const actorY = isFooter ? actor.stopy : actor.starty; const center = actor.x + actor.width / 2; - const centerY = actor.y + 5; + const centerY = actorY + 5; - const boxpluslineGroup = elem.append('g'); + const boxpluslineGroup = elem.append('g').lower(); var g = boxpluslineGroup; if (!isFooter) { @@ -359,6 +336,7 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) { .attr('x2', center) .attr('y2', 2000) .attr('class', 'actor-line') + .attr('class', '200') .attr('stroke-width', '0.5px') .attr('stroke', '#999'); @@ -371,7 +349,7 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) { } } - const rect = getNoteRect(); + const rect = svgDrawCommon.getNoteRect(); var cssclass = 'actor'; if (actor.properties != null && actor.properties['class']) { cssclass = actor.properties['class']; @@ -379,7 +357,7 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) { rect.fill = '#eaeaea'; } rect.x = actor.x; - rect.y = actor.y; + rect.y = actorY; rect.width = actor.width; rect.height = actor.height; rect.class = cssclass; @@ -391,9 +369,9 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) { if (actor.properties != null && actor.properties['icon']) { const iconSrc = actor.properties['icon'].trim(); if (iconSrc.charAt(0) === '@') { - drawEmbeddedImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc.substr(1)); + svgDrawCommon.drawEmbeddedImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc.substr(1)); } else { - drawImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc); + svgDrawCommon.drawImage(g, rect.x + rect.width - 20, rect.y + 10, iconSrc); } } @@ -419,8 +397,11 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) { }; const drawActorTypeActor = function (elem, actor, conf, isFooter) { + const actorY = isFooter ? actor.stopy : actor.starty; const center = actor.x + actor.width / 2; - const centerY = actor.y + 80; + const centerY = actorY + 80; + + elem.lower(); if (!isFooter) { actorCnt++; @@ -432,54 +413,56 @@ const drawActorTypeActor = function (elem, actor, conf, isFooter) { .attr('x2', center) .attr('y2', 2000) .attr('class', 'actor-line') + .attr('class', '200') .attr('stroke-width', '0.5px') .attr('stroke', '#999'); + + actor.actorCnt = actorCnt; } const actElem = elem.append('g'); actElem.attr('class', 'actor-man'); - const rect = getNoteRect(); + const rect = svgDrawCommon.getNoteRect(); rect.x = actor.x; - rect.y = actor.y; + rect.y = actorY; rect.fill = '#eaeaea'; rect.width = actor.width; rect.height = actor.height; rect.class = 'actor'; rect.rx = 3; rect.ry = 3; - // drawRect(actElem, rect); actElem .append('line') .attr('id', 'actor-man-torso' + actorCnt) .attr('x1', center) - .attr('y1', actor.y + 25) + .attr('y1', actorY + 25) .attr('x2', center) - .attr('y2', actor.y + 45); + .attr('y2', actorY + 45); actElem .append('line') .attr('id', 'actor-man-arms' + actorCnt) - .attr('x1', center - 18) - .attr('y1', actor.y + 33) - .attr('x2', center + 18) - .attr('y2', actor.y + 33); + .attr('x1', center - ACTOR_TYPE_WIDTH / 2) + .attr('y1', actorY + 33) + .attr('x2', center + ACTOR_TYPE_WIDTH / 2) + .attr('y2', actorY + 33); actElem .append('line') - .attr('x1', center - 18) - .attr('y1', actor.y + 60) + .attr('x1', center - ACTOR_TYPE_WIDTH / 2) + .attr('y1', actorY + 60) .attr('x2', center) - .attr('y2', actor.y + 45); + .attr('y2', actorY + 45); actElem .append('line') .attr('x1', center) - .attr('y1', actor.y + 45) - .attr('x2', center + 16) - .attr('y2', actor.y + 60); + .attr('y1', actorY + 45) + .attr('x2', center + ACTOR_TYPE_WIDTH / 2 - 2) + .attr('y2', actorY + 60); const circle = actElem.append('circle'); circle.attr('cx', actor.x + actor.width / 2); - circle.attr('cy', actor.y + 10); + circle.attr('cy', actorY + 10); circle.attr('r', 15); circle.attr('width', actor.width); circle.attr('height', actor.height); @@ -532,6 +515,7 @@ export const drawBox = function (elem, box, conf) { export const anchorElement = function (elem) { return elem.append('g'); }; + /** * Draws an activation in the diagram * @@ -542,7 +526,7 @@ export const anchorElement = function (elem) { * @param {any} actorActivations - Number of activations on the actor. */ export const drawActivation = function (elem, bounds, verticalPos, conf, actorActivations) { - const rect = getNoteRect(); + const rect = svgDrawCommon.getNoteRect(); const g = bounds.anchored; rect.x = bounds.startx; rect.y = bounds.starty; @@ -594,7 +578,7 @@ export const drawLoop = function (elem, loopModel, labelText, conf) { }); } - let txt = getTextObj(); + let txt = svgDrawCommon.getTextObj(); txt.text = labelText; txt.x = loopModel.startx; txt.y = loopModel.starty; @@ -661,16 +645,7 @@ export const drawLoop = function (elem, loopModel, labelText, conf) { * @param {any} bounds Shape of the rectangle */ export const drawBackgroundRect = function (elem, bounds) { - const rectElem = drawRect(elem, { - x: bounds.startx, - y: bounds.starty, - width: bounds.stopx - bounds.startx, - height: bounds.stopy - bounds.starty, - fill: bounds.fill, - stroke: bounds.stroke, - class: 'rect', - }); - rectElem.lower(); + svgDrawCommon.drawBackgroundRect(elem, bounds); }; export const insertDatabaseIcon = function (elem) { @@ -728,7 +703,7 @@ export const insertArrowHead = function (elem) { .append('defs') .append('marker') .attr('id', 'arrowhead') - .attr('refX', 9) + .attr('refX', 7.9) .attr('refY', 5) .attr('markerUnits', 'userSpaceOnUse') .attr('markerWidth', 12) @@ -737,6 +712,7 @@ export const insertArrowHead = function (elem) { .append('path') .attr('d', 'M 0 0 L 10 5 L 0 10 z'); // this is actual shape for arrowhead }; + /** * Setup arrow head and define the marker. The result is appended to the svg. * @@ -747,7 +723,7 @@ export const insertArrowFilledHead = function (elem) { .append('defs') .append('marker') .attr('id', 'filled-head') - .attr('refX', 18) + .attr('refX', 15.5) .attr('refY', 7) .attr('markerWidth', 20) .attr('markerHeight', 28) @@ -755,6 +731,7 @@ export const insertArrowFilledHead = function (elem) { .append('path') .attr('d', 'M 18,7 L9,13 L14,7 L9,1 Z'); }; + /** * Setup node number. The result is appended to the svg. * @@ -776,6 +753,7 @@ export const insertSequenceNumber = function (elem) { .attr('r', 6); // .style("fill", '#f00'); }; + /** * Setup cross head and define the marker. The result is appended to the svg. * @@ -790,7 +768,7 @@ export const insertArrowCrossHead = function (elem) { .attr('markerHeight', 8) .attr('orient', 'auto') .attr('refX', 4) - .attr('refY', 5); + .attr('refY', 4.5); // The cross marker .append('path') @@ -1062,8 +1040,6 @@ export default { drawActor, drawBox, drawPopup, - drawImage, - drawEmbeddedImage, anchorElement, drawActivation, drawLoop, diff --git a/packages/mermaid/src/diagrams/sequence/svgDraw.spec.js b/packages/mermaid/src/diagrams/sequence/svgDraw.spec.js index ed60285ed..c17bf0f1a 100644 --- a/packages/mermaid/src/diagrams/sequence/svgDraw.spec.js +++ b/packages/mermaid/src/diagrams/sequence/svgDraw.spec.js @@ -1,5 +1,5 @@ import { vi } from 'vitest'; -import svgDraw from './svgDraw'; +import svgDraw from './svgDraw.js'; // This is the only place that uses this mock export const MockD3 = (name, parent) => { @@ -174,16 +174,4 @@ describe('svgDraw', function () { expect(rect.lower).toHaveBeenCalled(); }); }); - describe('sanitizeUrl', function () { - it('should sanitize malicious urls', function () { - const maliciousStr = 'javascript:script:alert(1)'; - const result = svgDraw.sanitizeUrl(maliciousStr); - expect(result).not.toContain('javascript:alert(1)'); - }); - it('should not sanitize non dangerous urls', function () { - const maliciousStr = 'javajavascript:script:alert(1)'; - const result = svgDraw.sanitizeUrl(maliciousStr); - expect(result).not.toContain('javascript:alert(1)'); - }); - }); }); diff --git a/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js b/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js index 5ec5642e1..e56931ade 100644 --- a/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js +++ b/packages/mermaid/src/diagrams/state/parser/state-parser.spec.js @@ -1,6 +1,6 @@ -import stateDb from '../stateDb'; -import stateDiagram from './stateDiagram'; -import { setConfig } from '../../../config'; +import stateDb from '../stateDb.js'; +import stateDiagram from './stateDiagram.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', @@ -117,7 +117,7 @@ describe('state parser can parse...', () => { state "Big State 1" as bigState1 { state "inner state 1" as inner1 inner2: inner state 2 - inner1 --> inner2 + inner1 --> inner2 }`; stateDiagram.parser.parse(diagramText); stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2()); diff --git a/packages/mermaid/src/diagrams/state/parser/state-style.spec.js b/packages/mermaid/src/diagrams/state/parser/state-style.spec.js index 75ecb4b13..9ce41df50 100644 --- a/packages/mermaid/src/diagrams/state/parser/state-style.spec.js +++ b/packages/mermaid/src/diagrams/state/parser/state-style.spec.js @@ -1,6 +1,6 @@ -import stateDb from '../stateDb'; -import stateDiagram from './stateDiagram'; -import { setConfig } from '../../../config'; +import stateDb from '../stateDb.js'; +import stateDiagram from './stateDiagram.jison'; +import { setConfig } from '../../../config.js'; setConfig({ securityLevel: 'strict', diff --git a/packages/mermaid/src/diagrams/state/shapes.js b/packages/mermaid/src/diagrams/state/shapes.js index 0a495e56c..e82a1ad61 100644 --- a/packages/mermaid/src/diagrams/state/shapes.js +++ b/packages/mermaid/src/diagrams/state/shapes.js @@ -1,10 +1,10 @@ import { line, curveBasis } from 'd3'; import idCache from './id-cache.js'; -import stateDb from './stateDb'; -import utils from '../../utils'; -import common from '../common/common'; -import { getConfig } from '../../config'; -import { log } from '../../logger'; +import stateDb from './stateDb.js'; +import utils from '../../utils.js'; +import common from '../common/common.js'; +import { getConfig } from '../../config.js'; +import { log } from '../../logger.js'; /** * Draws a start state as a black circle diff --git a/packages/mermaid/src/diagrams/state/stateDb.js b/packages/mermaid/src/diagrams/state/stateDb.js index 81b8ffb8b..f71290ec3 100644 --- a/packages/mermaid/src/diagrams/state/stateDb.js +++ b/packages/mermaid/src/diagrams/state/stateDb.js @@ -1,8 +1,8 @@ -import { log } from '../../logger'; -import { generateId } from '../../utils'; -import mermaidAPI from '../../mermaidAPI'; -import common from '../common/common'; -import * as configApi from '../../config'; +import { log } from '../../logger.js'; +import { generateId } from '../../utils.js'; +import mermaidAPI from '../../mermaidAPI.js'; +import common from '../common/common.js'; +import * as configApi from '../../config.js'; import { setAccTitle, getAccTitle, @@ -11,7 +11,7 @@ import { clear as commonClear, setDiagramTitle, getDiagramTitle, -} from '../../commonDb'; +} from '../common/commonDb.js'; import { DEFAULT_DIAGRAM_DIRECTION, @@ -21,7 +21,7 @@ import { STMT_APPLYCLASS, DEFAULT_STATE_TYPE, DIVIDER_TYPE, -} from './stateCommon'; +} from './stateCommon.js'; const START_NODE = '[*]'; const START_TYPE = 'start'; diff --git a/packages/mermaid/src/diagrams/state/stateDb.spec.js b/packages/mermaid/src/diagrams/state/stateDb.spec.js index d51d919c3..0264c34cc 100644 --- a/packages/mermaid/src/diagrams/state/stateDb.spec.js +++ b/packages/mermaid/src/diagrams/state/stateDb.spec.js @@ -1,4 +1,4 @@ -import stateDb from './stateDb'; +import stateDb from './stateDb.js'; describe('State Diagram stateDb', () => { beforeEach(() => { diff --git a/packages/mermaid/src/diagrams/state/stateDetector-V2.ts b/packages/mermaid/src/diagrams/state/stateDetector-V2.ts index 9e59c4a04..5201f3fae 100644 --- a/packages/mermaid/src/diagrams/state/stateDetector-V2.ts +++ b/packages/mermaid/src/diagrams/state/stateDetector-V2.ts @@ -1,11 +1,30 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const stateDetectorV2: DiagramDetector = (text, config) => { - if (text.match(/^\s*stateDiagram-v2/) !== null) { +const id = 'stateDiagram'; + +const detector: DiagramDetector = (txt, config) => { + if (/^\s*stateDiagram-v2/.test(txt)) { return true; } - if (text.match(/^\s*stateDiagram/) && config?.state?.defaultRenderer === 'dagre-wrapper') { + if (/^\s*stateDiagram/.test(txt) && config?.state?.defaultRenderer === 'dagre-wrapper') { return true; } return false; }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./stateDiagram-v2.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/state/stateDetector.ts b/packages/mermaid/src/diagrams/state/stateDetector.ts index 85338c6df..5903d06cf 100644 --- a/packages/mermaid/src/diagrams/state/stateDetector.ts +++ b/packages/mermaid/src/diagrams/state/stateDetector.ts @@ -1,10 +1,29 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const stateDetector: DiagramDetector = (txt, config) => { +const id = 'state'; + +const detector: DiagramDetector = (txt, config) => { // If we have confirmed to only use new state diagrams this function should always return false // as in not signalling true for a legacy state diagram if (config?.state?.defaultRenderer === 'dagre-wrapper') { return false; } - return txt.match(/^\s*stateDiagram/) !== null; + return /^\s*stateDiagram/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./stateDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/state/stateDiagram-v2.spec.js b/packages/mermaid/src/diagrams/state/stateDiagram-v2.spec.js index 7ed5555db..e64ecfdf8 100644 --- a/packages/mermaid/src/diagrams/state/stateDiagram-v2.spec.js +++ b/packages/mermaid/src/diagrams/state/stateDiagram-v2.spec.js @@ -1,5 +1,5 @@ -import { parser } from './parser/stateDiagram'; -import stateDb from './stateDb'; +import { parser } from './parser/stateDiagram.jison'; +import stateDb from './stateDb.js'; import stateDiagram from './parser/stateDiagram.jison'; describe('state diagram V2, ', function () { diff --git a/packages/mermaid/src/diagrams/state/stateDiagram-v2.ts b/packages/mermaid/src/diagrams/state/stateDiagram-v2.ts new file mode 100644 index 000000000..36fc95edd --- /dev/null +++ b/packages/mermaid/src/diagrams/state/stateDiagram-v2.ts @@ -0,0 +1,20 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: JISON doesn't support types +import parser from './parser/stateDiagram.jison'; +import db from './stateDb.js'; +import styles from './styles.js'; +import renderer from './stateRenderer-v2.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/state/stateDiagram.spec.js b/packages/mermaid/src/diagrams/state/stateDiagram.spec.js index d2bbb409e..e6e470140 100644 --- a/packages/mermaid/src/diagrams/state/stateDiagram.spec.js +++ b/packages/mermaid/src/diagrams/state/stateDiagram.spec.js @@ -1,5 +1,5 @@ -import { parser } from './parser/stateDiagram'; -import stateDb from './stateDb'; +import { parser } from './parser/stateDiagram.jison'; +import stateDb from './stateDb.js'; describe('state diagram, ', function () { describe('when parsing an info graph it', function () { diff --git a/packages/mermaid/src/diagrams/state/stateDiagram.ts b/packages/mermaid/src/diagrams/state/stateDiagram.ts new file mode 100644 index 000000000..643e847ce --- /dev/null +++ b/packages/mermaid/src/diagrams/state/stateDiagram.ts @@ -0,0 +1,20 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: JISON doesn't support types +import parser from './parser/stateDiagram.jison'; +import db from './stateDb.js'; +import styles from './styles.js'; +import renderer from './stateRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/state/stateRenderer-v2.js b/packages/mermaid/src/diagrams/state/stateRenderer-v2.js index 8629f74db..1c9b2d1d3 100644 --- a/packages/mermaid/src/diagrams/state/stateRenderer-v2.js +++ b/packages/mermaid/src/diagrams/state/stateRenderer-v2.js @@ -1,11 +1,11 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import { select } from 'd3'; -import { getConfig } from '../../config'; +import { getConfig } from '../../config.js'; import { render } from '../../dagre-wrapper/index.js'; -import { log } from '../../logger'; -import { configureSvgSize } from '../../setupGraphViewbox'; -import common from '../common/common'; -import utils from '../../utils'; +import { log } from '../../logger.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import common from '../common/common.js'; +import utils from '../../utils.js'; import { DEFAULT_DIAGRAM_DIRECTION, @@ -14,7 +14,7 @@ import { STMT_RELATION, DEFAULT_STATE_TYPE, DIVIDER_TYPE, -} from './stateCommon'; +} from './stateCommon.js'; // -------------------------------------- // Shapes @@ -84,17 +84,8 @@ export const setConf = function (cnf) { * @returns {object} ClassDef styles (a Map with keys = strings, values = ) */ export const getClasses = function (text, diagramObj) { - log.trace('Extracting classes'); - diagramObj.db.clear(); - try { - // Parse the graph definition - diagramObj.parser.parse(text); - // must run extract() to turn the parsed statements into states, relationships, classes, etc. - diagramObj.db.extract(diagramObj.db.getRootDocV2()); - return diagramObj.db.getClasses(); - } catch (e) { - return e; - } + diagramObj.db.extract(diagramObj.db.getRootDocV2()); + return diagramObj.db.getClasses(); }; /** @@ -232,6 +223,9 @@ const setupNode = (g, parent, parsedItem, diagramStates, diagramDb, altFlag) => type: newNode.type, padding: 15, //getConfig().flowchart.padding }; + // if (useHtmlLabels) { + nodeData.centerLabel = true; + // } if (parsedItem.note) { // Todo: set random id @@ -240,6 +234,7 @@ const setupNode = (g, parent, parsedItem, diagramStates, diagramDb, altFlag) => shape: SHAPE_NOTE, labelText: parsedItem.note.text, classes: CSS_DIAGRAM_NOTE, + // useHtmlLabels: false, style: '', // styles.style, id: itemId + NOTE_ID + '-' + graphItemCount, domId: stateDomId(itemId, graphItemCount, NOTE), @@ -354,7 +349,7 @@ const setupDoc = (g, parentParsedItem, doc, diagramStates, diagramDb, altFlag) = * 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 {object[]} parsedItem - the parsed statement item to look through - * @param [defaultDir=DEFAULT_NESTED_DOC_DIR] - the direction to use if none is found + * @param [defaultDir] - the direction to use if none is found * @returns {string} */ const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => { @@ -378,9 +373,8 @@ const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => { * @param _version * @param diag */ -export const draw = function (text, id, _version, diag) { +export const draw = async function (text, id, _version, diag) { log.info('Drawing state diagram (v2)', id); - // diag.sb.clear(); nodeDb = {}; // Fetch the default direction, use TD if none was found let dir = diag.db.getDirection(); @@ -432,7 +426,7 @@ export const draw = function (text, id, _version, diag) { // Run the renderer. This is what draws the final graph. const element = root.select('#' + id + ' g'); - render(element, g, ['barb'], CSS_DIAGRAM, id); + await render(element, g, ['barb'], CSS_DIAGRAM, id); const padding = 8; diff --git a/packages/mermaid/src/diagrams/state/stateRenderer-v2.spec.js b/packages/mermaid/src/diagrams/state/stateRenderer-v2.spec.js index 3a118e607..a190fe05b 100644 --- a/packages/mermaid/src/diagrams/state/stateRenderer-v2.spec.js +++ b/packages/mermaid/src/diagrams/state/stateRenderer-v2.spec.js @@ -1,8 +1,8 @@ import { expectTypeOf } from 'vitest'; -import { parser } from './parser/stateDiagram'; -import stateDb from './stateDb'; -import stateRendererV2 from './stateRenderer-v2'; +import { parser } from './parser/stateDiagram.jison'; +import stateDb from './stateDb.js'; +import stateRendererV2 from './stateRenderer-v2.js'; // Can use this instead of having to register diagrams and load/orchestrate them, etc. class FauxDiagramObj { diff --git a/packages/mermaid/src/diagrams/state/stateRenderer.js b/packages/mermaid/src/diagrams/state/stateRenderer.js index 8d410fdd9..1b3e0f27e 100644 --- a/packages/mermaid/src/diagrams/state/stateRenderer.js +++ b/packages/mermaid/src/diagrams/state/stateRenderer.js @@ -1,11 +1,11 @@ import { select } from 'd3'; import { layout as dagreLayout } from 'dagre-d3-es/src/dagre/index.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; -import { log } from '../../logger'; -import common from '../common/common'; -import { drawState, addTitleAndBox, drawEdge } from './shapes'; -import { getConfig } from '../../config'; -import { configureSvgSize } from '../../setupGraphViewbox'; +import { log } from '../../logger.js'; +import common from '../common/common.js'; +import { drawState, addTitleAndBox, drawEdge } from './shapes.js'; +import { getConfig } from '../../config.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; // TODO Move conf object to main conf in mermaidAPI let conf; @@ -57,28 +57,12 @@ export const draw = function (text, id, _version, diagObj) { : select('body'); const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; - // diagObj.db.clear(); - // parser.parse(text); log.debug('Rendering diagram ' + text); // Fetch the default direction, use TD if none was found const diagram = root.select(`[id='${id}']`); insertMarkers(diagram); - // Layout graph, Create a new directed graph - const graph = new graphlib.Graph({ - multigraph: true, - compound: true, - // acyclicer: 'greedy', - rankdir: 'RL', - // ranksep: '20' - }); - - // Default to assigning a new object as a label for each new edge. - graph.setDefaultEdgeLabel(function () { - return {}; - }); - const rootDoc = diagObj.db.getRootDoc(); renderDoc(rootDoc, diagram, undefined, false, root, doc, diagObj); diff --git a/packages/mermaid/src/diagrams/timeline/detector.ts b/packages/mermaid/src/diagrams/timeline/detector.ts index 9bd2b5ece..a6394bd54 100644 --- a/packages/mermaid/src/diagrams/timeline/detector.ts +++ b/packages/mermaid/src/diagrams/timeline/detector.ts @@ -1,12 +1,16 @@ -import type { ExternalDiagramDefinition } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; const id = 'timeline'; -const detector = (txt: string) => { - return txt.match(/^\s*timeline/) !== null; +const detector: DiagramDetector = (txt) => { + return /^\s*timeline/.test(txt); }; -const loader = async () => { +const loader: DiagramLoader = async () => { const { diagram } = await import('./timeline-definition.js'); return { id, diagram }; }; diff --git a/packages/mermaid/src/diagrams/timeline/timeline-definition.ts b/packages/mermaid/src/diagrams/timeline/timeline-definition.ts index 898af8b78..0c5561610 100644 --- a/packages/mermaid/src/diagrams/timeline/timeline-definition.ts +++ b/packages/mermaid/src/diagrams/timeline/timeline-definition.ts @@ -1,8 +1,8 @@ -// @ts-ignore: TODO Fix ts errors +// @ts-ignore: JISON doesn't support types import parser from './parser/timeline.jison'; -import * as db from './timelineDb'; -import renderer from './timelineRenderer'; -import styles from './styles'; +import * as db from './timelineDb.js'; +import renderer from './timelineRenderer.js'; +import styles from './styles.js'; export const diagram = { db, diff --git a/packages/mermaid/src/diagrams/timeline/timeline.spec.js b/packages/mermaid/src/diagrams/timeline/timeline.spec.js index 0697b194e..a6a94fd0c 100644 --- a/packages/mermaid/src/diagrams/timeline/timeline.spec.js +++ b/packages/mermaid/src/diagrams/timeline/timeline.spec.js @@ -1,8 +1,7 @@ -import { parser as timeline } from './parser/timeline'; -import * as timelineDB from './timelineDb'; -// import { injectUtils } from './mermaidUtils'; -import * as _commonDb from '../../commonDb'; -import { parseDirective as _parseDirective } from '../../directiveUtils'; +import { parser as timeline } from './parser/timeline.jison'; +import * as timelineDB from './timelineDb.js'; +// import { injectUtils } from './mermaidUtils.js'; +import { parseDirective as _parseDirective } from '../../directiveUtils.js'; import { log, @@ -10,7 +9,7 @@ import { getConfig, sanitizeText, setupGraphViewBox, -} from '../../diagram-api/diagramAPI'; +} from '../../diagram-api/diagramAPI.js'; // injectUtils( // log, @@ -18,7 +17,6 @@ import { // getConfig, // sanitizeText, // setupGraphViewBox, -// _commonDb, // _parseDirective // ); diff --git a/packages/mermaid/src/diagrams/timeline/timelineDb.js b/packages/mermaid/src/diagrams/timeline/timelineDb.js index 7bc5c2692..e5e22147d 100644 --- a/packages/mermaid/src/diagrams/timeline/timelineDb.js +++ b/packages/mermaid/src/diagrams/timeline/timelineDb.js @@ -1,5 +1,5 @@ -import { parseDirective as _parseDirective } from '../../directiveUtils'; -import * as commonDb from '../../commonDb'; +import { parseDirective as _parseDirective } from '../../directiveUtils.js'; +import * as commonDb from '../common/commonDb.js'; let currentSection = ''; let currentTaskId = 0; diff --git a/packages/mermaid/src/diagrams/timeline/timelineRenderer.ts b/packages/mermaid/src/diagrams/timeline/timelineRenderer.ts index 02e706bf6..ee351d905 100644 --- a/packages/mermaid/src/diagrams/timeline/timelineRenderer.ts +++ b/packages/mermaid/src/diagrams/timeline/timelineRenderer.ts @@ -1,28 +1,35 @@ -// @ts-nocheck TODO: fix file +// @ts-nocheck - don't check until handle it +import type { Selection } from 'd3'; import { select } from 'd3'; -import svgDraw from './svgDraw'; -import { log } from '../../logger'; -import { getConfig } from '../../config'; -import { setupGraphViewbox } from '../../setupGraphViewbox'; +import svgDraw from './svgDraw.js'; +import { log } from '../../logger.js'; +import { getConfig } from '../../config.js'; +import { setupGraphViewbox } from '../../setupGraphViewbox.js'; +import type { Diagram } from '../../Diagram.js'; +import type { MermaidConfig } from '../../config.type.js'; -export const setConf = function (cnf) { - const keys = Object.keys(cnf); +interface Block<TDesc, TSection> { + number: number; + descr: TDesc; + section: TSection; + width: number; + padding: number; + maxHeight: number; +} - keys.forEach(function (key) { - conf[key] = cnf[key]; - }); -}; - -export const draw = function (text, id, version, diagObj) { +interface TimelineTask { + id: number; + section: string; + type: string; + task: string; + score: number; + events: string[]; +} +export const draw = function (text: string, id: string, version: string, diagObj: Diagram) { //1. Fetch the configuration const conf = getConfig(); - const LEFT_MARGIN = conf.leftMargin ? conf.leftMargin : 50; - - //2. Clear the diagram db before parsing - diagObj.db.clear(); - - //3. Parse the diagram text - diagObj.parser.parse(text + '\n'); + // @ts-expect-error - wrong config? + const LEFT_MARGIN = conf.leftMargin ?? 50; log.debug('timeline', diagObj.db); @@ -42,7 +49,9 @@ export const draw = function (text, id, version, diagObj) { svg.append('g'); //4. Fetch the diagram data - const tasks = diagObj.db.getTasks(); + // @ts-expect-error - db not typed yet + const tasks: TimelineTask[] = diagObj.db.getTasks(); + // @ts-expect-error - db not typed yet const title = diagObj.db.getCommonDb().getDiagramTitle(); log.debug('task', tasks); @@ -50,7 +59,8 @@ export const draw = function (text, id, version, diagObj) { svgDraw.initGraphics(svg); // fetch Sections - const sections = diagObj.db.getSections(); + // @ts-expect-error - db not typed yet + const sections: string[] = diagObj.db.getSections(); log.debug('sections', sections); let maxSectionHeight = 0; @@ -67,8 +77,8 @@ export const draw = function (text, id, version, diagObj) { let hasSections = true; //Calculate the max height of the sections - sections.forEach(function (section) { - const sectionNode = { + sections.forEach(function (section: string) { + const sectionNode: Block<string, number> = { number: sectionNumber, descr: section, section: sectionNumber, @@ -87,8 +97,9 @@ export const draw = function (text, id, version, diagObj) { log.debug('tasks.length', tasks.length); //calculate max task height // for loop till tasks.length + for (const [i, task] of tasks.entries()) { - const taskNode = { + const taskNode: Block<TimelineTask, string> = { number: i, descr: task, section: task.section, @@ -124,11 +135,14 @@ export const draw = function (text, id, version, diagObj) { if (sections && sections.length > 0) { sections.forEach((section) => { - const sectionNode = { + //filter task where tasks.section == section + const tasksForSection = tasks.filter((task) => task.section === section); + + const sectionNode: Block<string, number> = { number: sectionNumber, descr: section, section: sectionNumber, - width: 150, + width: 200 * Math.max(tasksForSection.length, 1) - 50, padding: 20, maxHeight: maxSectionHeight, }; @@ -142,8 +156,6 @@ export const draw = function (text, id, version, diagObj) { masterY += maxSectionHeight + 50; //draw tasks for this section - //filter task where tasks.section == section - const tasksForSection = tasks.filter((task) => task.section === section); if (tasksForSection.length > 0) { drawTasks( svg, @@ -215,25 +227,25 @@ export const draw = function (text, id, version, diagObj) { setupGraphViewbox( undefined, svg, - conf.timeline.padding ? conf.timeline.padding : 50, - conf.timeline.useMaxWidth ? conf.timeline.useMaxWidth : false + conf.timeline?.padding ?? 50, + conf.timeline?.useMaxWidth ?? false ); // addSVGAccessibilityFields(diagObj.db, diagram, id); }; export const drawTasks = function ( - diagram, - tasks, - sectionColor, - masterX, - masterY, - maxTaskHeight, - conf, - maxEventCount, - maxEventLineLength, - maxSectionHeight, - isWithoutSections + diagram: Selection<SVGElement, unknown, null, undefined>, + tasks: TimelineTask[], + sectionColor: number, + masterX: number, + masterY: number, + maxTaskHeight: number, + conf: MermaidConfig, + maxEventCount: number, + maxEventLineLength: number, + maxSectionHeight: number, + isWithoutSections: boolean ) { // Draw the tasks for (const task of tasks) { @@ -249,6 +261,7 @@ export const drawTasks = function ( log.debug('taskNode', taskNode); // create task wrapper + const taskWrapper = diagram.append('g').attr('class', 'taskWrapper'); const node = svgDraw.drawNode(taskWrapper, taskNode, sectionColor, conf); const taskHeight = node.height; @@ -263,11 +276,11 @@ export const drawTasks = function ( if (task.events) { // draw a line between the task and the events const lineWrapper = diagram.append('g').attr('class', 'lineWrapper'); - let linelength = maxTaskHeight; + let lineLength = maxTaskHeight; //add margin to task masterY += 100; - linelength = - linelength + drawEvents(diagram, task.events, sectionColor, masterX, masterY, conf); + lineLength = + lineLength + drawEvents(diagram, task.events, sectionColor, masterX, masterY, conf); masterY -= 100; lineWrapper @@ -290,7 +303,7 @@ export const drawTasks = function ( } masterX = masterX + 200; - if (isWithoutSections && !getConfig().timeline.disableMulticolor) { + if (isWithoutSections && !conf.timeline?.disableMulticolor) { sectionColor++; } } @@ -299,14 +312,21 @@ export const drawTasks = function ( masterY = masterY - 10; }; -export const drawEvents = function (diagram, events, sectionColor, masterX, masterY, conf) { +export const drawEvents = function ( + diagram: Selection<SVGElement, unknown, null, undefined>, + events: string[], + sectionColor: number, + masterX: number, + masterY: number, + conf: MermaidConfig +) { let maxEventHeight = 0; const eventBeginY = masterY; masterY = masterY + 100; // Draw the events for (const event of events) { // create node from event - const eventNode = { + const eventNode: Block<string, number> = { descr: event, section: sectionColor, number: sectionColor, @@ -331,6 +351,8 @@ export const drawEvents = function (diagram, events, sectionColor, masterX, mast }; export default { - setConf, + setConf: () => { + // no-op + }, draw, }; diff --git a/packages/mermaid/src/diagrams/user-journey/journeyDb.js b/packages/mermaid/src/diagrams/user-journey/journeyDb.js index ce8705094..509c5dc14 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyDb.js +++ b/packages/mermaid/src/diagrams/user-journey/journeyDb.js @@ -1,5 +1,5 @@ -import mermaidAPI from '../../mermaidAPI'; -import * as configApi from '../../config'; +import mermaidAPI from '../../mermaidAPI.js'; +import * as configApi from '../../config.js'; import { setAccTitle, getAccTitle, @@ -8,7 +8,7 @@ import { getAccDescription, setAccDescription, clear as commonClear, -} from '../../commonDb'; +} from '../common/commonDb.js'; let currentSection = ''; diff --git a/packages/mermaid/src/diagrams/user-journey/journeyDb.spec.js b/packages/mermaid/src/diagrams/user-journey/journeyDb.spec.js index 78955c794..c740e40d0 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyDb.spec.js +++ b/packages/mermaid/src/diagrams/user-journey/journeyDb.spec.js @@ -1,5 +1,5 @@ -import journeyDb from './journeyDb'; -import { convert } from '../../tests/util'; +import journeyDb from './journeyDb.js'; +import { convert } from '../../tests/util.js'; describe('when using the journeyDb', function () { beforeEach(function () { diff --git a/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts b/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts index 535e7be9d..cb1d1837f 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyDetector.ts @@ -1,5 +1,24 @@ -import type { DiagramDetector } from '../../diagram-api/types'; +import type { + DiagramDetector, + DiagramLoader, + ExternalDiagramDefinition, +} from '../../diagram-api/types.js'; -export const journeyDetector: DiagramDetector = (txt) => { - return txt.match(/^\s*journey/) !== null; +const id = 'journey'; + +const detector: DiagramDetector = (txt) => { + return /^\s*journey/.test(txt); }; + +const loader: DiagramLoader = async () => { + const { diagram } = await import('./journeyDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/user-journey/journeyDiagram.ts b/packages/mermaid/src/diagrams/user-journey/journeyDiagram.ts new file mode 100644 index 000000000..c2b6cd717 --- /dev/null +++ b/packages/mermaid/src/diagrams/user-journey/journeyDiagram.ts @@ -0,0 +1,17 @@ +import type { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: JISON doesn't support types +import parser from './parser/journey.jison'; +import db from './journeyDb.js'; +import styles from './styles.js'; +import renderer from './journeyRenderer.js'; + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, + styles, + init: (cnf) => { + renderer.setConf(cnf.journey); + db.clear(); + }, +}; diff --git a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts index df46fc9c6..28c83f19d 100644 --- a/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts +++ b/packages/mermaid/src/diagrams/user-journey/journeyRenderer.ts @@ -1,8 +1,8 @@ // @ts-nocheck TODO: fix file import { select } from 'd3'; -import svgDraw from './svgDraw'; -import { getConfig } from '../../config'; -import { configureSvgSize } from '../../setupGraphViewbox'; +import svgDraw from './svgDraw.js'; +import { getConfig } from '../../config.js'; +import { configureSvgSize } from '../../setupGraphViewbox.js'; export const setConf = function (cnf) { const keys = Object.keys(cnf); @@ -49,8 +49,6 @@ const conf = getConfig().journey; const LEFT_MARGIN = conf.leftMargin; export const draw = function (text, id, version, diagObj) { const conf = getConfig().journey; - diagObj.db.clear(); - diagObj.parser.parse(text + '\n'); const securityLevel = getConfig().securityLevel; // Handle root and Document for when rendering in sandbox mode @@ -224,6 +222,17 @@ export const drawTasks = function (diagram, tasks, verticalPos) { num = sectionNumber % fills.length; colour = textColours[sectionNumber % textColours.length]; + // count how many consecutive tasks have the same section + let taskInSectionCount = 0; + const currentSection = task.section; + for (let taskIndex = i; taskIndex < tasks.length; taskIndex++) { + if (tasks[taskIndex].section == currentSection) { + taskInSectionCount = taskInSectionCount + 1; + } else { + break; + } + } + const section = { x: i * conf.taskMargin + i * conf.width + LEFT_MARGIN, y: 50, @@ -231,6 +240,7 @@ export const drawTasks = function (diagram, tasks, verticalPos) { fill, num, colour, + taskCount: taskInSectionCount, }; svgDraw.drawSection(diagram, section, conf); diff --git a/packages/mermaid/src/diagrams/user-journey/parser/journey.spec.js b/packages/mermaid/src/diagrams/user-journey/parser/journey.spec.js index cc54d9f78..8ed342bb5 100644 --- a/packages/mermaid/src/diagrams/user-journey/parser/journey.spec.js +++ b/packages/mermaid/src/diagrams/user-journey/parser/journey.spec.js @@ -1,5 +1,5 @@ -import { parser } from './journey'; -import journeyDb from '../journeyDb'; +import { parser } from './journey.jison'; +import journeyDb from '../journeyDb.js'; const parserFnConstructor = (str) => { return () => { diff --git a/packages/mermaid/src/diagrams/user-journey/svgDraw.js b/packages/mermaid/src/diagrams/user-journey/svgDraw.js index 74d5d2a02..7a8f791fa 100644 --- a/packages/mermaid/src/diagrams/user-journey/svgDraw.js +++ b/packages/mermaid/src/diagrams/user-journey/svgDraw.js @@ -1,21 +1,8 @@ import { arc as d3arc } from 'd3'; +import * as svgDrawCommon from '../common/svgDrawCommon.js'; export const drawRect = function (elem, rectData) { - const rectElem = elem.append('rect'); - rectElem.attr('x', rectData.x); - rectElem.attr('y', rectData.y); - rectElem.attr('fill', rectData.fill); - rectElem.attr('stroke', rectData.stroke); - rectElem.attr('width', rectData.width); - rectElem.attr('height', rectData.height); - rectElem.attr('rx', rectData.rx); - rectElem.attr('ry', rectData.ry); - - if (rectData.class !== undefined) { - rectElem.attr('class', rectData.class); - } - - return rectElem; + return svgDrawCommon.drawRect(elem, rectData); }; export const drawFace = function (element, faceData) { @@ -128,25 +115,7 @@ export const drawCircle = function (element, circleData) { }; export const drawText = function (elem, textData) { - // Remove and ignore br:s - const nText = textData.text.replace(/<br\s*\/?>/gi, ' '); - - const textElem = elem.append('text'); - textElem.attr('x', textData.x); - textElem.attr('y', textData.y); - textElem.attr('class', 'legend'); - - textElem.style('text-anchor', textData.anchor); - - if (textData.class !== undefined) { - textElem.attr('class', textData.class); - } - - const span = textElem.append('tspan'); - span.attr('x', textData.x + textData.textMargin * 2); - span.text(nText); - - return textElem; + return svgDrawCommon.drawText(elem, textData); }; export const drawLabel = function (elem, txtObject) { @@ -192,11 +161,14 @@ export const drawLabel = function (elem, txtObject) { export const drawSection = function (elem, section, conf) { const g = elem.append('g'); - const rect = getNoteRect(); + const rect = svgDrawCommon.getNoteRect(); rect.x = section.x; rect.y = section.y; rect.fill = section.fill; - rect.width = conf.width; + // section width covers all nested tasks + rect.width = + conf.width * section.taskCount + // width of the tasks + conf.diagramMarginX * (section.taskCount - 1); // width of space between tasks rect.height = conf.height; rect.class = 'journey-section section-type-' + section.num; rect.rx = 3; @@ -246,7 +218,7 @@ export const drawTask = function (elem, task, conf) { score: task.score, }); - const rect = getNoteRect(); + const rect = svgDrawCommon.getNoteRect(); rect.x = task.x; rect.y = task.y; rect.fill = task.fill; @@ -295,41 +267,7 @@ export const drawTask = function (elem, task, conf) { * @param {any} bounds The bounds of the drawing */ export const drawBackgroundRect = function (elem, bounds) { - const rectElem = drawRect(elem, { - x: bounds.startx, - y: bounds.starty, - width: bounds.stopx - bounds.startx, - height: bounds.stopy - bounds.starty, - fill: bounds.fill, - class: 'rect', - }); - rectElem.lower(); -}; - -export const getTextObj = function () { - return { - x: 0, - y: 0, - fill: undefined, - 'text-anchor': 'start', - width: 100, - height: 100, - textMargin: 0, - rx: 0, - ry: 0, - }; -}; - -export const getNoteRect = function () { - return { - x: 0, - y: 0, - width: 100, - anchor: 'start', - height: 100, - rx: 0, - ry: 0, - }; + svgDrawCommon.drawBackgroundRect(elem, bounds); }; const _drawTextCandidateFunc = (function () { @@ -472,7 +410,5 @@ export default { drawLabel, drawTask, drawBackgroundRect, - getTextObj, - getNoteRect, initGraphics, }; diff --git a/packages/mermaid/src/directiveUtils.ts b/packages/mermaid/src/directiveUtils.ts index 2d2971a85..baf628e74 100644 --- a/packages/mermaid/src/directiveUtils.ts +++ b/packages/mermaid/src/directiveUtils.ts @@ -1,7 +1,5 @@ -import * as configApi from './config'; - -import { log } from './logger'; -import { directiveSanitizer } from './utils'; +import * as configApi from './config.js'; +import { log } from './logger.js'; let currentDirective: { type?: string; args?: any } | undefined = {}; @@ -60,9 +58,6 @@ const handleDirective = function (p: any, directive: any, type: string): void { delete directive.args[prop]; } }); - log.info('sanitize in handleDirective', directive.args); - directiveSanitizer(directive.args); - log.info('sanitize in handleDirective (done)', directive.args); configApi.addDirective(directive.args); break; } diff --git a/packages/mermaid/src/docs/.vitepress/components/Contributors.vue b/packages/mermaid/src/docs/.vitepress/components/Contributors.vue new file mode 100644 index 000000000..94e918027 --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/components/Contributors.vue @@ -0,0 +1,27 @@ +<script setup lang="ts"> +import { contributors } from '../contributors'; +</script> + +<template> + <div flex="~ wrap gap2" justify-center> + <a + v-for="{ username, avatar } of contributors" + :key="username" + :href="`https://github.com/${username}`" + m-0 + rel="noopener noreferrer" + :aria-label="`${username} on GitHub`" + > + <img + loading="lazy" + :src="avatar" + width="50" + height="50" + rounded-full + h-12 + w-12 + :alt="`${username}'s avatar`" + /> + </a> + </div> +</template> diff --git a/packages/mermaid/src/docs/.vitepress/components/HomePage.vue b/packages/mermaid/src/docs/.vitepress/components/HomePage.vue new file mode 100644 index 000000000..b6998f249 --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/components/HomePage.vue @@ -0,0 +1,30 @@ +<script setup lang="ts"> +import { VPTeamMembers } from 'vitepress/theme'; +import { teamMembers } from '../contributors'; +</script> + +<template> + <div class="content"> + <div class="content-container"> + <main class="main"> + <div class="vp-doc" flex flex-col items-center mt-10> + <h2 id="meet-the-team" op50 font-normal p="t-10 b-2">Meet The Team</h2> + <div w-full p-10> + <VPTeamMembers size="small" :members="teamMembers" /> + </div> + <h2 id="the-team" op50 font-normal pt-5 pb-2>Contributors</h2> + <p text-lg max-w-200 text-center leading-7> + <Contributors /> + <br /> + <a + href="https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE" + rel="noopener noreferrer" + >Join the community</a + > + and get involved! + </p> + </div> + </main> + </div> + </div> +</template> diff --git a/packages/mermaid/src/docs/.vitepress/config.ts b/packages/mermaid/src/docs/.vitepress/config.ts index 9b01fdbde..ede064fa4 100644 --- a/packages/mermaid/src/docs/.vitepress/config.ts +++ b/packages/mermaid/src/docs/.vitepress/config.ts @@ -1,5 +1,5 @@ import { version } from '../../../package.json'; -import MermaidExample from './mermaid-markdown-all'; +import MermaidExample from './mermaid-markdown-all.js'; import { defineConfig, MarkdownOptions } from 'vitepress'; const allMarkdownTransformers: MarkdownOptions = { @@ -16,11 +16,31 @@ export default defineConfig({ description: 'Create diagrams and visualizations using text and code.', base: '/', markdown: allMarkdownTransformers, - head: [['link', { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]], + ignoreDeadLinks: [ + // ignore all localhost links + /^https?:\/\/localhost/, + ], + head: [ + ['link', { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }], + [ + 'script', + { + defer: 'true', + 'data-domain': 'mermaid.js.org', + // All tracked stats are public and available at https://p.mermaid.live/mermaid.js.org + src: 'https://p.mermaid.live/js/script.js', + }, + ], + ], themeConfig: { nav: nav(), editLink: { - pattern: 'https://github.com/mermaid-js/mermaid/edit/develop/packages/mermaid/src/docs/:path', + pattern: ({ filePath, frontmatter }) => { + if (typeof frontmatter.editLink === 'string') { + return frontmatter.editLink; + } + return `https://github.com/mermaid-js/mermaid/edit/develop/packages/mermaid/src/docs/${filePath}`; + }, text: 'Edit this page on GitHub', }, sidebar: { @@ -28,11 +48,21 @@ export default defineConfig({ }, socialLinks: [ { icon: 'github', link: 'https://github.com/mermaid-js/mermaid' }, - { icon: 'slack', link: 'https://mermaid-talk.slack.com' }, + { + icon: 'slack', + link: 'https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE', + }, + { + icon: { + svg: '<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 490.16 490.16"><defs><mask id="Mask"><rect x="0" y="0" width="490.16" height="490.16" fill="white" /><path fill="black" d="M407.48,111.18A165.2,165.2,0,0,0,245.08,220,165.2,165.2,0,0,0,82.68,111.18a165.5,165.5,0,0,0,72.06,143.64,88.81,88.81,0,0,1,38.53,73.45v50.86H296.9V328.27a88.8,88.8,0,0,1,38.52-73.45,165.41,165.41,0,0,0,72.06-143.64Z"/><path fill="black" d="M160.63,328.27a56.09,56.09,0,0,0-24.27-46.49,198.74,198.74,0,0,1-28.54-23.66A196.87,196.87,0,0,1,82.53,227V379.13h78.1Z"/><path fill="black" d="M329.53,328.27a56.09,56.09,0,0,1,24.27-46.49,198.74,198.74,0,0,0,28.54-23.66A196.87,196.87,0,0,0,407.63,227V379.13h-78.1Z"/></mask><style>.cls-1{fill:#76767B;}.cls-1:hover{fill:#FF3570}</style></defs><rect class="cls-1" width="490.16" height="490.16" rx="84.61" mask="url(#Mask)" /></svg>', + }, + link: 'https://www.mermaidchart.com/', + }, ], }, }); +// Top (across the page) menu function nav() { return [ { text: 'Docs', link: '/intro/', activeMatch: '/intro/' }, @@ -42,6 +72,16 @@ function nav() { activeMatch: '/config/', }, { text: 'Integrations', link: '/ecosystem/integrations', activeMatch: '/ecosystem/' }, + { + text: 'Contributing', + link: '/community/development.html', + activeMatch: '/community/', + }, + { + text: 'Latest News', + link: '/news/announcements', + activeMatch: '/announcements', + }, { text: version, items: [ @@ -51,7 +91,7 @@ function nav() { }, { text: 'Contributing', - link: 'https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md', + link: '/community/development', }, ], }, @@ -66,20 +106,18 @@ function sidebarAll() { return [ { text: '📔 Introduction', - collapsible: true, + collapsed: false, items: [ { text: 'About Mermaid', link: '/intro/' }, - { text: 'Deployment', link: '/intro/n00b-gettingStarted' }, - { - text: 'Syntax and Configuration', - link: '/intro/n00b-syntaxReference', - }, + { text: 'Getting Started', link: '/intro/getting-started' }, + { text: 'Syntax and Configuration', link: '/intro/syntax-reference' }, ], }, ...sidebarSyntax(), ...sidebarEcosystem(), ...sidebarConfig(), ...sidebarCommunity(), + ...sidebarNews(), ]; } @@ -87,7 +125,7 @@ function sidebarSyntax() { return [ { text: '📊 Diagram Syntax', - collapsible: true, + collapsed: false, items: [ { text: 'Flowchart', link: '/syntax/flowchart' }, { text: 'Sequence Diagram', link: '/syntax/sequenceDiagram' }, @@ -100,11 +138,14 @@ function sidebarSyntax() { { text: 'User Journey', link: '/syntax/userJourney' }, { text: 'Gantt', link: '/syntax/gantt' }, { 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: 'C4C Diagram (Context) Diagram 🦺⚠️', link: '/syntax/c4c' }, + { text: 'C4 Diagram 🦺⚠️', link: '/syntax/c4' }, { text: 'Mindmaps 🔥', link: '/syntax/mindmap' }, { text: 'Timeline 🔥', link: '/syntax/timeline' }, + { text: 'Zenuml 🔥', link: '/syntax/zenuml' }, + { text: 'Sankey 🔥', link: '/syntax/sankey' }, { text: 'Other Examples', link: '/syntax/examples' }, ], }, @@ -115,17 +156,18 @@ function sidebarConfig() { return [ { text: '⚙️ Deployment and Configuration', - collapsible: true, + collapsed: false, items: [ { text: 'Configuration', link: '/config/configuration' }, { text: 'Tutorials', link: '/config/Tutorials' }, { text: 'API-Usage', link: '/config/usage' }, { text: 'Mermaid API Configuration', link: '/config/setup/README' }, + { text: 'Mermaid Configuration Options', link: '/config/schema-docs/config' }, { text: 'Directives', link: '/config/directives' }, { text: 'Theming', link: '/config/theming' }, { text: 'Accessibility', link: '/config/accessibility' }, { text: 'Mermaid CLI', link: '/config/mermaidCLI' }, - { text: 'Advanced usage', link: '/config/n00b-advanced' }, + { text: 'Advanced usage', link: '/config/advanced' }, { text: 'FAQ', link: '/config/faq' }, ], }, @@ -136,7 +178,7 @@ function sidebarEcosystem() { return [ { text: '📚 Ecosystem', - collapsible: true, + collapsed: false, items: [ { text: 'Showcases', link: '/ecosystem/showcases' }, { text: 'Use-Cases and Integrations', link: '/ecosystem/integrations' }, @@ -149,16 +191,38 @@ function sidebarCommunity() { return [ { text: '🙌 Contributions and Community', - collapsible: true, + collapsed: false, items: [ - { text: 'Overview for Beginners', link: '/community/n00b-overview' }, - { - text: 'Development and Contribution', - link: '/community/development', - }, + { text: 'Contributing to Mermaid', link: '/community/development' }, + { text: 'Contributing Code', link: '/community/code' }, + { text: 'Contributing Documentation', link: '/community/documentation' }, + { text: 'Questions and Suggestions', link: '/community/questions-and-suggestions' }, { text: 'Adding Diagrams', link: '/community/newDiagram' }, { text: 'Security', link: '/community/security' }, ], }, ]; } + +function sidebarNews() { + return [ + { + text: '📰 Latest News', + collapsed: false, + items: [ + { text: 'Announcements', link: '/news/announcements' }, + { text: 'Blog', link: '/news/blog' }, + ], + }, + ]; +} + +/** + * 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 { + return pagePath + '#' + id; +} diff --git a/packages/mermaid/src/docs/.vitepress/contributors.ts b/packages/mermaid/src/docs/.vitepress/contributors.ts new file mode 100644 index 000000000..93eeee2e2 --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/contributors.ts @@ -0,0 +1,39 @@ +import contributorUsernamesJson from './contributor-names.json'; +import { CoreTeam, knut, plainTeamMembers } from './teamMembers.js'; + +const contributorUsernames: string[] = contributorUsernamesJson; + +export const contributors = contributorUsernames.map((username) => { + return { username, avatar: `/user-avatars/${username}.png` }; +}); + +const websiteSVG = { + svg: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-globe"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>', +}; + +const createLinks = (tm: CoreTeam): CoreTeam => { + tm.avatar = `/user-avatars/${tm.github}.png`; + tm.title = tm.title ?? 'Developer'; + tm.links = [{ icon: 'github', link: `https://github.com/${tm.github}` }]; + if (tm.mastodon) { + tm.links.push({ icon: 'mastodon', link: tm.mastodon }); + } + if (tm.twitter) { + tm.links.push({ icon: 'twitter', link: `https://twitter.com/${tm.twitter}` }); + } + if (tm.website) { + tm.links.push({ icon: websiteSVG, link: tm.website }); + } + if (tm.linkedIn) { + tm.links.push({ icon: 'linkedin', link: `https://www.linkedin.com/in/${tm.linkedIn}` }); + } + return tm; +}; + +const teamMembers = plainTeamMembers.map((tm) => createLinks(tm)); +teamMembers.sort( + (a, b) => contributorUsernames.indexOf(a.github) - contributorUsernames.indexOf(b.github) +); +teamMembers.unshift(createLinks(knut)); + +export { teamMembers }; diff --git a/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts b/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts index 14340462c..30f044d98 100644 --- a/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts +++ b/packages/mermaid/src/docs/.vitepress/mermaid-markdown-all.ts @@ -54,6 +54,15 @@ const MermaidExample = async (md: MarkdownRenderer) => { return `<div class="tip custom-block"><p class="custom-block-title">NOTE</p><p>${token.content}}</p></div>`; } + if (token.info.trim() === 'regexp') { + // shiki doesn't yet support regexp code blocks, but the javascript + // one still makes RegExes look good + token.info = 'javascript'; + // use trimEnd to move trailing `\n` outside if the JavaScript regex `/` block + token.content = `/${token.content.trimEnd()}/\n`; + return defaultRenderer(tokens, index, options, env, slf); + } + if (token.info.trim() === 'jison') { return `<div class="language-"> <button class="copy"></button> diff --git a/packages/mermaid/src/docs/.vitepress/scripts/fetch-avatars.ts b/packages/mermaid/src/docs/.vitepress/scripts/fetch-avatars.ts new file mode 100644 index 000000000..cd78be782 --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/scripts/fetch-avatars.ts @@ -0,0 +1,42 @@ +/* eslint-disable no-console */ +import { mkdir, writeFile, readFile } from 'node:fs/promises'; +import { existsSync } from 'node:fs'; +import { fileURLToPath } from 'url'; + +const pathContributors = new URL('../contributor-names.json', import.meta.url); +const getAvatarPath = (name: string) => + new URL(`../../public/user-avatars/${name}.png`, import.meta.url); + +let contributors: string[] = []; + +async function download(url: string, fileName: URL) { + if (existsSync(fileName)) { + return; + } + console.log('downloading', url); + try { + const image = await fetch(url); + await writeFile(fileName, Buffer.from(await image.arrayBuffer())); + } catch (error) { + console.error('failed to load', url, error); + // Exit the build process if we are in CI + if (process.env.CI) { + throw error; + } + } +} + +async function fetchAvatars() { + await mkdir(fileURLToPath(new URL(getAvatarPath('none'))).replace('none.png', ''), { + recursive: true, + }); + + contributors = JSON.parse(await readFile(pathContributors, { encoding: 'utf-8' })); + let avatars = contributors.map((name) => { + download(`https://github.com/${name}.png?size=100`, getAvatarPath(name)); + }); + + await Promise.allSettled(avatars); +} + +fetchAvatars(); diff --git a/packages/mermaid/src/docs/.vitepress/scripts/fetch-contributors.ts b/packages/mermaid/src/docs/.vitepress/scripts/fetch-contributors.ts new file mode 100644 index 000000000..da7621b29 --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/scripts/fetch-contributors.ts @@ -0,0 +1,52 @@ +// Adapted from https://github.dev/vitest-dev/vitest/blob/991ff33ab717caee85ef6cbe1c16dc514186b4cc/scripts/update-contributors.ts#L6 + +import { writeFile } from 'node:fs/promises'; +import { knut, plainTeamMembers } from '../teamMembers.js'; +import { existsSync } from 'node:fs'; + +const pathContributors = new URL('../contributor-names.json', import.meta.url); + +interface Contributor { + login: string; +} + +async function fetchContributors() { + const collaborators: string[] = []; + try { + let page = 1; + let data: Contributor[] = []; + do { + const response = await fetch( + `https://api.github.com/repos/mermaid-js/mermaid/contributors?per_page=100&page=${page}`, + { + method: 'GET', + headers: { + 'content-type': 'application/json', + }, + } + ); + data = await response.json(); + collaborators.push(...data.map((i) => i.login)); + console.log(`Fetched page ${page}`); + page++; + } while (data.length === 100); + } catch (e) { + /* contributors fetching failure must not hinder docs development */ + } + return collaborators.filter((name) => !name.includes('[bot]')); +} + +async function generate() { + if (existsSync(pathContributors)) { + // Only fetch contributors once, when running locally. + // In CI, the file won't exist, so it'll fetch every time as expected. + return; + } + // Will fetch all contributors only in CI to speed up local development. + const collaborators = process.env.CI + ? await fetchContributors() + : [knut, ...plainTeamMembers].map((m) => m.github); + await writeFile(pathContributors, JSON.stringify(collaborators, null, 2) + '\n', 'utf8'); +} + +void generate(); diff --git a/packages/mermaid/src/docs/.vitepress/style/main.css b/packages/mermaid/src/docs/.vitepress/style/main.css new file mode 100644 index 000000000..a6a31f3da --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/style/main.css @@ -0,0 +1,77 @@ +.dark [img-light] { + display: none; +} + +html:not(.dark) [img-dark] { + display: none; +} + +/* Overrides */ + +.VPSocialLink { + transform: scale(0.9); +} + +.vp-doc th, +.vp-doc td { + padding: 6px 10px; + border: 1px solid #8882; +} + +/* h3 breaks SEO => replaced with h2 with the same size */ +.home-content h2 { + margin-top: 2rem; + font-size: 1.35rem; + border-bottom: none; + margin-bottom: 0; +} + +img.resizable-img { + width: unset; + height: unset; +} + +/* fix height ~ 2 lines of text: 3 or more cards per row */ +.VPTeamMembersItem.small .profile .data .affiliation { + min-height: 3rem; +} +.VPTeamMembersItem.small .profile .data .desc { + min-height: 3rem; +} + +/* fix height ~ 3 lines of text: 4 cards per row */ +@media (min-width: 1064px) and (max-width: 1143px) { + .VPTeamMembersItem.small .profile .data .affiliation { + min-height: 4rem; + } + .VPTeamMembersItem.small .profile .data .desc { + min-height: 4rem; + } +} +/* fix height ~ 3 lines of text: 3 cards per row */ +@media (min-width: 815px) and (max-width: 875px) { + .VPTeamMembersItem.small .profile .data .affiliation { + min-height: 4rem; + } + .VPTeamMembersItem.small .profile .data .desc { + min-height: 4rem; + } +} +/* fix height ~ 3 lines of text: 2 cards per row */ +@media (max-width: 612px) { + .VPTeamMembersItem.small .profile .data .affiliation { + min-height: 4rem; + } + .VPTeamMembersItem.small .profile .data .desc { + min-height: 4rem; + } +} +/* fix height: one card per row */ +@media (max-width: 568px) { + .VPTeamMembersItem.small .profile .data .affiliation { + min-height: unset; + } + .VPTeamMembersItem.small .profile .data .desc { + min-height: unset; + } +} diff --git a/packages/mermaid/src/docs/.vitepress/teamMembers.ts b/packages/mermaid/src/docs/.vitepress/teamMembers.ts new file mode 100644 index 000000000..d95f49ed8 --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/teamMembers.ts @@ -0,0 +1,105 @@ +export interface Contributor { + name: string; + avatar: string; +} + +export interface SocialEntry { + icon: string | { svg: string }; + link: string; +} + +export interface CoreTeam { + name: string; + // required to download avatars from GitHub + github: string; + avatar?: string; + twitter?: string; + mastodon?: string; + sponsor?: string; + website?: string; + linkedIn?: string; + title?: string; + org?: string; + desc?: string; + links?: SocialEntry[]; +} + +export const knut: CoreTeam = { + github: 'knsv', + name: 'Knut Sveidqvist', + title: 'Creator', + twitter: 'knutsveidqvist', + sponsor: 'https://github.com/sponsors/knsv', +}; + +export const plainTeamMembers: CoreTeam[] = [ + { + github: 'NeilCuzon', + name: 'Neil Cuzon', + }, + { + github: 'tylerlong', + name: 'Tyler Liu', + }, + { + github: 'sidharthv96', + name: 'Sidharth Vinod', + twitter: 'sidv42', + mastodon: 'https://techhub.social/@sidv', + sponsor: 'https://github.com/sponsors/sidharthv96', + linkedIn: 'sidharth-vinod', + website: 'https://sidharth.dev', + }, + { + github: 'ashishjain0512', + name: 'Ashish Jain', + }, + { + github: 'mmorel-35', + name: 'Matthieu Morel', + linkedIn: 'matthieumorel35', + }, + { + github: 'aloisklink', + name: 'Alois Klink', + linkedIn: 'aloisklink', + website: 'https://aloisklink.com', + }, + { + github: 'pbrolin47', + name: 'Per Brolin', + }, + { + github: 'Yash-Singh1', + name: 'Yash Singh', + }, + { + github: 'GDFaber', + name: 'Marc Faber', + linkedIn: 'marc-faber', + }, + { + github: 'MindaugasLaganeckas', + name: 'Mindaugas Laganeckas', + }, + { + github: 'jgreywolf', + name: 'Justin Greywolf', + }, + { + github: 'IOrlandoni', + name: 'Nacho Orlandoni', + }, + { + github: 'huynhicode', + name: 'Steph Huynh', + }, + { + github: 'Yokozuna59', + name: 'Reda Al Sulais', + }, + { + github: 'nirname', + name: 'Nikolay Rozhkov', + }, +]; diff --git a/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue b/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue index 85c13393c..5012d3067 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue +++ b/packages/mermaid/src/docs/.vitepress/theme/Mermaid.vue @@ -17,7 +17,7 @@ const props = defineProps({ }, }); -const svg = ref(null); +const svg = ref(''); let mut = null; onMounted(async () => { diff --git a/packages/mermaid/src/docs/.vitepress/theme/index.ts b/packages/mermaid/src/docs/.vitepress/theme/index.ts index 273880d91..ba1ac9bdb 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/index.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/index.ts @@ -2,13 +2,29 @@ import DefaultTheme from 'vitepress/theme'; import './custom.css'; // @ts-ignore import Mermaid from './Mermaid.vue'; -import { getRedirect } from './redirect'; +// @ts-ignore +import Contributors from '../components/Contributors.vue'; +// @ts-ignore +import HomePage from '../components/HomePage.vue'; +import { getRedirect } from './redirect.js'; + +import { h } from 'vue'; + +import Theme from 'vitepress/theme'; +import '../style/main.css'; +import 'uno.css'; export default { ...DefaultTheme, + Layout() { + return h(Theme.Layout, null, { + 'home-features-after': () => h(HomePage), + }); + }, enhanceApp({ app, router }) { // register global components app.component('Mermaid', Mermaid); + app.component('Contributors', Contributors); router.onBeforeRouteChange = (to) => { try { const newPath = getRedirect(to); @@ -20,4 +36,4 @@ export default { } catch (e) {} }; }, -} as typeof DefaultTheme; +}; diff --git a/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts b/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts index c5b57f886..47e238692 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/mermaid.ts @@ -1,7 +1,11 @@ import mermaid, { type MermaidConfig } from 'mermaid'; +import zenuml from '../../../../../mermaid-zenuml/dist/mermaid-zenuml.core.mjs'; + +const init = mermaid.registerExternalDiagrams([zenuml]); export const render = async (id: string, code: string, config: MermaidConfig): Promise<string> => { + await init; mermaid.initialize(config); - const svg = await mermaid.render(id, code); + const { svg } = await mermaid.render(id, code); return svg; }; diff --git a/packages/mermaid/src/docs/.vitepress/theme/redirect.spec.ts b/packages/mermaid/src/docs/.vitepress/theme/redirect.spec.ts index ec0404264..09c14d935 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/redirect.spec.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/redirect.spec.ts @@ -2,7 +2,7 @@ // Update https://github.com/mermaid-js/mermaid/blob/18c27c6f1d0537a738cbd95898df301b83c38ffc/packages/mermaid/src/docs.mts#L246 once fixed import { expect, test } from 'vitest'; -import { getRedirect } from './redirect'; +import { getRedirect } from './redirect.js'; test.each([ // Old docs, localhost @@ -19,8 +19,17 @@ test.each([ 'https://mermaid-js.github.io/mermaid/#/flowchart?another=test&id=my-id&one=more', // with multiple params 'syntax/flowchart.html#my-id', ], - ['https://mermaid-js.github.io/mermaid/#/n00b-advanced', 'config/n00b-advanced.html'], // without .md - ['https://mermaid-js.github.io/mermaid/#/n00b-advanced.md', 'config/n00b-advanced.html'], // with .md + ['https://mermaid-js.github.io/mermaid/#/n00b-advanced', 'config/advanced.html'], // without .md + ['https://mermaid-js.github.io/mermaid/#/n00b-advanced.md', 'config/advanced.html'], // with .md + + ['https://mermaid-js.github.io/mermaid/#/n00b-gettingstarted', 'intro/getting-started.html'], + ['https://mermaid-js.github.io/mermaid/#/n00b-gettingstarted.md', 'intro/getting-started.html'], + ['https://mermaid-js.github.io/mermaid/#/n00b-overview', 'intro/getting-started.html'], + ['https://mermaid-js.github.io/mermaid/#/n00b-overview.md', 'intro/getting-started.html'], + ['https://mermaid-js.github.io/mermaid/#/n00b-syntaxreference', 'intro/syntax-reference.html'], + ['https://mermaid-js.github.io/mermaid/#/n00b-syntaxreference.md', 'intro/syntax-reference.html'], + ['https://mermaid-js.github.io/mermaid/#/quickstart', 'intro/getting-started.html'], + ['https://mermaid-js.github.io/mermaid/#/quickstart.md', 'intro/getting-started.html'], [ 'https://mermaid-js.github.io/mermaid/#/flowchart?id=a-node-in-the-form-of-a-circle', // with id, without .md 'syntax/flowchart.html#a-node-in-the-form-of-a-circle', diff --git a/packages/mermaid/src/docs/.vitepress/theme/redirect.ts b/packages/mermaid/src/docs/.vitepress/theme/redirect.ts index 936d6f7e2..ca8e5bda1 100644 --- a/packages/mermaid/src/docs/.vitepress/theme/redirect.ts +++ b/packages/mermaid/src/docs/.vitepress/theme/redirect.ts @@ -24,11 +24,18 @@ const getBaseFile = (url: URL): Redirect => { return { path, id }; }; +/** + * Used to redirect old (pre-vitepress) documentation pages to corresponding new pages. + * The key is the old documentation ID, and the value is the new documentation path. + * No key should be added here as it already has all the old documentation IDs. + * If you are changing a documentation page, you should update the corresponding value here, and add an entry in the urlRedirectMap below. + */ const idRedirectMap: Record<string, string> = { + // ID of the old documentation page: Path of the new documentation page '8.6.0_docs': '', accessibility: 'config/theming', breakingchanges: '', - c4c: 'syntax/c4c', + c4c: 'syntax/c4', classdiagram: 'syntax/classDiagram', configuration: 'config/configuration', demos: 'ecosystem/integrations', @@ -47,14 +54,14 @@ const idRedirectMap: Record<string, string> = { mermaidcli: 'config/mermaidCLI', mindmap: 'syntax/mindmap', 'more-pages': '', - 'n00b-advanced': 'config/n00b-advanced', - 'n00b-gettingstarted': 'intro/n00b-gettingStarted', - 'n00b-overview': 'community/n00b-overview', - 'n00b-syntaxreference': '', + 'n00b-advanced': 'config/advanced', + 'n00b-gettingstarted': 'intro/getting-started', + 'n00b-overview': 'intro/getting-started', + 'n00b-syntaxreference': 'intro/syntax-reference', newdiagram: 'community/newDiagram', pie: 'syntax/pie', plugins: '', - quickstart: 'intro/n00b-gettingStarted', + quickstart: 'intro/getting-started', requirementdiagram: 'syntax/requirementDiagram', security: 'community/security', sequencediagram: 'syntax/sequenceDiagram', @@ -68,8 +75,21 @@ const idRedirectMap: Record<string, string> = { 'user-journey': 'syntax/userJourney', }; +/** + * Used to redirect pages that have been moved in the vitepress site. + * No keys should be deleted from here. + * If you are changing a documentation page, you should update the corresponding value here, + * and update the entry in the idRedirectMap above if it was present + * (No need to add new keys in idRedirectMap). + */ const urlRedirectMap: Record<string, string> = { + // Old URL: New URL '/misc/faq.html': 'configure/faq.html', + '/syntax/c4c.html': 'syntax/c4.html', + '/config/n00b-advanced.html': 'config/advanced', + '/intro/n00b-gettingStarted.html': 'intro/getting-started', + '/intro/n00b-syntaxReference.html': 'intro/syntax-reference', + '/community/n00b-overview.html': 'intro/getting-started', }; /** diff --git a/packages/mermaid/src/docs/CHANGELOG.md b/packages/mermaid/src/docs/CHANGELOG.md deleted file mode 100644 index cc725bf00..000000000 --- a/packages/mermaid/src/docs/CHANGELOG.md +++ /dev/null @@ -1,1024 +0,0 @@ -# Change Log - -All changes are in descending order, beginning with the newest (latest) version. - -## Unreleased - -[Full Changelog](https://github.com/knsv/mermaid/compare/8.7.0...HEAD) - -## 8.7.0 (2020-08-09) - -🔖 [Release Notes](https://github.com/mermaid-js/mermaid/releases/tag/8.7.0) | -📜 [Full Changelog](https://github.com/mermaid-js/mermaid/compare/8.6.0...8.7.0) - -This version brings with it a system for [dynamic and integrated configuration of the diagram themes](config/theming.md). -The objective of this is to increase the customizability of mermaid and the ease of Styling, with the customization of themes through the `%%init%%` directive and `initialize` calls. - -Themes follow and build upon the Levels of Configuration and employ `directives` to modify and create custom configurations, as they were introduced in Version [8.6.0](config/8.6.0_docs.md). - -**These Theming Configurations, similar to directives, will also be made applicable in the Live-Editor, for easier styling.** - -### Site-wide Themes - -Site-wide themes are still declared via `initialize` by site owners. - -Example of `Initalize` call setting `theme` to `base`: - -```javascript -mermaidAPI.initialize({ - securityLevel: 'loose', - theme: 'base', -}); -``` - -**Notes**: Only site owners can use the `mermaidAPI.initialize` call, to set values. Site-Users will have to use `%%init%%` to modify or create the theme for their diagrams. - -### Themes at the Local or Current Level - -When Generating a diagram using on a webpage that supports mermaid. -It is also possible to override site-wide theme settings locally, for a specific diagram, using directives, as long as it is not prohibited by the `secure` array. - -**Following is an example:** - -```mmd -%%{init: {'theme':'base'}}%% - graph TD - a --> b -``` - -### Making a Custom Theme with `themeVariables` - -The easiest way to make a custom theme is to start with the base theme, and just modify theme variables through `themeVariables`, via `%%init%%`. - -| Parameter | Description | Type | Required | Objects contained | -| -------------- | ------------------------------------------------------------------ | ----- | -------- | ---------------------------------- | -| themeVariables | Array containing objects, modifiable with the `%%init%%` directive | Array | Required | primaryColor, lineColor, textColor | - -Here is an example of overriding `primaryColor` and giving everything a different look, using `%%init%%`. - -```mmd -%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#ff0000'}}}%% - 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 -``` - -**Notes:** -Leaving it empty will set all variable values to default. - -## 8.6.0 (2020-07-13) - -🔖 [Release Notes](https://github.com/mermaid-js/mermaid/releases/tag/8.6.0) - -[Version 8.6.0](../getting-started/8.6.0_docs.md) introduces New Configuration Protocols and Directives and a Beta for the [New Mermaid Live-Editor](https://mermaid-js.github.io/docs/mermaid-live-editor-beta/#/edit/eyJjb2RlIjoiJSV7aW5pdDoge1widGhlbWVcIjogXCJmb3Jlc3RcIiwgXCJsb2dMZXZlbFwiOiAxIH19JSVcbmdyYXBoIFREXG4gIEFbQ2hyaXN0bWFzXSAtLT58R2V0IG1vbmV5fCBCKEdvIHNob3BwaW5nKVxuICBCIC0tPiBDe0xldCBtZSB0aGlua31cbiAgQyAtLT58T25lfCBEW0xhcHRvcF1cbiAgQyAtLT58VHdvfCBFW2lQaG9uZV1cbiAgQyAtLT58VGhyZWV8IEZbZmE6ZmEtY2FyIENhcl1cblx0XHQiLCJtZXJtYWlkIjp7InRoZW1lIjoiZGFyayJ9fQ) - -**With version 8.6.0 comes the release of directives for mermaid, a new system for modifying configurations, with the aim of establishing centralized, sane defaults and simple implementation.** - -Directives allow for a diagram specific overriding of config, as it has been discussed in Configurations. -This allows site users to input modifications to config alongside diagram definitions, when creating diagrams on a private webpage that supports Mermaid. - -## 8.5.0 (2020-04-11) - -🔖 [Release Notes](https://github.com/mermaid-js/mermaid/releases/tag/untagged-31c93788afe260d914bb) - -This version introduces New diagrams! - -**New diagrams in 8.5** - -With version 8.5 there are some bug fixes and enhancements, plus a new diagram type, entity relationship diagrams. - -![Image showing the new ER diagram type](./img/er.png) - -## 8.2.0 (2019-07-17) - -🏷️ [Tag](https://github.com/mermaid-js/mermaid/tree/8.2.0) - -Version 8.2.0, introduces a security improvement. - -A `securityLevel` configuration has to first be cleared, `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. -This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use. - -### securityLevel - -| Parameter | Description | Type | Required | Values | -| ------------- | --------------------------------- | ------ | -------- | ------------------------- | -| securitylevel | Level of trust for parsed diagram | String | Required | Strict, Loose, antiscript | - -**Notes:** - -- **strict**: (**default**) tags in text are encoded, click functionality is disabled -- **loose**: tags in text are allowed, click functionality is enabled -- **antiscript**: html tags in text are allowed, (only script element is removed), click functionality is enabled - -⚠️ **Note**: This changes the default behaviour of mermaid so that after upgrade to 8.2, if the `securityLevel` is not configured, tags in flowcharts are encoded as tags and clicking is prohibited. - -If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing. -By doing this clicks and tags are again allowed. - -### To change `securityLevel` with `mermaidAPI.initialize`: - -```javascript -mermaidAPI.initialize({ - securityLevel: 'loose', -}); -``` - -**Closed issues:** - -- please add tag for 8.0.0 release [\#863](https://github.com/knsv/mermaid/issues/863) -- classDiagram breaks on any edit [\#858](https://github.com/knsv/mermaid/issues/858) - -## [8.1.0](https://github.com/knsv/mermaid/tree/8.1.0) (2019-06-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.5...8.1.0) - -**Implemented enhancements:** - -- Theme for dark background [\#301](https://github.com/knsv/mermaid/issues/301) -- \[Feature request\] gantt diagram axis format [\#269](https://github.com/knsv/mermaid/issues/269) -- Implement render function for server side rendering using phantomjs [\#169](https://github.com/knsv/mermaid/issues/169) - -**Fixed bugs:** - -- mermaid -v filename.mmd gives You must specify at least one source file. [\#328](https://github.com/knsv/mermaid/issues/328) -- Not Able to See Labels even htmlLabels:false added [\#268](https://github.com/knsv/mermaid/issues/268) - -**Closed issues:** - -- Gantt and sequence diagram do not render [\#853](https://github.com/knsv/mermaid/issues/853) -- margins around flowchart are not balanced [\#852](https://github.com/knsv/mermaid/issues/852) -- Smaller bundles [\#843](https://github.com/knsv/mermaid/issues/843) -- unicode in labels [\#776](https://github.com/knsv/mermaid/issues/776) -- Hard-changing drawing of arrows per edge type [\#775](https://github.com/knsv/mermaid/issues/775) -- SequenceDiagram wrong [\#773](https://github.com/knsv/mermaid/issues/773) -- Render mermaid on github pages with simple code [\#772](https://github.com/knsv/mermaid/issues/772) -- FlowChart - large space between text and the image [\#754](https://github.com/knsv/mermaid/issues/754) -- Class Diagram Issues when using Mermaid in Stackedit [\#748](https://github.com/knsv/mermaid/issues/748) -- Multi-platform CI [\#744](https://github.com/knsv/mermaid/issues/744) -- gantt: sections can't have a colon [\#742](https://github.com/knsv/mermaid/issues/742) -- Yarn build does not add mermaid.min.css to dist [\#732](https://github.com/knsv/mermaid/issues/732) -- Is there a grammar / keyword / more than just the basic examples? [\#718](https://github.com/knsv/mermaid/issues/718) -- Click event and react component [\#717](https://github.com/knsv/mermaid/issues/717) -- Long text going outside the box [\#706](https://github.com/knsv/mermaid/issues/706) -- How to migrate from yUML to mermaid? [\#704](https://github.com/knsv/mermaid/issues/704) -- Issue on Dynamic Creation in PHP [\#690](https://github.com/knsv/mermaid/issues/690) -- `click "\#target"` and `click "http://url"` should create regular links [\#689](https://github.com/knsv/mermaid/issues/689) -- Support Chinese punctuation [\#687](https://github.com/knsv/mermaid/issues/687) -- \[Question\] Proper way to install on Mac? [\#681](https://github.com/knsv/mermaid/issues/681) -- Has Mermaid a graphical interface to make diagrams? [\#668](https://github.com/knsv/mermaid/issues/668) -- mermaid installation on debian [\#649](https://github.com/knsv/mermaid/issues/649) -- "Cannot activate" in sequenceDiagram [\#647](https://github.com/knsv/mermaid/issues/647) -- Link \("click" statement\) in flowchart does not work in exported SVG [\#646](https://github.com/knsv/mermaid/issues/646) -- How to pass styling [\#639](https://github.com/knsv/mermaid/issues/639) -- The live editor cant show seq diagram with notes for 8.0.0-alpha.3 [\#638](https://github.com/knsv/mermaid/issues/638) -- import mermaid.css with ES6 + NPM [\#634](https://github.com/knsv/mermaid/issues/634) -- Actor line cuts through other elements [\#633](https://github.com/knsv/mermaid/issues/633) -- Graph TD line out of the picture \(left side\) [\#630](https://github.com/knsv/mermaid/issues/630) -- Flowchart labels appear "cutoff" [\#628](https://github.com/knsv/mermaid/issues/628) -- Uncaught TypeError: \_.constant is not a function \(mermaid.js\) [\#626](https://github.com/knsv/mermaid/issues/626) -- Missing tags and releases for newer versions [\#623](https://github.com/knsv/mermaid/issues/623) -- Mermaid and Leo / Leo Vue [\#622](https://github.com/knsv/mermaid/issues/622) -- mermaidAPI gantt Vue.js [\#621](https://github.com/knsv/mermaid/issues/621) -- Gantt sections are not separated by colors - Fix: set numberSectionStyles to 4 instead of 3 [\#620](https://github.com/knsv/mermaid/issues/620) -- how to get mermaidAPI? [\#617](https://github.com/knsv/mermaid/issues/617) -- Error in startOnLoad documentation? [\#616](https://github.com/knsv/mermaid/issues/616) -- Example export to SVG generates error [\#614](https://github.com/knsv/mermaid/issues/614) -- The new online editor does not support previously generated links [\#613](https://github.com/knsv/mermaid/issues/613) -- Grammar / Syntax documentation for flowcharts [\#607](https://github.com/knsv/mermaid/issues/607) -- Mermaid does not work with d3.js [\#606](https://github.com/knsv/mermaid/issues/606) -- Why does this code's flowchart lines get cut-off on screen? [\#604](https://github.com/knsv/mermaid/issues/604) -- click keyword does not fire my callback \(on the demo Website too\) [\#603](https://github.com/knsv/mermaid/issues/603) -- Online Editor fails to show exported SVG [\#601](https://github.com/knsv/mermaid/issues/601) -- Just saying thanks! [\#597](https://github.com/knsv/mermaid/issues/597) -- stylesheet crashed with other library like abcjs [\#596](https://github.com/knsv/mermaid/issues/596) -- Missing connection [\#594](https://github.com/knsv/mermaid/issues/594) -- How to use mermaid on node.js restful api? [\#593](https://github.com/knsv/mermaid/issues/593) -- Remove status code [\#589](https://github.com/knsv/mermaid/issues/589) -- Golang based editor [\#588](https://github.com/knsv/mermaid/issues/588) -- sequenceDiagram -\> notetext css font is hardcoded [\#587](https://github.com/knsv/mermaid/issues/587) -- Multiple graph in the live editor [\#586](https://github.com/knsv/mermaid/issues/586) -- All \<svg\> elements in page are colored black [\#584](https://github.com/knsv/mermaid/issues/584) -- Styling: classes aren't applied to elements. [\#582](https://github.com/knsv/mermaid/issues/582) -- Rounded connections [\#580](https://github.com/knsv/mermaid/issues/580) -- Arrows are not being shown correctly in the dark theme [\#578](https://github.com/knsv/mermaid/issues/578) -- The documentation for CLI seems outdated. [\#572](https://github.com/knsv/mermaid/issues/572) -- No effect of click event:can not open link [\#571](https://github.com/knsv/mermaid/issues/571) -- Text colors are not correct in VSCODE [\#570](https://github.com/knsv/mermaid/issues/570) -- Nodes aren't aligned properly \(just need an explanation\) [\#568](https://github.com/knsv/mermaid/issues/568) -- setting margin around figure in R [\#567](https://github.com/knsv/mermaid/issues/567) -- Arrows should Come out in upward and Downward direction from decision Node [\#566](https://github.com/knsv/mermaid/issues/566) -- TypeError: Cannot read property 'select' of undefined [\#563](https://github.com/knsv/mermaid/issues/563) -- A little bug [\#557](https://github.com/knsv/mermaid/issues/557) -- Japanese text appears garbled [\#554](https://github.com/knsv/mermaid/issues/554) -- classdiagram not works in mermaid live_editor [\#553](https://github.com/knsv/mermaid/issues/553) -- font awesome in link text? [\#546](https://github.com/knsv/mermaid/issues/546) -- q: heard of the cosmogol standard? [\#545](https://github.com/knsv/mermaid/issues/545) -- Arrow heads missing \(cli, 7.0.3\) [\#544](https://github.com/knsv/mermaid/issues/544) -- No Edge Boxes if useHtmlLabels=false [\#541](https://github.com/knsv/mermaid/issues/541) -- how to change mermaid text color or line text block color? [\#534](https://github.com/knsv/mermaid/issues/534) -- FlowChart visualization broken when downloading from live editor [\#533](https://github.com/knsv/mermaid/issues/533) -- Can't get flowchart to render paths at the top of the diagram; I even tried the online editor and that shows the same issue. Thoughts? [\#532](https://github.com/knsv/mermaid/issues/532) -- live editor make browser\(safari on macOS&iOS\) not longer respond [\#531](https://github.com/knsv/mermaid/issues/531) -- css classes need a prefix/namespace [\#527](https://github.com/knsv/mermaid/issues/527) -- input activate/deactivate cause safari unresponding [\#521](https://github.com/knsv/mermaid/issues/521) -- Cannot Render the Mermaid Graph to PDF ? [\#520](https://github.com/knsv/mermaid/issues/520) -- clicking links works from inset in subgraph but not from nodes [\#516](https://github.com/knsv/mermaid/issues/516) -- Strange syntax error - when importing mermaid.js [\#515](https://github.com/knsv/mermaid/issues/515) -- gantt x-axis display [\#510](https://github.com/knsv/mermaid/issues/510) -- phantomjs renamed to phantomjs-prebuilt [\#508](https://github.com/knsv/mermaid/issues/508) -- issue when using sphinxcontrib-mermaid extension for sphinx [\#507](https://github.com/knsv/mermaid/issues/507) -- layout of docs page looks broken [\#504](https://github.com/knsv/mermaid/issues/504) -- Problem showing graph with php on localhost [\#502](https://github.com/knsv/mermaid/issues/502) -- logLevel's option doesn't 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) -- 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) -- Very different styles when rendering as png vs. svg [\#489](https://github.com/knsv/mermaid/issues/489) -- New editor that supports mermaid: Caret [\#488](https://github.com/knsv/mermaid/issues/488) -- Gant PNG margin [\#486](https://github.com/knsv/mermaid/issues/486) -- ReferenceError: window is not defined [\#485](https://github.com/knsv/mermaid/issues/485) -- Menu and layout bugs in docs [\#484](https://github.com/knsv/mermaid/issues/484) -- Mermaid resets some of the page CSS styles [\#482](https://github.com/knsv/mermaid/issues/482) -- Arrows rendering incorrectly in online editor [\#480](https://github.com/knsv/mermaid/issues/480) -- CSS stroke-dasharray ignored by browsers but not other viewers [\#474](https://github.com/knsv/mermaid/issues/474) -- mermaid - Browser Support issue [\#472](https://github.com/knsv/mermaid/issues/472) -- Totally love mermaid I might pop! [\#471](https://github.com/knsv/mermaid/issues/471) -- Sequence Diagram: Missing x on async arrows \(png\) [\#469](https://github.com/knsv/mermaid/issues/469) -- live editor: the svg file rendered from graph is not supported by browsers [\#468](https://github.com/knsv/mermaid/issues/468) -- Not found css [\#462](https://github.com/knsv/mermaid/issues/462) -- Phantomjs Dependency [\#461](https://github.com/knsv/mermaid/issues/461) -- Mermaid cli not working for subgraphs [\#459](https://github.com/knsv/mermaid/issues/459) -- Support for notes across multiple participants? [\#458](https://github.com/knsv/mermaid/issues/458) -- Related to Issue \#329: Phantomjs issues. [\#455](https://github.com/knsv/mermaid/issues/455) -- Add a click style [\#426](https://github.com/knsv/mermaid/issues/426) -- Add Parallel block \(par\) to sequence diagrams [\#425](https://github.com/knsv/mermaid/issues/425) -- updating shapes after the flow chart rendering complete [\#424](https://github.com/knsv/mermaid/issues/424) -- can't catch parse error Maximum call stack size exceeded on safari [\#421](https://github.com/knsv/mermaid/issues/421) -- Arrows endings are missing [\#419](https://github.com/knsv/mermaid/issues/419) -- shouldn't mermaid become more like Markdown ? [\#417](https://github.com/knsv/mermaid/issues/417) -- Live editor show rendered diagram if syntax invalid [\#415](https://github.com/knsv/mermaid/issues/415) -- Linkstyle stroke does not work [\#410](https://github.com/knsv/mermaid/issues/410) -- flowchart id's with dots in them .. break links [\#408](https://github.com/knsv/mermaid/issues/408) -- Flowchart: Link text beginning with lowercase 'o' causes flowchart to break [\#407](https://github.com/knsv/mermaid/issues/407) -- Some Chinese character will case Safari no responding. [\#405](https://github.com/knsv/mermaid/issues/405) -- Cannot center-justify text in nodes? [\#397](https://github.com/knsv/mermaid/issues/397) -- Edge labels should have white background in live editor [\#396](https://github.com/knsv/mermaid/issues/396) -- Live editor does not support activate/deactivate [\#394](https://github.com/knsv/mermaid/issues/394) -- Styling subgraph? [\#391](https://github.com/knsv/mermaid/issues/391) -- Update live editor to version 6.0.0 [\#387](https://github.com/knsv/mermaid/issues/387) -- sequence diagram config issue [\#385](https://github.com/knsv/mermaid/issues/385) -- How to add newline in the text [\#384](https://github.com/knsv/mermaid/issues/384) -- PhantomJS crashes on a large graph [\#380](https://github.com/knsv/mermaid/issues/380) -- Finnish support for class diagrams using plantuml syntax [\#377](https://github.com/knsv/mermaid/issues/377) -- mermaidAPI.render generated different svg code from mermaid.int\(\) [\#374](https://github.com/knsv/mermaid/issues/374) -- Put your own action on the chart [\#372](https://github.com/knsv/mermaid/issues/372) -- when declaring participants the elements are generated twice [\#370](https://github.com/knsv/mermaid/issues/370) -- Example Flowchart is cut in display \(Chrome\). [\#368](https://github.com/knsv/mermaid/issues/368) -- Add shebang support to diagrams [\#365](https://github.com/knsv/mermaid/issues/365) -- Silencing CLI output [\#352](https://github.com/knsv/mermaid/issues/352) -- SequenceDiagram: 3+ Alternative Paths [\#348](https://github.com/knsv/mermaid/issues/348) -- Smaller height of actor boxes [\#342](https://github.com/knsv/mermaid/issues/342) -- Question: lib/phantomscript.js - foreignObjects in SVG - related to \#58 [\#340](https://github.com/knsv/mermaid/issues/340) -- npm test fails on osx being blocked at Can not load "PhantomJS", it is not registered! [\#337](https://github.com/knsv/mermaid/issues/337) -- Tabs & subgraphs cause rendering error [\#336](https://github.com/knsv/mermaid/issues/336) -- Display question: right angles [\#335](https://github.com/knsv/mermaid/issues/335) -- No Arrows rendered v0.5.8 [\#330](https://github.com/knsv/mermaid/issues/330) -- You had errors in your syntax. Use --help for further information. [\#327](https://github.com/knsv/mermaid/issues/327) -- Allow alternate arrow syntax that doesn't close html comments [\#322](https://github.com/knsv/mermaid/issues/322) -- Comment in subgraph [\#319](https://github.com/knsv/mermaid/issues/319) -- Update graph [\#311](https://github.com/knsv/mermaid/issues/311) -- css conflicts with boostrap's css [\#308](https://github.com/knsv/mermaid/issues/308) -- Can not get click event to fire. [\#306](https://github.com/knsv/mermaid/issues/306) -- Fix phantomjs2 compatibility [\#304](https://github.com/knsv/mermaid/issues/304) -- Flowcharts do not work in native IE11 [\#303](https://github.com/knsv/mermaid/issues/303) -- Integration with remark.js - tutorial added [\#302](https://github.com/knsv/mermaid/issues/302) -- Sequence diagram Loops: changing boxMargin spoils the "loop" notation [\#299](https://github.com/knsv/mermaid/issues/299) -- src/mermaid.js generates bad code [\#297](https://github.com/knsv/mermaid/issues/297) -- Fresh fork: jasmine tests fail [\#294](https://github.com/knsv/mermaid/issues/294) -- CSS clash [\#292](https://github.com/knsv/mermaid/issues/292) -- Mermaid does not work in Chrome 48 [\#281](https://github.com/knsv/mermaid/issues/281) -- circle and ellipse cannot change color by classDef [\#271](https://github.com/knsv/mermaid/issues/271) -- npm run watch doesn't work due missing dependencies [\#266](https://github.com/knsv/mermaid/issues/266) -- label out of node [\#262](https://github.com/knsv/mermaid/issues/262) -- IE11 Support issue [\#261](https://github.com/knsv/mermaid/issues/261) -- mermaid without browser [\#260](https://github.com/knsv/mermaid/issues/260) -- Insufficient capacity of gantt diagrams [\#226](https://github.com/knsv/mermaid/issues/226) -- some WARN about installation [\#222](https://github.com/knsv/mermaid/issues/222) -- Live editor offline access [\#217](https://github.com/knsv/mermaid/issues/217) -- suggest: code highlight mode config for editors [\#212](https://github.com/knsv/mermaid/issues/212) -- Uncaught RangeError: Maximum call stack size exceeded [\#189](https://github.com/knsv/mermaid/issues/189) -- Styling label texts [\#50](https://github.com/knsv/mermaid/issues/50) - -**Merged pull requests:** - -- Remove console.log in classDB. [\#861](https://github.com/knsv/mermaid/pull/861) ([Arthaey](https://github.com/Arthaey)) -- Bump sshpk from 1.13.1 to 1.16.1 [\#851](https://github.com/knsv/mermaid/pull/851) ([dependabot[bot]](https://github.com/apps/dependabot)) -- Significantly smaller bundles [\#850](https://github.com/knsv/mermaid/pull/850) ([fabiospampinato](https://github.com/fabiospampinato)) -- Support styling of subgraphs [\#845](https://github.com/knsv/mermaid/pull/845) ([Qix-](https://github.com/Qix-)) -- fix dark theme loop labels not visible [\#837](https://github.com/knsv/mermaid/pull/837) ([jnnnnn](https://github.com/jnnnnn)) -- fix draw function can only call once [\#832](https://github.com/knsv/mermaid/pull/832) ([vaniship](https://github.com/vaniship)) -- Fix dotted lines not appearing in flowcharts when HTML labels disabled [\#828](https://github.com/knsv/mermaid/pull/828) ([stanhu](https://github.com/stanhu)) -- Fix issue with XML line breaks inside vertex labels [\#824](https://github.com/knsv/mermaid/pull/824) ([jsyang](https://github.com/jsyang)) -- fixed diagrams [\#810](https://github.com/knsv/mermaid/pull/810) ([0xflotus](https://github.com/0xflotus)) -- Clickable gantt tasks [\#804](https://github.com/knsv/mermaid/pull/804) ([abzicht](https://github.com/abzicht)) -- linkStyle now supports list of indexes with a few tests [\#798](https://github.com/knsv/mermaid/pull/798) ([ivan-danilov](https://github.com/ivan-danilov)) -- fix class diagram mermaid [\#795](https://github.com/knsv/mermaid/pull/795) ([DanShai](https://github.com/DanShai)) -- Added exclude weekdays to definition [\#792](https://github.com/knsv/mermaid/pull/792) ([jopapo](https://github.com/jopapo)) -- SVG link rendering [\#791](https://github.com/knsv/mermaid/pull/791) ([flying-sheep](https://github.com/flying-sheep)) -- Gantt milestones [\#788](https://github.com/knsv/mermaid/pull/788) ([gijswijs](https://github.com/gijswijs)) -- Remove duplicate code [\#768](https://github.com/knsv/mermaid/pull/768) ([znxkznxk1030](https://github.com/znxkznxk1030)) -- Render nodes as real links [\#765](https://github.com/knsv/mermaid/pull/765) ([flying-sheep](https://github.com/flying-sheep)) -- Fix issue with marker-end. [\#757](https://github.com/knsv/mermaid/pull/757) ([gjlubbertsen](https://github.com/gjlubbertsen)) -- Make Class Diagrams usable in Stackedit and Live Editor [\#749](https://github.com/knsv/mermaid/pull/749) ([monsterkrampe](https://github.com/monsterkrampe)) -- Adding trapezoid and inverse trapezoid vertex options. [\#741](https://github.com/knsv/mermaid/pull/741) ([adamwulf](https://github.com/adamwulf)) -- Add option for right angles [\#721](https://github.com/knsv/mermaid/pull/721) ([paulbland](https://github.com/paulbland)) -- Add nested activation classes [\#720](https://github.com/knsv/mermaid/pull/720) ([paulbland](https://github.com/paulbland)) -- wip: class diagram cardinality display [\#705](https://github.com/knsv/mermaid/pull/705) ([Vrixyz](https://github.com/Vrixyz)) -- add comments about CSS in config [\#688](https://github.com/knsv/mermaid/pull/688) ([imma90](https://github.com/imma90)) -- SequenceDiagram: Add support for multiple alt else statements [\#641](https://github.com/knsv/mermaid/pull/641) ([sechel](https://github.com/sechel)) -- fix \#426 - add class .clickable on nodes with click function or link [\#598](https://github.com/knsv/mermaid/pull/598) ([thomasleveil](https://github.com/thomasleveil)) -- Spec fix 1 [\#595](https://github.com/knsv/mermaid/pull/595) ([frankschmitt](https://github.com/frankschmitt)) - -## [7.0.5](https://github.com/knsv/mermaid/tree/7.0.5) (2017-09-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.3...7.0.5) - -**Closed issues:** - -- live editor latin error after update [\#560](https://github.com/knsv/mermaid/issues/560) -- Simple full example in online documentation is broken [\#558](https://github.com/knsv/mermaid/issues/558) -- Graph No Arrow Head v7.0.3 [\#543](https://github.com/knsv/mermaid/issues/543) -- Conflict while using mermaid along with core-js [\#512](https://github.com/knsv/mermaid/issues/512) -- Export to pdf on website [\#496](https://github.com/knsv/mermaid/issues/496) -- New downstream project: Mermaid Preview for VSCode [\#442](https://github.com/knsv/mermaid/issues/442) -- Can't Zoom the flowchart ? [\#399](https://github.com/knsv/mermaid/issues/399) -- line labels are not rendered correctly in live editor [\#366](https://github.com/knsv/mermaid/issues/366) -- mermaid-loader [\#361](https://github.com/knsv/mermaid/issues/361) -- Are there any documentation or examples for classDiagram and gitGraph? [\#359](https://github.com/knsv/mermaid/issues/359) -- \# character broken in 0.5.8 [\#347](https://github.com/knsv/mermaid/issues/347) -- Documentation issue: CSS example is not visible [\#345](https://github.com/knsv/mermaid/issues/345) -- Include documentation for command line usage [\#326](https://github.com/knsv/mermaid/issues/326) -- Fresh fork: can't build dist [\#296](https://github.com/knsv/mermaid/issues/296) -- Invalid value for \<svg\> attribute viewBox="0 0 -Infinity -Infinity" [\#291](https://github.com/knsv/mermaid/issues/291) -- Webpack require fails [\#277](https://github.com/knsv/mermaid/issues/277) -- New documentation - need improved logo [\#216](https://github.com/knsv/mermaid/issues/216) - -## [7.0.3](https://github.com/knsv/mermaid/tree/7.0.3) (2017-06-04) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.2...7.0.3) - -**Closed issues:** - -- the documentation website is down [\#539](https://github.com/knsv/mermaid/issues/539) -- Good example of interactivity with mermaidAPI [\#514](https://github.com/knsv/mermaid/issues/514) - -## [7.0.2](https://github.com/knsv/mermaid/tree/7.0.2) (2017-06-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/7.0.0...7.0.2) - -**Closed issues:** - -- CDN is not working [\#511](https://github.com/knsv/mermaid/issues/511) -- A sampe sequenceDiagram crashes mermaid-cli [\#492](https://github.com/knsv/mermaid/issues/492) -- Mermaid doesn't delete nodes when called multiple times [\#491](https://github.com/knsv/mermaid/issues/491) -- API crashes on 2nd render\(\) call [\#478](https://github.com/knsv/mermaid/issues/478) -- sequenceDiagram: dotted line for alt and empty bracket should be hidden [\#456](https://github.com/knsv/mermaid/issues/456) -- SVG output \(almost\) not correct [\#434](https://github.com/knsv/mermaid/issues/434) -- How to set axisFormatter of gantt in mermaid CLI? [\#428](https://github.com/knsv/mermaid/issues/428) -- customizing link style with any color sets `fill` property to `black` instead of `none` [\#416](https://github.com/knsv/mermaid/issues/416) -- New line at the end of SVG file [\#400](https://github.com/knsv/mermaid/issues/400) -- CLI doesn't work [\#389](https://github.com/knsv/mermaid/issues/389) -- Can't render subgraphs with htmlLabels: false [\#367](https://github.com/knsv/mermaid/issues/367) -- Color arrowhead [\#362](https://github.com/knsv/mermaid/issues/362) -- CLI: Invisible text, lines in SVG output [\#341](https://github.com/knsv/mermaid/issues/341) - -**Merged pull requests:** - -- Support Multi-line Actor Descriptions [\#764](https://github.com/knsv/mermaid/pull/764) ([watsoncj](https://github.com/watsoncj)) -- Update Travis config [\#538](https://github.com/knsv/mermaid/pull/538) ([tylerlong](https://github.com/tylerlong)) -- Fix spelling of 'you' in sequenceDiagram docs [\#537](https://github.com/knsv/mermaid/pull/537) ([ctruelson](https://github.com/ctruelson)) -- Improve CLI output [\#536](https://github.com/knsv/mermaid/pull/536) ([gibson042](https://github.com/gibson042)) -- Modernize mermaid [\#524](https://github.com/knsv/mermaid/pull/524) ([tylerlong](https://github.com/tylerlong)) -- Modernize mermaid [\#519](https://github.com/knsv/mermaid/pull/519) ([tylerlong](https://github.com/tylerlong)) -- Update CLI instructions [\#509](https://github.com/knsv/mermaid/pull/509) ([filipedeschamps](https://github.com/filipedeschamps)) -- Add style for classDiagram to dark/default theme [\#503](https://github.com/knsv/mermaid/pull/503) ([yudenzel](https://github.com/yudenzel)) -- Fix documentation for git graph. [\#498](https://github.com/knsv/mermaid/pull/498) ([gomlgs](https://github.com/gomlgs)) -- Fix links in documentations [\#497](https://github.com/knsv/mermaid/pull/497) ([saveman71](https://github.com/saveman71)) -- Update README.md with git graph sample [\#481](https://github.com/knsv/mermaid/pull/481) ([raghur](https://github.com/raghur)) -- Fix misspelling of “another” [\#479](https://github.com/knsv/mermaid/pull/479) ([stevenschobert](https://github.com/stevenschobert)) -- Fixed \#456 sequenceDiagram: dotted line for alt and empty bracket sho… [\#477](https://github.com/knsv/mermaid/pull/477) ([brookhong](https://github.com/brookhong)) -- Add viewbox attr to class diagram [\#473](https://github.com/knsv/mermaid/pull/473) ([gnkm](https://github.com/gnkm)) -- add par statement to sequenceDiagram [\#470](https://github.com/knsv/mermaid/pull/470) ([u-minor](https://github.com/u-minor)) - -## [7.0.0](https://github.com/knsv/mermaid/tree/7.0.0) (2017-01-29) - -[Full Changelog](https://github.com/knsv/mermaid/compare/6.0.0...7.0.0) - -**Implemented enhancements:** - -- npm install -g mermaid does not install phantomjs [\#329](https://github.com/knsv/mermaid/issues/329) -- activation boxes [\#313](https://github.com/knsv/mermaid/issues/313) - -**Closed issues:** - -- demos on io site not working [\#466](https://github.com/knsv/mermaid/issues/466) -- Can not be generated PNG pictures through CLI with Chinese [\#451](https://github.com/knsv/mermaid/issues/451) -- Round nodes cannot be styled with CSS classes [\#443](https://github.com/knsv/mermaid/issues/443) -- webpack gulp UglifyJsPlugin error. [\#440](https://github.com/knsv/mermaid/issues/440) -- String concatenation isn't working [\#432](https://github.com/knsv/mermaid/issues/432) -- text flow/wrap in actor box of sequence diagram [\#422](https://github.com/knsv/mermaid/issues/422) -- Online live editor still use old version [\#402](https://github.com/knsv/mermaid/issues/402) -- uncaught TypeError: t.getTransformToElement is not a function [\#401](https://github.com/knsv/mermaid/issues/401) -- Only works when using browserify'd code [\#373](https://github.com/knsv/mermaid/issues/373) -- document the use of shebang line in mmd files [\#364](https://github.com/knsv/mermaid/issues/364) -- Diagrams are small and unreadable in IE 11 - since 0.5.1 [\#356](https://github.com/knsv/mermaid/issues/356) -- \[Feature Request\] ER-Diagram Support [\#354](https://github.com/knsv/mermaid/issues/354) -- The need for mermaid.css should be mentioned explicitly in the intro docs... [\#273](https://github.com/knsv/mermaid/issues/273) - -**Merged pull requests:** - -- Update index.html [\#465](https://github.com/knsv/mermaid/pull/465) ([bmsleight](https://github.com/bmsleight)) -- Fix for \#416, customizing link style with any color sets `fill` property to `black` instead of `none` [\#452](https://github.com/knsv/mermaid/pull/452) ([joshuacolvin](https://github.com/joshuacolvin)) -- Allow .node\>circle to receive css styles [\#449](https://github.com/knsv/mermaid/pull/449) ([bfriedz](https://github.com/bfriedz)) -- Fix spelling [\#447](https://github.com/knsv/mermaid/pull/447) ([jawn](https://github.com/jawn)) -- added tests and fix cli css style selector lowercase problem [\#445](https://github.com/knsv/mermaid/pull/445) ([whyzdev](https://github.com/whyzdev)) -- Update d3.js [\#441](https://github.com/knsv/mermaid/pull/441) ([hetz](https://github.com/hetz)) -- added tests to reproduce \#434 in flowchart [\#439](https://github.com/knsv/mermaid/pull/439) ([whyzdev](https://github.com/whyzdev)) -- Code Climate config [\#437](https://github.com/knsv/mermaid/pull/437) ([larkinscott](https://github.com/larkinscott)) -- fix gantt and sequence digram cli cfg [\#435](https://github.com/knsv/mermaid/pull/435) ([whyzdev](https://github.com/whyzdev)) -- fix gantt chart cli configuration broken [\#433](https://github.com/knsv/mermaid/pull/433) ([whyzdev](https://github.com/whyzdev)) -- fix gantt chart cli configuration parsing including functions [\#430](https://github.com/knsv/mermaid/pull/430) ([whyzdev](https://github.com/whyzdev)) -- Uses an empty text node instead of a string for svg group labels [\#429](https://github.com/knsv/mermaid/pull/429) ([daveaglick](https://github.com/daveaglick)) -- use tspan via d3.textwrap to place actor text in sequence diagram [\#427](https://github.com/knsv/mermaid/pull/427) ([whyzdev](https://github.com/whyzdev)) -- \#422 use foreignObject/div to place actor label in sequence diagram [\#423](https://github.com/knsv/mermaid/pull/423) ([whyzdev](https://github.com/whyzdev)) -- Clarify the need for a CSS stylesheet [\#413](https://github.com/knsv/mermaid/pull/413) ([sifb](https://github.com/sifb)) -- Added hads downstream project [\#412](https://github.com/knsv/mermaid/pull/412) ([sinedied](https://github.com/sinedied)) -- update usage and fix \#273 [\#406](https://github.com/knsv/mermaid/pull/406) ([jinntrance](https://github.com/jinntrance)) -- Add https://github.com/raghur/mermaid-filter to downstream projects docs page [\#404](https://github.com/knsv/mermaid/pull/404) ([raghur](https://github.com/raghur)) -- New neutral theme [\#395](https://github.com/knsv/mermaid/pull/395) ([sinedied](https://github.com/sinedied)) -- fix cli issues [\#390](https://github.com/knsv/mermaid/pull/390) ([ben-page](https://github.com/ben-page)) -- Add missing space for 'Labels out of bounds' section [\#386](https://github.com/knsv/mermaid/pull/386) ([The-Alchemist](https://github.com/The-Alchemist)) -- Fix typo: `pats` -\> `paths` [\#382](https://github.com/knsv/mermaid/pull/382) ([swhgoon](https://github.com/swhgoon)) -- Added class diagram example to README.md [\#379](https://github.com/knsv/mermaid/pull/379) ([HustLion](https://github.com/HustLion)) -- override normal flowchart arrowhead to allow css styling [\#376](https://github.com/knsv/mermaid/pull/376) ([dodoinblue](https://github.com/dodoinblue)) -- added sphinx extension [\#371](https://github.com/knsv/mermaid/pull/371) ([mgaitan](https://github.com/mgaitan)) -- Fix typo in the sequence diagram documentation [\#369](https://github.com/knsv/mermaid/pull/369) ([ggpasqualino](https://github.com/ggpasqualino)) - -## [6.0.0](https://github.com/knsv/mermaid/tree/6.0.0) (2016-05-29) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.8...6.0.0) - -**Closed issues:** - -- Docs css: code hard to read [\#324](https://github.com/knsv/mermaid/issues/324) -- About Markpad integration [\#323](https://github.com/knsv/mermaid/issues/323) -- How to link backwards in flowchart? [\#321](https://github.com/knsv/mermaid/issues/321) -- Help with editor [\#310](https://github.com/knsv/mermaid/issues/310) -- +1 [\#293](https://github.com/knsv/mermaid/issues/293) -- Basic chart does not render on Chome, but does in Firefox [\#290](https://github.com/knsv/mermaid/issues/290) -- Live editor is broken [\#285](https://github.com/knsv/mermaid/issues/285) -- "No such file or directory" trying to run mermaid 0.5.7 on OS X [\#284](https://github.com/knsv/mermaid/issues/284) -- participant name as "Long Long Name" [\#283](https://github.com/knsv/mermaid/issues/283) -- Windows - cli - could not find phantomjs at the specified path [\#236](https://github.com/knsv/mermaid/issues/236) - -**Merged pull requests:** - -- The option of gantt for the spaces for the section names. [\#353](https://github.com/knsv/mermaid/pull/353) ([zeroyonichihachi](https://github.com/zeroyonichihachi)) -- Gitgraph: Make reset work with parent ref carets [\#350](https://github.com/knsv/mermaid/pull/350) ([raghur](https://github.com/raghur)) -- Remove the text-shadows that make the text look blurry [\#349](https://github.com/knsv/mermaid/pull/349) ([AsaAyers](https://github.com/AsaAyers)) -- add line interpolation to linkStyle in flowchart [\#346](https://github.com/knsv/mermaid/pull/346) ([AlanHohn](https://github.com/AlanHohn)) -- Support git graph diagrams in mermaid [\#344](https://github.com/knsv/mermaid/pull/344) ([raghur](https://github.com/raghur)) -- Build and test execution changes [\#338](https://github.com/knsv/mermaid/pull/338) ([ssbarnea](https://github.com/ssbarnea)) -- Reformatting of css files [\#331](https://github.com/knsv/mermaid/pull/331) ([Jmuccigr](https://github.com/Jmuccigr)) -- \(WIP\) Sequence Diagram Title Support [\#320](https://github.com/knsv/mermaid/pull/320) ([bronsoja](https://github.com/bronsoja)) -- activations doc + few fixes [\#318](https://github.com/knsv/mermaid/pull/318) ([ciekawy](https://github.com/ciekawy)) -- Dark theme for better contrast on darker backgrounds [\#317](https://github.com/knsv/mermaid/pull/317) ([crodriguez1a](https://github.com/crodriguez1a)) -- Activations [\#316](https://github.com/knsv/mermaid/pull/316) ([ciekawy](https://github.com/ciekawy)) -- Support leading comments for sequenceDiagrams [\#312](https://github.com/knsv/mermaid/pull/312) ([ashsearle](https://github.com/ashsearle)) -- Show a little lenience for white-space around names [\#309](https://github.com/knsv/mermaid/pull/309) ([ashsearle](https://github.com/ashsearle)) -- Update list of downstream projects [\#307](https://github.com/knsv/mermaid/pull/307) ([maxArturo](https://github.com/maxArturo)) -- Issue 299: Sequence diagram Loops: changing boxMargin spoils the "loop" notation [\#300](https://github.com/knsv/mermaid/pull/300) ([LarryKlugerDS](https://github.com/LarryKlugerDS)) -- Issue 297 - src/mermaid.js generates bad code [\#298](https://github.com/knsv/mermaid/pull/298) ([LarryKlugerDS](https://github.com/LarryKlugerDS)) -- Updated instructions for running tests [\#295](https://github.com/knsv/mermaid/pull/295) ([LarryKlugerDS](https://github.com/LarryKlugerDS)) -- Add Markdown Plus to Downstream projects [\#288](https://github.com/knsv/mermaid/pull/288) ([tylerlong](https://github.com/tylerlong)) -- Quote phantomPath so that it doesn't fail on window [\#286](https://github.com/knsv/mermaid/pull/286) ([raghur](https://github.com/raghur)) - -## [0.5.8](https://github.com/knsv/mermaid/tree/0.5.8) (2016-01-27) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.7...0.5.8) - -## [0.5.7](https://github.com/knsv/mermaid/tree/0.5.7) (2016-01-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.6...0.5.7) - -**Closed issues:** - -- Mermaid + LightPaper = ❤️ [\#280](https://github.com/knsv/mermaid/issues/280) -- Bower Integration [\#278](https://github.com/knsv/mermaid/issues/278) -- Mermaid breaks when variables end in 'v' [\#276](https://github.com/knsv/mermaid/issues/276) -- sequence diagrams don't support participant aliasing [\#263](https://github.com/knsv/mermaid/issues/263) -- One diagram that fails to render stops further execution on the page [\#259](https://github.com/knsv/mermaid/issues/259) -- Where to find line layout algorithm? [\#258](https://github.com/knsv/mermaid/issues/258) -- Compatibility with node.js [\#257](https://github.com/knsv/mermaid/issues/257) -- Label resizing with dynamically loaded fonts [\#255](https://github.com/knsv/mermaid/issues/255) -- SVG arrowheads are broken in the CLI [\#249](https://github.com/knsv/mermaid/issues/249) -- Cannot read property 'replace' of undefined [\#239](https://github.com/knsv/mermaid/issues/239) - -**Merged pull requests:** - -- gh-50 Allow styling of edge labels in css [\#267](https://github.com/knsv/mermaid/pull/267) ([Anoia](https://github.com/Anoia)) -- Allow sequenceDiagram participant aliasing [\#265](https://github.com/knsv/mermaid/pull/265) ([gibson042](https://github.com/gibson042)) - -## [0.5.6](https://github.com/knsv/mermaid/tree/0.5.6) (2015-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.5...0.5.6) - -**Implemented enhancements:** - -- Add download SVG link to the live editor [\#144](https://github.com/knsv/mermaid/issues/144) - -**Fixed bugs:** - -- Live Editor: Permalink address not being parsed [\#202](https://github.com/knsv/mermaid/issues/202) - -**Closed issues:** - -- title doesn't work in sequenceDiagram [\#248](https://github.com/knsv/mermaid/issues/248) -- hypen-minus should be valid in sequence diagram alt/else/etc. descriptions [\#247](https://github.com/knsv/mermaid/issues/247) -- Broken in firefox? [\#245](https://github.com/knsv/mermaid/issues/245) -- When there is a Chinese symbol in the flowchart, it will crash。 [\#238](https://github.com/knsv/mermaid/issues/238) -- Non-alpha characters included in ALPHA token \(flow graph jison\) [\#232](https://github.com/knsv/mermaid/issues/232) -- subgraph not rendering with change to sample [\#231](https://github.com/knsv/mermaid/issues/231) -- sequence diagram requires a new line at the end? [\#229](https://github.com/knsv/mermaid/issues/229) - -**Merged pull requests:** - -- Make sequenceDiagram terminal newline optional [\#253](https://github.com/knsv/mermaid/pull/253) ([gibson042](https://github.com/gibson042)) -- Support sequenceDiagram "over" notes [\#252](https://github.com/knsv/mermaid/pull/252) ([gibson042](https://github.com/gibson042)) -- Properly handle "rest of line" statements [\#251](https://github.com/knsv/mermaid/pull/251) ([gibson042](https://github.com/gibson042)) -- CLI: Propagate exit code from lib \(i.e., phantomjs\) [\#250](https://github.com/knsv/mermaid/pull/250) ([gibson042](https://github.com/gibson042)) -- flowRender.js - Fix FontAwesome icon insert [\#244](https://github.com/knsv/mermaid/pull/244) ([ma-zal](https://github.com/ma-zal)) -- updated sequence diagram link in live editor [\#242](https://github.com/knsv/mermaid/pull/242) ([r-a-v-a-s](https://github.com/r-a-v-a-s)) -- updated links in README.md [\#240](https://github.com/knsv/mermaid/pull/240) ([r-a-v-a-s](https://github.com/r-a-v-a-s)) -- Ellipse syntax [\#237](https://github.com/knsv/mermaid/pull/237) ([spect88](https://github.com/spect88)) -- Allow keywords as suffixes of node ids [\#235](https://github.com/knsv/mermaid/pull/235) ([spect88](https://github.com/spect88)) -- Highlighted the editor in the nav [\#234](https://github.com/knsv/mermaid/pull/234) ([knsv](https://github.com/knsv)) -- Live editor tweaks [\#233](https://github.com/knsv/mermaid/pull/233) ([spect88](https://github.com/spect88)) -- Add a Gitter chat badge to README.md [\#230](https://github.com/knsv/mermaid/pull/230) ([gitter-badger](https://github.com/gitter-badger)) - -## [0.5.5](https://github.com/knsv/mermaid/tree/0.5.5) (2015-10-21) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.4...0.5.5) - -**Closed issues:** - -- sequence diagram, arrowhead instead of crosshead [\#227](https://github.com/knsv/mermaid/issues/227) - -**Merged pull requests:** - -- Fix a typo: crosshead --\> arrowhead [\#228](https://github.com/knsv/mermaid/pull/228) ([tylerlong](https://github.com/tylerlong)) - -## [0.5.4](https://github.com/knsv/mermaid/tree/0.5.4) (2015-10-19) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.3...0.5.4) - -**Implemented enhancements:** - -- Set log level from mermaid configuration [\#220](https://github.com/knsv/mermaid/issues/220) -- Links in sequence diagrams [\#159](https://github.com/knsv/mermaid/issues/159) -- Add syntax for double headed arrows [\#123](https://github.com/knsv/mermaid/issues/123) - -**Fixed bugs:** - -- comment characters `%%` cause parse error [\#141](https://github.com/knsv/mermaid/issues/141) - -**Closed issues:** - -- Marker-end arrow cannot be shown for URL with query parameter [\#225](https://github.com/knsv/mermaid/issues/225) -- Please update bower's D3 version [\#221](https://github.com/knsv/mermaid/issues/221) -- Width fixed to 400px [\#204](https://github.com/knsv/mermaid/issues/204) -- render to png from the cli does not display the marker-end arrow heads [\#181](https://github.com/knsv/mermaid/issues/181) - -**Merged pull requests:** - -- Allow `end` as a substring of vertex id [\#224](https://github.com/knsv/mermaid/pull/224) ([spect88](https://github.com/spect88)) -- Remove duplicate npm dependencies: d3 and he [\#223](https://github.com/knsv/mermaid/pull/223) ([spect88](https://github.com/spect88)) - -## [0.5.3](https://github.com/knsv/mermaid/tree/0.5.3) (2015-10-04) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.2...0.5.3) - -## [0.5.2](https://github.com/knsv/mermaid/tree/0.5.2) (2015-10-04) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.1...0.5.2) - -**Implemented enhancements:** - -- Support for hyperlink and tooltip [\#34](https://github.com/knsv/mermaid/issues/34) - -**Closed issues:** - -- Installing “atom-mermaid@0.1.3” failed [\#218](https://github.com/knsv/mermaid/issues/218) -- node feature request [\#211](https://github.com/knsv/mermaid/issues/211) -- Please add prefix for styles [\#208](https://github.com/knsv/mermaid/issues/208) -- Bad handling of block arguments [\#207](https://github.com/knsv/mermaid/issues/207) -- please consider port to mac osx [\#203](https://github.com/knsv/mermaid/issues/203) -- allow phantomjs \>=1.9.x [\#201](https://github.com/knsv/mermaid/issues/201) -- syntax for venn diagrams? [\#200](https://github.com/knsv/mermaid/issues/200) -- Broken CLI Graphs? \(v0.5.1\) [\#196](https://github.com/knsv/mermaid/issues/196) -- Static site does not render under HTTPS [\#194](https://github.com/knsv/mermaid/issues/194) -- Error on simple graph [\#192](https://github.com/knsv/mermaid/issues/192) -- Escape "~" [\#191](https://github.com/knsv/mermaid/issues/191) -- Trying to add link using 'click' to flowchart [\#188](https://github.com/knsv/mermaid/issues/188) -- cli: no lines and arrowheads rendered / only dotted lines [\#187](https://github.com/knsv/mermaid/issues/187) -- text of mermaid div displayed on page [\#186](https://github.com/knsv/mermaid/issues/186) -- using mermaid with laravel [\#185](https://github.com/knsv/mermaid/issues/185) -- Atom editor package [\#183](https://github.com/knsv/mermaid/issues/183) -- Auto linewrap for notes in sequence diagrams [\#178](https://github.com/knsv/mermaid/issues/178) -- Execute code after initialize [\#176](https://github.com/knsv/mermaid/issues/176) -- Autoscaling for all diagram types [\#175](https://github.com/knsv/mermaid/issues/175) -- Problem wit click event callback [\#174](https://github.com/knsv/mermaid/issues/174) -- How to escape characters? [\#170](https://github.com/knsv/mermaid/issues/170) -- it can not work [\#167](https://github.com/knsv/mermaid/issues/167) -- Broken subgraph using the CLI [\#153](https://github.com/knsv/mermaid/issues/153) -- IE Support issue [\#142](https://github.com/knsv/mermaid/issues/142) -- Flowchart truncated [\#140](https://github.com/knsv/mermaid/issues/140) -- Double Quote as text is not working [\#219](https://github.com/knsv/mermaid/issues/219) -- classDef / class not working with htmlLabels? [\#210](https://github.com/knsv/mermaid/issues/210) -- Links in graph missing [\#209](https://github.com/knsv/mermaid/issues/209) -- Last word in comment boxes getting cut off by word wrap library : \( [\#195](https://github.com/knsv/mermaid/issues/195) -- Escaping characters in sequence diagram [\#193](https://github.com/knsv/mermaid/issues/193) -- SVG foreignObject rendering [\#180](https://github.com/knsv/mermaid/issues/180) -- IE9 issue [\#179](https://github.com/knsv/mermaid/issues/179) -- inoperable in an AMD/requirejs environment: IPython Notebook [\#127](https://github.com/knsv/mermaid/issues/127) -- \[Parser\] Hyphen in participant name bring TypeError [\#74](https://github.com/knsv/mermaid/issues/74) - -**Merged pull requests:** - -- Update flowchart.md [\#214](https://github.com/knsv/mermaid/pull/214) ([orschiro](https://github.com/orschiro)) -- Default style when using the CLI [\#205](https://github.com/knsv/mermaid/pull/205) ([gillesdemey](https://github.com/gillesdemey)) -- Gantt chart - add minutes and seconds durations [\#198](https://github.com/knsv/mermaid/pull/198) ([dbrans](https://github.com/dbrans)) -- Using QUnit for AMD testing [\#190](https://github.com/knsv/mermaid/pull/190) ([bollwyvl](https://github.com/bollwyvl)) -- Update phantomscript.js [\#182](https://github.com/knsv/mermaid/pull/182) ([phairow](https://github.com/phairow)) - -## [0.5.1](https://github.com/knsv/mermaid/tree/0.5.1) (2015-06-21) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.5.0...0.5.1) - -**Implemented enhancements:** - -- To SVG Export [\#146](https://github.com/knsv/mermaid/issues/146) -- Possibility to set the width of the generated flowchart [\#129](https://github.com/knsv/mermaid/issues/129) -- Special characters break parsing [\#54](https://github.com/knsv/mermaid/issues/54) -- Responsive graph layout for mobile viewers [\#51](https://github.com/knsv/mermaid/issues/51) -- Styling connector lines [\#31](https://github.com/knsv/mermaid/issues/31) - -**Fixed bugs:** - -- flowchart - styling of edges via css overrides specific styles set in the graph definition [\#128](https://github.com/knsv/mermaid/issues/128) - -**Closed issues:** - -- Live editor is broken [\#173](https://github.com/knsv/mermaid/issues/173) -- 0.5.0 no longer respects custom date definitions in Gantt diagrams [\#171](https://github.com/knsv/mermaid/issues/171) -- Drop label character restrictions [\#162](https://github.com/knsv/mermaid/issues/162) -- can't nest subgraphs in flowchart [\#161](https://github.com/knsv/mermaid/issues/161) -- Unable to generate gantt diagram with mermaid CLI [\#158](https://github.com/knsv/mermaid/issues/158) -- Inline css by "mermaid" [\#157](https://github.com/knsv/mermaid/issues/157) -- Finite State Machine Diagram [\#152](https://github.com/knsv/mermaid/issues/152) -- How to center align gantt diagram [\#150](https://github.com/knsv/mermaid/issues/150) -- Security concern regarding class definition [\#148](https://github.com/knsv/mermaid/issues/148) -- File Extension [\#147](https://github.com/knsv/mermaid/issues/147) -- `setTimeout` with clusters problematic with programmatic edits and no callback [\#133](https://github.com/knsv/mermaid/issues/133) -- module.exports.cloneCssStyles\(\) in combination with Angularjs breaks display in Chrome and IE [\#126](https://github.com/knsv/mermaid/issues/126) -- Gantt - suitable xAxis for longer project [\#125](https://github.com/knsv/mermaid/issues/125) -- How to get started with this project ? [\#64](https://github.com/knsv/mermaid/issues/64) - -**Merged pull requests:** - -- Remove moot `version` property from bower.json [\#172](https://github.com/knsv/mermaid/pull/172) ([kkirsche](https://github.com/kkirsche)) - -## [0.5.0](https://github.com/knsv/mermaid/tree/0.5.0) (2015-06-07) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.4.0...0.5.0) - -**Implemented enhancements:** - -- Add a css file, mermaid.css, with default styling [\#122](https://github.com/knsv/mermaid/issues/122) -- software architecture diagram [\#36](https://github.com/knsv/mermaid/issues/36) -- Support for bar charts and pie diagrams [\#22](https://github.com/knsv/mermaid/issues/22) - -**Closed issues:** - -- uglifyjs wanrings which means we can improve the code [\#156](https://github.com/knsv/mermaid/issues/156) -- New\(er\) features unavailable in downloadable js files? [\#151](https://github.com/knsv/mermaid/issues/151) -- Add gh-gapes link to description [\#143](https://github.com/knsv/mermaid/issues/143) -- Some examples not displayed on Firefox 36.0.1 [\#138](https://github.com/knsv/mermaid/issues/138) -- tags ending in a "v" don't render [\#132](https://github.com/knsv/mermaid/issues/132) -- Links in flowchart [\#131](https://github.com/knsv/mermaid/issues/131) -- Using the library for iOS development [\#130](https://github.com/knsv/mermaid/issues/130) -- Add capability for gantt diagrams [\#118](https://github.com/knsv/mermaid/issues/118) -- lower case v causes error in the parser [\#108](https://github.com/knsv/mermaid/issues/108) -- Label's css conflict with boostrap's .label [\#67](https://github.com/knsv/mermaid/issues/67) -- TypeError: Cannot read property 'layout' of undefined [\#37](https://github.com/knsv/mermaid/issues/37) - -**Merged pull requests:** - -- Dev 0.5.0 [\#168](https://github.com/knsv/mermaid/pull/168) ([knsv](https://github.com/knsv)) -- Fix spacing [\#164](https://github.com/knsv/mermaid/pull/164) ([rhcarvalho](https://github.com/rhcarvalho)) -- Fixing typo: "Think" -\> "Thick" [\#160](https://github.com/knsv/mermaid/pull/160) ([it0a](https://github.com/it0a)) -- IE, local html, cssRules access is denied [\#155](https://github.com/knsv/mermaid/pull/155) ([tylerlong](https://github.com/tylerlong)) -- Add automatically generated change log file. [\#139](https://github.com/knsv/mermaid/pull/139) ([skywinder](https://github.com/skywinder)) -- Adding init argument to the global API [\#137](https://github.com/knsv/mermaid/pull/137) ([bollwyvl](https://github.com/bollwyvl)) -- Add description of manual calling of init [\#136](https://github.com/knsv/mermaid/pull/136) ([bollwyvl](https://github.com/bollwyvl)) -- Allow other forms of node selection for init\(\) [\#135](https://github.com/knsv/mermaid/pull/135) ([bollwyvl](https://github.com/bollwyvl)) -- Use a library-level variable for assigning ids [\#134](https://github.com/knsv/mermaid/pull/134) ([bollwyvl](https://github.com/bollwyvl)) - -## [0.4.0](https://github.com/knsv/mermaid/tree/0.4.0) (2015-03-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.5...0.4.0) - -**Implemented enhancements:** - -- Assymetric shapes not documented [\#82](https://github.com/knsv/mermaid/issues/82) -- Improve arrows [\#3](https://github.com/knsv/mermaid/issues/3) - -**Fixed bugs:** - -- NoModificationAllowedError [\#23](https://github.com/knsv/mermaid/issues/23) - -**Closed issues:** - -- subgraph background is black in rendered flowchart PNG via CLI [\#121](https://github.com/knsv/mermaid/issues/121) -- Integrate editor at https://github.com/naseer/mermaid-webapp [\#110](https://github.com/knsv/mermaid/issues/110) -- Internet Explorer Support [\#99](https://github.com/knsv/mermaid/issues/99) - -## [0.3.5](https://github.com/knsv/mermaid/tree/0.3.5) (2015-02-15) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.4...0.3.5) - -## [0.3.4](https://github.com/knsv/mermaid/tree/0.3.4) (2015-02-15) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.3...0.3.4) - -**Implemented enhancements:** - -- Apply styling from css when using the CLI utility [\#85](https://github.com/knsv/mermaid/issues/85) -- Generated SVG works poorly outside web browsers [\#58](https://github.com/knsv/mermaid/issues/58) -- Generating SVG text blob for use in Node [\#2](https://github.com/knsv/mermaid/issues/2) - -**Closed issues:** - -- Subgraph syntax bug? [\#120](https://github.com/knsv/mermaid/issues/120) -- Live editor [\#115](https://github.com/knsv/mermaid/issues/115) -- Error in "Basic Syntax" wiki page [\#113](https://github.com/knsv/mermaid/issues/113) -- semicolons, anyone? [\#111](https://github.com/knsv/mermaid/issues/111) -- undefined `sequenceConfig` fails [\#109](https://github.com/knsv/mermaid/issues/109) -- Sequence Diagrams: Show Actors below as well [\#106](https://github.com/knsv/mermaid/issues/106) -- Allow overriding sequence diagram configuration \(SVG properties\) [\#103](https://github.com/knsv/mermaid/issues/103) -- Error when rendering A-- This is the text -- B [\#102](https://github.com/knsv/mermaid/issues/102) -- Clipping in documentation [\#97](https://github.com/knsv/mermaid/issues/97) -- isolate class styling to the svg container [\#92](https://github.com/knsv/mermaid/issues/92) -- Make the new graph declaration more visual [\#40](https://github.com/knsv/mermaid/issues/40) - -**Merged pull requests:** - -- Add live editor [\#119](https://github.com/knsv/mermaid/pull/119) ([naseer](https://github.com/naseer)) -- Adds CSS option to the CLI [\#116](https://github.com/knsv/mermaid/pull/116) ([fardog](https://github.com/fardog)) -- Update flowchart.md in response Issue \#113 [\#114](https://github.com/knsv/mermaid/pull/114) ([vijay40](https://github.com/vijay40)) -- Ignore all files except the license and dist/ folder when installing with Bower. [\#112](https://github.com/knsv/mermaid/pull/112) ([jasonbellamy](https://github.com/jasonbellamy)) - -## [0.3.3](https://github.com/knsv/mermaid/tree/0.3.3) (2015-01-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.2...0.3.3) - -**Implemented enhancements:** - -- Support for dotted links [\#26](https://github.com/knsv/mermaid/issues/26) - -**Closed issues:** - -- Missing arrows in sequence diagram [\#98](https://github.com/knsv/mermaid/issues/98) -- Error with \>9 linkStyles [\#95](https://github.com/knsv/mermaid/issues/95) - -**Merged pull requests:** - -- Require d3 directly to better support Node usage [\#107](https://github.com/knsv/mermaid/pull/107) ([markdalgleish](https://github.com/markdalgleish)) -- update doc with -c option [\#105](https://github.com/knsv/mermaid/pull/105) ([jjmr](https://github.com/jjmr)) -- Add new parameter to the console client to override the svg configuration in sequence diagrams [\#104](https://github.com/knsv/mermaid/pull/104) ([jjmr](https://github.com/jjmr)) -- Text based labels, new shape [\#101](https://github.com/knsv/mermaid/pull/101) ([bjowes](https://github.com/bjowes)) -- fix html tags in example usage [\#100](https://github.com/knsv/mermaid/pull/100) ([deiwin](https://github.com/deiwin)) - -## [0.3.2](https://github.com/knsv/mermaid/tree/0.3.2) (2015-01-11) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.1...0.3.2) - -**Implemented enhancements:** - -- Make link text look like it is on the line [\#53](https://github.com/knsv/mermaid/issues/53) - -**Closed issues:** - -- disable auto render [\#91](https://github.com/knsv/mermaid/issues/91) -- Tidy breaks mermaid \(linebreaks in \<div\>\) [\#87](https://github.com/knsv/mermaid/issues/87) -- Bug: \<br\> being rendered as text in node [\#73](https://github.com/knsv/mermaid/issues/73) -- Graph edges appear to render outside of the canvas [\#70](https://github.com/knsv/mermaid/issues/70) - -**Merged pull requests:** - -- 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)) -- 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) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.3.0...0.3.1) - -**Implemented enhancements:** - -- Support for sequence diagrams [\#16](https://github.com/knsv/mermaid/issues/16) -- Client utility for mermaid [\#6](https://github.com/knsv/mermaid/issues/6) - -**Closed issues:** - -- Non ASCII chars in labels [\#84](https://github.com/knsv/mermaid/issues/84) -- 'undefined' titles of Quicklinks on the usage page [\#80](https://github.com/knsv/mermaid/issues/80) -- \[cli\] Enhancement proposal: not fail --version / --help if phantomjs isn't installed [\#71](https://github.com/knsv/mermaid/issues/71) - -**Merged pull requests:** - -- Flowchart doc: Text in the circle now in a circle [\#81](https://github.com/knsv/mermaid/pull/81) ([Grahack](https://github.com/Grahack)) -- Fix for issue \#73 [\#79](https://github.com/knsv/mermaid/pull/79) ([it0a](https://github.com/it0a)) -- Ink template [\#78](https://github.com/knsv/mermaid/pull/78) ([gkchic](https://github.com/gkchic)) -- Show help and version even if phantom isn't present. Fixes \#71 [\#75](https://github.com/knsv/mermaid/pull/75) ([fardog](https://github.com/fardog)) -- Add apostrophe & 'and' [\#72](https://github.com/knsv/mermaid/pull/72) ([sudodoki](https://github.com/sudodoki)) - -## [0.3.0](https://github.com/knsv/mermaid/tree/0.3.0) (2014-12-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.16...0.3.0) - -**Implemented enhancements:** - -- How do I do comments? [\#47](https://github.com/knsv/mermaid/issues/47) -- Improve readability with new line as terminator and whitespace [\#38](https://github.com/knsv/mermaid/issues/38) - -**Fixed bugs:** - -- This characters failed the lexical parsing [\#46](https://github.com/knsv/mermaid/issues/46) - -**Closed issues:** - -- Trailing whitespace at the end of lines is not ignored [\#55](https://github.com/knsv/mermaid/issues/55) -- Use classes instead of inline style for easy styling [\#24](https://github.com/knsv/mermaid/issues/24) - -**Merged pull requests:** - -- Adds Command Line Interface for generating PNGs from mermaid description files [\#69](https://github.com/knsv/mermaid/pull/69) ([fardog](https://github.com/fardog)) -- Allow special symbols for direction along with acronyms [\#66](https://github.com/knsv/mermaid/pull/66) ([vijay40](https://github.com/vijay40)) - -## [0.2.16](https://github.com/knsv/mermaid/tree/0.2.16) (2014-12-15) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.15...0.2.16) - -**Fixed bugs:** - -- Lines routed outside visible area [\#19](https://github.com/knsv/mermaid/issues/19) - -**Closed issues:** - -- Mermaid not rendering properly on Wordpress pages [\#59](https://github.com/knsv/mermaid/issues/59) -- Improve example page with live demo [\#52](https://github.com/knsv/mermaid/issues/52) -- Does not render upon AngularJS Updates [\#45](https://github.com/knsv/mermaid/issues/45) -- Download link in README.MD doesn't work. [\#42](https://github.com/knsv/mermaid/issues/42) -- linkStyle usage is not obvious [\#41](https://github.com/knsv/mermaid/issues/41) -- Move \*.spec.js in src/ to test/ [\#35](https://github.com/knsv/mermaid/issues/35) - -**Merged pull requests:** - -- New grammar will allow statements ending without semicolon as disccused in Issue \#38 [\#63](https://github.com/knsv/mermaid/pull/63) ([vijay40](https://github.com/vijay40)) -- Class based styling [\#62](https://github.com/knsv/mermaid/pull/62) ([bjowes](https://github.com/bjowes)) -- Fix typos [\#60](https://github.com/knsv/mermaid/pull/60) ([sublimino](https://github.com/sublimino)) -- Included .DS_Store in gitignore [\#57](https://github.com/knsv/mermaid/pull/57) ([alvynmcq](https://github.com/alvynmcq)) -- Improves readability discussed in issue \#38 [\#56](https://github.com/knsv/mermaid/pull/56) ([vijay40](https://github.com/vijay40)) -- Added a linting task for gulp [\#43](https://github.com/knsv/mermaid/pull/43) ([serv](https://github.com/serv)) - -## [0.2.15](https://github.com/knsv/mermaid/tree/0.2.15) (2014-12-05) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.14...0.2.15) - -**Fixed bugs:** - -- Error with some characters [\#25](https://github.com/knsv/mermaid/issues/25) -- Cap-cased words break parser [\#8](https://github.com/knsv/mermaid/issues/8) - -**Closed issues:** - -- Question marks don't render properly with /dist/mermaid.full.min.js [\#30](https://github.com/knsv/mermaid/issues/30) -- Provide parse function in browser widthout `require`? [\#21](https://github.com/knsv/mermaid/issues/21) -- Better label text support [\#18](https://github.com/knsv/mermaid/issues/18) - -**Merged pull requests:** - -- Include bower_components/ to .gitignore [\#33](https://github.com/knsv/mermaid/pull/33) ([serv](https://github.com/serv)) -- Fixed reference to Git repo. [\#32](https://github.com/knsv/mermaid/pull/32) ([guyellis](https://github.com/guyellis)) - -## [0.2.14](https://github.com/knsv/mermaid/tree/0.2.14) (2014-12-03) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.13...0.2.14) - -## [0.2.13](https://github.com/knsv/mermaid/tree/0.2.13) (2014-12-03) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.10...0.2.13) - -**Implemented enhancements:** - -- Publish to NPM [\#7](https://github.com/knsv/mermaid/issues/7) - -**Closed issues:** - -- modified init to be applied more than once [\#29](https://github.com/knsv/mermaid/issues/29) -- Wanted to know build process for the project. [\#28](https://github.com/knsv/mermaid/issues/28) -- can not support Chinese description [\#20](https://github.com/knsv/mermaid/issues/20) -- Support unicode chars in labels [\#9](https://github.com/knsv/mermaid/issues/9) - -## [0.2.10](https://github.com/knsv/mermaid/tree/0.2.10) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.9...0.2.10) - -## [0.2.9](https://github.com/knsv/mermaid/tree/0.2.9) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.8...0.2.9) - -**Closed issues:** - -- Add link to jsbin playground to README [\#11](https://github.com/knsv/mermaid/issues/11) -- What are the requirements ? [\#10](https://github.com/knsv/mermaid/issues/10) - -**Merged pull requests:** - -- Allow unicode chars in labels [\#13](https://github.com/knsv/mermaid/pull/13) ([codebeige](https://github.com/codebeige)) - -## [0.2.8](https://github.com/knsv/mermaid/tree/0.2.8) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.7...0.2.8) - -## [0.2.7](https://github.com/knsv/mermaid/tree/0.2.7) (2014-12-01) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.6...0.2.7) - -**Closed issues:** - -- Provide parser as separate module [\#4](https://github.com/knsv/mermaid/issues/4) - -## [0.2.6](https://github.com/knsv/mermaid/tree/0.2.6) (2014-11-27) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.5...0.2.6) - -## [0.2.5](https://github.com/knsv/mermaid/tree/0.2.5) (2014-11-27) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.4...0.2.5) - -**Merged pull requests:** - -- Added new shapes! [\#1](https://github.com/knsv/mermaid/pull/1) ([bjowes](https://github.com/bjowes)) - -## [0.2.4](https://github.com/knsv/mermaid/tree/0.2.4) (2014-11-25) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.3...0.2.4) - -## [0.2.3](https://github.com/knsv/mermaid/tree/0.2.3) (2014-11-24) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.2...0.2.3) - -## [0.2.2](https://github.com/knsv/mermaid/tree/0.2.2) (2014-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.1...0.2.2) - -## [0.2.1](https://github.com/knsv/mermaid/tree/0.2.1) (2014-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.2.0...0.2.1) - -## [0.2.0](https://github.com/knsv/mermaid/tree/0.2.0) (2014-11-22) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.1.1...0.2.0) - -## [0.1.1](https://github.com/knsv/mermaid/tree/0.1.1) (2014-11-17) - -[Full Changelog](https://github.com/knsv/mermaid/compare/0.1.0...0.1.1) - -## [0.1.0](https://github.com/knsv/mermaid/tree/0.1.0) (2014-11-16) diff --git a/packages/mermaid/src/docs/community/code.md b/packages/mermaid/src/docs/community/code.md new file mode 100644 index 000000000..93a5fcd95 --- /dev/null +++ b/packages/mermaid/src/docs/community/code.md @@ -0,0 +1,165 @@ +# Contributing Code + +The basic steps for contributing code are: + +```mermaid +graph LR + git[1. Checkout a git branch] --> codeTest[2. Write tests and code] --> doc[3. Update documentation] --> submit[4. Submit a PR] --> review[5. Review and merge] +``` + +1. **Create** and checkout a git branch and work on your code in the branch +2. Write and update **tests** (unit and perhaps even integration (e2e) tests) (If you do TDD/BDD, the order might be different.) +3. **Let users know** that things have changed or been added in the documents! This is often overlooked, but _critical_ +4. **Submit** your code as a _pull request_. +5. Maintainers will **review** your code. If there are no changes necessary, the PR will be merged. Otherwise, make the requested changes and repeat. + +## 1. Checkout a git branch + +Mermaid uses a [Git Flow](https://guides.github.com/introduction/flow/)–inspired approach to branching. + +Development is done in the `develop` branch. + +Once development is done we create a `release/vX.X.X` branch from `develop` for testing. + +Once the release happens we add a tag to the `release` branch and merge it with `master`. The live product and on-line documentation are what is in the `master` branch. + +**All new work should be based on the `develop` branch.** + +**When you are ready to do work, always, ALWAYS:** + +1. Make sure you have the most up-to-date version of the `develop` branch. (fetch or pull to update it) +2. Check out the `develop` branch +3. Create a new branch for your work. Please name the branch following our naming convention below. + +We use the following naming convention for branches: + +```txt + [feature | bug | chore | docs]/[issue number]_[short description using dashes ('-') or underscores ('_') instead of spaces] +``` + +You can always check current [configuration of labelling and branch prefixes](https://github.com/mermaid-js/mermaid/blob/develop/.github/pr-labeler.yml) + +- The first part is the **type** of change: a feature, bug, chore, or documentation change ('docs') +- followed by a _slash_ (which helps to group like types together in many git tools) +- followed by the **issue number** +- followed by an _underscore_ ('\_') +- followed by a short text description (but use dashes ('-') or underscores ('\_') instead of spaces) + +If your work is specific to a single diagram type, it is a good idea to put the diagram type at the start of the description. This will help us keep release notes organized: it will help us keep changes for a diagram type together. + +**Ex: A new feature described in issue 2945 that adds a new arrow type called 'florbs' to state diagrams** + +`feature/2945_state-diagram-new-arrow-florbs` + +**Ex: A bug described in issue 1123 that causes random ugly red text in multiple diagram types** +`bug/1123_fix_random_ugly_red_text` + +## 2. Write Tests + +Tests ensure that each function, module, or part of code does what it says it will do. This is critically +important when other changes are made to ensure that existing code is not broken (no regression). + +Just as important, the tests act as _specifications:_ they specify what the code does (or should do). +Whenever someone is new to a section of code, they should be able to read the tests to get a thorough understanding of what it does and why. + +If you are fixing a bug, you should add tests to ensure that your code has actually fixed the bug, to specify/describe what the code is doing, and to ensure the bug doesn't happen again. +(If there had been a test for the situation, the bug never would have happened in the first place.) +You may need to change existing tests if they were inaccurate. + +If you are adding a feature, you will definitely need to add tests. Depending on the size of your feature, you may need to add integration tests. + +### Unit Tests + +Unit tests are tests that test a single function or module. They are the easiest to write and the fastest to run. + +Unit tests are mandatory all code except the renderers. (The renderers are tested with integration tests.) + +We use [Vitest](https://vitest.dev) to run unit tests. + +You can use the following command to run the unit tests: + +```sh +pnpm test +``` + +When writing new tests, it's easier to have the tests automatically run as you make changes. You can do this by running the following command: + +```sh +pnpm test:watch +``` + +### Integration/End-to-End (e2e) tests + +These test the rendering and visual appearance of the diagrams. +This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks! + +To start working with the e2e tests: + +1. Run `pnpm dev` to start the dev server +2. Start **Cypress** by running `pnpm cypress:open`. + +The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress. + +When running in CI it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag it for review if it differs. + +This is what a rendering test looks like: + +```js +it('should render forks and joins', () => { + imgSnapshotTest( + ` + stateDiagram + 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 --> [*] + `, + { logLevel: 0 } + ); + cy.get('svg'); +}); +``` + +**_[TODO - running the tests against what is expected in development. ]_** + +**_[TODO - how to generate new screenshots]_** +.... + +## 3. Update Documentation + +If the users have no way to know that things have changed, then you haven't really _fixed_ anything for the users; you've just added to making Mermaid feel broken. +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 to users know that things have changed and added! +If you are adding a new feature, add `(v<MERMAID_RELEASE_VERSION>+)` in the title or description. It will be replaced automatically with the current version number when the release happens. + +eg: `# Feature Name (v<MERMAID_RELEASE_VERSION>+)` + +We know it can sometimes be hard to code _and_ write user documentation. + +Our documentation is managed in `packages/mermaid/src/docs`. Details on how to edit is in the [Contributing Documentation](#contributing-documentation) section. + +Create another issue specifically for the documentation. +You will need to help with the PR, but definitely ask for help if you feel stuck. +When it feels hard to write stuff out, explaining it to someone and having that person ask you clarifying questions can often be 80% of the work! + +When in doubt, write up and submit what you can. It can be clarified and refined later. (With documentation, something is better than nothing!) + +## 4. Submit your pull request + +**[TODO - PR titles should start with (fix | feat | ....)]** + +We make all changes via Pull Requests (PRs). As we have many Pull Requests from developers new to Mermaid, we have put in place a process wherein _knsv, Knut Sveidqvist_ is in charge of the final release process and the active maintainers are in charge of reviewing and merging most PRs. + +- PRs will be reviewed by active maintainers, who will provide feedback and request changes as needed. +- The maintainers will request a review from knsv, if necessary. +- Once the PR is approved, the maintainers will merge the PR into the `develop` branch. +- When a release is ready, the `release/x.x.x` branch will be created, extensively tested and knsv will be in charge of the release process. + +**Reminder: Pull Requests should be submitted to the develop branch.** diff --git a/packages/mermaid/src/docs/community/development.md b/packages/mermaid/src/docs/community/development.md index bfa5ddfcf..fc11a1f6c 100644 --- a/packages/mermaid/src/docs/community/development.md +++ b/packages/mermaid/src/docs/community/development.md @@ -1,4 +1,8 @@ -# Development and Contribution 🙌 +# Contributing to Mermaid + +> The following documentation describes how to work with Mermaid in your host environment. +> There's also a [Docker installation guide](../community/docker-development.md) +> if you prefer to work in a Docker environment. So you want to help? That's great! @@ -6,125 +10,76 @@ So you want to help? That's great! Here are a few things to get you started on the right path. -**The Docs Structure is dictated by [.vitepress/config.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/.vitepress/config.ts)**. +## Get the Source Code -**Note: Commits and Pull Requests should be directed to the develop branch.** +In GitHub, you first **fork** a repository when you are going to make changes and submit pull requests. -## Branching +Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with. -Mermaid uses a [Git Flow](https://guides.github.com/introduction/flow/)–inspired approach to branching. So development is done in the `develop` branch. +[Fork mermaid](https://github.com/mermaid-js/mermaid/fork) to start contributing to the main project and its documentation, or [search for other repositories](https://github.com/orgs/mermaid-js/repositories). -Once development is done we branch a `release` branch from `develop` for testing. +[Here is a GitHub document that gives an overview of the process.](https://docs.github.com/en/get-started/quickstart/fork-a-repo) -Once the release happens we merge the `release` branch with `master` and kill the `release` branch. +## Technical Requirements -This means that **you should branch off your pull request from develop** and direct all Pull Requests to it. +> The following documentation describes how to work with Mermaid in your host environment. +> There's also a [Docker installation guide](../community/docker-development.md) +> if you prefer to work in a Docker environment. -## Contributing Code +These are the tools we use for working with the code and documentation: -We make all changes via Pull Requests. As we have many Pull Requests from developers new to mermaid, we have put in place a process, wherein _knsv, Knut Sveidqvist_ is the primary reviewer of changes and merging pull requests. The process is as follows: +- [volta](https://volta.sh/) to manage node versions. +- [Node.js](https://nodejs.org/en/). `volta install node` +- [pnpm](https://pnpm.io/) package manager. `volta install pnpm` +- [npx](https://docs.npmjs.com/cli/v8/commands/npx) the packaged executor in npm. This is needed [to install pnpm.](#install-packages) -- Large changes reviewed by knsv or other developer asked to review by knsv -- Smaller, low-risk changes like dependencies, documentation, etc. can be merged by active collaborators -- Documentation (we encourage updates to the `/packages/mermaid/src/docs` folder; you can submit them via direct commits) +Follow the setup steps below to install them and start the development. -When you commit code, create a branch with the following naming convention: +## Setup and Launch -Start with the type, such as **feature** or **bug**, followed by the issue number for reference, and a text that describes the issue. +### Switch to project -**One example:** +Once you have cloned the repository onto your development machine, change into the `mermaid` project folder (the top level directory of the mermaid project repository) -`feature/945_state_diagrams` - -**Another example:** - -`bug/123_nasty_bug_branch` - -## Contributing to Documentation - -If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature? - -The docs are located in the `src/docs` folder and are written in Markdown. Just pick the right section and start typing. If you want to propose changes to the structure of the documentation, such as adding a new section or a new file you do that via **[.vitepress/config.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/.vitepress/config.ts)**. - -> **All the documents displayed in the GitHub.io page are listed in [.vitepress/config.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/.vitepress/config.ts)**. - -The contents of [https://mermaid-js.github.io/mermaid/](https://mermaid-js.github.io/mermaid/) are based on the docs from the `master` branch. Updates committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid-js.github.io/mermaid/) once released. - -## How to Contribute to Documentation - -We are a little less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator. - -The documentation is located in the `src/docs` directory and organized according to relevant subfolder. - -The `docs` folder will be automatically generated when committing to `src/docs` and should not be edited manually. - -We encourage contributions to the documentation at [mermaid-js/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs). We publish documentation using GitHub Pages with [Docsify](https://www.youtube.com/watch?v=TV88lp7egMw&t=3s) - -### Add Unit Tests for Parsing - -This is important so that, if someone that does not know about this great feature suggests a change to the grammar, they get notified early on when that change breaks the parser. Another important aspect is that, without proper parsing, tests refactoring is pretty much impossible. - -### Add E2E Tests - -This tests the rendering and visual appearance of the diagrams. This ensures that the rendering of that feature in the e2e will be reviewed in the release process going forward. Less chance that it breaks! - -To start working with the e2e tests: - -1. Run `pnpm run dev` to start the dev server -2. Start **Cypress** by running `pnpm exec cypress open` in the **mermaid** folder. - -The rendering tests are very straightforward to create. There is a function `imgSnapshotTest`, which takes a diagram in text form and the mermaid options, and it renders that diagram in Cypress. - -When running in CI it will take a snapshot of the rendered diagram and compare it with the snapshot from last build and flag it for review if it differs. - -This is what a rendering test looks like: - -```js -it('should render forks and joins', () => { - imgSnapshotTest( - ` - stateDiagram - 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 --> [*] - `, - { logLevel: 0 } - ); - cy.get('svg'); -}); +```bash +cd mermaid ``` -### Any Questions or Suggestions? +### Install packages -After logging in at [GitHub.com](https://www.github.com), open or append to an issue [using the GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Documentation%22). +Run `npx pnpm install`. You will need `npx` for this because volta doesn't support it yet. -### How to Contribute a Suggestion +```bash +npx pnpm install # npx is required for first install +``` -Markdown is used to format the text, for more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). +### Launch -To edit Docs on your computer: +```bash +npx pnpm run dev +``` -1. Find the Markdown file (.md) to edit in the [packages/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs) directory in the `develop` branch. -2. Create a fork of the develop branch. -3. Make changes or add new documentation. -4. Commit changes to your fork and push it to GitHub. -5. Create a Pull Request of your fork. +Now you are ready to make your changes! Edit whichever files in `src` as required. -To edit Docs on GitHub: +Open <http://localhost:9000> in your browser, after starting the dev server. +There is a list of demos that can be used to see and test your changes. -1. Login to [GitHub.com](https://www.github.com). -2. Navigate to [packages/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs). -3. To edit a file, click the pencil icon at the top-right of the file contents panel. -4. Describe what you changed in the **Propose file change** section, located at the bottom of the page. -5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch). -6. Create a Pull Request of your newly forked branch by clicking the green **Create Pull Request** button. +If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy. + +That will be served at <http://localhost:9000/dev/your-file-name.html>. +After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!) + +## Verify Everything is Working + +You can run the `test` script to verify that pnpm is working _and_ that the repository has been cloned correctly: + +```bash +pnpm test +``` + +The `test` script and others are in the top-level `package.json` file. + +All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.) ## Last Words diff --git a/packages/mermaid/src/docs/community/docker-development.md b/packages/mermaid/src/docs/community/docker-development.md new file mode 100644 index 000000000..89e08b3f7 --- /dev/null +++ b/packages/mermaid/src/docs/community/docker-development.md @@ -0,0 +1,104 @@ +# Contributing to Mermaid via Docker + +> The following documentation describes how to work with Mermaid in a Docker environment. +> There's also a [host installation guide](../community/development.md) +> if you prefer to work without a Docker environment. + +So you want to help? That's great! + +![Image of happy people jumping with excitement](https://media.giphy.com/media/BlVnrxJgTGsUw/giphy.gif) + +Here are a few things to get you started on the right path. + +## Get the Source Code + +In GitHub, you first **fork** a repository when you are going to make changes and submit pull requests. + +Then you **clone** a copy to your local development machine (e.g. where you code) to make a copy with all the files to work with. + +[Fork mermaid](https://github.com/mermaid-js/mermaid/fork) to start contributing to the main project and its documentation, or [search for other repositories](https://github.com/orgs/mermaid-js/repositories). + +[Here is a GitHub document that gives an overview of the process.](https://docs.github.com/en/get-started/quickstart/fork-a-repo) + +## Technical Requirements + +> The following documentation describes how to work with Mermaid in a Docker environment. +> There's also a [host installation guide](../community/development.md) +> if you prefer to work without a Docker environment. + +[Install Docker](https://docs.docker.com/engine/install/). And that is pretty much all you need. + +Optionally, to run GUI (Cypress) within Docker you will also need an X11 server installed. +You might already have it installed, so check this by running: + +```bash +echo $DISPLAY +``` + +If the `$DISPLAY` variable is not empty, then an X11 server is running. Otherwise you may need to install one. + +## Setup and Launch + +### Switch to project + +Once you have cloned the repository onto your development machine, change into the `mermaid` project folder (the top level directory of the mermaid project repository) + +```bash +cd mermaid +``` + +### Make `./run` executable + +For development using Docker there is a self-documented `run` bash script, which provides convenient aliases for `docker compose` commands. + +Ensure `./run` script is executable: + +```bash +chmod +x run +``` + +```tip +To get detailed help simply type `./run` or `./run help`. + +It also has short _Development quick start guide_ embedded. +``` + +### Install packages + +```bash +./run pnpm install # Install packages +``` + +### Launch + +```bash +./run dev +``` + +Now you are ready to make your changes! Edit whichever files in `src` as required. + +Open <http://localhost:9000> in your browser, after starting the dev server. +There is a list of demos that can be used to see and test your changes. + +If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy. + +That will be served at <http://localhost:9000/dev/your-file-name.html>. +After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!) + +## Verify Everything is Working + +```bash +./run pnpm test +``` + +The `test` script and others are in the top-level `package.json` file. + +All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.) + +## Last Words + +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. + +[Join our Slack community if you want closer contact!](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) + +![Image of superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif) diff --git a/packages/mermaid/src/docs/community/documentation.md b/packages/mermaid/src/docs/community/documentation.md new file mode 100644 index 000000000..6a0df983d --- /dev/null +++ b/packages/mermaid/src/docs/community/documentation.md @@ -0,0 +1,92 @@ +# Contributing Documentation + +**_[TODO: This section is still a WIP. It still needs MAJOR revision.]_** + +If it is not in the documentation, it's like it never happened. Wouldn't that be sad? With all the effort that was put into the feature? + +The docs are located in the `packages/mermaid/src/docs` folder and are written in Markdown. Just pick the right section and start typing. + +The contents of [mermaid.js.org](https://mermaid.js.org/) are based on the docs from the `master` branch. +Updates committed to the `master` branch are reflected in the [Mermaid Docs](https://mermaid.js.org/) once published. + +## How to Contribute to Documentation + +We are a little less strict here, it is OK to commit directly in the `develop` branch if you are a collaborator. + +The documentation is located in the `packages/mermaid/src/docs` directory and organized according to relevant subfolder. + +The `docs` folder will be automatically generated when committing to `packages/mermaid/src/docs` and **should not** be edited manually. + +```mermaid +flowchart LR + classDef default fill:#fff,color:black,stroke:black + + source["files in /packages/mermaid/src/docs\n(changes should be done here)"] -- automatic processing\nto generate the final documentation--> published["files in /docs\ndisplayed on the official documentation site"] + +``` + +You can use `note`, `tip`, `warning` and `danger` in triple backticks to add a note, tip, warning or danger box. +Do not use vitepress specific markdown syntax `::: warning` as it will not be processed correctly. + +````markdown +```note +Note content +``` + +```tip +Tip content +``` + +```warning +Warning content +``` + +```danger +Danger content +``` +```` + +```note +If the change is _only_ to the documentation, you can get your changes published to the site quicker by making a PR to the `master` branch. In that case, your branch should be based on master, not develop. +``` + +We encourage contributions to the documentation at [packages/mermaid/src/docs in the _develop_ branch](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs). + +**_DO NOT CHANGE FILES IN `/docs`_** + +## The official documentation site + +**[The mermaid documentation site](https://mermaid.js.org/) is powered by [Vitepress](https://vitepress.vuejs.org/).** + +To run the documentation site locally: + +1. Run `pnpm --filter mermaid run docs:dev` to start the dev server. (Or `pnpm docs:dev` inside the `packages/mermaid` directory.) +2. Open [http://localhost:3333/](http://localhost:3333/) in your browser. + +Markdown is used to format the text, for more information about Markdown [see the GitHub Markdown help page](https://help.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). + +To edit Docs on your computer: + +_[TODO: need to keep this in sync with [check out a git branch in Contributing Code above](#1-checkout-a-git-branch) ]_ + +1. Create a fork of the develop branch to work on. +2. Find the Markdown file (.md) to edit in the `packages/mermaid/src/docs` directory. +3. Make changes or add new documentation. +4. Commit changes to your branch and push it to GitHub (which should create a new branch). +5. Create a Pull Request from the branch of your fork. + +To edit Docs on GitHub: + +1. Login to [GitHub.com](https://www.github.com). +2. Navigate to [packages/mermaid/src/docs](https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/src/docs) in the mermaid-js repository. +3. To edit a file, click the pencil icon at the top-right of the file contents panel. +4. Describe what you changed in the **Propose file change** section, located at the bottom of the page. +5. Submit your changes by clicking the button **Propose file change** at the bottom (by automatic creation of a fork and a new branch). +6. Visit the Actions tab in Github, `https://github.com/<Your Username>/mermaid/actions` and enable the actions for your fork. This will ensure that the documentation is built and updated in your fork. +7. Create a Pull Request of your newly forked branch by clicking the green **Create Pull Request** button. + +## Documentation organization: Sidebar 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.** + +The sidebar navigation is defined in [the vitepress configuration file config.ts](../.vitepress/config.ts). diff --git a/packages/mermaid/src/docs/community/n00b-overview.md b/packages/mermaid/src/docs/community/n00b-overview.md deleted file mode 100644 index a72e500bd..000000000 --- a/packages/mermaid/src/docs/community/n00b-overview.md +++ /dev/null @@ -1,68 +0,0 @@ -# Overview for Beginners - -**Explaining with a Diagram** - -A picture is worth a thousand words, a good diagram is undoubtedly worth more. They make understanding easier. - -## Creating and Maintaining Diagrams - -Anyone who has used Visio, or (God Forbid) Excel to make a Gantt Chart, knows how hard it is to create, edit and maintain good visualizations. - -Diagrams/Charts are significant but also become obsolete/inaccurate very fast. This catch-22 hobbles the productivity of teams. - -# Doc Rot in Diagrams - -Doc-Rot kills diagrams as quickly as it does text, but it takes hours in a desktop application to produce a diagram. - -Mermaid seeks to change using markdown-inspired syntax. The process is a quicker, less complicated, and more convenient way of going from concept to visualization. - -It is a relatively straightforward solution to a significant hurdle with the software teams. - -# Definition of Terms/ Dictionary - -**Mermaid text definitions can be saved for later reuse and editing.** - -> These are the Mermaid diagram definitions inside `<div>` tags, with the `class=mermaid`. - -```html -<pre class="mermaid"> - graph TD - A[Client] --> B[Load Balancer] - B --> C[Server01] - B --> D[Server02] -</pre> -``` - -**render** - -> This is the core function of the Mermaid API. It reads all the `Mermaid Definitions` inside `div` tags and returns an SVG file, based on the definition. - -**Nodes** - -> These are the boxes that contain text or otherwise discrete pieces of each diagram, separated generally by arrows, except for Gantt Charts and User Journey Diagrams. They will be referred often in the instructions. Read for Diagram Specific [Syntax](../intro/n00b-syntaxReference.md) - -## Advantages of using Mermaid - -- Ease to generate, modify and render diagrams when you make them. -- The number of integrations and plugins it has. -- You can add it to your or companies website. -- Diagrams can be created through comments like this in a script: - -## The catch-22 of Diagrams and Charts: - -**Diagramming and charting is a large waste of developer's time, but not having diagrams ruins productivity.** - -Mermaid solves this by reducing the time and effort required to create diagrams and charts. - -Because, the text base for the diagrams allows it to be updated easily. Also, it can be made part of production scripts (and other pieces of code). So less time is spent on documenting, as a separate task. - -## Catching up with Development - -Being based on markdown, Mermaid can be used, not only by accomplished front-end developers, but by most computer savvy people to render diagrams, at much faster speeds. -In fact one can pick up the syntax for it quite easily from the examples given and there are many tutorials available in the internet. - -## Mermaid is for everyone. - -Video [Tutorials](https://mermaid-js.github.io/mermaid/#/../config/Tutorials) are also available for the mermaid [live editor](https://mermaid.live/). - -Alternatively you can use Mermaid [Plug-Ins](https://mermaid-js.github.io/mermaid/#/./integrations), with tools you already use, like Google Docs. diff --git a/packages/mermaid/src/docs/community/newDiagram.md b/packages/mermaid/src/docs/community/newDiagram.md index 75e17e4c9..bc43475bf 100644 --- a/packages/mermaid/src/docs/community/newDiagram.md +++ b/packages/mermaid/src/docs/community/newDiagram.md @@ -4,7 +4,7 @@ #### Grammar -This would be to define a jison grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2. +This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2. For instance: @@ -13,7 +13,7 @@ For instance: #### Store data found during parsing -There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call a object provided to the parser by the user of the parser. This object can be called during parsing for storing data. +There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call an object provided to the parser by the user of the parser. This object can be called during parsing for storing data. ```jison statement @@ -30,7 +30,7 @@ In the extract of the grammar above, it is defined that a call to the setTitle m Make sure that the `parseError` function for the parser is defined and calling `mermaid.parseError`. This way a common way of detecting parse errors is provided for the end-user. ``` -For more info look in the example diagram type: +For more info look at the example diagram type: The `yy` object has the following function: @@ -49,15 +49,15 @@ parser.yy = db; ### Step 2: Rendering -Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather then the flowchart renderer as this is a more generic example. +Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather than the flowchart renderer as this is a more generic example. Place the renderer in the diagram folder. ### Step 3: Detection of the new diagram type -The second thing to do is to add the capability to detect the new diagram to type to the detectType in utils.js. The detection should return a key for the new diagram type. +The second thing to do is to add the capability to detect the new diagram to type to the detectType in `diagram-api/detectType.ts`. The detection should return a key for the new diagram type. [This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type. -For example, if your new diagram use a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader +For example, if your new diagram uses a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram. Note that the diagram type key does not have to be the same as the diagram keyword chosen for the [grammar](#grammar), but it is helpful if they are the same. @@ -117,54 +117,7 @@ There are a few features that are common between the different types of diagrams - Themes, there is a common way to modify the styling of diagrams in Mermaid. - Comments should follow mermaid standards -Here some pointers on how to handle these different areas. - -#### [Directives](../config/directives.md) - -Here is example handling from flowcharts: -Jison: - -```jison -/* lexical grammar */ -%lex -%x open_directive -%x type_directive -%x arg_directive -%x close_directive - -\%\%\{ { this.begin('open_directive'); return 'open_directive'; } -<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } -<type_directive>":" { this.popState(); this.begin('arg_directive'); return ':'; } -<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; } -<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive'; - -/* language grammar */ - -/* ... */ - -directive - : openDirective typeDirective closeDirective separator - | openDirective typeDirective ':' argDirective closeDirective separator - ; - -openDirective - : open_directive { yy.parseDirective('%%{', 'open_directive'); } - ; - -typeDirective - : type_directive { yy.parseDirective($1, 'type_directive'); } - ; - -argDirective - : arg_directive { $1 = $1.trim().replace(/'/g, '"'); yy.parseDirective($1, 'arg_directive'); } - ; - -closeDirective - : close_directive { yy.parseDirective('}%%', 'close_directive', 'flowchart'); } - ; -``` - -It is probably a good idea to keep the handling similar to this in your new diagram. The parseDirective function is provided by the mermaidAPI. +Here are some pointers on how to handle these different areas. ## Accessibility @@ -182,9 +135,9 @@ See [the definition of aria-roledescription](https://www.w3.org/TR/wai-aria-1.1/ ### accessible title and description -The syntax for accessible titles and descriptions is described in [the Accessibility documenation section.](../config/accessibility.md) +The syntax for accessible titles and descriptions is described in [the Accessibility documentation section.](../config/accessibility.md) -In a similar way to the directives, the jison syntax are quite similar between the diagrams. +As a design goal, the jison syntax should be similar between the diagrams. ```jison diff --git a/packages/mermaid/src/docs/community/questions-and-suggestions.md b/packages/mermaid/src/docs/community/questions-and-suggestions.md new file mode 100644 index 000000000..6d6f80fb6 --- /dev/null +++ b/packages/mermaid/src/docs/community/questions-and-suggestions.md @@ -0,0 +1,20 @@ +# Questions or Suggestions? + +**_[TODO: This section is still a WIP. It still needs MAJOR revision.]_** + +## First search to see if someone has already asked (and hopefully been answered) or suggested the same thing. + +- Search in Discussions +- Search in open Issues +- Search in closed Issues + +If you find an open issue or discussion thread that is similar to your question but isn't answered, you can let us know that you are also interested in it. +Use the GitHub reactions to add a thumbs-up to the issue or discussion thread. + +This helps the team know the relative interest in something and helps them set priorities and assignments. + +Feel free to add to the discussion on the issue or topic. + +If you can't find anything that already addresses your question or suggestion, _open a new issue:_ + +Log in to [GitHub.com](https://www.github.com), open or append to an issue [using the GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Documentation%22). 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 7b470eab8..efd29bfdc 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**: -```mmd +```mermaid %%{init: {"theme": "default", "logLevel": 1 }}%% graph LR a-->b diff --git a/packages/mermaid/src/docs/config/Tutorials.md b/packages/mermaid/src/docs/config/Tutorials.md index e07635641..ed0143f05 100644 --- a/packages/mermaid/src/docs/config/Tutorials.md +++ b/packages/mermaid/src/docs/config/Tutorials.md @@ -1,6 +1,6 @@ # Tutorials -This is list of publicly available Tutorials for using Mermaid.JS . This is intended as a basic introduction for the use of the Live Editor for generating diagrams, and deploying Mermaid.JS through HTML. +This is a list of publicly available Tutorials for using Mermaid.JS and is intended as a basic introduction for the use of the Live Editor for generating diagrams, and deploying Mermaid.JS through HTML. **Note that these tutorials might display an older interface, but the usage of the live-editor will largely be the same.** @@ -20,9 +20,13 @@ The definitions that can be generated the Live-Editor are also backwards-compati [Eddie Jaoude: Can you code your diagrams?](https://www.youtube.com/watch?v=9HZzKkAqrX8) +## Mermaid with OpenAI + +[Elle Neal: Mind Mapping with AI: An Accessible Approach for Neurodiverse Learners Tutorial:](https://medium.com/@elle.neal_71064/mind-mapping-with-ai-an-accessible-approach-for-neurodiverse-learners-1a74767359ff), [Demo:](https://databutton.com/v/jk9vrghc) + ## Mermaid with HTML -Examples are provided in [Getting Started](../intro/n00b-gettingStarted.md) +Examples are provided in [Getting Started](../intro/getting-started.md) **CodePen Examples:** @@ -52,10 +56,10 @@ from IPython.display import Image, display import matplotlib.pyplot as plt def mm(graph): - graphbytes = graph.encode("ascii") - base64_bytes = base64.b64encode(graphbytes) - base64_string = base64_bytes.decode("ascii") - display(Image(url="https://mermaid.ink/img/" + base64_string)) + graphbytes = graph.encode("utf8") + base64_bytes = base64.b64encode(graphbytes) + base64_string = base64_bytes.decode("ascii") + display(Image(url="https://mermaid.ink/img/" + base64_string)) mm(""" graph LR; diff --git a/packages/mermaid/src/docs/config/n00b-advanced.md b/packages/mermaid/src/docs/config/advanced.md similarity index 90% rename from packages/mermaid/src/docs/config/n00b-advanced.md rename to packages/mermaid/src/docs/config/advanced.md index 2932faa48..4ab477428 100644 --- a/packages/mermaid/src/docs/config/n00b-advanced.md +++ b/packages/mermaid/src/docs/config/advanced.md @@ -1,4 +1,4 @@ -# Advanced n00b mermaid (Coming soon..) +# Advanced mermaid (Coming soon..) ## splitting mermaid code from html diff --git a/packages/mermaid/src/docs/config/configuration.md b/packages/mermaid/src/docs/config/configuration.md index d248944dd..e52f2c6d5 100644 --- a/packages/mermaid/src/docs/config/configuration.md +++ b/packages/mermaid/src/docs/config/configuration.md @@ -4,10 +4,28 @@ When mermaid starts, configuration is extracted to determine a configuration to - The default configuration - Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**. -- Directives - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config. +- Frontmatter (v<MERMAID_RELEASE_VERSION>+) - diagram authors can update select configuration parameters in the frontmatter of the diagram. These are applied to the render config. +- Directives (Deprecated by Frontmatter) - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config. **The render config** is configuration that is used when rendering by applying these configurations. +## Frontmatter config + +The entire mermaid configuration (except the secure configs) can be overridden by the diagram author in the frontmatter of the diagram. The frontmatter is a YAML block at the top of the diagram. + +```mermaid-example +--- +title: Hello Title +config: + theme: base + themeVariables: + primaryColor: "#00ff00" +--- +flowchart + Hello --> World + +``` + ## Theme configuration ## Starting mermaid diff --git a/packages/mermaid/src/docs/config/directives.md b/packages/mermaid/src/docs/config/directives.md index ac57e6d21..7763eb073 100644 --- a/packages/mermaid/src/docs/config/directives.md +++ b/packages/mermaid/src/docs/config/directives.md @@ -1,12 +1,16 @@ # Directives +```warning +Directives are deprecated from v<MERMAID_RELEASE_VERSION>. Please use the `config` key in frontmatter to pass configuration. See [Configuration](./configuration.md) for more details. +``` + ## Directives -Directives gives a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration. +Directives give a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration. -The significance of having directives is that you have them available while writing the diagram, and can modify the default global and diagram specific configurations. So, directives are applied on top of the default configurations. The beauty of directives is that you can use them to alter configuration settings for a specific diagram, i.e. at an individual level. +The significance of having directives is that you have them available while writing the diagram, and can modify the default global and diagram-specific configurations. So, directives are applied on top of the default configuration. The beauty of directives is that you can use them to alter configuration settings for a specific diagram, i.e. at an individual level. -While directives allow you to change most of the default configuration settings, there are some that are not available, that too for security reasons. Also, you do have the _option to define the set of configurations_ that you would allow to be available to the diagram author for overriding with help of directives. +While directives allow you to change most of the default configuration settings, there are some that are not available, for security reasons. Also, you have the _option to define the set of configurations_ that you wish to allow diagram authors to override with directives. ## Types of Directives options @@ -14,30 +18,30 @@ Mermaid basically supports two types of configuration options to be overridden b 1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are: -- theme -- fontFamily -- logLevel -- securityLevel -- startOnLoad -- secure + - theme + - fontFamily + - logLevel + - securityLevel + - startOnLoad + - secure -2. _Diagram specific configurations_ : These are the configurations that are available and applied to a specific diagram. For each diagram there are specific configuration that will alter how that particular diagram looks and behaves. - For example, `mirrorActors` is a configuration that is specific to the `SequenceDiagram` and alter whether the actors are mirrored or not. So this config is available only for the `SequenceDiagram` type. +2. _Diagram-specific configurations_ : These are the configurations that are available and applied to a specific diagram. For each diagram there are specific configuration that will alter how that particular diagram looks and behaves. + For example, `mirrorActors` is a configuration that is specific to the `SequenceDiagram` and alters whether the actors are mirrored or not. So this config is available only for the `SequenceDiagram` type. -**NOTE:** These options listed here are not all the configuration options. To get hold of all the configuration options, please refer to the [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. +**NOTE:** Not all configuration options are listed here. To get hold of all the configuration options, please refer to the [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. ```note -We plan to publish a complete list of top-level configurations & all the diagram specific configurations, with their possible values in the docs soon. +We plan to publish a complete list of top-level configurations & diagram-specific configurations with their possible values in the docs soon. ``` ## Declaring directives Now that we have defined the types of configurations that are available, we can learn how to declare directives. -A directive always starts and end `%%` sign with directive text in between, like `%% {directive_text} %%`. +A directive always starts and ends with `%%` signs with directive text in between, like `%% {directive_text} %%`. Here the structure of a directive text is like a nested key-value pair map or a JSON object with root being _init_. Where all the general configurations are defined in the top level, and all the diagram specific configurations are defined one level deeper with diagram type as key/root for that section. -Following code snippet shows the structure of a directive: +The following code snippet shows the structure of a directive: ``` %%{ @@ -59,7 +63,7 @@ Following code snippet shows the structure of a directive: You can also define the directives in a single line, like this: ``` -%%{init: { **insert argument here**}}%% +%%{init: { **insert configuration options here** } }%% ``` For example, the following code snippet: @@ -69,7 +73,7 @@ For example, the following code snippet: ``` **Notes:** -The json object that is passed as {**argument** } must be valid key value pairs and encased in quotation marks or it will be ignored. +The JSON object that is passed as {**argument**} must be valid key value pairs and encased in quotation marks or it will be ignored. Valid Key Value pairs can be found in config. Example with a simple graph: @@ -82,15 +86,15 @@ A-->B Here the directive declaration will set the `logLevel` to `debug` and the `theme` to `dark` for a rendered mermaid diagram, changing the appearance of the diagram itself. -Note: You can use 'init' or 'initialize' as both acceptable as init directives. Also note that `%%init%%` and `%%initialize%%` directives will be grouped together after they are parsed. This means: +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. -```mmd +```mermaid %%{init: { 'logLevel': 'debug', 'theme': 'forest' } }%% %%{initialize: { 'logLevel': 'fatal', "theme":'dark', 'startOnLoad': true } }%% ... ``` -parsing the above generates a single `%%init%%` JSON object below, combining the two directives and carrying over the last value given for `loglevel`: +For example, parsing the above generates a single `%%init%%` JSON object below, combining the two directives and carrying over the last value given for `loglevel`: ```json { @@ -104,16 +108,15 @@ This will then be sent to `mermaid.initialize(...)` for rendering. ## Directive Examples -More directive examples for diagram specific configuration overrides -Now that the concept of directives has been explained, Let us see some more examples for directives usage: +Now that the concept of directives has been explained, let us see some more examples of directive usage: -### Changing Theme via directive +### Changing theme via directive -The following code snippet changes theme to forest: +The following code snippet changes `theme` to `forest`: `%%{init: { "theme": "forest" } }%%` -Possible themes value are: `default`,`base`, `dark`, `forest` and `neutral`. +Possible theme values are: `default`, `base`, `dark`, `forest` and `neutral`. Default Value is `default`. Example: @@ -132,7 +135,7 @@ A --> C[End] ### Changing fontFamily via directive -The following code snippet changes fontFamily to rebuchet MS, Verdana, Arial, Sans-Serif: +The following code snippet changes fontFamily to Trebuchet MS, Verdana, Arial, Sans-Serif: `%%{init: { "fontFamily": "Trebuchet MS, Verdana, Arial, Sans-Serif" } }%%` @@ -152,11 +155,11 @@ A --> C[End] ### Changing logLevel via directive -The following code snippet changes logLevel to 2: +The following code snippet changes `logLevel` to `2`: `%%{init: { "logLevel": 2 } }%%` -Possible logLevel values are: +Possible `logLevel` values are: - `1` for _debug_, - `2` for _info_ @@ -188,14 +191,14 @@ Some common flowchart configurations are: - _diagramPadding_: number - _useMaxWidth_: number -For complete list of flowchart configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. -_Soon we plan to publish a complete list all diagram specific configurations updated in the docs_ +For a complete list of flowchart configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. +_Soon we plan to publish a complete list of all diagram-specific configurations updated in the docs._ The following code snippet changes flowchart config: `%%{init: { "flowchart": { "htmlLabels": true, "curve": "linear" } } }%%` -Here were are overriding only the flowchart config, and not the general config, where HtmlLabels is set to true and curve is set to linear. +Here we are overriding only the flowchart config, and not the general config, setting `htmlLabels` to `true` and `curve` to `linear`. ```mermaid-example %%{init: { "flowchart": { "htmlLabels": true, "curve": "linear" } } }%% @@ -210,7 +213,7 @@ A --> C[End] ### Changing Sequence diagram config via directive -Some common sequence configurations are: +Some common sequence diagram configurations are: - _width_: number - _height_: number @@ -221,8 +224,8 @@ Some common sequence configurations are: - _showSequenceNumbers_: boolean - _wrap_: boolean -For complete list of sequence diagram configurations, see _defaultConfig.ts_ in the source code. -_Soon we plan to publish a complete list all diagram specific configurations updated in the docs_ +For a complete list of sequence diagram configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code. +_Soon we plan to publish a complete list of all diagram-specific configurations updated in the docs._ So, `wrap` by default has a value of `false` for sequence diagrams. @@ -232,7 +235,7 @@ Let us see an example: sequenceDiagram Alice->Bob: Hello Bob, how are you? -Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion? +Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion? Alice->Bob: Good. Bob->Alice: Cool ``` @@ -243,13 +246,13 @@ The following code snippet changes sequence diagram config for `wrap` to `true`: `%%{init: { "sequence": { "wrap": true} } }%%` -Using in the diagram above, the wrap will be enabled. +By applying that snippet to the diagram above, `wrap` will be enabled: ```mermaid-example %%{init: { "sequence": { "wrap": true, "width":300 } } }%% sequenceDiagram Alice->Bob: Hello Bob, how are you? -Bob->Alice: Fine, How did you mother like the book I suggested? And did you catch with the new book about alien invasion? +Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion? Alice->Bob: Good. Bob->Alice: Cool ``` diff --git a/packages/mermaid/src/docs/config/theming.md b/packages/mermaid/src/docs/config/theming.md index da021f7f8..0e0853283 100644 --- a/packages/mermaid/src/docs/config/theming.md +++ b/packages/mermaid/src/docs/config/theming.md @@ -55,9 +55,9 @@ To make a custom theme, modify `themeVariables` via `init`. 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-reference-table)) | +| Parameter | Description | Type | Properties | +| -------------- | ------------------------------------ | ------ | ----------------------------------------------------------------------------------- | +| themeVariables | Modifiable with the `init` directive | Object | `primaryColor`, `primaryTextColor`, `lineColor` ([see full list](#theme-variables)) | Example of modifying `themeVariables` using the `init` directive: @@ -183,6 +183,34 @@ The theming engine will only recognize hex colors and not color names. So, the v | activationBkgColor | secondaryColor | Activation Background Color | | sequenceNumberColor | calculated from lineColor | Sequence Number Color | +## Pie Diagram Variables + +| Variable | Default value | Description | +| ------------------- | ------------------------------ | ------------------------------------------ | +| pie1 | primaryColor | Fill for 1st section in pie diagram | +| pie2 | secondaryColor | Fill for 2nd section in pie diagram | +| pie3 | calculated from tertiary | Fill for 3rd section in pie diagram | +| pie4 | calculated from primaryColor | Fill for 4th section in pie diagram | +| pie5 | calculated from secondaryColor | Fill for 5th section in pie diagram | +| pie6 | calculated from tertiaryColor | Fill for 6th section in pie diagram | +| pie7 | calculated from primaryColor | Fill for 7th section in pie diagram | +| pie8 | calculated from primaryColor | Fill for 8th section in pie diagram | +| pie9 | calculated from primaryColor | Fill for 9th section in pie diagram | +| pie10 | calculated from primaryColor | Fill for 10th section in pie diagram | +| pie11 | calculated from primaryColor | Fill for 11th section in pie diagram | +| pie12 | calculated from primaryColor | Fill for 12th section in pie diagram | +| pieTitleTextSize | 25px | Title text size | +| pieTitleTextColor | taskTextDarkColor | Title text color | +| pieSectionTextSize | 17px | Text size of individual section labels | +| pieSectionTextColor | textColor | Text color of individual section labels | +| pieLegendTextSize | 17px | Text size of labels in diagram legend | +| pieLegendTextColor | taskTextDarkColor | Text color of labels in diagram legend | +| pieStrokeColor | black | Border color of individual pie sections | +| pieStrokeWidth | 2px | Border width of individual pie sections | +| pieOuterStrokeWidth | 2px | Border width of pie diagram's outer circle | +| pieOuterStrokeColor | black | Border color of pie diagram's outer circle | +| pieOpacity | 0.7 | Opacity of individual pie sections | + ## State Colors | Variable | Default value | Description | diff --git a/packages/mermaid/src/docs/config/usage.md b/packages/mermaid/src/docs/config/usage.md index dd989069f..ae3ad0f0a 100644 --- a/packages/mermaid/src/docs/config/usage.md +++ b/packages/mermaid/src/docs/config/usage.md @@ -14,29 +14,34 @@ Please note that you can switch versions through the dropdown box at the top rig For the majority of users, Using the [Live Editor](https://mermaid.live/) would be sufficient, however you may also opt to deploy mermaid as a dependency or using the [Mermaid API](./setup/README.md). -We have compiled some Video [Tutorials](./Tutorials.md) on how to use the mermaid Live Editor. +We have compiled some Video [Tutorials](./Tutorials.md) on how to use the Mermaid Live Editor. ### Installing and Hosting Mermaid on a Webpage **Using the npm package:** -1. You will need to install `node v16`, which would have npm. +Requirements: -2. Download `yarn` using npm. +- Node >= 16 -3. Enter the following command: `yarn add mermaid`. - -4. At this point, you can add mermaid as a dev dependency using this command: `yarn add --dev mermaid`. - -5. Alternatively, you can also deploy mermaid using the script tag in an HTML file with mermaid diagram descriptions as is shown in the example below. +```bash +# NPM +npm install mermaid +# Yarn +yarn add mermaid +# PNPM +pnpm add mermaid +``` **Hosting mermaid on a web page:** -> Note:This topic explored in greater depth in the [User Guide for Beginners](../intro/n00b-gettingStarted.md) +> Note: This topic is explored in greater depth in the [User Guide for Beginners](../intro/getting-started.md) The easiest way to integrate mermaid on a web page requires two elements: -- A graph definition, inside `<pre>` tags labeled `class=mermaid`. Example: +- A graph definition, inside `<pre>` tags labeled `class=mermaid`. + +Example: ```html <pre class="mermaid"> @@ -47,14 +52,13 @@ The easiest way to integrate mermaid on a web page requires two elements: </pre> ``` -- Inclusion of the mermaid address in the html page body using a `script` tag as an ESM import, and the `mermaidAPI` call. +- The mermaid js script. Added using a `script` tag as an ESM import. Example: ```html <script type="module"> import mermaid from '<CDN_URL>/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs'; - mermaid.initialize({ startOnLoad: true }); </script> ``` @@ -65,9 +69,6 @@ Example: ```html <!DOCTYPE html> <html lang="en"> - <head> - <meta charset="utf-8" /> - </head> <body> <pre class="mermaid"> graph LR @@ -77,7 +78,6 @@ Example: </pre> <script type="module"> import mermaid from '<CDN_URL>/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs'; - mermaid.initialize({ startOnLoad: true }); </script> </body> </html> @@ -89,11 +89,12 @@ An id attribute is also added to mermaid tags without one. Mermaid can load multiple diagrams, in the same page. -> Try it out, save this code as HTML and load it using any browser.(Except Internet Explorer, please don't use Internet Explorer.) +> Try it out, save this code as HTML and load it using any browser. +> (Except Internet Explorer, please don't use Internet Explorer.) ## Enabling Click Event and Tags in Nodes -A `securityLevel` configuration has to first be cleared, `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduce in version 8.2 as a security improvement, aimed at preventing malicious use. +A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use. **It is the site owner's responsibility to discriminate between trustworthy and untrustworthy user-bases and we encourage the use of discretion.** @@ -101,42 +102,33 @@ A `securityLevel` configuration has to first be cleared, `securityLevel` sets th | Parameter | Description | Type | Required | Values | | ------------- | --------------------------------- | ------ | -------- | ------------------------------------------ | -| securityLevel | Level of trust for parsed diagram | String | Required | 'sandbox', 'strict', 'loose', 'antiscript' | +| securityLevel | Level of trust for parsed diagram | String | Optional | 'sandbox', 'strict', 'loose', 'antiscript' | Values: -- **strict**: (**default**) tags in text are encoded, click functionality is disabled -- **loose**: tags in text are allowed, click functionality is enabled -- **antiscript**: html tags in text are allowed, (only script element is removed), click functionality is enabled -- **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This prevent any JavaScript running in the context. This may hinder interactive functionality of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc. +- **strict**: (**default**) HTML tags in the text are encoded and click functionality is disabled. +- **antiscript**: HTML tags in text are allowed (only script elements are removed) and click functionality is enabled. +- **loose**: HTML tags in text are allowed and click functionality is enabled. +- **sandbox**: With this security level, all rendering takes place in a sandboxed iframe. This prevents any JavaScript from running in the context. This may hinder interactive functionality of the diagram, like scripts, popups in the sequence diagram, links to other tabs or targets, etc. ```note This changes the default behaviour of mermaid so that after upgrade to 8.2, unless the `securityLevel` is not changed, tags in flowcharts are encoded as tags and clicking is disabled. **sandbox** security level is still in the beta version. ``` -**If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing . This allows clicks and tags are allowed.** +**If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing. This allows clicks and tags are allowed.** -**To change `securityLevel`, you have to call `mermaidAPI.initialize`:** +**To change `securityLevel`, you have to call `mermaid.initialize`:** ```javascript -mermaidAPI.initialize({ +mermaid.initialize({ securityLevel: 'loose', }); ``` ### Labels out of bounds -If you use dynamically loaded fonts that are loaded through CSS, such as Google fonts, mermaid should wait for the -whole page to load (dom + assets, particularly the fonts file). - -```javascript -$(document).load(function () { - mermaid.initialize(); -}); -``` - -or +If you use dynamically loaded fonts that are loaded through CSS, such as fonts, mermaid should wait for the whole page to load (dom + assets, particularly the fonts file). ```javascript $(document).ready(function () { @@ -149,12 +141,55 @@ Not doing so will most likely result in mermaid rendering graphs that have label If your page has other fonts in its body those might be used instead of the mermaid font. Specifying the font in your styling is a workaround for this. ```css -div.mermaid { +pre.mermaid { font-family: 'trebuchet ms', verdana, arial; } ``` -### Calling `mermaid.init` +### Using `mermaid.run` + +mermaid.run was added in v10 and is the preferred way of handling more complex integration. +By default, `mermaid.run` will be called when the document is ready, rendering all elements with `class="mermaid"`. + +You can customize that behavior by calling `await mermaid.run(<config>)`. + +`mermaid.initialize({startOnLoad: false})` will prevent `mermaid.run` from being called automatically after load. + +Render all elements with querySelector ".someOtherClass" + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + querySelector: '.someOtherClass', +}); +``` + +Render all elements passed as an array + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + nodes: [document.getElementById('someId'), document.getElementById('anotherId')], +}); +await mermaid.run({ + nodes: document.querySelectorAll('.yetAnotherClass'), +}); +``` + +Render all `.mermaid` elements while suppressing any error + +```js +mermaid.initialize({ startOnLoad: false }); +await mermaid.run({ + suppressErrors: true, +}); +``` + +### Calling `mermaid.init` - Deprecated + +```warning +mermaid.init is deprecated in v10 and will be removed in v11. Please use mermaid.run instead. +``` By default, `mermaid.init` will be called when the document is ready, finding all elements with `class="mermaid"`. If you are adding content after mermaid is loaded, or otherwise need @@ -188,25 +223,41 @@ mermaid fully supports webpack. Here is a [working demo](https://github.com/merm ## API usage -The main idea of the API is to be able to call a render function with the graph definition as a string. The render function -will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to -fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. +The main idea of the API is to be able to call a render function with the graph definition as a string. The render function will render the graph and call a callback with the resulting SVG code. With this approach it is up to the site creator to fetch the graph definition from the site (perhaps from a textarea), render it and place the graph somewhere in the site. -The example below show an outline of how this could be used. The example just logs the resulting SVG to the JavaScript console. +The example below shows an example of how this could be used. The example just logs the resulting SVG to the JavaScript console. ```html <script type="module"> - import mermaid from './mermaid.mjs'; - mermaid.mermaidAPI.initialize({ startOnLoad: false }); - $(async function () { - // Example of using the API var + import mermaid from './mermaid.esm.mjs'; + mermaid.initialize({ startOnLoad: false }); + + // Example of using the render function + const drawDiagram = async function () { element = document.querySelector('#graphDiv'); - const insertSvg = function (svgCode, bindFunctions) { - element.innerHTML = svgCode; - }; const graphDefinition = 'graph TB\na-->b'; - const graph = await mermaid.mermaidAPI.render('graphDiv', graphDefinition, insertSvg); - }); + const { svg } = await mermaid.render('graphDiv', graphDefinition); + element.innerHTML = svg; + }; + + await drawDiagram(); +</script> +``` + +To determine the type of diagram present in a given text, you can utilize the `mermaid.detectType` function, as demonstrated in the example below. + +```html +<script type="module"> + import mermaid from './mermaid.esm.mjs'; + const graphDefinition = `sequenceDiagram + Pumbaa->>Timon:I ate like a pig. + Timon->>Pumbaa:Pumbaa, you ARE a pig.`; + try { + const type = mermaid.detectType(graphDefinition); + console.log(type); // 'sequence' + } catch (error) { + // UnknownDiagramError + } </script> ``` @@ -219,17 +270,17 @@ The example code below is an extract of what mermaid does when using the API. Th bind events to an SVG when using the API for rendering. ```javascript -const insertSvg = function (svgCode, bindFunctions) { - element.innerHTML = svgCode; - if (typeof callback !== 'undefined') { - callback(id); +// Example of using the bindFunctions +const drawDiagram = async function () { + element = document.querySelector('#graphDiv'); + const graphDefinition = 'graph TB\na-->b'; + const { svg, bindFunctions } = await mermaid.render('graphDiv', graphDefinition); + element.innerHTML = svg; + // This can also be written as `bindFunctions?.(element);` using the `?` shorthand. + if (bindFunctions) { + bindFunctions(element); } - bindFunctions(element); }; - -const id = 'theGraph'; - -mermaidAPI.render(id, txt, insertSvg, element); ``` 1. The graph is generated using the render call. @@ -294,10 +345,10 @@ mermaid.parseError = function (err, hash) { displayErrorInGui(err); }; -const textFieldUpdated = function () { +const textFieldUpdated = async function () { const textStr = getTextFromFormField('code'); - if (mermaid.parse(textStr)) { + if (await mermaid.parse(textStr)) { reRender(textStr); } }; diff --git a/packages/mermaid/src/docs/ecosystem/integrations.md b/packages/mermaid/src/docs/ecosystem/integrations.md index cf4ccc9f8..0a27d0aad 100644 --- a/packages/mermaid/src/docs/ecosystem/integrations.md +++ b/packages/mermaid/src/docs/ecosystem/integrations.md @@ -1,5 +1,19 @@ # Integrations +## Recommendations + +### File Extension + +Applications that support mermaid files [SHOULD](https://datatracker.ietf.org/doc/html/rfc2119#section-3) use `.mermaid` or `.mmd` file extensions. + +### MIME Type + +The recommended [MIME type](https://www.iana.org/assignments/media-types/media-types.xhtml) for mermaid media is `text/vnd.mermaid`. + +[IANA](https://www.iana.org/) recognition pending. + +--- + The following list is a compilation of different integrations and plugins that allow the rendering of mermaid definitions within other applications. They also serve as proof of concept, for the variety of things that can be built with mermaid. @@ -10,21 +24,26 @@ They also serve as proof of concept, for the variety of things that can be built - [Using code blocks](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) (**Native support**) - [GitHub action: Compile mermaid to image](https://github.com/neenjaw/compile-mermaid-markdown-action) - [svg-generator](https://github.com/SimonKenyonShepard/mermaidjs-github-svg-generator) + - [GitHub Writer](https://github.com/ckeditor/github-writer) - [GitLab](https://docs.gitlab.com/ee/user/markdown.html#diagrams-and-flowcharts) (**Native support**) - [Gitea](https://gitea.io) (**Native support**) - [Azure Devops](https://docs.microsoft.com/en-us/azure/devops/project/wiki/wiki-markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) (**Native support**) - [Tuleap](https://docs.tuleap.org/user-guide/writing-in-tuleap.html#graphs) (**Native support**) +- [Mermaid Flow Visual Editor](https://www.mermaidflow.app) (**Native support**) +- [Deepdwn](https://billiam.itch.io/deepdwn) (**Native support**) - [Joplin](https://joplinapp.org) (**Native support**) +- [Slab](https://slab.com) (**Native support**) - [Swimm](https://swimm.io) (**Native support**) - [Notion](https://notion.so) (**Native support**) - [Observable](https://observablehq.com/@observablehq/mermaid) (**Native support**) -- [Obsidian](https://help.obsidian.md/How+to/Format+your+notes#Diagram) (**Native support**) +- [Obsidian](https://help.obsidian.md/Editing+and+formatting/Advanced+formatting+syntax#Diagram) (**Native support**) - [GitBook](https://gitbook.com) - [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid) - [Markdown with Mermaid CLI](https://github.com/miao1007/gitbook-plugin-mermaid-cli) - [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf) - [LiveBook](https://livebook.dev) (**Native support**) - [Atlassian Products](https://www.atlassian.com) + - [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview) - [Mermaid Plugin for Confluence](https://marketplace.atlassian.com/apps/1214124/mermaid-plugin-for-confluence?hosting=server&tab=overview) - [CloudScript.io Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview) - [Auto convert diagrams in Jira](https://github.com/coddingtonbear/jirafs-mermaid) @@ -42,13 +61,15 @@ They also serve as proof of concept, for the variety of things that can be built ## Blogs -- [Wordpress](https://wordpress.org) +- [WordPress](https://wordpress.org) - [WordPress Markdown Editor](https://wordpress.org/plugins/wp-githuber-md) - [WP-ReliableMD](https://wordpress.org/plugins/wp-reliablemd/) - [Hexo](https://hexo.io) - [hexo-filter-mermaid-diagrams](https://github.com/webappdevelp/hexo-filter-mermaid-diagrams) - [hexo-tag-mermaid](https://github.com/JameChou/hexo-tag-mermaid) - [hexo-mermaid-diagrams](https://github.com/mslxl/hexo-mermaid-diagrams) +- [Nextra](https://nextra.site/) + - [Mermaid](https://nextra.site/docs/guide/mermaid) ## CMS @@ -58,7 +79,7 @@ They also serve as proof of concept, for the variety of things that can be built - [Plugin for Mermaid.js](https://github.com/eFrane/vuepress-plugin-mermaidjs) - [Grav CMS](https://getgrav.org/) - [Mermaid Diagrams](https://github.com/DanielFlaum/grav-plugin-mermaid-diagrams) - - [Gitlab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter) + - [GitLab Markdown Adapter](https://github.com/Goutte/grav-plugin-gitlab-markdown-adapter) ## Communication @@ -78,10 +99,10 @@ They also serve as proof of concept, for the variety of things that can be built - [Flex Diagrams Extension](https://www.mediawiki.org/wiki/Extension:Flex_Diagrams) - [Semantic Media Wiki](https://semantic-mediawiki.org) - [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid) -- [FosWiki](https://foswiki.org) +- [Foswiki](https://foswiki.org) - [Mermaid Plugin](https://foswiki.org/Extensions/MermaidPlugin) - [DokuWiki](https://dokuwiki.org) - - [Flowcharts](https://www.dokuwiki.org/plugin:flowcharts?s[]=mermaid) + - [Mermaid Plugin](https://www.dokuwiki.org/plugin:mermaid) - [ComboStrap](https://combostrap.com/mermaid) - [TiddlyWiki](https://tiddlywiki.com/) - [mermaid-tw5: full js library](https://github.com/efurlanm/mermaid-tw5) @@ -133,16 +154,24 @@ They also serve as proof of concept, for the variety of things that can be built - [Named block =Diagram](https://github.com/zag/podlite/tree/main/packages/podlite-diagrams) - [GNU Nano](https://www.nano-editor.org/) - [Nano Mermaid](https://github.com/Yash-Singh1/nano-mermaid) +- [CKEditor](https://github.com/ckeditor/ckeditor5) + - [CKEditor 5 Mermaid plugin](https://github.com/ckeditor/ckeditor5-mermaid) +- [Standard Notes](https://standardnotes.com/) + - [sn-mermaid](https://github.com/nienow/sn-mermaid) ## Document Generation - [Sphinx](https://www.sphinx-doc.org/en/master/) - [sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid) -- [remark.js](https://remark.js.org/) - - [remark-mermaid](https://github.com/temando/remark-mermaid) -- [jSDoc](https://jsdoc.app/) +- [remark](https://remark.js.org/) + - [remark-mermaidjs](https://github.com/remcohaszing/remark-mermaidjs) +- [rehype](https://github.com/rehypejs/rehype) + - [rehype-mermaidjs](https://github.com/remcohaszing/rehype-mermaidjs) +- [Gatsby](https://www.gatsbyjs.com/) + - [gatsby-remark-mermaid](https://github.com/remcohaszing/gatsby-remark-mermaid) +- [JSDoc](https://jsdoc.app/) - [jsdoc-mermaid](https://github.com/Jellyvision/jsdoc-mermaid) -- [MkDocs](https://mkdocs.org) +- [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/) - [Type Doc](https://typedoc.org/) @@ -152,6 +181,8 @@ They also serve as proof of concept, for the variety of things that can be built - [codedoc-mermaid-plugin](https://www.npmjs.com/package/codedoc-mermaid-plugin) - [mdbook](https://rust-lang.github.io/mdBook/index.html) - [mdbook-mermaid](https://github.com/badboy/mdbook-mermaid) +- [Quarto](https://quarto.org/) +- [Typora](https://typora.io/) ([Native support](https://support.typora.io/Draw-Diagrams-With-Markdown/#mermaid)) ## Browser Extensions @@ -179,6 +210,10 @@ They also serve as proof of concept, for the variety of things that can be built - [bisheng-plugin-mermaid](https://github.com/yct21/bisheng-plugin-mermaid) - [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) - [ExDoc](https://github.com/elixir-lang/ex_doc) - [Rendering Mermaid graphs](https://github.com/elixir-lang/ex_doc#rendering-mermaid-graphs) +- [NiceGUI: Let any browser be the frontend of your Python code](https://nicegui.io) + - [ui.mermaid(...)](https://nicegui.io/reference#mermaid_diagrams) + - [ui.markdown(..., extras=['mermaid'])](https://nicegui.io/reference#markdown_element) diff --git a/packages/mermaid/src/docs/index.md b/packages/mermaid/src/docs/index.md index b0b38bd79..dd1025d56 100644 --- a/packages/mermaid/src/docs/index.md +++ b/packages/mermaid/src/docs/index.md @@ -1,5 +1,6 @@ --- layout: home +sidebar: false title: Mermaid titleTemplate: Diagramming and charting tool @@ -23,166 +24,13 @@ features: - title: ➕ Easy to use! details: Easily create and render detailed diagrams and charts with the Mermaid Live Editor. link: https://mermaid.live/ - - title: 🎥 Video Tutorials! - details: Curated list of video tutorials and examples created by the community. - link: ../../config/Tutorials.html - title: 🧩 Integrations available! details: Use Mermaid with your favorite applications, check out the integrations list. link: ../../ecosystem/integrations.md - title: 🏆 Award winning! details: 2019 JavaScript Open Source Award winner for "The Most Exciting Use of Technology". link: https://osawards.com/javascript/2019 + - title: 🥰 Mermaid + Mermaid Chart + details: Mermaid Chart is a major supporter of the Mermaid project. + link: https://www.mermaidchart.com/ --- - -<script setup> -import { VPTeamMembers } from 'vitepress/theme' - -const websiteSVG = { - svg: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-globe"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>' -} - -const members = [ - { - avatar: "https://avatars.githubusercontent.com/u/5837277?v=4", - name: "Knut Sveidqvist", - title: "Creator", - links: [{ icon: "github", link: "https://github.com/knsv" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/58763315?v=4", - name: "Neil Cuzon", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/NeilCuzon" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/733544?v=4", - name: "Tyler Liu", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/tylerlong" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/10703445?v=4", - name: "Sidharth Vinod", - title: "Developer", - links: [ - { icon: "github", link: "https://github.com/sidharthv96" }, - { icon: websiteSVG, link: "https://sidharth.dev" }, - { icon: "linkedin", link: "https://www.linkedin.com/in/sidharth-vinod/" }, - ], - }, - { - avatar: "https://avatars.githubusercontent.com/u/16836093?v=4", - name: "Ashish Jain", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/ashishjain0512" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/6032561?v=4", - name: "Matthieu Morel", - title: "Developer", - links: [ - { icon: "github", link: "https://github.com/mmorel-35" }, - { - icon: "linkedin", - link: "https://www.linkedin.com/in/matthieumorel35/", - }, - ], - }, - { - avatar: "https://avatars.githubusercontent.com/u/6552521?v=4", - name: "Christian Klemm", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/klemmchr" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/19716675?v=4", - name: "Alois Klink", - title: "Developer", - links: [ - { icon: "github", link: "https://github.com/aloisklink" }, - { icon: websiteSVG, link: "https://aloisklink.com" }, - { icon: "linkedin", link: "https://www.linkedin.com/in/aloisklink/" }, - ], - }, - { - avatar: "https://avatars.githubusercontent.com/u/114684273?v=4", - name: "Per Brolin", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/pbrolin47" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/53054099?v=4", - name: "Yash Singh", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/Yash-Singh1" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/1912783?v=4", - name: "Marc Faber", - title: "Developer", - links: [ - { icon: "github", link: "https://gdfaber.github.io/" }, - { icon: "linkedin", link: "https://www.linkedin.com/in/marc-faber/" }, - ], - }, - { - avatar: "https://avatars.githubusercontent.com/u/12032557?v=4", - name: "Mindaugas Laganeckas", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/MindaugasLaganeckas" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/300077?v=4", - name: "Justin Greywolf", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/jgreywolf" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/1564825?v=4", - name: "Nacho Orlandoni", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/IOrlandoni" }], - }, - { - avatar: "https://avatars.githubusercontent.com/u/19526120?v=4", - name: "Adrian Hall", - title: "Developer", - links: [{ icon: "github", link: "https://github.com/spopida" }], - }, -]; - -</script> - -<div class="vp-doc" > - <h2 id="meet-the-team"> Meet The Team </h2> - <VPTeamMembers size="small" :members="members" /> -</div> - -<style> - .image-container .image-src { - margin: 1rem auto; - max-width: 100%; - width: 100%; -} - - .dark .image-src{ - filter: invert(1) hue-rotate(217deg) contrast(0.72); - max-width: 100%; - } - - .vp-doc { - align-items: center; - flex-direction: column; - display: flex; - margin: 1.5rem; - } - - .vp-doc h2 { - margin: 48px 0 16px; - border-top: 1px solid var(--vp-c-divider-light); - padding-top: 24px; - letter-spacing: -.02em; - line-height: 32px; - font-size: 24px; -} -</style> diff --git a/packages/mermaid/src/docs/intro/examples.md b/packages/mermaid/src/docs/intro/examples.md index f4cb3b929..7dda288dc 100644 --- a/packages/mermaid/src/docs/intro/examples.md +++ b/packages/mermaid/src/docs/intro/examples.md @@ -98,3 +98,22 @@ journey Go downstairs: 5: Me Sit down: 5: Me ``` + +### [Quadrant Chart](../syntax/quadrantChart.md) + +```mermaid-example +quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + Campaign A: [0.3, 0.6] + Campaign B: [0.45, 0.23] + Campaign C: [0.57, 0.69] + Campaign D: [0.78, 0.34] + Campaign E: [0.40, 0.34] + Campaign F: [0.35, 0.78] +``` diff --git a/packages/mermaid/src/docs/intro/n00b-gettingStarted.md b/packages/mermaid/src/docs/intro/getting-started.md similarity index 86% rename from packages/mermaid/src/docs/intro/n00b-gettingStarted.md rename to packages/mermaid/src/docs/intro/getting-started.md index cfc16e707..d61737f92 100644 --- a/packages/mermaid/src/docs/intro/n00b-gettingStarted.md +++ b/packages/mermaid/src/docs/intro/getting-started.md @@ -2,7 +2,7 @@ Mermaid is composed of three parts: Deployment, Syntax and Configuration. -This section talks about the different ways to deploy Mermaid. Learning the [Syntax](n00b-syntaxReference.md) would be of great help to the beginner. +This section talks about the different ways to deploy Mermaid. Learning the [Syntax](syntax-reference.md) would be of great help to the beginner. > Generally the live editor is enough for most general uses of mermaid, and is a good place to start learning. @@ -36,7 +36,7 @@ graph TD In the `Code` section one can write or edit raw mermaid code, and instantly `Preview` the rendered result on the panel beside it. -The `Configuration` Section is for changing the appearance and behavior of mermaid diagrams. An easy introduction to mermaid configuration is found in the [Advanced usage](../config/n00b-advanced.md) section. A complete configuration reference cataloging the default values can be found on the [mermaidAPI](../config/setup/README.md) page. +The `Configuration` Section is for changing the appearance and behavior of mermaid diagrams. An easy introduction to mermaid configuration is found in the [Advanced usage](../config/advanced.md) section. A complete configuration reference cataloging the default values can be found on the [mermaidAPI](../config/setup/README.md) page. ![Code,Config and Preview](./img/Code-Preview-Config.png) @@ -86,7 +86,7 @@ When writing the .html file, we give two instructions inside the html code to th a. The mermaid code for the diagram we want to create. -b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process . +b. The importing of mermaid library through the `mermaid.esm.mjs` or `mermaid.esm.min.mjs` and the `mermaid.initialize()` call, which dictates the appearance of diagrams and also starts the rendering process. **a. The embedded mermaid diagram definition inside a `<pre class="mermaid">`:** @@ -118,7 +118,7 @@ b. The importing of mermaid library through the `mermaid.esm.js` or `mermaid.esm ``` **Notes**: -Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can place `mermaid.initialize()` inside `mermaid.esm.min.mjs` for brevity. However, doing the opposite lets you control when it starts looking for `<div>`tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `<div>` tags may have loaded on the execution of `mermaid.esm.min.mjs` file. +Rendering in Mermaid is initialized by `mermaid.initialize()` call. However, doing the opposite lets you control when it starts looking for `<pre>` tags inside the web page with `mermaid.initialize()`. This is useful when you think that not all `<pre>` tags may have loaded on the execution of `mermaid.esm.min.mjs` file. `startOnLoad` is one of the parameters that can be defined by `mermaid.initialize()` @@ -126,10 +126,6 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. You can plac | ----------- | --------------------------------- | ------- | ----------- | | startOnLoad | Toggle for Rendering upon loading | Boolean | true, false | -### Adding external diagrams to mermaid - -Please refer to the [Mindmap](../syntax/mindmap.md?id=integrating-with-your-librarywebsite) section for more information. - ### Working Examples **Here is a full working example of the mermaidAPI being called through the CDN:** @@ -208,4 +204,4 @@ In this example mermaid.js is referenced in `src` as a separate JavaScript file, **Comments from Knut Sveidqvist, creator of mermaid:** -- In early versions of mermaid, the `<script>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflects the previous way which still works. +- In early versions of mermaid, the `<script>` tag was invoked in the `<head>` part of the web page. Nowadays we can place it in the `<body>` as seen above. Older parts of the documentation frequently reflect the previous way which still works. diff --git a/packages/mermaid/src/docs/intro/index.md b/packages/mermaid/src/docs/intro/index.md index 2e94e9f5c..7718949b7 100644 --- a/packages/mermaid/src/docs/intro/index.md +++ b/packages/mermaid/src/docs/intro/index.md @@ -4,11 +4,22 @@ It is a JavaScript based diagramming and charting tool that renders Markdown-inspired text definitions to create and modify diagrams dynamically. -> If you are familiar with Markdown you should have no problem learning [Mermaid's Syntax](n00b-syntaxReference.md). +> If you are familiar with Markdown you should have no problem learning [Mermaid's Syntax](syntax-reference.md). <img src="/header.png" alt="" /> -[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) [![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid) [![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 Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_) +<div class='badges'> + +[![Build CI Status](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml/badge.svg)](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) +[![NPM](https://img.shields.io/npm/v/mermaid)](https://www.npmjs.com/package/mermaid) +[![npm minified gzipped bundle size](https://img.shields.io/bundlephobia/minzip/mermaid)](https://bundlephobia.com/package/mermaid) +[![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 Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) +[![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_) + +</div> <!-- Mermaid book banner --> @@ -28,7 +39,7 @@ Mermaid allows even non-programmers to easily create detailed and diagrams throu [Tutorials](../config/Tutorials.md) has video tutorials. Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](../ecosystem/integrations.md). -For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](../community/n00b-overview.md) and [Usage](../config/usage.md). +For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](../intro/getting-started.md) and [Usage](../config/usage.md). 🌐 [CDN](https://www.jsdelivr.com/package/npm/mermaid) | 📖 [Documentation](https://mermaidjs.github.io) | 🙌 [Contribution](../community/development.md) | 🔌 [Plug-Ins](../ecosystem/integrations.md) @@ -48,9 +59,9 @@ In our release process we rely heavily on visual regression tests using [applito ## Installation -**In depth guides and examples can be found at [Getting Started](./n00b-gettingStarted.md) and [Usage](../config/usage.md).** +**In depth guides and examples can be found at [Getting Started](./getting-started.md) and [Usage](../config/usage.md).** -**It would also be helpful to learn more about mermaid's [Syntax](./n00b-syntaxReference.md).** +**It would also be helpful to learn more about mermaid's [Syntax](./syntax-reference.md).** ### CDN @@ -76,7 +87,7 @@ To Deploy Mermaid: ### [Mermaid API](../config/setup/README.md): -**To deploy mermaid without a bundler, one can insert a `script` tag with an absolute address and a `mermaid.initialize` call into the HTML like so:** +**To deploy mermaid without a bundler, insert a `script` tag with an absolute address and a `mermaid.initialize` call into the HTML using the following example:** ```html <script type="module"> @@ -85,9 +96,9 @@ To Deploy Mermaid: </script> ``` -**Doing so will command the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags mermaid will try to read the diagram/chart definitions and render them into SVG charts.** +**Doing so commands the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags, mermaid tries read the diagram/chart definitions and render them into SVG charts.** -**Examples can be found at** [Other examples](../syntax/examples.md) +**Examples can be found in** [Other examples](../syntax/examples.md) ## Sibling projects @@ -111,7 +122,19 @@ Together we could continue the work with things like: Don't hesitate to contact me if you want to get involved! -## For contributors +## Contributors + +<div class='badges'> + +[![Good first issue](https://img.shields.io/github/labels/mermaid-js/mermaid/Good%20first%20issue%21)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%21%22) +[![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) +[![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) + +</div> + +Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. + +Detailed information about how to contribute can be found in the [contribution guideline](/community/development). ### Requirements @@ -119,7 +142,7 @@ Don't hesitate to contact me if you want to get involved! - [Node.js](https://nodejs.org/en/). `volta install node` - [pnpm](https://pnpm.io/) package manager. `volta install pnpm` -## Development Installation +### Development Installation ```bash git clone git@github.com:mermaid-js/mermaid.git @@ -156,19 +179,7 @@ Update version number in `package.json`. npm publish ``` -The above command generates files into the `dist` folder and publishes them to <npmjs.org>. - -## Related projects - -- [Command Line Interface](https://github.com/mermaid-js/mermaid-cli) -- [Live Editor](https://github.com/mermaid-js/mermaid-live-editor) -- [HTTP Server](https://github.com/TomWright/mermaid-server) - -## Contributors [![Good first issue](https://img.shields.io/github/labels/mermaid-js/mermaid/Good%20first%20issue%21)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+first+issue%21%22) [![Contributors](https://img.shields.io/github/contributors/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) [![Commits](https://img.shields.io/github/commit-activity/m/mermaid-js/mermaid)](https://github.com/mermaid-js/mermaid/graphs/contributors) - -Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out. - -Detailed information about how to contribute can be found in the [contribution guide](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md) +The above command generates files into the `dist` folder and publishes them to [npmjs.com](https://www.npmjs.com/). ## Security and safe diagrams @@ -199,20 +210,15 @@ A quick note from Knut Sveidqvist: _Mermaid was created by Knut Sveidqvist for easier documentation._ <style scoped> - #contributors + p, - #about-mermaid + p + p + blockquote + img + p - { - display: flex + .badges > p { + display: flex; } - #contributors + p a, - #about-mermaid + p + p + blockquote + img + p a - { - margin: 0 0.5rem + .badges > p > a { + margin: 0 0.5rem; } - .dark #VPContent > div > div > div.content > div > main > div > div > img - { + .dark #VPContent > div > div > div.content > div > main > div > div > img { filter: invert(1) hue-rotate(217deg) contrast(0.72); } </style> diff --git a/packages/mermaid/src/docs/intro/n00b-syntaxReference.md b/packages/mermaid/src/docs/intro/syntax-reference.md similarity index 90% rename from packages/mermaid/src/docs/intro/n00b-syntaxReference.md rename to packages/mermaid/src/docs/intro/syntax-reference.md index 8e8c18a4d..b7b78781c 100644 --- a/packages/mermaid/src/docs/intro/n00b-syntaxReference.md +++ b/packages/mermaid/src/docs/intro/syntax-reference.md @@ -24,7 +24,7 @@ erDiagram PRODUCT ||--o{ ORDER-ITEM : "ordered in" ``` -The [Getting Started](./n00b-gettingStarted.md) section can also provide some practical examples of mermaid syntax. +The [Getting Started](./getting-started.md) section can also provide some practical examples of mermaid syntax. ## Diagram Breaking @@ -38,30 +38,30 @@ One should **beware the use of some words or symbols** that can break diagrams. | 'end' | The word "End" can cause Flowcharts and Sequence diagrams to break | Wrap them in quotation marks to prevent breakage. | | [Nodes inside Nodes](../syntax/flowchart.md?id=special-characters-that-break-syntax) | Mermaid gets confused with nested shapes | wrap them in quotation marks to prevent breaking | -### Mermaid Live Editor +## Mermaid Live Editor Now, that you've seen what you should not add to your diagrams, you can play around with them in the [Mermaid Live Editor](https://mermaid.live). -# Configuration +## Configuration Configuration is the third part of Mermaid, after deployment and syntax. It deals with the different ways that Mermaid can be customized across different deployments. If you are interested in altering and customizing your Mermaid Diagrams, you will find the methods and values available for [Configuration](../config/setup/README.md) here. It includes themes. This section will introduce the different methods of configuring the behaviors and appearances of Mermaid Diagrams. -The following are the most commonly used methods, and they are all tied to Mermaid [Deployment](./n00b-gettingStarted.md) methods. +The following are the most commonly used methods, and they are all tied to Mermaid [Deployment](./getting-started.md) methods. ### Configuration Section in the [Live Editor](https://mermaid.live). Here you can edit certain values to change the behavior and appearance of the diagram. -### [The initialize() call](https://mermaid-js.github.io/mermaid/#/n00b-gettingStarted?id=_3-calling-the-javascript-api), +### [The initialize() call](./getting-started.md#_3-calling-the-javascript-api) Used when Mermaid is called via an API, or through a `<script>` tag. -### [Directives](../config/directives.md), +### [Directives](../config/directives.md) Allows for the limited reconfiguration of a diagram just before it is rendered. It can alter the font style, color and other aesthetic aspects of the diagram. You can pass a directive alongside your definition inside `%%{ }%%`. It can be done either above or below your diagram definition. -### [Theme Manipulation](../config/theming.md): +### [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. diff --git a/packages/mermaid/src/docs/news/announcements.md b/packages/mermaid/src/docs/news/announcements.md new file mode 100644 index 000000000..951c42cbd --- /dev/null +++ b/packages/mermaid/src/docs/news/announcements.md @@ -0,0 +1,7 @@ +# Announcements + +## [Special cases broke Microsoft Zune and can ruin your code base too](https://www.mermaidchart.com/blog/posts/special-cases-broke-microsoft-zune-and-can-ruin-your-code-base-too/) + +23 August 2023 · 15 mins + +Read about the pitfalls of special cases in programming, illustrating how they can lead to complexity, diminish readability, and create maintenance challenges. diff --git a/packages/mermaid/src/docs/news/blog.md b/packages/mermaid/src/docs/news/blog.md new file mode 100644 index 000000000..b18e11650 --- /dev/null +++ b/packages/mermaid/src/docs/news/blog.md @@ -0,0 +1,85 @@ +# Blog + +## [Special cases broke Microsoft Zune and can ruin your code base too](https://www.mermaidchart.com/blog/posts/special-cases-broke-microsoft-zune-and-can-ruin-your-code-base-too/) + +23 August 2023 · 15 mins + +Read about the pitfalls of special cases in programming, illustrating how they can lead to complexity, diminish readability, and create maintenance challenges. + +## [New AI chatbot now available on Mermaid Chart to simplify text-based diagram creation](https://www.mermaidchart.com/blog/posts/ai-chatbot-now-available-on-mermaid-chart-to-simplify-text-based-diagram-creation/) + +14 August 2023 · 4 mins + +Introducing Mermaid Chart’s new AI chatbot, a diagramming assistant that simplifies text-based diagram creation for everyone, from developers to educators, offering features to start, edit, and fix diagrams, and embodying our vision to make diagramming accessible, user-friendly, and fun. + +## [Believe It or Not, You Still Need an Online UML Diagram Tool](https://www.mermaidchart.com/blog/posts/uml-diagram-tool/) + +14 August 2023 · 8 mins + +A UML diagram tool helps developers and other professionals quickly create and share UML diagrams that communicate information about complex software systems. + +## [From Chaos to Clarity: Exploring Mind Maps with MermaidJS](https://www.mermaidchart.com/blog/posts/from-chaos-to-clarity-exploring-mind-maps-with-mermaidjs) + +24 July 2023 · 4 mins + +Introducing the concept of mind mapping as a tool for organizing complex information, and highlights Mermaid as a user-friendly software that simplifies the creation and editing of mind maps for applications in IT solution design, business decision-making, and knowledge organization. + +## [Mermaid Chart Announces Visual Studio Code Plugin to Simplify Development Workflows](https://www.mermaidchart.com/blog/posts/mermaid-chart-announces-visual-studio-code-plugin) + +17 July 2023 · 3 mins + +New Integration Enhances Workflows By Enabling Developers To Reference And Edit Diagrams Within Visual Studio Code. + +## [Mermaid Chart’s ChatGPT Plugin Combines Generative AI and Smart Diagramming For Users](https://www.mermaidchart.com/blog/posts/mermaid-chart-chatgpt-plugin-combines-generative-ai-and-smart-diagramming) + +29 June 2023 · 4 mins + +Mermaid Chart’s new ChatGPT plugin integrates AI-powered text prompts with Mermaid’s intuitive diagramming editor, enabling users to generate, edit, and share complex diagrams with ease and efficiency. + +## [Sequence diagrams, the only good thing UML brought to software development](https://www.mermaidchart.com/blog/posts/sequence-diagrams-the-good-thing-uml-brought-to-software-development/) + +15 June 2023 · 12 mins + +Sequence diagrams really shine when you’re documenting different parts of a system and the various ways these parts interact with each other. + +## [subhash-halder contributed quadrant charts so you can show your manager what to select - just like the strategy consultants at BCG do](https://www.mermaidchart.com/blog/posts/subhash-halder-contributed-quadrant-charts-so-you-can-show-your-manager-what-to-select-just-like-the-strategy-consultants-at-bcg-do/) + +8 June 2023 · 7 mins + +A quadrant chart is a useful diagram that helps users visualize data and identify patterns in a data set. + +## [Bad documentation is bad for developers](https://www.mermaidchart.com/blog/posts/bad-documentation-is-bad-for-developers) + +26 April 2023 · 11 mins + +Documentation tends to be bad because companies and projects don’t fully realize the costs of bad documentation. + +## [Automatic text wrapping in flowcharts is here!](https://www.mermaidchart.com/blog/posts/automatic-text-wrapping-in-flowcharts-is-here/) + +3 April 2023 · 3 mins + +Markdown Strings reduce the hassle # Starting from v10. + +## [Mermaid Chart officially launched with sharable diagram links and presentation mode](https://www.mermaidchart.com/blog/posts/mermaid-chart-officially-launched-with-sharable-diagram-links-and-presentation-mode/) + +27 March 2023 · 2 mins + +Exciting news for all Mermaid OSS fans: Mermaid Chart has officially launched with Mermaid Chart! + +## [If you're not excited about ChatGPT, then you're not being creative](https://www.mermaidchart.com/blog/posts/if-youre-not-excited-about-chatgpt-then-youre-not-being-creative-enough/) + +8 March 2023 · 9 mins + +The hype around AI in general and ChatGPT, in particular, is so intense that it’s very understandable to assume the hype train is driving straight toward the trough of disillusionment. + +## [Flow charts are O(n)2 complex, so don't go over 100 connections](https://www.mermaidchart.com/blog/posts/flow-charts-are-on2-complex-so-dont-go-over-100-connections/) + +1 March 2023 · 12 mins + +Flowchart design is a game of balance: Read about the importance of dialling in the right level of detail and how to manage complexity in large flowcharts. + +## [Busting the myth that developers can't write](https://www.mermaidchart.com/blog/posts/busting-the-myth-that-developers-cant-write/) + +10 February 2023 · 10 mins + +Busting the myth that developers can’t write # It’s an annoying stereotype that developers don’t know how to write, speak, and otherwise communicate. diff --git a/packages/mermaid/src/docs/package.json b/packages/mermaid/src/docs/package.json new file mode 100644 index 000000000..742a28c0a --- /dev/null +++ b/packages/mermaid/src/docs/package.json @@ -0,0 +1,38 @@ +{ + "name": "docs", + "private": true, + "type": "module", + "scripts": { + "dev": "vitepress --port 3333 --open", + "dev:docker": "vitepress --port 3333 --host", + "build": "pnpm prefetch && vitepress build", + "build-no-prefetch": "vitepress build", + "serve": "vitepress serve", + "preview-https": "pnpm build && serve .vitepress/dist", + "preview-https-no-prefetch": "pnpm build-no-prefetch && serve .vitepress/dist", + "prefetch": "pnpm fetch-contributors && pnpm fetch-avatars", + "fetch-avatars": "ts-node-esm .vitepress/scripts/fetch-avatars.ts", + "fetch-contributors": "ts-node-esm .vitepress/scripts/fetch-contributors.ts" + }, + "dependencies": { + "@vueuse/core": "^10.1.0", + "jiti": "^1.18.2", + "vue": "^3.3", + "mermaid": "workspace:^" + }, + "devDependencies": { + "@iconify-json/carbon": "^1.1.16", + "@unocss/reset": "^0.55.2", + "@vite-pwa/vitepress": "^0.2.0", + "@vitejs/plugin-vue": "^4.2.1", + "fast-glob": "^3.2.12", + "https-localhost": "^4.7.1", + "pathe": "^1.1.0", + "unocss": "^0.55.2", + "unplugin-vue-components": "^0.25.0", + "vite": "^4.3.9", + "vite-plugin-pwa": "^0.16.0", + "vitepress": "1.0.0-rc.10", + "workbox-window": "^7.0.0" + } +} diff --git a/packages/mermaid/src/docs/public/favicon.ico b/packages/mermaid/src/docs/public/favicon.ico index d41818c5b..05d8a737b 100644 Binary files a/packages/mermaid/src/docs/public/favicon.ico and b/packages/mermaid/src/docs/public/favicon.ico differ diff --git a/packages/mermaid/src/docs/syntax/c4c.md b/packages/mermaid/src/docs/syntax/c4.md similarity index 88% rename from packages/mermaid/src/docs/syntax/c4c.md rename to packages/mermaid/src/docs/syntax/c4.md index 78528f7b9..be13323ea 100644 --- a/packages/mermaid/src/docs/syntax/c4c.md +++ b/packages/mermaid/src/docs/syntax/c4.md @@ -2,7 +2,7 @@ > C4 Diagram: This is an experimental diagram for now. The syntax and properties can change in future releases. Proper documentation will be provided when the syntax is stable. -Mermaid's c4 diagram syntax is compatible with plantUML. See example below: +Mermaid's C4 diagram syntax is compatible with plantUML. See example below: ```mermaid-example C4Context @@ -61,7 +61,7 @@ For an example, see the source code demos/index.html - Dynamic diagram (C4Dynamic) - Deployment diagram (C4Deployment) -Please refer to the linked document [C4-PlantUML syntax](https://github.com/plantuml-stdlib/C4-PlantUML/blob/master/README.md) for how to write the c4 diagram. +Please refer to the linked document [C4-PlantUML syntax](https://github.com/plantuml-stdlib/C4-PlantUML/blob/master/README.md) for how to write the C4 diagram. C4 diagram is fixed style, such as css color, so different css is not provided under different skins. updateElementStyle and UpdateElementStyle are written in the diagram last part. updateElementStyle is inconsistent with the original definition and updates the style of the relationship, including the offset of the text label relative to the original position. @@ -70,10 +70,10 @@ The layout does not use a fully automated layout algorithm. The position of shap The number of shapes per row and the number of boundaries can be adjusted using UpdateLayoutConfig. - Layout -- - Lay_U, Lay_Up -- - Lay_D, Lay_Down -- - Lay_L, Lay_Left -- - Lay_R, Lay_Right + - Lay_U, Lay_Up + - Lay_D, Lay_Down + - Lay_L, Lay_Left + - Lay_R, Lay_Right The following unfinished features are not supported in the short term. @@ -83,65 +83,71 @@ The following unfinished features are not supported in the short term. - [ ] Legend - [x] System Context -- - [x] Person(alias, label, ?descr, ?sprite, ?tags, $link) -- - [x] Person_Ext -- - [x] System(alias, label, ?descr, ?sprite, ?tags, $link) -- - [x] SystemDb -- - [x] SystemQueue -- - [x] System_Ext -- - [x] SystemDb_Ext -- - [x] SystemQueue_Ext -- - [x] Boundary(alias, label, ?type, ?tags, $link) -- - [x] Enterprise_Boundary(alias, label, ?tags, $link) -- - [x] System_Boundary + + - [x] Person(alias, label, ?descr, ?sprite, ?tags, $link) + - [x] Person_Ext + - [x] System(alias, label, ?descr, ?sprite, ?tags, $link) + - [x] SystemDb + - [x] SystemQueue + - [x] System_Ext + - [x] SystemDb_Ext + - [x] SystemQueue_Ext + - [x] Boundary(alias, label, ?type, ?tags, $link) + - [x] Enterprise_Boundary(alias, label, ?tags, $link) + - [x] System_Boundary - [x] Container diagram -- - [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) -- - [x] ContainerDb -- - [x] ContainerQueue -- - [x] Container_Ext -- - [x] ContainerDb_Ext -- - [x] ContainerQueue_Ext -- - [x] Container_Boundary(alias, label, ?tags, $link) + + - [x] Container(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) + - [x] ContainerDb + - [x] ContainerQueue + - [x] Container_Ext + - [x] ContainerDb_Ext + - [x] ContainerQueue_Ext + - [x] Container_Boundary(alias, label, ?tags, $link) - [x] Component diagram -- - [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) -- - [x] ComponentDb -- - [x] ComponentQueue -- - [x] Component_Ext -- - [x] ComponentDb_Ext -- - [x] ComponentQueue_Ext + + - [x] Component(alias, label, ?techn, ?descr, ?sprite, ?tags, $link) + - [x] ComponentDb + - [x] ComponentQueue + - [x] Component_Ext + - [x] ComponentDb_Ext + - [x] ComponentQueue_Ext - [x] Dynamic diagram -- - [x] RelIndex(index, from, to, label, ?tags, $link) + + - [x] RelIndex(index, from, to, label, ?tags, $link) - [x] Deployment diagram -- - [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link) -- - [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node() -- - [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node() -- - [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node() + + - [x] Deployment_Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link) + - [x] Node(alias, label, ?type, ?descr, ?sprite, ?tags, $link): short name of Deployment_Node() + - [x] Node_L(alias, label, ?type, ?descr, ?sprite, ?tags, $link): left aligned Node() + - [x] Node_R(alias, label, ?type, ?descr, ?sprite, ?tags, $link): right aligned Node() - [x] Relationship Types -- - [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link) -- - [x] BiRel (bidirectional relationship) -- - [x] Rel_U, Rel_Up -- - [x] Rel_D, Rel_Down -- - [x] Rel_L, Rel_Left -- - [x] Rel_R, Rel_Right -- - [x] Rel_Back -- - [x] RelIndex \* Compatible with C4-Plantuml syntax, but ignores the index parameter. The sequence number is determined by the order in which the rel statements are written. + + - [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link) + - [x] BiRel (bidirectional relationship) + - [x] Rel_U, Rel_Up + - [x] Rel_D, Rel_Down + - [x] Rel_L, Rel_Left + - [x] Rel_R, Rel_Right + - [x] Rel_Back + - [x] RelIndex \* Compatible with C4-Plantuml syntax, but ignores the index parameter. The sequence number is determined by the order in which the rel statements are written. - [ ] Custom tags/stereotypes support and skin param updates -- - [ ] AddElementTag(tagStereo, ?bgColor, ?fontColor, ?borderColor, ?shadowing, ?shape, ?sprite, ?techn, ?legendText, ?legendSprite): Introduces a new element tag. The styles of the tagged elements are updated and the tag is displayed in the calculated legend. -- - [ ] AddRelTag(tagStereo, ?textColor, ?lineColor, ?lineStyle, ?sprite, ?techn, ?legendText, ?legendSprite): Introduces a new Relationship tag. The styles of the tagged relationships are updated and the tag is displayed in the calculated legend. -- - [x] UpdateElementStyle(elementName, ?bgColor, ?fontColor, ?borderColor, ?shadowing, ?shape, ?sprite, ?techn, ?legendText, ?legendSprite): This call updates the default style of the elements (component, ...) and creates no additional legend entry. -- - [x] UpdateRelStyle(from, to, ?textColor, ?lineColor, ?offsetX, ?offsetY): This call updates the default relationship colors and creates no additional legend entry. Two new parameters, offsetX and offsetY, are added to set the offset of the original position of the text. -- - [ ] RoundedBoxShape(): This call returns the name of the rounded box shape and can be used as ?shape argument. -- - [ ] EightSidedShape(): This call returns the name of the eight sided shape and can be used as ?shape argument. -- - [ ] DashedLine(): This call returns the name of the dashed line and can be used as ?lineStyle argument. -- - [ ] DottedLine(): This call returns the name of the dotted line and can be used as ?lineStyle argument. -- - [ ] BoldLine(): This call returns the name of the bold line and can be used as ?lineStyle argument. -- - [x] UpdateLayoutConfig(?c4ShapeInRow, ?c4BoundaryInRow): New. This call updates the default c4ShapeInRow(4) and c4BoundaryInRow(2). + - [ ] AddElementTag(tagStereo, ?bgColor, ?fontColor, ?borderColor, ?shadowing, ?shape, ?sprite, ?techn, ?legendText, ?legendSprite): Introduces a new element tag. The styles of the tagged elements are updated and the tag is displayed in the calculated legend. + - [ ] AddRelTag(tagStereo, ?textColor, ?lineColor, ?lineStyle, ?sprite, ?techn, ?legendText, ?legendSprite): Introduces a new Relationship tag. The styles of the tagged relationships are updated and the tag is displayed in the calculated legend. + - [x] UpdateElementStyle(elementName, ?bgColor, ?fontColor, ?borderColor, ?shadowing, ?shape, ?sprite, ?techn, ?legendText, ?legendSprite): This call updates the default style of the elements (component, ...) and creates no additional legend entry. + - [x] UpdateRelStyle(from, to, ?textColor, ?lineColor, ?offsetX, ?offsetY): This call updates the default relationship colors and creates no additional legend entry. Two new parameters, offsetX and offsetY, are added to set the offset of the original position of the text. + - [ ] RoundedBoxShape(): This call returns the name of the rounded box shape and can be used as ?shape argument. + - [ ] EightSidedShape(): This call returns the name of the eight sided shape and can be used as ?shape argument. + - [ ] DashedLine(): This call returns the name of the dashed line and can be used as ?lineStyle argument. + - [ ] DottedLine(): This call returns the name of the dotted line and can be used as ?lineStyle argument. + - [ ] BoldLine(): This call returns the name of the bold line and can be used as ?lineStyle argument. + - [x] UpdateLayoutConfig(?c4ShapeInRow, ?c4BoundaryInRow): New. This call updates the default c4ShapeInRow(4) and c4BoundaryInRow(2). There are two ways to assign parameters with question marks. One uses the non-named parameter assignment method in the order of the parameters, and the other uses the named parameter assignment method, where the name must start with a $ symbol. diff --git a/packages/mermaid/src/docs/syntax/classDiagram.md b/packages/mermaid/src/docs/syntax/classDiagram.md index 10ccc3522..4b0cd49de 100644 --- a/packages/mermaid/src/docs/syntax/classDiagram.md +++ b/packages/mermaid/src/docs/syntax/classDiagram.md @@ -74,7 +74,27 @@ classDiagram Vehicle <|-- Car ``` -Naming convention: a class name should be composed only of alphanumeric characters (including unicode), and underscores. +Naming convention: a class name should be composed only of alphanumeric characters (including unicode), underscores, and dashes (-). + +### Class labels + +In case you need to provide a label for a class, you can use the following syntax: + +```mermaid-example +classDiagram + class Animal["Animal with a label"] + class Car["Car with *! symbols"] + Animal --> Car +``` + +You can also use backticks to escape special characters in the label: + +```mermaid-example +classDiagram + class `Animal Class!` + class `Car Class` + `Animal Class!` --> `Car Class` +``` ## Defining Members of a class @@ -151,12 +171,12 @@ To describe the visibility (or encapsulation) of an attribute or method/function - `#` Protected - `~` Package/Internal -> _note_ you can also include additional _classifiers_ to a method definition by adding the following notation to the _end_ of the method, i.e.: after the `()`: +> _note_ you can also include additional _classifiers_ to a method definition by adding the following notation to the _end_ of the method, i.e.: after the `()` or after the return type: > -> - `*` Abstract e.g.: `someAbstractMethod()*` -> - `$` Static e.g.: `someStaticMethod()$` +> - `*` Abstract e.g.: `someAbstractMethod()*` or `someAbstractMethod() int*` +> - `$` Static e.g.: `someStaticMethod()$` or `someStaticMethod() String$` -> _note_ you can also include additional _classifiers_ to a field definition by adding the following notation to the end of its name: +> _note_ you can also include additional _classifiers_ to a field definition by adding the following notation to the very end: > > - `$` Static e.g.: `String someField$` @@ -228,7 +248,7 @@ classE o-- classF : aggregation Relations can logically represent an N:M association: -```mmd +```mermaid classDiagram Animal <|--|> Zebra ``` @@ -257,6 +277,23 @@ And `Link` can be one of: | -- | Solid | | .. | Dashed | +## Define Namespace + +A namespace groups classes. + +Code: + +```mermaid-example +classDiagram +namespace BaseShapes { + class Triangle + class Rectangle { + double width + double height + } +} +``` + ## Cardinality / Multiplicity on relations Multiplicity or cardinality in class diagrams indicates the number of instances of one class that can be linked to an instance of the other class. For example, each company will have one or more employees (not zero), and each employee currently works for zero or one companies. @@ -331,7 +368,7 @@ class Color{ Comments can be entered within a class 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 until the next newline will be treated as a comment, including any class diagram syntax. -```mmd +```mermaid classDiagram %% This whole line is a comment classDiagram class Shape <<interface>> class Shape{ @@ -383,13 +420,21 @@ click className href "url" "tooltip" ## Notes -It is possible to add notes on diagram using `note "line1\nline2"` or note for class using `note for class "line1\nline2"` +It is possible to add notes on the diagram using `note "line1\nline2"`. A note can be added for a specific class using `note for <CLASS NAME> "line1\nline2"`. ### Examples +```mermaid +classDiagram + note "This is a general note" + note for MyClass "This is a note for a class" + class MyClass{ + } +``` + _URL Link:_ -```mmd +```mermaid classDiagram class Shape link Shape "https://www.github.com" "This is a tooltip for a link" @@ -399,7 +444,7 @@ click Shape2 href "https://www.github.com" "This is a tooltip for a link" _Callback:_ -```mmd +```mermaid classDiagram class Shape callback Shape "callbackFunction" "This is a tooltip for a callback" @@ -477,11 +522,11 @@ Beginner's tip—a full example using interactive links in an HTML page: ### Styling a node -It is possible to apply specific styles such as a thicker border or a different background color to individual nodes. This is done by predefining classes in css styles that can be applied from the graph definition: +It is possible to apply specific styles such as a thicker border or a different background color to individual nodes. 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. ```html <style> - .cssClass > rect { + .styleClass > rect { fill: #ff0000; stroke: #ffff00; stroke-width: 4px; @@ -492,27 +537,27 @@ It is possible to apply specific styles such as a thicker border or a different Then attaching that class to a specific node: ``` - cssClass "nodeId1" cssClass; + cssClass "nodeId1" styleClass; ``` It is also possible to attach a class to a list of nodes in one statement: ``` - cssClass "nodeId1,nodeId2" cssClass; + cssClass "nodeId1,nodeId2" styleClass; ``` A shorter form of adding a class is to attach the classname to the node using the `:::` operator: ```mermaid-example classDiagram - class Animal:::cssClass + class Animal:::styleClass ``` Or: ```mermaid-example classDiagram - class Animal:::cssClass { + class Animal:::styleClass { -int sizeInFeet -canEat() } diff --git a/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md b/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md index 7067a65d9..82c6f1e48 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 and may also contain digits, hyphens, and underscores. +- `first-entity` is the name of an entity. Names must begin with an alphabetic character or an underscore (from v<MERMAID_RELEASE_VERSION>+), and may also contain digits and hyphens. - `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. @@ -116,7 +116,7 @@ Relationships may be classified as either _identifying_ or _non-identifying_ and | to | _identifying_ | | optionally to | _non-identifying_ | -```mmd +```mermaid erDiagram CAR ||--o{ NAMED-DRIVER : allows PERSON ||--o{ NAMED-DRIVER : is @@ -142,7 +142,23 @@ erDiagram } ``` -The `type` and `name` values must begin with an alphabetic character and may contain digits, hyphens, underscores, parentheses and square brackets. Other than that, there are no restrictions, and there is no implicit set of valid data types. +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 (v<MERMAID_RELEASE_VERSION>+) + +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. + +```mermaid-example +erDiagram + p[Person] { + string firstName + string lastName + } + a["Customer Account"] { + string email + } + p ||--o| a : has +``` #### Attribute Keys and Comments diff --git a/packages/mermaid/src/docs/syntax/flowchart.md b/packages/mermaid/src/docs/syntax/flowchart.md index 5896e0518..a49e974ab 100644 --- a/packages/mermaid/src/docs/syntax/flowchart.md +++ b/packages/mermaid/src/docs/syntax/flowchart.md @@ -5,11 +5,11 @@ outline: 'deep' # shows all h3 headings in outline in Vitepress # Flowcharts - Basic Syntax -All Flowcharts are composed of **nodes**, the geometric shapes and **edges**, the arrows or lines. The mermaid code defines the way that these **nodes** and **edges** are made and interact. +Flowcharts are composed of **nodes** (geometric shapes) and **edges** (arrows or lines). The Mermaid code defines how nodes and edges are made and accommodates different arrow types, multi-directional arrows, and any linking to and from subgraphs. -It can also accommodate different arrow types, multi directional arrows, and linking to and from subgraphs. - -> **Important note**: Do not type the word "end" as a Flowchart node. Capitalize all or any one the letters to keep the flowchart from breaking, i.e, "End" or "END". Or you can apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897). +```warning +If you are using the word "end" in a Flowchart node, capitalize the entire word or any of the letters (e.g., "End" or "END"), or apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897). Typing "end" in all lowercase letters will break the Flowchart. +``` ### A node (default) @@ -25,6 +25,10 @@ flowchart LR The id is what is displayed in the box. ``` +```tip +Instead of `flowchart` one can also use `graph`. +``` + ### A node with text It is also possible to set text in the box that differs from the id. If this is done several times, it is the last text @@ -39,7 +43,30 @@ flowchart LR id1[This is the text in the box] ``` -## Graph +#### Unicode text + +Use `"` to enclose the unicode text. + +```mermaid-example +flowchart LR + id["This ❤ Unicode"] +``` + +#### Markdown formatting + +Use double quotes and backticks "\` text \`" to enclose the markdown text. + +```mermaid-example +%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart LR + markdown["`This **is** _Markdown_`"] + newLines["`Line1 + Line 2 + Line 3`"] + markdown --> newLines +``` + +### Direction This statement declares the direction of the Flowchart. @@ -57,15 +84,13 @@ flowchart LR Start --> Stop ``` -## Flowchart Orientation - Possible FlowChart orientations are: -- TB - top to bottom -- TD - top-down/ same as top to bottom -- BT - bottom to top -- RL - right to left -- LR - left to right +- TB - Top to bottom +- TD - Top-down/ same as top to bottom +- BT - Bottom to top +- RL - Right to left +- LR - Left to right ## Node shapes @@ -122,16 +147,7 @@ flowchart LR ### A hexagon node -Code: - -```mmd -flowchart LR - id1{{This is the text in the box}} -``` - -Render: - -```mermaid +```mermaid-example flowchart LR id1{{This is the text in the box}} ``` @@ -245,6 +261,15 @@ flowchart LR A == text ==> B ``` +### An invisible link + +This can be a useful tool in some instances where you want to alter the default positioning of a node. + +```mermaid-example +flowchart LR + A ~~~ B +``` + ### Chaining of links It is possible declare many links in the same line as per below: @@ -273,7 +298,7 @@ word of warning, one could go overboard with this making the flowchart harder to markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little. This goes for expressive syntaxes as well. -```mmd +```mermaid flowchart TB A --> C A --> D @@ -365,7 +390,7 @@ It is possible to escape characters using the syntax exemplified here. ```mermaid-example flowchart LR - A["A double quote:#quot;"] -->B["A dec char:#9829;"] + A["A double quote:#quot;"] --> B["A dec char:#9829;"] ``` Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names. @@ -404,7 +429,7 @@ flowchart TB end ``` -## flowcharts +### flowcharts With the graphtype flowchart it is also possible to set edges to and from subgraphs as in the flowchart below. @@ -425,7 +450,7 @@ flowchart TB two --> c2 ``` -## Direction in subgraphs +### Direction in subgraphs With the graphtype flowcharts you can use the direction statement to set the direction which the subgraph will render like in this example. @@ -446,9 +471,61 @@ flowchart LR B1 --> B2 ``` +#### Limitation + +If any of a subgraph's nodes are linked to the outside, subgraph direction will be ignored. Instead the subgraph will inherit the direction of the parent graph: + +```mermaid-example +flowchart LR + subgraph subgraph1 + direction TB + top1[top] --> bottom1[bottom] + end + subgraph subgraph2 + direction TB + top2[top] --> bottom2[bottom] + end + %% ^ These subgraphs are identical, except for the links to them: + + %% Link *to* subgraph1: subgraph1 direction is mantained + outside --> subgraph1 + %% Link *within* subgraph2: + %% subgraph2 inherits the direction of the top-level graph (LR) + outside ---> top2 +``` + +## Markdown Strings + +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}} }%% +flowchart LR +subgraph "One" + a("`The **cat** + in the hat`") -- "edge label" --> b{{"`The **dog** in the hog`"}} +end +subgraph "`**Two**`" + c("`The **cat** + in the hat`") -- "`Bold **edge label**`" --> d("The dog in the hog") +end +``` + +Formatting: + +- For bold text, use double asterisks (`**`) before and after the text. +- For italics, use single asterisks (`*`) before and after the text. +- With traditional strings, you needed to add `<br>` tags for text to wrap in nodes. However, markdown strings automatically wrap text when it becomes too long and allows you to start a new line by simply using a newline character instead of a `<br>` tag. + +This feature is applicable to node labels, edge labels, and subgraph labels. + ## Interaction -It is possible to bind a click event to a node, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`. +It is possible to bind a click event to a node, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab. + +```note +This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`. +``` ``` click nodeId callback @@ -532,7 +609,7 @@ Beginner's tip—a full example using interactive links in a html context: Comments can be entered within a flow 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 flow syntax -```mmd +```mermaid flowchart LR %% this is a comment A -- text --> B{node} A -- text --> B -- text2 --> C @@ -551,6 +628,12 @@ In the example below the style defined in the linkStyle statement will belong to linkStyle 3 stroke:#ff3,stroke-width:4px,color:red; ``` +It is also possible to add style to multiple links in a single statement, by separating link numbers with commas: + +``` +linkStyle 1,2,7 color:blue; +``` + ### Styling line curves It is possible to style the type of curve used for lines between items, if the default method does not meet your needs. @@ -584,12 +667,18 @@ flowchart LR 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: +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: ``` @@ -610,9 +699,19 @@ flowchart LR classDef someclass fill:#f96 ``` -### Css classes +This form can be used when declaring multiple links between nodes: -It is also possible to predefine classes in css styles that can be applied from the graph definition as in the example +```mermaid-example +flowchart LR + A:::foo & B:::bar --> C:::foobar + classDef foo stroke:#f00 + classDef bar stroke:#0f0 + classDef foobar stroke:#00f +``` + +### 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** @@ -652,13 +751,13 @@ The icons are accessed via the syntax fa:#icon class name#. ```mermaid-example flowchart TD - B["fab:fa-twitter for peace"] + B["fa:fa-twitter for peace"] B-->C[fa:fa-ban forbidden] B-->D(fa:fa-spinner) B-->E(A fa:fa-camera-retro perhaps?) ``` -?> Mermaid is now only compatible with Font Awesome versions 4 and 5. Check that you are using the correct version of Font Awesome. +Mermaid is compatible with Font Awesome up to verion 5, Free icons only. Check that the icons you use are from the [supported set of icons](https://fontawesome.com/v5/search?o=r&m=free). ## Graph declarations with spaces between vertices and link and without semicolon @@ -691,7 +790,9 @@ You can change the renderer to elk by adding this directive: %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% ``` +```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. +``` ### Width diff --git a/packages/mermaid/src/docs/syntax/gantt.md b/packages/mermaid/src/docs/syntax/gantt.md index 0cc915ca1..a0cebc560 100644 --- a/packages/mermaid/src/docs/syntax/gantt.md +++ b/packages/mermaid/src/docs/syntax/gantt.md @@ -19,13 +19,13 @@ Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pas ```mermaid-example gantt title A Gantt Diagram - dateFormat YYYY-MM-DD + dateFormat YYYY-MM-DD section Section - A task :a1, 2014-01-01, 30d - Another task :after a1 , 20d + A task :a1, 2014-01-01, 30d + Another task :after a1, 20d section Another - Task in sec :2014-01-12 , 12d - another task : 24d + Task in Another :2014-01-12, 12d + another task :24d ``` ## Syntax @@ -66,10 +66,10 @@ gantt It is possible to set multiple dependencies separated by space: ```mermaid-example - gantt - apple :a, 2017-07-20, 1w - banana :crit, b, 2017-07-23, 1d - cherry :active, c, after b a, 1d +gantt + apple :a, 2017-07-20, 1w + banana :crit, b, 2017-07-23, 1d + cherry :active, c, after b a, 1d ``` ### Title @@ -88,12 +88,12 @@ You can add milestones to the diagrams. Milestones differ from tasks as they rep ```mermaid-example gantt -dateFormat HH:mm -axisFormat %H:%M -Initial milestone : milestone, m1, 17:49,2min -taska2 : 10min -taska3 : 5min -Final milestone : milestone, m2, 18:14, 2min + dateFormat HH:mm + axisFormat %H:%M + Initial milestone : milestone, m1, 17:49, 2m + Task A : 10m + Task B : 5m + Final milestone : milestone, m2, 18:08, 4m ``` ## Setting dates @@ -116,7 +116,7 @@ The following formatting options are supported: | `YY` | 14 | 2 digit year | | `Q` | 1..4 | Quarter of year. Sets month to first month in quarter. | | `M MM` | 1..12 | Month number | -| `MMM MMMM` | January..Dec | Month name in locale set by `moment.locale()` | +| `MMM MMMM` | January..Dec | Month name in locale set by `dayjs.locale()` | | `D DD` | 1..31 | Day of month | | `Do` | 1st..31st | Day of month with ordinal | | `DDD DDDD` | 1..365 | Day of year | @@ -132,7 +132,7 @@ The following formatting options are supported: | `SSS` | 0..999 | Thousandths of a second | | `Z ZZ` | +12:00 | Offset from UTC as +-HH:mm, +-HHmm, or Z | -More info in: https://momentjs.com/docs/#/parsing/string-format/ +More info in: https://day.js.org/docs/en/parse/string-format/ ### Output date format on the axis @@ -173,7 +173,7 @@ The following formatting strings are supported: More info in: [https://github.com/d3/d3-time-format/tree/v4.0.0#locale_format](https://github.com/d3/d3-time-format/tree/v4.0.0#locale_format) -### Axis ticks +### Axis ticks (v10.3.0+) The default output ticks are auto. You can custom your `tickInterval`, like `1day` or `1week`. @@ -184,27 +184,56 @@ tickInterval 1day The pattern is: ```javascript -/^([1-9][0-9]*)(minute|hour|day|week|month)$/; +/^([1-9][0-9]*)(millisecond|second|minute|hour|day|week|month)$/; ``` More info in: [https://github.com/d3/d3-time#interval_every](https://github.com/d3/d3-time#interval_every) -## Comments +Week-based `tickInterval`s start the week on sunday by default. If you wish to specify another weekday on which the `tickInterval` should start, use the `weekday` option: -Comments can be entered within a gantt chart, 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-example +gantt + tickInterval 1week + weekday monday +``` -```mmd +```warning +`millisecond` and `second` support was added in vMERMAID_RELEASE_VERSION +``` + +## Output in compact mode + +The compact mode allows you to display multiple tasks in the same row. Compact mode can be enabled for a gantt chart by setting the display mode of the graph via preceeding YAML settings. + +```mermaid +--- +displayMode: compact +--- gantt title A Gantt Diagram - %% this is a comment dateFormat YYYY-MM-DD + section Section A task :a1, 2014-01-01, 30d - Another task :after a1 , 20d - section Another - Task in sec :2014-01-12 , 12d - another task : 24d + Another task :a2, 2014-01-20, 25d + Another one :a3, 2014-02-10, 20d +``` +## Comments + +Comments can be entered within a gantt chart, 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 +gantt + title A Gantt Diagram + %% This is a comment + dateFormat YYYY-MM-DD + section Section + A task :a1, 2014-01-01, 30d + Another task :after a1, 20d + section Another + Task in Another :2014-01-12, 12d + another task :24d ``` ## Styling @@ -332,7 +361,7 @@ Beginner's tip—a full example using interactive links in an html context: dateFormat YYYY-MM-DD section Clickable - Visit mermaidjs :active, cl1, 2014-01-07, 3d + Visit mermaidjs :active, cl1, 2014-01-07, 3d Print arguments :cl2, after cl1, 3d Print task :cl3, after cl2, 3d @@ -356,3 +385,24 @@ Beginner's tip—a full example using interactive links in an html context: </script> </body> ``` + +## Examples + +### Bar chart (using gantt chart) + +```mermaid-example +gantt + title Git Issues - days since last update + dateFormat X + axisFormat %s + section Issue19062 + 71 : 0, 71 + section Issue19401 + 36 : 0, 36 + section Issue193 + 34 : 0, 34 + section Issue7441 + 9 : 0, 9 + section Issue1300 + 5 : 0, 5 +``` diff --git a/packages/mermaid/src/docs/syntax/gitgraph.md b/packages/mermaid/src/docs/syntax/gitgraph.md index f1930bb27..87f43afdd 100644 --- a/packages/mermaid/src/docs/syntax/gitgraph.md +++ b/packages/mermaid/src/docs/syntax/gitgraph.md @@ -511,6 +511,50 @@ NOTE: Because we have overridden the `mainBranchOrder` to `2`, the `main` branch Here, we have changed the default main branch name to `MetroLine1`. +## Orientation (v10.3.0+) + +In Mermaid, the default orientation is Left to Right. The branches are lined vertically. + +Usage example: + +```mermaid-example + gitGraph + commit + commit + branch develop + commit + commit + commit + checkout main + commit + commit + merge develop + commit + commit +``` + +Sometimes we may want to change the orientation. Currently, Mermaid supports two orientations: **Left to Right**(default) and **Top to Bottom**. + +In order to change the orientation from top to bottom i.e. branches lined horizontally, you need to add `TB` along with `gitGraph`. + +Usage example: + +```mermaid-example + gitGraph TB: + commit + commit + branch develop + commit + commit + commit + checkout main + commit + commit + merge develop + commit + commit +``` + ## 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). diff --git a/packages/mermaid/src/docs/syntax/img/zenuml-participant-annotators.png b/packages/mermaid/src/docs/syntax/img/zenuml-participant-annotators.png new file mode 100644 index 000000000..13789371f Binary files /dev/null and b/packages/mermaid/src/docs/syntax/img/zenuml-participant-annotators.png differ diff --git a/packages/mermaid/src/docs/syntax/mindmap.md b/packages/mermaid/src/docs/syntax/mindmap.md index c8a252691..18a3f17cc 100644 --- a/packages/mermaid/src/docs/syntax/mindmap.md +++ b/packages/mermaid/src/docs/syntax/mindmap.md @@ -31,7 +31,7 @@ mindmap The syntax for creating Mindmaps is simple and relies on indentation for setting the levels in the hierarchy. -In the following example you can see how there are 3 different levels. One with starting at the left of the text and another level with two rows starting at the same column, defining the node A. At the end there is one more level where the text is indented further then the previous lines defining the nodes B and C. +In the following example you can see how there are 3 different levels. One with starting at the left of the text and another level with two rows starting at the same column, defining the node A. At the end there is one more level where the text is indented further than the previous lines defining the nodes B and C. ``` mindmap @@ -41,7 +41,7 @@ mindmap C ``` -In summary is a simple text outline where there are one node at the root level called `Root` which has one child `A`. `A` in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. +In summary is a simple text outline where there is one node at the root level called `Root` which has one child `A`. `A` in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap. ```mermaid mindmap @@ -114,7 +114,7 @@ More shapes will be added, beginning with the shapes available in flowcharts. ## Icons -As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parenthesis like in the following example where icons for material design and fontawesome 4 are displayed. The intention is that this approach should be used for all diagrams supporting icons. **Experimental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. +As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parenthesis like in the following example where icons for material design and [Font Awesome 5](https://fontawesome.com/v5/search?o=r&m=free) are displayed. The intention is that this approach should be used for all diagrams supporting icons. **Experimental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change. ```mermaid-example mindmap @@ -138,11 +138,11 @@ mindmap C ``` -_These classes needs top be supplied by the site administrator._ +_These classes need to be supplied by the site administrator._ ## Unclear indentation -The actual indentation does not really matter only compared with the previous rows. If we take the previous example and disrupt it a little we can se how the calculations are performed. Let us start with placing C with a smaller indentation than `B`but larger then `A`. +The actual indentation does not really matter only compared with the previous rows. If we take the previous example and disrupt it a little we can see how the calculations are performed. Let us start with placing C with a smaller indentation than `B` but larger then `A`. ``` mindmap @@ -162,6 +162,25 @@ Root C ``` +## Markdown Strings + +The "Markdown Strings" feature enhances 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 +mindmap + id1["`**Root** with +a second line +Unicode works too: 🤓`"] + id2["`The dog in **the** hog... a *very long text* that wraps to a new line`"] + id3[Regular labels still works] +``` + +Formatting: + +- For bold text, use double asterisks \*\* before and after the text. +- For italics, use single asterisks \* before and after the text. +- With traditional strings, you needed to add <br> tags for text to wrap in nodes. However, markdown strings automatically wrap text when it becomes too long and allows you to start a new line by simply using a newline character instead of a <br> tag. + ## Integrating with your library/website. Mindmap uses the experimental lazy loading & async rendering features which could change in the future. From version 9.4.0 this diagram is included in mermaid but use lazy loading in order to keep the size of mermaid down. This is important in order to be able to add additional diagrams going forward. diff --git a/packages/mermaid/src/docs/syntax/pie.md b/packages/mermaid/src/docs/syntax/pie.md index 2fe8c3e54..81ec720c4 100644 --- a/packages/mermaid/src/docs/syntax/pie.md +++ b/packages/mermaid/src/docs/syntax/pie.md @@ -35,6 +35,7 @@ Drawing a pie chart is really simple in mermaid. ## Example ```mermaid-example +%%{init: {"pie": {"textPosition": 0.5}, "themeVariables": {"pieOuterStrokeWidth": "5px"}} }%% pie showData title Key elements in Product X "Calcium" : 42.96 @@ -42,3 +43,11 @@ pie showData "Magnesium" : 10.01 "Iron" : 5 ``` + +## Configuration + +Possible pie diagram configuration parameters: + +| Parameter | Description | Default value | +| -------------- | ------------------------------------------------------------------------------------------------------------ | ------------- | +| `textPosition` | The axial position of the pie slice labels, from 0.0 at the center to 1.0 at the outside edge of the circle. | `0.75` | diff --git a/packages/mermaid/src/docs/syntax/quadrantChart.md b/packages/mermaid/src/docs/syntax/quadrantChart.md new file mode 100644 index 000000000..835bbfa32 --- /dev/null +++ b/packages/mermaid/src/docs/syntax/quadrantChart.md @@ -0,0 +1,138 @@ +# Quadrant Chart + +> A quadrant chart is a visual representation of data that is divided into four quadrants. It is used to plot data points on a two-dimensional grid, with one variable represented on the x-axis and another variable represented on the y-axis. The quadrants are determined by dividing the chart into four equal parts based on a set of criteria that is specific to the data being analyzed. Quadrant charts are often used to identify patterns and trends in data, and to prioritize actions based on the position of data points within the chart. They are commonly used in business, marketing, and risk management, among other fields. + +## Example + +```mermaid-example +quadrantChart + title Reach and engagement of campaigns + x-axis Low Reach --> High Reach + y-axis Low Engagement --> High Engagement + quadrant-1 We should expand + quadrant-2 Need to promote + quadrant-3 Re-evaluate + quadrant-4 May be improved + Campaign A: [0.3, 0.6] + Campaign B: [0.45, 0.23] + Campaign C: [0.57, 0.69] + Campaign D: [0.78, 0.34] + Campaign E: [0.40, 0.34] + Campaign F: [0.35, 0.78] +``` + +## Syntax + +```note +If there are no points available in the chart both **axis** text and **quadrant** will be rendered in the center of the respective quadrant. +If there are points **x-axis** labels will rendered from the left of the respective quadrant also they will be displayed at the bottom of the chart, and **y-axis** labels will be rendered at the bottom of the respective quadrant, the quadrant text will render at the top of the respective quadrant. +``` + +```note +For points x and y value min value is 0 and max value is 1. +``` + +### Title + +The title is a short description of the chart and it will always render on top of the chart. + +#### Example + +``` +quadrantChart + title This is a sample example +``` + +### x-axis + +The x-axis determines what text would be displayed in the x-axis. In x-axis there is two part **left** and **right** you can pass **both** or you can pass only **left**. The statement should start with `x-axis` then the `left axis text` followed by the delimiter `-->` then `right axis text`. + +#### Example + +1. `x-axis <text> --> <text>` both the left and right axis text will be rendered. +2. `x-axis <text>` only the left axis text will be rendered. + +### y-axis + +The y-axis determines what text would be displayed in the y-axis. In y-axis there is two part **top** and **bottom** you can pass **both** or you can pass only **bottom**. The statement should start with `y-axis` then the `bottom axis text` followed by the delimiter `-->` then `top axis text`. + +#### Example + +1. `y-axis <text> --> <text>` both the bottom and top axis text will be rendered. +2. `y-axis <text>` only the bottom axis text will be rendered. + +### Quadrants text + +The `quadrant-[1,2,3,4]` determine what text would be displayed inside the quadrants. + +#### Example + +1. `quadrant-1 <text>` determine what text will be rendered inside the top right quadrant. +2. `quadrant-2 <text>` determine what text will be rendered inside the top left quadrant. +3. `quadrant-3 <text>` determine what text will be rendered inside the bottom left quadrant. +4. `quadrant-4 <text>` determine what text will be rendered inside the bottom right quadrant. + +### Points + +Points are used to plot a circle inside the quadrantChart. The syntax is `<text>: [x, y]` here x and y value is in the range 0 - 1. + +#### Example + +1. `Point 1: [0.75, 0.80]` here the Point 1 will be drawn in the top right quadrant. +2. `Point 2: [0.35, 0.24]` here the Point 2 will be drawn in the bottom left quadrant. + +## Chart Configurations + +| Parameter | Description | Default value | +| --------------------------------- | ------------------------------------------------------------------------------------------------- | :-----------: | +| chartWidth | Width of the chart | 500 | +| chartHeight | Height of the chart | 500 | +| titlePadding | Top and Bottom padding of the title | 10 | +| titleFontSize | Title font size | 20 | +| quadrantPadding | Padding outside all the quadrants | 5 | +| quadrantTextTopPadding | Quadrant text top padding when text is drawn on top ( not data points are there) | 5 | +| quadrantLabelFontSize | Quadrant text font size | 16 | +| quadrantInternalBorderStrokeWidth | Border stroke width inside the quadrants | 1 | +| quadrantExternalBorderStrokeWidth | Quadrant external border stroke width | 2 | +| xAxisLabelPadding | Top and bottom padding of x-axis text | 5 | +| xAxisLabelFontSize | X-axis texts font size | 16 | +| xAxisPosition | Position of x-axis (top , bottom) if there are points the x-axis will alway be rendered in bottom | 'top' | +| yAxisLabelPadding | Left and Right padding of y-axis text | 5 | +| yAxisLabelFontSize | Y-axis texts font size | 16 | +| yAxisPosition | Position of y-axis (left , right) | 'left' | +| pointTextPadding | Padding between point and the below text | 5 | +| pointLabelFontSize | Point text font size | 12 | +| pointRadius | Radius of the point to be drawn | 5 | + +## Chart Theme Variables + +| Parameter | Description | +| -------------------------------- | --------------------------------------- | +| quadrant1Fill | Fill color of the top right quadrant | +| quadrant2Fill | Fill color of the top left quadrant | +| quadrant3Fill | Fill color of the bottom left quadrant | +| quadrant4Fill | Fill color of the bottom right quadrant | +| quadrant1TextFill | Text color of the top right quadrant | +| quadrant2TextFill | Text color of the top left quadrant | +| quadrant3TextFill | Text color of the bottom left quadrant | +| quadrant4TextFill | Text color of the bottom right quadrant | +| quadrantPointFill | Points fill color | +| quadrantPointTextFill | Points text color | +| quadrantXAxisTextFill | X-axis text color | +| quadrantYAxisTextFill | Y-axis text color | +| quadrantInternalBorderStrokeFill | Quadrants inner border color | +| quadrantExternalBorderStrokeFill | Quadrants outer border color | +| quadrantTitleFill | Title color | + +## Example on config and theme + +```mermaid-example +%%{init: {"quadrantChart": {"chartWidth": 400, "chartHeight": 400}, "themeVariables": {"quadrant1TextFill": "#ff0000"} }}%% +quadrantChart + x-axis Urgent --> Not Urgent + y-axis Not Important --> "Important ❤" + quadrant-1 Plan + quadrant-2 Do + quadrant-3 Delegate + quadrant-4 Delete +``` diff --git a/packages/mermaid/src/docs/syntax/sankey.md b/packages/mermaid/src/docs/syntax/sankey.md new file mode 100644 index 000000000..f5160ea86 --- /dev/null +++ b/packages/mermaid/src/docs/syntax/sankey.md @@ -0,0 +1,182 @@ +# Sankey diagram (v10.3.0+) + +> A sankey diagram is a visualization used to depict a flow from one set of values to another. + +::: warning +This is an experimental diagram. Its syntax are very close to plain CSV, but it is to be extended in the nearest future. +::: + +The things being connected are called nodes and the connections are called links. + +## Example + +This example taken from [observable](https://observablehq.com/@d3/sankey/2?collection=@d3/d3-sankey). It may be rendered a little bit differently, though, in terms of size and colors. + +```mermaid-example +sankey-beta + +Agricultural 'waste',Bio-conversion,124.729 +Bio-conversion,Liquid,0.597 +Bio-conversion,Losses,26.862 +Bio-conversion,Solid,280.322 +Bio-conversion,Gas,81.144 +Biofuel imports,Liquid,35 +Biomass imports,Solid,35 +Coal imports,Coal,11.606 +Coal reserves,Coal,63.965 +Coal,Solid,75.571 +District heating,Industry,10.639 +District heating,Heating and cooling - commercial,22.505 +District heating,Heating and cooling - homes,46.184 +Electricity grid,Over generation / exports,104.453 +Electricity grid,Heating and cooling - homes,113.726 +Electricity grid,H2 conversion,27.14 +Electricity grid,Industry,342.165 +Electricity grid,Road transport,37.797 +Electricity grid,Agriculture,4.412 +Electricity grid,Heating and cooling - commercial,40.858 +Electricity grid,Losses,56.691 +Electricity grid,Rail transport,7.863 +Electricity grid,Lighting & appliances - commercial,90.008 +Electricity grid,Lighting & appliances - homes,93.494 +Gas imports,Ngas,40.719 +Gas reserves,Ngas,82.233 +Gas,Heating and cooling - commercial,0.129 +Gas,Losses,1.401 +Gas,Thermal generation,151.891 +Gas,Agriculture,2.096 +Gas,Industry,48.58 +Geothermal,Electricity grid,7.013 +H2 conversion,H2,20.897 +H2 conversion,Losses,6.242 +H2,Road transport,20.897 +Hydro,Electricity grid,6.995 +Liquid,Industry,121.066 +Liquid,International shipping,128.69 +Liquid,Road transport,135.835 +Liquid,Domestic aviation,14.458 +Liquid,International aviation,206.267 +Liquid,Agriculture,3.64 +Liquid,National navigation,33.218 +Liquid,Rail transport,4.413 +Marine algae,Bio-conversion,4.375 +Ngas,Gas,122.952 +Nuclear,Thermal generation,839.978 +Oil imports,Oil,504.287 +Oil reserves,Oil,107.703 +Oil,Liquid,611.99 +Other waste,Solid,56.587 +Other waste,Bio-conversion,77.81 +Pumped heat,Heating and cooling - homes,193.026 +Pumped heat,Heating and cooling - commercial,70.672 +Solar PV,Electricity grid,59.901 +Solar Thermal,Heating and cooling - homes,19.263 +Solar,Solar Thermal,19.263 +Solar,Solar PV,59.901 +Solid,Agriculture,0.882 +Solid,Thermal generation,400.12 +Solid,Industry,46.477 +Thermal generation,Electricity grid,525.531 +Thermal generation,Losses,787.129 +Thermal generation,District heating,79.329 +Tidal,Electricity grid,9.452 +UK land based bioenergy,Bio-conversion,182.01 +Wave,Electricity grid,19.013 +Wind,Electricity grid,289.366 +``` + +## Syntax + +The idea behind syntax is that a user types `sankey-beta` keyword first, then pastes raw CSV below and get the result. + +It implements CSV standard as [described here](https://www.ietf.org/rfc/rfc4180.txt) with subtle **differences**: + +- CSV must contain **3 columns only** +- It is **allowed** to have **empty lines** without comma separators for visual purposes + +### Basic + +It is implied that 3 columns inside CSV should represent `source`, `target` and `value` accordingly: + +```mermaid-example +sankey-beta + +%% source,target,value +Electricity grid,Over generation / exports,104.453 +Electricity grid,Heating and cooling - homes,113.726 +Electricity grid,H2 conversion,27.14 +``` + +### Empty Lines + +CSV does not support empty lines without comma delimiters by default. But you can add them if needed: + +```mermaid-example +sankey-beta + +Bio-conversion,Losses,26.862 + +Bio-conversion,Solid,280.322 + +Bio-conversion,Gas,81.144 +``` + +### Commas + +If you need to have a comma, wrap it in double quotes: + +```mermaid-example +sankey-beta + +Pumped heat,"Heating and cooling, homes",193.026 +Pumped heat,"Heating and cooling, commercial",70.672 +``` + +### Double Quotes + +If you need to have double quote, put a pair of them inside quoted string: + +```mermaid-example +sankey-beta + +Pumped heat,"Heating and cooling, ""homes""",193.026 +Pumped heat,"Heating and cooling, ""commercial""",70.672 +``` + +## Configuration + +You can customize link colors, node alignments and diagram dimensions. + +```html +<script> + const config = { + startOnLoad: true, + securityLevel: 'loose', + sankey: { + width: 800, + height: 400, + linkColor: 'source', + nodeAlignment: 'left', + }, + }; + mermaid.initialize(config); +</script> +``` + +### Links Coloring + +You can adjust links' color by setting `linkColor` to one of those: + +- `source` - link will be of a source node color +- `target` - link will be of a target node color +- `gradient` - link color will be smoothly transient between source and target node colors +- hex code of color, like `#a1a1a1` + +### Node Alignment + +Graph layout can be changed by setting `nodeAlignment` to: + +- `justify` +- `center` +- `left` +- `right` diff --git a/packages/mermaid/src/docs/syntax/sequenceDiagram.md b/packages/mermaid/src/docs/syntax/sequenceDiagram.md index 3f3818589..cdcdaffeb 100644 --- a/packages/mermaid/src/docs/syntax/sequenceDiagram.md +++ b/packages/mermaid/src/docs/syntax/sequenceDiagram.md @@ -58,6 +58,31 @@ sequenceDiagram J->>A: Great! ``` +### Actor Creation and Destruction (v10.3.0+) + +It is possible to create and destroy actors by messages. To do so, add a create or destroy directive before the message. + +``` +create participant B +A --> B: Hello +``` + +Create directives support actor/participant distinction and aliases. The sender or the recipient of a message can be destroyed but only the recipient can be created. + +```mermaid-example +sequenceDiagram + Alice->>Bob: Hello Bob, how are you ? + Bob->>Alice: Fine, thank you. And you? + create participant Carl + Alice->>Carl: Hi Carl! + create actor D as Donald + Carl->>D: Hi! + destroy Carl + Alice-xCarl: We are too many + destroy Bob + Bob->>Alice: I agree +``` + ### Grouping / Box The actor(s) can be grouped in vertical boxes. You can define a color (if not, it will be transparent) and/or a descriptive label using the following notation: @@ -96,7 +121,7 @@ end end A->>J: Hello John, how are you? J->>A: Great! - A->>B: Hello Bob, how is Charly ? + A->>B: Hello Bob, how is Charly? B->>C: Hello Charly, how are you? ``` @@ -387,7 +412,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 -```mmd +```mermaid sequenceDiagram Alice->>John: Hello John, how are you? %% this is a comment @@ -418,7 +443,7 @@ It is possible to get a sequence number attached to each arrow in a sequence dia </script> ``` -It can also be be turned on via the diagram code as in the diagram: +It can also be turned on via the diagram code as in the diagram: ```mermaid-example sequenceDiagram @@ -443,7 +468,7 @@ This can be configured by adding one or more link lines with the format: link <actor>: <link-label> @ <link-url> ``` -```mmd +```mermaid sequenceDiagram participant Alice participant John diff --git a/packages/mermaid/src/docs/syntax/stateDiagram.md b/packages/mermaid/src/docs/syntax/stateDiagram.md index ddfe61c49..f35796b13 100644 --- a/packages/mermaid/src/docs/syntax/stateDiagram.md +++ b/packages/mermaid/src/docs/syntax/stateDiagram.md @@ -249,7 +249,7 @@ Comments can be entered within a state diagram chart, which will be ignored by t 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 -```mmd +```mermaid stateDiagram-v2 [*] --> Still Still --> [*] @@ -304,7 +304,7 @@ where - the second _property_ is `color` and its _value_ is `white` - the third _property_ is `font-weight` and its _value_ is `bold` - the fourth _property_ is `stroke-width` and its _value_ is `2px` -- the fifth _property_ is `stroke` and its _value_ is `yello` +- the fifth _property_ is `stroke` and its _value_ is `yellow` ### Apply classDef styles to states diff --git a/packages/mermaid/src/docs/syntax/timeline.md b/packages/mermaid/src/docs/syntax/timeline.md index ef48d2b61..201ab6b16 100644 --- a/packages/mermaid/src/docs/syntax/timeline.md +++ b/packages/mermaid/src/docs/syntax/timeline.md @@ -2,7 +2,7 @@ > Timeline: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stable except for the icon integration which is the experimental part. -"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia +"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life." Wikipedia ### An example of a timeline. @@ -100,7 +100,7 @@ timeline 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.<br> The people who live here are hunter-gatherers. - section Broze Age + section Bronze Age 2300 BC : People arrive from Europe and settle in Britain. <br>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.<br> People now bury their dead in stone circles. @@ -139,7 +139,7 @@ However, if there is no section defined, then we have two possibilities: ``` -Note that this is no, section defined, and each time period and its corresponding events will have its own color scheme. +Note that there are no sections defined, and each time period and its corresponding events will have its own color scheme. 2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme. @@ -172,9 +172,11 @@ let us look at same example, where we have disabled the multiColor option. ### Customizing Color scheme -You can customize the color scheme using the `cScale0` to `cScale11` theme variables. Mermaid allows you to set unique colors for up-to 12, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on. +You can customize the color scheme using the `cScale0` to `cScale11` theme variables, which will change the background colors. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on. In case you have more than 12 sections, the color scheme will start to repeat. +If you also want to change the foreground color of a section, you can do so use theme variables corresponding `cScaleLabel0` to `cScaleLabel11` variables. + NOTE: Default values for these theme variables are picked from the selected theme. If you want to override the default values, you can use the `initialize` call to add your custom theme variable values. Example: @@ -183,9 +185,9 @@ Now let's override the default values for the `cScale0` to `cScale2` variables: ```mermaid-example %%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': { - 'cScale0': '#ff0000', + 'cScale0': '#ff0000', 'cScaleLabel0': '#ffffff', 'cScale1': '#00ff00', - 'cScale2': '#0000ff' + 'cScale2': '#0000ff', 'cScaleLabel2': '#ffffff' } } }%% timeline title History of Social Media Platform diff --git a/packages/mermaid/src/docs/syntax/zenuml.md b/packages/mermaid/src/docs/syntax/zenuml.md new file mode 100644 index 000000000..292c0f1c1 --- /dev/null +++ b/packages/mermaid/src/docs/syntax/zenuml.md @@ -0,0 +1,314 @@ +# ZenUML + +> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order. + +Mermaid can render sequence diagrams with [ZenUML](https://zenuml.com). Note that ZenUML uses a different +syntax than the original Sequence Diagram in mermaid. + +```mermaid-example +zenuml + title Demo + Alice->John: Hello John, how are you? + John->Alice: Great! + Alice->John: See you later! +``` + +## Syntax + +### Participants + +The participants can be defined implicitly as in the first example on this page. The participants or actors are +rendered in order of appearance in the diagram source text. Sometimes you might want to show the participants in a +different order than how they appear in the first message. It is possible to specify the actor's order of +appearance by doing the following: + +```mermaid-example +zenuml + title Declare participant (optional) + Bob + Alice + Alice->Bob: Hi Bob + Bob->Alice: Hi Alice +``` + +### Annotators + +If you specifically want to use symbols instead of just rectangles with text you can do so by using the annotator syntax to declare participants as per below. + +```mermaid-example +zenuml + title Annotators + @Actor Alice + @Database Bob + Alice->Bob: Hi Bob + Bob->Alice: Hi Alice +``` + +Here are the available annotators: +![img.png](img/zenuml-participant-annotators.png) + +### Aliases + +The participants can have a convenient identifier and a descriptive label. + +```mermaid-example +zenuml + title Aliases + A as Alice + J as John + A->J: Hello John, how are you? + J->A: Great! +``` + +## Messages + +Messages can be one of: + +1. Sync message +2. Async message +3. Creation message +4. Reply message + +### Sync message + +You can think of a sync (blocking) method in a programming language. + +```mermaid-example +zenuml + title Sync message + A.SyncMessage + A.SyncMessage(with, parameters) { + B.nestedSyncMessage() + } +``` + +### Async message + +You can think of an async (non-blocking) method in a programming language. +Fire an event and forget about it. + +```mermaid-example +zenuml + title Async message + Alice->Bob: How are you? +``` + +### Creation message + +We use `new` keyword to create an object. + +```mermaid-example +zenuml + new A1 + new A2(with, parameters) +``` + +### Reply message + +There are three ways to express a reply message: + +```mermaid-example +zenuml + // 1. assign a variable from a sync message. + a = A.SyncMessage() + + // 1.1. optionally give the variable a type + SomeType a = A.SyncMessage() + + // 2. use return keyword + A.SyncMessage() { + return result + } + + // 3. use @return or @reply annotator on an async message + @return + A->B: result +``` + +The third way `@return` is rarely used, but it is useful when you want to return to one level up. + +```mermaid-example +zenuml + title Reply message + Client->A.method() { + B.method() { + if(condition) { + return x1 + // return early + @return + A->Client: x11 + } + } + return x2 + } +``` + +## Nesting + +Sync messages and Creation messages are naturally nestable with `{}`. + +```mermaid-example +zenuml + A.method() { + B.nested_sync_method() + B->C: nested async message + } +``` + +## Comments + +It is possible to add comments to a sequence diagram with `// comment` syntax. +Comments will be rendered above the messages or fragments. Comments on other places +are ignored. Markdown is supported. + +See the example below: + +```mermaid-example +zenuml + // a comment on a participant will not be rendered + BookService + // a comment on a message. + // **Markdown** is supported. + BookService.getBook() +``` + +## Loops + +It is possible to express loops in a ZenUML diagram. This is done by any of the +following notations: + +1. while +2. for +3. forEach, foreach +4. loop + +```zenuml +while(condition) { + ...statements... +} +``` + +See the example below: + +```mermaid-example +zenuml + Alice->John: Hello John, how are you? + while(true) { + John->Alice: Great! + } +``` + +## Alt + +It is possible to express alternative paths in a sequence diagram. This is done by the notation + +```zenuml +if(condition1) { + ...statements... +} else if(condition2) { + ...statements... +} else { + ...statements... +} +``` + +See the example below: + +```mermaid-example +zenuml + Alice->Bob: Hello Bob, how are you? + if(is_sick) { + Bob->Alice: Not so good :( + } else { + Bob->Alice: Feeling fresh like a daisy + } +``` + +## Opt + +It is possible to render an `opt` fragment. This is done by the notation + +```zenuml +opt { + ...statements... +} +``` + +See the example below: + +```mermaid-example +zenuml + Alice->Bob: Hello Bob, how are you? + Bob->Alice: Not so good :( + opt { + Bob->Alice: Thanks for asking + } +``` + +## Parallel + +It is possible to show actions that are happening in parallel. + +This is done by the notation + +```zenuml +par { + statement1 + statement2 + statement3 +} +``` + +See the example below: + +```mermaid-example +zenuml + par { + Alice->Bob: Hello guys! + Alice->John: Hello guys! + } +``` + +## Try/Catch/Finally (Break) + +It is possible to indicate a stop of the sequence within the flow (usually used to model exceptions). + +This is done by the notation + +``` +try { + ...statements... +} catch { + ...statements... +} finally { + ...statements... +} +``` + +See the example below: + +```mermaid-example +zenuml + try { + Consumer->API: Book something + API->BookingService: Start booking process + } catch { + API->Consumer: show failure + } finally { + API->BookingService: rollback status + } +``` + +## Integrating with your library/website. + +Zenuml uses the experimental lazy loading & async rendering features which could change in the future. + +You can use this method to add mermaid including the zenuml diagram to a web page: + +```html +<script type="module"> + import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs'; + import zenuml from 'https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-zenuml@0.1.0/dist/mermaid-zenuml.esm.min.mjs'; + await mermaid.registerExternalDiagrams([zenuml]); +</script> +``` diff --git a/packages/mermaid/src/docs/vite.config.ts b/packages/mermaid/src/docs/vite.config.ts index 179e271fd..ed5f4bab9 100644 --- a/packages/mermaid/src/docs/vite.config.ts +++ b/packages/mermaid/src/docs/vite.config.ts @@ -1,12 +1,49 @@ -import { defineConfig, type PluginOption, searchForWorkspaceRoot } from 'vite'; +import { defineConfig, searchForWorkspaceRoot } from 'vite'; +import type { PluginOption, Plugin } from 'vite'; import path from 'path'; +// @ts-expect-error This package has an incorrect export map. import { SearchPlugin } from 'vitepress-plugin-search'; +import fs from 'fs'; +import Components from 'unplugin-vue-components/vite'; +import Unocss from 'unocss/vite'; +import { presetAttributify, presetIcons, presetUno } from 'unocss'; +import { resolve } from 'pathe'; const virtualModuleId = 'virtual:mermaid-config'; const resolvedVirtualModuleId = '\0' + virtualModuleId; export default defineConfig({ + optimizeDeps: { + // vitepress is aliased with replacement `join(DIST_CLIENT_PATH, '/index')` + // This needs to be excluded from optimization + exclude: ['vitepress'], + }, plugins: [ + // @ts-ignore This package has an incorrect exports. + Components({ + include: [/\.vue/, /\.md/], + dirs: '.vitepress/components', + dts: '.vitepress/components.d.ts', + }) as Plugin, + // @ts-ignore This package has an incorrect exports. + Unocss({ + shortcuts: [ + [ + 'btn', + 'px-4 py-1 rounded inline-flex justify-center gap-2 text-white leading-30px children:mya !no-underline cursor-pointer disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50', + ], + ], + presets: [ + presetUno({ + dark: 'media', + }), + presetAttributify(), + presetIcons({ + scale: 1.2, + }), + ], + }) as unknown as Plugin, + IncludesPlugin(), SearchPlugin() as PluginOption, { // TODO: will be fixed in the next vitepress release. @@ -47,3 +84,21 @@ export default defineConfig({ }, }, }); + +function IncludesPlugin(): Plugin { + return { + name: 'include-plugin', + enforce: 'pre', + transform(code: string, id: string): string | undefined { + let changed = false; + code = code.replace(/\[@@include]\((.*?)\)/, (_: string, url: any): string => { + changed = true; + const full = resolve(id, url); + return fs.readFileSync(full, 'utf-8'); + }); + if (changed) { + return code; + } + }, + } as Plugin; +} diff --git a/packages/mermaid/src/logger.ts b/packages/mermaid/src/logger.ts index b1c035e22..44b98315c 100644 --- a/packages/mermaid/src/logger.ts +++ b/packages/mermaid/src/logger.ts @@ -2,7 +2,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable no-console */ -import moment from 'moment-mini'; +import dayjs from 'dayjs'; export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'; @@ -85,6 +85,6 @@ export const setLogLevel = function (level: keyof typeof LEVELS | number | strin * @returns The format with the timestamp and log level */ const format = (level: Uppercase<LogLevel>): string => { - const time = moment().format('ss.SSS'); + const time = dayjs().format('ss.SSS'); return `%c${time} : ${level} : `; }; diff --git a/packages/mermaid/src/mermaid.spec.ts b/packages/mermaid/src/mermaid.spec.ts index 75cafcdf3..0b4437d74 100644 --- a/packages/mermaid/src/mermaid.spec.ts +++ b/packages/mermaid/src/mermaid.spec.ts @@ -1,9 +1,16 @@ -import mermaid from './mermaid'; -import { mermaidAPI } from './mermaidAPI'; -import './diagram-api/diagram-orchestration'; +import mermaid from './mermaid.js'; +import { mermaidAPI } from './mermaidAPI.js'; +import './diagram-api/diagram-orchestration.js'; +import { addDiagrams } from './diagram-api/diagram-orchestration.js'; +import { beforeAll, describe, it, expect, vi } from 'vitest'; +import type { DiagramDefinition } from './diagram-api/types.js'; + +beforeAll(async () => { + addDiagrams(); +}); const spyOn = vi.spyOn; -vi.mock('./mermaidAPI'); +vi.mock('./mermaidAPI.js'); afterEach(() => { vi.clearAllMocks(); @@ -66,9 +73,9 @@ describe('when using mermaid and ', () => { mermaid.registerExternalDiagrams( [ { - id: 'dummy', - detector: (text) => /dummy/.test(text), - loader: () => Promise.reject('error'), + id: 'dummyError', + detector: (text) => /dummyError/.test(text), + loader: () => Promise.reject('dummyError'), }, ], { lazyLoad: false } @@ -86,13 +93,16 @@ describe('when using mermaid and ', () => { it('should defer diagram load based on parameter', async () => { let loaded = false; - const dummyDiagram = { + const dummyDiagram: DiagramDefinition = { db: {}, renderer: () => { // do nothing }, - parser: () => { - // do nothing + parser: { + parse: (_text) => { + return; + }, + parser: { yy: {} }, }, styles: () => { // do nothing @@ -146,7 +156,11 @@ describe('when using mermaid and ', () => { describe('checking validity of input ', () => { it('should throw for an invalid definition', async () => { - await expect(mermaid.parse('this is not a mermaid diagram definition')).rejects.toThrow(); + await expect( + mermaid.parse('this is not a mermaid diagram definition') + ).rejects.toThrowErrorMatchingInlineSnapshot( + '"No diagram type detected matching given configuration for text: this is not a mermaid diagram definition"' + ); }); it('should not throw for a valid flow definition', async () => { @@ -155,7 +169,12 @@ describe('when using mermaid and ', () => { ).resolves.not.toThrow(); }); it('should throw for an invalid flow definition', async () => { - await expect(mermaid.parse('graph TQ;A--x|text including URL space|B;')).rejects.toThrow(); + await expect(mermaid.parse('graph TQ;A--x|text including URL space|B;')).rejects + .toThrowErrorMatchingInlineSnapshot(` + "Lexical error on line 1. Unrecognized text. + graph TQ;A--x|text includ + -----^" + `); }); it('should not throw for a valid sequenceDiagram definition (mmds1)', async () => { @@ -183,7 +202,12 @@ describe('when using mermaid and ', () => { 'else isSick\n' + 'Bob-->Alice: Feel sick...\n' + 'end'; - await expect(mermaid.parse(text)).rejects.toThrow(); + await expect(mermaid.parse(text)).rejects.toThrowErrorMatchingInlineSnapshot(` + "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'" + `); }); it('should return false for invalid definition WITH a parseError() callback defined', async () => { @@ -191,7 +215,11 @@ describe('when using mermaid and ', () => { mermaid.setParseErrorHandler(() => { parseErrorWasCalled = true; }); - await expect(mermaid.parse('this is not a mermaid diagram definition')).rejects.toThrow(); + await expect( + mermaid.parse('this is not a mermaid diagram definition') + ).rejects.toThrowErrorMatchingInlineSnapshot( + '"No diagram type detected matching given configuration for text: this is not a mermaid diagram definition"' + ); expect(parseErrorWasCalled).toEqual(true); }); }); diff --git a/packages/mermaid/src/mermaid.ts b/packages/mermaid/src/mermaid.ts index 29d25c016..caf4a2b9b 100644 --- a/packages/mermaid/src/mermaid.ts +++ b/packages/mermaid/src/mermaid.ts @@ -2,17 +2,19 @@ * Web page integration module for the mermaid framework. It uses the mermaidAPI for mermaid * functionality and to render the diagrams to svg code! */ -import dedent from 'ts-dedent'; -import { MermaidConfig } from './config.type'; -import { log } from './logger'; -import utils from './utils'; -import { mermaidAPI, ParseOptions, RenderResult } from './mermaidAPI'; -import { registerLazyLoadedDiagrams } from './diagram-api/detectType'; -import type { ParseErrorFunction } from './Diagram'; -import { isDetailedError } from './utils'; -import type { DetailedError } from './utils'; -import { registerDiagram } from './diagram-api/diagramAPI'; -import { ExternalDiagramDefinition } from './diagram-api/types'; +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, 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'; export type { MermaidConfig, @@ -21,21 +23,25 @@ export type { ParseErrorFunction, RenderResult, ParseOptions, + UnknownDiagramError, }; -/** - * The options used when running mermaid. - * - * @param querySelector - The query selector to use when finding elements to render. Default: .mermaid - * @param nodes - The nodes to render. If this is set, querySelector will be ignored. - * @param postRenderCallback - A callback to call after each diagram is rendered. - * @param suppressErrors - If true, errors will be logged to the console, but not thrown. Default: false - */ export interface RunOptions { - // Default: .mermaid + /** + * The query selector to use when finding elements to render. Default: `".mermaid"`. + */ querySelector?: string; + /** + * The nodes to render. If this is set, `querySelector` will be ignored. + */ nodes?: ArrayLike<HTMLElement>; + /** + * A callback to call after each diagram is rendered. + */ postRenderCallback?: (id: string) => unknown; + /** + * If `true`, errors will be logged to the console, but not thrown. Default: `false` + */ suppressErrors?: boolean; } @@ -64,30 +70,6 @@ const handleError = (error: unknown, errors: DetailedError[], parseError?: Parse } }; -/** - * This is an internal function and should not be made public, as it will likely change. - * @internal - * @param diagrams - Array of {@link ExternalDiagramDefinition}. - */ -const loadExternalDiagrams = async (...diagrams: ExternalDiagramDefinition[]) => { - log.debug(`Loading ${diagrams.length} external diagrams`); - // Load all lazy loaded diagrams in parallel - const results = await Promise.allSettled( - diagrams.map(async ({ id, detector, loader }) => { - const { diagram } = await loader(); - registerDiagram(id, diagram, detector); - }) - ); - const failed = results.filter((result) => result.status === 'rejected'); - if (failed.length > 0) { - log.error(`Failed to load ${failed.length} external diagrams`); - for (const res of failed) { - log.error(res); - } - throw new Error(`Failed to load ${failed.length} external diagrams`); - } -}; - /** * ## run * @@ -184,7 +166,7 @@ const runThrowsErrors = async function ( log.debug('Detected early reinit: ', init); } try { - const { svg, bindFunctions } = await mermaidAPI.render(id, txt, element); + const { svg, bindFunctions } = await render(id, txt, element); element.innerHTML = svg; if (postRenderCallback) { await postRenderCallback(id); @@ -251,7 +233,7 @@ const init = async function ( /** * Used to register external diagram types. * @param diagrams - Array of {@link ExternalDiagramDefinition}. - * @param opts - If opts.lazyLoad is true, the diagram will be loaded on demand. + * @param opts - If opts.lazyLoad is false, the diagrams will be loaded immediately. */ const registerExternalDiagrams = async ( diagrams: ExternalDiagramDefinition[], @@ -261,10 +243,9 @@ const registerExternalDiagrams = async ( lazyLoad?: boolean; } = {} ) => { - if (lazyLoad) { - registerLazyLoadedDiagrams(...diagrams); - } else { - await loadExternalDiagrams(...diagrams); + registerLazyLoadedDiagrams(...diagrams); + if (lazyLoad === false) { + await loadRegisteredDiagrams(); } }; @@ -336,7 +317,7 @@ const executeQueue = async () => { */ const parse = async (text: string, parseOptions?: ParseOptions): Promise<boolean | void> => { return new Promise((resolve, reject) => { - // This promise will resolve when the mermaidAPI.render call is done. + // This promise will resolve when the render call is done. // It will be queued first and will be executed when it is first in line const performCall = () => new Promise((res, rej) => { @@ -360,6 +341,29 @@ const parse = async (text: string, parseOptions?: ParseOptions): Promise<boolean }); }; +/** + * Function that renders an svg with a graph from a chart definition. Usage example below. + * + * ```javascript + * element = document.querySelector('#graphDiv'); + * const graphDefinition = 'graph TB\na-->b'; + * const { svg, bindFunctions } = await mermaid.render('graphDiv', graphDefinition); + * element.innerHTML = svg; + * bindFunctions?.(element); + * ``` + * + * @remarks + * Multiple calls to this function will be enqueued to run serially. + * + * @param id - The id for the SVG element (the element to be rendered) + * @param text - The text for the graph definition + * @param container - HTML element where the svg will be inserted. (Is usually element with the .mermaid class) + * If no svgContainingElement is provided then the SVG element will be appended to the body. + * Selector to element in which a div with the graph temporarily will be + * inserted. If one is provided a hidden div will be inserted in the body of the page instead. The + * element will be removed when rendering is completed. + * @returns Returns the SVG Definition and BindFunctions. + */ const render = (id: string, text: string, container?: Element): Promise<RenderResult> => { return new Promise((resolve, reject) => { // This promise will resolve when the mermaidAPI.render call is done. @@ -386,7 +390,7 @@ const render = (id: string, text: string, container?: Element): Promise<RenderRe }); }; -const mermaid: { +export interface Mermaid { startOnLoad: boolean; parseError?: ParseErrorFunction; mermaidAPI: typeof mermaidAPI; @@ -398,7 +402,10 @@ const mermaid: { initialize: typeof initialize; contentLoaded: typeof contentLoaded; setParseErrorHandler: typeof setParseErrorHandler; -} = { + detectType: typeof detectType; +} + +const mermaid: Mermaid = { startOnLoad: true, mermaidAPI, parse, @@ -410,6 +417,7 @@ const mermaid: { parseError: undefined, contentLoaded, setParseErrorHandler, + detectType, }; export default mermaid; diff --git a/packages/mermaid/src/mermaidAPI.spec.ts b/packages/mermaid/src/mermaidAPI.spec.ts index cf858b58e..d7c16a1cf 100644 --- a/packages/mermaid/src/mermaidAPI.spec.ts +++ b/packages/mermaid/src/mermaidAPI.spec.ts @@ -4,39 +4,39 @@ import { vi } from 'vitest'; // ------------------------------------- // Mocks and mocking -import { MockedD3 } from './tests/MockedD3'; +import { MockedD3 } from './tests/MockedD3.js'; // Note: If running this directly from within an IDE, the mocks directory must be at packages/mermaid/mocks vi.mock('d3'); vi.mock('dagre-d3'); // mermaidAPI.spec.ts: -import * as accessibility from './accessibility'; // Import it this way so we can use spyOn(accessibility,...) -vi.mock('./accessibility', () => ({ +import * as accessibility from './accessibility.js'; // Import it this way so we can use spyOn(accessibility,...) +vi.mock('./accessibility.js', () => ({ setA11yDiagramInfo: vi.fn(), addSVGa11yTitleDescription: vi.fn(), })); // Mock the renderers specifically so we can test render(). Need to mock draw() for each renderer -vi.mock('./diagrams/c4/c4Renderer'); -vi.mock('./diagrams/class/classRenderer'); -vi.mock('./diagrams/class/classRenderer-v2'); -vi.mock('./diagrams/er/erRenderer'); -vi.mock('./diagrams/flowchart/flowRenderer-v2'); -vi.mock('./diagrams/git/gitGraphRenderer'); -vi.mock('./diagrams/gantt/ganttRenderer'); -vi.mock('./diagrams/user-journey/journeyRenderer'); -vi.mock('./diagrams/pie/pieRenderer'); -vi.mock('./diagrams/requirement/requirementRenderer'); -vi.mock('./diagrams/sequence/sequenceRenderer'); -vi.mock('./diagrams/state/stateRenderer-v2'); +vi.mock('./diagrams/c4/c4Renderer.js'); +vi.mock('./diagrams/class/classRenderer.js'); +vi.mock('./diagrams/class/classRenderer-v2.js'); +vi.mock('./diagrams/er/erRenderer.js'); +vi.mock('./diagrams/flowchart/flowRenderer-v2.js'); +vi.mock('./diagrams/git/gitGraphRenderer.js'); +vi.mock('./diagrams/gantt/ganttRenderer.js'); +vi.mock('./diagrams/user-journey/journeyRenderer.js'); +vi.mock('./diagrams/pie/pieRenderer.js'); +vi.mock('./diagrams/requirement/requirementRenderer.js'); +vi.mock('./diagrams/sequence/sequenceRenderer.js'); +vi.mock('./diagrams/state/stateRenderer-v2.js'); // ------------------------------------- -import mermaid from './mermaid'; -import { MermaidConfig } from './config.type'; +import mermaid from './mermaid.js'; +import type { MermaidConfig } from './config.type.js'; -import mermaidAPI, { removeExistingElements } from './mermaidAPI'; +import mermaidAPI, { removeExistingElements } from './mermaidAPI.js'; import { encodeEntities, decodeEntities, @@ -45,20 +45,20 @@ import { appendDivSvgG, cleanUpSvgCode, putIntoIFrame, -} from './mermaidAPI'; +} from './mermaidAPI.js'; -import assignWithDepth from './assignWithDepth'; +import assignWithDepth from './assignWithDepth.js'; // -------------- // Mocks // To mock a module, first define a mock for it, then (if used explicitly in the tests) import it. Be sure the path points to exactly the same file as is imported in mermaidAPI (the module being tested) -vi.mock('./styles', () => { +vi.mock('./styles.js', () => { return { addStylesForDiagram: vi.fn(), default: vi.fn().mockReturnValue(' .userStyle { font-weight:bold; }'), }; }); -import getStyles from './styles'; +import getStyles from './styles.js'; vi.mock('stylis', () => { return { @@ -666,7 +666,7 @@ describe('mermaidAPI', () => { ).rejects.toThrow( 'Diagrams beginning with --- are not valid. ' + 'If you were trying to use a YAML front-matter, please ensure that ' + - "you've correctly opened and closed the YAML front-matter with unindented `---` blocks" + "you've correctly opened and closed the YAML front-matter with un-indented `---` blocks" ); }); it('does not throw for a valid definition', async () => { @@ -678,7 +678,7 @@ describe('mermaidAPI', () => { await expect( mermaidAPI.parse('this is not a mermaid diagram definition') ).rejects.toThrowErrorMatchingInlineSnapshot( - '"No diagram type detected for text: this is not a mermaid diagram definition"' + '"No diagram type detected matching given configuration for text: this is not a mermaid diagram definition"' ); }); it('returns false for invalid definition with silent option', async () => { @@ -689,7 +689,7 @@ describe('mermaidAPI', () => { it('resolves for valid definition', async () => { await expect( mermaidAPI.parse('graph TD;A--x|text including URL space|B;') - ).resolves.not.toThrow(); + ).resolves.toBeTruthy(); }); it('returns true for valid definition with silent option', async () => { await expect( @@ -733,59 +733,7 @@ describe('mermaidAPI', () => { const diagramText = `${diagramType}\n accTitle: ${a11yTitle}\n accDescr: ${a11yDescr}\n`; const expectedDiagramType = testedDiagram.expectedType; - it('aria-roledscription is set to the diagram type, addSVGa11yTitleDescription is called', async () => { - const a11yDiagramInfo_spy = vi.spyOn(accessibility, 'setA11yDiagramInfo'); - const a11yTitleDesc_spy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription'); - await mermaidAPI.render(id, diagramText); - expect(a11yDiagramInfo_spy).toHaveBeenCalledWith( - expect.anything(), - expectedDiagramType - ); - expect(a11yTitleDesc_spy).toHaveBeenCalled(); - }); - }); - }); - }); - }); - - describe('render', () => { - // Be sure to add async before each test (anonymous) method - - // These are more like integration tests right now because nothing is mocked. - // But it is faster that a cypress test and there's no real reason to actually evaluate an image pixel by pixel. - - // render(id, text, cb?, svgContainingElement?) - - // Test all diagram types. Note that old flowchart 'graph' type will invoke the flowRenderer-v2. (See the flowchart v2 detector.) - // 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-v2', expectedType: 'classDiagram' }, - { textDiagramType: 'erDiagram', expectedType: 'er' }, - { textDiagramType: 'graph', expectedType: 'flowchart-v2' }, - { textDiagramType: 'flowchart', expectedType: 'flowchart-v2' }, - { textDiagramType: 'gitGraph', expectedType: 'gitGraph' }, - { textDiagramType: 'gantt', expectedType: 'gantt' }, - { textDiagramType: 'journey', expectedType: 'journey' }, - { textDiagramType: 'pie', expectedType: 'pie' }, - { textDiagramType: 'requirementDiagram', expectedType: 'requirement' }, - { textDiagramType: 'sequenceDiagram', expectedType: 'sequence' }, - { textDiagramType: 'stateDiagram-v2', expectedType: 'stateDiagram' }, - ]; - - describe('accessibility', () => { - const id = 'mermaid-fauxId'; - const a11yTitle = 'a11y title'; - const a11yDescr = 'a11y description'; - - diagramTypesAndExpectations.forEach((testedDiagram) => { - describe(`${testedDiagram.textDiagramType}`, () => { - const diagramType = testedDiagram.textDiagramType; - const diagramText = `${diagramType}\n accTitle: ${a11yTitle}\n accDescr: ${a11yDescr}\n`; - const expectedDiagramType = testedDiagram.expectedType; - - it('aria-roledscription is set to the diagram type, addSVGa11yTitleDescription is called', async () => { + it('should set aria-roledscription to the diagram type AND should call addSVGa11yTitleDescription', async () => { const a11yDiagramInfo_spy = vi.spyOn(accessibility, 'setA11yDiagramInfo'); const a11yTitleDesc_spy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription'); await mermaidAPI.render(id, diagramText); diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index 999db5088..bb7570034 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -15,24 +15,32 @@ import { select } from 'd3'; import { compile, serialize, stringify } from 'stylis'; // @ts-ignore: TODO Fix ts errors import { version } from '../package.json'; -import * as configApi from './config'; -import { addDiagrams } from './diagram-api/diagram-orchestration'; -import { Diagram, getDiagramFromText } from './Diagram'; -import errorRenderer from './diagrams/error/errorRenderer'; -import { attachFunctions } from './interactionDb'; -import { log, setLogLevel } from './logger'; -import getStyles from './styles'; -import theme from './themes'; -import utils, { directiveSanitizer } from './utils'; +import * as configApi from './config.js'; +import { addDiagrams } from './diagram-api/diagram-orchestration.js'; +import { Diagram, getDiagramFromText } from './Diagram.js'; +import errorRenderer from './diagrams/error/errorRenderer.js'; +import { attachFunctions } from './interactionDb.js'; +import { log, setLogLevel } from './logger.js'; +import getStyles from './styles.js'; +import theme from './themes/index.js'; +import utils from './utils.js'; import DOMPurify from 'dompurify'; -import { MermaidConfig } from './config.type'; -import { evaluate } from './diagrams/common/common'; +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'; -import { parseDirective } from './directiveUtils'; +import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js'; +import { parseDirective } from './directiveUtils.js'; +import { extractFrontMatter } from './diagram-api/frontmatter.js'; // diagram names that support classDef statements -const CLASSDEF_DIAGRAMS = ['graph', 'flowchart', 'flowchart-v2', 'stateDiagram', 'stateDiagram-v2']; +const CLASSDEF_DIAGRAMS = [ + 'graph', + 'flowchart', + 'flowchart-v2', + 'flowchart-elk', + 'stateDiagram', + 'stateDiagram-v2', +]; const MAX_TEXTLENGTH = 50_000; const MAX_TEXTLENGTH_EXCEEDED_MSG = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa'; @@ -71,9 +79,25 @@ export interface ParseOptions { } // 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. -// @ts-ignore Could replicate the type definition in d3. This also makes it possible to use the untyped info from the js diagram files. export type D3Element = any; +export interface RenderResult { + /** + * The svg code for the rendered graph. + */ + svg: 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; +} + /** * Parse the text and validate the syntax. * @param text - The mermaid diagram definition. @@ -82,21 +106,17 @@ export type D3Element = any; * @throws Error if the diagram is invalid and parseOptions.suppressErrors is false. */ -async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean | void> { +async function parse(text: string, parseOptions?: ParseOptions): Promise<boolean> { addDiagrams(); - let error; try { - const diagram = await getDiagramFromText(text); - diagram.parse(); - } catch (err) { - error = err; - } - if (parseOptions?.suppressErrors) { - return error === undefined; - } - if (error) { + await getDiagramFromText(text); + } catch (error) { + if (parseOptions?.suppressErrors) { + return false; + } throw error; } + return true; } /** @@ -133,13 +153,7 @@ export const encodeEntities = function (text: string): string { * @returns */ export const decodeEntities = function (text: string): string { - let txt = text; - - txt = txt.replace(/fl°°/g, '&#'); - txt = txt.replace(/fl°/g, '&'); - txt = txt.replace(/¶ß/g, ';'); - - return txt; + return text.replace(/fl°°/g, '&#').replace(/fl°/g, '&').replace(/¶ß/g, ';'); }; // append !important; to each cssClass followed by a final !important, all enclosed in { } @@ -248,7 +262,10 @@ export const cleanUpSvgCode = ( // Replace marker-end urls with just the # anchor (remove the preceding part of the URL) if (!useArrowMarkerUrls && !inSandboxMode) { - cleanedUpSvg = cleanedUpSvg.replace(/marker-end="url\(.*?#/g, 'marker-end="url(#'); + cleanedUpSvg = cleanedUpSvg.replace( + /marker-end="url\([\d+./:=?A-Za-z-]*?#/g, + 'marker-end="url(#' + ); } cleanedUpSvg = decodeEntities(cleanedUpSvg); @@ -268,7 +285,9 @@ export const cleanUpSvgCode = ( * TODO replace btoa(). Replace with buf.toString('base64')? */ export const putIntoIFrame = (svgCode = '', svgElement?: D3Element): string => { - const height = svgElement ? svgElement.viewBox.baseVal.height + 'px' : IFRAME_HEIGHT; + const height = svgElement?.viewBox?.baseVal?.height + ? svgElement.viewBox.baseVal.height + 'px' + : IFRAME_HEIGHT; const base64encodedSrc = btoa('<body style="' + IFRAME_BODY_STYLE + '">' + svgCode + '</body>'); return `<iframe style="width:${IFRAME_WIDTH};height:${height};${IFRAME_STYLES}" src="data:text/html;base64,${base64encodedSrc}" sandbox="${IFRAME_SANDBOX_OPTS}"> ${IFRAME_NOT_SUPPORTED_MSG} @@ -353,37 +372,11 @@ export const removeExistingElements = ( }; /** - * Function that renders an svg with a graph from a chart definition. Usage example below. + * @deprecated - use the `mermaid.render` function instead of `mermaid.mermaidAPI.render` * - * ```javascript - * mermaidAPI.initialize({ - * startOnLoad: true, - * }); - * $(function () { - * const graphDefinition = 'graph TB\na-->b'; - * const cb = function (svgGraph) { - * console.log(svgGraph); - * }; - * mermaidAPI.render('id1', graphDefinition, cb); - * }); - * ``` - * - * @param id - The id for the SVG element (the element to be rendered) - * @param text - The text for the graph definition - * @param cb - Callback which is called after rendering is finished with the svg code as in param. - * @param svgContainingElement - HTML element where the svg will be inserted. (Is usually element with the .mermaid class) - * If no svgContainingElement is provided then the SVG element will be appended to the body. - * Selector to element in which a div with the graph temporarily will be - * inserted. If one is provided a hidden div will be inserted in the body of the page instead. The - * element will be removed when rendering is completed. - * @returns Returns the rendered element as a string containing the SVG definition. + * Deprecated for external use. */ -export interface RenderResult { - svg: string; - bindFunctions?: (element: Element) => void; -} - const render = async function ( id: string, text: string, @@ -393,10 +386,14 @@ const render = async function ( configApi.reset(); - // Add Directives. Must do this before getting the config and before creating the diagram. + // We need to add the directives before creating the diagram. + // So extractFrontMatter is called twice. Once here and once in the diagram parser. + // This can be fixed in a future refactor. + extractFrontMatter(text, {}, configApi.addDirective); + + // Add Directives. const graphInit = utils.detectInit(text); if (graphInit) { - directiveSanitizer(graphInit); configApi.addDirective(graphInit); } @@ -411,6 +408,12 @@ const render = async function ( // clean up text CRLFs text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;; + // clean up html tags so that all attributes use single quotes, parser throws error on double quotes + text = text.replace( + /<(\w+)([^>]*)>/g, + (match, tag, attributes) => '<' + tag + attributes.replace(/="([^"]*)"/g, "='$1'") + '>' + ); + const idSelector = '#' + id; const iFrameID = 'i' + id; const iFrameID_selector = '#' + iFrameID; @@ -481,7 +484,7 @@ const render = async function ( // Get the temporary div element containing the svg const element = root.select(enclosingDivID_selector).node(); - const graphType = diag.type; + const diagramType = diag.type; // ------------------------------------------------------------------------------- // Create and insert the styles (user styles, theme styles, config styles) @@ -489,17 +492,11 @@ const render = async function ( // Insert an element into svg. This is where we put the styles const svg = element.firstChild; const firstChild = svg.firstChild; - const diagramClassDefs = CLASSDEF_DIAGRAMS.includes(graphType) + const diagramClassDefs = CLASSDEF_DIAGRAMS.includes(diagramType) ? diag.renderer.getClasses(text, diag) : {}; - const rules = createUserStyles( - config, - graphType, - // @ts-ignore convert renderer to TS. - diagramClassDefs, - idSelector - ); + const rules = createUserStyles(config, diagramType, diagramClassDefs, idSelector); const style1 = document.createElement('style'); style1.innerHTML = rules; @@ -516,9 +513,9 @@ const render = async function ( // This is the d3 node for the svg element const svgNode = root.select(`${enclosingDivID_selector} svg`); - const a11yTitle = diag.db.getAccTitle?.(); - const a11yDescr = diag.db.getAccDescription?.(); - addA11yInfo(graphType, svgNode, a11yTitle, a11yDescr); + const a11yTitle: string | undefined = diag.db.getAccTitle?.(); + const a11yDescr: string | undefined = diag.db.getAccDescription?.(); + addA11yInfo(diagramType, svgNode, a11yTitle, a11yDescr); // ------------------------------------------------------------------------------- // Clean up SVG code @@ -543,6 +540,10 @@ const render = async function ( attachFunctions(); + if (parseEncounteredException) { + throw parseEncounteredException; + } + // ------------------------------------------------------------------------------- // Remove the temporary HTML element if appropriate const tmpElementSelector = isSandboxed ? iFrameID_selector : enclosingDivID_selector; @@ -551,10 +552,6 @@ const render = async function ( node.remove(); } - if (parseEncounteredException) { - throw parseEncounteredException; - } - return { svg: svgCode, bindFunctions: diag.db.bindFunctions, @@ -567,7 +564,10 @@ const render = async function ( function initialize(options: MermaidConfig = {}) { // Handle legacy location of font-family configuration if (options?.fontFamily && !options.themeVariables?.fontFamily) { - options.themeVariables = { fontFamily: options.fontFamily }; + if (!options.themeVariables) { + options.themeVariables = {}; + } + options.themeVariables.fontFamily = options.fontFamily; } // Set default options @@ -592,14 +592,18 @@ function initialize(options: MermaidConfig = {}) { /** * Add accessibility (a11y) information to the diagram. * + * @param diagramType - diagram type + * @param svgNode - d3 node to insert the a11y title and desc info + * @param a11yTitle - a11y title + * @param a11yDescr - a11y description */ function addA11yInfo( - graphType: string, + diagramType: string, svgNode: D3Element, - a11yTitle: string | undefined, - a11yDescr: string | undefined -) { - setA11yDiagramInfo(svgNode, graphType); + a11yTitle?: string, + a11yDescr?: string +): void { + setA11yDiagramInfo(svgNode, diagramType); addSVGa11yTitleDescription(svgNode, a11yTitle, a11yDescr, svgNode.attr('id')); } @@ -659,6 +663,7 @@ function addA11yInfo( * numberSectionStyles: 4, * axisFormat: '%Y-%m-%d', * topAxis: false, + * displayMode: '', * }, * }; * mermaid.initialize(config); @@ -669,6 +674,7 @@ export const mermaidAPI = Object.freeze({ render, parse, parseDirective, + getDiagramFromText, initialize, getConfig: configApi.getConfig, setConfig: configApi.setConfig, diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts new file mode 100644 index 000000000..a0aaa66ba --- /dev/null +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -0,0 +1,190 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +// @ts-nocheck TODO: Fix types +import { log } from '../logger.js'; +import { decodeEntities } from '../mermaidAPI.js'; +import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdown-text.js'; +import { splitLineToFitWidth } from './splitText.js'; +import type { MarkdownLine, MarkdownWord } from './types.js'; + +function applyStyle(dom, styleFn) { + if (styleFn) { + dom.attr('style', styleFn); + } +} + +function addHtmlSpan(element, node, width, classes, addBackground = false) { + const fo = element.append('foreignObject'); + const div = fo.append('xhtml:div'); + + const label = node.label; + const labelClass = node.isNode ? 'nodeLabel' : 'edgeLabel'; + div.html( + ` + <span class="${labelClass} ${classes}" ` + + (node.labelStyle ? 'style="' + node.labelStyle + '"' : '') + + '>' + + label + + '</span>' + ); + + applyStyle(div, node.labelStyle); + div.style('display', 'table-cell'); + div.style('white-space', 'nowrap'); + div.style('max-width', width + 'px'); + div.attr('xmlns', 'http://www.w3.org/1999/xhtml'); + if (addBackground) { + div.attr('class', 'labelBkg'); + } + + let bbox = div.node().getBoundingClientRect(); + if (bbox.width === width) { + div.style('display', 'table'); + div.style('white-space', 'break-spaces'); + div.style('width', width + 'px'); + bbox = div.node().getBoundingClientRect(); + } + + fo.style('width', bbox.width); + fo.style('height', bbox.height); + + return fo.node(); +} + +/** + * Creates a tspan element with the specified attributes for text positioning. + * + * @param textElement - The parent text element to append the tspan element. + * @param lineIndex - The index of the current line in the structuredText array. + * @param lineHeight - The line height value for the text. + * @returns The created tspan element. + */ +function createTspan(textElement: any, lineIndex: number, lineHeight: number) { + return textElement + .append('tspan') + .attr('class', 'text-outer-tspan') + .attr('x', 0) + .attr('y', lineIndex * lineHeight - 0.1 + 'em') + .attr('dy', lineHeight + 'em'); +} + +function computeWidthOfText(parentNode: any, lineHeight: number, line: MarkdownLine): number { + const testElement = parentNode.append('text'); + const testSpan = createTspan(testElement, 1, lineHeight); + updateTextContentAndStyles(testSpan, line); + const textLength = testSpan.node().getComputedTextLength(); + testElement.remove(); + return textLength; +} + +/** + * Creates a formatted text element by breaking lines and applying styles based on + * the given structuredText. + * + * @param width - The maximum allowed width of the text. + * @param g - The parent group element to append the formatted text. + * @param structuredText - The structured text data to format. + * @param addBackground - Whether to add a background to the text. + */ +function createFormattedText( + width: number, + g: any, + structuredText: MarkdownWord[][], + addBackground = false +) { + const lineHeight = 1.1; + const labelGroup = g.append('g'); + const bkg = labelGroup.insert('rect').attr('class', 'background'); + const textElement = labelGroup.append('text').attr('y', '-10.1'); + let lineIndex = 0; + for (const line of structuredText) { + /** + * Preprocess raw string content of line data + * Creating an array of strings pre-split to satisfy width limit + */ + const checkWidth = (line: MarkdownLine) => + computeWidthOfText(labelGroup, lineHeight, line) <= width; + const linesUnderWidth = checkWidth(line) ? [line] : splitLineToFitWidth(line, checkWidth); + /** Add each prepared line as a tspan to the parent node */ + for (const preparedLine of linesUnderWidth) { + const tspan = createTspan(textElement, lineIndex, lineHeight); + updateTextContentAndStyles(tspan, preparedLine); + lineIndex++; + } + } + if (addBackground) { + const bbox = textElement.node().getBBox(); + const padding = 2; + bkg + .attr('x', -padding) + .attr('y', -padding) + .attr('width', bbox.width + 2 * padding) + .attr('height', bbox.height + 2 * padding); + + return labelGroup.node(); + } else { + return textElement.node(); + } +} + +/** + * Updates the text content and styles of the given tspan element based on the + * provided wrappedLine data. + * + * @param tspan - The tspan element to update. + * @param wrappedLine - The line data to apply to the tspan element. + */ +function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) { + tspan.text(''); + + wrappedLine.forEach((word, index) => { + const innerTspan = tspan + .append('tspan') + .attr('font-style', word.type === 'emphasis' ? 'italic' : 'normal') + .attr('class', 'text-inner-tspan') + .attr('font-weight', word.type === 'strong' ? 'bold' : 'normal'); + if (index === 0) { + innerTspan.text(word.content); + } else { + // TODO: check what joiner to use. + innerTspan.text(' ' + word.content); + } + }); +} + +// 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' +// When not using htmlLabels => to set classes to 'title-row' when isTitle=true otherwise 'title-row' +export const createText = ( + el, + text = '', + { + style = '', + isTitle = false, + classes = '', + useHtmlLabels = true, + isNode = true, + width = 200, + addSvgBackground = false, + } = {} +) => { + log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground); + if (useHtmlLabels) { + // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? + // text = text.replace(/\\n|\n/g, '<br />'); + const htmlText = markdownToHTML(text); + // log.info('markdo wnToHTML' + text, markdownToHTML(text)); + const node = { + isNode, + label: decodeEntities(htmlText).replace( + /fa[blrs]?:fa-[\w-]+/g, + (s) => `<i class='${s.replace(':', ' ')}'></i>` + ), + labelStyle: style.replace('fill:', 'color:'), + }; + const vertexNode = addHtmlSpan(el, node, width, classes, addSvgBackground); + return vertexNode; + } else { + const structuredText = markdownToLines(text); + const svgLabel = createFormattedText(width, el, structuredText, addSvgBackground); + 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 new file mode 100644 index 000000000..3ca7a3d7a --- /dev/null +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.spec.ts @@ -0,0 +1,264 @@ +import { markdownToLines, markdownToHTML } from './handle-markdown-text.js'; +import { test, expect } from 'vitest'; + +test('markdownToLines - Basic test', () => { + const input = `This is regular text +Here is a new line +There is some words **with a bold** section +Here is a line *with an italic* section`; + + const expectedOutput = [ + [ + { content: 'This', type: 'normal' }, + { content: 'is', type: 'normal' }, + { content: 'regular', type: 'normal' }, + { content: 'text', type: 'normal' }, + ], + [ + { content: 'Here', type: 'normal' }, + { content: 'is', type: 'normal' }, + { content: 'a', type: 'normal' }, + { content: 'new', type: 'normal' }, + { content: 'line', type: 'normal' }, + ], + [ + { content: 'There', type: 'normal' }, + { content: 'is', type: 'normal' }, + { content: 'some', type: 'normal' }, + { content: 'words', type: 'normal' }, + { content: 'with', type: 'strong' }, + { content: 'a', type: 'strong' }, + { content: 'bold', type: 'strong' }, + { content: 'section', type: 'normal' }, + ], + [ + { content: 'Here', type: 'normal' }, + { 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: 'section', type: 'normal' }, + ], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToLines - Empty input', () => { + const input = ''; + const expectedOutput = [[]]; + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToLines - No formatting', () => { + const input = `This is a simple test +with no formatting`; + + const expectedOutput = [ + [ + { content: 'This', type: 'normal' }, + { content: 'is', type: 'normal' }, + { content: 'a', type: 'normal' }, + { content: 'simple', type: 'normal' }, + { content: 'test', type: 'normal' }, + ], + [ + { content: 'with', type: 'normal' }, + { content: 'no', type: 'normal' }, + { content: 'formatting', type: 'normal' }, + ], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToLines - Only bold formatting', () => { + const input = `This is a **bold** test`; + + const expectedOutput = [ + [ + { content: 'This', type: 'normal' }, + { content: 'is', type: 'normal' }, + { content: 'a', type: 'normal' }, + { content: 'bold', type: 'strong' }, + { content: 'test', type: 'normal' }, + ], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToLines - paragraph 1', () => { + const input = `**Start** with + a second line`; + + const expectedOutput = [ + [ + { content: 'Start', type: 'strong' }, + { content: 'with', type: 'normal' }, + ], + [ + { content: 'a', type: 'normal' }, + { content: 'second', type: 'normal' }, + { content: 'line', type: 'normal' }, + ], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToLines - paragraph', () => { + const input = `**Start** with + a second line`; + + const expectedOutput = [ + [ + { content: 'Start', type: 'strong' }, + { content: 'with', type: 'normal' }, + ], + [ + { content: 'a', type: 'normal' }, + { content: 'second', type: 'normal' }, + { content: 'line', type: 'normal' }, + ], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToLines - Only italic formatting', () => { + const input = `This is an *italic* test`; + + const expectedOutput = [ + [ + { content: 'This', type: 'normal' }, + { content: 'is', type: 'normal' }, + { content: 'an', type: 'normal' }, + { content: 'italic', type: 'emphasis' }, + { content: 'test', type: 'normal' }, + ], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +it('markdownToLines - Mixed formatting', () => { + let input = `*Italic* and **bold** formatting`; + let expected = [ + [ + { content: 'Italic', type: 'emphasis' }, + { content: 'and', type: 'normal' }, + { content: 'bold', type: 'strong' }, + { content: 'formatting', type: 'normal' }, + ], + ]; + expect(markdownToLines(input)).toEqual(expected); + + input = `*Italic with space* and **bold ws** formatting`; + expected = [ + [ + { content: 'Italic', type: 'emphasis' }, + { content: 'with', type: 'emphasis' }, + { content: 'space', type: 'emphasis' }, + { content: 'and', type: 'normal' }, + { content: 'bold', type: 'strong' }, + { content: 'ws', type: 'strong' }, + { content: 'formatting', type: 'normal' }, + ], + ]; + expect(markdownToLines(input)).toEqual(expected); +}); + +it('markdownToLines - Mixed formatting', () => { + const input = `The dog in **the** hog... a *very long text* about it +Word!`; + + const expectedOutput = [ + [ + { content: 'The', type: 'normal' }, + { content: 'dog', type: 'normal' }, + { content: 'in', type: 'normal' }, + { 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: 'about', type: 'normal' }, + { content: 'it', type: 'normal' }, + ], + [{ content: 'Word!', type: 'normal' }], + ]; + + const output = markdownToLines(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToHTML - Basic test', () => { + const input = `This is regular text +Here is a new line +There is some words **with a bold** section +Here is a line *with an italic* section`; + + const expectedOutput = `<p>This is regular text<br/>Here is a new line<br/>There is some words <strong>with a bold</strong> section<br/>Here is a line <em>with an italic</em> section</p>`; + + const output = markdownToHTML(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToHTML - Empty input', () => { + const input = ''; + const expectedOutput = ''; + const output = markdownToHTML(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToHTML - No formatting', () => { + const input = `This is a simple test +with no formatting`; + + const expectedOutput = `<p>This is a simple test<br/>with no formatting</p>`; + const output = markdownToHTML(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToHTML - Only bold formatting', () => { + const input = `This is a **bold** test`; + + const expectedOutput = `<p>This is a <strong>bold</strong> test</p>`; + const output = markdownToHTML(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToHTML - Only italic formatting', () => { + const input = `This is an *italic* test`; + + const expectedOutput = `<p>This is an <em>italic</em> test</p>`; + const output = markdownToHTML(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToHTML - Mixed formatting', () => { + const input = `*Italic* and **bold** formatting`; + const expectedOutput = `<p><em>Italic</em> and <strong>bold</strong> formatting</p>`; + const output = markdownToHTML(input); + expect(output).toEqual(expectedOutput); +}); + +test('markdownToHTML - Unsupported formatting', () => { + expect( + markdownToHTML(`Hello + - l1 + - l2 + - l3`) + ).toMatchInlineSnapshot('"<p>Hello</p>Unsupported markdown: list"'); +}); diff --git a/packages/mermaid/src/rendering-util/handle-markdown-text.ts b/packages/mermaid/src/rendering-util/handle-markdown-text.ts new file mode 100644 index 000000000..ce694edcd --- /dev/null +++ b/packages/mermaid/src/rendering-util/handle-markdown-text.ts @@ -0,0 +1,76 @@ +import type { Content } from 'mdast'; +import { fromMarkdown } from 'mdast-util-from-markdown'; +import { dedent } from 'ts-dedent'; +import type { MarkdownLine, MarkdownWordType } from './types.js'; + +/** + * @param markdown - markdown to process + * @returns processed markdown + */ +function preprocessMarkdown(markdown: string): string { + // Replace multiple newlines with a single newline + const withoutMultipleNewlines = markdown.replace(/\n{2,}/g, '\n'); + // Remove extra spaces at the beginning of each line + const withoutExtraSpaces = dedent(withoutMultipleNewlines); + return withoutExtraSpaces; +} + +/** + * @param markdown - markdown to split into lines + */ +export function markdownToLines(markdown: string): MarkdownLine[] { + const preprocessedMarkdown = preprocessMarkdown(markdown); + const { children } = fromMarkdown(preprocessedMarkdown); + const lines: MarkdownLine[] = [[]]; + let currentLine = 0; + + function processNode(node: Content, parentType: MarkdownWordType = 'normal') { + if (node.type === 'text') { + const textLines = node.value.split('\n'); + textLines.forEach((textLine, index) => { + if (index !== 0) { + currentLine++; + lines.push([]); + } + textLine.split(' ').forEach((word) => { + 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); + }); + } + } + + children.forEach((treeNode) => { + if (treeNode.type === 'paragraph') { + treeNode.children.forEach((contentNode) => { + processNode(contentNode); + }); + } + }); + + return lines; +} + +export function markdownToHTML(markdown: string) { + const { children } = fromMarkdown(markdown); + + function output(node: Content): string { + if (node.type === 'text') { + return node.value.replace(/\n/g, '<br/>'); + } else if (node.type === 'strong') { + return `<strong>${node.children.map(output).join('')}</strong>`; + } else if (node.type === 'emphasis') { + return `<em>${node.children.map(output).join('')}</em>`; + } else if (node.type === 'paragraph') { + return `<p>${node.children.map(output).join('')}</p>`; + } + return `Unsupported markdown: ${node.type}`; + } + + return children.map(output).join(''); +} diff --git a/packages/mermaid/src/rendering-util/selectSvgElement.ts b/packages/mermaid/src/rendering-util/selectSvgElement.ts new file mode 100644 index 000000000..ae106ef78 --- /dev/null +++ b/packages/mermaid/src/rendering-util/selectSvgElement.ts @@ -0,0 +1,22 @@ +import { select } from 'd3'; +import { getConfig } from '../config.js'; +import type { HTML, SVG } from '../diagram-api/types.js'; + +/** + * Selects the SVG element using {@link id}. + * + * @param id - The diagram ID. + * @returns The selected {@link SVG} element using {@link id}. + */ +export const selectSvgElement = (id: string): SVG => { + const { securityLevel } = getConfig(); + // handle root and document for when rendering in sandbox mode + let root: HTML = select('body'); + if (securityLevel === 'sandbox') { + const sandboxElement: HTML = select(`#i${id}`); + const doc: Document = sandboxElement.node()?.contentDocument ?? document; + root = select(doc.body as HTMLIFrameElement); + } + const svg: SVG = root.select(`#${id}`); + return svg; +}; diff --git a/packages/mermaid/src/rendering-util/splitText.spec.ts b/packages/mermaid/src/rendering-util/splitText.spec.ts new file mode 100644 index 000000000..bc7df08dd --- /dev/null +++ b/packages/mermaid/src/rendering-util/splitText.spec.ts @@ -0,0 +1,147 @@ +import { splitTextToChars, splitLineToFitWidth, splitLineToWords } from './splitText.js'; +import { describe, it, expect, vi } from 'vitest'; +import type { CheckFitFunction, MarkdownLine, MarkdownWordType } from './types.js'; + +describe('when Intl.Segmenter is available', () => { + describe('splitText', () => { + it.each([ + { str: '', split: [] }, + { str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] }, + { str: 'ok', split: ['o', 'k'] }, + { str: 'abc', split: ['a', 'b', 'c'] }, + ])('should split $str into graphemes', ({ str, split }: { str: string; split: string[] }) => { + expect(splitTextToChars(str)).toEqual(split); + }); + }); + + describe('split lines', () => { + it('should create valid checkFit function', () => { + const checkFit5 = createCheckFn(5); + expect(checkFit5([{ content: 'hello', type: 'normal' }])).toBe(true); + expect( + checkFit5([ + { content: 'hello', type: 'normal' }, + { content: 'world', type: 'normal' }, + ]) + ).toBe(false); + const checkFit1 = createCheckFn(1); + expect(checkFit1([{ content: 'A', type: 'normal' }])).toBe(true); + expect(checkFit1([{ content: '🏳️‍⚧️', type: 'normal' }])).toBe(true); + expect(checkFit1([{ content: '🏳️‍⚧️🏳️‍⚧️', type: 'normal' }])).toBe(false); + }); + + it.each([ + // empty string + { str: 'hello world', width: 7, split: ['hello', 'world'] }, + // width > full line + { str: 'hello world', width: 20, split: ['hello world'] }, + // width < individual word + { str: 'hello world', width: 3, split: ['hel', 'lo', 'wor', 'ld'] }, + { str: 'hello 12 world', width: 4, split: ['hell', 'o 12', 'worl', 'd'] }, + { str: 'hello 1 2 world', width: 4, split: ['hell', 'o 1', '2', 'worl', 'd'] }, + { str: 'hello 1 2 world', width: 6, split: ['hello', ' 1 2', 'world'] }, + // width = 0, impossible, so split into individual characters + { str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 0, split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] }, + { str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 1, split: ['🏳️‍⚧️', '🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] }, + { str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 2, split: ['🏳️‍⚧️🏳️‍🌈', '👩🏾‍❤️‍👨🏻'] }, + { str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 3, split: ['🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻'] }, + { str: '中文中', width: 1, split: ['中', '文', '中'] }, + { str: '中文中', width: 2, split: ['中文', '中'] }, + { str: '中文中', width: 3, split: ['中文中'] }, + { str: 'Flag 🏳️‍⚧️ this 🏳️‍🌈', width: 6, split: ['Flag 🏳️‍⚧️', 'this 🏳️‍🌈'] }, + ])( + 'should split $str into lines of $width characters', + ({ str, split, width }: { str: string; width: number; split: string[] }) => { + const checkFn = createCheckFn(width); + const line: MarkdownLine = getLineFromString(str); + expect(splitLineToFitWidth(line, checkFn)).toEqual( + split.map((str) => getLineFromString(str)) + ); + } + ); + }); +}); + +/** + * Intl.Segmenter is not supported in Firefox yet, + * see https://bugzilla.mozilla.org/show_bug.cgi?id=1423593 + */ +describe('when Intl.Segmenter is not available', () => { + beforeAll(() => { + vi.stubGlobal('Intl', { Segmenter: undefined }); + }); + afterAll(() => { + vi.unstubAllGlobals(); + }); + + it.each([ + { str: '', split: [] }, + { + str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', + split: [...'🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻'], + }, + { str: 'ok', split: ['o', 'k'] }, + { str: 'abc', split: ['a', 'b', 'c'] }, + ])('should split $str into characters', ({ str, split }: { str: string; split: string[] }) => { + expect(splitTextToChars(str)).toEqual(split); + }); + + it.each([ + // empty string + { str: 'hello world', width: 7, split: ['hello', 'world'] }, + // width > full line + { str: 'hello world', width: 20, split: ['hello world'] }, + // width < individual word + { str: 'hello world', width: 3, split: ['hel', 'lo', 'wor', 'ld'] }, + { str: 'hello 12 world', width: 4, split: ['hell', 'o 12', 'worl', 'd'] }, + { str: 'hello 1 2 world', width: 4, split: ['hell', 'o 1', '2', 'worl', 'd'] }, + { str: 'hello 1 2 world', width: 6, split: ['hello', ' 1 2', 'world'] }, + // width = 0, impossible, so split into individual characters + { str: 'abc', width: 0, split: ['a', 'b', 'c'] }, + { str: '🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻', width: 1, split: [...'🏳️‍⚧️🏳️‍🌈👩🏾‍❤️‍👨🏻'] }, + { str: '中文中', width: 1, split: ['中', '文', '中'] }, + { str: '中文中', width: 2, split: ['中文', '中'] }, + { str: '中文中', width: 3, split: ['中文中'] }, + ])( + 'should split $str into lines of $width characters', + ({ str, split, width }: { str: string; width: number; split: string[] }) => { + const checkFn = createCheckFn(width); + const line: MarkdownLine = getLineFromString(str); + expect(splitLineToFitWidth(line, checkFn)).toEqual( + split.map((str) => getLineFromString(str)) + ); + } + ); +}); + +it('should handle strings with newlines', () => { + const checkFn: CheckFitFunction = createCheckFn(6); + const str = `Flag + 🏳️‍⚧️ this 🏳️‍🌈`; + expect(() => + splitLineToFitWidth(getLineFromString(str), checkFn) + ).toThrowErrorMatchingInlineSnapshot( + '"splitLineToFitWidth does not support newlines in the line"' + ); +}); + +const getLineFromString = (str: string, type: MarkdownWordType = 'normal'): MarkdownLine => { + return splitLineToWords(str).map((content) => ({ + content, + type, + })); +}; + +/** + * Creates a checkFunction for a given width + * @param width - width of characters to fit in a line + * @returns checkFunction + */ +const createCheckFn = (width: number): CheckFitFunction => { + return (text: MarkdownLine) => { + // Join all words into a single string + const joinedContent = text.map((w) => w.content).join(''); + const characters = splitTextToChars(joinedContent); + return characters.length <= width; + }; +}; diff --git a/packages/mermaid/src/rendering-util/splitText.ts b/packages/mermaid/src/rendering-util/splitText.ts new file mode 100644 index 000000000..36dc6278e --- /dev/null +++ b/packages/mermaid/src/rendering-util/splitText.ts @@ -0,0 +1,135 @@ +import type { CheckFitFunction, MarkdownLine, MarkdownWord, MarkdownWordType } from './types.js'; + +/** + * Splits a string into graphemes if available, otherwise characters. + */ +export function splitTextToChars(text: string): string[] { + if (Intl.Segmenter) { + return [...new Intl.Segmenter().segment(text)].map((s) => s.segment); + } + return [...text]; +} + +/** + * Splits a string into words by using `Intl.Segmenter` if available, or splitting by ' '. + * `Intl.Segmenter` uses the default locale, which might be different across browsers. + */ +export function splitLineToWords(text: string): string[] { + if (Intl.Segmenter) { + return [...new Intl.Segmenter(undefined, { granularity: 'word' }).segment(text)].map( + (s) => s.segment + ); + } + // Split by ' ' removes the ' 's from the result. + const words = text.split(' '); + // Add the ' 's back to the result. + const wordsWithSpaces = words.flatMap((s) => [s, ' ']).filter((s) => s); + // Remove last space. + wordsWithSpaces.pop(); + return wordsWithSpaces; +} + +/** + * Splits a word into two parts, the first part fits the width and the remaining part. + * @param checkFit - Function to check if word fits + * @param word - Word to split + * @returns [first part of word that fits, rest of word] + */ +export function splitWordToFitWidth( + checkFit: CheckFitFunction, + word: MarkdownWord +): [MarkdownWord, MarkdownWord] { + const characters = splitTextToChars(word.content); + return splitWordToFitWidthRecursion(checkFit, [], characters, word.type); +} + +function splitWordToFitWidthRecursion( + checkFit: CheckFitFunction, + usedChars: string[], + remainingChars: string[], + type: MarkdownWordType +): [MarkdownWord, MarkdownWord] { + if (remainingChars.length === 0) { + return [ + { content: usedChars.join(''), type }, + { content: '', type }, + ]; + } + const [nextChar, ...rest] = remainingChars; + const newWord = [...usedChars, nextChar]; + if (checkFit([{ content: newWord.join(''), type }])) { + return splitWordToFitWidthRecursion(checkFit, newWord, rest, type); + } + if (usedChars.length === 0 && nextChar) { + // If the first character does not fit, split it anyway + usedChars.push(nextChar); + remainingChars.shift(); + } + return [ + { content: usedChars.join(''), type }, + { content: remainingChars.join(''), type }, + ]; +} + +/** + * Splits a line into multiple lines that satisfy the checkFit function. + * @param line - Line to split + * @param checkFit - Function to check if line fits + * @returns Array of lines that fit + */ +export function splitLineToFitWidth( + line: MarkdownLine, + checkFit: CheckFitFunction +): MarkdownLine[] { + if (line.some(({ content }) => content.includes('\n'))) { + throw new Error('splitLineToFitWidth does not support newlines in the line'); + } + return splitLineToFitWidthRecursion(line, checkFit); +} + +function splitLineToFitWidthRecursion( + words: MarkdownWord[], + checkFit: CheckFitFunction, + lines: MarkdownLine[] = [], + newLine: MarkdownLine = [] +): MarkdownLine[] { + // Return if there is nothing left to split + if (words.length === 0) { + // If there is a new line, add it to the lines + if (newLine.length > 0) { + lines.push(newLine); + } + return lines.length > 0 ? lines : []; + } + let joiner = ''; + if (words[0].content === ' ') { + joiner = ' '; + words.shift(); + } + const nextWord: MarkdownWord = words.shift() ?? { content: ' ', type: 'normal' }; + const lineWithNextWord: MarkdownLine = [...newLine]; + if (joiner !== '') { + lineWithNextWord.push({ content: joiner, type: 'normal' }); + } + lineWithNextWord.push(nextWord); + + if (checkFit(lineWithNextWord)) { + // nextWord fits, so we can add it to the new line and continue + return splitLineToFitWidthRecursion(words, checkFit, lines, lineWithNextWord); + } + + // nextWord doesn't fit, so we need to split it + if (newLine.length > 0) { + // There was text in newLine, so add it to lines and push nextWord back into words. + lines.push(newLine); + words.unshift(nextWord); + } else if (nextWord.content) { + // There was no text in newLine, so we need to split nextWord + const [line, rest] = splitWordToFitWidth(checkFit, nextWord); + lines.push([line]); + if (rest.content) { + words.unshift(rest); + } + } + return splitLineToFitWidthRecursion(words, checkFit, lines); +} diff --git a/packages/mermaid/src/rendering-util/types.d.ts b/packages/mermaid/src/rendering-util/types.d.ts new file mode 100644 index 000000000..6dabb476d --- /dev/null +++ b/packages/mermaid/src/rendering-util/types.d.ts @@ -0,0 +1,8 @@ +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/uid.ts b/packages/mermaid/src/rendering-util/uid.ts new file mode 100644 index 000000000..9f581faa7 --- /dev/null +++ b/packages/mermaid/src/rendering-util/uid.ts @@ -0,0 +1,18 @@ +export class Uid { + private static count = 0; + id: string; + href: string; + + public static next(name: string): Uid { + return new Uid(name + ++Uid.count); + } + + constructor(id: string) { + this.id = id; + this.href = `#${id}`; + } + + toString(): string { + return 'url(' + this.href + ')'; + } +} diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml new file mode 100644 index 000000000..6f01d5715 --- /dev/null +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -0,0 +1,1915 @@ +# Used for VS Code's YAML plugin to automatically error on invalid types +# yaml-language-server: $schema=https://json-schema.org/draft/2019-09/schema + +# This file defines the MermaidConfig JSON Schema as a YAML file. +# +# From this file, the following things can be generated: +# - `scripts/create-types-from-json-schema.mjs` +# Used to generate the `src/config.type.ts` TypeScript types for MermaidConfig +# with the `json-schema-to-typescript` NPM package. +# - `.vite/jsonSchemaPlugin.ts` +# Used to generate the default values from the `default` keys in this +# JSON Schema using the `ajv` NPM package. +# Non-JSON values, like functions or `undefined`, still need to be manually +# set in `src/defaultConfig.ts`) +# - `src/docs.mts` +# Used to generate Markdown documentation for this JSON Schema by using +# the `@adobe/jsonschema2md` NPM package. + +# Useful things to know when editing this file +# - Use the `|` character for multi-line strings +# - Use `meta:enum` to document enum values (from jsonschema2md) +# - Use `tsType` to override the TypeScript type (from json-schema-to-typescript) +# - If adding a new object to `MermaidConfig` (e.g. a new diagram type), +# you may need to add it to `.vite/jsonSchemaPlugin.ts` and `src/docs.mts` +# to get the docs/default values to generate properly. +$id: https://mermaid-js.github.io/schemas/config.schema.json +$schema: https://json-schema.org/draft/2019-09/schema +title: Mermaid Config +type: object +additionalProperties: false +required: + - fontFamily + - logLevel + - securityLevel + - startOnLoad + - arrowMarkerAbsolute + - flowchart + - sequence + - gantt + - journey + - class + - state + - er + - pie + - quadrantChart + - requirement + - mindmap + - gitGraph + - c4 + - sankey +properties: + theme: + description: | + Theme, the CSS style sheet. + You may also use `themeCSS` to override this value. + type: string + enum: + - default + - forest + - dark + - neutral + - 'null' # should this be a `null`-type? + meta:enum: + 'null': Can be set to disable any pre-defined mermaid theme + default: 'default' + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "default" | "forest" | "dark" | "neutral" | "null"' + themeVariables: + tsType: any + themeCSS: + type: string + maxTextSize: + description: The maximum allowed size of the users text diagram + type: number + default: 50000 + darkMode: + type: boolean + default: false + htmlLabels: + type: boolean # maybe unused, seems to be copied in each diagram config + fontFamily: + description: | + Specifies the font to be used in the rendered diagrams. + Can be any possible CSS `font-family`. + See https://developer.mozilla.org/en-US/docs/Web/CSS/font-family + type: string + default: '"trebuchet ms", verdana, arial, sans-serif;' + altFontFamily: + # TODO: seems to be unused, except for in tests + type: string + logLevel: + description: | + This option decides the amount of logging to be used by mermaid. + type: + - string + - number + enum: + - trace + - 0 + - debug + - 1 + - info + - 2 + - warn + - 3 + - error + - 4 + - fatal + - 5 + meta:enum: + trace: Equivalent to 0 + debug: Equivalent to 1 + info: Equivalent to 2 + warn: Equivalent to 3 + error: Equivalent to 4 + fatal: Equivalent to 5 (default) + default: 5 + # Allow any number or string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'number | string | 0 | 2 | 1 | "trace" | "debug" | "info" | "warn" | "error" | "fatal" | 3 | 4 | 5 | undefined' + securityLevel: + description: Level of trust for parsed diagram + type: string + enum: + - strict + - loose + - antiscript + - sandbox + meta:enum: + strict: (**default**) HTML tags in the text are encoded and click functionality is disabled. + antiscript: HTML tags in text are allowed (only script elements are removed), and click functionality is enabled. + loose: HTML tags in text are allowed and click functionality is enabled. + sandbox: | + With this security level, all rendering takes place in a sandboxed iframe. + This prevent any JavaScript from running in the context. + This may hinder interactive functionality of the diagram, like scripts, popups in the sequence diagram, or links to other tabs or targets, etc. + default: strict + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "strict" | "loose" | "antiscript" | "sandbox" | undefined' + startOnLoad: + description: Dictates whether mermaid starts on Page load + type: boolean + default: true + arrowMarkerAbsolute: + &arrowMarkerAbsolute # YAML anchor, can be used later with `*arrowMarkerAbsolute` + description: | + Controls whether or arrow markers in html code are absolute paths or anchors. + This matters if you are using base tag settings. + type: boolean + default: false + 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`. + + This prevents malicious graph directives from overriding a site's default security. + default: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'] + type: array + items: + type: string + uniqueItems: false # Should be enabled, but it may be a breaking change from the old config + deterministicIds: + description: | + This option controls if the generated ids of nodes in the SVG are + generated randomly or based on a seed. + If set to `false`, the IDs are generated based on the current date and + thus are not deterministic. This is the default behavior. + + This matters if your files are checked into source control e.g. git and + should not change unless content is changed. + type: boolean + default: false + deterministicIDSeed: + description: | + This option is the optional seed for deterministic ids. + If set to `undefined` but deterministicIds is `true`, a simple number iterator is used. + You can set this attribute to base the seed on a static string. + type: string + flowchart: + $ref: '#/$defs/FlowchartDiagramConfig' + sequence: + $ref: '#/$defs/SequenceDiagramConfig' + gantt: + $ref: '#/$defs/GanttDiagramConfig' + journey: + $ref: '#/$defs/JourneyDiagramConfig' + timeline: + $ref: '#/$defs/TimelineDiagramConfig' + class: + $ref: '#/$defs/ClassDiagramConfig' + state: + $ref: '#/$defs/StateDiagramConfig' + er: + $ref: '#/$defs/ErDiagramConfig' + pie: + $ref: '#/$defs/PieDiagramConfig' + quadrantChart: + $ref: '#/$defs/QuadrantChartConfig' + requirement: + $ref: '#/$defs/RequirementDiagramConfig' + mindmap: + $ref: '#/$defs/MindmapDiagramConfig' + gitGraph: + $ref: '#/$defs/GitGraphDiagramConfig' + c4: + $ref: '#/$defs/C4DiagramConfig' + sankey: + $ref: '#/$defs/SankeyDiagramConfig' + dompurifyConfig: + title: DOM Purify Configuration + description: Configuration options to pass to the `dompurify` library. + type: object + tsType: "import('dompurify').Config" + wrap: + type: boolean + fontSize: + type: number + default: 16 + +$defs: # JSON Schema definition (maybe we should move these to a seperate file) + BaseDiagramConfig: + # TODO: More config needs to be moved here + title: Base Diagram Config + type: object + properties: + useWidth: + type: number + useMaxWidth: + description: | + When this flag is set to `true`, the height and width is set to 100% + and is then scaled with the available space. + If set to `false`, the absolute space required is used. + type: boolean + default: true + C4DiagramConfig: + title: C4 Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for c4 diagrams + type: object + unevaluatedProperties: false + required: + - diagramMarginX + - diagramMarginY + - c4ShapeMargin + - c4ShapePadding + - width + - height + - boxMargin + - useMaxWidth + - c4ShapeInRow + - c4BoundaryInRow + properties: + diagramMarginX: + description: | + Margin to the right and left of the c4 diagram, must be a positive value. + type: integer + default: 50 + minimum: 0 + diagramMarginY: + description: | + Margin to the over and under the c4 diagram, must be a positive value. + type: integer + default: 10 + minimum: 0 + c4ShapeMargin: + description: Margin between shapes + type: integer + default: 50 + minimum: 0 + c4ShapePadding: + description: Padding between shapes + type: integer + default: 20 + minimum: 0 + width: + description: Width of person boxes + type: integer + default: 216 + minimum: 0 + height: + description: Height of person boxes + type: integer + default: 60 + minimum: 0 + boxMargin: + description: Margin around boxes + type: integer + default: 10 + minimum: 0 + c4ShapeInRow: + description: How many shapes to place in each row. + type: integer + default: 4 + minimum: 0 + nextLinePaddingX: + # TODO: add description + type: number + default: 0 + c4BoundaryInRow: + description: How many boundaries to place in each row. + type: integer + default: 2 + minimum: 0 + + # --------------------------------------------------------------------- # + # Default font values + # --------------------------------------------------------------------- # + personFontSize: + description: This sets the font size of Person shape for the diagram + type: &fontSizeType ['string', 'number'] # YAML anchor + default: 14 + personFontFamily: + description: This sets the font weight of Person shape for the diagram + type: string + default: '"Open Sans", sans-serif' + personFontWeight: + description: This sets the font weight of Person shape for the diagram + type: ['string', 'number'] + default: normal + external_personFontSize: + description: This sets the font size of External Person shape for the diagram + type: *fontSizeType + default: 14 + external_personFontFamily: + description: This sets the font family of External Person shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_personFontWeight: + description: This sets the font weight of External Person shape for the diagram + type: ['string', 'number'] + default: normal + systemFontSize: + description: This sets the font size of System shape for the diagram + type: *fontSizeType + default: 14 + systemFontFamily: + description: This sets the font family of System shape for the diagram + type: string + default: '"Open Sans", sans-serif' + systemFontWeight: + description: This sets the font weight of System shape for the diagram + type: ['string', 'number'] + default: normal + external_systemFontSize: + description: This sets the font size of External System shape for the diagram + type: *fontSizeType + default: 14 + external_systemFontFamily: + description: This sets the font family of External System shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_systemFontWeight: + description: This sets the font weight of External System shape for the diagram + type: ['string', 'number'] + default: normal + system_dbFontSize: + description: This sets the font size of System DB shape for the diagram + type: *fontSizeType + default: 14 + system_dbFontFamily: + description: This sets the font family of System DB shape for the diagram + type: string + default: '"Open Sans", sans-serif' + system_dbFontWeight: + description: This sets the font weight of System DB shape for the diagram + type: ['string', 'number'] + default: normal + external_system_dbFontSize: + description: This sets the font size of External System DB shape for the diagram + type: *fontSizeType + default: 14 + external_system_dbFontFamily: + description: This sets the font family of External System DB shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_system_dbFontWeight: + description: This sets the font weight of External System DB shape for the diagram + type: ['string', 'number'] + default: normal + system_queueFontSize: + description: This sets the font size of System Queue shape for the diagram + type: *fontSizeType + default: 14 + system_queueFontFamily: + description: This sets the font family of System Queue shape for the diagram + type: string + default: '"Open Sans", sans-serif' + system_queueFontWeight: + description: This sets the font weight of System Queue shape for the diagram + type: ['string', 'number'] + default: normal + external_system_queueFontSize: + description: This sets the font size of External System Queue shape for the diagram + type: *fontSizeType + default: 14 + external_system_queueFontFamily: + description: This sets the font family of External System Queue shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_system_queueFontWeight: + description: This sets the font weight of External System Queue shape for the diagram + type: ['string', 'number'] + default: normal + boundaryFontSize: + description: This sets the font size of Boundary shape for the diagram + type: *fontSizeType + default: 14 + boundaryFontFamily: + description: This sets the font family of Boundary shape for the diagram + type: string + default: '"Open Sans", sans-serif' + boundaryFontWeight: + description: This sets the font weight of Boundary shape for the diagram + type: ['string', 'number'] + default: normal + messageFontSize: + description: This sets the font size of Message shape for the diagram + type: *fontSizeType + default: 12 + messageFontFamily: + description: This sets the font family of Message shape for the diagram + type: string + default: '"Open Sans", sans-serif' + messageFontWeight: + description: This sets the font weight of Message shape for the diagram + type: ['string', 'number'] + default: normal + + containerFontSize: + description: This sets the font size of Container shape for the diagram + type: *fontSizeType + default: 14 + containerFontFamily: + description: This sets the font family of Container shape for the diagram + type: string + default: '"Open Sans", sans-serif' + containerFontWeight: + description: This sets the font weight of Container shape for the diagram + type: ['string', 'number'] + default: normal + external_containerFontSize: + description: This sets the font size of External Container shape for the diagram + type: *fontSizeType + default: 14 + external_containerFontFamily: + description: This sets the font family of External Container shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_containerFontWeight: + description: This sets the font weight of External Container shape for the diagram + type: ['string', 'number'] + default: normal + + container_dbFontSize: + description: This sets the font size of Container DB shape for the diagram + type: *fontSizeType + default: 14 + container_dbFontFamily: + description: This sets the font family of Container DB shape for the diagram + type: string + default: '"Open Sans", sans-serif' + container_dbFontWeight: + description: This sets the font weight of Container DB shape for the diagram + type: ['string', 'number'] + default: normal + external_container_dbFontSize: + description: This sets the font size of External Container DB shape for the diagram + type: *fontSizeType + default: 14 + external_container_dbFontFamily: + description: This sets the font family of External Container DB shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_container_dbFontWeight: + description: This sets the font weight of External Container DB shape for the diagram + type: ['string', 'number'] + default: normal + + container_queueFontSize: + description: This sets the font size of Container Queue shape for the diagram + type: *fontSizeType + default: 14 + container_queueFontFamily: + description: This sets the font family of Container Queue shape for the diagram + type: string + default: '"Open Sans", sans-serif' + container_queueFontWeight: + description: This sets the font weight of Container Queue shape for the diagram + type: ['string', 'number'] + default: normal + external_container_queueFontSize: + description: This sets the font size of External Container Queue shape for the diagram + type: *fontSizeType + default: 14 + external_container_queueFontFamily: + description: This sets the font family of External Container Queue shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_container_queueFontWeight: + description: This sets the font weight of External Container Queue shape for the diagram + type: ['string', 'number'] + default: normal + + componentFontSize: + description: This sets the font size of Component shape for the diagram + type: *fontSizeType + default: 14 + componentFontFamily: + description: This sets the font family of Component shape for the diagram + type: string + default: '"Open Sans", sans-serif' + componentFontWeight: + description: This sets the font weight of Component shape for the diagram + type: ['string', 'number'] + default: normal + external_componentFontSize: + description: This sets the font size of External Component shape for the diagram + type: *fontSizeType + default: 14 + external_componentFontFamily: + description: This sets the font family of External Component shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_componentFontWeight: + description: This sets the font weight of External Component shape for the diagram + type: ['string', 'number'] + default: normal + + component_dbFontSize: + description: This sets the font size of Component DB shape for the diagram + type: *fontSizeType + default: 14 + component_dbFontFamily: + description: This sets the font family of Component DB shape for the diagram + type: string + default: '"Open Sans", sans-serif' + component_dbFontWeight: + description: This sets the font weight of Component DB shape for the diagram + type: ['string', 'number'] + default: normal + external_component_dbFontSize: + description: This sets the font size of External Component DB shape for the diagram + type: *fontSizeType + default: 14 + external_component_dbFontFamily: + description: This sets the font family of External Component DB shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_component_dbFontWeight: + description: This sets the font weight of External Component DB shape for the diagram + type: ['string', 'number'] + default: normal + + component_queueFontSize: + description: This sets the font size of Component Queue shape for the diagram + type: *fontSizeType + default: 14 + component_queueFontFamily: + description: This sets the font family of Component Queue shape for the diagram + type: string + default: '"Open Sans", sans-serif' + component_queueFontWeight: + description: This sets the font weight of Component Queue shape for the diagram + type: ['string', 'number'] + default: normal + external_component_queueFontSize: + description: This sets the font size of External Component Queue shape for the diagram + type: *fontSizeType + default: 14 + external_component_queueFontFamily: + description: This sets the font family of External Component Queue shape for the diagram + type: string + default: '"Open Sans", sans-serif' + external_component_queueFontWeight: + description: This sets the font weight of External Component Queue shape for the diagram + type: ['string', 'number'] + default: normal + + wrap: + description: This sets the auto-wrap state for the diagram + type: boolean + default: true + wrapPadding: + description: This sets the auto-wrap padding for the diagram (sides only) + type: number + default: 10 + + # --------------------------------------------------------------------- # + # Colors + # --------------------------------------------------------------------- # + person_bg_color: + type: string + default: '#08427B' + person_border_color: + type: string + default: '#073B6F' + external_person_bg_color: + type: string + default: '#686868' + external_person_border_color: + type: string + default: '#8A8A8A' + system_bg_color: + type: string + default: '#1168BD' + system_border_color: + type: string + default: '#3C7FC0' + system_db_bg_color: + type: string + default: '#1168BD' + system_db_border_color: + type: string + default: '#3C7FC0' + system_queue_bg_color: + type: string + default: '#1168BD' + system_queue_border_color: + type: string + default: '#3C7FC0' + external_system_bg_color: + type: string + default: '#999999' + external_system_border_color: + type: string + default: '#8A8A8A' + external_system_db_bg_color: + type: string + default: '#999999' + external_system_db_border_color: + type: string + default: '#8A8A8A' + external_system_queue_bg_color: + type: string + default: '#999999' + external_system_queue_border_color: + type: string + default: '#8A8A8A' + container_bg_color: + type: string + default: '#438DD5' + container_border_color: + type: string + default: '#3C7FC0' + container_db_bg_color: + type: string + default: '#438DD5' + container_db_border_color: + type: string + default: '#3C7FC0' + container_queue_bg_color: + type: string + default: '#438DD5' + container_queue_border_color: + type: string + default: '#3C7FC0' + external_container_bg_color: + type: string + default: '#B3B3B3' + external_container_border_color: + type: string + default: '#A6A6A6' + external_container_db_bg_color: + type: string + default: '#B3B3B3' + external_container_db_border_color: + type: string + default: '#A6A6A6' + external_container_queue_bg_color: + type: string + default: '#B3B3B3' + external_container_queue_border_color: + type: string + default: '#A6A6A6' + component_bg_color: + type: string + default: '#85BBF0' + component_border_color: + type: string + default: '#78A8D8' + component_db_bg_color: + type: string + default: '#85BBF0' + component_db_border_color: + type: string + default: '#78A8D8' + component_queue_bg_color: + type: string + default: '#85BBF0' + component_queue_border_color: + type: string + default: '#78A8D8' + external_component_bg_color: + type: string + default: '#CCCCCC' + external_component_border_color: + type: string + default: '#BFBFBF' + external_component_db_bg_color: + type: string + default: '#CCCCCC' + external_component_db_border_color: + type: string + default: '#BFBFBF' + external_component_queue_bg_color: + type: string + default: '#CCCCCC' + external_component_queue_border_color: + type: string + default: '#BFBFBF' + + # Font Calculators + # By default, these all return the values from this configuration. + personFont: { '$ref': '#/$defs/FontCalculator' } + external_personFont: { '$ref': '#/$defs/FontCalculator' } + systemFont: { '$ref': '#/$defs/FontCalculator' } + external_systemFont: { '$ref': '#/$defs/FontCalculator' } + system_dbFont: { '$ref': '#/$defs/FontCalculator' } + external_system_dbFont: { '$ref': '#/$defs/FontCalculator' } + system_queueFont: { '$ref': '#/$defs/FontCalculator' } + external_system_queueFont: { '$ref': '#/$defs/FontCalculator' } + containerFont: { '$ref': '#/$defs/FontCalculator' } + external_containerFont: { '$ref': '#/$defs/FontCalculator' } + container_dbFont: { '$ref': '#/$defs/FontCalculator' } + external_container_dbFont: { '$ref': '#/$defs/FontCalculator' } + container_queueFont: { '$ref': '#/$defs/FontCalculator' } + external_container_queueFont: { '$ref': '#/$defs/FontCalculator' } + componentFont: { '$ref': '#/$defs/FontCalculator' } + external_componentFont: { '$ref': '#/$defs/FontCalculator' } + component_dbFont: { '$ref': '#/$defs/FontCalculator' } + external_component_dbFont: { '$ref': '#/$defs/FontCalculator' } + component_queueFont: { '$ref': '#/$defs/FontCalculator' } + external_component_queueFont: { '$ref': '#/$defs/FontCalculator' } + boundaryFont: { '$ref': '#/$defs/FontCalculator' } + messageFont: { '$ref': '#/$defs/FontCalculator' } + + GitGraphDiagramConfig: + title: Git Graph Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + type: object + unevaluatedProperties: false + required: + - titleTopMargin + properties: + titleTopMargin: + # TODO: I've removed the `Git` part from this description, so that I + # could $ref: "#/$defs/GitGraphDiagramConfig/properties/titleTopMargin" + # this field in other diagrams + description: Margin top for the text over the diagram + type: integer + default: 25 + minimum: 0 + diagramPadding: + type: number + default: 8 + nodeLabel: + allOf: [{ $ref: '#/$defs/NodeLabel' }] + type: object + default: + width: 75 + height: 100 + x: -25 + y: 0 + mainBranchName: + type: string + default: 'main' + mainBranchOrder: + type: number + default: 0 + showCommitLabel: + type: boolean + default: true + showBranches: + type: boolean + default: true + rotateCommitLabel: + type: boolean + default: true + # YAML anchor reference, don't use $ref since ajv doesn't load defaults + arrowMarkerAbsolute: *arrowMarkerAbsolute + + NodeLabel: + title: Node Label + type: object + properties: + width: + type: number + height: + type: number + x: + type: number + y: + type: number + + RequirementDiagramConfig: + title: Requirement Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for req diagrams + type: object + unevaluatedProperties: false + required: + - useMaxWidth + properties: + rect_fill: + type: string + default: '#f9f9f9' + text_color: + type: string + default: '#333' + rect_border_size: + type: string + default: '0.5px' + rect_border_color: + type: string + default: '#bbb' + rect_min_width: + type: number + default: 200 + rect_min_height: + type: number + default: 200 + fontSize: + type: number # TODO, should this be `type: *fontSizeType` (aka string too) + default: 14 + rect_padding: + type: number + default: 10 + line_height: + type: number + default: 20 + + MindmapDiagramConfig: + title: Mindmap Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for mindmap diagrams + type: object + unevaluatedProperties: false + required: + - useMaxWidth + - padding + - maxNodeWidth + properties: + padding: + type: number + default: 10 + maxNodeWidth: + type: number + default: 200 + + PieDiagramConfig: + title: Pie Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + type: object + unevaluatedProperties: false + properties: + textPosition: + type: number + minimum: 0 + maximum: 1 + description: | + Axial position of slice's label from zero at the center to 1 at the outside edges. + default: 0.75 + + QuadrantChartConfig: + title: Quadrant Chart Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + type: object + unevaluatedProperties: false + required: + - chartWidth + - chartHeight + - titleFontSize + - titlePadding + - quadrantPadding + - xAxisLabelPadding + - yAxisLabelPadding + - xAxisLabelFontSize + - yAxisLabelFontSize + - quadrantLabelFontSize + - quadrantTextTopPadding + - pointTextPadding + - pointLabelFontSize + - pointRadius + - xAxisPosition + - yAxisPosition + - quadrantInternalBorderStrokeWidth + - quadrantExternalBorderStrokeWidth + - useMaxWidth + properties: + chartWidth: + description: Width of the chart + type: number + minimum: 0 + default: 500 + chartHeight: + description: Height of the chart + type: number + minimum: 0 + default: 500 + titleFontSize: + description: Chart title top and bottom padding + type: number + minimum: 0 + default: 20 + titlePadding: + description: Padding around the quadrant square + type: number + minimum: 0 + default: 10 + quadrantPadding: + description: quadrant title padding from top if the quadrant is rendered on top + type: number + minimum: 0 + default: 5 + xAxisLabelPadding: + description: Padding around x-axis labels + type: number + minimum: 0 + default: 5 + yAxisLabelPadding: + description: Padding around y-axis labels + type: number + minimum: 0 + default: 5 + xAxisLabelFontSize: + description: x-axis label font size + type: number + minimum: 0 + default: 16 + yAxisLabelFontSize: + description: y-axis label font size + type: number + minimum: 0 + default: 16 + quadrantLabelFontSize: + description: quadrant title font size + type: number + minimum: 0 + default: 16 + quadrantTextTopPadding: + description: quadrant title padding from top if the quadrant is rendered on top + type: number + minimum: 0 + default: 5 + pointTextPadding: + description: padding between point and point label + type: number + minimum: 0 + default: 5 + pointLabelFontSize: + description: point title font size + type: number + minimum: 0 + default: 12 + pointRadius: + description: radius of the point to be drawn + type: number + minimum: 0 + default: 5 + xAxisPosition: + description: position of x-axis labels + type: string + enum: + - top + - bottom + default: top + yAxisPosition: + description: position of y-axis labels + type: string + enum: + - left + - right + default: left + quadrantInternalBorderStrokeWidth: + description: stroke width of edges of the box that are inside the quadrant + type: number + minimum: 0 + default: 1 + quadrantExternalBorderStrokeWidth: + description: stroke width of edges of the box that are outside the quadrant + type: number + minimum: 0 + default: 2 + + ErDiagramConfig: + title: Er Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for entity relationship diagrams + type: object + unevaluatedProperties: false + required: + - titleTopMargin + - diagramPadding + - layoutDirection + - minEntityWidth + - minEntityHeight + - entityPadding + - stroke + - fill + # TODO: fontSize is the only property that is not required, is this correct? + - useMaxWidth + properties: + titleTopMargin: + $ref: '#/$defs/GitGraphDiagramConfig/properties/titleTopMargin' + default: 25 + diagramPadding: + description: | + The amount of padding around the diagram as a whole so that embedded + diagrams have margins, expressed in pixels. + type: integer + default: 20 + minimum: 0 + layoutDirection: + description: Directional bias for layout of entities + type: string + enum: ['TB', 'BT', 'LR', 'RL'] + meta:enum: + TB: Top-Bottom + BT: Bottom-Top + LR: Left-Right + RL: Right to Left + default: TB + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "TB" | "BT" | "LR" | "RL"' + minEntityWidth: + description: The minimum width of an entity box. Expressed in pixels. + type: integer + default: 100 + minimum: 0 + minEntityHeight: + description: The minimum height of an entity box. Expressed in pixels. + type: integer + default: 75 + minimum: 0 + entityPadding: + description: | + The minimum internal padding between text in an entity box and the enclosing box borders. + Expressed in pixels. + type: integer + default: 15 + minimum: 0 + stroke: + description: Stroke color of box edges and lines. + type: string + default: gray + fill: + description: Fill color of entity boxes + type: string + default: honeydew + fontSize: + description: Font size (expressed as an integer representing a number of pixels) + type: integer + default: 12 + minimum: 0 + + StateDiagramConfig: + title: State Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for entity relationship diagrams + type: object + unevaluatedProperties: false + required: + - titleTopMargin + - useMaxWidth + - defaultRenderer + properties: + titleTopMargin: + $ref: '#/$defs/GitGraphDiagramConfig/properties/titleTopMargin' + default: 25 + arrowMarkerAbsolute: + # TODO: use $ref: '#/properties/arrowMarkerAbsolute' to copy main setting + type: boolean + dividerMargin: + type: number + default: 10 + sizeUnit: + type: number + default: 5 + padding: + type: number + default: 8 + textHeight: + type: number + default: 10 + titleShift: + type: number + default: -15 + noteMargin: + type: number + default: 10 + forkWidth: + type: number + default: 70 + forkHeight: + type: number + default: 7 + # Used + miniPadding: + type: number + default: 2 + fontSizeFactor: + description: | + 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 + type: number + default: 5.02 + fontSize: + type: number + default: 24 + labelHeight: + type: number + default: 16 + edgeLengthFactor: + type: string + default: '20' + compositTitleSize: + type: number + default: 35 + radius: + type: number + default: 5 + defaultRenderer: + description: | + Decides which rendering engine that is to be used for the rendering. + type: string + enum: + - dagre-d3 + - dagre-wrapper + - elk + # todo, check this, old docs said dagre-d3 even though value was dagre-wrapper + default: dagre-wrapper + meta:enum: + dagre-d3: The [dagre-d3-es](https://www.npmjs.com/package/dagre-d3-es) library. + dagre-wrapper: wrapper for dagre implemented in mermaid + elk: Layout using [elkjs](https://github.com/kieler/elkjs) + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "dagre-d3" | "dagre-wrapper" | "elk"' + + ClassDiagramConfig: + title: Class Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + type: object + unevaluatedProperties: false + required: + - titleTopMargin + - useMaxWidth + - defaultRenderer + properties: + titleTopMargin: + $ref: '#/$defs/GitGraphDiagramConfig/properties/titleTopMargin' + default: 25 + # YAML anchor reference, don't use $ref since ajv doesn't load defaults + arrowMarkerAbsolute: *arrowMarkerAbsolute + dividerMargin: + type: number + default: 10 + padding: + type: number + default: 5 + textHeight: + type: number + default: 10 + defaultRenderer: + $ref: '#/$defs/StateDiagramConfig/properties/defaultRenderer' + default: dagre-wrapper + 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 + diagramPadding: + $ref: '#/$defs/ErDiagramConfig/properties/diagramPadding' + htmlLabels: + type: boolean + default: false + + JourneyDiagramConfig: + title: Journey Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: | + The object containing configurations specific for journey diagrams + type: object + unevaluatedProperties: false + required: + - diagramMarginX + - diagramMarginY + - leftMargin + - width + - height + - boxMargin + - boxTextMargin + - noteMargin + - messageMargin + - messageAlign + - bottomMarginAdj + - useMaxWidth + - rightAngles + properties: + diagramMarginX: + $ref: '#/$defs/C4DiagramConfig/properties/diagramMarginX' + default: 50 + diagramMarginY: + $ref: '#/$defs/C4DiagramConfig/properties/diagramMarginY' + default: 10 + leftMargin: + description: Margin between actors + type: integer + default: 150 + minimum: 0 + width: + description: Width of actor boxes + type: integer + default: 150 + minimum: 0 + height: + description: Height of actor boxes + type: integer + default: 50 + minimum: 0 + boxMargin: + description: Margin around loop boxes + type: integer + default: 10 + minimum: 0 + boxTextMargin: + description: Margin around the text in loop/alt/opt boxes + type: integer + default: 5 + minimum: 0 + noteMargin: + description: Margin around notes + type: integer + default: 10 + minimum: 0 + messageMargin: + description: Space between messages. + type: integer + default: 35 + minimum: 0 + messageAlign: + description: Multiline message alignment + type: string + enum: + - left + - center + - right + default: center + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "left" | "center" | "right"' + bottomMarginAdj: + description: | + Prolongs the edge of the diagram downwards. + + Depending on css styling this might need adjustment. + type: integer + default: 1 + minimum: 0 + rightAngles: + description: | + Curved Arrows become Right Angles + + This will display arrows that start and begin at the same node as + right angles, rather than as curves. + type: boolean + default: false + taskFontSize: + type: *fontSizeType + default: 14 + taskFontFamily: + type: string + default: '"Open Sans", sans-serif' + taskMargin: + type: number + default: 50 + activationWidth: + description: Width of activation box + type: number + default: 10 + textPlacement: + description: | + text placement as: tspan | fo | old only text as before + type: string + # TODO, should this be an enum? + default: fo + actorColours: + type: array + items: + type: string + default: ['#8FBC8F', '#7CFC00', '#00FFFF', '#20B2AA', '#B0E0E6', '#FFFFE0'] + sectionFills: + type: array + items: + type: string + default: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'] + sectionColours: + type: array + items: + type: string + default: ['#fff'] + + TimelineDiagramConfig: + # added by https://github.com/mermaid-js/mermaid/commit/0d5246fbc730bf15463d7183fe4400a1e2fc492c + title: Timeline Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + type: object + unevaluatedProperties: false + required: + - diagramMarginX + - diagramMarginY + - leftMargin + - width + - height + - boxMargin + - boxTextMargin + - noteMargin + - messageMargin + - messageAlign + - bottomMarginAdj + - useMaxWidth + properties: + diagramMarginX: + $ref: '#/$defs/C4DiagramConfig/properties/diagramMarginX' + default: 50 + diagramMarginY: + $ref: '#/$defs/C4DiagramConfig/properties/diagramMarginY' + default: 10 + leftMargin: + description: Margin between actors + type: integer + default: 150 + minimum: 0 + width: + description: Width of actor boxes + type: integer + default: 150 + minimum: 0 + height: + description: Height of actor boxes + type: integer + default: 50 + minimum: 0 + padding: + type: number + # should the default value be 50? + # see https://github.com/mermaid-js/mermaid/blob/7647ae317a7b2130e32777248d25a9c4d24b8f9f/packages/mermaid/src/diagrams/timeline/timelineRenderer.ts#L237 + boxMargin: + description: Margin around loop boxes + type: integer + default: 10 + minimum: 0 + boxTextMargin: + description: Margin around the text in loop/alt/opt boxes + type: integer + default: 5 + minimum: 0 + noteMargin: + description: Margin around notes + type: integer + default: 10 + minimum: 0 + messageMargin: + description: Space between messages. + type: integer + default: 35 + minimum: 0 + messageAlign: + description: Multiline message alignment + type: string + enum: + - left + - center + - right + default: center + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "left" | "center" | "right"' + bottomMarginAdj: + description: | + Prolongs the edge of the diagram downwards. + + Depending on css styling this might need adjustment. + type: integer + default: 1 + minimum: 0 + rightAngles: + description: | + Curved Arrows become Right Angles + + This will display arrows that start and begin at the same node as + right angles, rather than as curves. + type: boolean + default: false + taskFontSize: + type: *fontSizeType + default: 14 + taskFontFamily: + type: string + default: '"Open Sans", sans-serif' + taskMargin: + type: number + default: 50 + activationWidth: + description: Width of activation box + type: number + default: 10 + textPlacement: + description: | + text placement as: tspan | fo | old only text as before + type: string + # TODO, should this be an enum? + default: fo + actorColours: + type: array + items: + type: string + default: ['#8FBC8F', '#7CFC00', '#00FFFF', '#20B2AA', '#B0E0E6', '#FFFFE0'] + sectionFills: + type: array + items: + type: string + default: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'] + sectionColours: + type: array + items: + type: string + default: ['#fff'] + disableMulticolor: + # added by https://github.com/mermaid-js/mermaid/commit/652a42fe1aed7911a781a84716940a973b995639 + type: boolean + default: false + + GanttDiagramConfig: + title: Gantt Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: | + The object containing configurations specific for gantt diagrams + type: object + unevaluatedProperties: false + required: + - titleTopMargin + - barHeight + - topPadding + - rightPadding + - leftPadding + - gridLineStartPadding + - fontSize + - sectionFontSize + - numberSectionStyles + - axisFormat + - useMaxWidth + - topAxis + - weekday + properties: + titleTopMargin: + $ref: '#/$defs/GitGraphDiagramConfig/properties/titleTopMargin' + default: 25 + barHeight: + description: The height of the bars in the graph + type: integer + default: 20 + minimum: 0 + barGap: + description: The margin between the different activities in the gantt diagram + type: integer + default: 4 + minimum: 0 + topPadding: + description: | + Margin between title and gantt diagram and between axis and gantt diagram. + type: integer + default: 50 + minimum: 0 + rightPadding: + description: | + The space allocated for the section name to the right of the activities + type: integer + default: 75 + minimum: 0 + leftPadding: + description: | + The space allocated for the section name to the left of the activities + type: integer + default: 75 + minimum: 0 + gridLineStartPadding: + description: Vertical starting position of the grid lines + type: integer + default: 35 + minimum: 0 + fontSize: + description: Font size + type: integer + default: 11 + minimum: 0 + sectionFontSize: + description: Font size for sections + type: integer + # TODO: typescript type for this also allows strings, but the docs say only integers + tsType: 'string | number' + default: 11 + minimum: 0 + numberSectionStyles: + description: The number of alternating section styles + type: integer + default: 4 + minimum: 0 + axisFormat: + description: | + Date/time format of the axis + + This might need adjustment to match your locale and preferences. + type: string + default: '%Y-%m-%d' + tickInterval: + description: | + axis ticks + + Pattern is: + + ```javascript + /^([1-9][0-9]*)(millisecond|second|minute|hour|day|week|month)$/ + ``` + type: string + pattern: ^([1-9][0-9]*)(millisecond|second|minute|hour|day|week|month)$ + topAxis: + description: | + When this flag is set, date labels will be added to the top of the chart + type: boolean + default: false + displayMode: + description: | + Controls the display mode. + type: string + enum: + - '' + - compact + meta:enum: + compact: Enables displaying multiple tasks on the same row. + default: '' + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "compact"' + weekday: + description: | + On which day a week-based interval should start + type: string + tsType: '"monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday" | "sunday"' + enum: + - monday + - tuesday + - wednesday + - thursday + - friday + - saturday + - sunday + default: sunday + + SequenceDiagramConfig: + title: Sequence Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for sequence diagrams + type: object + unevaluatedProperties: false + required: + - activationWidth + - diagramMarginX + - diagramMarginY + - actorMargin + - width + - height + - boxMargin + - boxTextMargin + - noteMargin + - messageMargin + - messageAlign + - mirrorActors + - forceMenus + - bottomMarginAdj + - useMaxWidth + - rightAngles + - showSequenceNumbers + - actorFontSize + - actorFontFamily + - actorFontWeight + - noteFontSize + - noteFontFamily + - noteFontWeight + - noteAlign + - messageFontSize + - messageFontFamily + - messageFontWeight + properties: + arrowMarkerAbsolute: + type: boolean # TODO, is this actually used here (it has no default value but was in types) + hideUnusedParticipants: + type: boolean + default: false + activationWidth: + description: Width of the activation rect + type: integer + default: 10 + minimum: 0 + diagramMarginX: + description: Margin to the right and left of the sequence diagram + type: integer + default: 50 + minimum: 0 + diagramMarginY: + description: Margin to the over and under the sequence diagram + type: integer + default: 10 + minimum: 0 + actorMargin: + description: Margin between actors + type: integer + default: 50 + minimum: 0 + width: + $ref: '#/$defs/JourneyDiagramConfig/properties/width' + default: 150 + height: + $ref: '#/$defs/JourneyDiagramConfig/properties/height' + default: 65 + boxMargin: + $ref: '#/$defs/JourneyDiagramConfig/properties/boxMargin' + default: 10 + boxTextMargin: + $ref: '#/$defs/JourneyDiagramConfig/properties/boxTextMargin' + default: 5 + noteMargin: + $ref: '#/$defs/JourneyDiagramConfig/properties/noteMargin' + default: 10 + messageMargin: + $ref: '#/$defs/JourneyDiagramConfig/properties/messageMargin' + default: 35 + messageAlign: + $ref: '#/$defs/JourneyDiagramConfig/properties/messageAlign' + default: center + mirrorActors: + description: | + Mirror actors under diagram + type: boolean + default: true + forceMenus: + description: | + forces actor popup menus to always be visible (to support E2E testing). + type: boolean + default: false + bottomMarginAdj: + $ref: '#/$defs/JourneyDiagramConfig/properties/bottomMarginAdj' + default: 1 + rightAngles: + $ref: '#/$defs/JourneyDiagramConfig/properties/rightAngles' + default: false + showSequenceNumbers: + description: This will show the node numbers + type: boolean + default: false + actorFontSize: + description: This sets the font size of the actor's description + type: *fontSizeType + default: 14 + actorFontFamily: + description: This sets the font family of the actor's description + type: string + default: '"Open Sans", sans-serif' + actorFontWeight: + description: This sets the font weight of the actor's description + type: ['string', 'number'] + default: 400 + + noteFontSize: + description: This sets the font size of actor-attached notes + type: *fontSizeType + default: 14 + noteFontFamily: + description: This sets the font family of actor-attached notes + type: string + default: '"trebuchet ms", verdana, arial, sans-serif' + noteFontWeight: + description: This sets the font weight of actor-attached notes + type: ['string', 'number'] + default: 400 + noteAlign: + description: This sets the text alignment of actor-attached notes + type: string + enum: ['left', 'center', 'right'] + default: 'center' + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "left" | "center" | "right"' + + messageFontSize: + description: This sets the font size of actor messages + type: *fontSizeType + default: 16 + messageFontFamily: + description: This sets the font family of actor messages + type: string + default: '"trebuchet ms", verdana, arial, sans-serif' + messageFontWeight: + description: This sets the font weight of actor messages + type: ['string', 'number'] + default: 400 + + wrap: + description: This sets the auto-wrap state for the diagram + type: boolean + default: false # different from C4 Diagram + wrapPadding: + $ref: '#/$defs/C4DiagramConfig/properties/wrapPadding' + default: 10 + labelBoxWidth: + description: This sets the width of the loop-box (loop, alt, opt, par) + type: number + default: 50 + labelBoxHeight: + description: This sets the height of the loop-box (loop, alt, opt, par) + type: number + default: 20 + messageFont: { '$ref': '#/$defs/FontCalculator' } + noteFont: { '$ref': '#/$defs/FontCalculator' } + actorFont: { '$ref': '#/$defs/FontCalculator' } + + FlowchartDiagramConfig: + title: Flowchart Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for flowcharts + type: object + unevaluatedProperties: false + required: + - titleTopMargin + - diagramPadding + - htmlLabels + - nodeSpacing + - rankSpacing + - curve + - useMaxWidth + - defaultRenderer + - wrappingWidth + properties: + titleTopMargin: + $ref: '#/$defs/GitGraphDiagramConfig/properties/titleTopMargin' + default: 25 + arrowMarkerAbsolute: + type: boolean # TODO, is this actually used here (it has no default value but was in types) + diagramPadding: + $ref: '#/$defs/ErDiagramConfig/properties/diagramPadding' + default: 8 + htmlLabels: + description: | + Flag for setting whether or not a html tag should be used for rendering labels on the edges. + type: boolean + default: true + nodeSpacing: + description: | + 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. + type: integer + default: 50 + minimum: 0 + rankSpacing: + description: | + 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. + type: integer + default: 50 + minimum: 0 + curve: + description: | + Defines how mermaid renders curves for flowcharts. + type: string + enum: ['basis', 'linear', 'cardinal'] + default: 'basis' + # Allow any string for typescript backwards compatibility (fix in Mermaid v10) + tsType: 'string | "basis" | "linear" | "cardinal"' + padding: + description: | + Represents the padding between the labels and the shape + + **Only used in new experimental rendering.** + type: number + default: 15 + defaultRenderer: + $ref: '#/$defs/StateDiagramConfig/properties/defaultRenderer' + default: dagre-wrapper + wrappingWidth: + description: | + 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. + type: number + default: 200 + + SankeyLinkColor: + description: | + Picks the color of the sankey diagram links, using the colors of the source and/or target of the links. + type: string + enum: + - source + - target + - gradient + meta:enum: + source: Use the source of sankey link for the color of the link. + target: Use the target of sankey link for the color of the link. + gradient: Use a gradient of the source and target for the color of the link. + default: gradient + + SankeyNodeAlignment: + description: | + Controls the alignment of the Sankey diagrams. + + See <https://github.com/d3/d3-sankey#alignments>. + type: string + enum: + - left + - right + - center + - justify + meta:enum: + left: Align all inputs to the left. + right: Align all outputs to the right. + center: Like `left`, except that nodes without any incoming links are moved as right as possible. + justify: Like `left`, except that nodes without any outgoing links are moved to the far right. + default: justify + + SankeyDiagramConfig: + title: Sankey Diagram Config + allOf: [{ $ref: '#/$defs/BaseDiagramConfig' }] + description: The object containing configurations specific for sankey diagrams. + type: object + unevaluatedProperties: false + properties: + width: + type: number + default: 600 + height: + type: number + default: 400 + linkColor: + description: | + The color of the links in the sankey diagram. + anyOf: + - $ref: '#/$defs/SankeyLinkColor' + - description: An arbitrary [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) + type: string + default: gradient + nodeAlignment: + $ref: '#/$defs/SankeyNodeAlignment' + default: justify + useMaxWidth: + default: false + showValues: + description: | + Toggle to display or hide values along with title. + default: true + prefix: + description: | + The prefix to use for values + type: string + default: '' + suffix: + description: | + The suffix to use for values + type: string + default: '' + + FontCalculator: + title: Font Calculator + description: | + JavaScript function that returns a `FontConfig`. + + By default, these return the appropriate `*FontSize`, `*FontFamily`, `*FontWeight` + values. + + For example, the font calculator called `boundaryFont` might be defined as: + + ```javascript + boundaryFont: function () { + return { + fontFamily: this.boundaryFontFamily, + fontSize: this.boundaryFontSize, + fontWeight: this.boundaryFontWeight, + }; + } + ``` + tsType: '() => Partial<FontConfig>' + + FontConfig: + title: Font Config + type: object + additionalProperties: false + properties: + fontSize: + title: CSS Font Size + description: The font size to use + type: *fontSizeType + default: 14 + fontFamily: + description: The CSS [`font-family`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family) to use. + type: string + default: '"Open Sans", sans-serif' + fontWeight: + description: The font weight to use. + type: ['string', 'number'] + default: normal diff --git a/packages/mermaid/src/setupGraphViewbox.js b/packages/mermaid/src/setupGraphViewbox.js index 14929d3d7..ba74b79fd 100644 --- a/packages/mermaid/src/setupGraphViewbox.js +++ b/packages/mermaid/src/setupGraphViewbox.js @@ -1,4 +1,4 @@ -import { log } from './logger'; +import { log } from './logger.js'; /** * Applies d3 attributes @@ -35,7 +35,7 @@ export const calculateSvgSizeAttrs = function (height, width, useMaxWidth) { /** * Applies attributes from `calculateSvgSizeAttrs` * - * @param {SVGSVGElement} svgElem The SVG Element to configure + * @param {import('./diagram-api/types.js').SVG} svgElem The SVG Element to configure * @param {number} height The height of the SVG * @param {number} width The width of the SVG * @param {boolean} useMaxWidth Whether or not to use max-width and set width to 100% @@ -70,7 +70,6 @@ export const setupGraphViewbox = function (graph, svgElem, padding, useMaxWidth) height = sHeight + padding * 2; // } - // width = log.info(`Calculated bounds: ${width}x${height}`); configureSvgSize(svgElem, height, width, useMaxWidth); diff --git a/packages/mermaid/src/setupGraphViewbox.spec.js b/packages/mermaid/src/setupGraphViewbox.spec.js index 6b5c3e210..36154e2df 100644 --- a/packages/mermaid/src/setupGraphViewbox.spec.js +++ b/packages/mermaid/src/setupGraphViewbox.spec.js @@ -1,8 +1,8 @@ -import utils from './utils'; -import assignWithDepth from './assignWithDepth'; -import { detectType } from './diagram-api/detectType'; -import { addDiagrams } from './diagram-api/diagram-orchestration'; -import { calculateSvgSizeAttrs } from './setupGraphViewbox'; +import utils from './utils.js'; +import assignWithDepth from './assignWithDepth.js'; +import { detectType } from './diagram-api/detectType.js'; +import { addDiagrams } from './diagram-api/diagram-orchestration.js'; +import { calculateSvgSizeAttrs } from './setupGraphViewbox.js'; addDiagrams(); describe('when calculating SVG size', function () { diff --git a/packages/mermaid/src/styles.spec.ts b/packages/mermaid/src/styles.spec.ts new file mode 100644 index 000000000..420ee9757 --- /dev/null +++ b/packages/mermaid/src/styles.spec.ts @@ -0,0 +1,116 @@ +import { vi } from 'vitest'; + +// @ts-expect-error This module has no TypeScript types +import { validate } from 'csstree-validator'; +import { compile, serialize, stringify } from 'stylis'; + +import { getConfig } from './config.js'; +import theme from './themes/index.js'; + +/** + * Import the getStyles function from each diagram. + * + * Unfortunately, we can't use the `diagrams/*?/*Detector.ts` functions, + * because many of the diagrams have a circular dependency import error + * (they import mermaidAPI.js, which imports diagramOrchestrator.js, which causes a loop) + */ +import c4 from './diagrams/c4/styles.js'; +import classDiagram from './diagrams/class/styles.js'; +import flowchart from './diagrams/flowchart/styles.js'; +import flowchartElk from './diagrams/flowchart/elk/styles.js'; +import er from './diagrams/er/styles.js'; +import git from './diagrams/git/styles.js'; +import gantt from './diagrams/gantt/styles.js'; +import pie from './diagrams/pie/pieStyles.js'; +import requirement from './diagrams/requirement/styles.js'; +import sequence from './diagrams/sequence/styles.js'; +import state from './diagrams/state/styles.js'; +import journey from './diagrams/user-journey/styles.js'; +import timeline from './diagrams/timeline/styles.js'; +import mindmap from './diagrams/mindmap/styles.js'; +import themes from './themes/index.js'; + +async 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[]; + + const unexpectedErrors = errors.filter((error) => { + const cssErrorsToIgnore = [ + // Valid in SVG2, see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx + // Ideally, we'd remove this, since some browsers do not support SVG2. + 'Unknown property `rx`', + // Valid in SVG2, see https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry + 'Unknown property `ry`', + // TODO: I'm pretty sure that even in SVG2, this isn't allowed to be a CSS + // attribute. + 'Unknown property `dy`', + ]; + return !cssErrorsToIgnore.some((cssErrorToIgnore) => error.message.match(cssErrorToIgnore)); + }); + + if (unexpectedErrors.length > 0) { + throw new Error( + `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}` + ); + } +} + +describe('styles', () => { + beforeEach(() => { + // resets the styles added to addStylesForDiagram() + vi.resetModules(); + }); + + describe('getStyles', () => { + test('should return a valid style for an empty type', async () => { + const { default: getStyles, addStylesForDiagram } = await import('./styles.js'); + + const diagramType = 'my-custom-mocked-type-with-no-styles'; + const myTypeGetStylesFunc = vi.fn().mockReturnValue(''); + + addStylesForDiagram(diagramType, myTypeGetStylesFunc); + + const styles = getStyles(diagramType, '', getConfig().themeVariables); + + await checkValidStylisCSSStyleSheet(styles); + }); + + /** + * Test CSS for each diagram type and each theme. + */ + for (const themeId of Object.keys(theme) as (keyof typeof theme)[]) { + for (const [diagramId, getDiagramStyles] of Object.entries({ + c4, + classDiagram, + er, + flowchart, + flowchartElk, + gantt, + git, + journey, + mindmap, + pie, + requirement, + sequence, + state, + timeline, + })) { + test(`should return a valid style for diagram ${diagramId} and theme ${themeId}`, async () => { + const { default: getStyles, addStylesForDiagram } = await import('./styles.js'); + + addStylesForDiagram(diagramId, getDiagramStyles); + const styles = getStyles( + diagramId, + '', + // @ts-expect-error This will probably be broken until we create a proper Themes type. + themes[themeId].getThemeVariables() + ); + + await checkValidStylisCSSStyleSheet(styles); + }); + } + } + }); +}); diff --git a/packages/mermaid/src/styles.ts b/packages/mermaid/src/styles.ts index 055f63be5..fde079450 100644 --- a/packages/mermaid/src/styles.ts +++ b/packages/mermaid/src/styles.ts @@ -1,39 +1,8 @@ -import classDiagram from './diagrams/class/styles'; -import er from './diagrams/er/styles'; -import error from './diagrams/error/styles'; -import flowchart from './diagrams/flowchart/styles'; -import gantt from './diagrams/gantt/styles'; -// import gitGraph from './diagrams/git/styles'; -import info from './diagrams/info/styles'; -import pie from './diagrams/pie/styles'; -import requirement from './diagrams/requirement/styles'; -import sequence from './diagrams/sequence/styles'; -import stateDiagram from './diagrams/state/styles'; -import journey from './diagrams/user-journey/styles'; -import c4 from './diagrams/c4/styles'; -import { FlowChartStyleOptions } from './diagrams/flowchart/styles'; -import { log } from './logger'; +import type { FlowChartStyleOptions } from './diagrams/flowchart/styles.js'; +import { log } from './logger.js'; +import type { DiagramStylesProvider } from './diagram-api/types.js'; -// TODO @knut: Inject from registerDiagram. -const themes: Record<string, any> = { - flowchart, - 'flowchart-v2': flowchart, - sequence, - gantt, - classDiagram, - 'classDiagram-v2': classDiagram, - class: classDiagram, - stateDiagram, - state: stateDiagram, - // gitGraph, - info, - pie, - er, - error, - journey, - requirement, - c4, -}; +const themes: Record<string, DiagramStylesProvider> = {}; const getStyles = ( type: string, @@ -105,8 +74,10 @@ const getStyles = ( `; }; -export const addStylesForDiagram = (type: string, diagramTheme: unknown): void => { - themes[type] = diagramTheme; +export const addStylesForDiagram = (type: string, diagramTheme?: DiagramStylesProvider): void => { + if (diagramTheme !== undefined) { + themes[type] = diagramTheme; + } }; export default getStyles; diff --git a/packages/mermaid/src/tests/MockedD3.ts b/packages/mermaid/src/tests/MockedD3.ts index ccf21a269..c5e080ba3 100644 --- a/packages/mermaid/src/tests/MockedD3.ts +++ b/packages/mermaid/src/tests/MockedD3.ts @@ -1,5 +1,3 @@ -import type {} from '@vitest/spy/dist/index'; - /** * This is a mocked/stubbed version of the d3 Selection type. Each of the main functions are all * mocked (via vi.fn()) so you can track if they have been called, etc. @@ -7,9 +5,8 @@ import type {} from '@vitest/spy/dist/index'; * Note that node() returns a HTML Element with tag 'svg'. It is an empty element (no innerHTML, no children, etc). * This potentially allows testing of mermaidAPI render(). */ - export class MockedD3 { - public attribs = new Map<string, string | null>(); + public attribs = new Map<string, string>(); public id: string | undefined = ''; _children: MockedD3[] = []; @@ -72,9 +69,9 @@ export class MockedD3 { return newMock; }; - attr(attrName: string): null | undefined | string | number; - // attr(attrName: string, attrValue: string): MockedD3; - attr(attrName: string, attrValue?: string): null | undefined | string | number | MockedD3 { + attr(attrName: string): undefined | string; + attr(attrName: string, attrValue: string): MockedD3; + attr(attrName: string, attrValue?: string): undefined | string | MockedD3 { if (arguments.length === 1) { return this.attribs.get(attrName); } else { diff --git a/packages/mermaid/src/tests/util.ts b/packages/mermaid/src/tests/util.ts index 042f2cb43..922078876 100644 --- a/packages/mermaid/src/tests/util.ts +++ b/packages/mermaid/src/tests/util.ts @@ -7,8 +7,8 @@ Jest code ```ts it.each` str | expected -${'1d'} | ${moment.duration(1, 'd')} -${'2w'} | ${moment.duration(2, 'w')} +${'1d'} | ${dayjs.duration(1, 'd')} +${'2w'} | ${dayjs.duration(2, 'w')} `('should parse $str to $expected duration', ({ str, expected }) => { expect(yourFunction(str)).toEqual(expected); }); @@ -18,8 +18,8 @@ Vitest code ```ts it.each(convert` str | expected -${'1d'} | ${moment.duration(1, 'd')} -${'2w'} | ${moment.duration(2, 'w')} +${'1d'} | ${dayjs.duration(1, 'd')} +${'2w'} | ${dayjs.duration(2, 'w')} `)('should parse $str to $expected duration', ({ str, expected }) => { expect(yourFunction(str)).toEqual(expected); }); diff --git a/packages/mermaid/src/themes/index.js b/packages/mermaid/src/themes/index.js index 94e2b95a4..6ffe6274d 100644 --- a/packages/mermaid/src/themes/index.js +++ b/packages/mermaid/src/themes/index.js @@ -1,8 +1,8 @@ -import { getThemeVariables as baseThemeVariables } from './theme-base'; -import { getThemeVariables as darkThemeVariables } from './theme-dark'; -import { getThemeVariables as defaultThemeVariables } from './theme-default'; -import { getThemeVariables as forestThemeVariables } from './theme-forest'; -import { getThemeVariables as neutralThemeVariables } from './theme-neutral'; +import { getThemeVariables as baseThemeVariables } from './theme-base.js'; +import { getThemeVariables as darkThemeVariables } from './theme-dark.js'; +import { getThemeVariables as defaultThemeVariables } from './theme-default.js'; +import { getThemeVariables as forestThemeVariables } from './theme-forest.js'; +import { getThemeVariables as neutralThemeVariables } from './theme-neutral.js'; export default { base: { diff --git a/packages/mermaid/src/themes/theme-base.js b/packages/mermaid/src/themes/theme-base.js index 8ff544feb..ce1700d0b 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 } from 'khroma'; -import { mkBorder } from './theme-helpers'; +import { darken, lighten, adjust, invert, isDark, toRgba } from 'khroma'; +import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, oldAttributeBackgroundColorOdd, -} from './erDiagram-oldHardcodedValues'; +} from './erDiagram-oldHardcodedValues.js'; class Theme { constructor() { @@ -46,8 +46,12 @@ class Theme { this.secondaryTextColor = this.secondaryTextColor || invert(this.secondaryColor); this.tertiaryTextColor = this.tertiaryTextColor || invert(this.tertiaryColor); this.lineColor = this.lineColor || invert(this.background); + this.arrowheadColor = this.arrowheadColor || invert(this.background); this.textColor = this.textColor || this.primaryTextColor; + // TODO: should this instead default to secondaryBorderColor? + this.border2 = this.border2 || this.tertiaryBorderColor; + /* Flowchart variables */ this.nodeBkg = this.nodeBkg || this.primaryColor; this.mainBkg = this.mainBkg || this.primaryColor; @@ -212,12 +216,39 @@ class Theme { this.pieLegendTextColor = this.pieLegendTextColor || this.taskTextDarkColor; this.pieStrokeColor = this.pieStrokeColor || 'black'; this.pieStrokeWidth = this.pieStrokeWidth || '2px'; + this.pieOuterStrokeWidth = this.pieOuterStrokeWidth || '2px'; + this.pieOuterStrokeColor = this.pieOuterStrokeColor || 'black'; this.pieOpacity = this.pieOpacity || '0.7'; + /* quadrant-graph */ + this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; + this.quadrant2Fill = this.quadrant2Fill || adjust(this.primaryColor, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.primaryColor, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.primaryColor, { r: 15, g: 15, b: 15 }); + this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.primaryTextColor, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.primaryTextColor, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.primaryTextColor, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; + this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; + this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; + this.quadrantInternalBorderStrokeFill = + this.quadrantInternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantExternalBorderStrokeFill = + this.quadrantExternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantTitleFill = this.quadrantTitleFill || this.primaryTextColor; + /* requirement-diagram */ this.requirementBackground = this.requirementBackground || this.primaryColor; this.requirementBorderColor = this.requirementBorderColor || this.primaryBorderColor; - this.requirementBorderSize = this.requirementBorderSize || this.primaryBorderColor; + this.requirementBorderSize = this.requirementBorderSize || '1'; this.requirementTextColor = this.requirementTextColor || this.primaryTextColor; this.relationColor = this.relationColor || this.lineColor; this.relationLabelBackground = diff --git a/packages/mermaid/src/themes/theme-dark.js b/packages/mermaid/src/themes/theme-dark.js index af21b4f13..fd083e513 100644 --- a/packages/mermaid/src/themes/theme-dark.js +++ b/packages/mermaid/src/themes/theme-dark.js @@ -1,5 +1,5 @@ -import { invert, lighten, darken, rgba, adjust } from 'khroma'; -import { mkBorder } from './theme-helpers'; +import { invert, lighten, darken, rgba, adjust, isDark } from 'khroma'; +import { mkBorder } from './theme-helpers.js'; class Theme { constructor() { @@ -64,6 +64,7 @@ class Theme { this.sectionBkgColor = darken('#EAE8D9', 30); this.altSectionBkgColor = 'calculated'; this.sectionBkgColor2 = '#EAE8D9'; + this.excludeBkgColor = darken(this.sectionBkgColor, 10); this.taskBorderColor = rgba(255, 255, 255, 70); this.taskBkgColor = 'calculated'; this.taskTextColor = 'calculated'; @@ -81,9 +82,8 @@ class Theme { this.todayLineColor = '#DB5757'; /* C4 Context Diagram variables */ - - this.personBorder = 'calculated'; - this.personBkg = 'calculated'; + this.personBorder = this.primaryBorderColor; + this.personBkg = this.mainBkg; /* state colors */ this.labelColor = 'calculated'; @@ -222,15 +222,42 @@ class Theme { this.pieLegendTextColor = this.pieLegendTextColor || this.taskTextDarkColor; this.pieStrokeColor = this.pieStrokeColor || 'black'; this.pieStrokeWidth = this.pieStrokeWidth || '2px'; + this.pieOuterStrokeWidth = this.pieOuterStrokeWidth || '2px'; + this.pieOuterStrokeColor = this.pieOuterStrokeColor || 'black'; this.pieOpacity = this.pieOpacity || '0.7'; + /* quadrant-graph */ + this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; + this.quadrant2Fill = this.quadrant2Fill || adjust(this.primaryColor, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.primaryColor, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.primaryColor, { r: 15, g: 15, b: 15 }); + this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.primaryTextColor, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.primaryTextColor, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.primaryTextColor, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; + this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; + this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; + this.quadrantInternalBorderStrokeFill = + this.quadrantInternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantExternalBorderStrokeFill = + this.quadrantExternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantTitleFill = this.quadrantTitleFill || this.primaryTextColor; + /* class */ this.classText = this.primaryTextColor; /* requirement-diagram */ this.requirementBackground = this.requirementBackground || this.primaryColor; this.requirementBorderColor = this.requirementBorderColor || this.primaryBorderColor; - this.requirementBorderSize = this.requirementBorderSize || this.primaryBorderColor; + this.requirementBorderSize = this.requirementBorderSize || '1'; this.requirementTextColor = this.requirementTextColor || this.primaryTextColor; this.relationColor = this.relationColor || this.lineColor; this.relationLabelBackground = @@ -255,6 +282,14 @@ class Theme { this.gitInv5 = this.gitInv5 || invert(this.git5); this.gitInv6 = this.gitInv6 || invert(this.git6); this.gitInv7 = this.gitInv7 || invert(this.git7); + this.gitBranchLabel0 = this.gitBranchLabel0 || invert(this.labelTextColor); + this.gitBranchLabel1 = this.gitBranchLabel1 || this.labelTextColor; + this.gitBranchLabel2 = this.gitBranchLabel2 || this.labelTextColor; + this.gitBranchLabel3 = this.gitBranchLabel3 || invert(this.labelTextColor); + this.gitBranchLabel4 = this.gitBranchLabel4 || this.labelTextColor; + this.gitBranchLabel5 = this.gitBranchLabel5 || this.labelTextColor; + this.gitBranchLabel6 = this.gitBranchLabel6 || this.labelTextColor; + this.gitBranchLabel7 = this.gitBranchLabel7 || this.labelTextColor; this.tagLabelColor = this.tagLabelColor || this.primaryTextColor; this.tagLabelBackground = this.tagLabelBackground || this.primaryColor; diff --git a/packages/mermaid/src/themes/theme-default.js b/packages/mermaid/src/themes/theme-default.js index 391c0298f..3cd6bca4f 100644 --- a/packages/mermaid/src/themes/theme-default.js +++ b/packages/mermaid/src/themes/theme-default.js @@ -1,9 +1,9 @@ -import { invert, lighten, rgba, adjust, darken } from 'khroma'; -import { mkBorder } from './theme-helpers'; +import { invert, lighten, rgba, adjust, darken, isDark } from 'khroma'; +import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, oldAttributeBackgroundColorOdd, -} from './erDiagram-oldHardcodedValues'; +} from './erDiagram-oldHardcodedValues.js'; class Theme { constructor() { @@ -109,9 +109,8 @@ class Theme { this.todayLineColor = 'red'; /* C4 Context Diagram variables */ - - this.personBorder = 'calculated'; - this.personBkg = 'calculated'; + this.personBorder = this.primaryBorderColor; + this.personBkg = this.mainBkg; /* state colors */ this.labelColor = 'black'; @@ -244,12 +243,39 @@ class Theme { this.pieLegendTextColor = this.pieLegendTextColor || this.taskTextDarkColor; this.pieStrokeColor = this.pieStrokeColor || 'black'; this.pieStrokeWidth = this.pieStrokeWidth || '2px'; + this.pieOuterStrokeWidth = this.pieOuterStrokeWidth || '2px'; + this.pieOuterStrokeColor = this.pieOuterStrokeColor || 'black'; this.pieOpacity = this.pieOpacity || '0.7'; + /* quadrant-graph */ + this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; + this.quadrant2Fill = this.quadrant2Fill || adjust(this.primaryColor, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.primaryColor, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.primaryColor, { r: 15, g: 15, b: 15 }); + this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.primaryTextColor, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.primaryTextColor, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.primaryTextColor, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; + this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; + this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; + this.quadrantInternalBorderStrokeFill = + this.quadrantInternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantExternalBorderStrokeFill = + this.quadrantExternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantTitleFill = this.quadrantTitleFill || this.primaryTextColor; + /* requirement-diagram */ this.requirementBackground = this.requirementBackground || this.primaryColor; this.requirementBorderColor = this.requirementBorderColor || this.primaryBorderColor; - this.requirementBorderSize = this.requirementBorderSize || this.primaryBorderColor; + this.requirementBorderSize = this.requirementBorderSize || '1'; this.requirementTextColor = this.requirementTextColor || this.primaryTextColor; this.relationColor = this.relationColor || this.lineColor; this.relationLabelBackground = this.relationLabelBackground || this.labelBackground; diff --git a/packages/mermaid/src/themes/theme-forest.js b/packages/mermaid/src/themes/theme-forest.js index 59adc9139..65797b00c 100644 --- a/packages/mermaid/src/themes/theme-forest.js +++ b/packages/mermaid/src/themes/theme-forest.js @@ -1,9 +1,9 @@ -import { darken, lighten, adjust, invert } from 'khroma'; -import { mkBorder } from './theme-helpers'; +import { darken, lighten, adjust, invert, isDark } from 'khroma'; +import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, oldAttributeBackgroundColorOdd, -} from './erDiagram-oldHardcodedValues'; +} from './erDiagram-oldHardcodedValues.js'; class Theme { constructor() { @@ -83,9 +83,8 @@ class Theme { this.todayLineColor = 'red'; /* C4 Context Diagram variables */ - - this.personBorder = 'calculated'; - this.personBkg = 'calculated'; + this.personBorder = this.primaryBorderColor; + this.personBkg = this.mainBkg; /* state colors */ this.labelColor = 'black'; @@ -94,6 +93,15 @@ class Theme { this.errorTextColor = '#552222'; } updateColors() { + /* Sequence Diagram variables */ + this.actorBorder = darken(this.mainBkg, 20); + this.actorBkg = this.mainBkg; + this.labelBoxBkgColor = this.actorBkg; + this.labelTextColor = this.actorTextColor; + this.loopTextColor = this.actorTextColor; + this.noteBorderColor = this.border2; + this.noteTextColor = this.actorTextColor; + /* Each color-set will have a background, a foreground and a border color */ this.cScale0 = this.cScale0 || this.primaryColor; this.cScale1 = this.cScale1 || this.secondaryColor; @@ -145,16 +153,6 @@ class Theme { this.clusterBorder = this.border2; this.defaultLinkColor = this.lineColor; - /* Sequence Diagram variables */ - - this.actorBorder = darken(this.mainBkg, 20); - this.actorBkg = this.mainBkg; - this.labelBoxBkgColor = this.actorBkg; - this.labelTextColor = this.actorTextColor; - this.loopTextColor = this.actorTextColor; - this.noteBorderColor = this.border2; - this.noteTextColor = this.actorTextColor; - /* Gantt chart variables */ this.taskBorderColor = this.border1; @@ -213,12 +211,39 @@ class Theme { this.pieLegendTextColor = this.pieLegendTextColor || this.taskTextDarkColor; this.pieStrokeColor = this.pieStrokeColor || 'black'; this.pieStrokeWidth = this.pieStrokeWidth || '2px'; + this.pieOuterStrokeWidth = this.pieOuterStrokeWidth || '2px'; + this.pieOuterStrokeColor = this.pieOuterStrokeColor || 'black'; this.pieOpacity = this.pieOpacity || '0.7'; + /* quadrant-graph */ + this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; + this.quadrant2Fill = this.quadrant2Fill || adjust(this.primaryColor, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.primaryColor, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.primaryColor, { r: 15, g: 15, b: 15 }); + this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.primaryTextColor, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.primaryTextColor, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.primaryTextColor, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; + this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; + this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; + this.quadrantInternalBorderStrokeFill = + this.quadrantInternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantExternalBorderStrokeFill = + this.quadrantExternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantTitleFill = this.quadrantTitleFill || this.primaryTextColor; + /* requirement-diagram */ this.requirementBackground = this.requirementBackground || this.primaryColor; this.requirementBorderColor = this.requirementBorderColor || this.primaryBorderColor; - this.requirementBorderSize = this.requirementBorderSize || this.primaryBorderColor; + this.requirementBorderSize = this.requirementBorderSize || '1'; this.requirementTextColor = this.requirementTextColor || this.primaryTextColor; this.relationColor = this.relationColor || this.lineColor; this.relationLabelBackground = this.relationLabelBackground || this.edgeLabelBackground; @@ -260,6 +285,14 @@ class Theme { this.gitInv5 = this.gitInv5 || invert(this.git5); this.gitInv6 = this.gitInv6 || invert(this.git6); this.gitInv7 = this.gitInv7 || invert(this.git7); + this.gitBranchLabel0 = this.gitBranchLabel0 || invert(this.labelTextColor); + this.gitBranchLabel1 = this.gitBranchLabel1 || this.labelTextColor; + this.gitBranchLabel2 = this.gitBranchLabel2 || this.labelTextColor; + this.gitBranchLabel3 = this.gitBranchLabel3 || invert(this.labelTextColor); + this.gitBranchLabel4 = this.gitBranchLabel4 || this.labelTextColor; + this.gitBranchLabel5 = this.gitBranchLabel5 || this.labelTextColor; + this.gitBranchLabel6 = this.gitBranchLabel6 || this.labelTextColor; + this.gitBranchLabel7 = this.gitBranchLabel7 || this.labelTextColor; this.tagLabelColor = this.tagLabelColor || this.primaryTextColor; this.tagLabelBackground = this.tagLabelBackground || this.primaryColor; diff --git a/packages/mermaid/src/themes/theme-neutral.js b/packages/mermaid/src/themes/theme-neutral.js index e7a136c6b..963ce031d 100644 --- a/packages/mermaid/src/themes/theme-neutral.js +++ b/packages/mermaid/src/themes/theme-neutral.js @@ -1,9 +1,9 @@ -import { invert, darken, lighten, adjust } from 'khroma'; -import { mkBorder } from './theme-helpers'; +import { invert, darken, lighten, adjust, isDark } from 'khroma'; +import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, oldAttributeBackgroundColorOdd, -} from './erDiagram-oldHardcodedValues'; +} from './erDiagram-oldHardcodedValues.js'; // const Color = require ( 'khroma/dist/color' ).default // Color.format.hex.stringify(Color.parse('hsl(210, 66.6666666667%, 95%)')); // => "#EAF2FB" @@ -95,9 +95,8 @@ class Theme { this.todayLineColor = 'calculated'; /* C4 Context Diagram variables */ - - this.personBorder = 'calculated'; - this.personBkg = 'calculated'; + this.personBorder = this.primaryBorderColor; + this.personBkg = this.mainBkg; /* state colors */ this.labelColor = 'black'; @@ -109,6 +108,22 @@ class Theme { this.secondBkg = lighten(this.contrast, 55); this.border2 = this.contrast; + /* Sequence Diagram variables */ + + this.actorBorder = lighten(this.border1, 23); + this.actorBkg = this.mainBkg; + this.actorTextColor = this.text; + this.actorLineColor = this.lineColor; + this.signalColor = this.text; + this.signalTextColor = this.text; + this.labelBoxBkgColor = this.actorBkg; + this.labelBoxBorderColor = this.actorBorder; + this.labelTextColor = this.text; + this.loopTextColor = this.text; + this.noteBorderColor = '#999'; + this.noteBkgColor = '#666'; + this.noteTextColor = '#fff'; + /* Color Scale */ /* Each color-set will have a background, a foreground and a border color */ @@ -162,22 +177,6 @@ class Theme { this.defaultLinkColor = this.lineColor; this.titleColor = this.text; - /* Sequence Diagram variables */ - - this.actorBorder = lighten(this.border1, 23); - this.actorBkg = this.mainBkg; - this.actorTextColor = this.text; - this.actorLineColor = this.lineColor; - this.signalColor = this.text; - this.signalTextColor = this.text; - this.labelBoxBkgColor = this.actorBkg; - this.labelBoxBorderColor = this.actorBorder; - this.labelTextColor = this.text; - this.loopTextColor = this.text; - this.noteBorderColor = '#999'; - this.noteBkgColor = '#666'; - this.noteTextColor = '#fff'; - /* Gantt chart variables */ this.sectionBkgColor = lighten(this.contrast, 30); @@ -243,12 +242,39 @@ class Theme { this.pieLegendTextColor = this.pieLegendTextColor || this.taskTextDarkColor; this.pieStrokeColor = this.pieStrokeColor || 'black'; this.pieStrokeWidth = this.pieStrokeWidth || '2px'; + this.pieOuterStrokeWidth = this.pieOuterStrokeWidth || '2px'; + this.pieOuterStrokeColor = this.pieOuterStrokeColor || 'black'; this.pieOpacity = this.pieOpacity || '0.7'; + /* quadrant-graph */ + this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; + this.quadrant2Fill = this.quadrant2Fill || adjust(this.primaryColor, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.primaryColor, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.primaryColor, { r: 15, g: 15, b: 15 }); + this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.primaryTextColor, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.primaryTextColor, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.primaryTextColor, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; + this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; + this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; + this.quadrantInternalBorderStrokeFill = + this.quadrantInternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantExternalBorderStrokeFill = + this.quadrantExternalBorderStrokeFill || this.primaryBorderColor; + this.quadrantTitleFill = this.quadrantTitleFill || this.primaryTextColor; + /* requirement-diagram */ this.requirementBackground = this.requirementBackground || this.primaryColor; this.requirementBorderColor = this.requirementBorderColor || this.primaryBorderColor; - this.requirementBorderSize = this.requirementBorderSize || this.primaryBorderColor; + this.requirementBorderSize = this.requirementBorderSize || '1'; this.requirementTextColor = this.requirementTextColor || this.primaryTextColor; this.relationColor = this.relationColor || this.lineColor; this.relationLabelBackground = this.relationLabelBackground || this.edgeLabelBackground; diff --git a/packages/mermaid/src/utils.spec.js b/packages/mermaid/src/utils.spec.ts similarity index 78% rename from packages/mermaid/src/utils.spec.js rename to packages/mermaid/src/utils.spec.ts index 0f0bc1e92..271dc588c 100644 --- a/packages/mermaid/src/utils.spec.js +++ b/packages/mermaid/src/utils.spec.ts @@ -1,60 +1,60 @@ import { vi } from 'vitest'; -import utils from './utils'; -import assignWithDepth from './assignWithDepth'; -import { detectType } from './diagram-api/detectType'; -import { addDiagrams } from './diagram-api/diagram-orchestration'; +import utils, { cleanAndMerge } from './utils.js'; +import assignWithDepth from './assignWithDepth.js'; +import { detectType } from './diagram-api/detectType.js'; +import { addDiagrams } from './diagram-api/diagram-orchestration.js'; import memoize from 'lodash-es/memoize.js'; -import { MockedD3 } from './tests/MockedD3'; +import { MockedD3 } from './tests/MockedD3.js'; addDiagrams(); describe('when assignWithDepth: should merge objects within objects', function () { it('should handle simple, depth:1 types (identity)', function () { - let config_0 = { foo: 'bar', bar: 0 }; - let config_1 = { foo: 'bar', bar: 0 }; - let result = assignWithDepth(config_0, config_1); + const config_0 = { foo: 'bar', bar: 0 }; + const config_1 = { foo: 'bar', bar: 0 }; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_1); }); it('should handle simple, depth:1 types (dst: undefined)', function () { - let config_0 = undefined; - let config_1 = { foo: 'bar', bar: 0 }; - let result = assignWithDepth(config_0, config_1); + const config_0 = undefined; + const config_1 = { foo: 'bar', bar: 0 }; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_1); }); it('should handle simple, depth:1 types (src: undefined)', function () { - let config_0 = { foo: 'bar', bar: 0 }; - let config_1 = undefined; - let result = assignWithDepth(config_0, config_1); + const config_0 = { foo: 'bar', bar: 0 }; + const config_1 = undefined; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_0); }); it('should handle simple, depth:1 types (merge)', function () { - let config_0 = { foo: 'bar', bar: 0 }; - let config_1 = { foo: 'foo' }; - let result = assignWithDepth(config_0, config_1); + const config_0 = { foo: 'bar', bar: 0 }; + const config_1 = { foo: 'foo' }; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: 0 }); }); it('should handle depth:2 types (dst: orphan)', function () { - let config_0 = { foo: 'bar', bar: { foo: 'bar' } }; - let config_1 = { foo: 'bar' }; - let result = assignWithDepth(config_0, config_1); + const config_0 = { foo: 'bar', bar: { foo: 'bar' } }; + const config_1 = { foo: 'bar' }; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_0); }); it('should handle depth:2 types (dst: object, src: simple type)', function () { - let config_0 = { foo: 'bar', bar: { foo: 'bar' } }; - let config_1 = { foo: 'foo', bar: 'should NOT clobber' }; - let result = assignWithDepth(config_0, config_1); + const config_0 = { foo: 'bar', bar: { foo: 'bar' } }; + const config_1 = { foo: 'foo', bar: 'should NOT clobber' }; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: { foo: 'bar' } }); }); it('should handle depth:2 types (src: orphan)', function () { - let config_0 = { foo: 'bar' }; - let config_1 = { foo: 'bar', bar: { foo: 'bar' } }; - let result = assignWithDepth(config_0, config_1); + const config_0 = { foo: 'bar' }; + const config_1 = { foo: 'bar', bar: { foo: 'bar' } }; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual(config_1); }); it('should handle depth:2 types (merge)', function () { - let config_0 = { foo: 'bar', bar: { foo: 'bar' }, boofar: 1 }; - let config_1 = { foo: 'foo', bar: { bar: 0 }, foobar: 'foobar' }; - let result = assignWithDepth(config_0, config_1); + const config_0 = { foo: 'bar', bar: { foo: 'bar' }, boofar: 1 }; + const config_1 = { foo: 'foo', bar: { bar: 0 }, foobar: 'foobar' }; + const result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: { foo: 'bar', bar: 0 }, @@ -63,17 +63,17 @@ describe('when assignWithDepth: should merge objects within objects', function ( }); }); it('should handle depth:3 types (merge with clobber because assignWithDepth::depth == 2)', function () { - let config_0 = { + const config_0 = { foo: 'bar', bar: { foo: 'bar', bar: { foo: { message: 'this', willbe: 'clobbered' } } }, boofar: 1, }; - let config_1 = { + const config_1 = { foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } }, foobar: 'foobar', }; - let result = assignWithDepth(config_0, config_1); + const result = assignWithDepth(config_0, config_1); expect(result).toEqual({ foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } }, @@ -82,7 +82,7 @@ describe('when assignWithDepth: should merge objects within objects', function ( }); }); it('should handle depth:3 types (merge with clobber because assignWithDepth::depth == 1)', function () { - let config_0 = { + const config_0 = { foo: 'bar', bar: { foo: 'bar', @@ -90,12 +90,12 @@ describe('when assignWithDepth: should merge objects within objects', function ( }, boofar: 1, }; - let config_1 = { + const config_1 = { foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'this' } } }, foobar: 'foobar', }; - let result = assignWithDepth(config_0, config_1, { depth: 1 }); + const result = assignWithDepth(config_0, config_1, { depth: 1 }); expect(result).toEqual({ foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'this' } } }, @@ -104,17 +104,17 @@ describe('when assignWithDepth: should merge objects within objects', function ( }); }); it('should handle depth:3 types (merge with no clobber because assignWithDepth::depth == 3)', function () { - let config_0 = { + const config_0 = { foo: 'bar', bar: { foo: 'bar', bar: { foo: { message: '', willbe: 'present' } } }, boofar: 1, }; - let config_1 = { + const config_1 = { foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'this' } } }, foobar: 'foobar', }; - let result = assignWithDepth(config_0, config_1, { depth: 3 }); + const result = assignWithDepth(config_0, config_1, { depth: 3 }); expect(result).toEqual({ foo: 'foo', bar: { foo: 'foo', bar: { foo: { message: 'this', willbe: 'present' } } }, @@ -125,8 +125,8 @@ describe('when assignWithDepth: should merge objects within objects', function ( }); describe('when memoizing', function () { it('should return the same value', function () { - const fib = memoize( - function (n, x, canary) { + const fib: any = memoize( + function (n: number, x: string, canary: { flag: boolean }) { canary.flag = true; if (n < 2) { return 1; @@ -260,7 +260,7 @@ describe('when formatting urls', function () { it('should handle links', function () { const url = 'https://mermaid-js.github.io/mermaid/#/'; - let config = { securityLevel: 'loose' }; + const config = { securityLevel: 'loose' }; let result = utils.formatUrl(url, config); expect(result).toEqual(url); @@ -271,7 +271,7 @@ describe('when formatting urls', function () { it('should handle anchors', function () { const url = '#interaction'; - let config = { securityLevel: 'loose' }; + const config = { securityLevel: 'loose' }; let result = utils.formatUrl(url, config); expect(result).toEqual(url); @@ -282,7 +282,7 @@ describe('when formatting urls', function () { it('should handle mailto', function () { const url = 'mailto:user@user.user'; - let config = { securityLevel: 'loose' }; + const config = { securityLevel: 'loose' }; let result = utils.formatUrl(url, config); expect(result).toEqual(url); @@ -293,7 +293,7 @@ describe('when formatting urls', function () { it('should handle other protocols', function () { const url = 'notes://do-your-thing/id'; - let config = { securityLevel: 'loose' }; + const config = { securityLevel: 'loose' }; let result = utils.formatUrl(url, config); expect(result).toEqual(url); @@ -304,7 +304,7 @@ describe('when formatting urls', function () { it('should handle scripts', function () { const url = 'javascript:alert("test")'; - let config = { securityLevel: 'loose' }; + const config = { securityLevel: 'loose' }; let result = utils.formatUrl(url, config); expect(result).toEqual(url); @@ -425,6 +425,42 @@ describe('when parsing font sizes', function () { }); it('handles unparseable input', function () { + // @ts-expect-error Explicitly testing unparsable input expect(utils.parseFontSize({ fontSize: 14 })).toEqual([undefined, undefined]); }); }); + +describe('cleanAndMerge', () => { + test('should merge objects', () => { + expect(cleanAndMerge({ a: 1, b: 2 }, { b: 3 })).toEqual({ a: 1, b: 3 }); + expect(cleanAndMerge({ a: 1 }, { a: 2 })).toEqual({ a: 2 }); + }); + + test('should remove undefined values', () => { + expect(cleanAndMerge({ a: 1, b: 2 }, { b: undefined })).toEqual({ a: 1, b: 2 }); + expect(cleanAndMerge({ a: 1, b: 2 }, { a: 2, b: undefined })).toEqual({ a: 2, b: 2 }); + expect(cleanAndMerge({ a: 1, b: { c: 2 } }, { a: 2, b: undefined })).toEqual({ + a: 2, + b: { c: 2 }, + }); + // @ts-expect-error Explicitly testing different type + expect(cleanAndMerge({ a: 1, b: { c: 2 } }, { a: 2, b: { c: undefined } })).toEqual({ + a: 2, + b: { c: 2 }, + }); + }); + + test('should create deep copies of object', () => { + const input: { a: number; b?: number } = { a: 1 }; + const output = cleanAndMerge(input, { b: 2 }); + expect(output).toEqual({ a: 1, b: 2 }); + output.b = 3; + expect(input).toEqual({ a: 1 }); + + const inputDeep = { a: { b: 1 } }; + const outputDeep = cleanAndMerge(inputDeep, { a: { b: 2 } }); + expect(outputDeep).toEqual({ a: { b: 2 } }); + outputDeep.a.b = 3; + expect(inputDeep).toEqual({ a: { b: 1 } }); + }); +}); diff --git a/packages/mermaid/src/utils.ts b/packages/mermaid/src/utils.ts index 76fce1999..42b4ee67e 100644 --- a/packages/mermaid/src/utils.ts +++ b/packages/mermaid/src/utils.ts @@ -1,5 +1,6 @@ // @ts-nocheck : TODO Fix ts errors import { sanitizeUrl } from '@braintree/sanitize-url'; +import type { CurveFactory } from 'd3'; import { curveBasis, curveBasisClosed, @@ -13,7 +14,6 @@ import { curveCatmullRomClosed, curveCatmullRomOpen, curveCatmullRom, - CurveFactory, curveLinear, curveLinearClosed, curveMonotoneX, @@ -24,13 +24,17 @@ import { curveStepBefore, select, } from 'd3'; -import common from './diagrams/common/common'; -import { configKeys } from './defaultConfig'; -import { log } from './logger'; -import { detectType } from './diagram-api/detectType'; -import assignWithDepth from './assignWithDepth'; -import { MermaidConfig } from './config.type'; +import common from './diagrams/common/common.js'; +import { configKeys } from './defaultConfig.js'; +import { log } from './logger.js'; +import { detectType } from './diagram-api/detectType.js'; +import assignWithDepth from './assignWithDepth.js'; +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'; + +export const ZERO_WIDTH_SPACE = '\u200b'; // Effectively an enum of the supported curve types, accessible by name const d3CurveTypes = { @@ -55,7 +59,7 @@ const d3CurveTypes = { curveStepAfter: curveStepAfter, curveStepBefore: curveStepBefore, }; -const directive = /%{2}{\s*(?:(\w+)\s*:|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi; + const directiveWithoutOpen = /\s*(?:(\w+)(?=:):|(\w+))\s*(?:(\w+)|((?:(?!}%{2}).|\r?\n)*))?\s*(?:}%{2})?/gi; @@ -93,32 +97,36 @@ const directiveWithoutOpen = * @param config - Optional mermaid configuration object. * @returns The json object representing the init passed to mermaid.initialize() */ -export const detectInit = function (text: string, config?: MermaidConfig): MermaidConfig { +export const detectInit = function ( + text: string, + config?: MermaidConfig +): MermaidConfig | undefined { const inits = detectDirective(text, /(?:init\b)|(?:initialize\b)/); let results = {}; if (Array.isArray(inits)) { const args = inits.map((init) => init.args); - directiveSanitizer(args); - + sanitizeDirective(args); results = assignWithDepth(results, [...args]); } else { results = inits.args; } - if (results) { - let type = detectType(text, config); - ['config'].forEach((prop) => { - if (results[prop] !== undefined) { - if (type === 'flowchart-v2') { - type = 'flowchart'; - } - results[type] = results[prop]; - delete results[prop]; - } - }); + + if (!results) { + return; } - // Todo: refactor this, these results are never used + let type = detectType(text, config); + ['config'].forEach((prop) => { + if (results[prop] !== undefined) { + if (type === 'flowchart-v2') { + type = 'flowchart'; + } + results[type] = results[prop]; + delete results[prop]; + } + }); + return results; }; @@ -160,10 +168,10 @@ export const detectDirective = function ( ); let match; const result = []; - while ((match = directive.exec(text)) !== null) { + while ((match = directiveRegex.exec(text)) !== null) { // This is necessary to avoid infinite loops with zero-width matches - if (match.index === directive.lastIndex) { - directive.lastIndex++; + if (match.index === directiveRegex.lastIndex) { + directiveRegex.lastIndex++; } if ( (match && !type) || @@ -230,7 +238,7 @@ export function interpolateToCurve( * @param config - Configuration passed to MermaidJS * @returns The formatted URL or `undefined`. */ -export function formatUrl(linkStr: string, config: { securityLevel: string }): string | undefined { +export function formatUrl(linkStr: string, config: MermaidConfig): string | undefined { const url = linkStr.trim(); if (url) { @@ -765,13 +773,16 @@ export const calculateTextDimensions: ( const dim = { width: 0, height: 0, lineHeight: 0 }; for (const line of lines) { const textObj = getTextObj(); - textObj.text = line; + textObj.text = line || ZERO_WIDTH_SPACE; const textElem = drawSimpleText(g, textObj) .style('font-size', _fontSizePx) .style('font-weight', fontWeight) .style('font-family', fontFamily); const bBox = (textElem._groups || textElem)[0][0].getBBox(); + if (bBox.width === 0 && bBox.height === 0) { + throw new Error('svg element not in render tree'); + } dim.width = Math.round(Math.max(dim.width, bBox.width)); cheight = Math.round(bBox.height); dim.height += cheight; @@ -797,7 +808,7 @@ export const calculateTextDimensions: ( ); export const initIdGenerator = class iterator { - constructor(deterministic, seed) { + constructor(deterministic, seed?: any) { this.deterministic = deterministic; // TODO: Seed is only used for length? this.seed = seed; @@ -836,67 +847,63 @@ export const entityDecode = function (html: string): string { * * @param args - Directive's JSON */ -export const directiveSanitizer = (args: any) => { - log.debug('directiveSanitizer called with', args); - if (typeof args === 'object') { - // check for array - if (args.length) { - args.forEach((arg) => directiveSanitizer(arg)); - } else { - // This is an object - Object.keys(args).forEach((key) => { - log.debug('Checking key', key); - if (key.startsWith('__')) { - log.debug('sanitize deleting __ option', key); - delete args[key]; - } +export const sanitizeDirective = (args: unknown): void => { + log.debug('sanitizeDirective called with', args); - if (key.includes('proto')) { - log.debug('sanitize deleting proto option', key); - delete args[key]; - } + // Return if not an object + if (typeof args !== 'object' || args == null) { + return; + } - if (key.includes('constr')) { - log.debug('sanitize deleting constr option', key); - delete args[key]; - } + // Sanitize each element if an array + if (Array.isArray(args)) { + args.forEach((arg) => sanitizeDirective(arg)); + return; + } - if (key.includes('themeCSS')) { - log.debug('sanitizing themeCss option'); - args[key] = sanitizeCss(args[key]); - } - if (key.includes('fontFamily')) { - log.debug('sanitizing fontFamily option'); - args[key] = sanitizeCss(args[key]); - } - if (key.includes('altFontFamily')) { - log.debug('sanitizing altFontFamily option'); - args[key] = sanitizeCss(args[key]); - } - if (!configKeys.includes(key)) { - log.debug('sanitize deleting option', key); - delete args[key]; - } else { - if (typeof args[key] === 'object') { - log.debug('sanitize deleting object', key); - directiveSanitizer(args[key]); - } - } - }); + // Sanitize each key if an object + for (const key of Object.keys(args)) { + log.debug('Checking key', key); + if ( + key.startsWith('__') || + key.includes('proto') || + key.includes('constr') || + !configKeys.has(key) || + args[key] == null + ) { + log.debug('sanitize deleting key: ', key); + delete args[key]; + continue; + } + + // Recurse if an object + if (typeof args[key] === 'object') { + log.debug('sanitizing object', key); + sanitizeDirective(args[key]); + continue; + } + + const cssMatchers = ['themeCSS', 'fontFamily', 'altFontFamily']; + for (const cssKey of cssMatchers) { + if (key.includes(cssKey)) { + log.debug('sanitizing css option', key); + args[key] = sanitizeCss(args[key]); + } } } + if (args.themeVariables) { - const kArr = Object.keys(args.themeVariables); - for (const k of kArr) { + for (const k of Object.keys(args.themeVariables)) { const val = args.themeVariables[k]; - if (val && val.match && !val.match(/^[\d "#%(),.;A-Za-z]+$/)) { + if (val?.match && !val.match(/^[\d "#%(),.;A-Za-z]+$/)) { args.themeVariables[k] = ''; } } } log.debug('After sanitization', args); }; -export const sanitizeCss = (str) => { + +export const sanitizeCss = (str: string): string => { let startCnt = 0; let endCnt = 0; @@ -989,12 +996,17 @@ export const parseFontSize = (fontSize: string | number | undefined): [number?, } }; +export function cleanAndMerge<T>(defaultData: T, data?: Partial<T>): T { + return merge({}, defaultData, data); +} + export default { assignWithDepth, wrapLabel, calculateTextHeight, calculateTextWidth, calculateTextDimensions, + cleanAndMerge, detectInit, detectDirective, isSubstringInArray, @@ -1008,8 +1020,8 @@ export default { random, runFunc, entityDecode, - initIdGenerator: initIdGenerator, - directiveSanitizer, + initIdGenerator, + sanitizeDirective, sanitizeCss, insertTitle, parseFontSize, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c99933c35..b86be8ff1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,27 +1,37 @@ -lockfileVersion: 5.4-inlineSpecifiers +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false importers: .: devDependencies: '@applitools/eyes-cypress': - specifier: ^3.27.6 - version: 3.27.6 + specifier: ^3.33.1 + version: 3.33.1(typescript@5.1.3) '@commitlint/cli': - specifier: ^17.2.0 - version: 17.2.0 + specifier: ^17.6.1 + version: 17.6.1 '@commitlint/config-conventional': - specifier: ^17.2.0 - version: 17.2.0 + specifier: ^17.6.1 + version: 17.6.1 '@cspell/eslint-plugin': - specifier: ^6.14.2 - version: 6.14.2 + specifier: ^6.31.1 + version: 6.31.1 + '@cypress/code-coverage': + specifier: ^3.10.7 + version: 3.10.7(@babel/core@7.12.3)(@babel/preset-env@7.20.2)(babel-loader@9.1.2)(cypress@12.10.0)(webpack@5.88.2) + '@rollup/plugin-typescript': + specifier: ^11.1.1 + version: 11.1.1(typescript@5.1.3) '@types/cors': specifier: ^2.8.13 version: 2.8.13 '@types/eslint': - specifier: ^8.4.10 - version: 8.4.10 + specifier: ^8.37.0 + version: 8.37.0 '@types/express': specifier: ^4.17.17 version: 4.17.17 @@ -29,83 +39,83 @@ importers: specifier: ^4.0.5 version: 4.0.5 '@types/jsdom': - specifier: ^21.0.0 - version: 21.1.0 + specifier: ^21.1.1 + version: 21.1.1 '@types/lodash': - specifier: ^4.14.188 - version: 4.14.188 + specifier: ^4.14.194 + version: 4.14.194 '@types/mdast': - specifier: ^3.0.10 - version: 3.0.10 + specifier: ^3.0.11 + version: 3.0.11 '@types/node': - specifier: ^18.11.9 - version: 18.11.9 + specifier: ^18.16.0 + version: 18.16.0 '@types/prettier': - specifier: ^2.7.1 - version: 2.7.1 + specifier: ^2.7.2 + version: 2.7.2 '@types/rollup-plugin-visualizer': specifier: ^4.2.1 version: 4.2.1 '@typescript-eslint/eslint-plugin': - specifier: ^5.48.2 - version: 5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy + specifier: ^5.59.0 + version: 5.59.0(@typescript-eslint/parser@5.59.0)(eslint@8.39.0)(typescript@5.1.3) '@typescript-eslint/parser': - specifier: ^5.48.2 - version: 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - '@vitest/coverage-c8': - specifier: ^0.28.4 - version: 0.28.4_vun5xzxu3tkrssf3erdbijyyki + specifier: ^5.59.0 + version: 5.59.0(eslint@8.39.0)(typescript@5.1.3) + '@vitest/coverage-v8': + specifier: ^0.34.0 + version: 0.34.0(vitest@0.34.0) '@vitest/spy': - specifier: ^0.28.4 - version: 0.28.4 + specifier: ^0.34.0 + version: 0.34.0 '@vitest/ui': - specifier: ^0.28.4 - version: 0.28.4 + specifier: ^0.34.0 + version: 0.34.0(vitest@0.34.0) + ajv: + specifier: ^8.12.0 + version: 8.12.0 concurrently: - specifier: ^7.5.0 - version: 7.5.0 + specifier: ^8.0.1 + version: 8.0.1 cors: specifier: ^2.8.5 version: 2.8.5 - coveralls: - specifier: ^3.1.1 - version: 3.1.1 cypress: - specifier: ^12.0.0 - version: 12.5.1 + specifier: ^12.10.0 + version: 12.10.0 cypress-image-snapshot: specifier: ^4.0.1 - version: 4.0.1_cypress@12.5.1+jest@29.3.1 + version: 4.0.1(cypress@12.10.0)(jest@29.5.0) esbuild: - specifier: ^0.17.0 - version: 0.17.0 + specifier: ^0.19.0 + version: 0.19.0 eslint: - specifier: ^8.32.0 - version: 8.32.0 + specifier: ^8.39.0 + version: 8.39.0 eslint-config-prettier: - specifier: ^8.6.0 - version: 8.6.0_eslint@8.32.0 + specifier: ^8.8.0 + version: 8.8.0(eslint@8.39.0) eslint-plugin-cypress: - specifier: ^2.12.1 - version: 2.12.1_eslint@8.32.0 + specifier: ^2.13.2 + version: 2.13.2(eslint@8.39.0) eslint-plugin-html: specifier: ^7.1.0 version: 7.1.0 eslint-plugin-jest: - specifier: ^27.1.5 - version: 27.1.5_i5clxtuiaceouxhg5syqkw5wwi + specifier: ^27.2.1 + version: 27.2.1(@typescript-eslint/eslint-plugin@5.59.0)(eslint@8.39.0)(jest@29.5.0)(typescript@5.1.3) eslint-plugin-jsdoc: - specifier: ^39.6.2 - version: 39.6.2_eslint@8.32.0 + specifier: ^46.0.0 + version: 46.0.0(eslint@8.39.0) eslint-plugin-json: specifier: ^3.1.0 version: 3.1.0 eslint-plugin-lodash: specifier: ^7.4.0 - version: 7.4.0_eslint@8.32.0 + version: 7.4.0(eslint@8.39.0) eslint-plugin-markdown: specifier: ^3.0.0 - version: 3.0.0_eslint@8.32.0 + version: 3.0.0(eslint@8.39.0) eslint-plugin-no-only-tests: specifier: ^3.1.0 version: 3.1.0 @@ -113,20 +123,20 @@ importers: specifier: ^0.2.17 version: 0.2.17 eslint-plugin-unicorn: - specifier: ^45.0.0 - version: 45.0.0_eslint@8.32.0 + specifier: ^47.0.0 + version: 47.0.0(eslint@8.39.0) express: specifier: ^4.18.2 version: 4.18.2 globby: - specifier: ^13.1.2 - version: 13.1.2 + specifier: ^13.1.4 + version: 13.1.4 husky: - specifier: ^8.0.2 - version: 8.0.2 + specifier: ^8.0.3 + version: 8.0.3 jest: - specifier: ^29.3.1 - version: 29.3.1_odkjkoia5xunhxkdrka32ib6vi + specifier: ^29.5.0 + version: 29.5.0(@types/node@18.16.0)(ts-node@10.9.1) jison: specifier: ^0.4.18 version: 0.4.18 @@ -134,68 +144,86 @@ importers: specifier: ^4.1.0 version: 4.1.0 jsdom: - specifier: ^21.0.0 - version: 21.1.0 + specifier: ^22.0.0 + version: 22.0.0 lint-staged: - specifier: ^13.0.3 - version: 13.0.3 + specifier: ^13.2.1 + version: 13.2.1 + nyc: + specifier: ^15.1.0 + version: 15.1.0 path-browserify: specifier: ^1.0.1 version: 1.0.1 pnpm: - specifier: ^7.15.0 - version: 7.15.0 + specifier: ^8.6.8 + version: 8.6.8 prettier: - specifier: ^2.7.1 - version: 2.7.1 + specifier: ^2.8.8 + version: 2.8.8 prettier-plugin-jsdoc: specifier: ^0.4.2 - version: 0.4.2_prettier@2.7.1 + version: 0.4.2(prettier@2.8.8) rimraf: - specifier: ^4.0.0 - version: 4.1.2 + specifier: ^5.0.0 + version: 5.0.0 rollup-plugin-visualizer: - specifier: ^5.8.3 - version: 5.8.3 + specifier: ^5.9.2 + version: 5.9.2 start-server-and-test: - specifier: ^1.15.4 - version: 1.15.4 + specifier: ^2.0.0 + version: 2.0.0 ts-node: specifier: ^10.9.1 - version: 10.9.1_w6ufic3jqylcjznzspnj4wjqfe + version: 10.9.1(@types/node@18.16.0)(typescript@5.1.3) typescript: - specifier: ^4.8.4 - version: 4.9.5 + specifier: ^5.1.3 + version: 5.1.3 vite: - specifier: ^4.1.1 - version: 4.1.1_@types+node@18.11.9 + specifier: ^4.3.9 + version: 4.3.9(@types/node@18.16.0) + vite-plugin-istanbul: + specifier: ^4.1.0 + version: 4.1.0(vite@4.3.9) vitest: - specifier: ^0.28.5 - version: 0.28.5_vun5xzxu3tkrssf3erdbijyyki + specifier: ^0.34.0 + version: 0.34.0(@vitest/ui@0.34.0)(jsdom@22.0.0) packages/mermaid: dependencies: '@braintree/sanitize-url': - specifier: ^6.0.0 - version: 6.0.0 + specifier: ^6.0.1 + version: 6.0.2 + '@types/d3-scale': + specifier: ^4.0.3 + version: 4.0.3 + '@types/d3-scale-chromatic': + specifier: ^3.0.0 + version: 3.0.0 cytoscape: specifier: ^3.23.0 version: 3.23.0 cytoscape-cose-bilkent: specifier: ^4.1.0 - version: 4.1.0_cytoscape@3.23.0 + version: 4.1.0(cytoscape@3.23.0) cytoscape-fcose: specifier: ^2.1.0 - version: 2.1.0_cytoscape@3.23.0 + version: 2.1.0(cytoscape@3.23.0) d3: specifier: ^7.4.0 version: 7.8.2 + d3-sankey: + specifier: ^0.12.3 + version: 0.12.3 dagre-d3-es: - specifier: 7.0.8 - version: 7.0.8 + specifier: 7.0.10 + version: 7.0.10 + dayjs: + specifier: ^1.11.7 + version: 1.11.7 dompurify: - specifier: 2.4.3 - version: 2.4.3 + specifier: ^3.0.5 + version: 3.0.5 elkjs: specifier: ^0.8.2 version: 0.8.2 @@ -205,15 +233,15 @@ importers: lodash-es: specifier: ^4.17.21 version: 4.17.21 - moment-mini: - specifier: ^2.29.4 - version: 2.29.4 + mdast-util-from-markdown: + specifier: ^1.3.0 + version: 1.3.0 non-layered-tidy-tree-layout: specifier: ^2.0.2 version: 2.0.2 stylis: - specifier: ^4.1.2 - version: 4.1.2 + specifier: ^4.1.3 + version: 4.1.3 ts-dedent: specifier: ^2.2.0 version: 2.2.0 @@ -224,66 +252,84 @@ importers: specifier: ^1.2.0 version: 1.2.0 devDependencies: + '@adobe/jsonschema2md': + specifier: ^7.1.4 + version: 7.1.4 '@types/cytoscape': specifier: ^3.19.9 version: 3.19.9 '@types/d3': specifier: ^7.4.0 version: 7.4.0 + '@types/d3-sankey': + specifier: ^0.12.1 + version: 0.12.1 + '@types/d3-selection': + specifier: ^3.0.5 + version: 3.0.5 + '@types/d3-shape': + specifier: ^3.1.1 + version: 3.1.1 '@types/dompurify': - specifier: ^2.4.0 - version: 2.4.0 + specifier: ^3.0.2 + version: 3.0.2 '@types/jsdom': - specifier: ^21.0.0 - version: 21.1.0 + specifier: ^21.1.1 + version: 21.1.1 '@types/lodash-es': - specifier: ^4.17.6 - version: 4.17.6 + specifier: ^4.17.7 + version: 4.17.7 '@types/micromatch': specifier: ^4.0.2 version: 4.0.2 '@types/prettier': - specifier: ^2.7.1 - version: 2.7.1 + specifier: ^2.7.2 + version: 2.7.2 '@types/stylis': specifier: ^4.0.2 version: 4.0.2 '@types/uuid': - specifier: ^9.0.0 - version: 9.0.0 + specifier: ^9.0.1 + version: 9.0.1 '@typescript-eslint/eslint-plugin': - specifier: ^5.42.1 - version: 5.42.1_qxgr6oy2qtsmmpo3f6iejuryuq + specifier: ^5.59.0 + version: 5.59.0(@typescript-eslint/parser@5.59.0)(eslint@8.39.0)(typescript@5.0.4) '@typescript-eslint/parser': - specifier: ^5.42.1 - version: 5.42.1_yygwinqv3a2io74xmwofqb7uka + specifier: ^5.59.0 + version: 5.59.0(eslint@8.39.0)(typescript@5.0.4) + ajv: + specifier: ^8.11.2 + version: 8.12.0 chokidar: specifier: ^3.5.3 version: 3.5.3 concurrently: - specifier: ^7.5.0 - version: 7.5.0 - coveralls: - specifier: ^3.1.1 - version: 3.1.1 + specifier: ^8.0.1 + version: 8.0.1 cpy-cli: specifier: ^4.2.0 version: 4.2.0 cspell: - specifier: ^6.14.3 - version: 6.14.3 + specifier: ^6.31.1 + version: 6.31.1 + csstree-validator: + specifier: ^3.0.0 + version: 3.0.0 globby: - specifier: ^13.1.2 - version: 13.1.2 + specifier: ^13.1.4 + version: 13.1.4 jison: specifier: ^0.4.18 version: 0.4.18 js-base64: - specifier: ^3.7.2 - version: 3.7.2 + specifier: ^3.7.5 + version: 3.7.5 jsdom: - specifier: ^21.0.0 - version: 21.1.0 + specifier: ^22.0.0 + version: 22.0.0 + json-schema-to-typescript: + specifier: ^11.0.3 + version: 11.0.3 micromatch: specifier: ^4.0.5 version: 4.0.5 @@ -291,8 +337,8 @@ importers: specifier: ^1.0.1 version: 1.0.1 prettier: - specifier: ^2.7.1 - version: 2.7.1 + specifier: ^2.8.8 + version: 2.8.8 remark: specifier: ^14.0.2 version: 14.0.2 @@ -303,44 +349,50 @@ importers: specifier: ^3.0.1 version: 3.0.1 rimraf: - specifier: ^4.0.0 - version: 4.1.2 + specifier: ^5.0.0 + version: 5.0.0 start-server-and-test: - specifier: ^1.14.0 - version: 1.14.0 + specifier: ^2.0.0 + version: 2.0.0 + type-fest: + specifier: ^4.1.0 + version: 4.1.0 typedoc: - specifier: ^0.23.18 - version: 0.23.18_typescript@4.8.4 + specifier: ^0.25.0 + version: 0.25.0(typescript@5.0.4) typedoc-plugin-markdown: - specifier: ^3.13.6 - version: 3.13.6_typedoc@0.23.18 + specifier: ^3.15.2 + version: 3.15.2(typedoc@0.25.0) typescript: - specifier: ^4.8.4 - version: 4.8.4 + specifier: ^5.0.4 + version: 5.0.4 unist-util-flatmap: specifier: ^1.0.0 version: 1.0.0 + unist-util-visit: + specifier: ^4.1.2 + version: 4.1.2 vitepress: - specifier: ^1.0.0-alpha.46 - version: 1.0.0-alpha.46_tbpndr44ulefs3hehwpi2mkf2y + specifier: ^1.0.0-alpha.72 + version: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.16.0) vitepress-plugin-search: - specifier: ^1.0.4-alpha.19 - version: 1.0.4-alpha.19_g67lr3vgasogkevpbew55lljzq + specifier: ^1.0.4-alpha.20 + version: 1.0.4-alpha.20(flexsearch@0.7.31)(vitepress@1.0.0-alpha.72)(vue@3.3.4) packages/mermaid-example-diagram: dependencies: '@braintree/sanitize-url': - specifier: ^6.0.0 - version: 6.0.0 + specifier: ^6.0.1 + version: 6.0.2 cytoscape: specifier: ^3.23.0 version: 3.23.0 cytoscape-cose-bilkent: specifier: ^4.1.0 - version: 4.1.0_cytoscape@3.23.0 + version: 4.1.0(cytoscape@3.23.0) cytoscape-fcose: specifier: ^2.1.0 - version: 2.1.0_cytoscape@3.23.0 + version: 2.1.0(cytoscape@3.23.0) d3: specifier: ^7.0.0 version: 7.8.2 @@ -355,14 +407,79 @@ importers: specifier: ^3.19.9 version: 3.19.9 concurrently: - specifier: ^7.5.0 - version: 7.5.0 + specifier: ^8.0.0 + version: 8.0.1 mermaid: specifier: workspace:* version: link:../mermaid rimraf: - specifier: ^4.0.0 - version: 4.1.2 + specifier: ^5.0.0 + version: 5.0.0 + + packages/mermaid-zenuml: + dependencies: + '@zenuml/core': + specifier: ^3.0.6 + version: 3.0.6(ts-node@10.9.1) + devDependencies: + mermaid: + specifier: workspace:^ + version: link:../mermaid + + packages/mermaid/src/docs: + dependencies: + '@vueuse/core': + specifier: ^10.1.0 + version: 10.1.0(vue@3.3.4) + jiti: + specifier: ^1.18.2 + version: 1.18.2 + mermaid: + specifier: workspace:^ + version: link:../.. + vue: + specifier: ^3.3 + version: 3.3.4 + devDependencies: + '@iconify-json/carbon': + specifier: ^1.1.16 + version: 1.1.16 + '@unocss/reset': + specifier: ^0.55.2 + version: 0.55.2 + '@vite-pwa/vitepress': + specifier: ^0.2.0 + version: 0.2.0(vite-plugin-pwa@0.16.0) + '@vitejs/plugin-vue': + specifier: ^4.2.1 + version: 4.2.1(vite@4.3.9)(vue@3.3.4) + fast-glob: + specifier: ^3.2.12 + version: 3.2.12 + https-localhost: + specifier: ^4.7.1 + version: 4.7.1 + pathe: + specifier: ^1.1.0 + version: 1.1.0 + unocss: + specifier: ^0.55.2 + version: 0.55.2(postcss@8.4.27)(rollup@2.79.1)(vite@4.3.9) + unplugin-vue-components: + specifier: ^0.25.0 + version: 0.25.0(rollup@2.79.1)(vue@3.3.4) + vite: + specifier: ^4.3.9 + version: 4.3.9(@types/node@18.16.0) + vite-plugin-pwa: + specifier: ^0.16.0 + version: 0.16.0(vite@4.3.9)(workbox-build@7.0.0)(workbox-window@7.0.0) + vitepress: + specifier: 1.0.0-rc.10 + version: 1.0.0-rc.10(@algolia/client-search@4.19.1)(@types/node@18.16.0)(search-insights@2.6.0) + workbox-window: + specifier: ^7.0.0 + version: 7.0.0 tests/webpack: dependencies: @@ -374,55 +491,152 @@ importers: version: link:../../packages/mermaid devDependencies: webpack: - specifier: ^5.74.0 - version: 5.75.0_webpack-cli@4.10.0 + specifier: ^5.88.2 + version: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) webpack-cli: specifier: ^4.10.0 - version: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi + version: 4.10.0(webpack-dev-server@4.11.1)(webpack@5.88.2) webpack-dev-server: specifier: ^4.11.1 - version: 4.11.1_pda42hcaj7d62cr262fr632kue + version: 4.11.1(webpack-cli@4.10.0)(webpack@5.88.2) packages: - /@algolia/autocomplete-core/1.7.4: - resolution: {integrity: sha512-daoLpQ3ps/VTMRZDEBfU8ixXd+amZcNJ4QSP3IERGyzqnL5Ch8uSRFt/4G8pUvW9c3o6GA4vtVv4I4lmnkdXyg==} + /@adobe/helix-log@6.0.0: + resolution: {integrity: sha512-+9gpf49sFDmZLV3gtjY+RmEUistqYJdVWpiqlRYpxE59x5bHFzYf93dZ7fljSTBtZdVq8lm97HxrTUloh5HvRg==} dependencies: - '@algolia/autocomplete-shared': 1.7.4 + big.js: 6.2.1 + colorette: 2.0.20 + ferrum: 1.9.4 + phin: 3.7.0 + polka: 0.5.2 dev: true - /@algolia/autocomplete-preset-algolia/1.7.4_qs6lk5nhygj2o3hj4sf6xnr724: - resolution: {integrity: sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ==} + /@adobe/jsonschema2md@7.1.4: + resolution: {integrity: sha512-sqzH/G+2oNZi5ltwbl0hGJacGTDpXv7uUykzh+LD/DNfOIjUq577b1HbES/JP5yWcp4YkX4I3V5Kxltewr0BUg==} + engines: {node: '>= 14.0.0'} + hasBin: true + dependencies: + '@adobe/helix-log': 6.0.0 + '@types/json-schema': 7.0.11 + '@types/mdast': 3.0.11 + es2015-i18n-tag: 1.6.1 + ferrum: 1.9.4 + fs-extra: 11.0.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: 3.1.0 + readdirp: 3.6.0 + remark-gfm: 3.0.1 + remark-parse: 10.0.1 + remark-stringify: 10.0.2 + unified: 10.1.2 + unist-util-inspect: 7.0.1 + yargs: 17.6.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@algolia/autocomplete-core@1.8.2: + resolution: {integrity: sha512-mTeshsyFhAqw/ebqNsQpMtbnjr+qVOSKXArEj4K0d7sqc8It1XD0gkASwecm9mF/jlOQ4Z9RNg1HbdA8JPdRwQ==} + dependencies: + '@algolia/autocomplete-shared': 1.8.2 + dev: true + + /@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.6.0): + resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.6.0) + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + dev: true + + /@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.6.0): + resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} + peerDependencies: + search-insights: '>= 1 < 3' + dependencies: + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) + search-insights: 2.6.0 + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + dev: true + + /@algolia/autocomplete-preset-algolia@1.8.2(@algolia/client-search@4.19.1)(algoliasearch@4.14.2): + resolution: {integrity: sha512-J0oTx4me6ZM9kIKPuL3lyU3aB8DEvpVvR6xWmHVROx5rOYJGQcZsdG4ozxwcOyiiu3qxMkIbzntnV1S1VWD8yA==} peerDependencies: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' dependencies: - '@algolia/autocomplete-shared': 1.7.4 - '@algolia/client-search': 4.14.2 + '@algolia/autocomplete-shared': 1.8.2 + '@algolia/client-search': 4.19.1 algoliasearch: 4.14.2 dev: true - /@algolia/autocomplete-shared/1.7.4: - resolution: {integrity: sha512-2VGCk7I9tA9Ge73Km99+Qg87w0wzW4tgUruvWAn/gfey1ZXgmxZtyIRBebk35R1O8TbK77wujVtCnpsGpRy1kg==} + /@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1): + resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + dependencies: + '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) + '@algolia/client-search': 4.19.1 + algoliasearch: 4.19.1 dev: true - /@algolia/cache-browser-local-storage/4.14.2: + /@algolia/autocomplete-shared@1.8.2: + resolution: {integrity: sha512-b6Z/X4MczChMcfhk6kfRmBzPgjoPzuS9KGR4AFsiLulLNRAAqhP+xZTKtMnZGhLuc61I20d5WqlId02AZvcO6g==} + dev: true + + /@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1): + resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + dependencies: + '@algolia/client-search': 4.19.1 + algoliasearch: 4.19.1 + dev: true + + /@algolia/cache-browser-local-storage@4.14.2: resolution: {integrity: sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA==} dependencies: '@algolia/cache-common': 4.14.2 dev: true - /@algolia/cache-common/4.14.2: + /@algolia/cache-browser-local-storage@4.19.1: + resolution: {integrity: sha512-FYAZWcGsFTTaSAwj9Std8UML3Bu8dyWDncM7Ls8g+58UOe4XYdlgzXWbrIgjaguP63pCCbMoExKr61B+ztK3tw==} + dependencies: + '@algolia/cache-common': 4.19.1 + dev: true + + /@algolia/cache-common@4.14.2: resolution: {integrity: sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg==} dev: true - /@algolia/cache-in-memory/4.14.2: + /@algolia/cache-common@4.19.1: + resolution: {integrity: sha512-XGghi3l0qA38HiqdoUY+wvGyBsGvKZ6U3vTiMBT4hArhP3fOGLXpIINgMiiGjTe4FVlTa5a/7Zf2bwlIHfRqqg==} + dev: true + + /@algolia/cache-in-memory@4.14.2: resolution: {integrity: sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ==} dependencies: '@algolia/cache-common': 4.14.2 dev: true - /@algolia/client-account/4.14.2: + /@algolia/cache-in-memory@4.19.1: + resolution: {integrity: sha512-+PDWL+XALGvIginigzu8oU6eWw+o76Z8zHbBovWYcrtWOEtinbl7a7UTt3x3lthv+wNuFr/YD1Gf+B+A9V8n5w==} + dependencies: + '@algolia/cache-common': 4.19.1 + dev: true + + /@algolia/client-account@4.14.2: resolution: {integrity: sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w==} dependencies: '@algolia/client-common': 4.14.2 @@ -430,7 +644,15 @@ packages: '@algolia/transporter': 4.14.2 dev: true - /@algolia/client-analytics/4.14.2: + /@algolia/client-account@4.19.1: + resolution: {integrity: sha512-Oy0ritA2k7AMxQ2JwNpfaEcgXEDgeyKu0V7E7xt/ZJRdXfEpZcwp9TOg4TJHC7Ia62gIeT2Y/ynzsxccPw92GA==} + dependencies: + '@algolia/client-common': 4.19.1 + '@algolia/client-search': 4.19.1 + '@algolia/transporter': 4.19.1 + dev: true + + /@algolia/client-analytics@4.14.2: resolution: {integrity: sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ==} dependencies: '@algolia/client-common': 4.14.2 @@ -439,14 +661,30 @@ packages: '@algolia/transporter': 4.14.2 dev: true - /@algolia/client-common/4.14.2: + /@algolia/client-analytics@4.19.1: + resolution: {integrity: sha512-5QCq2zmgdZLIQhHqwl55ZvKVpLM3DNWjFI4T+bHr3rGu23ew2bLO4YtyxaZeChmDb85jUdPDouDlCumGfk6wOg==} + dependencies: + '@algolia/client-common': 4.19.1 + '@algolia/client-search': 4.19.1 + '@algolia/requester-common': 4.19.1 + '@algolia/transporter': 4.19.1 + dev: true + + /@algolia/client-common@4.14.2: resolution: {integrity: sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q==} dependencies: '@algolia/requester-common': 4.14.2 '@algolia/transporter': 4.14.2 dev: true - /@algolia/client-personalization/4.14.2: + /@algolia/client-common@4.19.1: + resolution: {integrity: sha512-3kAIVqTcPrjfS389KQvKzliC559x+BDRxtWamVJt8IVp7LGnjq+aVAXg4Xogkur1MUrScTZ59/AaUd5EdpyXgA==} + dependencies: + '@algolia/requester-common': 4.19.1 + '@algolia/transporter': 4.19.1 + dev: true + + /@algolia/client-personalization@4.14.2: resolution: {integrity: sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw==} dependencies: '@algolia/client-common': 4.14.2 @@ -454,7 +692,15 @@ packages: '@algolia/transporter': 4.14.2 dev: true - /@algolia/client-search/4.14.2: + /@algolia/client-personalization@4.19.1: + resolution: {integrity: sha512-8CWz4/H5FA+krm9HMw2HUQenizC/DxUtsI5oYC0Jxxyce1vsr8cb1aEiSJArQT6IzMynrERif1RVWLac1m36xw==} + dependencies: + '@algolia/client-common': 4.19.1 + '@algolia/requester-common': 4.19.1 + '@algolia/transporter': 4.19.1 + dev: true + + /@algolia/client-search@4.14.2: resolution: {integrity: sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw==} dependencies: '@algolia/client-common': 4.14.2 @@ -462,33 +708,67 @@ packages: '@algolia/transporter': 4.14.2 dev: true - /@algolia/logger-common/4.14.2: + /@algolia/client-search@4.19.1: + resolution: {integrity: sha512-mBecfMFS4N+yK/p0ZbK53vrZbL6OtWMk8YmnOv1i0LXx4pelY8TFhqKoTit3NPVPwoSNN0vdSN9dTu1xr1XOVw==} + dependencies: + '@algolia/client-common': 4.19.1 + '@algolia/requester-common': 4.19.1 + '@algolia/transporter': 4.19.1 + dev: true + + /@algolia/logger-common@4.14.2: resolution: {integrity: sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA==} dev: true - /@algolia/logger-console/4.14.2: + /@algolia/logger-common@4.19.1: + resolution: {integrity: sha512-i6pLPZW/+/YXKis8gpmSiNk1lOmYCmRI6+x6d2Qk1OdfvX051nRVdalRbEcVTpSQX6FQAoyeaui0cUfLYW5Elw==} + dev: true + + /@algolia/logger-console@4.14.2: resolution: {integrity: sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g==} dependencies: '@algolia/logger-common': 4.14.2 dev: true - /@algolia/requester-browser-xhr/4.14.2: + /@algolia/logger-console@4.19.1: + resolution: {integrity: sha512-jj72k9GKb9W0c7TyC3cuZtTr0CngLBLmc8trzZlXdfvQiigpUdvTi1KoWIb2ZMcRBG7Tl8hSb81zEY3zI2RlXg==} + dependencies: + '@algolia/logger-common': 4.19.1 + dev: true + + /@algolia/requester-browser-xhr@4.14.2: resolution: {integrity: sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw==} dependencies: '@algolia/requester-common': 4.14.2 dev: true - /@algolia/requester-common/4.14.2: + /@algolia/requester-browser-xhr@4.19.1: + resolution: {integrity: sha512-09K/+t7lptsweRTueHnSnmPqIxbHMowejAkn9XIcJMLdseS3zl8ObnS5GWea86mu3vy4+8H+ZBKkUN82Zsq/zg==} + dependencies: + '@algolia/requester-common': 4.19.1 + dev: true + + /@algolia/requester-common@4.14.2: resolution: {integrity: sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg==} dev: true - /@algolia/requester-node-http/4.14.2: + /@algolia/requester-common@4.19.1: + resolution: {integrity: sha512-BisRkcWVxrDzF1YPhAckmi2CFYK+jdMT60q10d7z3PX+w6fPPukxHRnZwooiTUrzFe50UBmLItGizWHP5bDzVQ==} + dev: true + + /@algolia/requester-node-http@4.14.2: resolution: {integrity: sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg==} dependencies: '@algolia/requester-common': 4.14.2 dev: true - /@algolia/transporter/4.14.2: + /@algolia/requester-node-http@4.19.1: + resolution: {integrity: sha512-6DK52DHviBHTG2BK/Vv2GIlEw7i+vxm7ypZW0Z7vybGCNDeWzADx+/TmxjkES2h15+FZOqVf/Ja677gePsVItA==} + dependencies: + '@algolia/requester-common': 4.19.1 + dev: true + + /@algolia/transporter@4.14.2: resolution: {integrity: sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ==} dependencies: '@algolia/cache-common': 4.14.2 @@ -496,254 +776,258 @@ packages: '@algolia/requester-common': 4.14.2 dev: true - /@applitools/core-base/1.1.7: - resolution: {integrity: sha512-jxiRS7pQ9Q6deXeDa/mIACL/7S7ZxIOms49WSZGhUjb+1bfKEsH6+kLZKy5wUDHrUWRqPdILkLKWgQ0rLnKmFA==} + /@algolia/transporter@4.19.1: + resolution: {integrity: sha512-nkpvPWbpuzxo1flEYqNIbGz7xhfhGOKGAZS7tzC+TELgEmi7z99qRyTfNSUlW7LZmB3ACdnqAo+9A9KFBENviQ==} + dependencies: + '@algolia/cache-common': 4.19.1 + '@algolia/logger-common': 4.19.1 + '@algolia/requester-common': 4.19.1 + dev: true + + /@alloc/quick-lru@5.2.0: + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + dev: false + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.17 + 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/utils@0.7.5: + resolution: {integrity: sha512-dlR6LdS+0SzOAPx/TPRhnoi7hE251OVeT2Snw0RguNbBSbjUHdWr0l3vcUUDg26rEysT89kCbtw1lVorBXLLCg==} + dev: true + + /@apideck/better-ajv-errors@0.3.6(ajv@8.12.0): + 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.1.56: + resolution: {integrity: sha512-eIHqaRUgXjle9n5V4mVIqhkINui7I9pQzaV2n8TV1vKPnTx7z53NzAW6Z9Gikoi4svG1In7pbg55kNtTtVmnPA==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/image': 1.0.4 - '@applitools/logger': 1.1.27 - '@applitools/req': 1.1.12 - '@applitools/utils': 1.3.13 + '@applitools/image': 1.0.34 + '@applitools/logger': 2.0.2 + '@applitools/req': 1.3.0 + '@applitools/utils': 1.3.37 + abort-controller: 3.0.0 + throat: 6.0.2 transitivePeerDependencies: - - encoding - supports-color dev: true - /@applitools/core-base/1.1.8: - resolution: {integrity: sha512-h5bm1uJmpn5NVagFnLpoXWEKfLtBBmdQsgtOwYAmbWGImMNsexEnki1JPPo4yTn6KN1sdGE1ShYo2+YzbQPgKA==} - engines: {node: '>=12.13.0'} - dependencies: - '@applitools/image': 1.0.5 - '@applitools/logger': 1.1.27 - '@applitools/req': 1.1.12 - '@applitools/utils': 1.3.13 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@applitools/core/1.2.4: - resolution: {integrity: sha512-BFbmUn39XFEVKHCb/bBXFZVAb46hOl4D/6VRnC5ey5tNTdriI35/l0jWpuBnYHU6LgK+5AvG70SUTKqiFJDZPQ==} + /@applitools/core@3.2.1(typescript@5.1.3): + resolution: {integrity: sha512-3Sq4r5cWrp/0hLxgb/AR+XdPTN+8AClZQGhqw4gze38BXeJO10FtxYhakOQ8iVuhUESwIHo86OCmLEGREZAroA==} engines: {node: '>=12.13.0'} hasBin: true dependencies: - '@applitools/core-base': 1.1.7 - '@applitools/dom-capture': 11.2.0 - '@applitools/dom-snapshot': 4.7.0 - '@applitools/driver': 1.11.0 - '@applitools/logger': 1.1.27 - '@applitools/nml-client': 1.3.5 - '@applitools/req': 1.1.12 - '@applitools/screenshoter': 3.7.0 - '@applitools/snippets': 2.4.5 - '@applitools/ufg-client': 1.1.2 - '@applitools/utils': 1.3.13 + '@applitools/core-base': 1.1.56 + '@applitools/dom-capture': 11.2.2 + '@applitools/dom-snapshot': 4.7.9 + '@applitools/driver': 1.12.1 + '@applitools/ec-client': 1.2.32(typescript@5.1.3) + '@applitools/logger': 2.0.2 + '@applitools/nml-client': 1.3.55 + '@applitools/req': 1.3.0 + '@applitools/screenshoter': 3.7.46 + '@applitools/snippets': 2.4.21 + '@applitools/socket': 1.1.1 + '@applitools/spec-driver-webdriver': 1.0.33(webdriver@7.30.0) + '@applitools/ufg-client': 1.2.18 + '@applitools/utils': 1.3.37 + '@types/ws': 8.5.4 abort-controller: 3.0.0 - throat: 6.0.1 + chalk: 4.1.2 + node-fetch: 2.6.7 + webdriver: 7.30.0(typescript@5.1.3) + ws: 8.12.0 + yargs: 17.6.2 transitivePeerDependencies: - bufferutil - encoding - supports-color + - typescript - utf-8-validate dev: true - /@applitools/core/1.2.7: - resolution: {integrity: sha512-cVH60tV3Uw1kIbml6IMPtwHRtJTRP5ySs2GRvDvHwq+dJNEddyIwJUwjHOI/xYYgc9rQRZOmM5Z4mzZXLjtgyw==} - engines: {node: '>=12.13.0'} - hasBin: true - dependencies: - '@applitools/core-base': 1.1.8 - '@applitools/dom-capture': 11.2.0 - '@applitools/dom-snapshot': 4.7.0 - '@applitools/driver': 1.11.1 - '@applitools/logger': 1.1.27 - '@applitools/nml-client': 1.3.5 - '@applitools/req': 1.1.12 - '@applitools/screenshoter': 3.7.2 - '@applitools/snippets': 2.4.6 - '@applitools/ufg-client': 1.1.2 - '@applitools/utils': 1.3.13 - abort-controller: 3.0.0 - throat: 6.0.1 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate - dev: true - - /@applitools/dom-capture/11.2.0: - resolution: {integrity: sha512-zFfYgvdXq5oTpLuYvOJdkh7jsbAxajOpD67pVoKc27lKwE0CGaM9I0Uf+qGh7GYtY93qyzMWBzqC7C8JlSK1gA==} + /@applitools/dom-capture@11.2.2: + resolution: {integrity: sha512-omSH+c8+ij/mUPKVwRp7ulCOz33EHMnG8Q3s7XuwaB9m04onEAg82/25otOrntqMKmO2doGWN3E97qUstZJiPQ==} engines: {node: '>=8.9.0'} dependencies: '@applitools/dom-shared': 1.0.5 '@applitools/functional-commons': 1.6.0 dev: true - /@applitools/dom-shared/1.0.5: + /@applitools/dom-shared@1.0.10: + resolution: {integrity: sha512-1k0CUQRm+38n6aTg/8IIppndYPDJLc/dU8Regbi/miP3xZmOG4Wwd5fBiu/MI5lgQm6RZU+at18lpCLFwU+Nng==} + engines: {node: '>=8.9.0'} + dev: true + + /@applitools/dom-shared@1.0.5: resolution: {integrity: sha512-O2zgnnqVi3/Atq7EQjURLa73XNaDFJCj8wHht6WQtxIv1EWYnPutNTmnJSKwK7FnbJAg65OVjZylcz4EezyYZA==} engines: {node: '>=8.9.0'} dev: true - /@applitools/dom-shared/1.0.9: - resolution: {integrity: sha512-u6nRHBklRAaODILm0HRluE0IAwrnjs8AMNRBFxHThKGt4qpbkhnwazGMr4zDu3WCBjr/sA31kekUqNl0Jx3YeQ==} - engines: {node: '>=8.9.0'} - dev: true - - /@applitools/dom-snapshot/4.7.0: - resolution: {integrity: sha512-exLRB2dTLiqD8i5oOK/QyfNMSLramVF5CFYNI29WWQjbXkIpCGOomGA8/xL+sYiC53jjx3Y9u6jHtlkb5ASJAQ==} + /@applitools/dom-snapshot@4.7.9: + resolution: {integrity: sha512-lY1tkNwNQUBM7snYUwVZ80EisgIYdNZxIBtbsRU0R60wKTQc8ccBPGo9e3TBbS4Z9XqQYVAupKQjZMlcMVEiwQ==} engines: {node: '>=8.9.0'} dependencies: - '@applitools/dom-shared': 1.0.9 + '@applitools/dom-shared': 1.0.10 '@applitools/functional-commons': 1.6.0 - css-tree: 1.0.0-alpha.39 + css-tree: 2.3.1 pako: 1.0.11 dev: true - /@applitools/driver/1.11.0: - resolution: {integrity: sha512-yNo4ljkk5C2wJ7foqENoIgtlbW3/RpDYBT5UCjq5yTK/xfnvAlh+zUmnqGJ43w8PZj4IH7E8xLRVBVIq2Mv9oQ==} + /@applitools/driver@1.12.1: + resolution: {integrity: sha512-/ku686w2BqCOVL1brBAgrGNGiFqPp+o9vUxmfNXTvsmrAYCsefyZ9R8APoRX0tQgNKr203F9UgaNDRRRmr+Uug==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/logger': 1.1.27 - '@applitools/snippets': 2.4.5 - '@applitools/utils': 1.3.13 + '@applitools/logger': 2.0.2 + '@applitools/snippets': 2.4.21 + '@applitools/utils': 1.3.37 semver: 7.3.7 + transitivePeerDependencies: + - supports-color dev: true - /@applitools/driver/1.11.1: - resolution: {integrity: sha512-HFkbEeTaBI+k5RMQFM6RjaIRCvLOrVx4UUDehnSlyfAwZIN/RMuxMcAQaiU5ZdNPf3K/+TtNjtmJoXuG8veEcQ==} - engines: {node: '>=12.13.0'} - dependencies: - '@applitools/logger': 1.1.27 - '@applitools/snippets': 2.4.6 - '@applitools/utils': 1.3.13 - semver: 7.3.7 - dev: true - - /@applitools/execution-grid-client/1.1.30: - resolution: {integrity: sha512-LoX0ZcNDZZV4aD6bpldfOTk94tNznRcIZPAVRRrKiqQJWJnDPP661EGxykXsfVnluCHaOGmbDPH6bfJGdDfUuQ==} + /@applitools/ec-client@1.2.32(typescript@5.1.3): + resolution: {integrity: sha512-03+qK41eza2808hXuc1D1UlJG+89oCF0EjJmP1Wkp2zq1nx6Za+R3NGVRTeUJhHhjOp6xdeqAHIyD8x1whCkmA==} engines: {node: '>=12.13.0'} hasBin: true dependencies: - '@applitools/logger': 1.1.27 - '@applitools/utils': 1.3.13 + '@applitools/core-base': 1.1.56 + '@applitools/driver': 1.12.1 + '@applitools/execution-grid-tunnel': 2.1.0 + '@applitools/logger': 2.0.2 + '@applitools/req': 1.3.0 + '@applitools/socket': 1.1.1 + '@applitools/spec-driver-webdriver': 1.0.33(webdriver@7.30.0) + '@applitools/utils': 1.3.37 abort-controller: 3.0.0 - node-fetch: 2.6.7 - proxy-agent: 5.0.0 - raw-body: 2.5.1 - yargs: 17.4.1 + webdriver: 7.30.0(typescript@5.1.3) + yargs: 17.6.2 transitivePeerDependencies: - - encoding - supports-color + - typescript dev: true - /@applitools/eyes-api/1.9.1: - resolution: {integrity: sha512-P/42YMcV8SbdZFXEph+Q37tMngIJv0jSC2S1QDp09/zi0V1z81yyAm8zK36PU0h0JTYeZxSs/T3BRhfitpzAIg==} + /@applitools/eg-frpc@1.0.3: + resolution: {integrity: sha512-16CrVdq2onkN5j6wpHxd8dfapJehHJq7GnYEg86QGFZPhTgZI5WukKrp9ryM0EblUJUjdTwEPymc5B8cffuZZQ==} engines: {node: '>=12.13.0'} - dependencies: - '@applitools/core': 1.2.4 - '@applitools/logger': 1.1.27 - '@applitools/utils': 1.3.13 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - utf-8-validate dev: true - /@applitools/eyes-cypress/3.27.6: - resolution: {integrity: sha512-2FpWKQ7rVhrr94Z8DjmJ8kD3f71aYahvTpT3dJyjfVKV8GxwAYAb/qrq6gAUnItaaoB2PgLHbIsqpOpRPki1tQ==} + /@applitools/eg-socks5-proxy-server@0.5.4: + resolution: {integrity: sha512-LEucOmy1MXft6c07CkqKPS1Ov9Zg9WyHV2vI1SbbHR3AG4cEM2M3N0qcWlytxjzef9t22+1tOpEJhrBS65bSQw==} + engines: {node: '>=12'} + dependencies: + binary: 0.3.0 + is-localhost-ip: 2.0.0 + dev: true + + /@applitools/execution-grid-tunnel@2.1.0: + resolution: {integrity: sha512-OooDCcS93+reh1hIpalDZVMhAsSaG/h+T5jGn7WzIYL4wVdi/GLyibvzxlY1hLFGi0EhUJGckpMoHiTZ6EuV2w==} engines: {node: '>=12.13.0'} hasBin: true dependencies: - '@applitools/core': 1.2.7 - '@applitools/eyes-api': 1.9.1 - '@applitools/eyes-universal': 2.16.9 + '@applitools/eg-frpc': 1.0.3 + '@applitools/eg-socks5-proxy-server': 0.5.4 + '@applitools/logger': 1.1.48 + dotenv: 16.0.3 + 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.9(encoding@0.1.13) + p-retry: 4.6.2 + teen_process: 1.16.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@applitools/eyes-cypress@3.33.1(typescript@5.1.3): + resolution: {integrity: sha512-hIvXiz/8xLarvnx78QuMm2NCkLYXgF/CC/X77dAAQO54tFgDmSsDaB9ak1cE5bDMCLxP84+roRghgJUQxpersQ==} + engines: {node: '>=12.13.0'} + hasBin: true + dependencies: + '@applitools/core': 3.2.1(typescript@5.1.3) + '@applitools/eyes': 1.2.14(typescript@5.1.3) '@applitools/functional-commons': 1.6.0 - '@applitools/logger': 1.1.27 + '@applitools/logger': 2.0.2 + '@applitools/utils': 1.3.37 + boxen: 5.1.2 chalk: 3.0.0 semver: 7.3.8 uuid: 8.3.2 - which: 2.0.2 ws: 8.5.0 transitivePeerDependencies: - bufferutil - encoding - supports-color + - typescript - utf-8-validate dev: true - /@applitools/eyes-sdk-core/13.11.15: - resolution: {integrity: sha512-oN2yTzFsuRMpmBpgzzqiUGRkezIez1JwQFRqqa6dsxUUBWE2IWp52MqJV5NRGHt9Sdh8q4+M6Hk6h8sVHE3LGg==} + /@applitools/eyes@1.2.14(typescript@5.1.3): + resolution: {integrity: sha512-pH9g3h2pQCGfrduT+gAZTyQ/iM+NxSmw3e8UjI+2/Zj0VnnlhprX18x5mT062tEZA6WExn59mLWsdZQcu1cDnA==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/core': 1.2.7 - '@applitools/driver': 1.11.1 - '@applitools/execution-grid-client': 1.1.30 - '@applitools/utils': 1.3.13 + '@applitools/core': 3.2.1(typescript@5.1.3) + '@applitools/logger': 2.0.2 + '@applitools/utils': 1.3.37 transitivePeerDependencies: - bufferutil - encoding - supports-color + - typescript - utf-8-validate dev: true - /@applitools/eyes-universal/2.16.9: - resolution: {integrity: sha512-D8MeOLoBETyg0oPxkaim3taiKWo6XMILTSAX+rWQHz0X7u+JRuCBLZu0WFlQPLTo7ndLiVyo2BpbBy9KIp5haA==} - engines: {node: '>=12.13.0'} - hasBin: true - dependencies: - '@applitools/core': 1.2.7 - '@applitools/driver': 1.11.1 - '@applitools/execution-grid-client': 1.1.30 - '@applitools/eyes-sdk-core': 13.11.15 - '@applitools/logger': 1.1.27 - '@applitools/utils': 1.3.13 - proxy-agent: 5.0.0 - webdriver: 7.16.11 - ws: 7.4.6 - yargs: 17.4.1 - transitivePeerDependencies: - - bufferutil - - encoding - - supports-color - - 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.0.4: - resolution: {integrity: sha512-eNr/fa+loGz1hrgwv/NKuVP13uRyfRUPFyCU8EtTdSWuGFJXIqwhtQWCFCokX1EXnhoCyGfFBAzWgW9StqTGfQ==} + /@applitools/image@1.0.34: + resolution: {integrity: sha512-PkgsC0bMrQl5XSsnWBz4rPxI1GeLr5OkV2X6Wr//HJPl/RpvKJYWVrgdwfA6Z+T10RETRqcxJAX5grvfytymog==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/utils': 1.3.13 + '@applitools/utils': 1.3.37 + bmpimagejs: 1.0.4 jpeg-js: 0.4.4 png-async: 0.9.4 dev: true - /@applitools/image/1.0.5: - resolution: {integrity: sha512-khv0fkjaoe0j/btEog8K/sqC2ULss+bkkHQQz80AOxnW/ixq5C4eQhTNzVRZ9/X7EDi7XsskvAXsi9RseIRnBw==} - engines: {node: '>=12.13.0'} - dependencies: - '@applitools/utils': 1.3.13 - jpeg-js: 0.4.4 - png-async: 0.9.4 - dev: true - - /@applitools/jsdom/1.0.4: + /@applitools/jsdom@1.0.4: resolution: {integrity: sha512-JtjNfTJtphJYHEkicW4xlwtYuRP3TRvjoszfkrcpxTNMCbGkbop8ed9MuUfR83dAZj5NY9begbmEqJohLJco6w==} engines: {node: '>=12'} dependencies: abab: 2.0.6 - acorn: 8.8.1 + acorn: 8.10.0 acorn-globals: 6.0.0 cssom: 0.5.0 cssstyle: 2.3.0 data-urls: 3.0.2 - decimal.js: 10.4.1 + decimal.js: 10.4.3 domexception: 4.0.0 escodegen: 2.0.0 form-data: 4.0.0 @@ -751,7 +1035,7 @@ packages: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.2 + nwsapi: 2.2.5 parse5: 6.0.1 saxes: 5.0.1 symbol-tree: 3.2.4 @@ -762,7 +1046,7 @@ packages: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 10.0.0 - ws: 8.9.0 + ws: 8.13.0 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -770,221 +1054,405 @@ packages: - utf-8-validate dev: true - /@applitools/logger/1.1.27: - resolution: {integrity: sha512-lwKCNhuMfLkqxfwYhLalDg2JZNgNj6rEgD8LnozsQdfxqVXThrJb/fkdSaSeUwnF+ljJyR7fnPy+p742p66U0Q==} + /@applitools/logger@1.1.48: + resolution: {integrity: sha512-A/8Q9p2INPDOMGE8Hqodpw5UxXLGdW4z2w8gOzEJ3zi0MyLOY3lBZiaPKEP0nmOs29q4r/yr0srYY5j9FVAmCg==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/utils': 1.3.13 + '@applitools/utils': 1.3.32 chalk: 4.1.2 - dev: true - - /@applitools/nml-client/1.3.5: - resolution: {integrity: sha512-MW1kB5AGe5l8HZ5GMkVhTm6XMndeIADmed37WrW3obD3FrmBGQLLj04GP6J7czLTeGjeh7QojvuAEvQUGFV5MQ==} - engines: {node: '>=12.13.0'} - dependencies: - '@applitools/logger': 1.1.27 - '@applitools/req': 1.1.12 - '@applitools/utils': 1.3.13 + debug: 4.3.3 transitivePeerDependencies: - - encoding - supports-color dev: true - /@applitools/req/1.1.12: - resolution: {integrity: sha512-eA8gsbqMxGEvW1KHb6P/AZ+IXlkxhf+Best683z9uo6O/wPQbg+B/20GoUpbUgpqWDQZmdhZDUb/RvxKwSl/PA==} + /@applitools/logger@2.0.2: + resolution: {integrity: sha512-tprqwPbP0q4bQ1wPJaLCb2nmFywRPJlwEADWJJ5oKJBhbvpqEKo6542GNp4DIebugLy99HUvkCTQS8ngKG0jdg==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/utils': 1.3.13 - '@types/node-fetch': 2.6.2 + '@applitools/utils': 1.3.37 + chalk: 4.1.2 + debug: 4.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@applitools/nml-client@1.3.55: + resolution: {integrity: sha512-r9C2fByQ0ce228LguFl/Q1RHjyhZZM+BOxOQosjt2NI5fW2NEByrjyfBrIU2JnZzArQjv8j6tX4ZgrpOXVpXxQ==} + engines: {node: '>=12.13.0'} + dependencies: + '@applitools/logger': 2.0.2 + '@applitools/req': 1.3.0 + '@applitools/utils': 1.3.37 + transitivePeerDependencies: + - supports-color + dev: true + + /@applitools/req@1.3.0: + resolution: {integrity: sha512-DwoWjMuP9VKpdCMqg91ItrQNKsjpGuYGAqvFitOpu4bs1kP0lcZHOHBuiHyNj97oUccJ1TT3RRrzrkA+byWseg==} + engines: {node: '>=12.13.0'} + dependencies: + '@applitools/utils': 1.3.37 abort-controller: 3.0.0 - node-fetch: 2.6.7 - proxy-agent: 5.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + node-fetch: 3.3.1 transitivePeerDependencies: - - encoding - supports-color dev: true - /@applitools/screenshoter/3.7.0: - resolution: {integrity: sha512-d723TI4InLQi06TpVj4rP+V5OrNL9mFQr+cWv2MOMfQbuAnZETTRzvDyk97e3qoDJHAPjyQuxi81qEaxsFxhOA==} + /@applitools/screenshoter@3.7.46: + resolution: {integrity: sha512-VOqzXm3BM4yKWIHxOZGFd+3NVyK9CgEYCxoywFqO+2G5dhYl2r51r60VKF3hS4A8ySXXqkJ878kaRceI3s8YNQ==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/image': 1.0.4 - '@applitools/logger': 1.1.27 - '@applitools/snippets': 2.4.5 - '@applitools/utils': 1.3.13 + '@applitools/image': 1.0.34 + '@applitools/logger': 2.0.2 + '@applitools/snippets': 2.4.21 + '@applitools/utils': 1.3.37 jpeg-js: 0.4.4 png-async: 0.9.4 + transitivePeerDependencies: + - supports-color dev: true - /@applitools/screenshoter/3.7.2: - resolution: {integrity: sha512-bWtNQeRvdcQBcc+5kAwVBnEQ3DhDncAE853SuJPgpczZkqy9t7Ot8L3kNLbi+210vbWSqpnVGt9tAeLgG/xZdA==} + /@applitools/snippets@2.4.21: + resolution: {integrity: sha512-3l+6pR0cJJjpG5subgqoI55vFFZ94//CS7jdhWuVwUtQJzeq6QSD6m/H+qfa8A7Sg9mzXnbyUenWQ7fpUk/5Fg==} + engines: {node: '>=12.13.0'} + dev: true + + /@applitools/socket@1.1.1: + resolution: {integrity: sha512-lQjglDC8r2QOVAQmZ+dqsTrtHMQ/9uAGsoMpFQo9amf+/DOipIwLKo0kGx+bMYmfDnAChlifukmMvrl9o1NcTQ==} engines: {node: '>=12.13.0'} dependencies: - '@applitools/image': 1.0.5 - '@applitools/logger': 1.1.27 - '@applitools/snippets': 2.4.6 - '@applitools/utils': 1.3.13 - jpeg-js: 0.4.4 - png-async: 0.9.4 + '@applitools/logger': 2.0.2 + '@applitools/utils': 1.3.37 + transitivePeerDependencies: + - supports-color dev: true - /@applitools/snippets/2.4.5: - resolution: {integrity: sha512-GoLN1wu8u5/qwdk1ozEElqmr4y7AoMQl0Ka0OzisGdx9/L7R0RzSWQCErjkf4LgKiWKK8j7lde3JT9yjxfritQ==} + /@applitools/spec-driver-webdriver@1.0.33(webdriver@7.30.0): + resolution: {integrity: sha512-5QbP945AyS5CjvqQ9N0d8UfnVKDjOsEhennm++W3xNBaBAGIQia2yP5xT3DFuEBH2fZCxJE+Cd/X1X4IbqGdfg==} engines: {node: '>=12.13.0'} + peerDependencies: + webdriver: '>=7.27.0' + dependencies: + '@applitools/driver': 1.12.1 + '@applitools/utils': 1.3.37 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + webdriver: 7.30.0(typescript@5.1.3) + transitivePeerDependencies: + - supports-color dev: true - /@applitools/snippets/2.4.6: - resolution: {integrity: sha512-hAsAalDxaa1w2RCEx2b35D9XJIGGRlqQKzXEE6/rNr5vMtT0eYye61SST5e2PD7B4F2jJ7jRKrZd7REawoxxmg==} - engines: {node: '>=12.13.0'} - dev: true - - /@applitools/ufg-client/1.1.2: - resolution: {integrity: sha512-yhjlp4QHWVazImfUUr9S9ueQhKstxfI3NNu/SLPPX7lHLOdpdWn7fUZOzTBCs6j914s87r9J9cmsU2gnOO8bOQ==} + /@applitools/ufg-client@1.2.18: + resolution: {integrity: sha512-2JzvCfJVtzyI4++jE6QDwm3nwIpuhaXVP1+BuqRnWFrwVFdwDwg24MkrF/WMX2gq6+x8tad7KXZ0rkQFhrQw5Q==} engines: {node: '>=12.13.0'} dependencies: '@applitools/jsdom': 1.0.4 - '@applitools/logger': 1.1.27 - '@applitools/req': 1.1.12 - '@applitools/utils': 1.3.13 + '@applitools/logger': 2.0.2 + '@applitools/req': 1.3.0 + '@applitools/utils': 1.3.37 abort-controller: 3.0.0 - postcss-value-parser: 4.2.0 + css-tree: 2.3.1 throat: 6.0.1 transitivePeerDependencies: - bufferutil - - encoding - supports-color - utf-8-validate dev: true - /@applitools/utils/1.3.13: - resolution: {integrity: sha512-UwA1skl9kzK+WrXu7WyX6A4K4TdIFZbDAcFJq2PA5fhmbviAlk4iFJtQjyopYTdY0sSh3VRSsCPr3DsbFa79AA==} + /@applitools/utils@1.3.32: + resolution: {integrity: sha512-GSMSf1NNW6fEm0u1ANGrQY+ESs8UgDYAZnaVrgjpFJ8ONL8eVDXn3tiIDdhmj/HKthAHqiYOYdRESmpuru/zrQ==} engines: {node: '>=12.13.0'} dev: true - /@babel/code-frame/7.18.6: + /@applitools/utils@1.3.37: + resolution: {integrity: sha512-w9RNmLoVg3BwOYCFOykqmM6pPgpgq3QuI3mUMSK3VLnOmkaz2bLqozTY7xOLnW4NACg/1hdpbVbrb8mygHYoEA==} + engines: {node: '>=12.13.0'} + dev: true + + /@arr/every@1.0.1: + resolution: {integrity: sha512-UQFQ6SgyJ6LX42W8rHCs8KVc0JS0tzVL9ct4XYedJukskYVWTo49tNiMEK9C2HTyarbNiT/RVIRSY82vH+6sTg==} + engines: {node: '>=4'} + dev: true + + /@babel/code-frame@7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} engines: {node: '>=6.9.0'} dependencies: '@babel/highlight': 7.18.6 dev: true - /@babel/core/7.12.3: + /@babel/compat-data@7.21.0: + resolution: {integrity: sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.12.3: resolution: {integrity: sha512-0qXcZYKZp3/6N2jKYVxZv0aNCsxTSVCiK72DTiTYZAu7sjg73W0/aynWjMbiGd87EQL4WyA8reiJVh92AVla9g==} engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.18.6 - '@babel/generator': 7.19.0 - '@babel/helper-module-transforms': 7.19.0 + '@babel/generator': 7.21.1 + '@babel/helper-module-transforms': 7.21.2 '@babel/helpers': 7.19.0 - '@babel/parser': 7.19.1 - '@babel/template': 7.18.10 - '@babel/traverse': 7.19.1 - '@babel/types': 7.19.0 + '@babel/parser': 7.21.8 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.2 + '@babel/types': 7.21.2 convert-source-map: 1.8.0 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 - json5: 2.2.1 + json5: 2.2.3 lodash: 4.17.21 - resolve: 1.22.1 + resolve: 1.22.2 semver: 5.7.1 source-map: 0.5.7 transitivePeerDependencies: - supports-color dev: true - /@babel/generator/7.19.0: - resolution: {integrity: sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==} + /@babel/generator@7.21.1: + resolution: {integrity: sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 '@jridgewell/gen-mapping': 0.3.2 + '@jridgewell/trace-mapping': 0.3.17 jsesc: 2.5.2 dev: true - /@babel/helper-environment-visitor/7.18.9: + /@babel/helper-annotate-as-pure@7.18.6: + resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.2 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: + resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-explode-assignable-expression': 7.18.6 + '@babel/types': 7.21.2 + dev: true + + /@babel/helper-compilation-targets@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.12.3 + '@babel/helper-validator-option': 7.21.0 + browserslist: 4.21.5 + lru-cache: 5.1.1 + semver: 6.3.0 + dev: true + + /@babel/helper-create-class-features-plugin@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-member-expression-to-functions': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-replace-supers': 7.20.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/helper-split-export-declaration': 7.18.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-create-regexp-features-plugin@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-annotate-as-pure': 7.18.6 + regexpu-core: 5.3.1 + dev: true + + /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.12.3): + resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} + peerDependencies: + '@babel/core': ^7.4.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + debug: 4.3.4(supports-color@8.1.1) + lodash.debounce: 4.0.8 + resolve: 1.22.2 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-environment-visitor@7.18.9: resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} engines: {node: '>=6.9.0'} dev: true - /@babel/helper-function-name/7.19.0: - resolution: {integrity: sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==} + /@babel/helper-explode-assignable-expression@7.18.6: + resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.18.10 - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 dev: true - /@babel/helper-hoist-variables/7.18.6: + /@babel/helper-function-name@7.21.0: + resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.20.7 + '@babel/types': 7.21.2 + dev: true + + /@babel/helper-hoist-variables@7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 dev: true - /@babel/helper-module-imports/7.18.6: + /@babel/helper-member-expression-to-functions@7.21.0: + resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.2 + dev: true + + /@babel/helper-module-imports@7.18.6: resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 dev: true - /@babel/helper-module-transforms/7.19.0: - resolution: {integrity: sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==} + /@babel/helper-module-transforms@7.21.2: + resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-module-imports': 7.18.6 - '@babel/helper-simple-access': 7.18.6 + '@babel/helper-simple-access': 7.20.2 '@babel/helper-split-export-declaration': 7.18.6 '@babel/helper-validator-identifier': 7.19.1 - '@babel/template': 7.18.10 - '@babel/traverse': 7.19.1 - '@babel/types': 7.19.0 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.2 + '@babel/types': 7.21.2 transitivePeerDependencies: - supports-color dev: true - /@babel/helper-plugin-utils/7.19.0: - resolution: {integrity: sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-simple-access/7.18.6: - resolution: {integrity: sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==} + /@babel/helper-optimise-call-expression@7.18.6: + resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 dev: true - /@babel/helper-split-export-declaration/7.18.6: + /@babel/helper-plugin-utils@7.20.2: + resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.12.3): + resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-wrap-function': 7.20.5 + '@babel/types': 7.21.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-replace-supers@7.20.7: + resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-member-expression-to-functions': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.2 + '@babel/types': 7.21.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-simple-access@7.20.2: + resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.2 + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.20.0: + resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.21.2 + dev: true + + /@babel/helper-split-export-declaration@7.18.6: resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} engines: {node: '>=6.9.0'} dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 dev: true - /@babel/helper-string-parser/7.18.10: - resolution: {integrity: sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==} + /@babel/helper-string-parser@7.19.4: + resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-validator-identifier/7.19.1: + /@babel/helper-validator-identifier@7.19.1: resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} + + /@babel/helper-validator-option@7.21.0: + resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} + engines: {node: '>=6.9.0'} dev: true - /@babel/helpers/7.19.0: - resolution: {integrity: sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==} + /@babel/helper-wrap-function@7.20.5: + resolution: {integrity: sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==} engines: {node: '>=6.9.0'} dependencies: - '@babel/template': 7.18.10 - '@babel/traverse': 7.19.1 - '@babel/types': 7.19.0 + '@babel/helper-function-name': 7.21.0 + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.2 + '@babel/types': 7.21.2 transitivePeerDependencies: - supports-color dev: true - /@babel/highlight/7.18.6: + /@babel/helpers@7.19.0: + resolution: {integrity: sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.20.7 + '@babel/traverse': 7.21.2 + '@babel/types': 7.21.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} dependencies: @@ -993,677 +1461,1413 @@ packages: js-tokens: 4.0.0 dev: true - /@babel/parser/7.19.1: - resolution: {integrity: sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==} + /@babel/parser@7.21.8: + resolution: {integrity: sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-async-generators/7.8.4_@babel+core@7.12.3: + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.12.3) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.12.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-static-block instead. + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.12.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-dynamic-import instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.12.3): + resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-json-strings instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-logical-assignment-operators instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.12.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-transform-parameters': 7.20.7(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.12.3) + dev: true + + /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-create-class-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.12.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} + engines: {node: '>=4'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.12.3): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-bigint/7.8.3_@babel+core@7.12.3: + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.12.3): resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-class-properties/7.12.13_@babel+core@7.12.3: + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.12.3): resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-import-meta/7.10.4_@babel+core@7.12.3: + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.12.3): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.12.3): + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.12.3): + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.12.3): + resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.12.3): resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-json-strings/7.8.3_@babel+core@7.12.3: + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.12.3): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-jsx/7.18.6_@babel+core@7.12.3: + /@babel/plugin-syntax-jsx@7.18.6(@babel/core@7.12.3): resolution: {integrity: sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-logical-assignment-operators/7.10.4_@babel+core@7.12.3: + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.12.3): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator/7.8.3_@babel+core@7.12.3: + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.12.3): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-numeric-separator/7.10.4_@babel+core@7.12.3: + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.12.3): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-object-rest-spread/7.8.3_@babel+core@7.12.3: + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.12.3): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-optional-catch-binding/7.8.3_@babel+core@7.12.3: + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.12.3): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-optional-chaining/7.8.3_@babel+core@7.12.3: + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.12.3): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-top-level-await/7.14.5_@babel+core@7.12.3: + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.12.3): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.12.3): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/plugin-syntax-typescript/7.18.6_@babel+core@7.12.3: + /@babel/plugin-syntax-typescript@7.18.6(@babel/core@7.12.3): resolution: {integrity: sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: '@babel/core': 7.12.3 - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/template/7.18.10: - resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} + /@babel/plugin-transform-arrow-functions@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/code-frame': 7.18.6 - '@babel/parser': 7.19.1 - '@babel/types': 7.19.0 + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 dev: true - /@babel/traverse/7.19.1: - resolution: {integrity: sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==} + /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/code-frame': 7.18.6 - '@babel/generator': 7.19.0 + '@babel/core': 7.12.3 + '@babel/helper-module-imports': 7.18.6 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.12.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-classes@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.12.3) '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.19.0 - '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-replace-supers': 7.20.7 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.19.1 - '@babel/types': 7.19.0 - debug: 4.3.4 globals: 11.12.0 transitivePeerDependencies: - supports-color dev: true - /@babel/types/7.19.0: - resolution: {integrity: sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==} + /@babel/plugin-transform-computed-properties@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 dependencies: - '@babel/helper-string-parser': 7.18.10 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/template': 7.20.7 dev: true - /@bcoe/v8-coverage/0.2.3: + /@babel/plugin-transform-destructuring@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.12.3): + resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-for-of@7.21.0(@babel/core@7.12.3): + resolution: {integrity: sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.12.3): + resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.12.3) + '@babel/helper-function-name': 7.21.0 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-literals@7.18.9(@babel/core@7.12.3): + resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.12.3): + resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-commonjs@7.21.2(@babel/core@7.12.3): + resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-simple-access': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.12.3): + resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-identifier': 7.19.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-module-transforms': 7.21.2 + '@babel/helper-plugin-utils': 7.20.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.12.3): + resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-replace-supers': 7.20.7 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/plugin-transform-parameters@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-regenerator@7.20.5(@babel/core@7.12.3): + resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + regenerator-transform: 0.15.1 + dev: true + + /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-spread@7.20.7(@babel/core@7.12.3): + resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + dev: true + + /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.12.3): + resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.12.3): + resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.12.3): + resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.12.3): + resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-create-regexp-features-plugin': 7.21.0(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + dev: true + + /@babel/preset-env@7.20.2(@babel/core@7.12.3): + resolution: {integrity: sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.12.3 + '@babel/helper-compilation-targets': 7.20.7(@babel/core@7.12.3) + '@babel/helper-plugin-utils': 7.20.2 + '@babel/helper-validator-option': 7.21.0 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.12.3) + '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.12.3) + '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.12.3) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.12.3) + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.12.3) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.12.3) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.12.3) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.12.3) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.12.3) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.12.3) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.12.3) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.12.3) + '@babel/plugin-transform-arrow-functions': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.12.3) + '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.12.3) + '@babel/plugin-transform-computed-properties': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-transform-destructuring': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.12.3) + '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-for-of': 7.21.0(@babel/core@7.12.3) + '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.12.3) + '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.12.3) + '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.12.3) + '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.12.3) + '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.12.3) + '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5(@babel/core@7.12.3) + '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-parameters': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-regenerator': 7.20.5(@babel/core@7.12.3) + '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-spread': 7.20.7(@babel/core@7.12.3) + '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.12.3) + '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.12.3) + '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.12.3) + '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.12.3) + '@babel/preset-modules': 0.1.5(@babel/core@7.12.3) + '@babel/types': 7.21.2 + babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.12.3) + babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.12.3) + babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.12.3) + core-js-compat: 3.28.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-modules@0.1.5(@babel/core@7.12.3): + resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-plugin-utils': 7.20.2 + '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.12.3) + '@babel/types': 7.21.2 + esutils: 2.0.3 + dev: true + + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + dev: true + + /@babel/runtime@7.21.0: + resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: true + + /@babel/template@7.20.7: + resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/parser': 7.21.8 + '@babel/types': 7.21.2 + dev: true + + /@babel/traverse@7.21.2: + resolution: {integrity: sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.18.6 + '@babel/generator': 7.21.1 + '@babel/helper-environment-visitor': 7.18.9 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-hoist-variables': 7.18.6 + '@babel/helper-split-export-declaration': 7.18.6 + '@babel/parser': 7.21.8 + '@babel/types': 7.21.2 + debug: 4.3.4(supports-color@8.1.1) + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.21.2: + resolution: {integrity: sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.19.4 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + + /@bcherny/json-schema-ref-parser@9.0.9: + resolution: {integrity: sha512-vmEmnJCfpkLdas++9OYg6riIezTYqTHpqUTODJzHLzs5UnXujbOJW9VwcVCnyo1mVRt32FRr23iXBx/sX8YbeQ==} + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.11 + call-me-maybe: 1.0.2 + js-yaml: 4.1.0 + dev: true + + /@bcoe/v8-coverage@0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true - /@braintree/sanitize-url/6.0.0: - resolution: {integrity: sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==} + /@braintree/sanitize-url@6.0.2: + resolution: {integrity: sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg==} dev: false - /@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 - /@commitlint/cli/17.2.0: - resolution: {integrity: sha512-kd1zykcrjIKyDRftWW1E1TJqkgzeosEkv1BiYPCdzkb/g/3BrfgwZUHR1vg+HO3qKUb/0dN+jNXArhGGAHpmaQ==} + /@commitlint/cli@17.6.1: + resolution: {integrity: sha512-kCnDD9LE2ySiTnj/VPaxy4/oRayRcdv4aCuVxtoum8SxIU7OADHc0nJPQfheE8bHcs3zZdWzDMWltRosuT13bg==} engines: {node: '>=v14'} hasBin: true dependencies: - '@commitlint/format': 17.0.0 - '@commitlint/lint': 17.2.0 - '@commitlint/load': 17.2.0 - '@commitlint/read': 17.2.0 - '@commitlint/types': 17.0.0 + '@commitlint/format': 17.4.4 + '@commitlint/lint': 17.6.1 + '@commitlint/load': 17.5.0 + '@commitlint/read': 17.5.1 + '@commitlint/types': 17.4.4 execa: 5.1.1 - lodash: 4.17.21 + lodash.isfunction: 3.0.9 resolve-from: 5.0.0 resolve-global: 1.0.0 - yargs: 17.5.1 + yargs: 17.7.2 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' dev: true - /@commitlint/config-conventional/17.2.0: - resolution: {integrity: sha512-g5hQqRa80f++SYS233dbDSg16YdyounMTAhVcmqtInNeY/GF3aA4st9SVtJxpeGrGmueMrU4L+BBb+6Vs5wrcg==} + /@commitlint/config-conventional@17.6.1: + resolution: {integrity: sha512-ng/ybaSLuTCH9F+7uavSOnEQ9EFMl7lHEjfAEgRh1hwmEe8SpLKpQeMo2aT1IWvHaGMuTb+gjfbzoRf2IR23NQ==} engines: {node: '>=v14'} dependencies: conventional-changelog-conventionalcommits: 5.0.0 dev: true - /@commitlint/config-validator/17.1.0: - resolution: {integrity: sha512-Q1rRRSU09ngrTgeTXHq6ePJs2KrI+axPTgkNYDWSJIuS1Op4w3J30vUfSXjwn5YEJHklK3fSqWNHmBhmTR7Vdg==} + /@commitlint/config-validator@17.4.4: + resolution: {integrity: sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.0.0 - ajv: 8.11.0 + '@commitlint/types': 17.4.4 + ajv: 8.12.0 dev: true - /@commitlint/ensure/17.0.0: - resolution: {integrity: sha512-M2hkJnNXvEni59S0QPOnqCKIK52G1XyXBGw51mvh7OXDudCmZ9tZiIPpU882p475Mhx48Ien1MbWjCP1zlyC0A==} + /@commitlint/ensure@17.4.4: + resolution: {integrity: sha512-AHsFCNh8hbhJiuZ2qHv/m59W/GRE9UeOXbkOqxYMNNg9pJ7qELnFcwj5oYpa6vzTSHtPGKf3C2yUFNy1GGHq6g==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.0.0 - lodash: 4.17.21 + '@commitlint/types': 17.4.4 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 dev: true - /@commitlint/execute-rule/17.0.0: - resolution: {integrity: sha512-nVjL/w/zuqjCqSJm8UfpNaw66V9WzuJtQvEnCrK4jDw6qKTmZB+1JQ8m6BQVZbNBcwfYdDNKnhIhqI0Rk7lgpQ==} + /@commitlint/execute-rule@17.4.0: + resolution: {integrity: sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==} engines: {node: '>=v14'} dev: true - /@commitlint/format/17.0.0: - resolution: {integrity: sha512-MZzJv7rBp/r6ZQJDEodoZvdRM0vXu1PfQvMTNWFb8jFraxnISMTnPBWMMjr2G/puoMashwaNM//fl7j8gGV5lA==} + /@commitlint/format@17.4.4: + resolution: {integrity: sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.0.0 + '@commitlint/types': 17.4.4 chalk: 4.1.2 dev: true - /@commitlint/is-ignored/17.2.0: - resolution: {integrity: sha512-rgUPUQraHxoMLxiE8GK430HA7/R2vXyLcOT4fQooNrZq9ERutNrP6dw3gdKLkq22Nede3+gEHQYUzL4Wu75ndg==} + /@commitlint/is-ignored@17.4.4: + resolution: {integrity: sha512-Y3eo1SFJ2JQDik4rWkBC4tlRIxlXEFrRWxcyrzb1PUT2k3kZ/XGNuCDfk/u0bU2/yS0tOA/mTjFsV+C4qyACHw==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.0.0 - semver: 7.3.7 + '@commitlint/types': 17.4.4 + semver: 7.3.8 dev: true - /@commitlint/lint/17.2.0: - resolution: {integrity: sha512-N2oLn4Dj672wKH5qJ4LGO+73UkYXGHO+NTVUusGw83SjEv7GjpqPGKU6KALW2kFQ/GsDefSvOjpSi3CzWHQBDg==} + /@commitlint/lint@17.6.1: + resolution: {integrity: sha512-VARJ9kxH64isgwVnC+ABPafCYzqxpsWJIpDaTuI0gh8aX4GQ0i7cn9tvxtFNfJj4ER2BAJeWJ0vURdNYjK2RQQ==} engines: {node: '>=v14'} dependencies: - '@commitlint/is-ignored': 17.2.0 - '@commitlint/parse': 17.2.0 - '@commitlint/rules': 17.2.0 - '@commitlint/types': 17.0.0 + '@commitlint/is-ignored': 17.4.4 + '@commitlint/parse': 17.4.4 + '@commitlint/rules': 17.6.1 + '@commitlint/types': 17.4.4 dev: true - /@commitlint/load/17.2.0: - resolution: {integrity: sha512-HDD57qSqNrk399R4TIjw31AWBG8dBjNj1MrDKZKmC/wvimtnIFlqzcu1+sxfXIOHj/+M6tcMWDtvknGUd7SU+g==} + /@commitlint/load@17.5.0: + resolution: {integrity: sha512-l+4W8Sx4CD5rYFsrhHH8HP01/8jEP7kKf33Xlx2Uk2out/UKoKPYMOIRcDH5ppT8UXLMV+x6Wm5osdRKKgaD1Q==} engines: {node: '>=v14'} dependencies: - '@commitlint/config-validator': 17.1.0 - '@commitlint/execute-rule': 17.0.0 - '@commitlint/resolve-extends': 17.1.0 - '@commitlint/types': 17.0.0 - '@types/node': 14.18.29 + '@commitlint/config-validator': 17.4.4 + '@commitlint/execute-rule': 17.4.0 + '@commitlint/resolve-extends': 17.4.4 + '@commitlint/types': 17.4.4 + '@types/node': 18.16.0 chalk: 4.1.2 - cosmiconfig: 7.0.1 - cosmiconfig-typescript-loader: 4.1.0_2uclxasecupgvdn72amnhmyg7y - lodash: 4.17.21 + cosmiconfig: 8.0.0 + cosmiconfig-typescript-loader: 4.1.0(@types/node@18.16.0)(cosmiconfig@8.0.0)(ts-node@10.9.1)(typescript@5.1.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 resolve-from: 5.0.0 - ts-node: 10.9.1_yxpazyh7n5pql7jdaglasgwqki - typescript: 4.9.5 + ts-node: 10.9.1(@types/node@18.16.0)(typescript@5.1.3) + typescript: 5.1.3 transitivePeerDependencies: - '@swc/core' - '@swc/wasm' dev: true - /@commitlint/message/17.2.0: - resolution: {integrity: sha512-/4l2KFKxBOuoEn1YAuuNNlAU05Zt7sNsC9H0mPdPm3chOrT4rcX0pOqrQcLtdMrMkJz0gC7b3SF80q2+LtdL9Q==} + /@commitlint/message@17.4.2: + resolution: {integrity: sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==} engines: {node: '>=v14'} dev: true - /@commitlint/parse/17.2.0: - resolution: {integrity: sha512-vLzLznK9Y21zQ6F9hf8D6kcIJRb2haAK5T/Vt1uW2CbHYOIfNsR/hJs0XnF/J9ctM20Tfsqv4zBitbYvVw7F6Q==} + /@commitlint/parse@17.4.4: + resolution: {integrity: sha512-EKzz4f49d3/OU0Fplog7nwz/lAfXMaDxtriidyGF9PtR+SRbgv4FhsfF310tKxs6EPj8Y+aWWuX3beN5s+yqGg==} engines: {node: '>=v14'} dependencies: - '@commitlint/types': 17.0.0 + '@commitlint/types': 17.4.4 conventional-changelog-angular: 5.0.13 conventional-commits-parser: 3.2.4 dev: true - /@commitlint/read/17.2.0: - resolution: {integrity: sha512-bbblBhrHkjxra3ptJNm0abxu7yeAaxumQ8ZtD6GIVqzURCETCP7Dm0tlVvGRDyXBuqX6lIJxh3W7oyKqllDsHQ==} + /@commitlint/read@17.5.1: + resolution: {integrity: sha512-7IhfvEvB//p9aYW09YVclHbdf1u7g7QhxeYW9ZHSO8Huzp8Rz7m05aCO1mFG7G8M+7yfFnXB5xOmG18brqQIBg==} engines: {node: '>=v14'} dependencies: - '@commitlint/top-level': 17.0.0 - '@commitlint/types': 17.0.0 - fs-extra: 10.1.0 + '@commitlint/top-level': 17.4.0 + '@commitlint/types': 17.4.4 + fs-extra: 11.1.1 git-raw-commits: 2.0.11 - minimist: 1.2.6 + minimist: 1.2.8 dev: true - /@commitlint/resolve-extends/17.1.0: - resolution: {integrity: sha512-jqKm00LJ59T0O8O4bH4oMa4XyJVEOK4GzH8Qye9XKji+Q1FxhZznxMV/bDLyYkzbTodBt9sL0WLql8wMtRTbqQ==} + /@commitlint/resolve-extends@17.4.4: + resolution: {integrity: sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==} engines: {node: '>=v14'} dependencies: - '@commitlint/config-validator': 17.1.0 - '@commitlint/types': 17.0.0 + '@commitlint/config-validator': 17.4.4 + '@commitlint/types': 17.4.4 import-fresh: 3.3.0 - lodash: 4.17.21 + lodash.mergewith: 4.6.2 resolve-from: 5.0.0 resolve-global: 1.0.0 dev: true - /@commitlint/rules/17.2.0: - resolution: {integrity: sha512-1YynwD4Eh7HXZNpqG8mtUlL2pSX2jBy61EejYJv4ooZPcg50Ak7LPOyD3a9UZnsE76AXWFBz+yo9Hv4MIpAa0Q==} + /@commitlint/rules@17.6.1: + resolution: {integrity: sha512-lUdHw6lYQ1RywExXDdLOKxhpp6857/4c95Dc/1BikrHgdysVUXz26yV0vp1GL7Gv+avx9WqZWTIVB7pNouxlfw==} engines: {node: '>=v14'} dependencies: - '@commitlint/ensure': 17.0.0 - '@commitlint/message': 17.2.0 - '@commitlint/to-lines': 17.0.0 - '@commitlint/types': 17.0.0 + '@commitlint/ensure': 17.4.4 + '@commitlint/message': 17.4.2 + '@commitlint/to-lines': 17.4.0 + '@commitlint/types': 17.4.4 execa: 5.1.1 dev: true - /@commitlint/to-lines/17.0.0: - resolution: {integrity: sha512-nEi4YEz04Rf2upFbpnEorG8iymyH7o9jYIVFBG1QdzebbIFET3ir+8kQvCZuBE5pKCtViE4XBUsRZz139uFrRQ==} + /@commitlint/to-lines@17.4.0: + resolution: {integrity: sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==} engines: {node: '>=v14'} dev: true - /@commitlint/top-level/17.0.0: - resolution: {integrity: sha512-dZrEP1PBJvodNWYPOYiLWf6XZergdksKQaT6i1KSROLdjf5Ai0brLOv5/P+CPxBeoj3vBxK4Ax8H1Pg9t7sHIQ==} + /@commitlint/top-level@17.4.0: + resolution: {integrity: sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==} engines: {node: '>=v14'} dependencies: find-up: 5.0.0 dev: true - /@commitlint/types/17.0.0: - resolution: {integrity: sha512-hBAw6U+SkAT5h47zDMeOu3HSiD0SODw4Aq7rRNh1ceUmL7GyLKYhPbUvlRWqZ65XjBLPHZhFyQlRaPNz8qvUyQ==} + /@commitlint/types@17.4.4: + resolution: {integrity: sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==} engines: {node: '>=v14'} dependencies: chalk: 4.1.2 dev: true - /@cspell/cspell-bundled-dicts/6.14.2: - resolution: {integrity: sha512-gh6h/1vy332s3IR7x1v53Cp/WGPpbKKRdte3qUG0KZol9A52agfPCju8TEHxsyk8rXAbVtqYwue8Y68Nz4ZbVg==} + /@cspell/cspell-bundled-dicts@6.31.1: + resolution: {integrity: sha512-rsIev+dk1Vd8H1OKZhNhXycIVsMfeWJaeW3QUi1l4oIoGwQfJVbs1ZPZPHE5cglzyHOW1jQNStXf34UKaC6siA==} engines: {node: '>=14'} dependencies: - '@cspell/dict-ada': 4.0.0 + '@cspell/dict-ada': 4.0.1 '@cspell/dict-aws': 3.0.0 - '@cspell/dict-bash': 4.1.0 - '@cspell/dict-companies': 3.0.3 - '@cspell/dict-cpp': 4.0.0 + '@cspell/dict-bash': 4.1.1 + '@cspell/dict-companies': 3.0.10 + '@cspell/dict-cpp': 5.0.3 '@cspell/dict-cryptocurrencies': 3.0.1 - '@cspell/dict-csharp': 4.0.1 - '@cspell/dict-css': 4.0.0 - '@cspell/dict-dart': 2.0.0 - '@cspell/dict-django': 4.0.0 - '@cspell/dict-docker': 1.1.3 - '@cspell/dict-dotnet': 4.0.0 - '@cspell/dict-elixir': 4.0.0 + '@cspell/dict-csharp': 4.0.2 + '@cspell/dict-css': 4.0.6 + '@cspell/dict-dart': 2.0.2 + '@cspell/dict-django': 4.0.2 + '@cspell/dict-docker': 1.1.6 + '@cspell/dict-dotnet': 5.0.0 + '@cspell/dict-elixir': 4.0.3 + '@cspell/dict-en-common-misspellings': 1.0.2 '@cspell/dict-en-gb': 1.1.33 - '@cspell/dict-en_us': 4.1.0 + '@cspell/dict-en_us': 4.3.2 '@cspell/dict-filetypes': 3.0.0 - '@cspell/dict-fonts': 3.0.0 - '@cspell/dict-fullstack': 3.0.0 + '@cspell/dict-fonts': 3.0.2 + '@cspell/dict-fullstack': 3.1.5 + '@cspell/dict-gaming-terms': 1.0.4 '@cspell/dict-git': 2.0.0 - '@cspell/dict-golang': 5.0.0 - '@cspell/dict-haskell': 4.0.0 - '@cspell/dict-html': 4.0.1 + '@cspell/dict-golang': 6.0.1 + '@cspell/dict-haskell': 4.0.1 + '@cspell/dict-html': 4.0.3 '@cspell/dict-html-symbol-entities': 4.0.0 - '@cspell/dict-java': 5.0.2 - '@cspell/dict-latex': 3.0.0 + '@cspell/dict-java': 5.0.5 + '@cspell/dict-k8s': 1.0.1 + '@cspell/dict-latex': 4.0.0 '@cspell/dict-lorem-ipsum': 3.0.0 - '@cspell/dict-lua': 3.0.0 - '@cspell/dict-node': 4.0.1 - '@cspell/dict-npm': 4.0.1 - '@cspell/dict-php': 3.0.3 - '@cspell/dict-powershell': 3.0.0 - '@cspell/dict-public-licenses': 2.0.0 - '@cspell/dict-python': 4.0.0 - '@cspell/dict-r': 2.0.0 - '@cspell/dict-ruby': 3.0.0 - '@cspell/dict-rust': 3.0.0 - '@cspell/dict-scala': 3.0.0 - '@cspell/dict-software-terms': 3.0.5 - '@cspell/dict-sql': 2.0.0 - '@cspell/dict-swift': 2.0.0 - '@cspell/dict-typescript': 3.0.1 + '@cspell/dict-lua': 4.0.1 + '@cspell/dict-node': 4.0.2 + '@cspell/dict-npm': 5.0.5 + '@cspell/dict-php': 4.0.1 + '@cspell/dict-powershell': 5.0.1 + '@cspell/dict-public-licenses': 2.0.2 + '@cspell/dict-python': 4.0.4 + '@cspell/dict-r': 2.0.1 + '@cspell/dict-ruby': 5.0.0 + '@cspell/dict-rust': 4.0.1 + '@cspell/dict-scala': 5.0.0 + '@cspell/dict-software-terms': 3.1.8 + '@cspell/dict-sql': 2.1.0 + '@cspell/dict-svelte': 1.0.2 + '@cspell/dict-swift': 2.0.1 + '@cspell/dict-typescript': 3.1.1 '@cspell/dict-vue': 3.0.0 dev: true - /@cspell/cspell-bundled-dicts/6.14.3: - resolution: {integrity: sha512-bgPBduoDi1jkrcLkmAwRG1c6F1iprF2yfBgEDT19dRG1kYuq/fLGNOcSmEp4CbApn8m0MmxsrhEp8O0Q9owQRQ==} - engines: {node: '>=14'} - dependencies: - '@cspell/dict-ada': 4.0.0 - '@cspell/dict-aws': 3.0.0 - '@cspell/dict-bash': 4.1.0 - '@cspell/dict-companies': 3.0.3 - '@cspell/dict-cpp': 4.0.0 - '@cspell/dict-cryptocurrencies': 3.0.1 - '@cspell/dict-csharp': 4.0.1 - '@cspell/dict-css': 4.0.0 - '@cspell/dict-dart': 2.0.0 - '@cspell/dict-django': 4.0.0 - '@cspell/dict-docker': 1.1.3 - '@cspell/dict-dotnet': 4.0.0 - '@cspell/dict-elixir': 4.0.0 - '@cspell/dict-en-gb': 1.1.33 - '@cspell/dict-en_us': 4.1.0 - '@cspell/dict-filetypes': 3.0.0 - '@cspell/dict-fonts': 3.0.0 - '@cspell/dict-fullstack': 3.0.0 - '@cspell/dict-git': 2.0.0 - '@cspell/dict-golang': 5.0.0 - '@cspell/dict-haskell': 4.0.0 - '@cspell/dict-html': 4.0.1 - '@cspell/dict-html-symbol-entities': 4.0.0 - '@cspell/dict-java': 5.0.2 - '@cspell/dict-latex': 3.0.0 - '@cspell/dict-lorem-ipsum': 3.0.0 - '@cspell/dict-lua': 3.0.0 - '@cspell/dict-node': 4.0.1 - '@cspell/dict-npm': 4.0.1 - '@cspell/dict-php': 3.0.3 - '@cspell/dict-powershell': 3.0.0 - '@cspell/dict-public-licenses': 2.0.0 - '@cspell/dict-python': 4.0.0 - '@cspell/dict-r': 2.0.0 - '@cspell/dict-ruby': 3.0.0 - '@cspell/dict-rust': 3.0.0 - '@cspell/dict-scala': 3.0.0 - '@cspell/dict-software-terms': 3.0.5 - '@cspell/dict-sql': 2.0.0 - '@cspell/dict-swift': 2.0.0 - '@cspell/dict-typescript': 3.0.1 - '@cspell/dict-vue': 3.0.0 - dev: true - - /@cspell/cspell-pipe/6.14.2: - resolution: {integrity: sha512-9H7Z/jy2tGpMW9T/JOk8T3bqvQoHJIz1wddktA5Lq8fnMqlDhM9le2uykhVlLpemLhWpDS2fNzLJ3sHiaPgHBA==} + /@cspell/cspell-pipe@6.31.1: + resolution: {integrity: sha512-zk1olZi4dr6GLm5PAjvsiZ01HURNSruUYFl1qSicGnTwYN8GaN4RhAwannAytcJ7zJPIcyXlid0YsB58nJf3wQ==} engines: {node: '>=14'} dev: true - /@cspell/cspell-pipe/6.14.3: - resolution: {integrity: sha512-/mLZxJOK3/UFpnR4jrImKY5W4cn5XWjvQPXnFCEzpU0tAAF6GboJgWl30TegqFJjLVCKTNRMOtT1r6kgvb66zw==} + /@cspell/cspell-service-bus@6.31.1: + resolution: {integrity: sha512-YyBicmJyZ1uwKVxujXw7sgs9x+Eps43OkWmCtDZmZlnq489HdTSuhF1kTbVi2yeFSeaXIS87+uHo12z97KkQpg==} engines: {node: '>=14'} dev: true - /@cspell/cspell-service-bus/6.14.2: - resolution: {integrity: sha512-IOK4MqwDNS2y29eZjdpHrCQ0ouTWZCS2e3EOmlvY+yUpT7e1AX8pVOaar4jLnXg03evAjrFrrmfmhFI6poO6Hg==} + /@cspell/cspell-types@6.31.1: + resolution: {integrity: sha512-1KeTQFiHMssW1eRoF2NZIEg4gPVIfXLsL2+VSD/AV6YN7lBcuf6gRRgV5KWYarhxtEfjxhDdDTmu26l/iJEUtw==} engines: {node: '>=14'} dev: true - /@cspell/cspell-service-bus/6.14.3: - resolution: {integrity: sha512-89OWGBzhorhiWcFqFTeHl9Y6WTdd5MGC2XNNCVZLM3VTYaFx4DVkiyxWdkE7gHjYxvNdGSH54/fE18TqLc//dQ==} - engines: {node: '>=14'} + /@cspell/dict-ada@4.0.1: + resolution: {integrity: sha512-/E9o3nHrXOhYmQE43deKbxZcR3MIJAsa+66IzP9TXGHheKEx8b9dVMVVqydDDH8oom1H0U20NRPtu6KRVbT9xw==} dev: true - /@cspell/cspell-types/6.14.2: - resolution: {integrity: sha512-/EZYVglm6+2GlnkFTzuLuQFr7vrttkhG+ZsNO9EDcFYB5N7O2ndNSkTQFxGi8FS8R3RS5CHyS5X6hANnolzvfQ==} - engines: {node: '>=14'} - dev: true - - /@cspell/cspell-types/6.14.3: - resolution: {integrity: sha512-u4Hun0vOQVkk3tJ6VzPjHVmv2dq0D6jYqX8pWLKWRwo38rdoIkdWseN359sWCz96tDM8g5rpSFdmecbWLU7BYg==} - engines: {node: '>=14'} - dev: true - - /@cspell/dict-ada/4.0.0: - resolution: {integrity: sha512-M0n4ZYmpLOXbDD07Qb/Ekk0K5pX2C+mCuJ2ZxPgbTq9HGlrN43PmqrGJHWcgtVHE3fd1D4VxS85QcQP6r1Y+KQ==} - dev: true - - /@cspell/dict-aws/3.0.0: + /@cspell/dict-aws@3.0.0: resolution: {integrity: sha512-O1W6nd5y3Z00AMXQMzfiYrIJ1sTd9fB1oLr+xf/UD7b3xeHeMeYE2OtcWbt9uyeHim4tk+vkSTcmYEBKJgS5bQ==} dev: true - /@cspell/dict-bash/4.1.0: - resolution: {integrity: sha512-8pFL03ZKejynfbsa2UZ3iZ7BrT1TAGTD8ZlK822ioAb7aoDvQhYao2Bjz5cXU0uk7CyrlgsSnYX94sLfqDfTxQ==} + /@cspell/dict-bash@4.1.1: + resolution: {integrity: sha512-8czAa/Mh96wu2xr0RXQEGMTBUGkTvYn/Pb0o+gqOO1YW+poXGQc3gx0YPqILDryP/KCERrNvkWUJz3iGbvwC2A==} dev: true - /@cspell/dict-companies/3.0.3: - resolution: {integrity: sha512-qBWdwA97HdnLbxPLOUTZ+/mg9eYhi14hM7PEUM1PZ004MEIxQHum0IQpypKAwP3teR1KEsyxEPHp8v24Dw45Zg==} + /@cspell/dict-companies@3.0.10: + resolution: {integrity: sha512-LgPi7t9cMc2gBL63jkx/H3LAAtM/DjgZEsnmYmGqrCPWYVmKY1Y4sH2PBaV2ocE9CypV83M0DellGiUNb0kmug==} dev: true - /@cspell/dict-cpp/4.0.0: - resolution: {integrity: sha512-NrCmer14tTSbPs1TwqyCjFEmWCBw0UFvAn4O3pdWuxktArHxRJ5vUQOoL2Gus2H9s3ihhOJZkcuJ47Kd21E7BQ==} + /@cspell/dict-cpp@5.0.3: + resolution: {integrity: sha512-7sx/RFsf0hB3q8chx8OHYl9Kd+g0pqA1laphwaAQ+/jPwoAreYT3kNQWbJ3bIt/rMoORetFSQxckSbaJXwwqpw==} dev: true - /@cspell/dict-cryptocurrencies/3.0.1: + /@cspell/dict-cryptocurrencies@3.0.1: resolution: {integrity: sha512-Tdlr0Ahpp5yxtwM0ukC13V6+uYCI0p9fCRGMGZt36rWv8JQZHIuHfehNl7FB/Qc09NCF7p5ep0GXbL+sVTd/+w==} dev: true - /@cspell/dict-csharp/4.0.1: - resolution: {integrity: sha512-BkfT6S790FcyWLTWYBwkj9dKxuNz4pHFDrj9GFrmqXd2HWzfSa944S0NJhal42TnW30JJljQY5P1ZYau+s2Pbg==} + /@cspell/dict-csharp@4.0.2: + resolution: {integrity: sha512-1JMofhLK+4p4KairF75D3A924m5ERMgd1GvzhwK2geuYgd2ZKuGW72gvXpIV7aGf52E3Uu1kDXxxGAiZ5uVG7g==} dev: true - /@cspell/dict-css/4.0.0: - resolution: {integrity: sha512-ieSeG9KAJGIr5eK0JRWqD5KXstPPUw6JUTmGWc7P/qiqj/sjmhWqWKEt7HhoSNcb8uQxAkAoxhrNpfbKzqnKAw==} + /@cspell/dict-css@4.0.6: + resolution: {integrity: sha512-2Lo8W2ezHmGgY8cWFr4RUwnjbndna5mokpCK/DuxGILQnuajR0J31ANQOXj/8iZM2phFB93ZzMNk/0c04TDfSQ==} dev: true - /@cspell/dict-dart/2.0.0: - resolution: {integrity: sha512-p7vHszsu2uJt+F04gvNy1e5okypFfVEYHBWgpOV/Jrvs0F5A+gUzFTG2Ix9b1jkCigAULYKQkIGue+qlhSoK5Q==} + /@cspell/dict-dart@2.0.2: + resolution: {integrity: sha512-jigcODm7Z4IFZ4vParwwP3IT0fIgRq/9VoxkXfrxBMsLBGGM2QltHBj7pl+joX+c4cOHxfyZktGJK1B1wFtR4Q==} dev: true - /@cspell/dict-django/4.0.0: - resolution: {integrity: sha512-k0npSzQrPQSqjR2XtumV14sv9waTRMUzPx0UfOuJZcnCCZY8ofPeqFYoku+O+9Kc9etFOziOxnScshKVDzYWOQ==} + /@cspell/dict-django@4.0.2: + resolution: {integrity: sha512-L0Yw6+Yh2bE9/FAMG4gy9m752G4V8HEBjEAGeRIQ9qvxDLR9yD6dPOtgEFTjv7SWlKSrLb9wA/W3Q2GKCOusSg==} dev: true - /@cspell/dict-docker/1.1.3: - resolution: {integrity: sha512-Iz7EQGnLBgnnmzCC8iLQ7JssCCQlCjZLiCs0qhooETWLifob3nzsI9AVBh3gkYLhISLIIjBpfa4LTknskT7LzA==} + /@cspell/dict-docker@1.1.6: + resolution: {integrity: sha512-zCCiRTZ6EOQpBnSOm0/3rnKW1kCcAUDUA7SxJG3SuH6iZvKi3I8FEg8+O83WQUeXg0SyPNerD9F40JLnnJjJig==} dev: true - /@cspell/dict-dotnet/4.0.0: - resolution: {integrity: sha512-biZiTWyDqwVV2m+c17lLIliPDXPjOR1VwwmyMxvb3nFS84aP9x52SAVCf0w7Io1CIpUiY7XnG6/xeI7esYU78w==} + /@cspell/dict-dotnet@5.0.0: + resolution: {integrity: sha512-EOwGd533v47aP5QYV8GlSSKkmM9Eq8P3G/eBzSpH3Nl2+IneDOYOBLEUraHuiCtnOkNsz0xtZHArYhAB2bHWAw==} dev: true - /@cspell/dict-elixir/4.0.0: - resolution: {integrity: sha512-0TqqdQjg/zu3wAjk2FQkZ87pPIS9tA9kl6he5NJB729ysrWhND/7aSPC48QrP46VZ+oFrvFZK8DC8ZlYs16cjQ==} + /@cspell/dict-elixir@4.0.3: + resolution: {integrity: sha512-g+uKLWvOp9IEZvrIvBPTr/oaO6619uH/wyqypqvwpmnmpjcfi8+/hqZH8YNKt15oviK8k4CkINIqNhyndG9d9Q==} dev: true - /@cspell/dict-en-gb/1.1.33: + /@cspell/dict-en-common-misspellings@1.0.2: + resolution: {integrity: sha512-jg7ZQZpZH7+aAxNBlcAG4tGhYF6Ksy+QS5Df73Oo+XyckBjC9QS+PrRwLTeYoFIgXy5j3ICParK5r3MSSoL4gw==} + dev: true + + /@cspell/dict-en-gb@1.1.33: resolution: {integrity: sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==} dev: true - /@cspell/dict-en_us/4.1.0: - resolution: {integrity: sha512-EnfxP/5U3kDhmTWcHV7Xs2Fxa9KAE5fbHm+4u8LGBOUZvSkZC5+ayjQ50CfEyTGuaI/946ITQYPRNxUZ7oqOiQ==} + /@cspell/dict-en_us@4.3.2: + resolution: {integrity: sha512-o8xtHDLPNzW6hK5b1TaDTWt25vVi9lWlL6/dZ9YoS+ZMj+Dy/yuXatqfOgeGyU3a9+2gxC0kbr4oufMUQXI2mQ==} dev: true - /@cspell/dict-filetypes/3.0.0: + /@cspell/dict-filetypes@3.0.0: resolution: {integrity: sha512-Fiyp0z5uWaK0d2TfR9GMUGDKmUMAsOhGD5A0kHoqnNGswL2iw0KB0mFBONEquxU65fEnQv4R+jdM2d9oucujuA==} dev: true - /@cspell/dict-fonts/3.0.0: - resolution: {integrity: sha512-zTZni0AbwBVG1MKA0WpwPyIJPVF+gp6neXDQzHcu4RUnuQ4uDu0PVEuZjGHCJWwwFoR5JmkqZxVSg1y3ufJODA==} + /@cspell/dict-fonts@3.0.2: + resolution: {integrity: sha512-Z5QdbgEI7DV+KPXrAeDA6dDm/vTzyaW53SGlKqz6PI5VhkOjgkBXv3YtZjnxMZ4dY2ZIqq+RUK6qa9Pi8rQdGQ==} dev: true - /@cspell/dict-fullstack/3.0.0: - resolution: {integrity: sha512-BMQRTaeReLufjMwgWqqwPdrXQ7jkVGTv7/YvOLsHFZvcAP3eM7WqX+rvdXckLhJmuuzbceFRDKs5F/9Ig2x/tQ==} + /@cspell/dict-fullstack@3.1.5: + resolution: {integrity: sha512-6ppvo1dkXUZ3fbYn/wwzERxCa76RtDDl5Afzv2lijLoijGGUw5yYdLBKJnx8PJBGNLh829X352ftE7BElG4leA==} dev: true - /@cspell/dict-git/2.0.0: + /@cspell/dict-gaming-terms@1.0.4: + resolution: {integrity: sha512-hbDduNXlk4AOY0wFxcDMWBPpm34rpqJBeqaySeoUH70eKxpxm+dvjpoRLJgyu0TmymEICCQSl6lAHTHSDiWKZg==} + dev: true + + /@cspell/dict-git@2.0.0: resolution: {integrity: sha512-n1AxyX5Kgxij/sZFkxFJlzn3K9y/sCcgVPg/vz4WNJ4K9YeTsUmyGLA2OQI7d10GJeiuAo2AP1iZf2A8j9aj2w==} dev: true - /@cspell/dict-golang/5.0.0: - resolution: {integrity: sha512-Cbx4mVHsGbr5D+wlT0yU3n/0c5iLvciU48rSOQR7SCAzu5mTXyM1mqRu6nqnRiMv6G6mO50EL2LCTq6RZrlIOg==} + /@cspell/dict-golang@6.0.1: + resolution: {integrity: sha512-Z19FN6wgg2M/A+3i1O8qhrGaxUUGOW8S2ySN0g7vp4HTHeFmockEPwYx7gArfssNIruw60JorZv+iLJ6ilTeow==} dev: true - /@cspell/dict-haskell/4.0.0: - resolution: {integrity: sha512-U/DPpDoitGeUvduM9teDkDc1zs4Plgh0pNONDP3YbsEICErSlp1NfatD0i35Z6cR0C7I8uEe4gG2phG00zrSqw==} + /@cspell/dict-haskell@4.0.1: + resolution: {integrity: sha512-uRrl65mGrOmwT7NxspB4xKXFUenNC7IikmpRZW8Uzqbqcu7ZRCUfstuVH7T1rmjRgRkjcIjE4PC11luDou4wEQ==} dev: true - /@cspell/dict-html-symbol-entities/4.0.0: + /@cspell/dict-html-symbol-entities@4.0.0: resolution: {integrity: sha512-HGRu+48ErJjoweR5IbcixxETRewrBb0uxQBd6xFGcxbEYCX8CnQFTAmKI5xNaIt2PKaZiJH3ijodGSqbKdsxhw==} dev: true - /@cspell/dict-html/4.0.1: - resolution: {integrity: sha512-q5fCzkoOz+8BW79qLrnANEDnG+Jb2WS2fXERxg9xwgKBXwXUxH8ttGVNhfkLpNWe/UMm00U1IZMnVGyYLNTO5w==} + /@cspell/dict-html@4.0.3: + resolution: {integrity: sha512-Gae8i8rrArT0UyG1I6DHDK62b7Be6QEcBSIeWOm4VIIW1CASkN9B0qFgSVnkmfvnu1Y3H7SSaaEynKjdj3cs8w==} dev: true - /@cspell/dict-java/5.0.2: - resolution: {integrity: sha512-HWgdp8plZOdYjOkndwmgHGVxoewylZcl886PqSL6TMcDshyI0+2nePft31nIuALRvt7HL8IX++DM1uk4UfY4kg==} + /@cspell/dict-java@5.0.5: + resolution: {integrity: sha512-X19AoJgWIBwJBSWGFqSgHaBR/FEykBHTMjL6EqOnhIGEyE9nvuo32tsSHjXNJ230fQxQptEvRZoaldNLtKxsRg==} dev: true - /@cspell/dict-latex/3.0.0: - resolution: {integrity: sha512-QsRWj+Jll4ueVbce8ofKa743oQ2exmbVNZN70MaMbmu8PSbjW2+Rj3OdExVStesANMj7qc20inS/TgPr8DrInQ==} + /@cspell/dict-k8s@1.0.1: + resolution: {integrity: sha512-gc5y4Nm3hVdMZNBZfU2M1AsAmObZsRWjCUk01NFPfGhFBXyVne41T7E62rpnzu5330FV/6b/TnFcPgRmak9lLw==} dev: true - /@cspell/dict-lorem-ipsum/3.0.0: + /@cspell/dict-latex@4.0.0: + resolution: {integrity: sha512-LPY4y6D5oI7D3d+5JMJHK/wxYTQa2lJMSNxps2JtuF8hbAnBQb3igoWEjEbIbRRH1XBM0X8dQqemnjQNCiAtxQ==} + dev: true + + /@cspell/dict-lorem-ipsum@3.0.0: resolution: {integrity: sha512-msEV24qEpzWZs2kcEicqYlhyBpR0amfDkJOs+iffC07si9ftqtQ+yP3lf1VFLpgqw3SQh1M1vtU7RD4sPrNlcQ==} dev: true - /@cspell/dict-lua/3.0.0: - resolution: {integrity: sha512-WOhSCgS5wMxkGQJ8siB90iTB9ElquJB7FeqYSbJqqs6cUwH8G7MM/CEDPL6h7vCo0+v3GuxQ8yKWDSUcUhz9Lg==} + /@cspell/dict-lua@4.0.1: + resolution: {integrity: sha512-j0MFmeCouSoC6EdZTbvGe1sJ9V+ruwKSeF+zRkNNNload7R72Co5kX1haW2xLHGdlq0kqSy1ODRZKdVl0e+7hg==} dev: true - /@cspell/dict-node/4.0.1: - resolution: {integrity: sha512-4EmT5yZFitdwnG0hYEd+Ek19zzD81Bp+n7w0kglZKldS5AvapwW6GM/SAps5YMQQc5zZMi+bMgV7NIzapREqUg==} + /@cspell/dict-node@4.0.2: + resolution: {integrity: sha512-FEQJ4TnMcXEFslqBQkXa5HposMoCGsiBv2ux4IZuIXgadXeHKHUHk60iarWpjhzNzQLyN2GD7NoRMd12bK3Llw==} dev: true - /@cspell/dict-npm/4.0.1: - resolution: {integrity: sha512-jNKImVG5ZX+Pp6PhbSR3TmC9+0ROx09dGhSgUsZyvXV5CGEr+OQGJtNL98TGwU3pP2Xjc++qnHA/XPwB5WvLfA==} + /@cspell/dict-npm@5.0.5: + resolution: {integrity: sha512-eirZm4XpJNEcbmLGIwI2qXdRRlCKwEsH9mT3qCUytmbj6S6yn63F+8bShMW/yQBedV7+GXq9Td+cJdqiVutOiA==} dev: true - /@cspell/dict-php/3.0.3: - resolution: {integrity: sha512-7dvXdPTfbIF2xEob9w94/eV5SU8BkYoN0R7EQghXi0fcF7T1unK+JwDgfoEs6wqApB5aCVYwguiaj8HGX2IRIQ==} + /@cspell/dict-php@4.0.1: + resolution: {integrity: sha512-XaQ/JkSyq2c07MfRG54DjLi2CV+HHwS99DDCAao9Fq2JfkWroTQsUeek7wYZXJATrJVOULoV3HKih12x905AtQ==} dev: true - /@cspell/dict-powershell/3.0.0: - resolution: {integrity: sha512-pkztY9Ak4oc33q+Qxcn9/CTOKo4N8YIRRE6v67WwQOncA5QIJfcOPUrjfR3Z8SpzElXhu3s9qtWWSqbCy6qmcA==} + /@cspell/dict-powershell@5.0.1: + resolution: {integrity: sha512-lLl+syWFgfv2xdsoxHfPIB2FGkn//XahCIKcRaf52AOlm1/aXeaJN579B9HCpvM7wawHzMqJ33VJuL/vb6Lc4g==} dev: true - /@cspell/dict-public-licenses/2.0.0: - resolution: {integrity: sha512-NdMHnS6xiYJKlzVoTV5CBhMiDpXMZ/PDcvXiOpxeR50xkjR18O/XFP4f4eDZpxGiBSUCMFRWf4JjILJ04Rpcfg==} + /@cspell/dict-public-licenses@2.0.2: + resolution: {integrity: sha512-baKkbs/WGEV2lCWZoL0KBPh3uiPcul5GSDwmXEBAsR5McEW52LF94/b7xWM0EmSAc/y8ODc5LnPYC7RDRLi6LQ==} dev: true - /@cspell/dict-python/4.0.0: - resolution: {integrity: sha512-MC6CKbYOly3Ig25ZnhlCzPbE/QozqfQv4VYW6HcoMQ5IbHu33ddf2lzkZ89qTXlxsF5NT5qfZEkQYHYuhuL6AQ==} + /@cspell/dict-python@4.0.4: + resolution: {integrity: sha512-whCrxsALD66PxSbxZ++xV1HQzxpRZMiX6LXEkZlj4gWuptrzyZUdTMiI8EqVEVfyf5G4EW7HNCTz35kNL5Zl+w==} dev: true - /@cspell/dict-r/2.0.0: - resolution: {integrity: sha512-rdt1cKc3VL2uXJ2X088gRhTFreN/MkJWK1jccW1EWdFHLzDwhKfrlAkoLCp0paD6HvmloLQ+eSR09D58DdsYfA==} + /@cspell/dict-r@2.0.1: + resolution: {integrity: sha512-KCmKaeYMLm2Ip79mlYPc8p+B2uzwBp4KMkzeLd5E6jUlCL93Y5Nvq68wV5fRLDRTf7N1LvofkVFWfDcednFOgA==} dev: true - /@cspell/dict-ruby/3.0.0: - resolution: {integrity: sha512-sA98T8Y1Pmq3RStVkO14E8vTWkq6JUn8c8PldiMyYgV0yfQgwhQfFAzlSfF3Gg2B0VkIdqt2et2SPN7f9wp7fQ==} + /@cspell/dict-ruby@5.0.0: + resolution: {integrity: sha512-ssb96QxLZ76yPqFrikWxItnCbUKhYXJ2owkoIYzUGNFl2CHSoHCb5a6Zetum9mQ/oUA3gNeUhd28ZUlXs0la2A==} dev: true - /@cspell/dict-rust/3.0.0: - resolution: {integrity: sha512-L1T1IBsYJZVDmfOGAbVLcpc6arWxRRCSJYvHSwEDBGrNuMyJ4jx/NvBEz5crcKf4vVKgwVlXgzQlJJZ8AVxU9w==} + /@cspell/dict-rust@4.0.1: + resolution: {integrity: sha512-xJSSzHDK2z6lSVaOmMxl3PTOtfoffaxMo7fTcbZUF+SCJzfKbO6vnN9TCGX2sx1RHFDz66Js6goz6SAZQdOwaw==} dev: true - /@cspell/dict-scala/3.0.0: - resolution: {integrity: sha512-sIiCQDIMMnNns/fzD61z5npbh5pypaKq07Orqe0+eRfdQpika8iRSGUGFHVbtdd1JzB1DyTCV2e8OwdaQiXqJQ==} + /@cspell/dict-scala@5.0.0: + resolution: {integrity: sha512-ph0twaRoV+ylui022clEO1dZ35QbeEQaKTaV2sPOsdwIokABPIiK09oWwGK9qg7jRGQwVaRPEq0Vp+IG1GpqSQ==} dev: true - /@cspell/dict-software-terms/3.0.5: - resolution: {integrity: sha512-xZVcX1zsIUbLvUc/RX+YgJRvbHaGMcdkRR+Vw8UoLjmhnT0yXWLds5uwRwAVjlQIrIcHylfDWuG70Cq5nmJHfA==} + /@cspell/dict-software-terms@3.1.8: + resolution: {integrity: sha512-gXJWSqnr8U50wHo/tpplLaZUQBQQGOwaJFHyMhN+DVNO92setoApHQ0zSqy4KSSkfvdbgYP0nPAj0MAo9/TvOw==} dev: true - /@cspell/dict-sql/2.0.0: - resolution: {integrity: sha512-J3X8VSgWpc/4McQEs138abtBw/SO3Z+vGaYi5X7XV1pKPBxjupHTTNQHSS/HWUDmVWj6fR3OV+ZGptcmvv3Clg==} + /@cspell/dict-sql@2.1.0: + resolution: {integrity: sha512-Bb+TNWUrTNNABO0bmfcYXiTlSt0RD6sB2MIY+rNlaMyIwug43jUjeYmkLz2tPkn3+2uvySeFEOMVYhMVfcuDKg==} dev: true - /@cspell/dict-swift/2.0.0: - resolution: {integrity: sha512-VStJ0fKPPNIXKmxJrbGH6vKNtJCwAnQatfSH0fVj+Unf3QHHlmuLKRG0cN0aVgEIolpRkxNXJcSB3CPbYr0Xhw==} + /@cspell/dict-svelte@1.0.2: + resolution: {integrity: sha512-rPJmnn/GsDs0btNvrRBciOhngKV98yZ9SHmg8qI6HLS8hZKvcXc0LMsf9LLuMK1TmS2+WQFAan6qeqg6bBxL2Q==} dev: true - /@cspell/dict-typescript/3.0.1: - resolution: {integrity: sha512-nKEtOpj+rJNIUK268/mCFDCIv1MWFdK1efm9YL4q1q3NHT+qCKhkXoA0eG8k4AaDIpsvebB8CgNIYFPxY92r4A==} + /@cspell/dict-swift@2.0.1: + resolution: {integrity: sha512-gxrCMUOndOk7xZFmXNtkCEeroZRnS2VbeaIPiymGRHj5H+qfTAzAKxtv7jJbVA3YYvEzWcVE2oKDP4wcbhIERw==} dev: true - /@cspell/dict-vue/3.0.0: + /@cspell/dict-typescript@3.1.1: + resolution: {integrity: sha512-N9vNJZoOXmmrFPR4ir3rGvnqqwmQGgOYoL1+y6D4oIhyr7FhaYiyF/d7QT61RmjZQcATMa6PSL+ZisCeRLx9+A==} + dev: true + + /@cspell/dict-vue@3.0.0: resolution: {integrity: sha512-niiEMPWPV9IeRBRzZ0TBZmNnkK3olkOPYxC1Ny2AX4TGlYRajcW0WUtoSHmvvjZNfWLSg2L6ruiBeuPSbjnG6A==} dev: true - /@cspell/eslint-plugin/6.14.2: - resolution: {integrity: sha512-GnwM/DOenB6VIt4lMpmw4jI1Sc83eR9/lsxz/yTQ8LZFYVxK0yWi+LbSLCLvKhLJ9RNm7jzyHCanIFNtx+aEyw==} + /@cspell/dynamic-import@6.31.1: + resolution: {integrity: sha512-uliIUv9uZlnyYmjUlcw/Dm3p0xJOEnWJNczHAfqAl4Ytg6QZktw0GtUA9b1umbRXLv0KRTPtSC6nMq3cR7rRmQ==} engines: {node: '>=14'} dependencies: - cspell-lib: 6.14.2 + import-meta-resolve: 2.2.2 + dev: true + + /@cspell/eslint-plugin@6.31.1: + resolution: {integrity: sha512-4WJXHZVHdVqIyaxCHRgd55bqkhjSDIu/kDJAvprxhEGdyladIOHZ/c3si8AMJYnYbZY56zY2LsF2W5uNyIsRgg==} + engines: {node: '>=14'} + dependencies: + cspell-lib: 6.31.1 + estree-walker: 3.0.3 + synckit: 0.8.5 transitivePeerDependencies: - encoding dev: true - /@cspell/strong-weak-map/6.14.2: - resolution: {integrity: sha512-OS/t4e5vfUyAiOcyuI1I9d4/EWCx7pA3L8uHNOQQHgjVP41tffMaKTirqRiNhkruIhmxa5Tk5fbQLRMEFapalg==} + /@cspell/strong-weak-map@6.31.1: + resolution: {integrity: sha512-z8AuWvUuSnugFKJOA9Ke0aiFuehcqLFqia9bk8XaQNEWr44ahPVn3sEWnAncTxPbpWuUw5UajoJa0egRAE1CCg==} engines: {node: '>=14.6'} dev: true - /@cspell/strong-weak-map/6.14.3: - resolution: {integrity: sha512-/FTvcywuwfFTMEpRabL8+rqB/ezSjvMp6todO0SwL/agYQmRIuTvTYLh0Ikq430oVnjo7LDgztW0tHq38UlFLw==} - engines: {node: '>=14.6'} - dev: true - - /@cspotcode/source-map-support/0.8.1: + /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} dependencies: '@jridgewell/trace-mapping': 0.3.9 + + /@cypress/code-coverage@3.10.7(@babel/core@7.12.3)(@babel/preset-env@7.20.2)(babel-loader@9.1.2)(cypress@12.10.0)(webpack@5.88.2): + resolution: {integrity: sha512-kQFB8GemDAAk6JBINsR9MLEgCw2AKb3FcdHQjIJ3KV4ZER6ZF0NGdO8SRj5oTVp28oqfOab4cgoBdecRiOE3qA==} + peerDependencies: + cypress: '*' + dependencies: + '@cypress/webpack-preprocessor': 5.17.1(@babel/core@7.12.3)(@babel/preset-env@7.20.2)(babel-loader@9.1.2)(webpack@5.88.2) + chalk: 4.1.2 + cypress: 12.10.0 + dayjs: 1.10.7 + debug: 4.3.4(supports-color@8.1.1) + execa: 4.1.0 + globby: 11.0.4 + istanbul-lib-coverage: 3.0.0 + js-yaml: 4.1.0 + nyc: 15.1.0 + transitivePeerDependencies: + - '@babel/core' + - '@babel/preset-env' + - babel-loader + - supports-color + - webpack dev: true - /@cypress/request/2.88.10: + /@cypress/request@2.88.10: resolution: {integrity: sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==} engines: {node: '>= 6'} dependencies: @@ -1687,28 +2891,55 @@ packages: uuid: 8.3.2 dev: true - /@cypress/xvfb/1.2.4_supports-color@8.1.1: + /@cypress/webpack-preprocessor@5.17.1(@babel/core@7.12.3)(@babel/preset-env@7.20.2)(babel-loader@9.1.2)(webpack@5.88.2): + resolution: {integrity: sha512-FE/e8ikPc8z4EVopJCaior3RGy0jd2q9Xcp5NtiwNG4XnLfEnUFTZlAGwXe75sEh4fNMPrBJW1KIz77PX5vGAw==} + peerDependencies: + '@babel/core': ^7.0.1 + '@babel/preset-env': ^7.0.0 + babel-loader: ^8.0.2 || ^9 + webpack: ^4 || ^5 + dependencies: + '@babel/core': 7.12.3 + '@babel/preset-env': 7.20.2(@babel/core@7.12.3) + babel-loader: 9.1.2(@babel/core@7.12.3)(webpack@5.88.2) + bluebird: 3.7.1 + debug: 4.3.4(supports-color@8.1.1) + lodash: 4.17.21 + webpack: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@cypress/xvfb@1.2.4(supports-color@8.1.1): resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} dependencies: - debug: 3.2.7_supports-color@8.1.1 + 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: + /@discoveryjs/json-ext@0.5.7: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} dev: true - /@docsearch/css/3.3.3: + /@docsearch/css@3.3.3: resolution: {integrity: sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==} dev: true - /@docsearch/js/3.3.3_tbpndr44ulefs3hehwpi2mkf2y: - resolution: {integrity: sha512-2xAv2GFuHzzmG0SSZgf8wHX0qZX8n9Y1ZirKUk5Wrdc+vH9CL837x2hZIUdwcPZI9caBA+/CzxsS68O4waYjUQ==} + /@docsearch/css@3.3.5: + resolution: {integrity: sha512-NaXVp3I8LdmJ54fn038KHgG7HmbIzZlKS2FkVf6mKcW5bYMJovkx4947joQyZk5yubxOZ+ddHSh79y39Aevufg==} + dev: true + + /@docsearch/css@3.5.2: + resolution: {integrity: sha512-SPiDHaWKQZpwR2siD0KQUwlStvIAnEyK6tAE2h2Wuoq8ue9skzhlyVQ1ddzOxX6khULnAALDiR/isSF3bnuciA==} + dev: true + + /@docsearch/js@3.3.5(@algolia/client-search@4.19.1): + resolution: {integrity: sha512-nZi074OCryZnzva2LNcbQkwBJIND6cvuFI4s1FIe6Ygf6n9g6B/IYUULXNx05rpoCZ+KEoEt3taROpsHBliuSw==} dependencies: - '@docsearch/react': 3.3.3_tbpndr44ulefs3hehwpi2mkf2y + '@docsearch/react': 3.3.5(@algolia/client-search@4.19.1) preact: 10.11.0 transitivePeerDependencies: - '@algolia/client-search' @@ -1717,8 +2948,21 @@ packages: - react-dom dev: true - /@docsearch/react/3.3.3_tbpndr44ulefs3hehwpi2mkf2y: - resolution: {integrity: sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==} + /@docsearch/js@3.5.2(@algolia/client-search@4.19.1)(search-insights@2.6.0): + resolution: {integrity: sha512-p1YFTCDflk8ieHgFJYfmyHBki1D61+U9idwrLh+GQQMrBSP3DLGKpy0XUJtPjAOPltcVbqsTjiPFfH7JImjUNg==} + dependencies: + '@docsearch/react': 3.5.2(@algolia/client-search@4.19.1)(search-insights@2.6.0) + preact: 10.11.0 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + dev: true + + /@docsearch/react@3.3.5(@algolia/client-search@4.19.1): + resolution: {integrity: sha512-Zuxf4z5PZ9eIQkVCNu76v1H+KAztKItNn3rLzZa7kpBS+++TgNARITnZeUS7C1DKoAhJZFr6T/H+Lvc6h/iiYg==} peerDependencies: '@types/react': '>= 16.8.0 < 19.0.0' react: '>= 16.8.0 < 19.0.0' @@ -1731,25 +2975,78 @@ packages: react-dom: optional: true dependencies: - '@algolia/autocomplete-core': 1.7.4 - '@algolia/autocomplete-preset-algolia': 1.7.4_qs6lk5nhygj2o3hj4sf6xnr724 - '@docsearch/css': 3.3.3 + '@algolia/autocomplete-core': 1.8.2 + '@algolia/autocomplete-preset-algolia': 1.8.2(@algolia/client-search@4.19.1)(algoliasearch@4.14.2) + '@docsearch/css': 3.3.5 algoliasearch: 4.14.2 transitivePeerDependencies: - '@algolia/client-search' dev: true - /@es-joy/jsdoccomment/0.36.0: - resolution: {integrity: sha512-u0XZyvUF6Urb2cSivSXA8qXIpT/CxkHcdtZKoWusAzgzmsTWpg0F2FpWXsolHmMUyVY3dLWaoy+0ccJ5uf2QjA==} - engines: {node: ^14 || ^16 || ^17 || ^18 || ^19} + /@docsearch/react@3.5.2(@algolia/client-search@4.19.1)(search-insights@2.6.0): + resolution: {integrity: sha512-9Ahcrs5z2jq/DcAvYtvlqEBHImbm4YJI8M9y0x6Tqg598P40HTEkX7hsMcIuThI+hTFxRGZ9hll0Wygm2yEjng==} + peerDependencies: + '@types/react': '>= 16.8.0 < 19.0.0' + react: '>= 16.8.0 < 19.0.0' + react-dom: '>= 16.8.0 < 19.0.0' + search-insights: '>= 1 < 3' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true + search-insights: + optional: true + dependencies: + '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.6.0) + '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) + '@docsearch/css': 3.5.2 + algoliasearch: 4.19.1 + search-insights: 2.6.0 + transitivePeerDependencies: + - '@algolia/client-search' + dev: true + + /@es-joy/jsdoccomment@0.39.4: + resolution: {integrity: sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==} + engines: {node: '>=16'} dependencies: comment-parser: 1.3.1 - esquery: 1.4.0 - jsdoc-type-pratt-parser: 3.1.0 + esquery: 1.5.0 + jsdoc-type-pratt-parser: 4.0.0 dev: true - /@esbuild/android-arm/0.16.17: - resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==} + /@esbuild/android-arm64@0.17.18: + resolution: {integrity: sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.18.11: + resolution: {integrity: sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.0: + resolution: {integrity: sha512-AzsozJnB+RNaDncBCs3Ys5g3kqhPFUueItfEaCpp89JH2naFNX2mYDIvUgPYMqqjm8hiFoo+jklb3QHZyR3ubw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.17.18: + resolution: {integrity: sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -1757,8 +3054,8 @@ packages: dev: true optional: true - /@esbuild/android-arm/0.17.0: - resolution: {integrity: sha512-hlbX5ym1V5kIKvnwFhm6rhar7MNqfJrZyYTNfk6+WS1uQfQmszFgXeyPH2beP3lSCumZyqX0zMBfOqftOpZ7GA==} + /@esbuild/android-arm@0.18.11: + resolution: {integrity: sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==} engines: {node: '>=12'} cpu: [arm] os: [android] @@ -1766,26 +3063,17 @@ packages: dev: true optional: true - /@esbuild/android-arm64/0.16.17: - resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==} + /@esbuild/android-arm@0.19.0: + resolution: {integrity: sha512-GAkjUyHgWTYuex3evPd5V7uV/XS4LMKr1PWHRPW1xNyy/Jx08x3uTrDFRefBYLKT/KpaWM8/YMQcwbp5a3yIDA==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [arm] os: [android] requiresBuild: true dev: true optional: true - /@esbuild/android-arm64/0.17.0: - resolution: {integrity: sha512-77GVyD7ToESy/7+9eI8z62GGBdS/hsqsrpM+JA4kascky86wHbN29EEFpkVvxajPL7k6mbLJ5VBQABdj7n9FhQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@esbuild/android-x64/0.16.17: - resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==} + /@esbuild/android-x64@0.17.18: + resolution: {integrity: sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1793,8 +3081,8 @@ packages: dev: true optional: true - /@esbuild/android-x64/0.17.0: - resolution: {integrity: sha512-TroxZdZhtAz0JyD0yahtjcbKuIXrBEAoAazaYSeR2e2tUtp9uXrcbpwFJF6oxxOiOOne6y7l4hx4YVnMW/tdFw==} + /@esbuild/android-x64@0.18.11: + resolution: {integrity: sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==} engines: {node: '>=12'} cpu: [x64] os: [android] @@ -1802,8 +3090,17 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64/0.16.17: - resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==} + /@esbuild/android-x64@0.19.0: + resolution: {integrity: sha512-SUG8/qiVhljBDpdkHQ9DvOWbp7hFFIP0OzxOTptbmVsgBgzY6JWowmMd6yJuOhapfxmj/DrvwKmjRLvVSIAKZg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.17.18: + resolution: {integrity: sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1811,8 +3108,8 @@ packages: dev: true optional: true - /@esbuild/darwin-arm64/0.17.0: - resolution: {integrity: sha512-wP/v4cgdWt1m8TS/WmbaBc3NZON10eCbm6XepdVc3zJuqruHCzCKcC9dTSTEk50zX04REcRcbIbdhTMciQoFIg==} + /@esbuild/darwin-arm64@0.18.11: + resolution: {integrity: sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] @@ -1820,8 +3117,17 @@ packages: dev: true optional: true - /@esbuild/darwin-x64/0.16.17: - resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==} + /@esbuild/darwin-arm64@0.19.0: + resolution: {integrity: sha512-HkxZ8k3Jvcw0FORPNTavA8BMgQjLOB6AajT+iXmil7BwY3gU1hWvJJAyWyEogCmA4LdbGvKF8vEykdmJ4xNJJQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.17.18: + resolution: {integrity: sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1829,8 +3135,8 @@ packages: dev: true optional: true - /@esbuild/darwin-x64/0.17.0: - resolution: {integrity: sha512-R4WB6D6V9KGO/3LVTT8UlwRJO26IBFatOdo/bRXksfJR0vyOi2/lgmAAMBSpgcnnwvts9QsWiyM++mTTlwRseA==} + /@esbuild/darwin-x64@0.18.11: + resolution: {integrity: sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] @@ -1838,8 +3144,17 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64/0.16.17: - resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==} + /@esbuild/darwin-x64@0.19.0: + resolution: {integrity: sha512-9IRWJjqpWFHM9a5Qs3r3bK834NCFuDY5ZaLrmTjqE+10B6w65UMQzeZjh794JcxpHolsAHqwsN/33crUXNCM2Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.17.18: + resolution: {integrity: sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1847,8 +3162,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-arm64/0.17.0: - resolution: {integrity: sha512-FO7+UEZv79gen2df8StFYFHZPI9ADozpFepLZCxY+O8sYLDa1rirvenmLwJiOHmeQRJ5orYedFeLk1PFlZ6t8Q==} + /@esbuild/freebsd-arm64@0.18.11: + resolution: {integrity: sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] @@ -1856,8 +3171,17 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64/0.16.17: - resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==} + /@esbuild/freebsd-arm64@0.19.0: + resolution: {integrity: sha512-s7i2WcXcK0V1PJHVBe7NsGddsL62a9Vhpz2U7zapPrwKoFuxPP9jybwX8SXnropR/AOj3ppt2ern4ItblU6UQQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.17.18: + resolution: {integrity: sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1865,8 +3189,8 @@ packages: dev: true optional: true - /@esbuild/freebsd-x64/0.17.0: - resolution: {integrity: sha512-qCsNRsVTaC3ekwZcb2sa7l1gwCtJK3EqCWyDgpoQocYf3lRpbAzaCvqZSF2+NOO64cV+JbedXPsFiXU1aaVcIg==} + /@esbuild/freebsd-x64@0.18.11: + resolution: {integrity: sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] @@ -1874,8 +3198,44 @@ packages: dev: true optional: true - /@esbuild/linux-arm/0.16.17: - resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==} + /@esbuild/freebsd-x64@0.19.0: + resolution: {integrity: sha512-NMdBSSdgwHCqCsucU5k1xflIIRU0qi1QZnM6+vdGy5fvxm1c8rKh50VzsWsIVTFUG3l91AtRxVwoz3Lcvy3I5w==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.17.18: + resolution: {integrity: sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.11: + resolution: {integrity: sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.19.0: + resolution: {integrity: sha512-I4zvE2srSZxRPapFnNqj+NL3sDJ1wkvEZqt903OZUlBBgigrQMvzUowvP/TTTu2OGYe1oweg5MFilfyrElIFag==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.17.18: + resolution: {integrity: sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1883,8 +3243,8 @@ packages: dev: true optional: true - /@esbuild/linux-arm/0.17.0: - resolution: {integrity: sha512-Y2G2NU6155gcfNKvrakVmZV5xUAEhXjsN/uKtbKKRnvee0mHUuaT3OdQJDJKjHVGr6B0898pc3slRpI1PqspoQ==} + /@esbuild/linux-arm@0.18.11: + resolution: {integrity: sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==} engines: {node: '>=12'} cpu: [arm] os: [linux] @@ -1892,26 +3252,17 @@ packages: dev: true optional: true - /@esbuild/linux-arm64/0.16.17: - resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==} + /@esbuild/linux-arm@0.19.0: + resolution: {integrity: sha512-2F1+lH7ZBcCcgxiSs8EXQV0PPJJdTNiNcXxDb61vzxTRJJkXX1I/ye9mAhfHyScXzHaEibEXg1Jq9SW586zz7w==} engines: {node: '>=12'} - cpu: [arm64] + cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-arm64/0.17.0: - resolution: {integrity: sha512-js4Vlch5XJQYISbDVJd2hsI/MsfVUz6d/FrclCE73WkQmniH37vFpuQI42ntWAeBghDIfaPZ6f9GilhwGzVFUg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@esbuild/linux-ia32/0.16.17: - resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==} + /@esbuild/linux-ia32@0.17.18: + resolution: {integrity: sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1919,8 +3270,8 @@ packages: dev: true optional: true - /@esbuild/linux-ia32/0.17.0: - resolution: {integrity: sha512-7tl/jSPkF59R3zeFDB2/09zLGhcM7DM+tCoOqjJbQjuL6qbMWomGT2RglCqRFpCSdzBx0hukmPPgUAMlmdj0sQ==} + /@esbuild/linux-ia32@0.18.11: + resolution: {integrity: sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==} engines: {node: '>=12'} cpu: [ia32] os: [linux] @@ -1928,8 +3279,17 @@ packages: dev: true optional: true - /@esbuild/linux-loong64/0.16.17: - resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==} + /@esbuild/linux-ia32@0.19.0: + resolution: {integrity: sha512-dz2Q7+P92r1Evc8kEN+cQnB3qqPjmCrOZ+EdBTn8lEc1yN8WDgaDORQQiX+mxaijbH8npXBT9GxUqE52Gt6Y+g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.17.18: + resolution: {integrity: sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -1937,8 +3297,8 @@ packages: dev: true optional: true - /@esbuild/linux-loong64/0.17.0: - resolution: {integrity: sha512-OG356F7dIVVF+EXJx5UfzFr1I5l6ES53GlMNSr3U1MhlaVyrP9um5PnrSJ+7TSDAzUC7YGjxb2GQWqHLd5XFoA==} + /@esbuild/linux-loong64@0.18.11: + resolution: {integrity: sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==} engines: {node: '>=12'} cpu: [loong64] os: [linux] @@ -1946,8 +3306,17 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el/0.16.17: - resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==} + /@esbuild/linux-loong64@0.19.0: + resolution: {integrity: sha512-IcVJovJVflih4oFahhUw+N7YgNbuMSVFNr38awb0LNzfaiIfdqIh518nOfYaNQU3aVfiJnOIRVJDSAP4k35WxA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.17.18: + resolution: {integrity: sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1955,8 +3324,8 @@ packages: dev: true optional: true - /@esbuild/linux-mips64el/0.17.0: - resolution: {integrity: sha512-LWQJgGpxrjh2x08UYf6G5R+Km7zhkpCvKXtFQ6SX0fimDvy1C8kslgFHGxLS0wjGV8C4BNnENW/HNy57+RB7iA==} + /@esbuild/linux-mips64el@0.18.11: + resolution: {integrity: sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] @@ -1964,8 +3333,17 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64/0.16.17: - resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==} + /@esbuild/linux-mips64el@0.19.0: + resolution: {integrity: sha512-bZGRAGySMquWsKw0gIdsClwfvgbsSq/7oq5KVu1H1r9Il+WzOcfkV1hguntIuBjRVL8agI95i4AukjdAV2YpUw==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.17.18: + resolution: {integrity: sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1973,8 +3351,8 @@ packages: dev: true optional: true - /@esbuild/linux-ppc64/0.17.0: - resolution: {integrity: sha512-f40N8fKiTQslUcUuhof2/syOQ+DC9Mqdnm9d063pew+Ptv9r6dBNLQCz4300MOfCLAbb0SdnrcMSzHbMehXWLw==} + /@esbuild/linux-ppc64@0.18.11: + resolution: {integrity: sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] @@ -1982,8 +3360,17 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64/0.16.17: - resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==} + /@esbuild/linux-ppc64@0.19.0: + resolution: {integrity: sha512-3LC6H5/gCDorxoRBUdpLV/m7UthYSdar0XcCu+ypycQxMS08MabZ06y1D1yZlDzL/BvOYliRNRWVG/YJJvQdbg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.17.18: + resolution: {integrity: sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -1991,8 +3378,8 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64/0.17.0: - resolution: {integrity: sha512-sc/pvLexRvxgEbmeq7LfLGnzUBFi/E2MGbnQj3CG8tnQ90tWPTi+9CbZEgIADhj6CAlCCmqxpUclIV1CRVUOTw==} + /@esbuild/linux-riscv64@0.18.11: + resolution: {integrity: sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] @@ -2000,8 +3387,17 @@ packages: dev: true optional: true - /@esbuild/linux-s390x/0.16.17: - resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==} + /@esbuild/linux-riscv64@0.19.0: + resolution: {integrity: sha512-jfvdKjWk+Cp2sgLtEEdSHXO7qckrw2B2eFBaoRdmfhThqZs29GMMg7q/LsQpybA7BxCLLEs4di5ucsWzZC5XPA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.17.18: + resolution: {integrity: sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -2009,8 +3405,8 @@ packages: dev: true optional: true - /@esbuild/linux-s390x/0.17.0: - resolution: {integrity: sha512-7xq9/kY0vunCL2vjHKdHGI+660pCdeEC6K6TWBVvbTGXvT8s/qacfxMgr8PCeQRbNUZLOA13G6/G1+c0lYXO1A==} + /@esbuild/linux-s390x@0.18.11: + resolution: {integrity: sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==} engines: {node: '>=12'} cpu: [s390x] os: [linux] @@ -2018,8 +3414,17 @@ packages: dev: true optional: true - /@esbuild/linux-x64/0.16.17: - resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==} + /@esbuild/linux-s390x@0.19.0: + resolution: {integrity: sha512-ofcucfNLkoXmcnJaw9ugdEOf40AWKGt09WBFCkpor+vFJVvmk/8OPjl/qRtks2Z7BuZbG3ztJuK1zS9z5Cgx9A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.17.18: + resolution: {integrity: sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -2027,8 +3432,8 @@ packages: dev: true optional: true - /@esbuild/linux-x64/0.17.0: - resolution: {integrity: sha512-o7FhBLONk1mLT2ytlj/j/WuJcPdhWcVpysSJn1s9+zRdLwLKveipbPi5SIasJIqMq0T4CkQW76pxJYMqz9HrQA==} + /@esbuild/linux-x64@0.18.11: + resolution: {integrity: sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==} engines: {node: '>=12'} cpu: [x64] os: [linux] @@ -2036,8 +3441,17 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64/0.16.17: - resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==} + /@esbuild/linux-x64@0.19.0: + resolution: {integrity: sha512-Fpf7zNDBti3xrQKQKLdXT0hTyOxgFdRJIMtNy8x1az9ATR9/GJ1brYbB/GLWoXhKiHsoWs+2DLkFVNNMTCLEwA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.17.18: + resolution: {integrity: sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -2045,8 +3459,8 @@ packages: dev: true optional: true - /@esbuild/netbsd-x64/0.17.0: - resolution: {integrity: sha512-V6xXsv71b8vwFCW/ky82Rs//SbyA+ORty6A7Mzkg33/4NbYZ/1Vcbk7qAN5oi0i/gS4Q0+7dYT7NqaiVZ7+Xjw==} + /@esbuild/netbsd-x64@0.18.11: + resolution: {integrity: sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] @@ -2054,8 +3468,17 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64/0.16.17: - resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==} + /@esbuild/netbsd-x64@0.19.0: + resolution: {integrity: sha512-AMQAp/5oENgDOvVhvOlbhVe1pWii7oFAMRHlmTjSEMcpjTpIHtFXhv9uAFgUERHm3eYtNvS9Vf+gT55cwuI6Aw==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.17.18: + resolution: {integrity: sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -2063,8 +3486,8 @@ packages: dev: true optional: true - /@esbuild/openbsd-x64/0.17.0: - resolution: {integrity: sha512-StlQor6A0Y9SSDxraytr46Qbz25zsSDmsG3MCaNkBnABKHP3QsngOCfdBikqHVVrXeK0KOTmtX92/ncTGULYgQ==} + /@esbuild/openbsd-x64@0.18.11: + resolution: {integrity: sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] @@ -2072,8 +3495,17 @@ packages: dev: true optional: true - /@esbuild/sunos-x64/0.16.17: - resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==} + /@esbuild/openbsd-x64@0.19.0: + resolution: {integrity: sha512-fDztEve1QUs3h/Dw2AUmBlWGkNQbhDoD05ppm5jKvzQv+HVuV13so7m5RYeiSMIC2XQy7PAjZh+afkxAnCRZxA==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.17.18: + resolution: {integrity: sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -2081,8 +3513,8 @@ packages: dev: true optional: true - /@esbuild/sunos-x64/0.17.0: - resolution: {integrity: sha512-K64Wqw57j8KrwjR3QjsuzN/qDGK6Cno6QYtIlWAmGab5iYPBZCWz7HFtF2a86/130LmUsdXqOID7J0SmjjRFIQ==} + /@esbuild/sunos-x64@0.18.11: + resolution: {integrity: sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==} engines: {node: '>=12'} cpu: [x64] os: [sunos] @@ -2090,8 +3522,17 @@ packages: dev: true optional: true - /@esbuild/win32-arm64/0.16.17: - resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==} + /@esbuild/sunos-x64@0.19.0: + resolution: {integrity: sha512-bKZzJ2/rvUjDzA5Ddyva2tMk89WzNJEibZEaq+wY6SiqPlwgFbqyQLimouxLHiHh1itb5P3SNCIF1bc2bw5H9w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.17.18: + resolution: {integrity: sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -2099,8 +3540,8 @@ packages: dev: true optional: true - /@esbuild/win32-arm64/0.17.0: - resolution: {integrity: sha512-hly6iSWAf0hf3aHD18/qW7iFQbg9KAQ0RFGG9plcxkhL4uGw43O+lETGcSO/PylNleFowP/UztpF6U4oCYgpPw==} + /@esbuild/win32-arm64@0.18.11: + resolution: {integrity: sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] @@ -2108,8 +3549,17 @@ packages: dev: true optional: true - /@esbuild/win32-ia32/0.16.17: - resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==} + /@esbuild/win32-arm64@0.19.0: + resolution: {integrity: sha512-NQJ+4jmnA79saI+sE+QzcEls19uZkoEmdxo7r//PDOjIpX8pmoWtTnWg6XcbnO7o4fieyAwb5U2LvgWynF4diA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.17.18: + resolution: {integrity: sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -2117,8 +3567,8 @@ packages: dev: true optional: true - /@esbuild/win32-ia32/0.17.0: - resolution: {integrity: sha512-aL4EWPh0nyC5uYRfn+CHkTgawd4DjtmwquthNDmGf6Ht6+mUc+bQXyZNH1QIw8x20hSqFc4Tf36aLLWP/TPR3g==} + /@esbuild/win32-ia32@0.18.11: + resolution: {integrity: sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==} engines: {node: '>=12'} cpu: [ia32] os: [win32] @@ -2126,8 +3576,17 @@ packages: dev: true optional: true - /@esbuild/win32-x64/0.16.17: - resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==} + /@esbuild/win32-ia32@0.19.0: + resolution: {integrity: sha512-uyxiZAnsfu9diHm9/rIH2soecF/HWLXYUhJKW4q1+/LLmNQ+55lRjvSUDhUmsgJtSUscRJB/3S4RNiTb9o9mCg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.17.18: + resolution: {integrity: sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -2135,8 +3594,8 @@ packages: dev: true optional: true - /@esbuild/win32-x64/0.17.0: - resolution: {integrity: sha512-W6IIQ9Rt43I/GqfXeBFLk0TvowKBoirs9sw2LPfhHax6ayMlW5PhFzSJ76I1ac9Pk/aRcSMrHWvVyZs8ZPK2wA==} + /@esbuild/win32-x64@0.18.11: + resolution: {integrity: sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -2144,13 +3603,37 @@ packages: dev: true optional: true - /@eslint/eslintrc/1.4.1: - resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==} + /@esbuild/win32-x64@0.19.0: + resolution: {integrity: sha512-jl+NXUjK2StMgqnZnqgNjZuerFG8zQqWXMBZdMMv4W/aO1ZKQaYWZBxTrtWKphkCBVEMh0wMVfGgOd2BjOZqUQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.39.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + 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.39.0 + eslint-visitor-keys: 3.4.0 + dev: true + + /@eslint-community/regexpp@4.5.0: + resolution: {integrity: sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.0.2: + resolution: {integrity: sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4 - espree: 9.4.0 + debug: 4.3.4(supports-color@8.1.1) + espree: 9.5.1 globals: 13.19.0 ignore: 5.2.0 import-fresh: 3.3.0 @@ -2161,37 +3644,75 @@ packages: - supports-color dev: true - /@hapi/hoek/9.3.0: + /@eslint/js@8.39.0: + resolution: {integrity: sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@fastify/ajv-compiler@1.1.0: + resolution: {integrity: sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==} + dependencies: + ajv: 6.12.6 + dev: true + + /@fastify/error@2.0.0: + resolution: {integrity: sha512-wI3fpfDT0t7p8E6dA2eTECzzOd+bZsZCJ2Hcv+Onn2b7ZwK3RwD27uW2QDaMtQhAfWQQP+WNK7nKf0twLsBf9w==} + dev: true + + /@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 - /@humanwhocodes/config-array/0.11.8: + /@humanwhocodes/config-array@0.11.8: resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color dev: true - /@humanwhocodes/module-importer/1.0.1: + /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} dev: true - /@humanwhocodes/object-schema/1.2.1: + /@humanwhocodes/object-schema@1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true - /@istanbuljs/load-nyc-config/1.1.0: + /@iconify-json/carbon@1.1.16: + resolution: {integrity: sha512-AD8bcnRSGA0WfcGEass2FbA0sagrUzrpFx5WchuDy3uf7yKBWumdypdQK121DH321fQDl5+zZQ26T6gC9knwUQ==} + dependencies: + '@iconify/types': 2.0.0 + dev: true + + /@iconify/types@2.0.0: + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + dev: true + + /@iconify/utils@2.1.7: + resolution: {integrity: sha512-P8S3z/L1LcV4Qem9AoCfVAaTFGySEMzFEY4CHZLkfRj0Fv9LiR+AwjDgrDrzyI93U2L2mg9JHsbTJ52mF8suNw==} + dependencies: + '@antfu/install-pkg': 0.1.1 + '@antfu/utils': 0.7.5 + '@iconify/types': 2.0.0 + debug: 4.3.4(supports-color@8.1.1) + kolorist: 1.8.0 + local-pkg: 0.4.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@istanbuljs/load-nyc-config@1.1.0: resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} dependencies: @@ -2202,25 +3723,25 @@ packages: 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.3.1: - resolution: {integrity: sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==} + /@jest/console@29.5.0: + resolution: {integrity: sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 chalk: 4.1.2 - jest-message-util: 29.3.1 - jest-util: 29.3.1 + jest-message-util: 29.5.0 + jest-util: 29.5.0 slash: 3.0.0 dev: true - /@jest/core/29.3.1_ts-node@10.9.1: - resolution: {integrity: sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==} + /@jest/core@29.5.0(ts-node@10.9.1): + resolution: {integrity: sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -2228,32 +3749,32 @@ packages: node-notifier: optional: true dependencies: - '@jest/console': 29.3.1 - '@jest/reporters': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@jest/console': 29.5.0 + '@jest/reporters': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 ansi-escapes: 4.3.2 chalk: 4.1.2 - ci-info: 3.6.2 + ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.10 - jest-changed-files: 29.2.0 - jest-config: 29.3.1_odkjkoia5xunhxkdrka32ib6vi - jest-haste-map: 29.3.1 - jest-message-util: 29.3.1 - jest-regex-util: 29.2.0 - jest-resolve: 29.3.1 - jest-resolve-dependencies: 29.3.1 - jest-runner: 29.3.1 - jest-runtime: 29.3.1 - jest-snapshot: 29.3.1 - jest-util: 29.3.1 - jest-validate: 29.3.1 - jest-watcher: 29.3.1 + jest-changed-files: 29.5.0 + jest-config: 29.5.0(@types/node@18.16.0)(ts-node@10.9.1) + jest-haste-map: 29.5.0 + jest-message-util: 29.5.0 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-resolve-dependencies: 29.5.0 + jest-runner: 29.5.0 + jest-runtime: 29.5.0 + jest-snapshot: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 + jest-watcher: 29.5.0 micromatch: 4.0.5 - pretty-format: 29.3.1 + pretty-format: 29.5.0 slash: 3.0.0 strip-ansi: 6.0.1 transitivePeerDependencies: @@ -2261,59 +3782,59 @@ packages: - ts-node dev: true - /@jest/environment/29.3.1: - resolution: {integrity: sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==} + /@jest/environment@29.5.0: + resolution: {integrity: sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/fake-timers': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 - jest-mock: 29.3.1 + '@jest/fake-timers': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 + jest-mock: 29.5.0 dev: true - /@jest/expect-utils/29.3.1: - resolution: {integrity: sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==} + /@jest/expect-utils@29.5.0: + resolution: {integrity: sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - jest-get-type: 29.2.0 + jest-get-type: 29.4.3 dev: true - /@jest/expect/29.3.1: - resolution: {integrity: sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==} + /@jest/expect@29.5.0: + resolution: {integrity: sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - expect: 29.3.1 - jest-snapshot: 29.3.1 + expect: 29.5.0 + jest-snapshot: 29.5.0 transitivePeerDependencies: - supports-color dev: true - /@jest/fake-timers/29.3.1: - resolution: {integrity: sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==} + /@jest/fake-timers@29.5.0: + resolution: {integrity: sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.3.1 - '@sinonjs/fake-timers': 9.1.2 - '@types/node': 18.11.9 - jest-message-util: 29.3.1 - jest-mock: 29.3.1 - jest-util: 29.3.1 + '@jest/types': 29.5.0 + '@sinonjs/fake-timers': 10.0.2 + '@types/node': 18.16.0 + jest-message-util: 29.5.0 + jest-mock: 29.5.0 + jest-util: 29.5.0 dev: true - /@jest/globals/29.3.1: - resolution: {integrity: sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==} + /@jest/globals@29.5.0: + resolution: {integrity: sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.3.1 - '@jest/expect': 29.3.1 - '@jest/types': 29.3.1 - jest-mock: 29.3.1 + '@jest/environment': 29.5.0 + '@jest/expect': 29.5.0 + '@jest/types': 29.5.0 + jest-mock: 29.5.0 transitivePeerDependencies: - supports-color dev: true - /@jest/reporters/29.3.1: - resolution: {integrity: sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==} + /@jest/reporters@29.5.0: + resolution: {integrity: sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -2322,84 +3843,84 @@ packages: optional: true dependencies: '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@jridgewell/trace-mapping': 0.3.15 - '@types/node': 18.11.9 + '@jest/console': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@jridgewell/trace-mapping': 0.3.17 + '@types/node': 18.16.0 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 glob: 7.2.3 graceful-fs: 4.2.10 istanbul-lib-coverage: 3.2.0 - istanbul-lib-instrument: 5.2.0 + istanbul-lib-instrument: 5.2.1 istanbul-lib-report: 3.0.0 istanbul-lib-source-maps: 4.0.1 istanbul-reports: 3.1.5 - jest-message-util: 29.3.1 - jest-util: 29.3.1 - jest-worker: 29.3.1 + jest-message-util: 29.5.0 + jest-util: 29.5.0 + jest-worker: 29.5.0 slash: 3.0.0 string-length: 4.0.2 strip-ansi: 6.0.1 - v8-to-istanbul: 9.0.1 + v8-to-istanbul: 9.1.0 transitivePeerDependencies: - supports-color dev: true - /@jest/schemas/29.0.0: - resolution: {integrity: sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==} + /@jest/schemas@29.4.3: + resolution: {integrity: sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@sinclair/typebox': 0.24.43 + '@sinclair/typebox': 0.25.24 dev: true - /@jest/source-map/29.2.0: - resolution: {integrity: sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==} + /@jest/source-map@29.4.3: + resolution: {integrity: sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jridgewell/trace-mapping': 0.3.15 + '@jridgewell/trace-mapping': 0.3.17 callsites: 3.1.0 graceful-fs: 4.2.10 dev: true - /@jest/test-result/29.3.1: - resolution: {integrity: sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==} + /@jest/test-result@29.5.0: + resolution: {integrity: sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/console': 29.3.1 - '@jest/types': 29.3.1 + '@jest/console': 29.5.0 + '@jest/types': 29.5.0 '@types/istanbul-lib-coverage': 2.0.4 collect-v8-coverage: 1.0.1 dev: true - /@jest/test-sequencer/29.3.1: - resolution: {integrity: sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==} + /@jest/test-sequencer@29.5.0: + resolution: {integrity: sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/test-result': 29.3.1 + '@jest/test-result': 29.5.0 graceful-fs: 4.2.10 - jest-haste-map: 29.3.1 + jest-haste-map: 29.5.0 slash: 3.0.0 dev: true - /@jest/transform/29.3.1: - resolution: {integrity: sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==} + /@jest/transform@29.5.0: + resolution: {integrity: sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/core': 7.12.3 - '@jest/types': 29.3.1 - '@jridgewell/trace-mapping': 0.3.15 + '@jest/types': 29.5.0 + '@jridgewell/trace-mapping': 0.3.17 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.10 - jest-haste-map: 29.3.1 - jest-regex-util: 29.2.0 - jest-util: 29.3.1 + jest-haste-map: 29.5.0 + jest-regex-util: 29.4.3 + jest-util: 29.5.0 micromatch: 4.0.5 pirates: 4.0.5 slash: 3.0.0 @@ -2408,67 +3929,68 @@ packages: - supports-color dev: true - /@jest/types/29.3.1: - resolution: {integrity: sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==} + /@jest/types@29.5.0: + resolution: {integrity: sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/schemas': 29.0.0 + '@jest/schemas': 29.4.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 18.11.9 + '@types/node': 18.16.0 '@types/yargs': 17.0.13 chalk: 4.1.2 dev: true - /@jridgewell/gen-mapping/0.3.2: + /@jridgewell/gen-mapping@0.3.2: resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} engines: {node: '>=6.0.0'} dependencies: '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.15 - dev: true + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.17 - /@jridgewell/resolve-uri/3.1.0: + /@jridgewell/resolve-uri@3.1.0: resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} - dev: true - /@jridgewell/set-array/1.1.2: + /@jridgewell/set-array@1.1.2: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} - dev: true - /@jridgewell/source-map/0.3.2: - resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} dependencies: '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.15 + '@jridgewell/trace-mapping': 0.3.17 dev: true - /@jridgewell/sourcemap-codec/1.4.14: + /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - dev: true - /@jridgewell/trace-mapping/0.3.15: - resolution: {integrity: sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==} + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@jridgewell/trace-mapping@0.3.17: + resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 - dev: true - /@jridgewell/trace-mapping/0.3.9: + /@jridgewell/trace-mapping@0.3.9: resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} dependencies: '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/sourcemap-codec': 1.4.15 + + /@jsdevtools/ono@7.1.3: + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} dev: true - /@leichtgewicht/ip-codec/2.0.4: + /@leichtgewicht/ip-codec@2.0.4: resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} dev: true - /@microsoft/tsdoc-config/0.16.2: + /@microsoft/tsdoc-config@0.16.2: resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} dependencies: '@microsoft/tsdoc': 0.14.2 @@ -2477,340 +3999,474 @@ packages: resolve: 1.19.0 dev: true - /@microsoft/tsdoc/0.14.2: + /@microsoft/tsdoc@0.14.2: resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} dev: true - /@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 - dev: true - /@nodelib/fs.stat/2.0.5: + /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - dev: true - /@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.13.0 + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@pkgr/utils@2.3.1: + resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dependencies: + cross-spawn: 7.0.3 + is-glob: 4.0.3 + open: 8.4.0 + picocolors: 1.0.0 + tiny-glob: 0.2.9 + tslib: 2.5.0 dev: true - /@polka/url/1.0.0-next.21: + /@polka/url@0.5.0: + resolution: {integrity: sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==} + dev: true + + /@polka/url@1.0.0-next.21: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true - /@sideway/address/4.1.4: + /@rollup/plugin-babel@5.3.1(@babel/core@7.12.3)(rollup@2.79.1): + resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} + engines: {node: '>= 10.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-module-imports': 7.18.6 + '@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'} + 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.2.2 + is-module: 1.0.0 + resolve: 1.22.2 + rollup: 2.79.1 + dev: true + + /@rollup/plugin-replace@2.4.2(rollup@2.79.1): + 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.1(typescript@5.1.3): + resolution: {integrity: sha512-Ioir+x5Bejv72Lx2Zbz3/qGg7tvGbxQZALCLoJaGrkNXak/19+vKgKYJYM3i/fJxvsb23I9FuFQ8CUBEfsmBRg==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.14.0||^3.0.0 + tslib: '*' + typescript: '>=3.7.0' + peerDependenciesMeta: + rollup: + optional: true + tslib: + optional: true + dependencies: + '@rollup/pluginutils': 5.0.2 + resolve: 1.22.2 + typescript: 5.1.3 + dev: true + + /@rollup/pluginutils@3.1.0(rollup@2.79.1): + 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.0.2: + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.0 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@rollup/pluginutils@5.0.3(rollup@2.79.1): + resolution: {integrity: sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.0 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 2.79.1 + dev: true + + /@sideway/address@4.1.4: resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} dependencies: '@hapi/hoek': 9.3.0 dev: true - /@sideway/formula/3.0.0: - resolution: {integrity: sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==} - 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.24.43: - resolution: {integrity: sha512-1orQTvtazZmsPeBroJjysvsOQCYV2yjWlebkSY38pl5vr2tdLjEJ+LoxITlGNZaH2RE19WlAwQMkH/7C14wLfw==} + /@sinclair/typebox@0.25.24: + resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==} 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 - /@sinonjs/commons/1.8.3: - resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} + /@sinonjs/commons@2.0.0: + resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==} dependencies: type-detect: 4.0.8 dev: true - /@sinonjs/fake-timers/9.1.2: - resolution: {integrity: sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==} + /@sinonjs/fake-timers@10.0.2: + resolution: {integrity: sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==} dependencies: - '@sinonjs/commons': 1.8.3 + '@sinonjs/commons': 2.0.0 dev: true - /@szmarczak/http-timer/4.0.6: + /@surma/rollup-plugin-off-main-thread@2.2.3: + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + dependencies: + ejs: 3.1.8 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.8 + dev: true + + /@szmarczak/http-timer@4.0.6: resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} engines: {node: '>=10'} dependencies: defer-to-connect: 2.0.1 dev: true - /@tootallnate/once/1.1.2: - resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} - engines: {node: '>= 6'} - dev: true - - /@tootallnate/once/2.0.0: + /@tootallnate/once@2.0.0: resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} engines: {node: '>= 10'} dev: true - /@tsconfig/node10/1.0.9: + /@tsconfig/node10@1.0.9: resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true - /@tsconfig/node12/1.0.11: + /@tsconfig/node12@1.0.11: resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - /@tsconfig/node14/1.0.3: + /@tsconfig/node14@1.0.3: resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - /@tsconfig/node16/1.0.3: + /@tsconfig/node16@1.0.3: resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} - dev: true - /@types/babel__core/7.1.19: + /@types/assert@1.5.6: + resolution: {integrity: sha512-Y7gDJiIqb9qKUHfBQYOWGngUpLORtirAVPuj/CWJrU2C6ZM4/y3XLwuwfGMF8s7QzW746LQZx23m0+1FSgjfug==} + dev: false + + /@types/babel__core@7.1.19: resolution: {integrity: sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==} dependencies: - '@babel/parser': 7.19.1 - '@babel/types': 7.19.0 + '@babel/parser': 7.21.8 + '@babel/types': 7.21.2 '@types/babel__generator': 7.6.4 '@types/babel__template': 7.4.1 '@types/babel__traverse': 7.18.2 dev: true - /@types/babel__generator/7.6.4: + /@types/babel__generator@7.6.4: resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 dev: true - /@types/babel__template/7.4.1: + /@types/babel__template@7.4.1: resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} dependencies: - '@babel/parser': 7.19.1 - '@babel/types': 7.19.0 + '@babel/parser': 7.21.8 + '@babel/types': 7.21.2 dev: true - /@types/babel__traverse/7.18.2: + /@types/babel__traverse@7.18.2: resolution: {integrity: sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==} dependencies: - '@babel/types': 7.19.0 + '@babel/types': 7.21.2 dev: true - /@types/body-parser/1.19.2: + /@types/body-parser@1.19.2: resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} dependencies: '@types/connect': 3.4.35 - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/bonjour/3.5.10: + /@types/bonjour@3.5.10: resolution: {integrity: sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/braces/3.0.1: + /@types/braces@3.0.1: resolution: {integrity: sha512-+euflG6ygo4bn0JHtn4pYqcXwRtLvElQ7/nnjDu7iYG56H0+OhCd7d6Ug0IE3WcFpZozBKW2+80FUbv5QGk5AQ==} dev: true - /@types/cacheable-request/6.0.2: + /@types/cacheable-request@6.0.2: resolution: {integrity: sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==} dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 18.11.9 + '@types/node': 18.16.0 '@types/responselike': 1.0.0 dev: true - /@types/chai-subset/1.3.3: + /@types/chai-subset@1.3.3: resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} dependencies: - '@types/chai': 4.3.4 + '@types/chai': 4.3.5 dev: true - /@types/chai/4.3.4: - resolution: {integrity: sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==} + /@types/chai@4.3.5: + resolution: {integrity: sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==} dev: true - /@types/connect-history-api-fallback/1.3.5: + /@types/connect-history-api-fallback@1.3.5: resolution: {integrity: sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==} dependencies: '@types/express-serve-static-core': 4.17.31 - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/connect/3.4.35: + /@types/connect@3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/cors/2.8.13: + /@types/cors@2.8.13: resolution: {integrity: sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/cytoscape/3.19.9: + /@types/cytoscape@3.19.9: resolution: {integrity: sha512-oqCx0ZGiBO0UESbjgq052vjDAy2X53lZpMrWqiweMpvVwKw/2IiYDdzPFK6+f4tMfdv9YKEM9raO5bAZc3UYBg==} dev: true - /@types/d3-array/3.0.3: + /@types/d3-array@3.0.3: resolution: {integrity: sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==} dev: true - /@types/d3-axis/3.0.1: + /@types/d3-axis@3.0.1: resolution: {integrity: sha512-zji/iIbdd49g9WN0aIsGcwcTBUkgLsCSwB+uH+LPVDAiKWENMtI3cJEWt+7/YYwelMoZmbBfzA3qCdrZ2XFNnw==} dependencies: - '@types/d3-selection': 3.0.3 + '@types/d3-selection': 3.0.5 dev: true - /@types/d3-brush/3.0.1: + /@types/d3-brush@3.0.1: resolution: {integrity: sha512-B532DozsiTuQMHu2YChdZU0qsFJSio3Q6jmBYGYNp3gMDzBmuFFgPt9qKA4VYuLZMp4qc6eX7IUFUEsvHiXZAw==} dependencies: - '@types/d3-selection': 3.0.3 + '@types/d3-selection': 3.0.5 dev: true - /@types/d3-chord/3.0.1: + /@types/d3-chord@3.0.1: resolution: {integrity: sha512-eQfcxIHrg7V++W8Qxn6QkqBNBokyhdWSAS73AbkbMzvLQmVVBviknoz2SRS/ZJdIOmhcmmdCRE/NFOm28Z1AMw==} dev: true - /@types/d3-color/3.1.0: + /@types/d3-color@3.1.0: resolution: {integrity: sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==} dev: true - /@types/d3-contour/3.0.1: + /@types/d3-contour@3.0.1: resolution: {integrity: sha512-C3zfBrhHZvrpAAK3YXqLWVAGo87A4SvJ83Q/zVJ8rFWJdKejUnDYaWZPkA8K84kb2vDA/g90LTQAz7etXcgoQQ==} dependencies: '@types/d3-array': 3.0.3 '@types/geojson': 7946.0.10 dev: true - /@types/d3-delaunay/6.0.1: + /@types/d3-delaunay@6.0.1: resolution: {integrity: sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==} dev: true - /@types/d3-dispatch/3.0.1: + /@types/d3-dispatch@3.0.1: resolution: {integrity: sha512-NhxMn3bAkqhjoxabVJWKryhnZXXYYVQxaBnbANu0O94+O/nX9qSjrA1P1jbAQJxJf+VC72TxDX/YJcKue5bRqw==} dev: true - /@types/d3-drag/3.0.1: + /@types/d3-drag@3.0.1: resolution: {integrity: sha512-o1Va7bLwwk6h03+nSM8dpaGEYnoIG19P0lKqlic8Un36ymh9NSkNFX1yiXMKNMx8rJ0Kfnn2eovuFaL6Jvj0zA==} dependencies: - '@types/d3-selection': 3.0.3 + '@types/d3-selection': 3.0.5 dev: true - /@types/d3-dsv/3.0.0: + /@types/d3-dsv@3.0.0: resolution: {integrity: sha512-o0/7RlMl9p5n6FQDptuJVMxDf/7EDEv2SYEO/CwdG2tr1hTfUVi0Iavkk2ax+VpaQ/1jVhpnj5rq1nj8vwhn2A==} dev: true - /@types/d3-ease/3.0.0: + /@types/d3-ease@3.0.0: resolution: {integrity: sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==} dev: true - /@types/d3-fetch/3.0.1: + /@types/d3-fetch@3.0.1: resolution: {integrity: sha512-toZJNOwrOIqz7Oh6Q7l2zkaNfXkfR7mFSJvGvlD/Ciq/+SQ39d5gynHJZ/0fjt83ec3WL7+u3ssqIijQtBISsw==} dependencies: '@types/d3-dsv': 3.0.0 dev: true - /@types/d3-force/3.0.3: + /@types/d3-force@3.0.3: resolution: {integrity: sha512-z8GteGVfkWJMKsx6hwC3SiTSLspL98VNpmvLpEFJQpZPq6xpA1I8HNBDNSpukfK0Vb0l64zGFhzunLgEAcBWSA==} dev: true - /@types/d3-format/3.0.1: + /@types/d3-format@3.0.1: resolution: {integrity: sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==} dev: true - /@types/d3-geo/3.0.2: + /@types/d3-geo@3.0.2: resolution: {integrity: sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ==} dependencies: '@types/geojson': 7946.0.10 dev: true - /@types/d3-hierarchy/3.1.0: + /@types/d3-hierarchy@3.1.0: resolution: {integrity: sha512-g+sey7qrCa3UbsQlMZZBOHROkFqx7KZKvUpRzI/tAp/8erZWpYq7FgNKvYwebi2LaEiVs1klhUfd3WCThxmmWQ==} dev: true - /@types/d3-interpolate/3.0.1: + /@types/d3-interpolate@3.0.1: resolution: {integrity: sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==} dependencies: '@types/d3-color': 3.1.0 dev: true - /@types/d3-path/3.0.0: + /@types/d3-path@1.0.9: + resolution: {integrity: sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==} + dev: true + + /@types/d3-path@3.0.0: resolution: {integrity: sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==} dev: true - /@types/d3-polygon/3.0.0: + /@types/d3-polygon@3.0.0: resolution: {integrity: sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==} dev: true - /@types/d3-quadtree/3.0.2: + /@types/d3-quadtree@3.0.2: resolution: {integrity: sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==} dev: true - /@types/d3-random/3.0.1: + /@types/d3-random@3.0.1: resolution: {integrity: sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==} dev: true - /@types/d3-scale-chromatic/3.0.0: - resolution: {integrity: sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==} + /@types/d3-sankey@0.12.1: + resolution: {integrity: sha512-10X6l6lXB42udBNX9/fDN+kJuooifSMk7+x4U9815eobavldqis4wDdFQUQjMazh+qlzsUZsGzXKxfWFUVt+3w==} + dependencies: + '@types/d3-shape': 1.3.8 dev: true - /@types/d3-scale/4.0.2: - resolution: {integrity: sha512-Yk4htunhPAwN0XGlIwArRomOjdoBFXC3+kCxK2Ubg7I9shQlVSJy/pG/Ht5ASN+gdMIalpk8TJ5xV74jFsetLA==} + /@types/d3-scale-chromatic@3.0.0: + resolution: {integrity: sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==} + + /@types/d3-scale@4.0.3: + resolution: {integrity: sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==} dependencies: '@types/d3-time': 3.0.0 + + /@types/d3-selection@3.0.5: + resolution: {integrity: sha512-xCB0z3Hi8eFIqyja3vW8iV01+OHGYR2di/+e+AiOcXIOrY82lcvWW8Ke1DYE/EUVMsBl4Db9RppSBS3X1U6J0w==} dev: true - /@types/d3-selection/3.0.3: - resolution: {integrity: sha512-Mw5cf6nlW1MlefpD9zrshZ+DAWL4IQ5LnWfRheW6xwsdaWOb6IRRu2H7XPAQcyXEx1D7XQWgdoKR83ui1/HlEA==} + /@types/d3-shape@1.3.8: + resolution: {integrity: sha512-gqfnMz6Fd5H6GOLYixOZP/xlrMtJms9BaS+6oWxTKHNqPGZ93BkWWupQSCYm6YHqx6h9wjRupuJb90bun6ZaYg==} + dependencies: + '@types/d3-path': 1.0.9 dev: true - /@types/d3-shape/3.1.0: - resolution: {integrity: sha512-jYIYxFFA9vrJ8Hd4Se83YI6XF+gzDL1aC5DCsldai4XYYiVNdhtpGbA/GM6iyQ8ayhSp3a148LY34hy7A4TxZA==} + /@types/d3-shape@3.1.1: + resolution: {integrity: sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A==} dependencies: '@types/d3-path': 3.0.0 dev: true - /@types/d3-time-format/4.0.0: + /@types/d3-time-format@4.0.0: resolution: {integrity: sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==} dev: true - /@types/d3-time/3.0.0: + /@types/d3-time@3.0.0: resolution: {integrity: sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==} - dev: true - /@types/d3-timer/3.0.0: + /@types/d3-timer@3.0.0: resolution: {integrity: sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==} dev: true - /@types/d3-transition/3.0.2: + /@types/d3-transition@3.0.2: resolution: {integrity: sha512-jo5o/Rf+/u6uerJ/963Dc39NI16FQzqwOc54bwvksGAdVfvDrqDpVeq95bEvPtBwLCVZutAEyAtmSyEMxN7vxQ==} dependencies: - '@types/d3-selection': 3.0.3 + '@types/d3-selection': 3.0.5 dev: true - /@types/d3-zoom/3.0.1: + /@types/d3-zoom@3.0.1: resolution: {integrity: sha512-7s5L9TjfqIYQmQQEUcpMAcBOahem7TRoSO/+Gkz02GbMVuULiZzjF2BOdw291dbO2aNon4m2OdFsRGaCq2caLQ==} dependencies: '@types/d3-interpolate': 3.0.1 - '@types/d3-selection': 3.0.3 + '@types/d3-selection': 3.0.5 dev: true - /@types/d3/7.4.0: + /@types/d3@7.4.0: resolution: {integrity: sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA==} dependencies: '@types/d3-array': 3.0.3 @@ -2834,10 +4490,10 @@ packages: '@types/d3-polygon': 3.0.0 '@types/d3-quadtree': 3.0.2 '@types/d3-random': 3.0.1 - '@types/d3-scale': 4.0.2 + '@types/d3-scale': 4.0.3 '@types/d3-scale-chromatic': 3.0.0 - '@types/d3-selection': 3.0.3 - '@types/d3-shape': 3.1.0 + '@types/d3-selection': 3.0.5 + '@types/d3-shape': 3.1.1 '@types/d3-time': 3.0.0 '@types/d3-time-format': 4.0.0 '@types/d3-timer': 3.0.0 @@ -2845,57 +4501,56 @@ packages: '@types/d3-zoom': 3.0.1 dev: true - /@types/debug/4.1.7: + /@types/debug@4.1.7: resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} dependencies: '@types/ms': 0.7.31 - dev: true - /@types/dompurify/2.4.0: - resolution: {integrity: sha512-IDBwO5IZhrKvHFUl+clZxgf3hn2b/lU6H1KaBShPkQyGJUQ0xwebezIPSuiyGwfz1UzJWQl4M7BDxtHtCCPlTg==} + /@types/dompurify@3.0.2: + resolution: {integrity: sha512-YBL4ziFebbbfQfH5mlC+QTJsvh0oJUrWbmxKMyEdL7emlHJqGR2Qb34TEFKj+VCayBvjKy3xczMFNhugThUsfQ==} dependencies: '@types/trusted-types': 2.0.2 dev: true - /@types/eslint-scope/3.7.4: + /@types/eslint-scope@3.7.4: resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} dependencies: - '@types/eslint': 8.4.10 + '@types/eslint': 8.37.0 '@types/estree': 1.0.0 dev: true - /@types/eslint/8.4.10: - resolution: {integrity: sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==} + /@types/eslint@8.37.0: + resolution: {integrity: sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==} dependencies: '@types/estree': 1.0.0 '@types/json-schema': 7.0.11 dev: true - /@types/estree/0.0.51: - resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} + /@types/estree@0.0.39: + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} dev: true - /@types/estree/1.0.0: + /@types/estree@1.0.0: resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} dev: true - /@types/express-serve-static-core/4.17.31: + /@types/express-serve-static-core@4.17.31: resolution: {integrity: sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 dev: true - /@types/express-serve-static-core/4.17.33: + /@types/express-serve-static-core@4.17.33: resolution: {integrity: sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 dev: true - /@types/express/4.17.14: + /@types/express@4.17.14: resolution: {integrity: sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==} dependencies: '@types/body-parser': 1.19.2 @@ -2904,7 +4559,7 @@ packages: '@types/serve-static': 1.15.0 dev: true - /@types/express/4.17.17: + /@types/express@4.17.17: resolution: {integrity: sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==} dependencies: '@types/body-parser': 1.19.2 @@ -2913,258 +4568,278 @@ packages: '@types/serve-static': 1.15.0 dev: true - /@types/flexsearch/0.7.3: + /@types/flexsearch@0.7.3: resolution: {integrity: sha512-HXwADeHEP4exXkCIwy2n1+i0f1ilP1ETQOH5KDOugjkTFZPntWo0Gr8stZOaebkxsdx+k0X/K6obU/+it07ocg==} dev: true - /@types/geojson/7946.0.10: + /@types/geojson@7946.0.10: resolution: {integrity: sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==} dev: true - /@types/graceful-fs/4.1.5: - resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} + /@types/glob@7.2.0: + resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: - '@types/node': 18.11.9 + '@types/minimatch': 5.1.2 + '@types/node': 18.16.0 dev: true - /@types/http-cache-semantics/4.0.1: + /@types/graceful-fs@4.1.5: + resolution: {integrity: sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==} + dependencies: + '@types/node': 18.16.0 + dev: true + + /@types/http-cache-semantics@4.0.1: resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} dev: true - /@types/http-proxy/1.17.9: + /@types/http-proxy@1.17.9: resolution: {integrity: sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/istanbul-lib-coverage/2.0.4: + /@types/istanbul-lib-coverage@2.0.4: resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} dev: true - /@types/istanbul-lib-report/3.0.0: + /@types/istanbul-lib-report@3.0.0: resolution: {integrity: sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==} dependencies: '@types/istanbul-lib-coverage': 2.0.4 dev: true - /@types/istanbul-reports/3.0.1: + /@types/istanbul-reports@3.0.1: resolution: {integrity: sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==} dependencies: '@types/istanbul-lib-report': 3.0.0 dev: true - /@types/js-yaml/4.0.5: + /@types/js-yaml@4.0.5: resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} dev: true - /@types/jsdom/21.1.0: - resolution: {integrity: sha512-leWreJOdnuIxq9Y70tBVm/bvTuh31DSlF/r4l7Cfi4uhVQqLHD0Q4v301GMisEMwwbMgF7ZKxuZ+Jbd4NcdmRw==} + /@types/jsdom@21.1.1: + resolution: {integrity: sha512-cZFuoVLtzKP3gmq9eNosUL1R50U+USkbLtUQ1bYVgl/lKp0FZM7Cq4aIHAL8oIvQ17uSHi7jXPtfDOdjPwBE7A==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 '@types/tough-cookie': 4.0.2 parse5: 7.1.1 dev: true - /@types/json-schema/7.0.11: + /@types/json-schema@7.0.11: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} dev: true - /@types/keyv/3.1.4: + /@types/keyv@3.1.4: resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/linkify-it/3.0.2: + /@types/linkify-it@3.0.2: resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} dev: true - /@types/lodash-es/4.17.6: - resolution: {integrity: sha512-R+zTeVUKDdfoRxpAryaQNRKk3105Rrgx2CFRClIgRGaqDTdjsm8h6IYA8ir584W3ePzkZfst5xIgDwYrlh9HLg==} + /@types/lodash-es@4.17.7: + resolution: {integrity: sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==} dependencies: - '@types/lodash': 4.14.188 + '@types/lodash': 4.14.194 dev: true - /@types/lodash/4.14.188: - resolution: {integrity: sha512-zmEmF5OIM3rb7SbLCFYoQhO4dGt2FRM9AMkxvA3LaADOF1n8in/zGJlWji9fmafLoNyz+FoL6FE0SLtGIArD7w==} + /@types/lodash@4.14.194: + resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==} dev: true - /@types/markdown-it/12.2.3: + /@types/markdown-it@12.2.3: resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} dependencies: '@types/linkify-it': 3.0.2 '@types/mdurl': 1.0.2 dev: true - /@types/mdast/3.0.10: + /@types/mdast@3.0.10: resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} dependencies: '@types/unist': 2.0.6 dev: true - /@types/mdurl/1.0.2: + /@types/mdast@3.0.11: + resolution: {integrity: sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==} + dependencies: + '@types/unist': 2.0.6 + + /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} dev: true - /@types/micromatch/4.0.2: + /@types/micromatch@4.0.2: resolution: {integrity: sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==} dependencies: '@types/braces': 3.0.1 dev: true - /@types/mime/3.0.1: + /@types/mime@3.0.1: resolution: {integrity: sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==} dev: true - /@types/minimist/1.2.2: + /@types/minimatch@5.1.2: + resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + dev: true + + /@types/minimist@1.2.2: resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==} dev: true - /@types/ms/0.7.31: + /@types/ms@0.7.31: resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: true - /@types/node-fetch/2.6.2: - resolution: {integrity: sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==} - dependencies: - '@types/node': 18.11.9 - form-data: 3.0.1 - dev: true - - /@types/node/14.18.29: + /@types/node@14.18.29: resolution: {integrity: sha512-LhF+9fbIX4iPzhsRLpK5H7iPdvW8L4IwGciXQIOEcuF62+9nw/VQVsOViAOOGxY3OlOKGLFv0sWwJXdwQeTn6A==} dev: true - /@types/node/16.11.59: - resolution: {integrity: sha512-6u+36Dj3aDzhfBVUf/mfmc92OEdzQ2kx2jcXGdigfl70E/neV21ZHE6UCz4MDzTRcVqGAM27fk+DLXvyDsn3Jw==} - dev: true + /@types/node@18.16.0: + resolution: {integrity: sha512-BsAaKhB+7X+H4GnSjGhJG9Qi8Tw+inU9nJDwmD5CgOmBLEI6ArdhikpLX7DjbjDRDTbqZzU2LSQNZg8WGPiSZQ==} - /@types/node/18.11.9: - resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} - dev: true - - /@types/normalize-package-data/2.4.1: + /@types/normalize-package-data@2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true - /@types/parse-json/4.0.0: - resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + /@types/prettier@2.7.2: + resolution: {integrity: sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==} dev: true - /@types/prettier/2.7.1: - resolution: {integrity: sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==} - dev: true - - /@types/qs/6.9.7: + /@types/qs@6.9.7: resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} dev: true - /@types/range-parser/1.2.4: + /@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.4: resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} dev: true - /@types/responselike/1.0.0: - resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} + /@types/resolve@1.17.1: + resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/retry/0.12.0: + /@types/responselike@1.0.0: + resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} + dependencies: + '@types/node': 18.16.0 + dev: true + + /@types/retry@0.12.0: resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} dev: true - /@types/rollup-plugin-visualizer/4.2.1: + /@types/rollup-plugin-visualizer@4.2.1: resolution: {integrity: sha512-Fk4y0EgmsSbvbayYhtSI9+cGvgw1rcQ9RlbExkQt4ivXRdiEwFKuRpxNuJCr0JktXIvOPUuPR7GSmtyZu0dujQ==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 rollup: 2.79.1 dev: true - /@types/semver/7.3.12: + /@types/semver@7.3.12: resolution: {integrity: sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==} dev: true - /@types/serve-index/1.9.1: + /@types/serve-index@1.9.1: resolution: {integrity: sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==} dependencies: '@types/express': 4.17.14 dev: true - /@types/serve-static/1.15.0: + /@types/serve-static@1.15.0: resolution: {integrity: sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==} dependencies: '@types/mime': 3.0.1 - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@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.3: + /@types/sizzle@2.3.3: resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==} dev: true - /@types/sockjs/0.3.33: + /@types/sockjs@0.3.33: resolution: {integrity: sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/stack-utils/2.0.1: + /@types/stack-utils@2.0.1: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} dev: true - /@types/stylis/4.0.2: + /@types/stylis@4.0.2: resolution: {integrity: sha512-wtckGuk1eXUlUz0Qb1eXHG37Z7HWT2GfMdqRf8F/ifddTwadSS9Jwsqi4qtXk7cP7MtoyGVIHPElFCLc6HItbg==} dev: true - /@types/tough-cookie/4.0.2: + /@types/tough-cookie@4.0.2: resolution: {integrity: sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==} dev: true - /@types/trusted-types/2.0.2: + /@types/trusted-types@2.0.2: resolution: {integrity: sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==} dev: true - /@types/unist/2.0.6: + /@types/unist@2.0.6: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + + /@types/uuid@9.0.1: + resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==} dev: true - /@types/uuid/9.0.0: - resolution: {integrity: sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==} - dev: true - - /@types/web-bluetooth/0.0.16: + /@types/web-bluetooth@0.0.16: resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} + dev: false + + /@types/web-bluetooth@0.0.17: + resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==} dev: true - /@types/ws/8.5.3: + /@types/ws@8.5.3: resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true - /@types/yargs-parser/21.0.0: + /@types/ws@8.5.4: + resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} + dependencies: + '@types/node': 18.16.0 + dev: true + + /@types/yargs-parser@21.0.0: resolution: {integrity: sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==} dev: true - /@types/yargs/17.0.13: + /@types/yargs@17.0.13: resolution: {integrity: sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg==} dependencies: '@types/yargs-parser': 21.0.0 dev: true - /@types/yauzl/2.10.0: + /@types/yauzl@2.10.0: resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} requiresBuild: true dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 dev: true optional: true - /@typescript-eslint/eslint-plugin/5.42.1_qxgr6oy2qtsmmpo3f6iejuryuq: - resolution: {integrity: sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==} + /@typescript-eslint/eslint-plugin@5.59.0(@typescript-eslint/parser@5.59.0)(eslint@8.39.0)(typescript@5.0.4): + resolution: {integrity: sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -3174,24 +4849,25 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.42.1_yygwinqv3a2io74xmwofqb7uka - '@typescript-eslint/scope-manager': 5.42.1 - '@typescript-eslint/type-utils': 5.42.1_yygwinqv3a2io74xmwofqb7uka - '@typescript-eslint/utils': 5.42.1_yygwinqv3a2io74xmwofqb7uka - debug: 4.3.4 - eslint: 8.32.0 + '@eslint-community/regexpp': 4.5.0 + '@typescript-eslint/parser': 5.59.0(eslint@8.39.0)(typescript@5.0.4) + '@typescript-eslint/scope-manager': 5.59.0 + '@typescript-eslint/type-utils': 5.59.0(eslint@8.39.0)(typescript@5.0.4) + '@typescript-eslint/utils': 5.59.0(eslint@8.39.0)(typescript@5.0.4) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.39.0 + grapheme-splitter: 1.0.4 ignore: 5.2.0 natural-compare-lite: 1.4.0 - regexpp: 3.2.0 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.8.4 - typescript: 4.8.4 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/eslint-plugin/5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy: - resolution: {integrity: sha512-sR0Gja9Ky1teIq4qJOl0nC+Tk64/uYdX+mi+5iB//MH8gwyx8e3SOyhEzeLZEFEEfCaLf8KJq+Bd/6je1t+CAg==} + /@typescript-eslint/eslint-plugin@5.59.0(@typescript-eslint/parser@5.59.0)(eslint@8.39.0)(typescript@5.1.3): + resolution: {integrity: sha512-p0QgrEyrxAWBecR56gyn3wkG15TJdI//eetInP3zYRewDh0XS+DhB3VUAd3QqvziFsfaQIoIuZMxZRB7vXYaYw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 @@ -3201,24 +4877,25 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/parser': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - '@typescript-eslint/scope-manager': 5.48.2 - '@typescript-eslint/type-utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - '@typescript-eslint/utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - debug: 4.3.4 - eslint: 8.32.0 + '@eslint-community/regexpp': 4.5.0 + '@typescript-eslint/parser': 5.59.0(eslint@8.39.0)(typescript@5.1.3) + '@typescript-eslint/scope-manager': 5.59.0 + '@typescript-eslint/type-utils': 5.59.0(eslint@8.39.0)(typescript@5.1.3) + '@typescript-eslint/utils': 5.59.0(eslint@8.39.0)(typescript@5.1.3) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.39.0 + grapheme-splitter: 1.0.4 ignore: 5.2.0 natural-compare-lite: 1.4.0 - regexpp: 3.2.0 semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 + tsutils: 3.21.0(typescript@5.1.3) + typescript: 5.1.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser/5.42.1_yygwinqv3a2io74xmwofqb7uka: - resolution: {integrity: sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==} + /@typescript-eslint/parser@5.59.0(eslint@8.39.0)(typescript@5.0.4): + resolution: {integrity: sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3227,18 +4904,18 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.42.1 - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4 - debug: 4.3.4 - eslint: 8.32.0 - typescript: 4.8.4 + '@typescript-eslint/scope-manager': 5.59.0 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.0.4) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.39.0 + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser/5.48.2_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-38zMsKsG2sIuM5Oi/olurGwYJXzmtdsHhn5mI/pQogP+BjYVkK5iRazCQ8RGS0V+YLk282uWElN70zAAUmaYHw==} + /@typescript-eslint/parser@5.59.0(eslint@8.39.0)(typescript@5.1.3): + resolution: {integrity: sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -3247,34 +4924,26 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 5.48.2 - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/typescript-estree': 5.48.2_typescript@4.9.5 - debug: 4.3.4 - eslint: 8.32.0 - typescript: 4.9.5 + '@typescript-eslint/scope-manager': 5.59.0 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.1.3) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.39.0 + typescript: 5.1.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/scope-manager/5.42.1: - resolution: {integrity: sha512-QAZY/CBP1Emx4rzxurgqj3rUinfsh/6mvuKbLNMfJMMKYLRBfweus8brgXF8f64ABkIZ3zdj2/rYYtF8eiuksQ==} + /@typescript-eslint/scope-manager@5.59.0: + resolution: {integrity: sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/visitor-keys': 5.42.1 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/visitor-keys': 5.59.0 dev: true - /@typescript-eslint/scope-manager/5.48.2: - resolution: {integrity: sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/visitor-keys': 5.48.2 - dev: true - - /@typescript-eslint/type-utils/5.42.1_yygwinqv3a2io74xmwofqb7uka: - resolution: {integrity: sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==} + /@typescript-eslint/type-utils@5.59.0(eslint@8.39.0)(typescript@5.0.4): + resolution: {integrity: sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -3283,18 +4952,18 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4 - '@typescript-eslint/utils': 5.42.1_yygwinqv3a2io74xmwofqb7uka - debug: 4.3.4 - eslint: 8.32.0 - tsutils: 3.21.0_typescript@4.8.4 - typescript: 4.8.4 + '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.0.4) + '@typescript-eslint/utils': 5.59.0(eslint@8.39.0)(typescript@5.0.4) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.39.0 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/type-utils/5.48.2_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==} + /@typescript-eslint/type-utils@5.59.0(eslint@8.39.0)(typescript@5.1.3): + resolution: {integrity: sha512-d/B6VSWnZwu70kcKQSCqjcXpVH+7ABKH8P1KNn4K7j5PXXuycZTPXF44Nui0TEm6rbWGi8kc78xRgOC4n7xFgA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -3303,28 +4972,23 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 5.48.2_typescript@4.9.5 - '@typescript-eslint/utils': 5.48.2_et5x32uxl7z5ldub3ye5rhlyqm - debug: 4.3.4 - eslint: 8.32.0 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 + '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.1.3) + '@typescript-eslint/utils': 5.59.0(eslint@8.39.0)(typescript@5.1.3) + debug: 4.3.4(supports-color@8.1.1) + eslint: 8.39.0 + tsutils: 3.21.0(typescript@5.1.3) + typescript: 5.1.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/types/5.42.1: - resolution: {integrity: sha512-Qrco9dsFF5lhalz+lLFtxs3ui1/YfC6NdXu+RAGBa8uSfn01cjO7ssCsjIsUs484vny9Xm699FSKwpkCcqwWwA==} + /@typescript-eslint/types@5.59.0: + resolution: {integrity: sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@typescript-eslint/types/5.48.2: - resolution: {integrity: sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/typescript-estree/5.42.1_typescript@4.8.4: - resolution: {integrity: sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==} + /@typescript-eslint/typescript-estree@5.59.0(typescript@5.0.4): + resolution: {integrity: sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -3332,20 +4996,20 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/visitor-keys': 5.42.1 - debug: 4.3.4 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/visitor-keys': 5.59.0 + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.3.8 - tsutils: 3.21.0_typescript@4.8.4 - typescript: 4.8.4 + semver: 7.5.0 + tsutils: 3.21.0(typescript@5.0.4) + typescript: 5.0.4 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/typescript-estree/5.42.1_typescript@4.9.5: - resolution: {integrity: sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==} + /@typescript-eslint/typescript-estree@5.59.0(typescript@5.1.3): + resolution: {integrity: sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' @@ -3353,345 +5017,591 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/visitor-keys': 5.42.1 - debug: 4.3.4 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/visitor-keys': 5.59.0 + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 - semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 + semver: 7.5.0 + tsutils: 3.21.0(typescript@5.1.3) + typescript: 5.1.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/typescript-estree/5.48.2_typescript@4.9.5: - resolution: {integrity: sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==} + /@typescript-eslint/utils@5.59.0(eslint@8.39.0)(typescript@5.0.4): + resolution: {integrity: sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - typescript: '*' + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.39.0) + '@types/json-schema': 7.0.11 + '@types/semver': 7.3.12 + '@typescript-eslint/scope-manager': 5.59.0 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.0.4) + eslint: 8.39.0 + eslint-scope: 5.1.1 + semver: 7.5.3 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@5.59.0(eslint@8.39.0)(typescript@5.1.3): + resolution: {integrity: sha512-GGLFd+86drlHSvPgN/el6dRQNYYGOvRSDVydsUaQluwIW3HvbXuxyuD5JETvBt/9qGYe+lOrDk6gRrWOHb/FvA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.39.0) + '@types/json-schema': 7.0.11 + '@types/semver': 7.3.12 + '@typescript-eslint/scope-manager': 5.59.0 + '@typescript-eslint/types': 5.59.0 + '@typescript-eslint/typescript-estree': 5.59.0(typescript@5.1.3) + eslint: 8.39.0 + eslint-scope: 5.1.1 + semver: 7.5.3 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@5.59.0: + resolution: {integrity: sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.59.0 + eslint-visitor-keys: 3.4.0 + dev: true + + /@unocss/astro@0.55.2(rollup@2.79.1)(vite@4.3.9): + resolution: {integrity: sha512-cSzBKPEveZZQDZp5bq0UlL8CVvzB/1LsgZmZufxi9oMMjMJYqzfTkKg5z65GcP82Xp5c0N3KKkl/R6I+/7Iwvw==} + peerDependencies: + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 peerDependenciesMeta: - typescript: + vite: optional: true dependencies: - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/visitor-keys': 5.48.2 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.3.8 - tsutils: 3.21.0_typescript@4.9.5 - typescript: 4.9.5 + '@unocss/core': 0.55.2 + '@unocss/reset': 0.55.2 + '@unocss/vite': 0.55.2(rollup@2.79.1)(vite@4.3.9) + vite: 4.3.9(@types/node@18.16.0) transitivePeerDependencies: - - supports-color + - rollup dev: true - /@typescript-eslint/utils/5.42.1_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@unocss/cli@0.55.2(rollup@2.79.1): + resolution: {integrity: sha512-ZJ8aBhm+3WjGCA5HcOQ4C3mbtJwkgMX2gpjjJ0MPh/iZOz3+/zmHlrXJCS3jIFouRYSwxxanWdrGUuLIQLqPhQ==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@ampproject/remapping': 2.2.1 + '@rollup/pluginutils': 5.0.3(rollup@2.79.1) + '@unocss/config': 0.55.2 + '@unocss/core': 0.55.2 + '@unocss/preset-uno': 0.55.2 + cac: 6.7.14 + chokidar: 3.5.3 + colorette: 2.0.20 + consola: 3.2.3 + fast-glob: 3.3.1 + magic-string: 0.30.2 + pathe: 1.1.1 + perfect-debounce: 1.0.0 + transitivePeerDependencies: + - rollup + dev: true + + /@unocss/config@0.55.2: + resolution: {integrity: sha512-RYDv9QzhUeBz9BY+Pty0xc9vk/m4LGBNMiBghcItW6zXN554JbSuoPD55DmnvO2iXrIYujBZdB/Kob6GLCZpqw==} + engines: {node: '>=14'} + dependencies: + '@unocss/core': 0.55.2 + unconfig: 0.3.10 + dev: true + + /@unocss/core@0.55.2: + resolution: {integrity: sha512-ZLEES8RDgWoK/vttUzl3PM2bZqL3HvhLgj8xdDa09Xw+JiTlR4c66s+hLn52oCoJTnT9lGsD2j7tTGN9ToSiTA==} + dev: true + + /@unocss/extractor-arbitrary-variants@0.55.2: + resolution: {integrity: sha512-mHEoFx+ITe3OgFoIUhkCQxRgUjvOJeHtI1Z3Sm8NDMy2vTqOlkSf7NLWEyFfQsSFYqpWGTkaW1XiMZujGMoB/g==} + dependencies: + '@unocss/core': 0.55.2 + dev: true + + /@unocss/inspector@0.55.2: + resolution: {integrity: sha512-AMNZ7FsBFhQCMuAQugCk7d+3uoHDN2VFwCzSxk0ITgG51J90jfVgAo9mJf28W/AM4g0qVHScveJDPKzA+2o+Vg==} + dependencies: + gzip-size: 6.0.0 + sirv: 2.0.3 + dev: true + + /@unocss/postcss@0.55.2(postcss@8.4.27): + resolution: {integrity: sha512-HJLGINNlQ3DGL9zRGuctX+mOVW2w7o8Wj89v3/2qTcqXBDpwfn1+KlxSjU9rsEPdE4Ur3MIcVXcJC0wz4+EwEA==} + engines: {node: '>=14'} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + postcss: ^8.4.21 dependencies: - '@types/json-schema': 7.0.11 - '@types/semver': 7.3.12 - '@typescript-eslint/scope-manager': 5.42.1 - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/typescript-estree': 5.42.1_typescript@4.9.5 - eslint: 8.32.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.32.0 - semver: 7.3.8 - transitivePeerDependencies: - - supports-color - - typescript + '@unocss/config': 0.55.2 + '@unocss/core': 0.55.2 + css-tree: 2.3.1 + fast-glob: 3.3.1 + magic-string: 0.30.2 + postcss: 8.4.27 dev: true - /@typescript-eslint/utils/5.42.1_yygwinqv3a2io74xmwofqb7uka: - resolution: {integrity: sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@unocss/preset-attributify@0.55.2: + resolution: {integrity: sha512-jn5ulsKpAipsX3Gf2/iSZydgI0eP1ENeoS6rrNBL8zl1mRihnZYFegS75rGYjO6sEfEHrhkBiSHOw7Uv5KtLbw==} + dependencies: + '@unocss/core': 0.55.2 + dev: true + + /@unocss/preset-icons@0.55.2: + resolution: {integrity: sha512-NK9LcTlBZv6zO8Qbu+VA9HblzYc5ebuFwaQMfQcYj2Z6dBOT27Ki41LY1qjEXzzMPXb44Q14Rlk0tJc8LtJIpQ==} + dependencies: + '@iconify/utils': 2.1.7 + '@unocss/core': 0.55.2 + ofetch: 1.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@unocss/preset-mini@0.55.2: + resolution: {integrity: sha512-jwUsrwtPwMvFVJUP+FVFjq+sp+xQPyFLRPSb89ZI34F1a3EwJ2wioDICLqWjOjY7zei9UgtSY0owBM9vwxw/kg==} + dependencies: + '@unocss/core': 0.55.2 + '@unocss/extractor-arbitrary-variants': 0.55.2 + dev: true + + /@unocss/preset-tagify@0.55.2: + resolution: {integrity: sha512-m8/9wBtUQSwnwsLANhUOc7sukF8ReHJ7ZC6fCfTozRMOhwu+bDcf9G7pguXdNC4DdZXI15cvbZzkYF2l733qUw==} + dependencies: + '@unocss/core': 0.55.2 + dev: true + + /@unocss/preset-typography@0.55.2: + resolution: {integrity: sha512-Y4JEihpKPDlXWXxnnMZbQclqZ4+DUD8RVFk46ERe9CLNEYkFObd4LG7yfSurr/C01zuU/GhEMyOWqSGsSyCxKg==} + dependencies: + '@unocss/core': 0.55.2 + '@unocss/preset-mini': 0.55.2 + dev: true + + /@unocss/preset-uno@0.55.2: + resolution: {integrity: sha512-8VJXC6+f5YBjUaTkf+EGAembDYMleb0zjkb4hwXxjPIsO+mXixdZC2icCiN/12DLlwH4FzEvObLKns3CGEAZZw==} + dependencies: + '@unocss/core': 0.55.2 + '@unocss/preset-mini': 0.55.2 + '@unocss/preset-wind': 0.55.2 + dev: true + + /@unocss/preset-web-fonts@0.55.2: + resolution: {integrity: sha512-kRnrfZPDkU2r9tp507rsh4kwhUzZ76XBTZLmElYm8tlP6HZzIHcFF8fdW15J4nh81b/IGw8ZOS7aQmqtHu3A8A==} + dependencies: + '@unocss/core': 0.55.2 + ofetch: 1.1.1 + dev: true + + /@unocss/preset-wind@0.55.2: + resolution: {integrity: sha512-th/aOokb10ApaiVLNI093mvko4XryJ70oEhzz4tHdSuhnQWf5eY7+k7y9EEYFz8i1OOrKuer0HzUV27llZaufw==} + dependencies: + '@unocss/core': 0.55.2 + '@unocss/preset-mini': 0.55.2 + dev: true + + /@unocss/reset@0.55.2: + resolution: {integrity: sha512-paInTGIhtI96fcJGZWbkPLW/7qiTlHxSbEIs1HGHcbf3WbwNuKrJUvKlQAhUs2HILNKhvsTXQl05Os8gtinLEA==} + dev: true + + /@unocss/scope@0.55.2: + resolution: {integrity: sha512-o1b86ejgaFDqfC712mUZqZDQNf6o1xDzm6+bgHySdiltR8Quo6l8RcoZjZrCvEogtPbko4/XJ374t1NQMUQf4g==} + dev: true + + /@unocss/transformer-attributify-jsx-babel@0.55.2: + resolution: {integrity: sha512-pmfF546i8pKfMNeYZOJz2UzbuUwj0v7GqcoP5fClyRUzBMUfXdJwBSdFaYkdWR5Q/O1sv+pI0S8r/G9T7QuldA==} + dependencies: + '@unocss/core': 0.55.2 + dev: true + + /@unocss/transformer-attributify-jsx@0.55.2: + resolution: {integrity: sha512-WerdaNagorTtYDvbhlZEmeuBrQ5lmPE0vG9r20bPR/vLy9UmbIFPpzt6b/hSLqOUnZnaEfbrpNUlpBZgUXpvsg==} + dependencies: + '@unocss/core': 0.55.2 + dev: true + + /@unocss/transformer-compile-class@0.55.2: + resolution: {integrity: sha512-zKeJtAirFrgj8TheKplgdKrPV9hPN3i2gEy/aQ+CrHHImcQtxZ1FJzmJT1yV77MOXOdeRJOhiePNOe2TE1A4tw==} + dependencies: + '@unocss/core': 0.55.2 + dev: true + + /@unocss/transformer-directives@0.55.2: + resolution: {integrity: sha512-IJKL5clOiv2RjvHYr4xumS4eFScPsi3Vg4vGugsmn43PZ1FsApp8UElHfhuhBsEEiffnsgTD+N5u/EiPpyI0Gw==} + dependencies: + '@unocss/core': 0.55.2 + css-tree: 2.3.1 + dev: true + + /@unocss/transformer-variant-group@0.55.2: + resolution: {integrity: sha512-BIAigftn+mfUeQT7sPzJNgvvbrmLj0gmYmeK4U7/8NxUuOuC0ROTNSw+MKU7yDiPYHqb1kxVZ47LZ3GdUcNPRA==} + dependencies: + '@unocss/core': 0.55.2 + dev: true + + /@unocss/vite@0.55.2(rollup@2.79.1)(vite@4.3.9): + resolution: {integrity: sha512-JEyEaJt8D+Ed3Z8GDQ0hMWqKsB47/DoS+aPzDoXSIVozgi8seHtfSChBOBUSgcCrozfBVp42YHbYYyloDkb2Yw==} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 dependencies: - '@types/json-schema': 7.0.11 - '@types/semver': 7.3.12 - '@typescript-eslint/scope-manager': 5.42.1 - '@typescript-eslint/types': 5.42.1 - '@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4 - eslint: 8.32.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.32.0 - semver: 7.3.8 + '@ampproject/remapping': 2.2.1 + '@rollup/pluginutils': 5.0.3(rollup@2.79.1) + '@unocss/config': 0.55.2 + '@unocss/core': 0.55.2 + '@unocss/inspector': 0.55.2 + '@unocss/scope': 0.55.2 + '@unocss/transformer-directives': 0.55.2 + chokidar: 3.5.3 + fast-glob: 3.3.1 + magic-string: 0.30.2 + vite: 4.3.9(@types/node@18.16.0) transitivePeerDependencies: - - supports-color - - typescript + - rollup dev: true - /@typescript-eslint/utils/5.48.2_et5x32uxl7z5ldub3ye5rhlyqm: - resolution: {integrity: sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + /@vite-pwa/vitepress@0.2.0(vite-plugin-pwa@0.16.0): + resolution: {integrity: sha512-dVQVaP6NB9woCFe4UASUqRp7uwBQJOVXlJlqK4krqXcbb3NuXIXIWOnU7HLpJnHqZj5U/81gKtLN6gs5gJBwiQ==} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + vite-plugin-pwa: '>=0.16.3 <1' dependencies: - '@types/json-schema': 7.0.11 - '@types/semver': 7.3.12 - '@typescript-eslint/scope-manager': 5.48.2 - '@typescript-eslint/types': 5.48.2 - '@typescript-eslint/typescript-estree': 5.48.2_typescript@4.9.5 - eslint: 8.32.0 - eslint-scope: 5.1.1 - eslint-utils: 3.0.0_eslint@8.32.0 - semver: 7.3.8 - transitivePeerDependencies: - - supports-color - - typescript + vite-plugin-pwa: 0.16.0(vite@4.3.9)(workbox-build@7.0.0)(workbox-window@7.0.0) dev: true - /@typescript-eslint/visitor-keys/5.42.1: - resolution: {integrity: sha512-LOQtSF4z+hejmpUvitPlc4hA7ERGoj2BVkesOcG91HCn8edLGUXbTrErmutmPbl8Bo9HjAvOO/zBKQHExXNA2A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.42.1 - eslint-visitor-keys: 3.3.0 - dev: true - - /@typescript-eslint/visitor-keys/5.48.2: - resolution: {integrity: sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.48.2 - eslint-visitor-keys: 3.3.0 - dev: true - - /@vitejs/plugin-vue/4.0.0_vite@4.1.1+vue@3.2.45: - resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==} + /@vitejs/plugin-vue@4.2.1(vite@4.3.9)(vue@3.3.4): + resolution: {integrity: sha512-ZTZjzo7bmxTRTkb8GSTwkPOYDIP7pwuyV+RV53c9PYUouwcbkIZIvWvNWlX2b1dYZqtOv7D6iUAnJLVNGcLrSw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.0.0 vue: ^3.2.25 dependencies: - vite: 4.1.1 - vue: 3.2.45 + vite: 4.3.9(@types/node@18.16.0) + vue: 3.3.4 dev: true - /@vitest/coverage-c8/0.28.4_vun5xzxu3tkrssf3erdbijyyki: - resolution: {integrity: sha512-btelLBxaWhHnywXRQxDlrvPhGdnuIaD3XulsxcZRIcnpLPbFu39dNTT0IYu2QWP2ZZrV0AmNtdLIfD4c77zMAg==} - dependencies: - c8: 7.12.0 - picocolors: 1.0.0 - std-env: 3.3.2 - vitest: 0.28.4_vun5xzxu3tkrssf3erdbijyyki - transitivePeerDependencies: - - '@edge-runtime/vm' - - '@vitest/browser' - - '@vitest/ui' - - happy-dom - - jsdom - - less - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /@vitest/expect/0.28.4: - resolution: {integrity: sha512-JqK0NZ4brjvOSL8hXAnIsfi+jxDF7rH/ZWCGCt0FAqRnVFc1hXsfwXksQvEnKqD84avRt3gmeXoK4tNbmkoVsQ==} - dependencies: - '@vitest/spy': 0.28.4 - '@vitest/utils': 0.28.4 - chai: 4.3.7 - dev: true - - /@vitest/expect/0.28.5: - resolution: {integrity: sha512-gqTZwoUTwepwGIatnw4UKpQfnoyV0Z9Czn9+Lo2/jLIt4/AXLTn+oVZxlQ7Ng8bzcNkR+3DqLJ08kNr8jRmdNQ==} - dependencies: - '@vitest/spy': 0.28.5 - '@vitest/utils': 0.28.5 - chai: 4.3.7 - dev: true - - /@vitest/runner/0.28.4: - resolution: {integrity: sha512-Q8UV6GjDvBSTfUoq0QXVCNpNOUrWu4P2qvRq7ssJWzn0+S0ojbVOxEjMt+8a32X6SdkhF8ak+2nkppsqV0JyNQ==} - dependencies: - '@vitest/utils': 0.28.4 - p-limit: 4.0.0 - pathe: 1.1.0 - dev: true - - /@vitest/runner/0.28.5: - resolution: {integrity: sha512-NKkHtLB+FGjpp5KmneQjTcPLWPTDfB7ie+MmF1PnUBf/tGe2OjGxWyB62ySYZ25EYp9krR5Bw0YPLS/VWh1QiA==} - dependencies: - '@vitest/utils': 0.28.5 - p-limit: 4.0.0 - pathe: 1.1.0 - dev: true - - /@vitest/spy/0.28.4: - resolution: {integrity: sha512-8WuhfXLlvCXpNXEGJW6Gc+IKWI32435fQJLh43u70HnZ1otJOa2Cmg2Wy2Aym47ZnNCP4NolF+8cUPwd0MigKQ==} - dependencies: - tinyspy: 1.0.2 - dev: true - - /@vitest/spy/0.28.5: - resolution: {integrity: sha512-7if6rsHQr9zbmvxN7h+gGh2L9eIIErgf8nSKYDlg07HHimCxp4H6I/X/DPXktVPPLQfiZ1Cw2cbDIx9fSqDjGw==} - dependencies: - tinyspy: 1.0.2 - dev: true - - /@vitest/ui/0.28.4: - resolution: {integrity: sha512-LQfCCFc17n49mwtraV9/NAWl2DUqJS/9ZEa3fqJjoYO+HowdseQ5jvWflpzliCyfrIAh6cXVo1bNzHnDXe0cbw==} - dependencies: - fast-glob: 3.2.12 - flatted: 3.2.7 - pathe: 1.1.0 - picocolors: 1.0.0 - sirv: 2.0.2 - dev: true - - /@vitest/utils/0.28.4: - resolution: {integrity: sha512-l2QztOLdc2LkR+w/lP52RGh8hW+Ul4KESmCAgVE8q737I7e7bQoAfkARKpkPJ4JQtGpwW4deqlj1732VZD7TFw==} - dependencies: - cli-truncate: 3.1.0 - diff: 5.1.0 - loupe: 2.3.6 - picocolors: 1.0.0 - pretty-format: 27.5.1 - dev: true - - /@vitest/utils/0.28.5: - resolution: {integrity: sha512-UyZdYwdULlOa4LTUSwZ+Paz7nBHGTT72jKwdFSV4IjHF1xsokp+CabMdhjvVhYwkLfO88ylJT46YMilnkSARZA==} - dependencies: - cli-truncate: 3.1.0 - diff: 5.1.0 - loupe: 2.3.6 - picocolors: 1.0.0 - pretty-format: 27.5.1 - dev: true - - /@vue/compiler-core/3.2.45: - resolution: {integrity: sha512-rcMj7H+PYe5wBV3iYeUgbCglC+pbpN8hBLTJvRiK2eKQiWqu+fG9F+8sW99JdL4LQi7Re178UOxn09puSXvn4A==} - dependencies: - '@babel/parser': 7.19.1 - '@vue/shared': 3.2.45 - estree-walker: 2.0.2 - source-map: 0.6.1 - dev: true - - /@vue/compiler-dom/3.2.45: - resolution: {integrity: sha512-tyYeUEuKqqZO137WrZkpwfPCdiiIeXYCcJ8L4gWz9vqaxzIQRccTSwSWZ/Axx5YR2z+LvpUbmPNXxuBU45lyRw==} - dependencies: - '@vue/compiler-core': 3.2.45 - '@vue/shared': 3.2.45 - dev: true - - /@vue/compiler-sfc/3.2.45: - resolution: {integrity: sha512-1jXDuWah1ggsnSAOGsec8cFjT/K6TMZ0sPL3o3d84Ft2AYZi2jWJgRMjw4iaK0rBfA89L5gw427H4n1RZQBu6Q==} - dependencies: - '@babel/parser': 7.19.1 - '@vue/compiler-core': 3.2.45 - '@vue/compiler-dom': 3.2.45 - '@vue/compiler-ssr': 3.2.45 - '@vue/reactivity-transform': 3.2.45 - '@vue/shared': 3.2.45 - estree-walker: 2.0.2 - magic-string: 0.25.9 - postcss: 8.4.20 - source-map: 0.6.1 - dev: true - - /@vue/compiler-ssr/3.2.45: - resolution: {integrity: sha512-6BRaggEGqhWht3lt24CrIbQSRD5O07MTmd+LjAn5fJj568+R9eUD2F7wMQJjX859seSlrYog7sUtrZSd7feqrQ==} - dependencies: - '@vue/compiler-dom': 3.2.45 - '@vue/shared': 3.2.45 - dev: true - - /@vue/devtools-api/6.5.0: - resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} - dev: true - - /@vue/reactivity-transform/3.2.45: - resolution: {integrity: sha512-BHVmzYAvM7vcU5WmuYqXpwaBHjsS8T63jlKGWVtHxAHIoMIlmaMyurUSEs1Zcg46M4AYT5MtB1U274/2aNzjJQ==} - dependencies: - '@babel/parser': 7.19.1 - '@vue/compiler-core': 3.2.45 - '@vue/shared': 3.2.45 - estree-walker: 2.0.2 - magic-string: 0.25.9 - dev: true - - /@vue/reactivity/3.2.45: - resolution: {integrity: sha512-PRvhCcQcyEVohW0P8iQ7HDcIOXRjZfAsOds3N99X/Dzewy8TVhTCT4uXpAHfoKjVTJRA0O0K+6QNkDIZAxNi3A==} - dependencies: - '@vue/shared': 3.2.45 - dev: true - - /@vue/runtime-core/3.2.45: - resolution: {integrity: sha512-gzJiTA3f74cgARptqzYswmoQx0fIA+gGYBfokYVhF8YSXjWTUA2SngRzZRku2HbGbjzB6LBYSbKGIaK8IW+s0A==} - dependencies: - '@vue/reactivity': 3.2.45 - '@vue/shared': 3.2.45 - dev: true - - /@vue/runtime-dom/3.2.45: - resolution: {integrity: sha512-cy88YpfP5Ue2bDBbj75Cb4bIEZUMM/mAkDMfqDTpUYVgTf/kuQ2VQ8LebuZ8k6EudgH8pYhsGWHlY0lcxlvTwA==} - dependencies: - '@vue/runtime-core': 3.2.45 - '@vue/shared': 3.2.45 - csstype: 2.6.21 - dev: true - - /@vue/server-renderer/3.2.45_vue@3.2.45: - resolution: {integrity: sha512-ebiMq7q24WBU1D6uhPK//2OTR1iRIyxjF5iVq/1a5I1SDMDyDu4Ts6fJaMnjrvD3MqnaiFkKQj+LKAgz5WIK3g==} + /@vitejs/plugin-vue@4.2.3(vite@4.4.9)(vue@3.3.4): + resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==} + engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vue: 3.2.45 + vite: ^4.0.0 + vue: ^3.2.25 dependencies: - '@vue/compiler-ssr': 3.2.45 - '@vue/shared': 3.2.45 - vue: 3.2.45 + vite: 4.4.9(@types/node@18.16.0) + vue: 3.3.4 dev: true - /@vue/shared/3.2.45: - resolution: {integrity: sha512-Ewzq5Yhimg7pSztDV+RH1UDKBzmtqieXQlpTVm2AwraoRL/Rks96mvd8Vgi7Lj+h+TH8dv7mXD3FRZR3TUvbSg==} + /@vitest/coverage-v8@0.34.0(vitest@0.34.0): + resolution: {integrity: sha512-rUFY9xX6nnrFvVfTDjlEaOFzfHqolUoA+Unz356T38W100QA+NiaekCFq/3XB/LXBISaFreCsVjAbPV3hjV7Jg==} + peerDependencies: + vitest: '>=0.32.0 <1' + dependencies: + '@ampproject/remapping': 2.2.1 + '@bcoe/v8-coverage': 0.2.3 + istanbul-lib-coverage: 3.2.0 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.5 + magic-string: 0.30.1 + picocolors: 1.0.0 + std-env: 3.3.3 + test-exclude: 6.0.0 + v8-to-istanbul: 9.1.0 + vitest: 0.34.0(@vitest/ui@0.34.0)(jsdom@22.0.0) + transitivePeerDependencies: + - supports-color dev: true - /@vueuse/core/9.12.0_vue@3.2.45: - resolution: {integrity: sha512-h/Di8Bvf6xRcvS/PvUVheiMYYz3U0tH3X25YxONSaAUBa841ayMwxkuzx/DGUMCW/wHWzD8tRy2zYmOC36r4sg==} + /@vitest/expect@0.34.0: + resolution: {integrity: sha512-d1ZU0XomWFAFyYIc6uNuY0N8NJIWESyO/6ZmwLvlHZw0GevH4AEEpq178KjXIvSCrbHN0GnzYzitd0yjfy7+Ow==} + dependencies: + '@vitest/spy': 0.34.0 + '@vitest/utils': 0.34.0 + chai: 4.3.7 + dev: true + + /@vitest/runner@0.34.0: + resolution: {integrity: sha512-xaqM+oArJothtYXzy/dwu/iHe93Khq5QkvnYbzTxiLA0enD2peft1cask3yE6cJpwMkr7C2D1uMJwnTt4mquDw==} + dependencies: + '@vitest/utils': 0.34.0 + p-limit: 4.0.0 + pathe: 1.1.1 + dev: true + + /@vitest/snapshot@0.34.0: + resolution: {integrity: sha512-eGN5XBZHYOghxCOQbf8dcn6/3g7IW77GOOOC/mNFYwRXsPeoQgcgWnhj+6wgJ04pVv25wpxWL9jUkzaQ7LoFtg==} + dependencies: + magic-string: 0.30.2 + pathe: 1.1.1 + pretty-format: 29.5.0 + dev: true + + /@vitest/spy@0.34.0: + resolution: {integrity: sha512-0SZaWrQvL9ZiF/uJvyWSvsKjfuMvD1M6dE5BbE4Dmt8Vh3k4htwCV8g3ce8YOYmJSxkbh6TNOpippD6NVsxW6w==} + dependencies: + tinyspy: 2.1.1 + dev: true + + /@vitest/ui@0.34.0(vitest@0.34.0): + resolution: {integrity: sha512-+MPvbOiKrOWm1JL8hfROybzTB0Y6gWbMCQZlEI67M1+a1iTjaowXTeYSN4pGu0SubeGJw0JTrZ/Z/sRLmb9wLw==} + peerDependencies: + vitest: '>=0.30.1 <1' + dependencies: + '@vitest/utils': 0.34.0 + fast-glob: 3.3.1 + fflate: 0.8.0 + flatted: 3.2.7 + pathe: 1.1.1 + picocolors: 1.0.0 + sirv: 2.0.3 + vitest: 0.34.0(@vitest/ui@0.34.0)(jsdom@22.0.0) + dev: true + + /@vitest/utils@0.34.0: + resolution: {integrity: sha512-IktrDLhBKf3dEUUxH+lcHiPnaw952+GdGvoxg99liMscgP6IePf6LuMY7B9dEIHkFunB1R8VMR/wmI/4UGg1aw==} + dependencies: + diff-sequences: 29.4.3 + loupe: 2.3.6 + pretty-format: 29.5.0 + dev: true + + /@vue/compat@3.3.4(vue@3.3.4): + resolution: {integrity: sha512-VwAsPqUqRJVxeLQPUC03Sa5d+T8UG2Qv4VItq74KmNvtQlRXICpa/sqq12BcyBB4Tz1U5paOEZxWCUoXkrZ9QQ==} + peerDependencies: + vue: 3.3.4 + dependencies: + '@babel/parser': 7.21.8 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + vue: 3.3.4 + dev: false + + /@vue/compiler-core@3.3.4: + resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + dependencies: + '@babel/parser': 7.21.8 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + + /@vue/compiler-dom@3.3.4: + resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + dependencies: + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + + /@vue/compiler-sfc@3.3.4: + resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} + dependencies: + '@babel/parser': 7.21.8 + '@vue/compiler-core': 3.3.4 + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-ssr': 3.3.4 + '@vue/reactivity-transform': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.2 + postcss: 8.4.27 + source-map-js: 1.0.2 + + /@vue/compiler-ssr@3.3.4: + resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} + dependencies: + '@vue/compiler-dom': 3.3.4 + '@vue/shared': 3.3.4 + + /@vue/devtools-api@6.5.0: + resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} + + /@vue/reactivity-transform@3.3.4: + resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} + dependencies: + '@babel/parser': 7.21.8 + '@vue/compiler-core': 3.3.4 + '@vue/shared': 3.3.4 + estree-walker: 2.0.2 + magic-string: 0.30.2 + + /@vue/reactivity@3.3.4: + resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} + dependencies: + '@vue/shared': 3.3.4 + + /@vue/runtime-core@3.3.4: + resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} + dependencies: + '@vue/reactivity': 3.3.4 + '@vue/shared': 3.3.4 + + /@vue/runtime-dom@3.3.4: + resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} + dependencies: + '@vue/runtime-core': 3.3.4 + '@vue/shared': 3.3.4 + csstype: 3.1.2 + + /@vue/server-renderer@3.3.4(vue@3.3.4): + resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} + peerDependencies: + vue: 3.3.4 + dependencies: + '@vue/compiler-ssr': 3.3.4 + '@vue/shared': 3.3.4 + vue: 3.3.4 + + /@vue/shared@3.3.4: + resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + + /@vueuse/core@10.1.0(vue@3.3.4): + resolution: {integrity: sha512-3Znoa5m5RO+z4/C9w6DRaKTR3wCVJvD5rav8HTDGsr+7rOZRHtcgFJ8NcCs0ZvIpmev2kExTa311ns5j2RbzDQ==} dependencies: '@types/web-bluetooth': 0.0.16 - '@vueuse/metadata': 9.12.0 - '@vueuse/shared': 9.12.0_vue@3.2.45 - vue-demi: 0.13.11_vue@3.2.45 + '@vueuse/metadata': 10.1.0 + '@vueuse/shared': 10.1.0(vue@3.3.4) + vue-demi: 0.14.5(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue - dev: true + dev: false - /@vueuse/metadata/9.12.0: - resolution: {integrity: sha512-9oJ9MM9lFLlmvxXUqsR1wLt1uF7EVbP5iYaHJYqk+G2PbMjY6EXvZeTjbdO89HgoF5cI6z49o2zT/jD9SVoNpQ==} - dev: true - - /@vueuse/shared/9.12.0_vue@3.2.45: - resolution: {integrity: sha512-TWuJLACQ0BVithVTRbex4Wf1a1VaRuSpVeyEd4vMUWl54PzlE0ciFUshKCXnlLuD0lxIaLK4Ypj3NXYzZh4+SQ==} + /@vueuse/core@10.3.0(vue@3.3.4): + resolution: {integrity: sha512-BEM5yxcFKb5btFjTSAFjTu5jmwoW66fyV9uJIP4wUXXU8aR5Hl44gndaaXp7dC5HSObmgbnR2RN+Un1p68Mf5Q==} dependencies: - vue-demi: 0.13.11_vue@3.2.45 + '@types/web-bluetooth': 0.0.17 + '@vueuse/metadata': 10.3.0 + '@vueuse/shared': 10.3.0(vue@3.3.4) + vue-demi: 0.14.5(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue dev: true - /@wdio/config/7.16.11: - resolution: {integrity: sha512-sIk9FINQfXohuDONb8RA1uv+29XvUw6OBHfaaU7/c9gfKiOWiRczdfiLqfySZRwYgEgNhzCw5vHIogTry1h+xQ==} + /@vueuse/core@10.4.1(vue@3.3.4): + resolution: {integrity: sha512-DkHIfMIoSIBjMgRRvdIvxsyboRZQmImofLyOHADqiVbQVilP8VVHDhBX2ZqoItOgu7dWa8oXiNnScOdPLhdEXg==} + dependencies: + '@types/web-bluetooth': 0.0.17 + '@vueuse/metadata': 10.4.1 + '@vueuse/shared': 10.4.1(vue@3.3.4) + vue-demi: 0.14.5(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/integrations@10.4.1(focus-trap@7.5.2)(vue@3.3.4): + resolution: {integrity: sha512-uRBPyG5Lxoh1A/J+boiioPT3ELEAPEo4t8W6Mr4yTKIQBeW/FcbsotZNPr4k9uz+3QEksMmflWloS9wCnypM7g==} + peerDependencies: + async-validator: '*' + axios: '*' + change-case: '*' + drauu: '*' + focus-trap: '*' + fuse.js: '*' + idb-keyval: '*' + jwt-decode: '*' + nprogress: '*' + qrcode: '*' + sortablejs: '*' + universal-cookie: '*' + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + dependencies: + '@vueuse/core': 10.4.1(vue@3.3.4) + '@vueuse/shared': 10.4.1(vue@3.3.4) + focus-trap: 7.5.2 + vue-demi: 0.14.5(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/metadata@10.1.0: + resolution: {integrity: sha512-cM28HjDEw5FIrPE9rgSPFZvQ0ZYnOLAOr8hl1XM6tFl80U3WAR5ROdnAqiYybniwP5gt9MKKAJAqd/ab2aHkqg==} + dev: false + + /@vueuse/metadata@10.3.0: + resolution: {integrity: sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw==} + dev: true + + /@vueuse/metadata@10.4.1: + resolution: {integrity: sha512-2Sc8X+iVzeuMGHr6O2j4gv/zxvQGGOYETYXEc41h0iZXIRnRbJZGmY/QP8dvzqUelf8vg0p/yEA5VpCEu+WpZg==} + dev: true + + /@vueuse/shared@10.1.0(vue@3.3.4): + resolution: {integrity: sha512-2X52ogu12i9DkKOQ01yeb/BKg9UO87RNnpm5sXkQvyORlbq8ONS5l39MYkjkeVWWjdT0teJru7a2S41dmHmqjQ==} + dependencies: + vue-demi: 0.14.5(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + + /@vueuse/shared@10.3.0(vue@3.3.4): + resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} + dependencies: + vue-demi: 0.14.5(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/shared@10.4.1(vue@3.3.4): + resolution: {integrity: sha512-vz5hbAM4qA0lDKmcr2y3pPdU+2EVw/yzfRsBdu+6+USGa4PxqSQRYIUC9/NcT06y+ZgaTsyURw2I9qOFaaXHAg==} + dependencies: + vue-demi: 0.14.5(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@wdio/config@7.30.0(typescript@5.1.3): + resolution: {integrity: sha512-/38rol9WCfFTMtXyd/C856/aexxIZnfVvXg7Fw2WXpqZ9qadLA+R4N35S2703n/RByjK/5XAYtHoljtvh3727w==} engines: {node: '>=12.0.0'} dependencies: - '@wdio/logger': 7.16.0 - '@wdio/types': 7.16.11 + '@wdio/logger': 7.26.0 + '@wdio/types': 7.26.0(typescript@5.1.3) + '@wdio/utils': 7.26.0(typescript@5.1.3) deepmerge: 4.2.2 - glob: 7.2.3 + glob: 8.0.3 + transitivePeerDependencies: + - typescript dev: true - /@wdio/logger/7.16.0: - resolution: {integrity: sha512-/6lOGb2Iow5eSsy7RJOl1kCwsP4eMlG+/QKro5zUJsuyNJSQXf2ejhpkzyKWLgQbHu83WX6cM1014AZuLkzoQg==} + /@wdio/logger@7.26.0: + resolution: {integrity: sha512-kQj9s5JudAG9qB+zAAcYGPHVfATl2oqKgqj47yjehOQ1zzG33xmtL1ArFbQKWhDG32y1A8sN6b0pIqBEIwgg8Q==} engines: {node: '>=12.0.0'} dependencies: chalk: 4.1.2 @@ -3700,154 +5610,162 @@ packages: strip-ansi: 6.0.1 dev: true - /@wdio/protocols/7.16.7: - resolution: {integrity: sha512-Wv40pNQcLiPzQ3o98Mv4A8T1EBQ6k4khglz/e2r16CTm+F3DDYh8eLMAsU5cgnmuwwDKX1EyOiFwieykBn5MCg==} + /@wdio/protocols@7.27.0: + resolution: {integrity: sha512-hT/U22R5i3HhwPjkaKAG0yd59eaOaZB0eibRj2+esCImkb5Y6rg8FirrlYRxIGFVBl0+xZV0jKHzR5+o097nvg==} engines: {node: '>=12.0.0'} dev: true - /@wdio/types/7.16.11: - resolution: {integrity: sha512-OFVTFEB6qdG84Y+cOWIacV0loGMgq2SF/rGGlGxai89V3UQxzCFTYVoAx6odAuSNZ37wmfWCykyAR/lAlMItoQ==} + /@wdio/types@7.26.0(typescript@5.1.3): + resolution: {integrity: sha512-mOTfWAGQ+iT58iaZhJMwlUkdEn3XEWE4jthysMLXFnSuZ2eaODVAiK31SmlS/eUqgSIaupeGqYUrtCuSNbLefg==} engines: {node: '>=12.0.0'} + peerDependencies: + typescript: ^4.6.2 + peerDependenciesMeta: + typescript: + optional: true dependencies: - '@types/node': 16.11.59 + '@types/node': 18.16.0 got: 11.8.5 + typescript: 5.1.3 dev: true - /@wdio/utils/7.16.11: - resolution: {integrity: sha512-qeXHREZJ7mz3C2cWGOmFG6MS6njp1js4f8zca3iqxaorWshwkrlNsps3B1iTHfkvK6oWnmc2Q0o5CrtLZl0LkA==} + /@wdio/utils@7.26.0(typescript@5.1.3): + resolution: {integrity: sha512-pVq2MPXZAYLkKGKIIHktHejnHqg4TYKoNYSi2EDv+I3GlT8VZKXHazKhci82ov0tD+GdF27+s4DWNDCfGYfBdQ==} engines: {node: '>=12.0.0'} dependencies: - '@wdio/logger': 7.16.0 - '@wdio/types': 7.16.11 + '@wdio/logger': 7.26.0 + '@wdio/types': 7.26.0(typescript@5.1.3) p-iteration: 1.1.8 + transitivePeerDependencies: + - typescript dev: true - /@webassemblyjs/ast/1.11.1: - resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} + /@webassemblyjs/ast@1.11.6: + resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} dependencies: - '@webassemblyjs/helper-numbers': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 dev: true - /@webassemblyjs/floating-point-hex-parser/1.11.1: - resolution: {integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==} + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} dev: true - /@webassemblyjs/helper-api-error/1.11.1: - resolution: {integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==} + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} dev: true - /@webassemblyjs/helper-buffer/1.11.1: - resolution: {integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==} + /@webassemblyjs/helper-buffer@1.11.6: + resolution: {integrity: sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==} dev: true - /@webassemblyjs/helper-numbers/1.11.1: - resolution: {integrity: sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==} + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.1 - '@webassemblyjs/helper-api-error': 1.11.1 + '@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.1: - resolution: {integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==} + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} dev: true - /@webassemblyjs/helper-wasm-section/1.11.1: - resolution: {integrity: sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==} + /@webassemblyjs/helper-wasm-section@1.11.6: + resolution: {integrity: sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-buffer': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 dev: true - /@webassemblyjs/ieee754/1.11.1: - resolution: {integrity: sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==} + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} dependencies: '@xtuc/ieee754': 1.2.0 dev: true - /@webassemblyjs/leb128/1.11.1: - resolution: {integrity: sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==} + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} dependencies: '@xtuc/long': 4.2.2 dev: true - /@webassemblyjs/utf8/1.11.1: - resolution: {integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==} + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} dev: true - /@webassemblyjs/wasm-edit/1.11.1: - resolution: {integrity: sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==} + /@webassemblyjs/wasm-edit@1.11.6: + resolution: {integrity: sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-buffer': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/helper-wasm-section': 1.11.1 - '@webassemblyjs/wasm-gen': 1.11.1 - '@webassemblyjs/wasm-opt': 1.11.1 - '@webassemblyjs/wasm-parser': 1.11.1 - '@webassemblyjs/wast-printer': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-opt': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + '@webassemblyjs/wast-printer': 1.11.6 dev: true - /@webassemblyjs/wasm-gen/1.11.1: - resolution: {integrity: sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==} + /@webassemblyjs/wasm-gen@1.11.6: + resolution: {integrity: sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/ieee754': 1.11.1 - '@webassemblyjs/leb128': 1.11.1 - '@webassemblyjs/utf8': 1.11.1 + '@webassemblyjs/ast': 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/wasm-opt/1.11.1: - resolution: {integrity: sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==} + /@webassemblyjs/wasm-opt@1.11.6: + resolution: {integrity: sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-buffer': 1.11.1 - '@webassemblyjs/wasm-gen': 1.11.1 - '@webassemblyjs/wasm-parser': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 dev: true - /@webassemblyjs/wasm-parser/1.11.1: - resolution: {integrity: sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==} + /@webassemblyjs/wasm-parser@1.11.6: + resolution: {integrity: sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-api-error': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/ieee754': 1.11.1 - '@webassemblyjs/leb128': 1.11.1 - '@webassemblyjs/utf8': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@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.11.1: - resolution: {integrity: sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==} + /@webassemblyjs/wast-printer@1.11.6: + resolution: {integrity: sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==} dependencies: - '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/ast': 1.11.6 '@xtuc/long': 4.2.2 dev: true - /@webpack-cli/configtest/1.2.0_pda42hcaj7d62cr262fr632kue: + /@webpack-cli/configtest@1.2.0(webpack-cli@4.10.0)(webpack@5.88.2): resolution: {integrity: sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==} peerDependencies: webpack: 4.x.x || 5.x.x webpack-cli: 4.x.x dependencies: - webpack: 5.75.0_webpack-cli@4.10.0 - webpack-cli: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi + webpack: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) + webpack-cli: 4.10.0(webpack-dev-server@4.11.1)(webpack@5.88.2) dev: true - /@webpack-cli/info/1.5.0_webpack-cli@4.10.0: + /@webpack-cli/info@1.5.0(webpack-cli@4.10.0): resolution: {integrity: sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==} peerDependencies: webpack-cli: 4.x.x dependencies: envinfo: 7.8.1 - webpack-cli: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi + webpack-cli: 4.10.0(webpack-dev-server@4.11.1)(webpack@5.88.2) dev: true - /@webpack-cli/serve/1.7.0_ud4agclah7rahur6ntojouq57y: + /@webpack-cli/serve@1.7.0(webpack-cli@4.10.0)(webpack-dev-server@4.11.1): resolution: {integrity: sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==} peerDependencies: webpack-cli: 4.x.x @@ -3856,24 +5774,49 @@ packages: webpack-dev-server: optional: true dependencies: - webpack-cli: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi - webpack-dev-server: 4.11.1_pda42hcaj7d62cr262fr632kue + webpack-cli: 4.10.0(webpack-dev-server@4.11.1)(webpack@5.88.2) + webpack-dev-server: 4.11.1(webpack-cli@4.10.0)(webpack@5.88.2) 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 - /JSONSelect/0.4.0: + /@zenuml/core@3.0.6(ts-node@10.9.1): + resolution: {integrity: sha512-azEBVrl+ClCPhII92TbzBUFcWhIjlOPdEHVzF6eZXs5Oy4JlrfldS5pAZBHCFL4riOBsjZ5sHHmQLQg9V07T4Q==} + engines: {node: '>=12.0.0'} + dependencies: + '@types/assert': 1.5.6 + '@types/ramda': 0.28.25 + '@vue/compat': 3.3.4(vue@3.3.4) + 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.14.1 + postcss: 8.4.27 + ramda: 0.28.0 + tailwindcss: 3.3.2(ts-node@10.9.1) + vue: 3.3.4 + vuex: 4.1.0(vue@3.3.4) + transitivePeerDependencies: + - ts-node + dev: false + + /JSONSelect@0.4.0: resolution: {integrity: sha512-VRLR3Su35MH+XV2lrvh9O7qWoug/TUyj9tLDjn9rtpUCNnILLrHjgd/tB0KrhugCxUpj3UqoLqfYb3fLJdIQQQ==} engines: {node: '>=0.4.7'} dev: true - /JSONStream/1.3.5: + /JSONStream@1.3.5: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true dependencies: @@ -3881,22 +5824,25 @@ packages: through: 2.3.8 dev: true - /JSV/4.0.2: + /JSV@4.0.2: resolution: {integrity: sha512-ZJ6wx9xaKJ3yFUhq5/sk82PJMuUyLk277I8mQeyDgCTjGdjWJIvPfaU5LIXaMuaN2UO1X3kZH4+lgphublZUHw==} dev: true - /abab/2.0.6: + /abab@2.0.6: resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} 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: + 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: @@ -3904,74 +5850,65 @@ packages: negotiator: 0.6.3 dev: true - /acorn-globals/6.0.0: + /acorn-globals@6.0.0: resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} dependencies: acorn: 7.4.1 acorn-walk: 7.2.0 dev: true - /acorn-globals/7.0.1: - resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} - dependencies: - acorn: 8.8.1 - acorn-walk: 8.2.0 - dev: true - - /acorn-import-assertions/1.8.0_acorn@8.8.0: - resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==} + /acorn-import-assertions@1.9.0(acorn@8.10.0): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} peerDependencies: acorn: ^8 dependencies: - acorn: 8.8.0 + acorn: 8.10.0 dev: true - /acorn-jsx/5.3.2_acorn@8.8.1: + /acorn-jsx@5.3.2(acorn@8.10.0): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.8.1 + acorn: 8.10.0 dev: true - /acorn-walk/7.2.0: + /acorn-walk@7.2.0: resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} engines: {node: '>=0.4.0'} dev: true - /acorn-walk/8.2.0: + /acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} - dev: true - /acorn/7.4.1: + /acorn@7.4.1: resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} engines: {node: '>=0.4.0'} hasBin: true dev: true - /acorn/8.8.0: - resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==} + /acorn@8.10.0: + resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} engines: {node: '>=0.4.0'} hasBin: true dev: true - /acorn/8.8.1: - resolution: {integrity: sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==} + /acorn@8.8.2: + resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} hasBin: true - dev: true - /agent-base/6.0.2: + /agent-base@6.0.2: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true - /aggregate-error/3.1.0: + /aggregate-error@3.1.0: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} dependencies: @@ -3979,7 +5916,7 @@ packages: 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: @@ -3987,7 +5924,7 @@ packages: indent-string: 5.0.0 dev: true - /ajv-formats/2.1.1_ajv@8.11.0: + /ajv-formats@2.1.1(ajv@8.12.0): resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: ajv: ^8.0.0 @@ -3995,10 +5932,10 @@ packages: ajv: optional: true dependencies: - ajv: 8.11.0 + ajv: 8.12.0 dev: true - /ajv-keywords/3.5.2_ajv@6.12.6: + /ajv-keywords@3.5.2(ajv@6.12.6): resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} peerDependencies: ajv: ^6.9.1 @@ -4006,16 +5943,16 @@ packages: ajv: 6.12.6 dev: true - /ajv-keywords/5.1.0_ajv@8.11.0: + /ajv-keywords@5.1.0(ajv@8.12.0): resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} peerDependencies: ajv: ^8.8.2 dependencies: - ajv: 8.11.0 + 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 @@ -4024,8 +5961,8 @@ packages: uri-js: 4.4.1 dev: true - /ajv/8.11.0: - resolution: {integrity: sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==} + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} dependencies: fast-deep-equal: 3.1.3 json-schema-traverse: 1.0.0 @@ -4033,7 +5970,7 @@ packages: uri-js: 4.4.1 dev: true - /algoliasearch/4.14.2: + /algoliasearch@4.14.2: resolution: {integrity: sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg==} dependencies: '@algolia/cache-browser-local-storage': 4.14.2 @@ -4052,222 +5989,278 @@ packages: '@algolia/transporter': 4.14.2 dev: true - /amdefine/1.0.1: + /algoliasearch@4.19.1: + resolution: {integrity: sha512-IJF5b93b2MgAzcE/tuzW0yOPnuUyRgGAtaPv5UUywXM8kzqfdwZTO4sPJBzoGz1eOy6H9uEchsJsBFTELZSu+g==} + dependencies: + '@algolia/cache-browser-local-storage': 4.19.1 + '@algolia/cache-common': 4.19.1 + '@algolia/cache-in-memory': 4.19.1 + '@algolia/client-account': 4.19.1 + '@algolia/client-analytics': 4.19.1 + '@algolia/client-common': 4.19.1 + '@algolia/client-personalization': 4.19.1 + '@algolia/client-search': 4.19.1 + '@algolia/logger-common': 4.19.1 + '@algolia/logger-console': 4.19.1 + '@algolia/requester-browser-xhr': 4.19.1 + '@algolia/requester-common': 4.19.1 + '@algolia/requester-node-http': 4.19.1 + '@algolia/transporter': 4.19.1 + dev: true + + /amdefine@1.0.1: resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} engines: {node: '>=0.4.2'} + requiresBuild: true dev: true optional: true - /ansi-colors/4.1.3: + /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: 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-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'} dev: true - /ansi-regex/6.0.1: + /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} dev: true - /ansi-sequence-parser/1.1.0: + /ansi-sequence-parser@1.1.0: resolution: {integrity: sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==} 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 dev: true - /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.1.1: + /ansi-styles@6.1.1: resolution: {integrity: sha512-qDOv24WjnYuL+wbwHdlsYZFy+cgPtrYw0Tn7GLORicQp9BkQLzrgI3Pm4VyR9ERZ41YTn7KlMPuL1n05WdZvmg==} engines: {node: '>=12'} dev: true - /anymatch/3.1.2: + /antlr4@4.11.0: + resolution: {integrity: sha512-GUGlpE2JUjAN+G8G5vY+nOoeyNhHsXoIJwP1XF1oRw89vifA1K46T6SEkwLwr7drihN7I/lf0DIjKc4OZvBX8w==} + engines: {node: '>=14'} + dev: false + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + /anymatch@3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} engines: {node: '>= 8'} dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: true - /app-path/3.3.0: + /app-path@3.3.0: resolution: {integrity: sha512-EAgEXkdcxH1cgEePOSsmUtw9ItPl0KTxnh/pj9ZbhvbKbij9x0oX6PWpGnorDr0DS5AosLgoa5n3T/hZmKQpYA==} engines: {node: '>=8'} dependencies: execa: 1.0.0 dev: true - /arch/2.2.0: + /appdata-path@1.0.0: + resolution: {integrity: sha512-ZbH3ezXfnT/YE3NdqduIt4lBV+H0ybvA2Qx3K76gIjQvh8gROpDFdDLpx6B1QJtW7zxisCbpTlCLhKqoR8cDBw==} + dev: true + + /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: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} dev: true - /arg/4.1.3: + /archy@1.0.0: + resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} + dev: true + + /are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + dev: true + + /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - /arg/5.0.2: + /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: true - /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-flatten/1.1.1: + /array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} dev: true - /array-flatten/2.1.2: + /array-flatten@2.1.2: resolution: {integrity: sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==} dev: true - /array-ify/1.0.0: + /array-ify@1.0.0: resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} 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 - /arrify/1.0.1: + /arrify@1.0.1: resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} engines: {node: '>=0.10.0'} 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: + /assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} dev: true - /ast-types/0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - dependencies: - tslib: 2.4.0 - dev: true - - /astral-regex/2.0.0: + /astral-regex@2.0.0: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} dev: true - /async/3.2.4: + /async@3.2.4: resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} dev: true - /asynckit/0.4.0: + /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 - /aws-sign2/0.7.0: + /atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + 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.13.0 + queue-microtask: 1.2.3 + transitivePeerDependencies: + - supports-color + dev: true + + /aws-sign2@0.7.0: resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} dev: true - /aws4/1.11.0: + /aws4@1.11.0: resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==} dev: true - /axios/0.21.4_debug@4.3.2: - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - dependencies: - follow-redirects: 1.15.2_debug@4.3.2 - transitivePeerDependencies: - - debug - dev: true - - /axios/0.27.2_debug@4.3.4: + /axios@0.27.2(debug@4.3.4): resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==} dependencies: - follow-redirects: 1.15.2_debug@4.3.4 + follow-redirects: 1.15.2(debug@4.3.4) form-data: 4.0.0 transitivePeerDependencies: - debug dev: true - /babel-jest/29.3.1_@babel+core@7.12.3: - resolution: {integrity: sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==} + /babel-jest@29.5.0(@babel/core@7.12.3): + resolution: {integrity: sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.8.0 dependencies: '@babel/core': 7.12.3 - '@jest/transform': 29.3.1 + '@jest/transform': 29.5.0 '@types/babel__core': 7.1.19 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.2.0_@babel+core@7.12.3 + babel-preset-jest: 29.5.0(@babel/core@7.12.3) chalk: 4.1.2 graceful-fs: 4.2.10 slash: 3.0.0 @@ -4275,100 +6268,165 @@ packages: - supports-color dev: true - /babel-plugin-istanbul/6.1.1: + /babel-loader@9.1.2(@babel/core@7.12.3)(webpack@5.88.2): + resolution: {integrity: sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==} + engines: {node: '>= 14.15.0'} + peerDependencies: + '@babel/core': ^7.12.0 + webpack: '>=5' + dependencies: + '@babel/core': 7.12.3 + find-cache-dir: 3.3.2 + schema-utils: 4.0.0 + webpack: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) + dev: true + + /babel-plugin-istanbul@6.1.1: resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} engines: {node: '>=8'} dependencies: - '@babel/helper-plugin-utils': 7.19.0 + '@babel/helper-plugin-utils': 7.20.2 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.0 + istanbul-lib-instrument: 5.2.1 test-exclude: 6.0.0 transitivePeerDependencies: - supports-color dev: true - /babel-plugin-jest-hoist/29.2.0: - resolution: {integrity: sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==} + /babel-plugin-jest-hoist@29.5.0: + resolution: {integrity: sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/template': 7.18.10 - '@babel/types': 7.19.0 + '@babel/template': 7.20.7 + '@babel/types': 7.21.2 '@types/babel__core': 7.1.19 '@types/babel__traverse': 7.18.2 dev: true - /babel-preset-current-node-syntax/1.0.1_@babel+core@7.12.3: + /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.12.3): + resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.21.0 + '@babel/core': 7.12.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.12.3) + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.12.3): + resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.12.3) + core-js-compat: 3.28.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.12.3): + resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.12.3 + '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.12.3) + transitivePeerDependencies: + - supports-color + dev: true + + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.12.3): resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.12.3 - '@babel/plugin-syntax-async-generators': 7.8.4_@babel+core@7.12.3 - '@babel/plugin-syntax-bigint': 7.8.3_@babel+core@7.12.3 - '@babel/plugin-syntax-class-properties': 7.12.13_@babel+core@7.12.3 - '@babel/plugin-syntax-import-meta': 7.10.4_@babel+core@7.12.3 - '@babel/plugin-syntax-json-strings': 7.8.3_@babel+core@7.12.3 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4_@babel+core@7.12.3 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3_@babel+core@7.12.3 - '@babel/plugin-syntax-numeric-separator': 7.10.4_@babel+core@7.12.3 - '@babel/plugin-syntax-object-rest-spread': 7.8.3_@babel+core@7.12.3 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3_@babel+core@7.12.3 - '@babel/plugin-syntax-optional-chaining': 7.8.3_@babel+core@7.12.3 - '@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.12.3 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.12.3) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.12.3) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.12.3) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.12.3) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.12.3) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.12.3) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.12.3) dev: true - /babel-preset-jest/29.2.0_@babel+core@7.12.3: - resolution: {integrity: sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==} + /babel-preset-jest@29.5.0(@babel/core@7.12.3): + resolution: {integrity: sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.0.0 dependencies: '@babel/core': 7.12.3 - babel-plugin-jest-hoist: 29.2.0 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.12.3 + babel-plugin-jest-hoist: 29.5.0 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.12.3) 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==} - dev: true - /base64-js/1.5.1: + /base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: true - /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==} - engines: {node: '>=8'} + /big.js@6.2.1: + resolution: {integrity: sha512-bCtHMwL9LeDIozFn+oNhhFoq+yQ3BNdnsLSASUxLciOb1vgvpHsIO1dsENiGMgbb4SkP5TrzWzRiLddn8ahVOQ==} dev: true - /binary-searching/2.0.5: + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + + /binary-searching@2.0.5: resolution: {integrity: sha512-v4N2l3RxL+m4zDxyxz3Ne2aTmiPn8ZUpKFpdPtO+ItW1NcTCXA7JeHG5GMBSvoKSkQZ9ycS+EouDVxYB9ufKWA==} dev: true - /blob-util/2.0.2: + /binary@0.3.0: + resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} + dependencies: + buffers: 0.1.1 + chainsaw: 0.1.0 + dev: true + + /blob-util@2.0.2: resolution: {integrity: sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==} dev: true - /bluebird/3.7.2: + /bluebird@3.7.1: + resolution: {integrity: sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==} + dev: true + + /bluebird@3.7.2: resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} dev: true - /body-parser/1.20.1: + /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==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} dependencies: @@ -4388,11 +6446,11 @@ packages: - supports-color dev: true - /body-scroll-lock/4.0.0-beta.0: + /body-scroll-lock@4.0.0-beta.0: resolution: {integrity: sha512-a7tP5+0Mw3YlUJcGAKUqIBkYYGlYxk2fnCasq/FUph1hadxlTRjF+gAcZksxANnaMnALjxEddmSi/H3OR8ugcQ==} dev: true - /bonjour-service/1.0.14: + /bonjour-service@1.0.14: resolution: {integrity: sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ==} dependencies: array-flatten: 2.1.2 @@ -4401,107 +6459,112 @@ packages: multicast-dns: 7.2.5 dev: true - /brace-expansion/1.1.11: + /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: 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 dev: true - /braces/3.0.2: + /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} dependencies: fill-range: 7.0.1 - dev: true - /browser-process-hrtime/1.0.0: + /browser-process-hrtime@1.0.0: resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} dev: true - /browserslist/4.21.4: - resolution: {integrity: sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==} + /browserslist@4.21.5: + resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001431 + caniuse-lite: 1.0.30001457 electron-to-chromium: 1.4.284 - node-releases: 2.0.6 - update-browserslist-db: 1.0.10_browserslist@4.21.4 + node-releases: 2.0.10 + update-browserslist-db: 1.0.10(browserslist@4.21.5) dev: true - /bser/2.1.1: + /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 - /builtin-modules/3.3.0: + /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: + 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 - /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 - /c8/7.12.0: - resolution: {integrity: sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==} - engines: {node: '>=10.12.0'} - hasBin: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@istanbuljs/schema': 0.1.3 - find-up: 5.0.0 - foreground-child: 2.0.0 - istanbul-lib-coverage: 3.2.0 - istanbul-lib-report: 3.0.0 - istanbul-reports: 3.1.5 - rimraf: 3.0.2 - test-exclude: 6.0.0 - v8-to-istanbul: 9.0.1 - yargs: 16.2.0 - yargs-parser: 20.2.9 - 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.2: + /cacheable-request@7.0.2: resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} engines: {node: '>=8'} dependencies: @@ -4514,24 +6577,43 @@ packages: responselike: 2.0.1 dev: true - /cachedir/2.3.0: + /cachedir@2.3.0: resolution: {integrity: sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==} engines: {node: '>=6'} dev: true - /call-bind/1.0.2: + /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.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: function-bind: 1.1.1 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 dev: true - /callsites/3.1.0: + /call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + dev: true + + /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} dev: true - /camelcase-keys/6.2.2: + /camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + dev: false + + /camelcase-keys@6.2.2: resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} engines: {node: '>=8'} dependencies: @@ -4540,7 +6622,7 @@ packages: quick-lru: 4.0.1 dev: true - /camelcase-keys/7.0.2: + /camelcase-keys@7.0.2: resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==} engines: {node: '>=12'} dependencies: @@ -4550,29 +6632,33 @@ packages: type-fest: 1.4.0 dev: true - /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.30001431: - resolution: {integrity: sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==} + /caniuse-lite@1.0.30001457: + resolution: {integrity: sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==} dev: true - /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.3.7: + /centra@2.6.0: + resolution: {integrity: sha512-dgh+YleemrT8u85QL11Z6tYhegAs3MMxsaWAq/oXeAmYJ7VxL3SI9TZtnfaEvNDMAPolj25FXIb3S+HCI4wQaQ==} + dev: true + + /chai@4.3.7: resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==} engines: {node: '>=4'} dependencies: @@ -4585,7 +6671,13 @@ packages: type-detect: 4.0.8 dev: true - /chalk/1.1.3: + /chainsaw@0.1.0: + resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} + dependencies: + traverse: 0.3.9 + dev: true + + /chalk@1.1.3: resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} engines: {node: '>=0.10.0'} dependencies: @@ -4596,7 +6688,7 @@ packages: 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: @@ -4605,7 +6697,7 @@ packages: 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: @@ -4613,7 +6705,7 @@ packages: 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: @@ -4621,37 +6713,41 @@ packages: supports-color: 7.2.0 dev: true - /char-regex/1.0.2: + /chalk@5.2.0: + resolution: {integrity: sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /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-legacy@1.1.4: resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} dev: true - /character-entities/1.2.4: + /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==} - dev: true - /character-reference-invalid/1.1.4: + /character-reference-invalid@1.1.4: resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} dev: true - /check-error/1.0.2: + /check-error@1.0.2: resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} dev: true - /check-more-types/2.24.0: + /check-more-types@2.24.0: resolution: {integrity: sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==} engines: {node: '>= 0.8.0'} dev: true - /chokidar/3.5.3: + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} dependencies: @@ -4664,49 +6760,55 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.2 - dev: true - /chrome-trace-event/1.0.3: + /chrome-trace-event@1.0.3: resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} engines: {node: '>=6.0'} dev: true - /ci-info/3.6.2: - resolution: {integrity: sha512-lVZdhvbEudris15CLytp2u6Y0p5EKfztae9Fqa189MfNmln9F33XuH69v5fvNfiRN5/0eAUz2yJL3mo+nhaRKg==} + /ci-info@3.8.0: + resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} engines: {node: '>=8'} dev: true - /cjs-module-lexer/1.2.2: + /cjs-module-lexer@1.2.2: resolution: {integrity: sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==} dev: true - /cjson/0.3.0: + /cjson@0.3.0: resolution: {integrity: sha512-bBRQcCIHzI1IVH59fR0bwGrFmi3Btb/JNwM/n401i1DnYgWndpsUBiQRAddLflkZage20A2d25OAWZZk0vBRlA==} engines: {node: '>= 0.3.0'} dependencies: jsonlint: 1.6.0 dev: true - /clean-regexp/1.0.0: + /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: 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: @@ -4714,14 +6816,30 @@ packages: resolve-from: 5.0.0 dev: true - /cli-cursor/3.1.0: + /cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + dev: true + + /cli-color@2.0.3: + resolution: {integrity: sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==} + engines: {node: '>=0.10'} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + memoizee: 0.4.15 + timers-ext: 0.1.7 + dev: true + + /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} engines: {node: '>=8'} dependencies: restore-cursor: 3.1.0 dev: true - /cli-table3/0.6.3: + /cli-table3@0.6.3: resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} engines: {node: 10.* || >= 12.*} dependencies: @@ -4730,7 +6848,7 @@ packages: '@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: @@ -4738,7 +6856,7 @@ packages: string-width: 4.2.3 dev: true - /cli-truncate/3.1.0: + /cli-truncate@3.1.0: resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: @@ -4746,15 +6864,24 @@ packages: string-width: 5.1.2 dev: true - /cliui/7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + /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: + 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: @@ -4763,82 +6890,97 @@ packages: 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: + /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.1: + /collect-v8-coverage@1.0.1: resolution: {integrity: sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==} 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 dev: true - /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==} - dev: true - /colorette/2.0.19: + /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.19: resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} dev: true - /colors/0.5.1: + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + + /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/2.20.3: + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: true + + /commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: true - /commander/5.1.0: + /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/7.2.0: + /commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + dev: true + + /commander@7.2.0: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} - /commander/9.4.0: - resolution: {integrity: sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==} - engines: {node: ^12.20.0 || >=14} - dev: true - - /commander/9.4.1: - resolution: {integrity: sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==} - engines: {node: ^12.20.0 || >=14} - dev: true - - /comment-json/4.2.3: + /comment-json@4.2.3: resolution: {integrity: sha512-SsxdiOf064DWoZLH799Ata6u7iV658A11PlWtZATDlXPpKGJnbJZ5Z24ybixAi+LUUqJ/GKowAejtC5GFUG7Tw==} engines: {node: '>= 6'} dependencies: @@ -4849,31 +6991,35 @@ packages: repeat-string: 1.6.1 dev: true - /comment-parser/1.3.1: + /comment-parser@1.3.1: resolution: {integrity: sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==} engines: {node: '>= 12.0.0'} 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 - /compare-func/2.0.0: + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + + /compare-func@2.0.0: resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} dependencies: array-ify: 1.0.0 dot-prop: 5.3.0 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: @@ -4888,27 +7034,26 @@ packages: - supports-color dev: true - /concat-map/0.0.1: - resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} - dev: true + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - /concurrently/7.5.0: - resolution: {integrity: sha512-5E3mwiS+i2JYBzr5BpXkFxOnleZTMsG+WnE/dCG4/P+oiVXrbmrBwJ2ozn4SxwB2EZDrKR568X+puVohxz3/Mg==} - engines: {node: ^12.20.0 || ^14.13.0 || >=16.0.0} + /concurrently@8.0.1: + resolution: {integrity: sha512-Sh8bGQMEL0TAmAm2meAXMjcASHZa7V0xXQVDBLknCPa9TPtkY9yYs+0cnGGgfdkW0SV1Mlg+hVGfXcoI8d3MJA==} + engines: {node: ^14.13.0 || >=16.0.0} hasBin: true dependencies: chalk: 4.1.2 date-fns: 2.29.3 lodash: 4.17.21 - rxjs: 7.5.6 - shell-quote: 1.7.3 + rxjs: 7.8.0 + shell-quote: 1.8.1 spawn-command: 0.0.2-1 supports-color: 8.1.1 tree-kill: 1.2.2 - yargs: 17.5.1 + yargs: 17.7.2 dev: true - /configstore/5.0.1: + /configstore@5.0.1: resolution: {integrity: sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==} engines: {node: '>=8'} dependencies: @@ -4920,24 +7065,29 @@ packages: xdg-basedir: 4.0.0 dev: true - /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 - /content-disposition/0.5.4: + /consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + dev: true + + /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.4: + /content-type@1.0.4: resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==} engines: {node: '>= 0.6'} dev: true - /conventional-changelog-angular/5.0.13: + /conventional-changelog-angular@5.0.13: resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==} engines: {node: '>=10'} dependencies: @@ -4945,7 +7095,7 @@ packages: q: 1.5.1 dev: true - /conventional-changelog-conventionalcommits/5.0.0: + /conventional-changelog-conventionalcommits@5.0.0: resolution: {integrity: sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==} engines: {node: '>=10'} dependencies: @@ -4954,7 +7104,7 @@ packages: q: 1.5.1 dev: true - /conventional-commits-parser/3.2.4: + /conventional-commits-parser@3.2.4: resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==} engines: {node: '>=10'} hasBin: true @@ -4967,34 +7117,40 @@ packages: through2: 4.0.2 dev: true - /convert-source-map/1.8.0: + /convert-source-map@1.8.0: resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} dependencies: safe-buffer: 5.1.2 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: + /cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} dev: true - /cookie/0.5.0: + /cookie@0.5.0: resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} engines: {node: '>= 0.6'} dev: true - /core-util-is/1.0.2: + /core-js-compat@3.28.0: + resolution: {integrity: sha512-myzPgE7QodMg4nnd3K1TDoES/nADRStM8Gpz0D6nhkwbmwEnE0ZGJgoWsvQ722FR8D7xS0n0LV556RcEicjTyg==} + dependencies: + browserslist: 4.21.5 + dev: true + + /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: @@ -5002,19 +7158,19 @@ packages: 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 - /cose-base/2.1.0: + /cose-base@2.1.0: resolution: {integrity: sha512-HTMm07dhxq1dIPGWwpiVrIk9n+DH7KYmqWA786mLe8jDS+1ZjGtJGIIsJVKoseZXS6/FxiUWCJ2B7XzqUCuhPw==} dependencies: layout-base: 2.0.1 dev: false - /cosmiconfig-typescript-loader/4.1.0_2uclxasecupgvdn72amnhmyg7y: + /cosmiconfig-typescript-loader@4.1.0(@types/node@18.16.0)(cosmiconfig@8.0.0)(ts-node@10.9.1)(typescript@5.1.3): resolution: {integrity: sha512-HbWIuR5O+XO5Oj9SZ5bzgrD4nN+rfhrm2PMb0FVx+t+XIvC45n8F0oTNnztXtspWGw0i2IzHaUWFD5LzV1JB4A==} engines: {node: '>=12', npm: '>=6'} peerDependencies: @@ -5023,47 +7179,23 @@ packages: ts-node: '>=10' typescript: '>=3' dependencies: - '@types/node': 14.18.29 - cosmiconfig: 7.0.1 - ts-node: 10.9.1_yxpazyh7n5pql7jdaglasgwqki - typescript: 4.9.5 + '@types/node': 18.16.0 + cosmiconfig: 8.0.0 + ts-node: 10.9.1(@types/node@18.16.0)(typescript@5.1.3) + typescript: 5.1.3 dev: true - /cosmiconfig/7.0.1: - resolution: {integrity: sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==} - engines: {node: '>=10'} + /cosmiconfig@8.0.0: + resolution: {integrity: sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==} + engines: {node: '>=14'} dependencies: - '@types/parse-json': 4.0.0 import-fresh: 3.3.0 + js-yaml: 4.1.0 parse-json: 5.2.0 path-type: 4.0.0 - yaml: 1.10.2 dev: true - /cosmiconfig/7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - dependencies: - '@types/parse-json': 4.0.0 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - dev: true - - /coveralls/3.1.1: - resolution: {integrity: sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==} - engines: {node: '>=6'} - hasBin: true - dependencies: - js-yaml: 3.14.1 - lcov-parse: 1.0.0 - log-driver: 1.2.7 - minimist: 1.2.6 - request: 2.88.2 - dev: true - - /cp-file/9.1.0: + /cp-file@9.1.0: resolution: {integrity: sha512-3scnzFj/94eb7y4wyXRWwvzLFaQp87yyfTnChIjlfYrVqp5lVO3E2hIJMeQIltUT0K2ZAB3An1qXcBmwGyvuwA==} engines: {node: '>=10'} dependencies: @@ -5073,7 +7205,7 @@ packages: p-event: 4.2.0 dev: true - /cpy-cli/4.2.0: + /cpy-cli@4.2.0: resolution: {integrity: sha512-b04b+cbdr29CdpREPKw/itrfjO43Ty0Aj7wRM6M6LoE4GJxZJCk9Xp+Eu1IqztkKh3LxIBt1tDplENsa6KYprg==} engines: {node: '>=12.20'} hasBin: true @@ -5082,13 +7214,13 @@ packages: meow: 10.1.5 dev: true - /cpy/9.0.1: + /cpy@9.0.1: resolution: {integrity: sha512-D9U0DR5FjTCN3oMTcFGktanHnAG5l020yvOCR1zKILmAyPP7I/9pl6NFgRbDcmSENtbK1sQLBz1p9HIOlroiNg==} engines: {node: ^12.20.0 || ^14.17.0 || >=16.0.0} dependencies: arrify: 3.0.0 cp-file: 9.1.0 - globby: 13.1.2 + globby: 13.1.4 junk: 4.0.0 micromatch: 4.0.5 nested-error-stacks: 2.1.1 @@ -5096,11 +7228,10 @@ packages: p-map: 5.5.0 dev: true - /create-require/1.1.1: + /create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - /cross-spawn/6.0.5: + /cross-spawn@6.0.5: resolution: {integrity: sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==} engines: {node: '>=4.8'} dependencies: @@ -5111,7 +7242,7 @@ packages: 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: @@ -5120,250 +7251,198 @@ packages: which: 2.0.2 dev: true - /crypto-random-string/2.0.0: + /crypto-random-string@2.0.0: resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} engines: {node: '>=8'} dev: true - /cspell-dictionary/6.14.2: - resolution: {integrity: sha512-j2+uZRru3xFtW7VUOoJCrlXta1DBiPq44yGjN/Npc0wtR/aWA/NOdRysap3jWhBS1t43CiA5fqXyMO7d4wDqxw==} + /cspell-dictionary@6.31.1: + resolution: {integrity: sha512-7+K7aQGarqbpucky26wled7QSCJeg6VkLUWS+hLjyf0Cqc9Zew5xsLa4QjReExWUJx+a97jbiflITZNuWxgMrg==} engines: {node: '>=14'} dependencies: - '@cspell/cspell-pipe': 6.14.2 - '@cspell/cspell-types': 6.14.2 - cspell-trie-lib: 6.14.2 + '@cspell/cspell-pipe': 6.31.1 + '@cspell/cspell-types': 6.31.1 + cspell-trie-lib: 6.31.1 fast-equals: 4.0.3 - gensequence: 4.0.2 + gensequence: 5.0.2 dev: true - /cspell-dictionary/6.14.3: - resolution: {integrity: sha512-yIqJEZZj36j1CmmjAiuQOYZM6T62Ih7k35DhAU1hYVARUEEnFN/Uz72UkDj2SAmURVn2On+bAmZ5zCx0JZzf2g==} - engines: {node: '>=14'} - dependencies: - '@cspell/cspell-pipe': 6.14.3 - '@cspell/cspell-types': 6.14.3 - cspell-trie-lib: 6.14.3 - fast-equals: 4.0.3 - gensequence: 4.0.2 - dev: true - - /cspell-gitignore/6.14.3: - resolution: {integrity: sha512-CZTGxx3msF6p1Z0xgLe5LXXvve7DooSuRMBMdGn230usce1nKoxpPoPxgs+zXeCpi+FanykKnoZkdRvjolMpOA==} + /cspell-gitignore@6.31.1: + resolution: {integrity: sha512-PAcmjN6X89Z8qgjem6HYb+VmvVtKuc+fWs4sk21+jv2MiLk23Bkp+8slSaIDVR//58fxJkMx17PHyo2cDO/69A==} engines: {node: '>=14'} hasBin: true dependencies: - cspell-glob: 6.14.3 + cspell-glob: 6.31.1 find-up: 5.0.0 dev: true - /cspell-glob/6.14.2: - resolution: {integrity: sha512-a9o3lBccEcH2676RGge2YqEORovm+II++D53P6hOW/23ltDe1J509MSY6CJdYdPk/VssOExas6akJ6FbKSCBgw==} + /cspell-glob@6.31.1: + resolution: {integrity: sha512-ygEmr5hgE4QtO5+L3/ihfMKBhPipbapfS22ilksFSChKMc15Regds0z+z/1ZBoe+OFAPneQfIuBxMwQ/fB00GQ==} engines: {node: '>=14'} dependencies: micromatch: 4.0.5 dev: true - /cspell-glob/6.14.3: - resolution: {integrity: sha512-ISwCK8GqM/dnvtaxA17w1MPmMzFLOqdTz+JWIcR4at47T9qd8bNB0X0P4eqyuqgsbKkWbfnSlsYlEjRHTi4a7A==} - engines: {node: '>=14'} - dependencies: - micromatch: 4.0.5 - dev: true - - /cspell-grammar/6.14.2: - resolution: {integrity: sha512-Q9+gwp1U/qnECTqxa7WBMPn6sgBfXPIM68jXg8RgNMAuy1CE+m1eTCM9FBNFNpNKJWjaZPvANLOW5/EStN2A/A==} + /cspell-grammar@6.31.1: + resolution: {integrity: sha512-AsRVP0idcNFVSb9+p9XjMumFj3BUV67WIPWApaAzJl/dYyiIygQObRE+si0/QtFWGNw873b7hNhWZiKjqIdoaQ==} engines: {node: '>=14'} hasBin: true dependencies: - '@cspell/cspell-pipe': 6.14.2 - '@cspell/cspell-types': 6.14.2 + '@cspell/cspell-pipe': 6.31.1 + '@cspell/cspell-types': 6.31.1 dev: true - /cspell-grammar/6.14.3: - resolution: {integrity: sha512-Nz8tYUmstyKcFlXbxdw4N8NsQ2ZY/5ztNfouokk47LKaTAS0LyWlLSkZUxN016fMY2h+C+3dI+jaut2H/rtNew==} - engines: {node: '>=14'} - hasBin: true - dependencies: - '@cspell/cspell-pipe': 6.14.3 - '@cspell/cspell-types': 6.14.3 - dev: true - - /cspell-io/6.14.2: - resolution: {integrity: sha512-QyQ0BBfDvF6B37SlSsmlzRnaGqiIHt7c5NsCNKf3ZfioTWkNI/fiabvSkpNGBAkELP6BPBxjsG+TaS+swZp+Kg==} + /cspell-io@6.31.1: + resolution: {integrity: sha512-deZcpvTYY/NmLfOdOtzcm+nDvJZozKmj4TY3pPpX0HquPX0A/w42bFRT/zZNmRslFl8vvrCZZUog7SOc6ha3uA==} engines: {node: '>=14'} dependencies: - '@cspell/cspell-service-bus': 6.14.2 - node-fetch: 2.6.7 + '@cspell/cspell-service-bus': 6.31.1 + node-fetch: 2.6.9(encoding@0.1.13) transitivePeerDependencies: - encoding dev: true - /cspell-io/6.14.3: - resolution: {integrity: sha512-EbH+qopgWIzr9SZCGDsF4AWYgucN4QzYeAgyXjTbV9RnNIGKOKovMe3vN9nxjOZyPKv2TvmgU+uMXDM61iObRw==} - engines: {node: '>=14'} - dependencies: - '@cspell/cspell-service-bus': 6.14.3 - node-fetch: 2.6.7 - transitivePeerDependencies: - - encoding - dev: true - - /cspell-lib/6.14.2: - resolution: {integrity: sha512-QNsmWix0oFi1CjzFfNG1xAJVl1OC+6kiWvq0A1S8VD3LJhJVvBqSv1vudpL1oS7H2/2yxk9PUC/MajGLi5i5MQ==} + /cspell-lib@6.31.1: + resolution: {integrity: sha512-KgSiulbLExY+z2jGwkO77+aAkyugsPAw7y07j3hTQLpd+0esPCZqrmbo2ItnkvkDNd/c34PqQCr7/044/rz8gw==} engines: {node: '>=14.6'} dependencies: - '@cspell/cspell-bundled-dicts': 6.14.2 - '@cspell/cspell-pipe': 6.14.2 - '@cspell/cspell-types': 6.14.2 - '@cspell/strong-weak-map': 6.14.2 + '@cspell/cspell-bundled-dicts': 6.31.1 + '@cspell/cspell-pipe': 6.31.1 + '@cspell/cspell-types': 6.31.1 + '@cspell/strong-weak-map': 6.31.1 clear-module: 4.1.2 comment-json: 4.2.3 configstore: 5.0.1 - cosmiconfig: 7.0.1 - cspell-dictionary: 6.14.2 - cspell-glob: 6.14.2 - cspell-grammar: 6.14.2 - cspell-io: 6.14.2 - cspell-trie-lib: 6.14.2 + cosmiconfig: 8.0.0 + cspell-dictionary: 6.31.1 + cspell-glob: 6.31.1 + cspell-grammar: 6.31.1 + cspell-io: 6.31.1 + cspell-trie-lib: 6.31.1 fast-equals: 4.0.3 find-up: 5.0.0 - fs-extra: 10.1.0 - gensequence: 4.0.2 + gensequence: 5.0.2 import-fresh: 3.3.0 resolve-from: 5.0.0 resolve-global: 1.0.0 - vscode-languageserver-textdocument: 1.0.7 - vscode-uri: 3.0.6 + vscode-languageserver-textdocument: 1.0.8 + vscode-uri: 3.0.7 transitivePeerDependencies: - encoding dev: true - /cspell-lib/6.14.3: - resolution: {integrity: sha512-RJT5Tbe0UCMCtqDWRujjxq9u23sc2XylIpDP7MnpLx8wLVgFv2WPzESYNRGZqceqZYwBAPnpqS9h2ANxXSi8UQ==} - engines: {node: '>=14.6'} - dependencies: - '@cspell/cspell-bundled-dicts': 6.14.3 - '@cspell/cspell-pipe': 6.14.3 - '@cspell/cspell-types': 6.14.3 - '@cspell/strong-weak-map': 6.14.3 - clear-module: 4.1.2 - comment-json: 4.2.3 - configstore: 5.0.1 - cosmiconfig: 7.1.0 - cspell-dictionary: 6.14.3 - cspell-glob: 6.14.3 - cspell-grammar: 6.14.3 - cspell-io: 6.14.3 - cspell-trie-lib: 6.14.3 - fast-equals: 4.0.3 - find-up: 5.0.0 - fs-extra: 10.1.0 - gensequence: 4.0.2 - import-fresh: 3.3.0 - resolve-from: 5.0.0 - resolve-global: 1.0.0 - vscode-languageserver-textdocument: 1.0.7 - vscode-uri: 3.0.6 - transitivePeerDependencies: - - encoding - dev: true - - /cspell-trie-lib/6.14.2: - resolution: {integrity: sha512-+aTRwFUzBPFbJ8zlDwzB1ew/gP7L6kddoXjmqCNeFx9B5DiwN1KPFRo+uBx21JOkoavnviGU//DpyWSU9Cittw==} + /cspell-trie-lib@6.31.1: + resolution: {integrity: sha512-MtYh7s4Sbr1rKT31P2BK6KY+YfOy3dWsuusq9HnqCXmq6aZ1HyFgjH/9p9uvqGi/TboMqn1KOV8nifhXK3l3jg==} engines: {node: '>=14'} dependencies: - '@cspell/cspell-pipe': 6.14.2 - '@cspell/cspell-types': 6.14.2 - fs-extra: 10.1.0 - gensequence: 4.0.2 + '@cspell/cspell-pipe': 6.31.1 + '@cspell/cspell-types': 6.31.1 + gensequence: 5.0.2 dev: true - /cspell-trie-lib/6.14.3: - resolution: {integrity: sha512-WVa5gbD9glsZ4c60qPD5RTwojKc5ooxw/Gn+HC9CBdWv5rE1AmM1V3yVWhYx2ZMbJufboBrzmSjJB9qdmUl3oA==} - engines: {node: '>=14'} - dependencies: - '@cspell/cspell-pipe': 6.14.3 - '@cspell/cspell-types': 6.14.3 - fs-extra: 10.1.0 - gensequence: 4.0.2 - dev: true - - /cspell/6.14.3: - resolution: {integrity: sha512-DimVpUiw2iOSvO1daOTtOWjmryVZdFnPmjPhyhWZUqakOEgE2MgoBuk3cFzXqb8GsGXHQh5PqiWr1rqIkQ99qA==} + /cspell@6.31.1: + resolution: {integrity: sha512-gyCtpkOpwI/TGibbtIgMBFnAUUp2hnYdvW/9Ky4RcneHtLH0+V/jUEbZD8HbRKz0GVZ6mhKWbNRSEyP9p3Cejw==} engines: {node: '>=14'} hasBin: true dependencies: - '@cspell/cspell-pipe': 6.14.3 + '@cspell/cspell-pipe': 6.31.1 + '@cspell/dynamic-import': 6.31.1 chalk: 4.1.2 - commander: 9.4.1 - cspell-gitignore: 6.14.3 - cspell-glob: 6.14.3 - cspell-lib: 6.14.3 + commander: 10.0.1 + cspell-gitignore: 6.31.1 + cspell-glob: 6.31.1 + cspell-io: 6.31.1 + cspell-lib: 6.31.1 + fast-glob: 3.3.1 fast-json-stable-stringify: 2.1.0 file-entry-cache: 6.0.1 - fs-extra: 10.1.0 get-stdin: 8.0.0 - glob: 8.0.3 imurmurhash: 0.1.4 semver: 7.3.8 strip-ansi: 6.0.1 - vscode-uri: 3.0.6 + vscode-uri: 3.0.7 transitivePeerDependencies: - encoding dev: true - /css-tree/1.0.0-alpha.39: - resolution: {integrity: sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==} - engines: {node: '>=8.0.0'} + /css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} dependencies: - mdn-data: 2.0.6 - source-map: 0.6.1 + mdn-data: 2.0.30 + source-map-js: 1.0.2 dev: true - /cssom/0.3.8: + /cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /cssom@0.3.8: resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} dev: true - /cssom/0.5.0: + /cssom@0.5.0: resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} dev: true - /cssstyle/2.3.0: + /cssstyle@2.3.0: resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} engines: {node: '>=8'} dependencies: cssom: 0.3.8 dev: true - /csstype/2.6.21: - resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==} + /cssstyle@3.0.0: + resolution: {integrity: sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg==} + engines: {node: '>=14'} + dependencies: + rrweb-cssom: 0.6.0 dev: true - /cypress-image-snapshot/4.0.1_cypress@12.5.1+jest@29.3.1: + /csstree-validator@3.0.0: + resolution: {integrity: sha512-Y5OSq3wI0Xz6L7DCgJQtQ97U+v99SkX9r663VjpvUMJPhEr0A149OxiAGqcnokB5bt81irgnMudspBzujzqn0w==} + 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.1 + dev: true + + /csstype@3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + + /cuint@0.2.2: + resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} + dev: true + + /cypress-image-snapshot@4.0.1(cypress@12.10.0)(jest@29.5.0): resolution: {integrity: sha512-PBpnhX/XItlx3/DAk5ozsXQHUi72exybBNH5Mpqj1DVmjq+S5Jd9WE5CRa4q5q0zuMZb2V2VpXHth6MjFpgj9Q==} engines: {node: '>=8'} peerDependencies: cypress: ^4.5.0 dependencies: chalk: 2.4.2 - cypress: 12.5.1 + cypress: 12.10.0 fs-extra: 7.0.1 glob: 7.2.3 - jest-image-snapshot: 4.2.0_jest@29.3.1 + jest-image-snapshot: 4.2.0(jest@29.5.0) pkg-dir: 3.0.0 term-img: 4.1.0 transitivePeerDependencies: - jest dev: true - /cypress/12.5.1: - resolution: {integrity: sha512-ZmCmJ3lsyeOpBfh410m5+AO2CO1AxAzFBt7k6/uVbNcrNZje1vdiwYTpj2ksPKg9mjr9lR6V8tmlDNMvr4H/YQ==} + /cypress@12.10.0: + resolution: {integrity: sha512-Y0wPc221xKKW1/4iAFCphkrG2jNR4MjOne3iGn4mcuCaE7Y5EtXL83N8BzRsAht7GYfWVjJ/UeTqEdDKHz39HQ==} engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0} hasBin: true requiresBuild: true dependencies: '@cypress/request': 2.88.10 - '@cypress/xvfb': 1.2.4_supports-color@8.1.1 + '@cypress/xvfb': 1.2.4(supports-color@8.1.1) '@types/node': 14.18.29 '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.3 @@ -5376,25 +7455,25 @@ packages: check-more-types: 2.24.0 cli-cursor: 3.1.0 cli-table3: 0.6.3 - commander: 5.1.0 + commander: 6.2.1 common-tags: 1.8.2 - dayjs: 1.11.5 - debug: 4.3.4_supports-color@8.1.1 + dayjs: 1.11.7 + debug: 4.3.4(supports-color@8.1.1) enquirer: 2.3.6 eventemitter2: 6.4.7 execa: 4.1.0 executable: 4.1.1 - extract-zip: 2.0.1_supports-color@8.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.3.6 + listr2: 3.14.0(enquirer@2.3.6) lodash: 4.17.21 log-symbols: 4.1.0 - minimist: 1.2.6 + minimist: 1.2.8 ospath: 1.2.2 pretty-bytes: 5.6.0 proxy-from-env: 1.0.0 @@ -5406,7 +7485,7 @@ packages: yauzl: 2.10.0 dev: true - /cytoscape-cose-bilkent/4.1.0_cytoscape@3.23.0: + /cytoscape-cose-bilkent@4.1.0(cytoscape@3.23.0): resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} peerDependencies: cytoscape: ^3.2.0 @@ -5415,7 +7494,7 @@ packages: cytoscape: 3.23.0 dev: false - /cytoscape-fcose/2.1.0_cytoscape@3.23.0: + /cytoscape-fcose@2.1.0(cytoscape@3.23.0): resolution: {integrity: sha512-Q3apPl66jf8/2sMsrCjNP247nbDkyIPjA9g5iPMMWNLZgP3/mn9aryF7EFY/oRPEpv7bKJ4jYmCoU5r5/qAc1Q==} peerDependencies: cytoscape: ^3.2.0 @@ -5424,7 +7503,7 @@ packages: cytoscape: 3.23.0 dev: false - /cytoscape/3.23.0: + /cytoscape@3.23.0: resolution: {integrity: sha512-gRZqJj/1kiAVPkrVFvz/GccxsXhF3Qwpptl32gKKypO4IlqnKBjTOu+HbXtEggSGzC5KCaHp3/F7GgENrtsFkA==} engines: {node: '>=0.10'} dependencies: @@ -5432,19 +7511,25 @@ packages: lodash: 4.17.21 dev: false - /d3-array/3.2.0: + /d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + dependencies: + internmap: 1.0.1 + dev: false + + /d3-array@3.2.0: resolution: {integrity: sha512-3yXFQo0oG3QCxbF06rMPFyGRMGJNS7NvsV1+2joOjbBE+9xvWQ8+GcMJAjRCzw06zQ3/arXeJgbPYcjUCuC+3g==} 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: @@ -5452,41 +7537,41 @@ packages: 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-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.0.1 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.0: + /d3-contour@4.0.0: resolution: {integrity: sha512-7aQo0QHUTu/Ko3cP9YK9yUTxtoDEiDGwnBHyLxG5M4vqlBkO/uixMRele3nfsfj6UXOcuReVpVXzAboGraYIJw==} engines: {node: '>=12'} dependencies: d3-array: 3.2.0 dev: false - /d3-delaunay/6.0.2: + /d3-delaunay@6.0.2: resolution: {integrity: sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==} engines: {node: '>=12'} dependencies: delaunator: 5.0.0 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: @@ -5494,7 +7579,7 @@ packages: 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 @@ -5504,19 +7589,19 @@ packages: 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: @@ -5525,51 +7610,62 @@ packages: 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.0.1: + /d3-geo@3.0.1: resolution: {integrity: sha512-Wt23xBych5tSy9IYAM1FR2rWIBFWa52B/oF/GYe5zbdHrg08FU8+BuI6X4PvTwPDdqdAdq04fuWJpELtsaEjeA==} engines: {node: '>=12'} dependencies: d3-array: 3.2.0 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/3.0.1: + /d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + dev: false + + /d3-path@3.0.1: resolution: {integrity: sha512-gq6gZom9AFZby0YLduxT1qmrp4xpBA1YZr19OI717WIdKE2OM5ETq5qrHLb301IgxhLwcuxvGZVLeeWc/k1I6w==} 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-scale-chromatic/3.0.0: + /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==} engines: {node: '>=12'} dependencies: @@ -5577,7 +7673,7 @@ packages: 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: @@ -5588,38 +7684,44 @@ packages: 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/3.1.0: + /d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + dependencies: + d3-path: 1.0.9 + dev: false + + /d3-shape@3.1.0: resolution: {integrity: sha512-tGDh1Muf8kWjEDT/LswZJ8WF85yDZLvVJpYU9Nq+8+yW1Z5enxrmXOhTArlkaElU+CTn0OTVNli+/i+HP45QEQ==} engines: {node: '>=12'} dependencies: d3-path: 3.0.1 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.0.0 dev: false - /d3-time/3.0.0: + /d3-time@3.0.0: resolution: {integrity: sha512-zmV3lRnlaLI08y9IMRXSDshQb5Nj77smnfpnd2LrBa/2K281Jijactokeak14QacHs/kKq0AQ121nidNYlarbQ==} engines: {node: '>=12'} dependencies: d3-array: 3.2.0 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(d3-selection@3.0.0): resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} engines: {node: '>=12'} peerDependencies: @@ -5633,7 +7735,7 @@ packages: 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: @@ -5641,10 +7743,10 @@ packages: 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-transition: 3.0.1(d3-selection@3.0.0) dev: false - /d3/7.8.2: + /d3@7.8.2: resolution: {integrity: sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ==} engines: {node: '>=12'} dependencies: @@ -5676,35 +7778,42 @@ packages: d3-time: 3.0.0 d3-time-format: 4.1.0 d3-timer: 3.0.1 - d3-transition: 3.0.1_d3-selection@3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) d3-zoom: 3.0.0 dev: false - /dagre-d3-es/7.0.8: - resolution: {integrity: sha512-eykdoYQ4FwCJinEYS0gPL2f2w+BPbSLvnQSJ3Ye1vAoPjdkq6xIMKBv+UkICd3qZE26wBKIn3p+6n0QC7R1LyA==} + /d@1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: true + + /dagre-d3-es@7.0.10: + resolution: {integrity: sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==} dependencies: d3: 7.8.2 lodash-es: 4.17.21 dev: false - /dargs/7.0.0: + /dargs@7.0.0: resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} engines: {node: '>=8'} dev: true - /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/3.0.1: - resolution: {integrity: sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og==} - engines: {node: '>= 6'} + /data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} dev: true - /data-urls/3.0.2: + /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} dependencies: @@ -5713,16 +7822,28 @@ packages: whatwg-url: 11.0.0 dev: true - /date-fns/2.29.3: + /data-urls@4.0.0: + resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} + engines: {node: '>=14'} + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 12.0.1 + dev: true + + /date-fns@2.29.3: resolution: {integrity: sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==} engines: {node: '>=0.11'} dev: true - /dayjs/1.11.5: - resolution: {integrity: sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==} + /dayjs@1.10.7: + resolution: {integrity: sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==} dev: true - /debug/2.6.9: + /dayjs@1.11.7: + resolution: {integrity: sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==} + + /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: supports-color: '*' @@ -5733,7 +7854,7 @@ packages: ms: 2.0.0 dev: true - /debug/3.2.7_supports-color@8.1.1: + /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: supports-color: '*' @@ -5745,8 +7866,8 @@ packages: supports-color: 8.1.1 dev: true - /debug/4.3.2: - resolution: {integrity: sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==} + /debug@4.3.3: + resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -5757,19 +7878,7 @@ packages: ms: 2.1.2 dev: true - /debug/4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - 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(supports-color@8.1.1): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} peerDependencies: @@ -5780,9 +7889,8 @@ packages: dependencies: ms: 2.1.2 supports-color: 8.1.1 - dev: true - /decamelize-keys/1.1.0: + /decamelize-keys@1.1.0: resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} engines: {node: '>=0.10.0'} dependencies: @@ -5790,165 +7898,178 @@ packages: map-obj: 1.0.1 dev: true - /decamelize/1.2.0: + /decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} dev: true - /decamelize/5.0.1: + /decamelize@5.0.1: resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} engines: {node: '>=10'} dev: true - /decimal.js/10.4.1: - resolution: {integrity: sha512-F29o+vci4DodHYT9UrR5IEbfBw9pE5eSapIJdTqXK5+6hq+t8VRxwQyKlW2i+KDKFkkJQRvFyI/QXD83h8LyQw==} - 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 - dev: true - /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/0.7.0: + /dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} dev: true - /deep-eql/4.1.3: + /deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} dependencies: type-detect: 4.0.8 dev: true - /deep-is/0.1.4: + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true - /deepmerge/4.2.2: + /deepmerge@4.2.2: resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} 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 - /defer-to-connect/2.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: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} dev: true - /define-lazy-prop/2.0.0: + /define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} dev: true - /degenerator/3.0.2: - resolution: {integrity: sha512-c0mef3SNQo56t6urUU6tdQAs+ThoD0o9B9MJ8HEt7NQcGEILCRFqQb7ZbP9JAv+QF1Ky5plydhMR/IrqWDm+TQ==} - engines: {node: '>= 6'} + /define-properties@1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} dependencies: - ast-types: 0.13.4 - escodegen: 1.14.3 - esprima: 4.0.1 - vm2: 3.9.11 + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 dev: true - /delaunator/5.0.0: + /defu@6.1.2: + resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==} + dev: true + + /delaunator@5.0.0: resolution: {integrity: sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==} dependencies: robust-predicates: 3.0.1 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: + /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + + /destr@2.0.0: + resolution: {integrity: sha512-FJ9RDpf3GicEBvzI3jxc2XhHzbqD8p4ANw/1kPsFBfTvP1b7Gn/Lg1vO7R9J4IVgoMbyUmFrFGZafJ1hPZpvlg==} 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-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 - /diff-sequences/29.3.1: - resolution: {integrity: sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==} + /didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + dev: false + + /diff-sequences@29.4.3: + resolution: {integrity: sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true - /diff/4.0.2: + /diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dev: true - /diff/5.1.0: + /diff@5.1.0: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} engines: {node: '>=0.3.1'} - 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 - /dns-equal/1.0.0: + /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.4.0: + /dns-packet@5.4.0: resolution: {integrity: sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==} engines: {node: '>=6'} dependencies: '@leichtgewicht/ip-codec': 2.0.4 dev: true - /doctrine/3.0.0: + /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 @@ -5956,29 +8077,33 @@ packages: entities: 4.4.0 dev: true - /domelementtype/2.3.0: + /dom-to-image-more@2.16.0: + resolution: {integrity: sha512-RyjtkaM/zVy90uJ20lT+/G7MwBZx6l/ePliq5CQOeAnPeew7aUGS6IqRWBkHpstU+POmhaKA8A9H9qf476gisQ==} + dev: false + + /domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} dev: true - /domexception/4.0.0: + /domexception@4.0.0: resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} engines: {node: '>=12'} dependencies: webidl-conversions: 7.0.0 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/2.4.3: - resolution: {integrity: sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==} + /dompurify@3.0.5: + resolution: {integrity: sha512-F9e6wPGtY+8KNMRAVfxeCOHU0/NPWMSENNq4pQctuXRqqdEPW7q3CrLbR5Nse044WwacyjHGOMlvNsBe1y6z9A==} dev: false - /domutils/3.0.1: + /domutils@3.0.1: resolution: {integrity: sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==} dependencies: dom-serializer: 2.0.0 @@ -5986,212 +8111,348 @@ packages: domhandler: 5.0.3 dev: true - /dot-prop/5.3.0: + /dot-prop@5.3.0: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} dependencies: is-obj: 2.0.0 dev: true - /duplexer/0.1.2: + /dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + dev: true + + /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==} dev: true - /ebnf-parser/0.1.10: + /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 - /electron-to-chromium/1.4.284: + /ejs@3.1.8: + resolution: {integrity: sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + jake: 10.8.5 + dev: true + + /electron-to-chromium@1.4.284: resolution: {integrity: sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==} dev: true - /elkjs/0.8.2: + /elkjs@0.8.2: resolution: {integrity: sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==} dev: false - /emittery/0.13.1: + /emittery@0.13.1: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} dev: true - /emoji-regex/8.0.0: + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true - /emoji-regex/9.2.2: + /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} dev: true - /encodeurl/1.0.2: + /encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} dev: true - /end-of-stream/1.4.4: + /encoding@0.1.13: + resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} + dependencies: + iconv-lite: 0.6.3 + dev: true + + /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.10.0: - resolution: {integrity: sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==} + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} engines: {node: '>=10.13.0'} dependencies: graceful-fs: 4.2.10 tapable: 2.2.1 dev: true - /enquirer/2.3.6: + /enquirer@2.3.6: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} dependencies: ansi-colors: 4.1.3 dev: true - /entities/3.0.1: + /entities@3.0.1: resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} engines: {node: '>=0.12'} dev: true - /entities/4.4.0: + /entities@4.4.0: resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==} engines: {node: '>=0.12'} dev: true - /envinfo/7.8.1: + /envinfo@7.8.1: resolution: {integrity: sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==} engines: {node: '>=4'} hasBin: true dev: true - /error-ex/1.3.2: + /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: is-arrayish: 0.2.1 dev: true - /es-module-lexer/0.9.3: - resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + /es-abstract@1.21.1: + resolution: {integrity: sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + es-set-tostringtag: 2.0.1 + es-to-primitive: 1.2.1 + function-bind: 1.1.1 + function.prototype.name: 1.1.5 + get-intrinsic: 1.2.0 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has: 1.0.3 + has-property-descriptors: 1.0.0 + has-proto: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + is-array-buffer: 3.0.1 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.10 + is-weakref: 1.0.2 + object-inspect: 1.12.3 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.4.3 + safe-regex-test: 1.0.0 + string.prototype.trimend: 1.0.6 + string.prototype.trimstart: 1.0.6 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.9 dev: true - /esbuild/0.16.17: - resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==} + /es-module-lexer@1.3.0: + resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==} + dev: true + + /es-set-tostringtag@2.0.1: + resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.0 + has: 1.0.3 + has-tostringtag: 1.0.0 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + 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: + resolution: {integrity: sha512-MYoh9p+JTkgnzBh0MEBON6xUyzdmwT6wzsmmFJvZujGSXiI2kM+3XvFl6+AcIO2eeL6VWgtX9szSiDTMwDxyYA==} + engines: {node: '>= 4.0.0'} + dev: true + + /es5-ext@0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: true + + /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.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: true + + /es6-symbol@3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: true + + /es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + dev: true + + /esbuild@0.17.18: + resolution: {integrity: sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.16.17 - '@esbuild/android-arm64': 0.16.17 - '@esbuild/android-x64': 0.16.17 - '@esbuild/darwin-arm64': 0.16.17 - '@esbuild/darwin-x64': 0.16.17 - '@esbuild/freebsd-arm64': 0.16.17 - '@esbuild/freebsd-x64': 0.16.17 - '@esbuild/linux-arm': 0.16.17 - '@esbuild/linux-arm64': 0.16.17 - '@esbuild/linux-ia32': 0.16.17 - '@esbuild/linux-loong64': 0.16.17 - '@esbuild/linux-mips64el': 0.16.17 - '@esbuild/linux-ppc64': 0.16.17 - '@esbuild/linux-riscv64': 0.16.17 - '@esbuild/linux-s390x': 0.16.17 - '@esbuild/linux-x64': 0.16.17 - '@esbuild/netbsd-x64': 0.16.17 - '@esbuild/openbsd-x64': 0.16.17 - '@esbuild/sunos-x64': 0.16.17 - '@esbuild/win32-arm64': 0.16.17 - '@esbuild/win32-ia32': 0.16.17 - '@esbuild/win32-x64': 0.16.17 + '@esbuild/android-arm': 0.17.18 + '@esbuild/android-arm64': 0.17.18 + '@esbuild/android-x64': 0.17.18 + '@esbuild/darwin-arm64': 0.17.18 + '@esbuild/darwin-x64': 0.17.18 + '@esbuild/freebsd-arm64': 0.17.18 + '@esbuild/freebsd-x64': 0.17.18 + '@esbuild/linux-arm': 0.17.18 + '@esbuild/linux-arm64': 0.17.18 + '@esbuild/linux-ia32': 0.17.18 + '@esbuild/linux-loong64': 0.17.18 + '@esbuild/linux-mips64el': 0.17.18 + '@esbuild/linux-ppc64': 0.17.18 + '@esbuild/linux-riscv64': 0.17.18 + '@esbuild/linux-s390x': 0.17.18 + '@esbuild/linux-x64': 0.17.18 + '@esbuild/netbsd-x64': 0.17.18 + '@esbuild/openbsd-x64': 0.17.18 + '@esbuild/sunos-x64': 0.17.18 + '@esbuild/win32-arm64': 0.17.18 + '@esbuild/win32-ia32': 0.17.18 + '@esbuild/win32-x64': 0.17.18 dev: true - /esbuild/0.17.0: - resolution: {integrity: sha512-4yGk3rD95iS/wGzrx0Ji5czZcx1j2wvfF1iAJaX2FIYLB6sU6wYkDeplpZHzfwQw2yXGXsAoxmO6LnMQkl04Kg==} + /esbuild@0.18.11: + resolution: {integrity: sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: - '@esbuild/android-arm': 0.17.0 - '@esbuild/android-arm64': 0.17.0 - '@esbuild/android-x64': 0.17.0 - '@esbuild/darwin-arm64': 0.17.0 - '@esbuild/darwin-x64': 0.17.0 - '@esbuild/freebsd-arm64': 0.17.0 - '@esbuild/freebsd-x64': 0.17.0 - '@esbuild/linux-arm': 0.17.0 - '@esbuild/linux-arm64': 0.17.0 - '@esbuild/linux-ia32': 0.17.0 - '@esbuild/linux-loong64': 0.17.0 - '@esbuild/linux-mips64el': 0.17.0 - '@esbuild/linux-ppc64': 0.17.0 - '@esbuild/linux-riscv64': 0.17.0 - '@esbuild/linux-s390x': 0.17.0 - '@esbuild/linux-x64': 0.17.0 - '@esbuild/netbsd-x64': 0.17.0 - '@esbuild/openbsd-x64': 0.17.0 - '@esbuild/sunos-x64': 0.17.0 - '@esbuild/win32-arm64': 0.17.0 - '@esbuild/win32-ia32': 0.17.0 - '@esbuild/win32-x64': 0.17.0 + '@esbuild/android-arm': 0.18.11 + '@esbuild/android-arm64': 0.18.11 + '@esbuild/android-x64': 0.18.11 + '@esbuild/darwin-arm64': 0.18.11 + '@esbuild/darwin-x64': 0.18.11 + '@esbuild/freebsd-arm64': 0.18.11 + '@esbuild/freebsd-x64': 0.18.11 + '@esbuild/linux-arm': 0.18.11 + '@esbuild/linux-arm64': 0.18.11 + '@esbuild/linux-ia32': 0.18.11 + '@esbuild/linux-loong64': 0.18.11 + '@esbuild/linux-mips64el': 0.18.11 + '@esbuild/linux-ppc64': 0.18.11 + '@esbuild/linux-riscv64': 0.18.11 + '@esbuild/linux-s390x': 0.18.11 + '@esbuild/linux-x64': 0.18.11 + '@esbuild/netbsd-x64': 0.18.11 + '@esbuild/openbsd-x64': 0.18.11 + '@esbuild/sunos-x64': 0.18.11 + '@esbuild/win32-arm64': 0.18.11 + '@esbuild/win32-ia32': 0.18.11 + '@esbuild/win32-x64': 0.18.11 dev: true - /escalade/3.1.1: + /esbuild@0.19.0: + resolution: {integrity: sha512-i7i8TP4vuG55bKeLyqqk5sTPu1ZjPH3wkcLvAj/0X/222iWFo3AJUYRKjbOoY6BWFMH3teizxHEdV9Su5ESl0w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.19.0 + '@esbuild/android-arm64': 0.19.0 + '@esbuild/android-x64': 0.19.0 + '@esbuild/darwin-arm64': 0.19.0 + '@esbuild/darwin-x64': 0.19.0 + '@esbuild/freebsd-arm64': 0.19.0 + '@esbuild/freebsd-x64': 0.19.0 + '@esbuild/linux-arm': 0.19.0 + '@esbuild/linux-arm64': 0.19.0 + '@esbuild/linux-ia32': 0.19.0 + '@esbuild/linux-loong64': 0.19.0 + '@esbuild/linux-mips64el': 0.19.0 + '@esbuild/linux-ppc64': 0.19.0 + '@esbuild/linux-riscv64': 0.19.0 + '@esbuild/linux-s390x': 0.19.0 + '@esbuild/linux-x64': 0.19.0 + '@esbuild/netbsd-x64': 0.19.0 + '@esbuild/openbsd-x64': 0.19.0 + '@esbuild/sunos-x64': 0.19.0 + '@esbuild/win32-arm64': 0.19.0 + '@esbuild/win32-ia32': 0.19.0 + '@esbuild/win32-x64': 0.19.0 + dev: true + + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 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.14.3: - resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} - engines: {node: '>=4.0'} - hasBin: true - dependencies: - esprima: 4.0.1 - estraverse: 4.3.0 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.6.1 - dev: true - - /escodegen/1.3.3: + /escodegen@1.3.3: resolution: {integrity: sha512-z9FWgKc48wjMlpzF5ymKS1AF8OIgnKLp9VyN7KbdtyrP/9lndwUFqCtMm+TAJmJf7KJFFYc4cFJfVTTGkKEwsA==} engines: {node: '>=0.10.0'} hasBin: true @@ -6203,7 +8464,7 @@ packages: source-map: 0.1.43 dev: true - /escodegen/2.0.0: + /escodegen@2.0.0: resolution: {integrity: sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==} engines: {node: '>=6.0'} hasBin: true @@ -6216,32 +8477,32 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-prettier/8.6.0_eslint@8.32.0: - resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} + /eslint-config-prettier@8.8.0(eslint@8.39.0): + resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true peerDependencies: eslint: '>=7.0.0' dependencies: - eslint: 8.32.0 + eslint: 8.39.0 dev: true - /eslint-plugin-cypress/2.12.1_eslint@8.32.0: - resolution: {integrity: sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==} + /eslint-plugin-cypress@2.13.2(eslint@8.39.0): + resolution: {integrity: sha512-LlwjnBTzuKuC0A4H0RxVjs0YeAWK+CD1iM9Dp8un3lzT713ePQxfpPstCD+9HSAss8emuE3b2hCNUST+NrUwKw==} peerDependencies: eslint: '>= 3.2.1' dependencies: - eslint: 8.32.0 + eslint: 8.39.0 globals: 11.12.0 dev: true - /eslint-plugin-html/7.1.0: + /eslint-plugin-html@7.1.0: resolution: {integrity: sha512-fNLRraV/e6j8e3XYOC9xgND4j+U7b1Rq+OygMlLcMg+wI/IpVbF+ubQa3R78EjKB9njT6TQOlcK5rFKBVVtdfg==} dependencies: htmlparser2: 8.0.1 dev: true - /eslint-plugin-jest/27.1.5_i5clxtuiaceouxhg5syqkw5wwi: - resolution: {integrity: sha512-CK2dekZ5VBdzsOSOH5Fc1rwC+cWXjkcyrmf1RV714nDUDKu+o73TTJiDxpbILG8PtPPpAAl3ywzh5QA7Ft0mjA==} + /eslint-plugin-jest@27.2.1(@typescript-eslint/eslint-plugin@5.59.0)(eslint@8.39.0)(jest@29.5.0)(typescript@5.1.3): + resolution: {integrity: sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': ^5.0.0 @@ -6253,34 +8514,35 @@ packages: jest: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 5.48.2_azmbqzqvrlvblbdtiwxwvyvjjy - '@typescript-eslint/utils': 5.42.1_et5x32uxl7z5ldub3ye5rhlyqm - eslint: 8.32.0 - jest: 29.3.1_odkjkoia5xunhxkdrka32ib6vi + '@typescript-eslint/eslint-plugin': 5.59.0(@typescript-eslint/parser@5.59.0)(eslint@8.39.0)(typescript@5.1.3) + '@typescript-eslint/utils': 5.59.0(eslint@8.39.0)(typescript@5.1.3) + eslint: 8.39.0 + jest: 29.5.0(@types/node@18.16.0)(ts-node@10.9.1) transitivePeerDependencies: - supports-color - typescript dev: true - /eslint-plugin-jsdoc/39.6.2_eslint@8.32.0: - resolution: {integrity: sha512-dvgY/W7eUFoAIIiaWHERIMI61ZWqcz9YFjEeyTzdPlrZc3TY/3aZm5aB91NUoTLWYZmO/vFlYSuQi15tF7uE5A==} - engines: {node: ^14 || ^16 || ^17 || ^18 || ^19} + /eslint-plugin-jsdoc@46.0.0(eslint@8.39.0): + resolution: {integrity: sha512-xmB5WleBcPCFYlrFfdjrcfSKOJBLwyGmKa+i+fVqlIHp8g5aAoeQpBGugUzToFtQgd4hNZYlfIcP7QSxC9NYWQ==} + engines: {node: '>=16'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: - '@es-joy/jsdoccomment': 0.36.0 + '@es-joy/jsdoccomment': 0.39.4 + are-docs-informative: 0.0.2 comment-parser: 1.3.1 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) escape-string-regexp: 4.0.0 - eslint: 8.32.0 - esquery: 1.4.0 - semver: 7.3.8 + eslint: 8.39.0 + esquery: 1.5.0 + semver: 7.5.3 spdx-expression-parse: 3.0.1 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-json/3.1.0: + /eslint-plugin-json@3.1.0: resolution: {integrity: sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g==} engines: {node: '>=12.0'} dependencies: @@ -6288,66 +8550,66 @@ packages: vscode-json-languageservice: 4.2.1 dev: true - /eslint-plugin-lodash/7.4.0_eslint@8.32.0: + /eslint-plugin-lodash@7.4.0(eslint@8.39.0): resolution: {integrity: sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A==} engines: {node: '>=10'} peerDependencies: eslint: '>=2' dependencies: - eslint: 8.32.0 + eslint: 8.39.0 lodash: 4.17.21 dev: true - /eslint-plugin-markdown/3.0.0_eslint@8.32.0: + /eslint-plugin-markdown@3.0.0(eslint@8.39.0): resolution: {integrity: sha512-hRs5RUJGbeHDLfS7ELanT0e29Ocyssf/7kBM+p7KluY5AwngGkDf8Oyu4658/NZSGTTq05FZeWbkxXtbVyHPwg==} 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.32.0 + eslint: 8.39.0 mdast-util-from-markdown: 0.8.5 transitivePeerDependencies: - supports-color dev: true - /eslint-plugin-no-only-tests/3.1.0: + /eslint-plugin-no-only-tests@3.1.0: resolution: {integrity: sha512-Lf4YW/bL6Un1R6A76pRZyE1dl1vr31G/ev8UzIc/geCgFWyrKil8hVjYqWVKGB/UIGmb6Slzs9T0wNezdSVegw==} engines: {node: '>=5.0.0'} dev: true - /eslint-plugin-tsdoc/0.2.17: + /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-unicorn/45.0.0_eslint@8.32.0: - resolution: {integrity: sha512-iP8cMRxXKHonKioOhnCoCcqVhoqhAp6rB+nsoLjXFDxTHz3btWMAp8xwzjHA0B1K6YV/U/Yvqn1bUXZt8sJPuQ==} - engines: {node: '>=14.18'} + /eslint-plugin-unicorn@47.0.0(eslint@8.39.0): + resolution: {integrity: sha512-ivB3bKk7fDIeWOUmmMm9o3Ax9zbMz1Bsza/R2qm46ufw4T6VBFBaJIR1uN3pCKSmSXm8/9Nri8V+iUut1NhQGA==} + engines: {node: '>=16'} peerDependencies: - eslint: '>=8.28.0' + eslint: '>=8.38.0' dependencies: '@babel/helper-validator-identifier': 7.19.1 - ci-info: 3.6.2 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.39.0) + ci-info: 3.8.0 clean-regexp: 1.0.0 - eslint: 8.32.0 - eslint-utils: 3.0.0_eslint@8.32.0 - esquery: 1.4.0 + eslint: 8.39.0 + esquery: 1.5.0 indent-string: 4.0.0 - is-builtin-module: 3.2.0 + is-builtin-module: 3.2.1 jsesc: 3.0.2 lodash: 4.17.21 pluralize: 8.0.0 read-pkg-up: 7.0.1 regexp-tree: 0.1.24 - regjsparser: 0.9.1 + regjsparser: 0.10.0 safe-regex: 2.1.1 - semver: 7.3.8 + semver: 7.5.3 strip-indent: 3.0.0 dev: true - /eslint-scope/5.1.1: + /eslint-scope@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} dependencies: @@ -6355,54 +8617,41 @@ packages: estraverse: 4.3.0 dev: true - /eslint-scope/7.1.1: - resolution: {integrity: sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==} + /eslint-scope@7.2.0: + resolution: {integrity: sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 dev: true - /eslint-utils/3.0.0_eslint@8.32.0: - resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} - engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} - peerDependencies: - eslint: '>=5' - dependencies: - eslint: 8.32.0 - eslint-visitor-keys: 2.1.0 - dev: true - - /eslint-visitor-keys/2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys/3.3.0: - resolution: {integrity: sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==} + /eslint-visitor-keys@3.4.0: + resolution: {integrity: sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /eslint/8.32.0: - resolution: {integrity: sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==} + /eslint@8.39.0: + resolution: {integrity: sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint/eslintrc': 1.4.1 + '@eslint-community/eslint-utils': 4.4.0(eslint@8.39.0) + '@eslint-community/regexpp': 4.5.0 + '@eslint/eslintrc': 2.0.2 + '@eslint/js': 8.39.0 '@humanwhocodes/config-array': 0.11.8 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 - eslint-scope: 7.1.1 - eslint-utils: 3.0.0_eslint@8.32.0 - eslint-visitor-keys: 3.3.0 - espree: 9.4.0 - esquery: 1.4.0 + eslint-scope: 7.2.0 + eslint-visitor-keys: 3.4.0 + espree: 9.5.1 + esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 @@ -6423,7 +8672,6 @@ packages: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.1 - regexpp: 3.2.0 strip-ansi: 6.0.1 strip-json-comments: 3.1.1 text-table: 0.2.0 @@ -6431,76 +8679,92 @@ packages: - supports-color dev: true - /espree/9.4.0: - resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==} + /espree@9.5.1: + resolution: {integrity: sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.8.1 - acorn-jsx: 5.3.2_acorn@8.8.1 - eslint-visitor-keys: 3.3.0 + acorn: 8.10.0 + acorn-jsx: 5.3.2(acorn@8.10.0) + eslint-visitor-keys: 3.4.0 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.4.0: - resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} 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/2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + /estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} dev: true - /esutils/1.0.0: + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.0 + dev: true + + /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-stream/3.3.4: + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + dev: true + + /event-stream@3.3.4: resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} dependencies: duplexer: 0.1.2 @@ -6512,25 +8776,23 @@ packages: 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'} - dev: true - /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 - /events/3.3.0: + /events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - dev: true - /execa/1.0.0: + /execa@1.0.0: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} dependencies: @@ -6543,7 +8805,7 @@ packages: 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: @@ -6558,7 +8820,7 @@ packages: 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: @@ -6573,13 +8835,13 @@ packages: strip-final-newline: 2.0.0 dev: true - /execa/6.1.0: - resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + /execa@7.1.1: + resolution: {integrity: sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==} + engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} dependencies: cross-spawn: 7.0.3 get-stream: 6.0.1 - human-signals: 3.0.1 + human-signals: 4.3.1 is-stream: 3.0.0 merge-stream: 2.0.0 npm-run-path: 5.1.0 @@ -6588,30 +8850,30 @@ packages: 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.3.1: - resolution: {integrity: sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==} + /expect@29.5.0: + resolution: {integrity: sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/expect-utils': 29.3.1 - jest-get-type: 29.2.0 - jest-matcher-utils: 29.3.1 - jest-message-util: 29.3.1 - jest-util: 29.3.1 + '@jest/expect-utils': 29.5.0 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.5.0 + jest-message-util: 29.5.0 + jest-util: 29.5.0 dev: true - /express/4.18.2: + /express@4.18.2: resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} engines: {node: '>= 0.10.0'} dependencies: @@ -6650,16 +8912,22 @@ packages: - supports-color dev: true - /extend/3.0.2: + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: true + + /extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} dev: true - /extract-zip/2.0.1_supports-color@8.1.1: + /extract-zip@2.0.1(supports-color@8.1.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 + debug: 4.3.4(supports-color@8.1.1) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -6668,20 +8936,28 @@ packages: - 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-deep-equal/3.1.3: + /fast-content-type-parse@1.0.0: + resolution: {integrity: sha512-Xbc4XcysUXcsP5aHUU7Nq3OwvHq97C+WnbkeIefpeYLX+ryzFJlU6OStFJhs6Ol0LkUGpcK+wL0JwfM+FCU5IA==} + dev: true + + /fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + dev: true + + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true - /fast-equals/4.0.3: + /fast-equals@4.0.3: resolution: {integrity: sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==} dev: true - /fast-glob/3.2.12: + /fast-glob@3.2.12: resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} engines: {node: '>=8.6.0'} dependencies: @@ -6692,77 +8968,159 @@ packages: micromatch: 4.0.5 dev: true - /fast-json-stable-stringify/2.1.0: + /fast-glob@3.3.1: + resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} + 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: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true - /fast-levenshtein/2.0.6: + /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.2.2 + rfdc: 1.3.0 + string-similarity: 4.0.4 + dev: true + + /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true - /fastest-levenshtein/1.0.16: + /fast-redact@3.1.2: + resolution: {integrity: sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==} + engines: {node: '>=6'} + + /fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + dev: true + + /fastest-levenshtein@1.0.16: resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} engines: {node: '>= 4.9.1'} dev: true - /fastq/1.13.0: + /fastestsmallesttextencoderdecoder@1.0.22: + resolution: {integrity: sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==} + dev: true + + /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.0.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.0 + secure-json-parse: 2.7.0 + semver: 7.5.3 + tiny-lru: 8.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /fastq@1.13.0: resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} dependencies: reusify: 1.0.4 - dev: true - /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 - /figures/3.2.0: + /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: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.2.1 + dev: true + + /fflate@0.8.0: + resolution: {integrity: sha512-FAdS4qMuFjsJj6XHbBaZeXOgaypXp8iw/Tpyuq/w3XA41jjLHT8NPA+n7czH/DDhdncq0nAyDZmPeWXh2qmdIg==} + dev: true + + /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: + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: flat-cache: 3.0.4 dev: true - /file-uri-to-path/2.0.0: - resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==} - engines: {node: '>= 6'} + /file-saver@2.0.5: + resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} + dev: false + + /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: + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 - dev: true - /finalhandler/1.2.0: + /finalhandler@1.2.0: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} dependencies: @@ -6777,14 +9135,44 @@ packages: - supports-color dev: true - /find-up/3.0.0: + /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-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==} + 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@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: @@ -6792,7 +9180,7 @@ packages: 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: @@ -6800,7 +9188,7 @@ packages: path-exists: 4.0.0 dev: true - /flat-cache/3.0.4: + /flat-cache@3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: @@ -6808,15 +9196,25 @@ packages: rimraf: 3.0.2 dev: true - /flatted/3.2.7: + /flatstr@1.0.12: + resolution: {integrity: sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==} + dev: true + + /flatted@3.2.7: resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} dev: true - /flexsearch/0.7.31: + /flexsearch@0.7.31: resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==} dev: true - /follow-redirects/1.15.2_debug@4.3.2: + /focus-trap@7.5.2: + resolution: {integrity: sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==} + dependencies: + tabbable: 6.2.0 + dev: true + + /follow-redirects@1.15.2(debug@4.3.4): resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} engines: {node: '>=4.0'} peerDependencies: @@ -6825,22 +9223,16 @@ packages: debug: optional: true dependencies: - debug: 4.3.2 + debug: 4.3.4(supports-color@8.1.1) dev: true - /follow-redirects/1.15.2_debug@4.3.4: - resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: - debug: 4.3.4 + is-callable: 1.2.7 dev: true - /foreground-child/2.0.0: + /foreground-child@2.0.0: resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} engines: {node: '>=8.0.0'} dependencies: @@ -6848,11 +9240,19 @@ packages: signal-exit: 3.0.7 dev: true - /forever-agent/0.6.1: + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.0.1 + dev: true + + /forever-agent@0.6.1: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} dev: true - /form-data/2.3.3: + /form-data@2.3.3: resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} engines: {node: '>= 0.12'} dependencies: @@ -6861,16 +9261,7 @@ packages: mime-types: 2.1.35 dev: true - /form-data/3.0.1: - resolution: {integrity: sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /form-data/4.0.0: + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} dependencies: @@ -6879,35 +9270,55 @@ packages: 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 - /forwarded/0.2.0: + /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: 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: + /from@0.1.7: resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} dev: true - /fs-extra/10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} + /fromentries@1.3.2: + resolution: {integrity: sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==} + dev: true + + /fs-extra@11.0.0: + resolution: {integrity: sha512-4YxRvMi4P5C3WQTvdRfrv5UVqbISpqjORFQAW5QPiKAauaxNCwrEdIi6pG3tDFhKKpMen+enEhHIzB/tvIO+/w==} + engines: {node: '>=14.14'} dependencies: graceful-fs: 4.2.10 jsonfile: 6.1.0 universalify: 2.0.0 dev: true - /fs-extra/7.0.1: + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.10 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} dependencies: @@ -6916,16 +9327,7 @@ packages: universalify: 0.1.2 dev: true - /fs-extra/8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.10 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-extra/9.1.0: + /fs-extra@9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} engines: {node: '>=10'} dependencies: @@ -6935,122 +9337,123 @@ packages: universalify: 2.0.0 dev: true - /fs-monkey/1.0.3: + /fs-monkey@1.0.3: resolution: {integrity: sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==} dev: true - /fs.realpath/1.0.0: + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - /fsevents/2.3.2: + /fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: true optional: true - /ftp/0.3.10: - resolution: {integrity: sha512-faFVML1aBx2UoDStmLwv2Wptt4vw5x03xxX172nhA5Y5HBshW5JweqQ2W4xL4dezQTG8inJsuYcpPHHU3X5OTQ==} - engines: {node: '>=0.8.0'} - dependencies: - readable-stream: 1.1.14 - xregexp: 2.0.0 - dev: true - - /function-bind/1.1.1: + /function-bind@1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + /function.prototype.name@1.1.5: + resolution: {integrity: sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.1 + functions-have-names: 1.2.3 dev: true - /gensequence/4.0.2: - resolution: {integrity: sha512-mQiFskYFPFDSUpBJ/n3ebAV2Ufu6DZGvUPXzyWYzFfJr6/DyOOZVnjx6VTWE4y0RLvYWnc5tZq5sCjzEWhRjqQ==} + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensequence@5.0.2: + resolution: {integrity: sha512-JlKEZnFc6neaeSVlkzBGGgkIoIaSxMgvdamRoPN8r3ozm2r9dusqxeKqYQ7lhzmj2UhFQP8nkyfCaiLQxiLrDA==} engines: {node: '>=14'} 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-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} dev: true - /get-func-name/2.0.0: + /get-func-name@2.0.0: resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==} dev: true - /get-intrinsic/1.1.3: - resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} + /get-intrinsic@1.2.0: + resolution: {integrity: sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==} dependencies: function-bind: 1.1.1 has: 1.0.3 has-symbols: 1.0.3 dev: true - /get-package-type/0.1.0: + /get-own-enumerable-property-symbols@3.0.2: + resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + dev: true + + /get-package-type@0.1.0: resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} engines: {node: '>=8.0.0'} dev: true - /get-stdin/5.0.1: + /get-stdin@5.0.1: resolution: {integrity: sha512-jZV7n6jGE3Gt7fgSTJoz91Ak5MuTLwMwkoYdjxuJ/AmjIsE1UC03y/IWkZCQGEvVNS9qoRNwy5BCqxImv0FVeA==} engines: {node: '>=0.12.0'} dev: true - /get-stdin/8.0.0: + /get-stdin@8.0.0: resolution: {integrity: sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==} engines: {node: '>=10'} 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-uri/3.0.2: - resolution: {integrity: sha512-+5s0SJbGoyiJTZZ2JTpFPLMPSch72KEqGOTvQsBqg0RBWvwhWUSYZFAtz3TPW0GXJuLBJPts1E241iHg+VRfhg==} - engines: {node: '>= 6'} + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} dependencies: - '@tootallnate/once': 1.1.2 - data-uri-to-buffer: 3.0.1 - debug: 4.3.4 - file-uri-to-path: 2.0.0 - fs-extra: 8.1.0 - ftp: 0.3.10 - transitivePeerDependencies: - - supports-color + call-bind: 1.0.2 + get-intrinsic: 1.2.0 dev: true - /getos/3.2.1: + /getos@3.2.1: resolution: {integrity: sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==} dependencies: async: 3.2.4 dev: true - /getpass/0.1.7: + /getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} dependencies: assert-plus: 1.0.0 dev: true - /git-raw-commits/2.0.11: + /git-raw-commits@2.0.11: resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==} engines: {node: '>=10'} hasBin: true @@ -7062,25 +9465,60 @@ packages: through2: 4.0.2 dev: true - /glob-parent/5.1.2: + /github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + dev: true + + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - dev: true - /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/7.2.3: + /glob@10.2.2: + resolution: {integrity: sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.1.1 + minimatch: 9.0.1 + minipass: 5.0.0 + path-scurry: 1.7.0 + dev: true + + /glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + 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: false + + /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: fs.realpath: 1.0.0 @@ -7091,71 +9529,104 @@ packages: path-is-absolute: 1.0.1 dev: true - /glob/8.0.3: + /glob@8.0.3: resolution: {integrity: sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==} engines: {node: '>=12'} dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 5.1.0 + minimatch: 5.1.6 once: 1.4.0 dev: true - /global-dirs/0.1.1: + /global-dirs@0.1.1: resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} engines: {node: '>=4'} dependencies: ini: 1.3.8 dev: true - /global-dirs/3.0.0: + /global-dirs@3.0.0: resolution: {integrity: sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==} 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.19.0: + /globals@13.19.0: resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 dev: true - /globby/11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.0 + dev: true + + /globalyzer@0.1.0: + resolution: {integrity: sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==} + dev: true + + /globby@11.0.4: + resolution: {integrity: sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==} engines: {node: '>=10'} dependencies: array-union: 2.1.0 dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.1 ignore: 5.2.0 merge2: 1.4.1 slash: 3.0.0 dev: true - /globby/13.1.2: - resolution: {integrity: sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==} + /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.1 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globby@13.1.4: + resolution: {integrity: sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: dir-glob: 3.0.1 - fast-glob: 3.2.12 + fast-glob: 3.3.1 ignore: 5.2.0 merge2: 1.4.1 slash: 4.0.0 dev: true - /glur/1.1.2: + /globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + + /glur@1.1.2: resolution: {integrity: sha512-l+8esYHTKOx2G/Aao4lEQ0bnHWg4fWtJbVoZZT9Knxi01pB8C80BR85nONLFwkkQoFRCmXY+BUcGZN3yZ2QsRA==} dev: true - /got/11.8.5: + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.0 + dev: true + + /got@11.8.5: resolution: {integrity: sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==} engines: {node: '>=10.19.0'} dependencies: @@ -7172,24 +9643,31 @@ packages: responselike: 2.0.1 dev: true - /graceful-fs/4.2.10: + /graceful-fs@4.2.10: resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} dev: true - /grapheme-splitter/1.0.4: + /grapheme-splitter@1.0.4: resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} dev: true - /handle-thing/2.0.1: + /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: resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} dev: true - /handlebars/4.7.7: + /handlebars@4.7.7: resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} engines: {node: '>=0.4.7'} hasBin: true dependencies: - minimist: 1.2.6 + minimist: 1.2.8 neo-async: 2.6.2 source-map: 0.6.1 wordwrap: 1.0.0 @@ -7197,75 +9675,93 @@ packages: uglify-js: 3.17.3 dev: true - /har-schema/2.0.0: - resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} - engines: {node: '>=4'} - dev: true - - /har-validator/5.1.5: - resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} - engines: {node: '>=6'} - deprecated: this library is no longer supported - dependencies: - ajv: 6.12.6 - har-schema: 2.0.0 - dev: true - - /hard-rejection/2.1.0: + /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} 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-flag/3.0.0: + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /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'} - dev: true - /has-own-prop/2.0.0: + /has-own-prop@2.0.0: resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} engines: {node: '>=8'} dev: true - /has-symbols/1.0.3: + /has-property-descriptors@1.0.0: + resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + dependencies: + get-intrinsic: 1.2.0 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} dev: true - /has/1.0.3: + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + 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 + + /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 - /heap/0.2.7: + /heap@0.2.7: resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} dev: false - /hosted-git-info/2.8.9: + /highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + dev: false + + /hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} dev: true - /hosted-git-info/4.1.0: + /hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} dependencies: lru-cache: 6.0.0 dev: true - /hpack.js/2.1.6: + /hpack.js@2.1.6: resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} dependencies: inherits: 2.0.4 @@ -7274,22 +9770,26 @@ packages: wbuf: 1.7.3 dev: true - /html-encoding-sniffer/3.0.0: + /html-encoding-sniffer@3.0.0: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} dependencies: whatwg-encoding: 2.0.0 dev: true - /html-entities/2.3.3: + /html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} dev: true - /html-escaper/2.0.2: + /html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true - /htmlparser2/8.0.1: + /html-to-image@1.11.11: + resolution: {integrity: sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA==} + dev: false + + /htmlparser2@8.0.1: resolution: {integrity: sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==} dependencies: domelementtype: 2.3.0 @@ -7298,15 +9798,15 @@ packages: entities: 4.4.0 dev: true - /http-cache-semantics/4.1.0: + /http-cache-semantics@4.1.0: resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} 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: @@ -7316,7 +9816,7 @@ packages: 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: @@ -7327,33 +9827,22 @@ packages: 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/4.0.1: - resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} - engines: {node: '>= 6'} - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - 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 + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true - /http-proxy-middleware/2.0.6_@types+express@4.17.14: + /http-proxy-middleware@2.0.6(@types/express@4.17.14): resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -7372,27 +9861,18 @@ packages: - 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.2_debug@4.3.2 + follow-redirects: 1.15.2(debug@4.3.4) requires-port: 1.0.0 transitivePeerDependencies: - debug dev: true - /http-signature/1.2.0: - resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} - engines: {node: '>=0.8', npm: '>=1.3.7'} - dependencies: - assert-plus: 1.0.0 - jsprim: 1.4.2 - sshpk: 1.17.0 - dev: true - - /http-signature/1.3.6: + /http-signature@1.3.6: resolution: {integrity: sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==} engines: {node: '>=0.10'} dependencies: @@ -7401,7 +9881,7 @@ packages: sshpk: 1.17.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: @@ -7409,60 +9889,77 @@ packages: resolve-alpn: 1.2.1 dev: true - /https-proxy-agent/5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} + /https-localhost@4.7.1: + resolution: {integrity: sha512-rl+NFV0l67/0W7fZwk4LB5gS6HdhtSFLpCpf1N+KD5WQAXtPXX1QE8H0cP8VNJii18rtpTkE9eAHdUfJ0goAnQ==} + hasBin: true dependencies: - agent-base: 6.0.2 - debug: 4.3.4 + 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.3 transitivePeerDependencies: - supports-color dev: true - /human-signals/1.1.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 + + /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/3.0.1: - resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==} - engines: {node: '>=12.20.0'} + /human-signals@4.3.1: + resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} + engines: {node: '>=14.18.0'} dev: true - /husky/8.0.2: - resolution: {integrity: sha512-Tkv80jtvbnkK3mYWxPZePGFpQ/tT3HNSs/sasF9P2YfkMezDl3ON37YN6jUUI4eTg5LcyVynlb6r4eyvOmspvg==} + /husky@8.0.3: + resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} engines: {node: '>=14'} 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 - /ieee754/1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + /idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} dev: true - /ignore/5.2.0: + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + /ignore@5.2.0: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} dev: true - /import-fresh/3.3.0: + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} dependencies: @@ -7470,7 +9967,7 @@ packages: resolve-from: 4.0.0 dev: true - /import-local/3.1.0: + /import-local@3.1.0: resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} engines: {node: '>=8'} hasBin: true @@ -7479,162 +9976,214 @@ packages: resolve-cwd: 3.0.0 dev: true - /imurmurhash/0.1.4: + /import-meta-resolve@2.2.2: + resolution: {integrity: sha512-f8KcQ1D80V7RnqVm+/lirO9zkOxjGxhaTC1IPrBGd3MEfNgmNG67tSUO9gTi2F3Blr2Az6g1vocaxzkVnWl9MA==} + dev: true + + /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: + /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true - /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/1.3.8: + /ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true - /ini/2.0.0: + /ini@2.0.0: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} dev: true - /internmap/2.0.3: + /ini@3.0.1: + resolution: {integrity: sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dev: true + + /internal-slot@1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.0 + has: 1.0.3 + side-channel: 1.0.4 + dev: true + + /internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + dev: false + + /internmap@2.0.3: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} dev: false - /interpret/2.2.0: + /interpret@2.2.0: resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} engines: {node: '>= 0.10'} dev: true - /ip/1.1.8: - resolution: {integrity: sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==} - dev: true - - /ip/2.0.0: - resolution: {integrity: sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==} - 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.0.1: + /ipaddr.js@2.0.1: resolution: {integrity: sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==} 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-arrayish/0.2.1: + /is-array-buffer@3.0.1: + resolution: {integrity: sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.0 + is-typed-array: 1.1.10 + dev: true + + /is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} dev: true - /is-binary-path/2.1.0: + /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-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==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 dev: true - /is-buffer/2.0.5: + /is-buffer@2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} dev: true - /is-builtin-module/3.2.0: - resolution: {integrity: sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw==} + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} dependencies: builtin-modules: 3.3.0 dev: true - /is-ci/3.0.1: + /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.6.2 + ci-info: 3.8.0 dev: true - /is-core-module/2.10.0: + /is-core-module@2.10.0: resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} dependencies: has: 1.0.3 dev: true - /is-decimal/1.0.4: + /is-core-module@2.12.1: + resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} + dependencies: + has: 1.0.3 + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /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'} - dev: true - /is-fullwidth-code-point/3.0.0: + /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} dev: true - /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-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-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 - dev: true - /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: @@ -7642,117 +10191,208 @@ packages: is-path-inside: 3.0.3 dev: true - /is-number/7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + /is-localhost-ip@2.0.0: + resolution: {integrity: sha512-vlgs2cSgMOfnKU8c1ewgKPyum9rVrjjLLW2HBdL5i0iAJjOs8NY55ZBd/hqUTaYR0EO9CKZd3hVSC2HlIbygTQ==} + engines: {node: '>=12'} dev: true - /is-obj/2.0.0: + /is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + 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.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + /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/1.1.0: + /is-plain-obj@1.1.0: resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} engines: {node: '>=0.10.0'} 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-stream/1.1.0: + /is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + has-tostringtag: 1.0.0 + dev: true + + /is-regexp@1.0.0: + resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} + engines: {node: '>=0.10.0'} + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.2 + dev: true + + /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-text-path/1.0.1: + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-text-path@1.0.1: resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} engines: {node: '>=0.10.0'} dependencies: text-extensions: 1.9.0 dev: true - /is-typedarray/1.0.0: + /is-typed-array@1.1.10: + resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /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-wsl/2.2.0: + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.2 + dev: true + + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: true + + /is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} dependencies: is-docker: 2.2.1 dev: true - /isarray/0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - dev: true - - /isarray/1.0.0: + /isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} dev: true - /isexe/2.0.0: + /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true - /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: + /istanbul-lib-coverage@3.0.0: + resolution: {integrity: sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} dev: true - /istanbul-lib-instrument/5.2.0: - resolution: {integrity: sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==} + /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: + resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} engines: {node: '>=8'} dependencies: '@babel/core': 7.12.3 - '@babel/parser': 7.19.1 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.0 @@ -7760,7 +10400,45 @@ packages: - supports-color dev: true - /istanbul-lib-report/3.0.0: + /istanbul-lib-instrument@5.2.0: + resolution: {integrity: sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.12.3 + '@babel/parser': 7.21.8 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.12.3 + '@babel/parser': 7.21.8 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.0 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + + /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.0: resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} engines: {node: '>=8'} dependencies: @@ -7769,18 +10447,27 @@ packages: supports-color: 7.2.0 dev: true - /istanbul-lib-source-maps/4.0.1: + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.0 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.3.4 + 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-reports/3.1.5: + /istanbul-reports@3.1.5: resolution: {integrity: sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==} engines: {node: '>=8'} dependencies: @@ -7788,7 +10475,7 @@ packages: istanbul-lib-report: 3.0.0 dev: true - /iterm2-version/4.2.0: + /iterm2-version@4.2.0: resolution: {integrity: sha512-IoiNVk4SMPu6uTcK+1nA5QaHNok2BMDLjSl5UomrOixe5g4GkylhPwuiGdw00ysSCrXAKNMfFTu+u/Lk5f6OLQ==} engines: {node: '>=8'} dependencies: @@ -7796,43 +10483,64 @@ packages: plist: 3.0.6 dev: true - /jest-changed-files/29.2.0: - resolution: {integrity: sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==} + /jackspeak@2.1.1: + resolution: {integrity: sha512-juf9stUEwUaILepraGOWIJTLwg48bUnBmRqd2ln2Os1sW987zeoj/hzhbvRB95oMuS2ZTpjULmdwHNX4rzZIZw==} + engines: {node: '>=14'} + dependencies: + cliui: 8.0.1 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /jake@10.8.5: + resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.4 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + dev: true + + /jest-changed-files@29.5.0: + resolution: {integrity: sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: execa: 5.1.1 p-limit: 3.1.0 dev: true - /jest-circus/29.3.1: - resolution: {integrity: sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==} + /jest-circus@29.5.0: + resolution: {integrity: sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.3.1 - '@jest/expect': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@jest/environment': 29.5.0 + '@jest/expect': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 is-generator-fn: 2.1.0 - jest-each: 29.3.1 - jest-matcher-utils: 29.3.1 - jest-message-util: 29.3.1 - jest-runtime: 29.3.1 - jest-snapshot: 29.3.1 - jest-util: 29.3.1 + jest-each: 29.5.0 + jest-matcher-utils: 29.5.0 + jest-message-util: 29.5.0 + jest-runtime: 29.5.0 + jest-snapshot: 29.5.0 + jest-util: 29.5.0 p-limit: 3.1.0 - pretty-format: 29.3.1 + pretty-format: 29.5.0 + pure-rand: 6.0.2 slash: 3.0.0 stack-utils: 2.0.5 transitivePeerDependencies: - supports-color dev: true - /jest-cli/29.3.1_odkjkoia5xunhxkdrka32ib6vi: - resolution: {integrity: sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==} + /jest-cli@29.5.0(@types/node@18.16.0)(ts-node@10.9.1): + resolution: {integrity: sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true peerDependencies: @@ -7841,26 +10549,26 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 29.3.1_ts-node@10.9.1 - '@jest/test-result': 29.3.1 - '@jest/types': 29.3.1 + '@jest/core': 29.5.0(ts-node@10.9.1) + '@jest/test-result': 29.5.0 + '@jest/types': 29.5.0 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.10 import-local: 3.1.0 - jest-config: 29.3.1_odkjkoia5xunhxkdrka32ib6vi - jest-util: 29.3.1 - jest-validate: 29.3.1 + jest-config: 29.5.0(@types/node@18.16.0)(ts-node@10.9.1) + jest-util: 29.5.0 + jest-validate: 29.5.0 prompts: 2.4.2 - yargs: 17.5.1 + yargs: 17.7.2 transitivePeerDependencies: - '@types/node' - supports-color - ts-node dev: true - /jest-config/29.3.1_odkjkoia5xunhxkdrka32ib6vi: - resolution: {integrity: sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==} + /jest-config@29.5.0(@types/node@18.16.0)(ts-node@10.9.1): + resolution: {integrity: sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@types/node': '*' @@ -7872,98 +10580,98 @@ packages: optional: true dependencies: '@babel/core': 7.12.3 - '@jest/test-sequencer': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 - babel-jest: 29.3.1_@babel+core@7.12.3 + '@jest/test-sequencer': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 + babel-jest: 29.5.0(@babel/core@7.12.3) chalk: 4.1.2 - ci-info: 3.6.2 + ci-info: 3.8.0 deepmerge: 4.2.2 glob: 7.2.3 graceful-fs: 4.2.10 - jest-circus: 29.3.1 - jest-environment-node: 29.3.1 - jest-get-type: 29.2.0 - jest-regex-util: 29.2.0 - jest-resolve: 29.3.1 - jest-runner: 29.3.1 - jest-util: 29.3.1 - jest-validate: 29.3.1 + jest-circus: 29.5.0 + jest-environment-node: 29.5.0 + jest-get-type: 29.4.3 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-runner: 29.5.0 + jest-util: 29.5.0 + jest-validate: 29.5.0 micromatch: 4.0.5 parse-json: 5.2.0 - pretty-format: 29.3.1 + pretty-format: 29.5.0 slash: 3.0.0 strip-json-comments: 3.1.1 - ts-node: 10.9.1_w6ufic3jqylcjznzspnj4wjqfe + ts-node: 10.9.1(@types/node@18.16.0)(typescript@5.1.3) transitivePeerDependencies: - supports-color dev: true - /jest-diff/29.3.1: - resolution: {integrity: sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==} + /jest-diff@29.5.0: + resolution: {integrity: sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: chalk: 4.1.2 - diff-sequences: 29.3.1 - jest-get-type: 29.2.0 - pretty-format: 29.3.1 + diff-sequences: 29.4.3 + jest-get-type: 29.4.3 + pretty-format: 29.5.0 dev: true - /jest-docblock/29.2.0: - resolution: {integrity: sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==} + /jest-docblock@29.4.3: + resolution: {integrity: sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: detect-newline: 3.1.0 dev: true - /jest-each/29.3.1: - resolution: {integrity: sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==} + /jest-each@29.5.0: + resolution: {integrity: sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.3.1 + '@jest/types': 29.5.0 chalk: 4.1.2 - jest-get-type: 29.2.0 - jest-util: 29.3.1 - pretty-format: 29.3.1 + jest-get-type: 29.4.3 + jest-util: 29.5.0 + pretty-format: 29.5.0 dev: true - /jest-environment-node/29.3.1: - resolution: {integrity: sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==} + /jest-environment-node@29.5.0: + resolution: {integrity: sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.3.1 - '@jest/fake-timers': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 - jest-mock: 29.3.1 - jest-util: 29.3.1 + '@jest/environment': 29.5.0 + '@jest/fake-timers': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 + jest-mock: 29.5.0 + jest-util: 29.5.0 dev: true - /jest-get-type/29.2.0: - resolution: {integrity: sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==} + /jest-get-type@29.4.3: + resolution: {integrity: sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true - /jest-haste-map/29.3.1: - resolution: {integrity: sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==} + /jest-haste-map@29.5.0: + resolution: {integrity: sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.3.1 + '@jest/types': 29.5.0 '@types/graceful-fs': 4.1.5 - '@types/node': 18.11.9 + '@types/node': 18.16.0 anymatch: 3.1.2 fb-watchman: 2.0.2 graceful-fs: 4.2.10 - jest-regex-util: 29.2.0 - jest-util: 29.3.1 - jest-worker: 29.3.1 + jest-regex-util: 29.4.3 + jest-util: 29.5.0 + jest-worker: 29.5.0 micromatch: 4.0.5 walker: 1.0.8 optionalDependencies: fsevents: 2.3.2 dev: true - /jest-image-snapshot/4.2.0_jest@29.3.1: + /jest-image-snapshot@4.2.0(jest@29.5.0): resolution: {integrity: sha512-6aAqv2wtfOgxiJeBayBCqHo1zX+A12SUNNzo7rIxiXh6W6xYVu8QyHWkada8HeRi+QUTHddp0O0Xa6kmQr+xbQ==} engines: {node: '>= 10.14.2'} peerDependencies: @@ -7972,7 +10680,7 @@ packages: chalk: 1.1.3 get-stdin: 5.0.1 glur: 1.1.2 - jest: 29.3.1_odkjkoia5xunhxkdrka32ib6vi + jest: 29.5.0(@types/node@18.16.0)(ts-node@10.9.1) lodash: 4.17.21 mkdirp: 0.5.6 pixelmatch: 5.3.0 @@ -7981,49 +10689,49 @@ packages: ssim.js: 3.5.0 dev: true - /jest-leak-detector/29.3.1: - resolution: {integrity: sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==} + /jest-leak-detector@29.5.0: + resolution: {integrity: sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - jest-get-type: 29.2.0 - pretty-format: 29.3.1 + jest-get-type: 29.4.3 + pretty-format: 29.5.0 dev: true - /jest-matcher-utils/29.3.1: - resolution: {integrity: sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==} + /jest-matcher-utils@29.5.0: + resolution: {integrity: sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: chalk: 4.1.2 - jest-diff: 29.3.1 - jest-get-type: 29.2.0 - pretty-format: 29.3.1 + jest-diff: 29.5.0 + jest-get-type: 29.4.3 + pretty-format: 29.5.0 dev: true - /jest-message-util/29.3.1: - resolution: {integrity: sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==} + /jest-message-util@29.5.0: + resolution: {integrity: sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/code-frame': 7.18.6 - '@jest/types': 29.3.1 + '@jest/types': 29.5.0 '@types/stack-utils': 2.0.1 chalk: 4.1.2 graceful-fs: 4.2.10 micromatch: 4.0.5 - pretty-format: 29.3.1 + pretty-format: 29.5.0 slash: 3.0.0 stack-utils: 2.0.5 dev: true - /jest-mock/29.3.1: - resolution: {integrity: sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==} + /jest-mock@29.5.0: + resolution: {integrity: sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.3.1 - '@types/node': 18.11.9 - jest-util: 29.3.1 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 + jest-util: 29.5.0 dev: true - /jest-pnp-resolver/1.2.2_jest-resolve@29.3.1: + /jest-pnp-resolver@1.2.2(jest-resolve@29.5.0): resolution: {integrity: sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==} engines: {node: '>=6'} peerDependencies: @@ -8032,189 +10740,197 @@ packages: jest-resolve: optional: true dependencies: - jest-resolve: 29.3.1 + jest-resolve: 29.5.0 dev: true - /jest-regex-util/29.2.0: - resolution: {integrity: sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==} + /jest-regex-util@29.4.3: + resolution: {integrity: sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true - /jest-resolve-dependencies/29.3.1: - resolution: {integrity: sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==} + /jest-resolve-dependencies@29.5.0: + resolution: {integrity: sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - jest-regex-util: 29.2.0 - jest-snapshot: 29.3.1 + jest-regex-util: 29.4.3 + jest-snapshot: 29.5.0 transitivePeerDependencies: - supports-color dev: true - /jest-resolve/29.3.1: - resolution: {integrity: sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==} + /jest-resolve@29.5.0: + resolution: {integrity: sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: chalk: 4.1.2 graceful-fs: 4.2.10 - jest-haste-map: 29.3.1 - jest-pnp-resolver: 1.2.2_jest-resolve@29.3.1 - jest-util: 29.3.1 - jest-validate: 29.3.1 - resolve: 1.22.1 - resolve.exports: 1.1.0 + jest-haste-map: 29.5.0 + jest-pnp-resolver: 1.2.2(jest-resolve@29.5.0) + jest-util: 29.5.0 + jest-validate: 29.5.0 + resolve: 1.22.2 + resolve.exports: 2.0.2 slash: 3.0.0 dev: true - /jest-runner/29.3.1: - resolution: {integrity: sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==} + /jest-runner@29.5.0: + resolution: {integrity: sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/console': 29.3.1 - '@jest/environment': 29.3.1 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@jest/console': 29.5.0 + '@jest/environment': 29.5.0 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.10 - jest-docblock: 29.2.0 - jest-environment-node: 29.3.1 - jest-haste-map: 29.3.1 - jest-leak-detector: 29.3.1 - jest-message-util: 29.3.1 - jest-resolve: 29.3.1 - jest-runtime: 29.3.1 - jest-util: 29.3.1 - jest-watcher: 29.3.1 - jest-worker: 29.3.1 + jest-docblock: 29.4.3 + jest-environment-node: 29.5.0 + jest-haste-map: 29.5.0 + jest-leak-detector: 29.5.0 + jest-message-util: 29.5.0 + jest-resolve: 29.5.0 + jest-runtime: 29.5.0 + jest-util: 29.5.0 + jest-watcher: 29.5.0 + jest-worker: 29.5.0 p-limit: 3.1.0 source-map-support: 0.5.13 transitivePeerDependencies: - supports-color dev: true - /jest-runtime/29.3.1: - resolution: {integrity: sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==} + /jest-runtime@29.5.0: + resolution: {integrity: sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/environment': 29.3.1 - '@jest/fake-timers': 29.3.1 - '@jest/globals': 29.3.1 - '@jest/source-map': 29.2.0 - '@jest/test-result': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@jest/environment': 29.5.0 + '@jest/fake-timers': 29.5.0 + '@jest/globals': 29.5.0 + '@jest/source-map': 29.4.3 + '@jest/test-result': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 chalk: 4.1.2 cjs-module-lexer: 1.2.2 collect-v8-coverage: 1.0.1 glob: 7.2.3 graceful-fs: 4.2.10 - jest-haste-map: 29.3.1 - jest-message-util: 29.3.1 - jest-mock: 29.3.1 - jest-regex-util: 29.2.0 - jest-resolve: 29.3.1 - jest-snapshot: 29.3.1 - jest-util: 29.3.1 + jest-haste-map: 29.5.0 + jest-message-util: 29.5.0 + jest-mock: 29.5.0 + jest-regex-util: 29.4.3 + jest-resolve: 29.5.0 + jest-snapshot: 29.5.0 + jest-util: 29.5.0 slash: 3.0.0 strip-bom: 4.0.0 transitivePeerDependencies: - supports-color dev: true - /jest-snapshot/29.3.1: - resolution: {integrity: sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==} + /jest-snapshot@29.5.0: + resolution: {integrity: sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@babel/core': 7.12.3 - '@babel/generator': 7.19.0 - '@babel/plugin-syntax-jsx': 7.18.6_@babel+core@7.12.3 - '@babel/plugin-syntax-typescript': 7.18.6_@babel+core@7.12.3 - '@babel/traverse': 7.19.1 - '@babel/types': 7.19.0 - '@jest/expect-utils': 29.3.1 - '@jest/transform': 29.3.1 - '@jest/types': 29.3.1 + '@babel/generator': 7.21.1 + '@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.12.3) + '@babel/plugin-syntax-typescript': 7.18.6(@babel/core@7.12.3) + '@babel/traverse': 7.21.2 + '@babel/types': 7.21.2 + '@jest/expect-utils': 29.5.0 + '@jest/transform': 29.5.0 + '@jest/types': 29.5.0 '@types/babel__traverse': 7.18.2 - '@types/prettier': 2.7.1 - babel-preset-current-node-syntax: 1.0.1_@babel+core@7.12.3 + '@types/prettier': 2.7.2 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.12.3) chalk: 4.1.2 - expect: 29.3.1 + expect: 29.5.0 graceful-fs: 4.2.10 - jest-diff: 29.3.1 - jest-get-type: 29.2.0 - jest-haste-map: 29.3.1 - jest-matcher-utils: 29.3.1 - jest-message-util: 29.3.1 - jest-util: 29.3.1 + jest-diff: 29.5.0 + jest-get-type: 29.4.3 + jest-matcher-utils: 29.5.0 + jest-message-util: 29.5.0 + jest-util: 29.5.0 natural-compare: 1.4.0 - pretty-format: 29.3.1 - semver: 7.3.8 + pretty-format: 29.5.0 + semver: 7.5.3 transitivePeerDependencies: - supports-color dev: true - /jest-util/29.3.1: - resolution: {integrity: sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==} + /jest-util@29.5.0: + resolution: {integrity: sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 chalk: 4.1.2 - ci-info: 3.6.2 + ci-info: 3.8.0 graceful-fs: 4.2.10 picomatch: 2.3.1 dev: true - /jest-validate/29.3.1: - resolution: {integrity: sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==} + /jest-validate@29.5.0: + resolution: {integrity: sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/types': 29.3.1 + '@jest/types': 29.5.0 camelcase: 6.3.0 chalk: 4.1.2 - jest-get-type: 29.2.0 + jest-get-type: 29.4.3 leven: 3.1.0 - pretty-format: 29.3.1 + pretty-format: 29.5.0 dev: true - /jest-watcher/29.3.1: - resolution: {integrity: sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==} + /jest-watcher@29.5.0: + resolution: {integrity: sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/test-result': 29.3.1 - '@jest/types': 29.3.1 - '@types/node': 18.11.9 + '@jest/test-result': 29.5.0 + '@jest/types': 29.5.0 + '@types/node': 18.16.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 - jest-util: 29.3.1 + jest-util: 29.5.0 string-length: 4.0.2 dev: true - /jest-worker/27.5.1: + /jest-worker@26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 18.16.0 + merge-stream: 2.0.0 + supports-color: 7.2.0 + dev: true + + /jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.11.9 + '@types/node': 18.16.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true - /jest-worker/29.3.1: - resolution: {integrity: sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==} + /jest-worker@29.5.0: + resolution: {integrity: sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 18.11.9 - jest-util: 29.3.1 + '@types/node': 18.16.0 + jest-util: 29.5.0 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true - /jest/29.3.1_odkjkoia5xunhxkdrka32ib6vi: - resolution: {integrity: sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==} + /jest@29.5.0(@types/node@18.16.0)(ts-node@10.9.1): + resolution: {integrity: sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true peerDependencies: @@ -8223,17 +10939,17 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 29.3.1_ts-node@10.9.1 - '@jest/types': 29.3.1 + '@jest/core': 29.5.0(ts-node@10.9.1) + '@jest/types': 29.5.0 import-local: 3.1.0 - jest-cli: 29.3.1_odkjkoia5xunhxkdrka32ib6vi + jest-cli: 29.5.0(@types/node@18.16.0)(ts-node@10.9.1) transitivePeerDependencies: - '@types/node' - 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 @@ -8242,7 +10958,7 @@ packages: 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 @@ -8257,21 +10973,20 @@ packages: nomnom: 1.5.2 dev: true - /jju/1.4.0: + /jiti@1.18.2: + resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==} + hasBin: true + dev: false + + /jiti@1.19.1: + resolution: {integrity: sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==} + hasBin: true + + /jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} dev: true - /joi/17.6.0: - resolution: {integrity: sha512-OX5dG6DTbcr/kbMFj0KGYxuew69HPcAE3K/sZpEV2nP6e/j/C0HV+HNiBPCASxdx5T7DMoa0s8UeHWMnb6n2zw==} - dependencies: - '@hapi/hoek': 9.3.0 - '@hapi/topo': 5.1.0 - '@sideway/address': 4.1.4 - '@sideway/formula': 3.0.0 - '@sideway/pinpoint': 2.0.0 - dev: true - - /joi/17.7.1: + /joi@17.7.1: resolution: {integrity: sha512-teoLhIvWE298R6AeJywcjR4sX2hHjB3/xJX4qPjg+gTg+c0mzUDsziYlqPmLomq9gVsfaMcgPaGc7VxtD/9StA==} dependencies: '@hapi/hoek': 9.3.0 @@ -8281,23 +10996,23 @@ packages: '@sideway/pinpoint': 2.0.0 dev: true - /jpeg-js/0.4.4: + /jpeg-js@0.4.4: resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} dev: true - /js-base64/3.7.2: - resolution: {integrity: sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ==} + /js-base64@3.7.5: + resolution: {integrity: sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==} dev: true - /js-sdsl/4.1.4: + /js-sdsl@4.1.4: resolution: {integrity: sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==} dev: true - /js-tokens/4.0.0: + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true - /js-yaml/3.14.1: + /js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true dependencies: @@ -8305,25 +11020,25 @@ packages: 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/3.1.0: - resolution: {integrity: sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw==} + /jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} engines: {node: '>=12.0.0'} dev: true - /jsdom/21.1.0: - resolution: {integrity: sha512-m0lzlP7qOtthD918nenK3hdItSd2I+V3W9IrBcB36sqDwG+KnUs66IF5GY7laGWUnlM9vTsD0W1QwSEBYWWcJg==} - engines: {node: '>=14'} + /jsdom@22.0.0: + resolution: {integrity: sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw==} + engines: {node: '>=16'} peerDependencies: canvas: ^2.5.0 peerDependenciesMeta: @@ -8331,21 +11046,18 @@ packages: optional: true dependencies: abab: 2.0.6 - acorn: 8.8.1 - acorn-globals: 7.0.1 - cssom: 0.5.0 - cssstyle: 2.3.0 - data-urls: 3.0.2 + cssstyle: 3.0.0 + data-urls: 4.0.0 decimal.js: 10.4.3 domexception: 4.0.0 - escodegen: 2.0.0 form-data: 4.0.0 html-encoding-sniffer: 3.0.0 http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.2 - parse5: 7.1.1 + nwsapi: 2.2.5 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 saxes: 6.0.0 symbol-tree: 3.2.4 tough-cookie: 4.1.2 @@ -8353,8 +11065,8 @@ packages: webidl-conversions: 7.0.0 whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 - whatwg-url: 11.0.0 - ws: 8.12.0 + whatwg-url: 12.0.1 + ws: 8.13.0 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -8362,68 +11074,89 @@ packages: - utf-8-validate dev: true - /jsesc/0.5.0: + /jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true dev: true - /jsesc/2.5.2: + /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: + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true - /json-parse-even-better-errors/2.3.1: + /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true - /json-schema-traverse/0.4.1: + /json-schema-to-typescript@11.0.3: + resolution: {integrity: sha512-EaEE9Y4VZ8b9jW5zce5a9L3+p4C9AqgIRHbNVDJahfMnoKzcd4sDb98BLxLdQhJEuRAXyKLg4H66NKm80W8ilg==} + engines: {node: '>=12.0.0'} + hasBin: true + dependencies: + '@bcherny/json-schema-ref-parser': 9.0.9 + '@types/json-schema': 7.0.11 + '@types/lodash': 4.14.194 + '@types/prettier': 2.7.2 + cli-color: 2.0.3 + 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: 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.1: - resolution: {integrity: sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==} + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true dev: true - /jsonc-parser/3.2.0: + /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true - /jsonfile/4.0.0: + /jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: graceful-fs: 4.2.10 dev: true - /jsonfile/6.1.0: + /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: universalify: 2.0.0 @@ -8431,7 +11164,7 @@ packages: graceful-fs: 4.2.10 dev: true - /jsonlint/1.6.0: + /jsonlint@1.6.0: resolution: {integrity: sha512-x6YLBe6NjdpmIeiklwQOxsZuYj/SOWkT33GlTpaG1UdFGjdWjPcxJ1CWZAX3wA7tarz8E2YHF6KiW5HTapPlXw==} engines: {node: '>= 0.6'} hasBin: true @@ -8440,22 +11173,17 @@ packages: nomnom: 1.5.2 dev: true - /jsonparse/1.3.1: + /jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} dev: true - /jsprim/1.4.2: - resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} - engines: {node: '>=0.6.0'} - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 + /jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} dev: true - /jsprim/2.0.2: + /jsprim@2.0.2: resolution: {integrity: sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==} engines: {'0': node >=0.6.0} dependencies: @@ -8465,65 +11193,63 @@ packages: verror: 1.10.0 dev: true - /junk/4.0.0: + /junk@4.0.0: resolution: {integrity: sha512-ojtSU++zLJ3jQG9bAYjg94w+/DOJtRyD7nPaerMFrBhmdVmiV5/exYH5t4uHga4G/95nT6hr1OJoKIFbYbrW5w==} engines: {node: '>=12.20'} dev: true - /keyv/4.5.0: + /keyv@4.5.0: resolution: {integrity: sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==} dependencies: json-buffer: 3.0.1 dev: true - /khroma/2.0.0: + /khroma@2.0.0: resolution: {integrity: sha512-2J8rDNlQWbtiNYThZRvmMv5yt44ZakX+Tz5ZIp/mN1pt4snn+m030Va5Z4v8xA0cQFDXBwO/8i42xL4QPsVk3g==} 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 - /kleur/4.1.5: + /kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} dev: true - /ky/0.28.7: - resolution: {integrity: sha512-a23i6qSr/ep15vdtw/zyEQIDLoUaKDg9Jf04CYl/0ns/wXNYna26zJpI+MeIFaPeDvkrjLPrKtKOiiI3IE53RQ==} + /ky@0.30.0: + resolution: {integrity: sha512-X/u76z4JtDVq10u1JA5UQfatPxgPaVDMYTrgHyiTpGN2z4TMEJkIHsoSBBSg9SWZEIXTKsi9kHgiQ9o3Y/4yog==} engines: {node: '>=12'} dev: true - /layout-base/1.0.2: + /layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} dev: false - /layout-base/2.0.1: + /layout-base@2.0.1: resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} dev: false - /lazy-ass/1.6.0: + /lazy-ass@1.6.0: resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} engines: {node: '> 0.8'} dev: true - /lcov-parse/1.0.0: - resolution: {integrity: sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==} - hasBin: true - dev: true - - /leven/3.1.0: + /leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} dev: true - /levn/0.3.0: + /levn@0.3.0: resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} engines: {node: '>= 0.8.0'} dependencies: @@ -8531,7 +11257,7 @@ packages: type-check: 0.3.2 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: @@ -8539,49 +11265,56 @@ packages: 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 - /lilconfig/2.0.5: - resolution: {integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==} + /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 + + /lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} - dev: true - /lines-and-columns/1.2.4: + /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - /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/13.0.3: - resolution: {integrity: sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==} + /lint-staged@13.2.1: + resolution: {integrity: sha512-8gfzinVXoPfga5Dz/ZOn8I2GOhf81Wvs+KwbEXQn/oWZAvCVS2PivrXfVbFJc93zD16uC0neS47RXHIjXKYZQw==} engines: {node: ^14.13.1 || >=16.0.0} hasBin: true dependencies: + chalk: 5.2.0 cli-truncate: 3.1.0 - colorette: 2.0.19 - commander: 9.4.0 - debug: 4.3.4 - execa: 6.1.0 - lilconfig: 2.0.5 - listr2: 4.0.5 + commander: 10.0.1 + debug: 4.3.4(supports-color@8.1.1) + execa: 7.1.1 + lilconfig: 2.1.0 + listr2: 5.0.8 micromatch: 4.0.5 normalize-path: 3.0.0 - object-inspect: 1.12.2 + object-inspect: 1.12.3 pidtree: 0.6.0 string-argv: 0.3.1 - yaml: 2.1.1 + yaml: 2.2.2 transitivePeerDependencies: - enquirer - supports-color dev: true - /listr2/3.14.0_enquirer@2.3.6: + /listr2@3.14.0(enquirer@2.3.6): resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==} engines: {node: '>=10.0.0'} peerDependencies: @@ -8591,19 +11324,19 @@ packages: optional: true dependencies: cli-truncate: 2.1.0 - colorette: 2.0.19 + colorette: 2.0.20 enquirer: 2.3.6 log-update: 4.0.0 p-map: 4.0.0 rfdc: 1.3.0 - rxjs: 7.5.6 + rxjs: 7.8.0 through: 2.3.8 wrap-ansi: 7.0.0 dev: true - /listr2/4.0.5: - resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==} - engines: {node: '>=12'} + /listr2@5.0.8: + resolution: {integrity: sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==} + engines: {node: ^14.13.1 || >=16.0.0} peerDependencies: enquirer: '>= 2.3.0 < 3' peerDependenciesMeta: @@ -8611,26 +11344,26 @@ packages: optional: true dependencies: cli-truncate: 2.1.0 - colorette: 2.0.19 + colorette: 2.0.20 log-update: 4.0.0 p-map: 4.0.0 rfdc: 1.3.0 - rxjs: 7.5.6 + rxjs: 7.8.0 through: 2.3.8 wrap-ansi: 7.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.2: - resolution: {integrity: sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==} + /local-pkg@0.4.3: + resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} engines: {node: '>=14'} dev: true - /locate-path/3.0.0: + /locate-path@3.0.0: resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} engines: {node: '>=6'} dependencies: @@ -8638,41 +11371,84 @@ packages: 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 - /lodash-es/4.17.21: + /lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} dev: false - /lodash.merge/4.6.2: + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: true + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + dev: true + + /lodash.flattendeep@4.4.0: + resolution: {integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==} + dev: true + + /lodash.isfunction@3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + dev: true + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + dev: true + + /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true - /lodash.once/4.1.1: + /lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: true + + /lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} dev: true - /lodash/4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - /log-driver/1.2.7: - resolution: {integrity: sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==} - engines: {node: '>=0.8.6'} + /lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} dev: true - /log-symbols/4.1.0: + /lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + dev: true + + /lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + + /lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: true + + /lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + /log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} dependencies: @@ -8680,7 +11456,7 @@ packages: 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: @@ -8690,85 +11466,119 @@ packages: wrap-ansi: 6.2.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.8.0: + /loglevel@1.8.0: resolution: {integrity: sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==} engines: {node: '>= 0.6.0'} dev: true - /longest-streak/3.0.1: + /longest-streak@3.0.1: resolution: {integrity: sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg==} dev: true - /loupe/2.3.6: + /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} dependencies: get-func-name: 2.0.0 dev: true - /lowercase-keys/2.0.0: + /lowercase-keys@2.0.0: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} engines: {node: '>=8'} dev: true - /lru-cache/5.1.1: + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 dev: true - /lru-cache/6.0.0: + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} dependencies: yallist: 4.0.0 dev: true - /lunr/2.3.9: + /lru-cache@9.1.1: + resolution: {integrity: sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==} + engines: {node: 14 || >=16.14} + dev: true + + /lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + dependencies: + es5-ext: 0.10.62 + dev: true + + /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 - /make-dir/3.1.0: + /magic-string@0.30.1: + resolution: {integrity: sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /magic-string@0.30.2: + resolution: {integrity: sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + + /make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} dependencies: semver: 6.3.0 dev: true - /make-error/1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.3 dev: true - /makeerror/1.0.12: + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + /makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} dependencies: tmpl: 1.0.5 dev: true - /map-obj/1.0.1: + /map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} dev: true - /map-obj/4.3.0: + /map-obj@4.3.0: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} dev: true - /map-stream/0.1.0: + /map-stream@0.1.0: resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} dev: true - /markdown-it/13.0.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==} hasBin: true dependencies: @@ -8779,17 +11589,29 @@ packages: uc.micro: 1.0.6 dev: true - /markdown-table/3.0.3: + /markdown-table@3.0.3: resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} dev: true - /marked/4.1.1: - resolution: {integrity: sha512-0cNMnTcUJPxbA6uWmCmjWz4NJRe/0Xfk2NhXCUHjew9qJzFN20krFnsUe7QynwqOwa5m1fZ4UDg0ycKFVC0ccw==} + /marked@4.3.0: + resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==} engines: {node: '>= 12'} hasBin: true + + /matchit@1.1.0: + resolution: {integrity: sha512-+nGYoOlfHmxe5BW5tE0EMJppXEwdSf8uBA1GTZC7Q77kbT35+VKLYJMzVNWCHSsga1ps1tPYFtFyvxvKzWVmMA==} + engines: {node: '>=6'} + dependencies: + '@arr/every': 1.0.1 dev: true - /mdast-util-find-and-replace/2.2.1: + /mdast-builder@1.1.1: + resolution: {integrity: sha512-a3KBk/LmYD6wKsWi8WJrGU/rXR4yuF4Men0JO0z6dSZCm5FrXXWTRDjqK0vGSqa+1M6p9edeuypZAZAzSehTUw==} + dependencies: + '@types/unist': 2.0.6 + dev: true + + /mdast-util-find-and-replace@2.2.1: resolution: {integrity: sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw==} dependencies: escape-string-regexp: 5.0.0 @@ -8797,10 +11619,10 @@ packages: unist-util-visit-parents: 5.1.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.10 + '@types/mdast': 3.0.11 mdast-util-to-string: 2.0.0 micromark: 2.11.4 parse-entities: 2.0.0 @@ -8809,10 +11631,10 @@ packages: - supports-color dev: true - /mdast-util-from-markdown/1.2.0: - resolution: {integrity: sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==} + /mdast-util-from-markdown@1.3.0: + resolution: {integrity: sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 '@types/unist': 2.0.6 decode-named-character-reference: 1.0.2 mdast-util-to-string: 3.1.0 @@ -8826,60 +11648,59 @@ packages: uvu: 0.5.6 transitivePeerDependencies: - supports-color - dev: true - /mdast-util-frontmatter/1.0.0: + /mdast-util-frontmatter@1.0.0: resolution: {integrity: sha512-7itKvp0arEVNpCktOET/eLFAYaZ+0cNjVtFtIPxgQ5tV+3i+D4SDDTjTzPWl44LT59PC+xdx+glNTawBdF98Mw==} dependencies: micromark-extension-frontmatter: 1.0.0 dev: true - /mdast-util-gfm-autolink-literal/1.0.2: + /mdast-util-gfm-autolink-literal@1.0.2: resolution: {integrity: sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 ccount: 2.0.1 mdast-util-find-and-replace: 2.2.1 micromark-util-character: 1.1.0 dev: true - /mdast-util-gfm-footnote/1.0.1: + /mdast-util-gfm-footnote@1.0.1: resolution: {integrity: sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 mdast-util-to-markdown: 1.3.0 micromark-util-normalize-identifier: 1.0.0 dev: true - /mdast-util-gfm-strikethrough/1.0.2: + /mdast-util-gfm-strikethrough@1.0.2: resolution: {integrity: sha512-T/4DVHXcujH6jx1yqpcAYYwd+z5lAYMw4Ls6yhTfbMMtCt0PHY4gEfhW9+lKsLBtyhUGKRIzcUA2FATVqnvPDA==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 mdast-util-to-markdown: 1.3.0 dev: true - /mdast-util-gfm-table/1.0.6: + /mdast-util-gfm-table@1.0.6: resolution: {integrity: sha512-uHR+fqFq3IvB3Rd4+kzXW8dmpxUhvgCQZep6KdjsLK4O6meK5dYZEayLtIxNus1XO3gfjfcIFe8a7L0HZRGgag==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 markdown-table: 3.0.3 - mdast-util-from-markdown: 1.2.0 + mdast-util-from-markdown: 1.3.0 mdast-util-to-markdown: 1.3.0 transitivePeerDependencies: - supports-color dev: true - /mdast-util-gfm-task-list-item/1.0.1: + /mdast-util-gfm-task-list-item@1.0.1: resolution: {integrity: sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 mdast-util-to-markdown: 1.3.0 dev: true - /mdast-util-gfm/2.0.1: + /mdast-util-gfm@2.0.1: resolution: {integrity: sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ==} dependencies: - mdast-util-from-markdown: 1.2.0 + mdast-util-from-markdown: 1.3.0 mdast-util-gfm-autolink-literal: 1.0.2 mdast-util-gfm-footnote: 1.0.1 mdast-util-gfm-strikethrough: 1.0.2 @@ -8890,47 +11711,59 @@ packages: - supports-color dev: true - /mdast-util-to-markdown/1.3.0: + /mdast-util-to-markdown@1.3.0: resolution: {integrity: sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 '@types/unist': 2.0.6 longest-streak: 3.0.1 mdast-util-to-string: 3.1.0 micromark-util-decode-string: 1.0.2 - unist-util-visit: 4.1.1 + unist-util-visit: 4.1.2 zwitch: 2.0.2 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/3.1.0: + /mdast-util-to-string@3.1.0: resolution: {integrity: sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==} + + /mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} dev: true - /mdn-data/2.0.6: - resolution: {integrity: sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==} - dev: true - - /mdurl/1.0.1: + /mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} dev: true - /media-typer/0.3.0: + /media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} dev: true - /memfs/3.4.11: + /memfs@3.4.11: resolution: {integrity: sha512-GvsCITGAyDCxxsJ+X6prJexFQEhOCJaIlUbsAvjzSI5o5O7j2dle3jWvz5Z5aOdpOxW6ol3vI1+0ut+641F1+w==} engines: {node: '>= 4.0.0'} dependencies: fs-monkey: 1.0.3 dev: true - /meow/10.1.5: + /memoizee@0.4.15: + resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + 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@10.1.5: resolution: {integrity: sha512-/d+PQ4GKmGvM9Bee/DPa8z3mXs/pkvJE2KEThngVNOqtmljC6K7NMPxtc2JeZYTmpWb9k/TmxjeL18ez3h7vCw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: @@ -8948,7 +11781,7 @@ packages: yargs-parser: 20.2.9 dev: true - /meow/8.1.2: + /meow@8.1.2: resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} engines: {node: '>=10'} dependencies: @@ -8965,25 +11798,24 @@ packages: yargs-parser: 20.2.9 dev: true - /merge-descriptors/1.0.1: + /merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} dev: true - /merge-stream/2.0.0: + /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'} - dev: true - /methods/1.1.2: + /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} dev: true - /micromark-core-commonmark/1.0.6: + /micromark-core-commonmark@1.0.6: resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==} dependencies: decode-named-character-reference: 1.0.2 @@ -9002,9 +11834,8 @@ packages: micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 uvu: 0.5.6 - dev: true - /micromark-extension-frontmatter/1.0.0: + /micromark-extension-frontmatter@1.0.0: resolution: {integrity: sha512-EXjmRnupoX6yYuUJSQhrQ9ggK0iQtQlpi6xeJzVD5xscyAI+giqco5fdymayZhJMbIFecjnE2yz85S9NzIgQpg==} dependencies: fault: 2.0.1 @@ -9012,7 +11843,7 @@ packages: micromark-util-symbol: 1.0.1 dev: true - /micromark-extension-gfm-autolink-literal/1.0.3: + /micromark-extension-gfm-autolink-literal@1.0.3: resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==} dependencies: micromark-util-character: 1.1.0 @@ -9022,7 +11853,7 @@ packages: uvu: 0.5.6 dev: true - /micromark-extension-gfm-footnote/1.0.4: + /micromark-extension-gfm-footnote@1.0.4: resolution: {integrity: sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg==} dependencies: micromark-core-commonmark: 1.0.6 @@ -9035,7 +11866,7 @@ packages: uvu: 0.5.6 dev: true - /micromark-extension-gfm-strikethrough/1.0.4: + /micromark-extension-gfm-strikethrough@1.0.4: resolution: {integrity: sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ==} dependencies: micromark-util-chunked: 1.0.0 @@ -9046,7 +11877,7 @@ packages: uvu: 0.5.6 dev: true - /micromark-extension-gfm-table/1.0.5: + /micromark-extension-gfm-table@1.0.5: resolution: {integrity: sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg==} dependencies: micromark-factory-space: 1.0.0 @@ -9056,13 +11887,13 @@ packages: uvu: 0.5.6 dev: true - /micromark-extension-gfm-tagfilter/1.0.1: + /micromark-extension-gfm-tagfilter@1.0.1: resolution: {integrity: sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA==} dependencies: micromark-util-types: 1.0.2 dev: true - /micromark-extension-gfm-task-list-item/1.0.3: + /micromark-extension-gfm-task-list-item@1.0.3: resolution: {integrity: sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q==} dependencies: micromark-factory-space: 1.0.0 @@ -9072,7 +11903,7 @@ packages: uvu: 0.5.6 dev: true - /micromark-extension-gfm/2.0.1: + /micromark-extension-gfm@2.0.1: resolution: {integrity: sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA==} dependencies: micromark-extension-gfm-autolink-literal: 1.0.3 @@ -9085,31 +11916,28 @@ packages: micromark-util-types: 1.0.2 dev: true - /micromark-factory-destination/1.0.0: + /micromark-factory-destination@1.0.0: resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==} dependencies: micromark-util-character: 1.1.0 micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 - dev: true - /micromark-factory-label/1.0.2: + /micromark-factory-label@1.0.2: resolution: {integrity: sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==} dependencies: micromark-util-character: 1.1.0 micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 uvu: 0.5.6 - dev: true - /micromark-factory-space/1.0.0: + /micromark-factory-space@1.0.0: resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==} dependencies: micromark-util-character: 1.1.0 micromark-util-types: 1.0.2 - dev: true - /micromark-factory-title/1.0.2: + /micromark-factory-title@1.0.2: resolution: {integrity: sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==} dependencies: micromark-factory-space: 1.0.0 @@ -9117,119 +11945,103 @@ packages: micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 uvu: 0.5.6 - dev: true - /micromark-factory-whitespace/1.0.0: + /micromark-factory-whitespace@1.0.0: resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==} dependencies: micromark-factory-space: 1.0.0 micromark-util-character: 1.1.0 micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 - dev: true - /micromark-util-character/1.1.0: + /micromark-util-character@1.1.0: resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==} dependencies: micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 - dev: true - /micromark-util-chunked/1.0.0: + /micromark-util-chunked@1.0.0: resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==} dependencies: micromark-util-symbol: 1.0.1 - dev: true - /micromark-util-classify-character/1.0.0: + /micromark-util-classify-character@1.0.0: resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==} dependencies: micromark-util-character: 1.1.0 micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 - dev: true - /micromark-util-combine-extensions/1.0.0: + /micromark-util-combine-extensions@1.0.0: resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==} dependencies: micromark-util-chunked: 1.0.0 micromark-util-types: 1.0.2 - dev: true - /micromark-util-decode-numeric-character-reference/1.0.0: + /micromark-util-decode-numeric-character-reference@1.0.0: resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==} dependencies: micromark-util-symbol: 1.0.1 - dev: true - /micromark-util-decode-string/1.0.2: + /micromark-util-decode-string@1.0.2: resolution: {integrity: sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==} dependencies: decode-named-character-reference: 1.0.2 micromark-util-character: 1.1.0 micromark-util-decode-numeric-character-reference: 1.0.0 micromark-util-symbol: 1.0.1 - dev: true - /micromark-util-encode/1.0.1: + /micromark-util-encode@1.0.1: resolution: {integrity: sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==} - dev: true - /micromark-util-html-tag-name/1.1.0: + /micromark-util-html-tag-name@1.1.0: resolution: {integrity: sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==} - dev: true - /micromark-util-normalize-identifier/1.0.0: + /micromark-util-normalize-identifier@1.0.0: resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==} dependencies: micromark-util-symbol: 1.0.1 - dev: true - /micromark-util-resolve-all/1.0.0: + /micromark-util-resolve-all@1.0.0: resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==} dependencies: micromark-util-types: 1.0.2 - dev: true - /micromark-util-sanitize-uri/1.0.0: + /micromark-util-sanitize-uri@1.0.0: resolution: {integrity: sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==} dependencies: micromark-util-character: 1.1.0 micromark-util-encode: 1.0.1 micromark-util-symbol: 1.0.1 - dev: true - /micromark-util-subtokenize/1.0.2: + /micromark-util-subtokenize@1.0.2: resolution: {integrity: sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==} dependencies: micromark-util-chunked: 1.0.0 micromark-util-symbol: 1.0.1 micromark-util-types: 1.0.2 uvu: 0.5.6 - dev: true - /micromark-util-symbol/1.0.1: + /micromark-util-symbol@1.0.1: resolution: {integrity: sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==} - dev: true - /micromark-util-types/1.0.2: + /micromark-util-types@1.0.2: resolution: {integrity: sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==} - dev: true - /micromark/2.11.4: + /micromark@2.11.4: resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) parse-entities: 2.0.0 transitivePeerDependencies: - supports-color dev: true - /micromark/3.0.10: + /micromark@3.0.10: resolution: {integrity: sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==} dependencies: '@types/debug': 4.1.7 - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) decode-named-character-reference: 1.0.2 micromark-core-commonmark: 1.0.6 micromark-factory-space: 1.0.0 @@ -9247,77 +12059,88 @@ packages: uvu: 0.5.6 transitivePeerDependencies: - supports-color - dev: true - /micromatch/4.0.5: + /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} dependencies: braces: 3.0.2 picomatch: 2.3.1 - dev: true - /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-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@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-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@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: true - /minimatch/5.1.0: - resolution: {integrity: sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==} + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} dependencies: brace-expansion: 2.0.1 dev: true - /minimist-options/4.1.0: + /minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} dependencies: @@ -9326,57 +12149,66 @@ packages: kind-of: 6.0.3 dev: true - /minimist/1.2.6: - resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} - dev: true - - /minimist/1.2.8: + /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true - /mkdirp/0.5.6: + /minipass@5.0.0: + resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} + engines: {node: '>=8'} + dev: true + + /minisearch@6.0.1: + resolution: {integrity: sha512-Ly1w0nHKnlhAAh6/BF/+9NgzXfoJxaJ8nhopFhQ3NcvFJrFIL+iCg9gw9e9UMBD+XIsp/RyznJ/o5UIe5Kw+kg==} + dev: true + + /minisearch@6.1.0: + resolution: {integrity: sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==} + dev: true + + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true dependencies: - minimist: 1.2.6 + minimist: 1.2.8 dev: true - /mlly/1.1.0: - resolution: {integrity: sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==} + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /mlly@1.4.0: + resolution: {integrity: sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==} dependencies: - acorn: 8.8.1 - pathe: 1.1.0 - pkg-types: 1.0.1 - ufo: 1.0.1 + acorn: 8.10.0 + pathe: 1.1.1 + pkg-types: 1.0.3 + ufo: 1.1.2 dev: true - /moment-mini/2.29.4: - resolution: {integrity: sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==} - dev: false - - /mri/1.2.0: + /mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} - dev: true - /mrmime/1.0.1: + /mrmime@1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} 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==} - dev: true - /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: @@ -9384,43 +12216,61 @@ packages: thunky: 1.1.0 dev: true - /nanoid/3.3.4: - resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} + /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.6: + resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true - /natural-compare-lite/1.4.0: + /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} dev: 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: + /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 - /netmask/2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} + /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-fetch/2.6.7: + /node-cleanup@2.1.2: + resolution: {integrity: sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==} + dev: true + + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: true + + /node-fetch-native@1.2.0: + resolution: {integrity: sha512-5IAMBTl9p6PaAjYCnMv5FmqIF6GcZnawAVnzaCG0rX2aYZJ4CxEkZNtVPuTRug7fL7wyM5BQYTlAzcyMPi6oTQ==} + dev: true + + /node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} peerDependencies: @@ -9432,20 +12282,49 @@ packages: whatwg-url: 5.0.0 dev: true - /node-forge/1.3.1: + /node-fetch@2.6.9(encoding@0.1.13): + resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + encoding: 0.1.13 + whatwg-url: 5.0.0 + dev: 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: 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-releases/2.0.6: - resolution: {integrity: sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==} + /node-preload@0.2.1: + resolution: {integrity: sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==} + engines: {node: '>=8'} + dependencies: + process-on-spawn: 1.0.0 dev: true - /nomnom/1.5.2: + /node-releases@2.0.10: + resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} + dev: true + + /nomnom@1.5.2: resolution: {integrity: sha512-fiVbT7BqxiQqjlR9U3FDGOSERFCKoXVCdxV2FwZuNN7/cmJ42iQx35nUFOAFDcyvemu9Adp+IlsCGlKQYLmBKw==} deprecated: Package no longer supported. Contact support@npmjs.com for more info. dependencies: @@ -9453,114 +12332,179 @@ packages: underscore: 1.1.7 dev: true - /non-layered-tidy-tree-layout/2.0.2: + /non-layered-tidy-tree-layout@2.0.2: resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} dev: false - /normalize-package-data/2.5.0: + /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.1 + resolve: 1.22.2 semver: 5.7.1 validate-npm-package-license: 3.0.4 dev: true - /normalize-package-data/3.0.3: + /normalize-package-data@3.0.3: resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} engines: {node: '>=10'} dependencies: hosted-git-info: 4.1.0 - is-core-module: 2.10.0 - semver: 7.3.8 + is-core-module: 2.12.1 + semver: 7.5.3 validate-npm-package-license: 3.0.4 dev: true - /normalize-path/3.0.0: + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - dev: true - /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.1.0: + /npm-run-path@5.1.0: resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: path-key: 4.0.0 dev: true - /nwsapi/2.2.2: - resolution: {integrity: sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==} + /nwsapi@2.2.5: + resolution: {integrity: sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==} dev: true - /oauth-sign/0.9.0: - resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + /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.8.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.0 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.5 + 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: + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - dev: true - /object-inspect/1.12.2: + /object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + dev: false + + /object-inspect@1.12.2: resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} dev: true - /obuf/1.1.2: + /object-inspect@1.12.3: + resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.4: + resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} dev: true - /on-finished/2.4.1: + /ofetch@1.1.1: + resolution: {integrity: sha512-SSMoktrp9SNLi20BWfB/BnnKcL0RDigXThD/mZBeQxkIRv1xrd9183MtLdsqRYLYSqW0eTr5t8w8MqjNhvoOQQ==} + dependencies: + destr: 2.0.0 + node-fetch-native: 1.2.0 + ufo: 1.1.2 + dev: true + + /on-exit-leak-free@2.1.0: + resolution: {integrity: sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==} + dev: false + + /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.0: + /open@8.4.0: resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==} engines: {node: '>=12'} dependencies: @@ -9569,7 +12513,7 @@ packages: is-wsl: 2.2.0 dev: true - /optionator/0.8.3: + /optionator@0.8.3: resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} engines: {node: '>= 0.8.0'} dependencies: @@ -9578,10 +12522,10 @@ packages: levn: 0.3.0 prelude-ls: 1.1.2 type-check: 0.3.2 - word-wrap: 1.2.3 + word-wrap: 1.2.4 dev: true - /optionator/0.9.1: + /optionator@0.9.1: resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} engines: {node: '>= 0.8.0'} dependencies: @@ -9590,99 +12534,106 @@ packages: levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 - word-wrap: 1.2.3 + word-wrap: 1.2.4 dev: true - /ospath/1.2.2: + /ospath@1.2.2: resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} dev: true - /p-cancelable/2.1.1: + /p-cancelable@2.1.1: resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} engines: {node: '>=8'} dev: true - /p-event/4.2.0: + /p-event@4.2.0: resolution: {integrity: sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==} engines: {node: '>=8'} dependencies: p-timeout: 3.2.0 dev: true - /p-filter/3.0.0: + /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-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-map/4.0.0: + /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: 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-retry/4.6.2: + /p-retry@4.6.2: resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} engines: {node: '>=8'} dependencies: @@ -9690,63 +12641,47 @@ packages: retry: 0.13.1 dev: true - /p-timeout/3.2.0: + /p-timeout@3.2.0: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} engines: {node: '>=8'} dependencies: p-finally: 1.0.0 dev: true - /p-try/2.2.0: + /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} dev: true - /pac-proxy-agent/5.0.0: - resolution: {integrity: sha512-CcFG3ZtnxO8McDigozwE3AqAw15zDvGH+OjXO4kzf7IkEKkQ4gxQ+3sdF50WmhQ4P/bVusXcqNE2S3XrNURwzQ==} - engines: {node: '>= 8'} + /package-hash@4.0.0: + resolution: {integrity: sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==} + engines: {node: '>=8'} dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.4 - get-uri: 3.0.2 - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - pac-resolver: 5.0.1 - raw-body: 2.5.1 - socks-proxy-agent: 5.0.1 - transitivePeerDependencies: - - supports-color + graceful-fs: 4.2.10 + hasha: 5.2.2 + lodash.flattendeep: 4.4.0 + release-zalgo: 1.0.0 dev: true - /pac-resolver/5.0.1: - resolution: {integrity: sha512-cy7u00ko2KVgBAjuhevqpPeHIkCIqPe1v24cydhWjmeuzaBfmUWFCZJ1iAh5TuVzVZoUzXIW7K8sMYOZ84uZ9Q==} - engines: {node: '>= 8'} - dependencies: - degenerator: 3.0.2 - ip: 1.1.8 - netmask: 2.0.2 - dev: true - - /pako/1.0.11: + /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 @@ -9757,7 +12692,7 @@ packages: is-hexadecimal: 1.0.4 dev: true - /parse-json/5.2.0: + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: @@ -9767,145 +12702,213 @@ packages: lines-and-columns: 1.2.4 dev: true - /parse5/6.0.1: + /parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} dev: true - /parse5/7.1.1: + /parse5@7.1.1: resolution: {integrity: sha512-kwpuwzB+px5WUg9pyK0IcK/shltJN5/OVhQagxhCQNtT9Y9QRZqNY2e1cmbu/paRh5LMnz/oVTVLBpjFmMZhSg==} dependencies: entities: 4.4.0 dev: true - /parseurl/1.3.3: + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.4.0 + dev: true + + /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-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-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'} dev: true - /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.7.0: + resolution: {integrity: sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 9.1.1 + minipass: 5.0.0 dev: true - /path-to-regexp/0.1.7: + /path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} dev: true - /path-type/4.0.0: + /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} dev: true - /pathe/1.1.0: + /pathe@1.1.0: resolution: {integrity: sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==} dev: true - /pathval/1.1.1: + /pathe@1.1.1: + resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + dev: true + + /pathval@1.1.1: resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} dev: true - /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: + /pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} dev: true - /performance-now/2.1.0: + /perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + dev: true + + /performance-now@2.1.0: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} dev: true - /picocolors/1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + /phin@3.7.0: + resolution: {integrity: sha512-DqnVNrpYhKGBZppNKprD+UJylMeEKOZxHgPB+ZP6mGzf3uA2uox4Ep9tUm+rUc8WLIdHT3HcAE4X8fhwQA9JKg==} + engines: {node: '>= 8'} + dependencies: + centra: 2.6.0 dev: true - /picomatch/2.3.1: + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + + /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - dev: true - /pidtree/0.6.0: + /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.0.0: + resolution: {integrity: sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==} + dependencies: + readable-stream: 4.4.0 + split2: 4.2.0 + dev: false + + /pino-std-serializers@3.2.0: + resolution: {integrity: sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==} dev: true - /pirates/4.0.5: + /pino-std-serializers@6.2.1: + resolution: {integrity: sha512-wHuWB+CvSVb2XqXM0W/WOYUkVSPbiJb9S5fNB7TBhd8s892Xq910bRxwHtC4l71hgztObTjXL6ZheZXFjhDrDQ==} + dev: false + + /pino@6.14.0: + resolution: {integrity: sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg==} + hasBin: true + dependencies: + fast-redact: 3.1.2 + 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.14.1: + resolution: {integrity: sha512-8LYNv7BKWXSfS+k6oEc6occy5La+q2sPwU3q2ljTX5AZk7v+5kND2o5W794FyRaqha6DJajmkNRsWtPpFyMUdw==} + hasBin: true + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.1.2 + on-exit-leak-free: 2.1.0 + pino-abstract-transport: 1.0.0 + pino-std-serializers: 6.2.1 + process-warning: 2.2.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.4.3 + sonic-boom: 3.3.0 + thread-stream: 2.3.0 + dev: false + + /pirates@4.0.5: resolution: {integrity: sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==} engines: {node: '>= 6'} - dev: true - /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-types/1.0.1: - resolution: {integrity: sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==} + /pkg-types@1.0.3: + resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} dependencies: jsonc-parser: 3.2.0 - mlly: 1.1.0 - pathe: 1.1.0 + mlly: 1.4.0 + pathe: 1.1.1 dev: true - /plist/3.0.6: + /plist@3.0.6: resolution: {integrity: sha512-WiIVYyrp8TD4w8yCvyeIr+lkmrGRd5u0VbRnU+tP/aRLxP/YadJUYOMZJ/6hIa3oUyVCsycXvtNRgd5XBJIbiA==} engines: {node: '>=6'} dependencies: @@ -9913,68 +12916,123 @@ packages: 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/7.15.0: - resolution: {integrity: sha512-GGQ5+MCwD0bpq+65uitpgO1+ZusZ1keO5ebG/CH6ciu1ohnZj5Y3X374Ow/CBApa+Jw2/NUifVRz2fW4JChftA==} - engines: {node: '>=14.6'} + /pnpm@8.6.8: + resolution: {integrity: sha512-OtrCRUE7VqRyKly9E3gfExZHOAHtFDpmulyVFKrnl3v/n2xJckdueVumWJqUA5FHxcRP/T42r8P8CDr9duPP9w==} + engines: {node: '>=16.14'} hasBin: true dev: true - /postcss-value-parser/4.2.0: + /polka@0.5.2: + resolution: {integrity: sha512-FVg3vDmCqP80tOrs+OeNlgXYmFppTXdjD5E7I4ET1NjvtNmQrb1/mJibybKkb/d4NA7YWAr1ojxuhpL3FHqdlw==} + dependencies: + '@polka/url': 0.5.0 + trouter: 2.0.1 + dev: true + + /postcss-import@15.1.0(postcss@8.4.27): + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + dependencies: + postcss: 8.4.27 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.2 + dev: false + + /postcss-js@4.0.1(postcss@8.4.27): + 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.27 + dev: false + + /postcss-load-config@4.0.1(postcss@8.4.27)(ts-node@10.9.1): + resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + postcss: 8.4.27 + ts-node: 10.9.1(@types/node@18.16.0)(typescript@5.1.3) + yaml: 2.2.2 + dev: false + + /postcss-nested@6.0.1(postcss@8.4.27): + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + dependencies: + postcss: 8.4.27 + postcss-selector-parser: 6.0.13 + dev: false + + /postcss-selector-parser@6.0.13: + resolution: {integrity: sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: false + + /postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true + dev: false - /postcss/8.4.20: - resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==} + /postcss@8.4.27: + resolution: {integrity: sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.3.4 + nanoid: 3.3.6 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true - /postcss/8.4.21: - resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.4 - picocolors: 1.0.0 - source-map-js: 1.0.2 - dev: true - - /preact/10.11.0: + /preact@10.11.0: resolution: {integrity: sha512-Fk6+vB2kb6mSJfDgODq0YDhMfl0HNtK5+Uc9QqECO4nlyPAQwCI+BKyWO//idA7ikV7o+0Fm6LQmNuQi1wXI1w==} dev: true - /prelude-ls/1.1.2: + /prelude-ls@1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} dev: true - /prelude-ls/1.2.1: + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} dev: true - /prettier-plugin-jsdoc/0.4.2_prettier@2.7.1: + /prettier-plugin-jsdoc@0.4.2(prettier@2.8.8): resolution: {integrity: sha512-w2jnAQm3z0GAG0bhzVJeehzDtrhGMSxJjit5ApCc2oxWfc7+jmLAkbtdOXaSpfwZz3IWkk+PiQPeRrLNpbM+Mw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -9982,46 +13040,62 @@ packages: dependencies: binary-searching: 2.0.5 comment-parser: 1.3.1 - mdast-util-from-markdown: 1.2.0 - prettier: 2.7.1 + mdast-util-from-markdown: 1.3.0 + prettier: 2.8.8 transitivePeerDependencies: - supports-color dev: true - /prettier/2.7.1: - resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==} + /prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} engines: {node: '>=10.13.0'} 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-format/27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 + /pretty-bytes@6.1.0: + resolution: {integrity: sha512-Rk753HI8f4uivXi4ZCIYdhmG1V+WKzvRMg/X+M42a6t7D07RcmopXJMDNk6N++7Bl75URRGsb40ruvg7Hcp2wQ==} + engines: {node: ^14.13.1 || >=16.0.0} dev: true - /pretty-format/29.3.1: - resolution: {integrity: sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==} + /pretty-format@29.5.0: + resolution: {integrity: sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@jest/schemas': 29.0.0 + '@jest/schemas': 29.4.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 - /prompts/2.4.2: + /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@2.2.0: + resolution: {integrity: sha512-/1WZ8+VQjR6avWOgHeEPd7SDQmFQ1B5mC1eRXsCm5TarlNmx/wCsa5GEaxGm05BORRtyG/Ex/3xq3TuRvq57qg==} + dev: false + + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: false + + /prompts@2.4.2: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} dependencies: @@ -10029,7 +13103,7 @@ packages: sisteransi: 1.0.5 dev: true - /proxy-addr/2.0.7: + /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} dependencies: @@ -10037,31 +13111,11 @@ packages: ipaddr.js: 1.9.1 dev: true - /proxy-agent/5.0.0: - resolution: {integrity: sha512-gkH7BkvLVkSfX9Dk27W6TyNOWWZWRilRfk1XxGNWOYJ2TuedAv1yFpCaU9QSBmBe716XOTNpYNOzhysyw8xn7g==} - engines: {node: '>= 8'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - lru-cache: 5.1.1 - pac-proxy-agent: 5.0.0 - proxy-from-env: 1.1.0 - socks-proxy-agent: 5.0.1 - transitivePeerDependencies: - - supports-color - 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: - 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 @@ -10069,69 +13123,79 @@ packages: event-stream: 3.3.4 dev: true - /psl/1.9.0: + /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true - /pump/3.0.0: + /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/2.1.1: - resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} + /punycode@2.3.0: + resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} dev: true - /q/1.5.1: + /pure-rand@6.0.2: + resolution: {integrity: sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==} + dev: true + + /q@1.5.1: resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} engines: {node: '>=0.6.0', teleport: '>=0.2.0'} dev: true - /qs/6.11.0: + /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} dependencies: side-channel: 1.0.4 dev: true - /qs/6.5.3: + /qs@6.5.3: resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} engines: {node: '>=0.6'} dev: true - /querystringify/2.2.0: + /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: true - /queue-microtask/1.2.3: + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - /quick-lru/4.0.1: + /quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + /quick-lru@4.0.1: resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} engines: {node: '>=8'} dev: true - /quick-lru/5.1.1: + /quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} dev: true - /randombytes/2.1.0: + /ramda@0.28.0: + resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==} + dev: false + + /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: + /raw-body@2.5.1: resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} engines: {node: '>= 0.8'} dependencies: @@ -10141,15 +13205,17 @@ packages: unpipe: 1.0.0 dev: true - /react-is/17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - dev: true - - /react-is/18.2.0: + /react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true - /read-pkg-up/7.0.1: + /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: @@ -10158,7 +13224,7 @@ packages: type-fest: 0.8.1 dev: true - /read-pkg-up/8.0.0: + /read-pkg-up@8.0.0: resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==} engines: {node: '>=12'} dependencies: @@ -10167,7 +13233,7 @@ packages: type-fest: 1.4.0 dev: true - /read-pkg/5.2.0: + /read-pkg@5.2.0: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} dependencies: @@ -10177,7 +13243,7 @@ packages: type-fest: 0.6.0 dev: true - /read-pkg/6.0.0: + /read-pkg@6.0.0: resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==} engines: {node: '>=12'} dependencies: @@ -10187,16 +13253,7 @@ packages: type-fest: 1.4.0 dev: true - /readable-stream/1.1.14: - resolution: {integrity: sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 0.0.1 - string_decoder: 0.10.31 - dev: true - - /readable-stream/2.3.7: + /readable-stream@2.3.7: resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} dependencies: core-util-is: 1.0.3 @@ -10208,7 +13265,7 @@ packages: util-deprecate: 1.0.2 dev: true - /readable-stream/3.6.0: + /readable-stream@3.6.0: resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} engines: {node: '>= 6'} dependencies: @@ -10217,21 +13274,35 @@ packages: util-deprecate: 1.0.2 dev: true - /readdirp/3.6.0: + /readable-stream@4.4.0: + resolution: {integrity: sha512-kDMOq0qLtxV9f/SQv522h8cxZBqNZXuXNyjyezmfAAuribMyVXziljpQ/uQhfE1XLg2/TLTW2DsnoE4VAi/krg==} + 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 + dev: false + + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 - dev: true - /rechoir/0.7.1: + /real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + dev: false + + /rechoir@0.7.1: resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==} engines: {node: '>= 0.10'} dependencies: - resolve: 1.22.1 + resolve: 1.22.2 dev: true - /redent/3.0.0: + /redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} dependencies: @@ -10239,7 +13310,7 @@ packages: strip-indent: 3.0.0 dev: true - /redent/4.0.0: + /redent@4.0.0: resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==} engines: {node: '>=12'} dependencies: @@ -10247,24 +13318,75 @@ packages: strip-indent: 4.0.0 dev: true - /regexp-tree/0.1.24: + /regenerate-unicode-properties@10.1.0: + resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: true + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true + + /regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: true + + /regenerator-transform@0.15.1: + resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} + dependencies: + '@babel/runtime': 7.21.0 + dev: true + + /regexp-tree@0.1.24: resolution: {integrity: sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==} hasBin: true dev: true - /regexpp/3.2.0: - resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} - engines: {node: '>=8'} + /regexp.prototype.flags@1.4.3: + resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + functions-have-names: 1.2.3 dev: true - /regjsparser/0.9.1: + /regexpu-core@5.3.1: + resolution: {integrity: sha512-nCOzW2V/X15XpLsK2rlgdwrysrBq+AauCn+omItIz4R1pIcmeot5zvjdmOBRLzEH/CkC6IxMJVmxDe3QcMuNVQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.0 + 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==} + 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 - /remark-frontmatter/4.0.1: + /release-zalgo@1.0.0: + resolution: {integrity: sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==} + engines: {node: '>=4'} + dependencies: + es6-error: 4.1.1 + dev: true + + /remark-frontmatter@4.0.1: resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} dependencies: '@types/mdast': 3.0.10 @@ -10273,7 +13395,7 @@ packages: unified: 10.1.2 dev: true - /remark-gfm/3.0.1: + /remark-gfm@3.0.1: resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} dependencies: '@types/mdast': 3.0.10 @@ -10284,25 +13406,25 @@ packages: - supports-color dev: true - /remark-parse/10.0.1: + /remark-parse@10.0.1: resolution: {integrity: sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==} dependencies: - '@types/mdast': 3.0.10 - mdast-util-from-markdown: 1.2.0 + '@types/mdast': 3.0.11 + mdast-util-from-markdown: 1.3.0 unified: 10.1.2 transitivePeerDependencies: - supports-color dev: true - /remark-stringify/10.0.2: + /remark-stringify@10.0.2: resolution: {integrity: sha512-6wV3pvbPvHkbNnWB0wdDvVFHOe1hBRAx1Q/5g/EpH4RppAII6J8Gnwe7VbHuXaoKIF6LAg6ExTel/+kNqSQ7lw==} dependencies: - '@types/mdast': 3.0.10 + '@types/mdast': 3.0.11 mdast-util-to-markdown: 1.3.0 unified: 10.1.2 dev: true - /remark/14.0.2: + /remark@14.0.2: resolution: {integrity: sha512-A3ARm2V4BgiRXaUo5K0dRvJ1lbogrbXnhkJRmD0yw092/Yl0kOCZt1k9ZeElEwkZsWGsMumz6qL5MfNJH9nOBA==} dependencies: '@types/mdast': 3.0.10 @@ -10313,99 +13435,76 @@ packages: - 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.0 dev: true - /request/2.88.2: - resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} - engines: {node: '>= 6'} - deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 - dependencies: - aws-sign2: 0.7.0 - aws4: 1.11.0 - caseless: 0.12.0 - combined-stream: 1.0.8 - extend: 3.0.2 - forever-agent: 0.6.1 - form-data: 2.3.3 - har-validator: 5.1.5 - http-signature: 1.2.0 - is-typedarray: 1.0.0 - isstream: 0.1.2 - json-stringify-safe: 5.0.1 - mime-types: 2.1.35 - oauth-sign: 0.9.0 - performance-now: 2.1.0 - qs: 6.5.3 - safe-buffer: 5.2.1 - tough-cookie: 2.5.0 - tunnel-agent: 0.6.0 - uuid: 3.4.0 - dev: true - - /require-directory/2.1.1: + /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 - /requires-port/1.0.0: + /require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + dev: 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-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-global/1.0.0: + /resolve-global@1.0.0: resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==} engines: {node: '>=8'} dependencies: global-dirs: 0.1.1 dev: true - /resolve.exports/1.1.0: - resolution: {integrity: sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==} + /resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} dev: true - /resolve/1.19.0: + /resolve@1.19.0: resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} dependencies: - is-core-module: 2.10.0 + is-core-module: 2.12.1 path-parse: 1.0.7 dev: true - /resolve/1.22.1: + /resolve@1.22.1: resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} hasBin: true dependencies: @@ -10414,13 +13513,21 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true - /responselike/2.0.1: + /resolve@1.22.2: + resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} + hasBin: true + dependencies: + is-core-module: 2.12.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + /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: @@ -10428,46 +13535,65 @@ packages: signal-exit: 3.0.7 dev: true - /retry/0.13.1: + /ret@0.2.2: + resolution: {integrity: sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==} + engines: {node: '>=4'} + dev: true + + /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'} - dev: true - /rfdc/1.3.0: + /rfdc@1.3.0: resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} dev: true - /rimraf/2.7.1: + /rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true dependencies: glob: 7.2.3 dev: true - /rimraf/3.0.2: + /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: glob: 7.2.3 dev: true - /rimraf/4.1.2: - resolution: {integrity: sha512-BlIbgFryTbw3Dz6hyoWFhKk+unCcHMSkZGrTFVAx2WmttdBSonsdtRlwiuTbDqTKr+UlXIUqJVS4QT5tUzGENQ==} + /rimraf@5.0.0: + resolution: {integrity: sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==} engines: {node: '>=14'} hasBin: true + dependencies: + glob: 10.2.2 dev: true - /robust-predicates/3.0.1: + /robust-predicates@3.0.1: resolution: {integrity: sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g==} dev: false - /rollup-plugin-visualizer/5.8.3: - resolution: {integrity: sha512-QGJk4Bqe4AOat5AjipOh8esZH1nck5X2KFpf4VytUdSUuuuSwvIQZjMGgjcxe/zXexltqaXp5Vx1V3LmnQH15Q==} + /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.18.6 + jest-worker: 26.6.2 + rollup: 2.79.1 + serialize-javascript: 4.0.0 + terser: 5.19.2 + dev: true + + /rollup-plugin-visualizer@5.9.2: + resolution: {integrity: sha512-waHktD5mlWrYFrhOLbti4YgQCn1uR24nYsNuXxg7LkPH8KdTXVWR9DNY1WU0QqokyMixVXJS4J04HNrVTMP01A==} engines: {node: '>=14'} hasBin: true peerDependencies: @@ -10477,11 +13603,12 @@ packages: optional: true dependencies: open: 8.4.0 + picomatch: 2.3.1 source-map: 0.7.4 - yargs: 17.5.1 + yargs: 17.7.2 dev: true - /rollup/2.79.1: + /rollup@2.79.1: resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} engines: {node: '>=10.0.0'} hasBin: true @@ -10489,115 +13616,143 @@ packages: fsevents: 2.3.2 dev: true - /rollup/3.15.0: - resolution: {integrity: sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==} + /rollup@3.28.0: + resolution: {integrity: sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==} engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: fsevents: 2.3.2 dev: true - /run-parallel/1.2.0: + /rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + dev: true + + /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 - dev: true - /rw/1.3.3: + /rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} dev: false - /rxjs/7.5.6: - resolution: {integrity: sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==} - dependencies: - tslib: 2.4.0 - dev: true - - /rxjs/7.8.0: + /rxjs@7.8.0: resolution: {integrity: sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==} dependencies: tslib: 2.4.0 dev: true - /sade/1.8.1: + /sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} dependencies: mri: 1.2.0 - 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==} dev: true - /safe-regex/2.1.1: + /safe-regex-test@1.0.0: + resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.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@2.1.1: resolution: {integrity: sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==} dependencies: regexp-tree: 0.1.24 dev: true - /safer-buffer/2.1.2: + /safe-stable-stringify@2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} + dev: false + + /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - /saxes/5.0.1: + /saxes@5.0.1: resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} engines: {node: '>=10'} dependencies: xmlchars: 2.2.0 dev: true - /saxes/6.0.0: + /saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} dependencies: xmlchars: 2.2.0 dev: true - /schema-utils/3.1.1: - resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} + /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.11 ajv: 6.12.6 - ajv-keywords: 3.5.2_ajv@6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) dev: true - /schema-utils/4.0.0: + /schema-utils@4.0.0: resolution: {integrity: sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==} engines: {node: '>= 12.13.0'} dependencies: '@types/json-schema': 7.0.11 - ajv: 8.11.0 - ajv-formats: 2.1.1_ajv@8.11.0 - ajv-keywords: 5.1.0_ajv@8.11.0 + ajv: 8.12.0 + ajv-formats: 2.1.1(ajv@8.12.0) + ajv-keywords: 5.1.0(ajv@8.12.0) dev: true - /select-hose/2.0.0: + /search-insights@2.6.0: + resolution: {integrity: sha512-vU2/fJ+h/Mkm/DJOe+EaM5cafJv/1rRTZpGJTuFPf/Q5LjzgMDsqPdSaZsAe+GAWHHsfsu+rQSAn6c8IGtBEVw==} + engines: {node: '>=8.16.0'} + dev: true + + /secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + dev: true + + /select-hose@2.0.0: resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} dev: true - /selfsigned/2.1.1: + /selfsigned@2.1.1: resolution: {integrity: sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==} engines: {node: '>=10'} dependencies: node-forge: 1.3.1 dev: true - /semver/5.7.1: + /semver-store@0.3.0: + resolution: {integrity: sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==} + dev: true + + /semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true dev: true - /semver/6.3.0: + /semver@6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true dev: true - /semver/7.3.7: + /semver@7.3.7: resolution: {integrity: sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==} engines: {node: '>=10'} hasBin: true @@ -10605,7 +13760,7 @@ packages: lru-cache: 6.0.0 dev: true - /semver/7.3.8: + /semver@7.3.8: resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} engines: {node: '>=10'} hasBin: true @@ -10613,7 +13768,23 @@ packages: lru-cache: 6.0.0 dev: true - /send/0.18.0: + /semver@7.5.0: + resolution: {integrity: sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /semver@7.5.3: + resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /send@0.18.0: resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} engines: {node: '>= 0.8.0'} dependencies: @@ -10634,13 +13805,19 @@ packages: - supports-color dev: true - /serialize-javascript/6.0.0: - resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} + /serialize-javascript@4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} dependencies: randombytes: 2.1.0 dev: true - /serve-index/1.9.1: + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: true + + /serve-index@1.9.1: resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} engines: {node: '>= 0.8.0'} dependencies: @@ -10655,7 +13832,7 @@ packages: - supports-color dev: true - /serve-static/1.15.0: + /serve-static@1.15.0: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} engines: {node: '>= 0.8.0'} dependencies: @@ -10667,58 +13844,58 @@ packages: - supports-color dev: true - /setprototypeof/1.1.0: + /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 + + /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: + /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 dev: true - /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'} dev: true - /shell-quote/1.7.3: - resolution: {integrity: sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==} + /shell-quote@1.8.1: + resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} dev: true - /shiki/0.11.1: - resolution: {integrity: sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==} - dependencies: - jsonc-parser: 3.2.0 - vscode-oniguruma: 1.6.2 - vscode-textmate: 6.0.0 - dev: true - - /shiki/0.14.1: + /shiki@0.14.1: resolution: {integrity: sha512-+Jz4nBkCBe0mEDqo1eKRcCdjRtrCjozmcbTUjbPTX7OOJfEbTZzlUWlZtGe3Gb5oV1/jnojhG//YZc3rs9zSEw==} dependencies: ansi-sequence-parser: 1.1.0 @@ -10727,24 +13904,44 @@ packages: vscode-textmate: 8.0.0 dev: true - /side-channel/1.0.4: + /shiki@0.14.3: + resolution: {integrity: sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==} + dependencies: + ansi-sequence-parser: 1.1.0 + jsonc-parser: 3.2.0 + vscode-oniguruma: 1.7.0 + vscode-textmate: 8.0.0 + dev: true + + /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.0 object-inspect: 1.12.2 dev: true - /siginfo/2.0.0: + /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 - /sirv/2.0.2: - resolution: {integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==} + /signal-exit@4.0.1: + resolution: {integrity: sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==} + engines: {node: '>=14'} + dev: true + + /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.3: + resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==} engines: {node: '>= 10'} dependencies: '@polka/url': 1.0.0-next.21 @@ -10752,21 +13949,21 @@ packages: totalist: 3.0.0 dev: true - /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 - /slice-ansi/3.0.0: + /slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} dependencies: @@ -10775,7 +13972,7 @@ packages: 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: @@ -10784,7 +13981,7 @@ packages: 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: @@ -10792,12 +13989,7 @@ packages: is-fullwidth-code-point: 4.0.0 dev: true - /smart-buffer/4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: true - - /sockjs/0.3.24: + /sockjs@0.3.24: resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} dependencies: faye-websocket: 0.11.4 @@ -10805,45 +13997,38 @@ packages: websocket-driver: 0.7.4 dev: true - /socks-proxy-agent/5.0.1: - resolution: {integrity: sha512-vZdmnjb9a2Tz6WEQVIurybSwElwPxMZaIc7PzqbJTrezcKNznv6giT7J7tZDZ1BojVaa1jvO/UiUdhDVB0ACoQ==} - engines: {node: '>= 6'} + /sonic-boom@1.4.1: + resolution: {integrity: sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==} dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - socks: 2.7.0 - transitivePeerDependencies: - - supports-color + atomic-sleep: 1.0.0 + flatstr: 1.0.12 dev: true - /socks/2.7.0: - resolution: {integrity: sha512-scnOe9y4VuiNUULJN72GrM26BNOjVsfPXI+j+98PkyEfsIXroa5ofyjT+FzGvn/xHs73U2JtoBYAVx9Hl4quSA==} - engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} + /sonic-boom@3.3.0: + resolution: {integrity: sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==} dependencies: - ip: 2.0.0 - smart-buffer: 4.2.0 - dev: true + atomic-sleep: 1.0.0 + dev: false - /source-map-js/1.0.2: + /source-map-js@1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} - dev: true - /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 @@ -10852,56 +14037,75 @@ packages: dev: true optional: true - /source-map/0.5.7: + /source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} dev: 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 - /sourcemap-codec/1.4.8: + /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: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead dev: true - /spawn-command/0.0.2-1: + /spawn-command@0.0.2-1: resolution: {integrity: sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==} dev: true - /spdx-correct/3.1.1: + /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.1.1: resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} dependencies: spdx-expression-parse: 3.0.1 spdx-license-ids: 3.0.12 dev: true - /spdx-exceptions/2.3.0: + /spdx-exceptions@2.3.0: resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} dev: true - /spdx-expression-parse/3.0.1: + /spdx-expression-parse@3.0.1: resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} dependencies: spdx-exceptions: 2.3.0 spdx-license-ids: 3.0.12 dev: true - /spdx-license-ids/3.0.12: + /spdx-license-ids@3.0.12: resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} dev: true - /spdy-transport/3.0.0: + /spdy-transport@3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} dependencies: - debug: 4.3.4 + debug: 4.3.4(supports-color@8.1.1) detect-node: 2.1.0 hpack.js: 2.1.6 obuf: 1.1.2 @@ -10911,11 +14115,11 @@ packages: - 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 + debug: 4.3.4(supports-color@8.1.1) handle-thing: 2.0.1 http-deceiver: 1.2.7 select-hose: 2.0.0 @@ -10924,23 +14128,28 @@ packages: - supports-color dev: true - /split/0.3.3: - resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} - dependencies: - through: 2.3.8 - dev: true - - /split2/3.2.2: + /split2@3.2.2: resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} dependencies: readable-stream: 3.6.0 dev: true - /sprintf-js/1.0.3: + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: false + + /split@0.3.3: + resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} + dependencies: + through: 2.3.8 + dev: true + + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true - /sshpk/1.17.0: + /sshpk@1.17.0: resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} engines: {node: '>=0.10.0'} hasBin: true @@ -10956,80 +14165,64 @@ packages: 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.5: + /stack-utils@2.0.5: resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} 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/1.14.0: - resolution: {integrity: sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw==} - engines: {node: '>=6'} - hasBin: true - dependencies: - bluebird: 3.7.2 - check-more-types: 2.24.0 - debug: 4.3.2 - execa: 5.1.1 - lazy-ass: 1.6.0 - ps-tree: 1.2.0 - wait-on: 6.0.0_debug@4.3.2 - transitivePeerDependencies: - - supports-color - dev: true - - /start-server-and-test/1.15.4: - resolution: {integrity: sha512-ucQtp5+UCr0m4aHlY+aEV2JSYNTiMZKdSKK/bsIr6AlmwAWDYDnV7uGlWWEtWa7T4XvRI5cPYcPcQgeLqpz+Tg==} + /start-server-and-test@2.0.0: + resolution: {integrity: sha512-UqKLw0mJbfrsG1jcRLTUlvuRi9sjNuUiDOLI42r7R5fA9dsFoywAy9DoLXNYys9B886E4RCKb+qM1Gzu96h7DQ==} engines: {node: '>=6'} hasBin: true dependencies: arg: 5.0.2 bluebird: 3.7.2 check-more-types: 2.24.0 - debug: 4.3.4 + 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.0.1_debug@4.3.4 + wait-on: 7.0.1(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.3.2: - resolution: {integrity: sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==} + /std-env@3.3.3: + resolution: {integrity: sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==} dev: true - /stream-combiner/0.0.4: + /stream-combiner@0.0.4: resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} dependencies: duplexer: 0.1.2 dev: true - /string-argv/0.3.1: + /string-argv@0.3.1: resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==} 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: @@ -11037,7 +14230,12 @@ packages: strip-ansi: 6.0.1 dev: true - /string-width/4.2.3: + /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: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} dependencies: @@ -11046,7 +14244,7 @@ packages: strip-ansi: 6.0.1 dev: true - /string-width/5.1.2: + /string-width@5.1.2: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} dependencies: @@ -11055,133 +14253,255 @@ packages: strip-ansi: 7.0.1 dev: true - /string_decoder/0.10.31: - resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + /string.prototype.matchall@4.0.8: + resolution: {integrity: sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.1 + get-intrinsic: 1.2.0 + has-symbols: 1.0.3 + internal-slot: 1.0.5 + regexp.prototype.flags: 1.4.3 + side-channel: 1.0.4 dev: true - /string_decoder/1.1.1: + /string.prototype.trimend@1.0.6: + resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.1 + dev: true + + /string.prototype.trimstart@1.0.6: + resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 + es-abstract: 1.21.1 + dev: true + + /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 dev: true - /strip-ansi/3.0.1: + /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: 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 dev: true - /strip-ansi/7.0.1: + /strip-ansi@7.0.1: resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==} engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 dev: true - /strip-bom/4.0.0: + /strip-bom@4.0.0: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} dev: true - /strip-eof/1.0.0: + /strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} + engines: {node: '>=10'} + dev: true + + /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: + /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: + /strip-indent@4.0.0: resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==} engines: {node: '>=12'} dependencies: min-indent: 1.0.1 dev: true - /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/1.0.0: - resolution: {integrity: sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==} + /strip-literal@1.0.1: + resolution: {integrity: sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==} dependencies: - acorn: 8.8.1 + acorn: 8.10.0 dev: true - /stylis/4.1.2: - resolution: {integrity: sha512-Nn2CCrG2ZaFziDxaZPN43CXqn+j7tcdjPFCkRBkFue8QYXC2HdEwnw5TCBo4yQZ2WxKYeSi0fdoOrtEqgDrXbA==} + /stylis@4.1.3: + resolution: {integrity: sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==} dev: false - /supports-color/2.0.0: + /sucrase@3.32.0: + resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==} + engines: {node: '>=8'} + hasBin: true + dependencies: + '@jridgewell/gen-mapping': 0.3.2 + commander: 4.1.1 + glob: 7.1.6 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.5 + ts-interface-checker: 0.1.13 + dev: false + + /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 - dev: true - /supports-preserve-symlinks-flag/1.0.0: + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - dev: true - /symbol-tree/3.2.4: + /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true - /tapable/2.2.1: + /synckit@0.8.5: + resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/utils': 2.3.1 + tslib: 2.5.0 + dev: true + + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: true + + /tailwindcss@3.3.2(ts-node@10.9.1): + resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.19.1 + 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.27 + postcss-import: 15.1.0(postcss@8.4.27) + postcss-js: 4.0.1(postcss@8.4.27) + postcss-load-config: 4.0.1(postcss@8.4.27)(ts-node@10.9.1) + postcss-nested: 6.0.1(postcss@8.4.27) + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + resolve: 1.22.2 + sucrase: 3.32.0 + transitivePeerDependencies: + - ts-node + dev: false + + /tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} dev: true - /term-img/4.1.0: + /teen_process@1.16.0: + resolution: {integrity: sha512-RnW7HHZD1XuhSTzD3djYOdIl1adE3oNEprE3HOFFxWs5m4FZsqYRhKJ4mDU2udtNGMLUS7jV7l8vVRLWAvmPDw==} + engines: {'0': node} + dependencies: + '@babel/runtime': 7.21.0 + 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: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + dev: true + + /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: resolution: {integrity: sha512-DFpBhaF5j+2f7kheKFc1ajsAUUDGOaNPpKPtiIMxlbfud6mvfFZuWGnTRpaujUa5J7yl6cIw/h6nyr4mSsENPg==} engines: {node: '>=8'} dependencies: @@ -11189,8 +14509,8 @@ packages: iterm2-version: 4.2.0 dev: true - /terser-webpack-plugin/5.3.6_webpack@5.75.0: - resolution: {integrity: sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==} + /terser-webpack-plugin@5.3.9(esbuild@0.19.0)(webpack@5.88.2): + resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -11205,26 +14525,27 @@ packages: uglify-js: optional: true dependencies: - '@jridgewell/trace-mapping': 0.3.15 + '@jridgewell/trace-mapping': 0.3.17 + esbuild: 0.19.0 jest-worker: 27.5.1 - schema-utils: 3.1.1 - serialize-javascript: 6.0.0 - terser: 5.15.1 - webpack: 5.75.0_webpack-cli@4.10.0 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.19.2 + webpack: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) dev: true - /terser/5.15.1: - resolution: {integrity: sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==} + /terser@5.19.2: + resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==} engines: {node: '>=10'} hasBin: true dependencies: - '@jridgewell/source-map': 0.3.2 - acorn: 8.8.1 + '@jridgewell/source-map': 0.3.5 + acorn: 8.10.0 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: @@ -11233,138 +14554,204 @@ packages: minimatch: 3.1.2 dev: true - /text-extensions/1.9.0: + /text-extensions@1.9.0: resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==} engines: {node: '>=0.10'} dev: true - /text-table/0.2.0: + /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} dev: true - /throat/6.0.1: + /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: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + + /thread-stream@2.3.0: + resolution: {integrity: sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==} + dependencies: + real-require: 0.2.0 + dev: false + + /throat@6.0.1: resolution: {integrity: sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==} dev: true - /throttleit/1.0.0: + /throat@6.0.2: + resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} + dev: true + + /throttleit@1.0.0: resolution: {integrity: sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==} dev: true - /through/2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: true - - /through2/4.0.2: + /through2@4.0.2: resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} dependencies: readable-stream: 3.6.0 dev: true - /thunky/1.1.0: + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} dev: true - /tinybench/2.3.1: - resolution: {integrity: sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==} + /timers-ext@0.1.7: + resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} + dependencies: + es5-ext: 0.10.62 + next-tick: 1.1.0 dev: true - /tinypool/0.3.1: - resolution: {integrity: sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==} + /tiny-glob@0.2.9: + resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} + dependencies: + globalyzer: 0.1.0 + globrex: 0.1.2 + dev: true + + /tiny-lru@8.0.2: + resolution: {integrity: sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg==} + engines: {node: '>=6'} + dev: true + + /tinybench@2.5.0: + resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} + dev: true + + /tinypool@0.7.0: + resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==} engines: {node: '>=14.0.0'} dev: true - /tinyspy/1.0.2: - resolution: {integrity: sha512-bSGlgwLBYf7PnUsQ6WOc6SJ3pGOcd+d8AA6EUnLDDM0kWEstC1JIlSZA3UNliDXhd9ABoS7hiRBDCu+XP/sf1Q==} + /tinyspy@2.1.1: + resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==} engines: {node: '>=14.0.0'} dev: true - /tmp/0.2.1: + /tmp@0.2.1: resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} engines: {node: '>=8.17.0'} dependencies: rimraf: 3.0.2 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: + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} - dev: true - /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 - dev: true - /toidentifier/1.0.1: + /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} dev: true - /totalist/3.0.0: + /totalist@3.0.0: resolution: {integrity: sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==} engines: {node: '>=6'} dev: true - /tough-cookie/2.5.0: + /tough-cookie@2.5.0: resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} engines: {node: '>=0.8'} dependencies: psl: 1.9.0 - punycode: 2.1.1 + punycode: 2.3.0 dev: true - /tough-cookie/4.1.2: + /tough-cookie@4.1.2: resolution: {integrity: sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==} engines: {node: '>=6'} dependencies: psl: 1.9.0 - punycode: 2.1.1 + punycode: 2.3.0 universalify: 0.2.0 url-parse: 1.5.10 dev: true - /tr46/0.0.3: + /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} dev: true - /tr46/3.0.0: + /tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + dependencies: + punycode: 2.3.0 + dev: true + + /tr46@3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} dependencies: - punycode: 2.1.1 + punycode: 2.3.0 dev: true - /tree-kill/1.2.2: + /tr46@4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + dependencies: + punycode: 2.3.0 + dev: true + + /traverse@0.3.9: + resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} + dev: true + + /tree-kill@1.2.2: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true dev: true - /trim-newlines/3.0.1: + /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} dev: true - /trim-newlines/4.0.2: + /trim-newlines@4.0.2: resolution: {integrity: sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==} engines: {node: '>=12'} dev: true - /trough/2.1.0: + /trough@2.1.0: resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} dev: true - /ts-dedent/2.2.0: + /trouter@2.0.1: + resolution: {integrity: sha512-kr8SKKw94OI+xTGOkfsvwZQ8mWoikZDd2n8XZHjJVZUARZT+4/VV6cacRS6CLsH9bNm+HFIPU1Zx4CnNnb4qlQ==} + engines: {node: '>=6'} + dependencies: + matchit: 1.1.0 + dev: true + + /ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} dev: false - /ts-node/10.9.1_w6ufic3jqylcjznzspnj4wjqfe: + /ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + dev: false + + /ts-node@10.9.1(@types/node@18.16.0)(typescript@5.1.3): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -11383,137 +14770,123 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.3 - '@types/node': 18.11.9 - acorn: 8.8.0 + '@types/node': 18.16.0 + acorn: 8.8.2 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 4.9.5 + typescript: 5.1.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true - /ts-node/10.9.1_yxpazyh7n5pql7jdaglasgwqki: - resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 - '@types/node': 14.18.29 - acorn: 8.8.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 4.9.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true + /ts-toolbelt@6.15.5: + resolution: {integrity: sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==} + dev: false - /tslib/1.14.1: + /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: true - /tslib/2.4.0: + /tslib@2.4.0: resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} dev: true - /tsutils/3.21.0_typescript@4.8.4: + /tslib@2.5.0: + resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + dev: true + + /tsutils@3.21.0(typescript@5.0.4): 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: 4.8.4 + typescript: 5.0.4 dev: true - /tsutils/3.21.0_typescript@4.9.5: + /tsutils@3.21.0(typescript@5.1.3): 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: 4.9.5 + typescript: 5.1.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: + /tweetnacl@0.14.5: resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} dev: true - /type-check/0.3.2: + /type-check@0.3.2: resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.1.2 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.18.1: + /type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.18.1: resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} 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: + /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: + /type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} dev: true - /type-is/1.6.18: + /type-fest@4.1.0: + resolution: {integrity: sha512-VJGJVepayd8OWavP+rgXt4i3bfLk+tSomTV7r4mca2XD/oTCWnkJlNkpXavkxdmtU2aKdAmFGeHvoQutOVHCZg==} + engines: {node: '>=16'} + dev: true + + /type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} dependencies: @@ -11521,68 +14894,132 @@ packages: mime-types: 2.1.35 dev: true - /typedarray-to-buffer/3.1.5: + /type@1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: true + + /type@2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.2 + for-each: 0.3.3 + is-typed-array: 1.1.10 + dev: true + + /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.13.6_typedoc@0.23.18: - resolution: {integrity: sha512-ISSc9v3BK7HkokxSBuJPttXox4tJ6hP0N9wfSIk0fmLN67+eqtAxbk97gs2nDiuha+RTO5eW9gdeAb+RPP0mgg==} + /typedoc-plugin-markdown@3.15.2(typedoc@0.25.0): + resolution: {integrity: sha512-OPXAL9hhdoVJzH/UaKAz6CBS/s8KlYyLWwnxF7ap0fQCuaMMWShA1JBq4n1SXbiGjx+7DOhOfTKQ5OzwryN3Vw==} peerDependencies: - typedoc: '>=0.23.0' + typedoc: '>=0.24.0' dependencies: handlebars: 4.7.7 - typedoc: 0.23.18_typescript@4.8.4 + typedoc: 0.25.0(typescript@5.0.4) + typedoc-plugin-mdn-links: 3.0.3(typedoc@0.25.0) dev: true - /typedoc/0.23.18_typescript@4.8.4: - resolution: {integrity: sha512-0Tq/uFkUuWyRYyjOShTkhsOm6u5E8wf0i6L76/k5znEaxvWKHGeT2ywZThGrDrryV/skO/REM824D1gm8ccQuA==} - engines: {node: '>= 14.14'} + /typedoc-plugin-mdn-links@3.0.3(typedoc@0.25.0): + resolution: {integrity: sha512-NXhIpwQnsg7BcyMCHVqj3tUK+DL4g3Bt96JbFl4APzTGFkA+iM6GfZ/fn3TAqJ8O0CXG5R9BfWxolw1m1omNuQ==} + peerDependencies: + typedoc: '>= 0.23.14 || 0.24.x' + dependencies: + typedoc: 0.25.0(typescript@5.0.4) + dev: true + + /typedoc@0.25.0(typescript@5.0.4): + resolution: {integrity: sha512-FvCYWhO1n5jACE0C32qg6b3dSfQ8f2VzExnnRboowHtqUD6ARzM2r8YJeZFYXhcm2hI4C2oCRDgNPk/yaQUN9g==} + engines: {node: '>= 16'} hasBin: true peerDependencies: - typescript: 4.6.x || 4.7.x || 4.8.x + typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x dependencies: lunr: 2.3.9 - marked: 4.1.1 - minimatch: 5.1.0 - shiki: 0.11.1 - typescript: 4.8.4 + marked: 4.3.0 + minimatch: 9.0.3 + shiki: 0.14.3 + typescript: 5.0.4 dev: true - /typescript/4.8.4: - resolution: {integrity: sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==} - engines: {node: '>=4.2.0'} + /typescript@5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} + engines: {node: '>=12.20'} hasBin: true dev: true - /typescript/4.9.5: - resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==} - engines: {node: '>=4.2.0'} + /typescript@5.1.3: + resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==} + engines: {node: '>=14.17'} hasBin: true - dev: true - /uc.micro/1.0.6: + /uc.micro@1.0.6: resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} dev: true - /ufo/1.0.1: - resolution: {integrity: sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==} + /ufo@1.1.2: + resolution: {integrity: sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==} dev: true - /uglify-js/3.17.3: + /uglify-js@3.17.3: resolution: {integrity: sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==} engines: {node: '>=0.8.0'} hasBin: true requiresBuild: true dev: true - optional: true - /underscore/1.1.7: + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.2 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /unconfig@0.3.10: + resolution: {integrity: sha512-tj317lhIq2iZF/NXrJnU1t2UaGUKKz1eL1sK2t63Oq66V9BxqvZV12m55fp/fpQJ+DDmVlLgo7cnLVOZkhlO/A==} + dependencies: + '@antfu/utils': 0.7.5 + defu: 6.1.2 + jiti: 1.19.1 + mlly: 1.4.0 + dev: true + + /underscore@1.1.7: resolution: {integrity: sha512-w4QtCHoLBXw1mjofIDoMyexaEdWGMedWNDhlWTtT1V1lCRqi65Pnoygkh6+WRdr+Bm8ldkBNkNeCsXGMlQS9HQ==} dev: true - /unified/10.1.2: + /unicode-canonical-property-names-ecmascript@2.0.0: + resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + engines: {node: '>=4'} + dev: true + + /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==} + engines: {node: '>=4'} + dev: true + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: true + + /unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} dependencies: '@types/unist': 2.0.6 @@ -11594,123 +15031,203 @@ packages: vfile: 5.3.5 dev: true - /unique-string/2.0.0: + /unique-string@2.0.0: resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} engines: {node: '>=8'} dependencies: crypto-random-string: 2.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-is/5.1.1: + /unist-util-inspect@7.0.1: + resolution: {integrity: sha512-gEPeSrsYXus8012VJ00p9uZC8D0iogtLLiHlBgvS61hU22KNKduQhMKezJm83viHlLf3TYS2y9SDEFglWPDMKw==} + dependencies: + '@types/unist': 2.0.6 + dev: true + + /unist-util-is@5.1.1: resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==} dev: true - /unist-util-stringify-position/2.0.3: + /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} dependencies: '@types/unist': 2.0.6 dev: true - /unist-util-stringify-position/3.0.2: + /unist-util-stringify-position@3.0.2: resolution: {integrity: sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==} dependencies: '@types/unist': 2.0.6 - dev: true - /unist-util-visit-parents/5.1.1: + /unist-util-visit-parents@5.1.1: resolution: {integrity: sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==} dependencies: '@types/unist': 2.0.6 unist-util-is: 5.1.1 dev: true - /unist-util-visit/4.1.1: - resolution: {integrity: sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==} + /unist-util-visit@4.1.2: + resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} dependencies: '@types/unist': 2.0.6 unist-util-is: 5.1.1 unist-util-visit-parents: 5.1.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: + /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} dev: true - /universalify/2.0.0: + /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} dev: true - /unpipe/1.0.0: + /unocss@0.55.2(postcss@8.4.27)(rollup@2.79.1)(vite@4.3.9): + resolution: {integrity: sha512-+C8tFUFIEv40DpEhjA/Yv+RB5HZumkWiON2OlPyrbzapQ8x60F9TUwUS3pw7MlpxI6GfTCYwXKEE6DTGCm1SLA==} + engines: {node: '>=14'} + peerDependencies: + '@unocss/webpack': 0.55.2 + vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 + peerDependenciesMeta: + '@unocss/webpack': + optional: true + vite: + optional: true + dependencies: + '@unocss/astro': 0.55.2(rollup@2.79.1)(vite@4.3.9) + '@unocss/cli': 0.55.2(rollup@2.79.1) + '@unocss/core': 0.55.2 + '@unocss/extractor-arbitrary-variants': 0.55.2 + '@unocss/postcss': 0.55.2(postcss@8.4.27) + '@unocss/preset-attributify': 0.55.2 + '@unocss/preset-icons': 0.55.2 + '@unocss/preset-mini': 0.55.2 + '@unocss/preset-tagify': 0.55.2 + '@unocss/preset-typography': 0.55.2 + '@unocss/preset-uno': 0.55.2 + '@unocss/preset-web-fonts': 0.55.2 + '@unocss/preset-wind': 0.55.2 + '@unocss/reset': 0.55.2 + '@unocss/transformer-attributify-jsx': 0.55.2 + '@unocss/transformer-attributify-jsx-babel': 0.55.2 + '@unocss/transformer-compile-class': 0.55.2 + '@unocss/transformer-directives': 0.55.2 + '@unocss/transformer-variant-group': 0.55.2 + '@unocss/vite': 0.55.2(rollup@2.79.1)(vite@4.3.9) + vite: 4.3.9(@types/node@18.16.0) + transitivePeerDependencies: + - postcss + - rollup + - supports-color + dev: true + + /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} dev: true - /untildify/4.0.0: + /unplugin-vue-components@0.25.0(rollup@2.79.1)(vue@3.3.4): + resolution: {integrity: sha512-HxrQ4GMSS1RwVww2av3a42cABo/v5AmTRN9iARv6e/xwkrfTyHhLh84kFwXxKkXK61vxDHxaryn694mQmkiVBg==} + engines: {node: '>=14'} + peerDependencies: + '@babel/parser': ^7.15.8 + '@nuxt/kit': ^3.2.2 + vue: 2 || 3 + peerDependenciesMeta: + '@babel/parser': + optional: true + '@nuxt/kit': + optional: true + dependencies: + '@antfu/utils': 0.7.5 + '@rollup/pluginutils': 5.0.3(rollup@2.79.1) + chokidar: 3.5.3 + debug: 4.3.4(supports-color@8.1.1) + fast-glob: 3.3.1 + local-pkg: 0.4.3 + magic-string: 0.30.2 + minimatch: 9.0.1 + resolve: 1.22.2 + unplugin: 1.3.1 + vue: 3.3.4 + transitivePeerDependencies: + - rollup + - supports-color + dev: true + + /unplugin@1.3.1: + resolution: {integrity: sha512-h4uUTIvFBQRxUKS2Wjys6ivoeofGhxzTe2sRWlooyjHXVttcVfV/JiavNd3d4+jty0SVV0dxGw9AkY9MwiaCEw==} + dependencies: + acorn: 8.10.0 + chokidar: 3.5.3 + webpack-sources: 3.2.3 + webpack-virtual-modules: 0.5.0 + dev: true + + /untildify@4.0.0: resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} engines: {node: '>=8'} dev: true - /update-browserslist-db/1.0.10_browserslist@4.21.4: + /upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + dev: true + + /update-browserslist-db@1.0.10(browserslist@4.21.5): resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: - browserslist: 4.21.4 + browserslist: 4.21.5 escalade: 3.1.1 picocolors: 1.0.0 dev: true - /uri-js/4.4.1: + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: - punycode: 2.1.1 + punycode: 2.3.0 dev: true - /url-parse/1.5.10: + /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==} - dev: true - /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/3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - dev: true - - /uuid/8.3.2: + /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true dev: true - /uuid/9.0.0: + /uuid@9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true dev: false - /uvu/0.5.6: + /uvu@0.5.6: resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} engines: {node: '>=8'} hasBin: true @@ -11719,34 +15236,32 @@ packages: diff: 5.1.0 kleur: 4.1.5 sade: 1.8.1 - dev: true - /v8-compile-cache-lib/3.0.1: + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - /v8-to-istanbul/9.0.1: - resolution: {integrity: sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==} + /v8-to-istanbul@9.1.0: + resolution: {integrity: sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==} engines: {node: '>=10.12.0'} dependencies: - '@jridgewell/trace-mapping': 0.3.15 + '@jridgewell/trace-mapping': 0.3.17 '@types/istanbul-lib-coverage': 2.0.4 convert-source-map: 1.8.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.1.1 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: @@ -11755,14 +15270,14 @@ packages: extsprintf: 1.3.0 dev: true - /vfile-message/3.1.2: + /vfile-message@3.1.2: resolution: {integrity: sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==} dependencies: '@types/unist': 2.0.6 unist-util-stringify-position: 3.0.2 dev: true - /vfile/5.3.5: + /vfile@5.3.5: resolution: {integrity: sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ==} dependencies: '@types/unist': 2.0.6 @@ -11771,22 +15286,21 @@ packages: vfile-message: 3.1.2 dev: true - /vite-node/0.28.4_@types+node@18.11.9: - resolution: {integrity: sha512-KM0Q0uSG/xHHKOJvVHc5xDBabgt0l70y7/lWTR7Q0pR5/MrYxadT+y32cJOE65FfjGmJgxpVEEY+69btJgcXOQ==} - engines: {node: '>=v14.16.0'} + /vite-node@0.34.0(@types/node@18.16.0): + resolution: {integrity: sha512-rGZMvpb052rjUwJA/a17xMfOibzNF7byMdRSTcN2Lw8uxX08s5EfjWW5mBkm3MSFTPctMSVtT2yC+8ShrZbT5g==} + engines: {node: '>=v14.18.0'} hasBin: true dependencies: cac: 6.7.14 - debug: 4.3.4 - mlly: 1.1.0 - pathe: 1.1.0 + debug: 4.3.4(supports-color@8.1.1) + mlly: 1.4.0 + pathe: 1.1.1 picocolors: 1.0.0 - source-map: 0.6.1 - source-map-support: 0.5.21 - vite: 4.1.1_@types+node@18.11.9 + vite: 4.4.9(@types/node@18.16.0) transitivePeerDependencies: - '@types/node' - less + - lightningcss - sass - stylus - sugarss @@ -11794,31 +15308,40 @@ packages: - terser dev: true - /vite-node/0.28.5_@types+node@18.11.9: - resolution: {integrity: sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==} - engines: {node: '>=v14.16.0'} - hasBin: true + /vite-plugin-istanbul@4.1.0(vite@4.3.9): + resolution: {integrity: sha512-d8FRxaswOUYlGqCCNv2BTbt9pyqt7J4RPgab3WmMf+T2TflLlCmC7S26zDRfL9Ve4JSHrcf5bdzt+E0n9CrPvA==} + peerDependencies: + vite: '>=2.9.1 <= 5' dependencies: - cac: 6.7.14 - debug: 4.3.4 - mlly: 1.1.0 - pathe: 1.1.0 + '@istanbuljs/load-nyc-config': 1.1.0 + istanbul-lib-instrument: 5.2.0 picocolors: 1.0.0 - source-map: 0.6.1 - source-map-support: 0.5.21 - vite: 4.1.1_@types+node@18.11.9 + test-exclude: 6.0.0 + vite: 4.3.9(@types/node@18.16.0) transitivePeerDependencies: - - '@types/node' - - less - - sass - - stylus - - sugarss - supports-color - - terser dev: true - /vite/4.1.1: - resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==} + /vite-plugin-pwa@0.16.0(vite@4.3.9)(workbox-build@7.0.0)(workbox-window@7.0.0): + resolution: {integrity: sha512-E+AQRzHxqNU4ZhEeR8X37/foZB+ezJEhXauE/mcf1UITY6k2Pa1dtlFl+BQu57fTdiVlWim5S0Qy44Yap93Dkg==} + engines: {node: '>=16.0.0'} + peerDependencies: + vite: ^3.1.0 || ^4.0.0 + workbox-build: ^7.0.0 + workbox-window: ^7.0.0 + dependencies: + debug: 4.3.4(supports-color@8.1.1) + fast-glob: 3.3.1 + pretty-bytes: 6.1.0 + vite: 4.3.9(@types/node@18.16.0) + workbox-build: 7.0.0 + workbox-window: 7.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /vite@4.3.9(@types/node@18.16.0): + resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: @@ -11842,21 +15365,22 @@ packages: terser: optional: true dependencies: - esbuild: 0.16.17 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 3.15.0 + '@types/node': 18.16.0 + esbuild: 0.17.18 + postcss: 8.4.27 + rollup: 3.28.0 optionalDependencies: fsevents: 2.3.2 dev: true - /vite/4.1.1_@types+node@18.11.9: - resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==} + /vite@4.4.9(@types/node@18.16.0): + resolution: {integrity: sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true peerDependencies: '@types/node': '>= 14' less: '*' + lightningcss: ^1.21.0 sass: '*' stylus: '*' sugarss: '*' @@ -11866,6 +15390,8 @@ packages: optional: true less: optional: true + lightningcss: + optional: true sass: optional: true stylus: @@ -11875,50 +15401,53 @@ packages: terser: optional: true dependencies: - '@types/node': 18.11.9 - esbuild: 0.16.17 - postcss: 8.4.21 - resolve: 1.22.1 - rollup: 3.15.0 + '@types/node': 18.16.0 + esbuild: 0.18.11 + postcss: 8.4.27 + rollup: 3.28.0 optionalDependencies: fsevents: 2.3.2 dev: true - /vitepress-plugin-search/1.0.4-alpha.19_g67lr3vgasogkevpbew55lljzq: - resolution: {integrity: sha512-WFOPn5dStyMINd+rVjNxbEmGa7U+qGHLxLnda56EG+ATil1i0yOauGhJEh5LPMvuCUVIA9tInJnFXklOBb39dA==} + /vitepress-plugin-search@1.0.4-alpha.20(flexsearch@0.7.31)(vitepress@1.0.0-alpha.72)(vue@3.3.4): + resolution: {integrity: sha512-zG+ev9pw1Mg7htABlFCNXb8XwnKN+qfTKw+vU0Ers6RIrABx+45EAAFBoaL1mEpl1FRFn1o/dQ7F4b8GP6HdGQ==} engines: {node: ^14.13.1 || ^16.7.0 || >=18} peerDependencies: flexsearch: ^0.7.31 - vitepress: ^1.0.0-alpha.13 + vitepress: ^1.0.0-alpha.65 vue: '3' dependencies: '@types/flexsearch': 0.7.3 '@types/markdown-it': 12.2.3 flexsearch: 0.7.31 + glob-to-regexp: 0.4.1 markdown-it: 13.0.1 - vitepress: 1.0.0-alpha.46_tbpndr44ulefs3hehwpi2mkf2y - vue: 3.2.45 + vitepress: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.16.0) + vue: 3.3.4 dev: true - /vitepress/1.0.0-alpha.46_tbpndr44ulefs3hehwpi2mkf2y: - resolution: {integrity: sha512-HiKiHzC0iTPsRsKs8XcsMeMzCpcCt5LWcX9mpDr288Ju+nQf1G8A2+Wm44ZkBsVv4EHxFK4ChmWyZrL1OJUXpg==} + /vitepress@1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.16.0): + resolution: {integrity: sha512-Ou7fNE/OVYLrKGQMHSTVG6AcNsdv7tm4ACrdhx93SPMzEDj8UgIb4RFa5CTTowaYf3jeDGi2EAJlzXVC+IE3dg==} hasBin: true dependencies: '@docsearch/css': 3.3.3 - '@docsearch/js': 3.3.3_tbpndr44ulefs3hehwpi2mkf2y - '@vitejs/plugin-vue': 4.0.0_vite@4.1.1+vue@3.2.45 + '@docsearch/js': 3.3.5(@algolia/client-search@4.19.1) + '@vitejs/plugin-vue': 4.2.3(vite@4.4.9)(vue@3.3.4) '@vue/devtools-api': 6.5.0 - '@vueuse/core': 9.12.0_vue@3.2.45 + '@vueuse/core': 10.3.0(vue@3.3.4) body-scroll-lock: 4.0.0-beta.0 + mark.js: 8.11.1 + minisearch: 6.0.1 shiki: 0.14.1 - vite: 4.1.1 - vue: 3.2.45 + vite: 4.4.9(@types/node@18.16.0) + vue: 3.3.4 transitivePeerDependencies: - '@algolia/client-search' - '@types/node' - '@types/react' - '@vue/composition-api' - less + - lightningcss - react - react-dom - sass @@ -11927,9 +15456,51 @@ packages: - terser dev: true - /vitest/0.28.4_vun5xzxu3tkrssf3erdbijyyki: - resolution: {integrity: sha512-sfWIy0AdlbyGRhunm+TLQEJrFH9XuRPdApfubsyLcDbCRrUX717BRQKInTgzEfyl2Ipi1HWoHB84Nqtcwxogcg==} - engines: {node: '>=v14.16.0'} + /vitepress@1.0.0-rc.10(@algolia/client-search@4.19.1)(@types/node@18.16.0)(search-insights@2.6.0): + resolution: {integrity: sha512-+MsahIWqq5WUEmj6MR4obcKYbT7im07jZPCQPdNJExkeOSbOAJ4xypSLx88x7rvtzWHhHc5aXbOhCRvGEGjFrw==} + hasBin: true + dependencies: + '@docsearch/css': 3.5.2 + '@docsearch/js': 3.5.2(@algolia/client-search@4.19.1)(search-insights@2.6.0) + '@vue/devtools-api': 6.5.0 + '@vueuse/core': 10.4.1(vue@3.3.4) + '@vueuse/integrations': 10.4.1(focus-trap@7.5.2)(vue@3.3.4) + focus-trap: 7.5.2 + mark.js: 8.11.1 + minisearch: 6.1.0 + shiki: 0.14.3 + vite: 4.4.9(@types/node@18.16.0) + vue: 3.3.4 + 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 + - universal-cookie + dev: true + + /vitest@0.34.0(@vitest/ui@0.34.0)(jsdom@22.0.0): + resolution: {integrity: sha512-8Pnc1fVt1P6uBncdUZ++hgiJGgxIRKuz4bmS/PQziaEcUj0D1g9cGiR1MbLrcsvFTC6fgrqDhYoTAdBG356WMA==} + engines: {node: '>=v14.18.0'} hasBin: true peerDependencies: '@edge-runtime/vm': '*' @@ -11937,6 +15508,9 @@ packages: '@vitest/ui': '*' happy-dom: '*' jsdom: '*' + playwright: '*' + safaridriver: '*' + webdriverio: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -11948,35 +15522,42 @@ packages: optional: true jsdom: optional: true + playwright: + optional: true + safaridriver: + optional: true + webdriverio: + optional: true dependencies: - '@types/chai': 4.3.4 + '@types/chai': 4.3.5 '@types/chai-subset': 1.3.3 - '@types/node': 18.11.9 - '@vitest/expect': 0.28.4 - '@vitest/runner': 0.28.4 - '@vitest/spy': 0.28.4 - '@vitest/ui': 0.28.4 - '@vitest/utils': 0.28.4 - acorn: 8.8.1 + '@types/node': 18.16.0 + '@vitest/expect': 0.34.0 + '@vitest/runner': 0.34.0 + '@vitest/snapshot': 0.34.0 + '@vitest/spy': 0.34.0 + '@vitest/ui': 0.34.0(vitest@0.34.0) + '@vitest/utils': 0.34.0 + acorn: 8.10.0 acorn-walk: 8.2.0 cac: 6.7.14 chai: 4.3.7 - debug: 4.3.4 - jsdom: 21.1.0 - local-pkg: 0.4.2 - pathe: 1.1.0 + debug: 4.3.4(supports-color@8.1.1) + jsdom: 22.0.0 + local-pkg: 0.4.3 + magic-string: 0.30.1 + pathe: 1.1.1 picocolors: 1.0.0 - source-map: 0.6.1 - std-env: 3.3.2 - strip-literal: 1.0.0 - tinybench: 2.3.1 - tinypool: 0.3.1 - tinyspy: 1.0.2 - vite: 4.1.1_@types+node@18.11.9 - vite-node: 0.28.4_@types+node@18.11.9 + std-env: 3.3.3 + strip-literal: 1.0.1 + tinybench: 2.5.0 + tinypool: 0.7.0 + vite: 4.4.9(@types/node@18.16.0) + vite-node: 0.34.0(@types/node@18.16.0) why-is-node-running: 2.2.2 transitivePeerDependencies: - less + - lightningcss - sass - stylus - sugarss @@ -11984,73 +15565,7 @@ packages: - terser dev: true - /vitest/0.28.5_vun5xzxu3tkrssf3erdbijyyki: - resolution: {integrity: sha512-pyCQ+wcAOX7mKMcBNkzDwEHRGqQvHUl0XnoHR+3Pb1hytAHISgSxv9h0gUiSiYtISXUU3rMrKiKzFYDrI6ZIHA==} - engines: {node: '>=v14.16.0'} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' - happy-dom: '*' - jsdom: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - dependencies: - '@types/chai': 4.3.4 - '@types/chai-subset': 1.3.3 - '@types/node': 18.11.9 - '@vitest/expect': 0.28.5 - '@vitest/runner': 0.28.5 - '@vitest/spy': 0.28.5 - '@vitest/ui': 0.28.4 - '@vitest/utils': 0.28.5 - acorn: 8.8.1 - acorn-walk: 8.2.0 - cac: 6.7.14 - chai: 4.3.7 - debug: 4.3.4 - jsdom: 21.1.0 - local-pkg: 0.4.2 - pathe: 1.1.0 - picocolors: 1.0.0 - source-map: 0.6.1 - std-env: 3.3.2 - strip-literal: 1.0.0 - tinybench: 2.3.1 - tinypool: 0.3.1 - tinyspy: 1.0.2 - vite: 4.1.1_@types+node@18.11.9 - vite-node: 0.28.5_@types+node@18.11.9 - why-is-node-running: 2.2.2 - transitivePeerDependencies: - - less - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /vm2/3.9.11: - resolution: {integrity: sha512-PFG8iJRSjvvBdisowQ7iVF580DXb1uCIiGaXgm7tynMR1uTBlv7UJlB1zdv5KJ+Tmq1f0Upnj3fayoEOPpCBKg==} - engines: {node: '>=6.0'} - hasBin: true - dependencies: - acorn: 8.8.1 - acorn-walk: 8.2.0 - 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.0 @@ -12060,40 +15575,40 @@ packages: vscode-uri: 3.0.6 dev: true - /vscode-languageserver-textdocument/1.0.7: + /vscode-languageserver-textdocument@1.0.7: resolution: {integrity: sha512-bFJH7UQxlXT8kKeyiyu41r22jCZXG8kuuVVA33OEJn1diWOZK5n8zBSPZFHVBOu8kXZ6h0LIRhf5UnCo61J4Hg==} dev: true - /vscode-languageserver-types/3.17.2: + /vscode-languageserver-textdocument@1.0.8: + resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==} + dev: true + + /vscode-languageserver-types@3.17.2: resolution: {integrity: sha512-zHhCWatviizPIq9B7Vh9uvrH6x3sK8itC84HkamnBWoDFJtzBf7SWlpLCZUit72b3os45h6RWQNC9xHRDF8dRA==} dev: true - /vscode-nls/5.2.0: + /vscode-nls@5.2.0: resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} dev: true - /vscode-oniguruma/1.6.2: - resolution: {integrity: sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==} - dev: true - - /vscode-oniguruma/1.7.0: + /vscode-oniguruma@1.7.0: resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} dev: true - /vscode-textmate/6.0.0: - resolution: {integrity: sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==} - dev: true - - /vscode-textmate/8.0.0: + /vscode-textmate@8.0.0: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} dev: true - /vscode-uri/3.0.6: + /vscode-uri@3.0.6: resolution: {integrity: sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==} dev: true - /vue-demi/0.13.11_vue@3.2.45: - resolution: {integrity: sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==} + /vscode-uri@3.0.7: + resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==} + dev: true + + /vue-demi@0.14.5(vue@3.3.4): + resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==} engines: {node: '>=12'} hasBin: true requiresBuild: true @@ -12104,60 +15619,53 @@ packages: '@vue/composition-api': optional: true dependencies: - vue: 3.2.45 - dev: true + vue: 3.3.4 - /vue/3.2.45: - resolution: {integrity: sha512-9Nx/Mg2b2xWlXykmCwiTUCWHbWIj53bnkizBxKai1g61f2Xit700A1ljowpTIM11e3uipOeiPcSqnmBg6gyiaA==} + /vue@3.3.4: + resolution: {integrity: sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==} dependencies: - '@vue/compiler-dom': 3.2.45 - '@vue/compiler-sfc': 3.2.45 - '@vue/runtime-dom': 3.2.45 - '@vue/server-renderer': 3.2.45_vue@3.2.45 - '@vue/shared': 3.2.45 - dev: true + '@vue/compiler-dom': 3.3.4 + '@vue/compiler-sfc': 3.3.4 + '@vue/runtime-dom': 3.3.4 + '@vue/server-renderer': 3.3.4(vue@3.3.4) + '@vue/shared': 3.3.4 - /w3c-hr-time/1.0.2: + /vuex@4.1.0(vue@3.3.4): + resolution: {integrity: sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==} + peerDependencies: + vue: ^3.2.0 + dependencies: + '@vue/devtools-api': 6.5.0 + vue: 3.3.4 + dev: false + + /w3c-hr-time@1.0.2: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} deprecated: Use your platform's native performance.now() and performance.timeOrigin. dependencies: browser-process-hrtime: 1.0.0 dev: true - /w3c-xmlserializer/3.0.0: + /w3c-xmlserializer@3.0.0: resolution: {integrity: sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==} engines: {node: '>=12'} dependencies: xml-name-validator: 4.0.0 dev: true - /w3c-xmlserializer/4.0.0: + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} dependencies: xml-name-validator: 4.0.0 dev: true - /wait-on/6.0.0_debug@4.3.2: - resolution: {integrity: sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==} - engines: {node: '>=10.0.0'} - hasBin: true - dependencies: - axios: 0.21.4_debug@4.3.2 - joi: 17.6.0 - lodash: 4.17.21 - minimist: 1.2.6 - rxjs: 7.5.6 - transitivePeerDependencies: - - debug - dev: true - - /wait-on/7.0.1_debug@4.3.4: + /wait-on@7.0.1(debug@4.3.4): resolution: {integrity: sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==} engines: {node: '>=12.0.0'} hasBin: true dependencies: - axios: 0.27.2_debug@4.3.4 + axios: 0.27.2(debug@4.3.4) joi: 17.7.1 lodash: 4.17.21 minimist: 1.2.8 @@ -12166,13 +15674,13 @@ packages: - 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.0: + /watchpack@2.4.0: resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} engines: {node: '>=10.13.0'} dependencies: @@ -12180,41 +15688,52 @@ packages: graceful-fs: 4.2.10 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-worker/1.2.0: + /web-streams-polyfill@3.2.1: + resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} + engines: {node: '>= 8'} + dev: true + + /web-worker@1.2.0: resolution: {integrity: sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==} dev: false - /webdriver/7.16.11: - resolution: {integrity: sha512-6nBOXae4xuBH4Nqvi/zvtwjnxSLTONBpxOiRJtQ68CYTYv5+w3m8CsaWy3HbK/0XXa++NYl62bDNn70OGEKb+Q==} + /webdriver@7.30.0(typescript@5.1.3): + resolution: {integrity: sha512-bQE4oVgjjg5sb3VkCD+Eb8mscEvf3TioP0mnEZK0f5OJUNI045gMCJgpX8X4J8ScGyEhzlhn1KvlAn3yzxjxog==} engines: {node: '>=12.0.0'} dependencies: - '@types/node': 16.11.59 - '@wdio/config': 7.16.11 - '@wdio/logger': 7.16.0 - '@wdio/protocols': 7.16.7 - '@wdio/types': 7.16.11 - '@wdio/utils': 7.16.11 + '@types/node': 18.16.0 + '@wdio/config': 7.30.0(typescript@5.1.3) + '@wdio/logger': 7.26.0 + '@wdio/protocols': 7.27.0 + '@wdio/types': 7.26.0(typescript@5.1.3) + '@wdio/utils': 7.26.0(typescript@5.1.3) got: 11.8.5 - ky: 0.28.7 + 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/7.0.0: + /webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + dev: true + + /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} dev: true - /webpack-cli/4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi: + /webpack-cli@4.10.0(webpack-dev-server@4.11.1)(webpack@5.88.2): resolution: {integrity: sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==} engines: {node: '>=10.13.0'} hasBin: true @@ -12235,9 +15754,9 @@ packages: optional: true dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 1.2.0_pda42hcaj7d62cr262fr632kue - '@webpack-cli/info': 1.5.0_webpack-cli@4.10.0 - '@webpack-cli/serve': 1.7.0_ud4agclah7rahur6ntojouq57y + '@webpack-cli/configtest': 1.2.0(webpack-cli@4.10.0)(webpack@5.88.2) + '@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.11.1) colorette: 2.0.19 commander: 7.2.0 cross-spawn: 7.0.3 @@ -12245,26 +15764,26 @@ packages: import-local: 3.1.0 interpret: 2.2.0 rechoir: 0.7.1 - webpack: 5.75.0_webpack-cli@4.10.0 - webpack-dev-server: 4.11.1_pda42hcaj7d62cr262fr632kue + webpack: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) + webpack-dev-server: 4.11.1(webpack-cli@4.10.0)(webpack@5.88.2) webpack-merge: 5.8.0 dev: true - /webpack-dev-middleware/5.3.3_webpack@5.75.0: + /webpack-dev-middleware@5.3.3(webpack@5.88.2): resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} engines: {node: '>= 12.13.0'} peerDependencies: webpack: ^4.0.0 || ^5.0.0 dependencies: - colorette: 2.0.19 + colorette: 2.0.20 memfs: 3.4.11 mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.0.0 - webpack: 5.75.0_webpack-cli@4.10.0 + webpack: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) dev: true - /webpack-dev-server/4.11.1_pda42hcaj7d62cr262fr632kue: + /webpack-dev-server@4.11.1(webpack-cli@4.10.0)(webpack@5.88.2): resolution: {integrity: sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==} engines: {node: '>= 12.13.0'} hasBin: true @@ -12292,7 +15811,7 @@ packages: express: 4.18.2 graceful-fs: 4.2.10 html-entities: 2.3.3 - http-proxy-middleware: 2.0.6_@types+express@4.17.14 + http-proxy-middleware: 2.0.6(@types/express@4.17.14) ipaddr.js: 2.0.1 open: 8.4.0 p-retry: 4.6.2 @@ -12302,9 +15821,9 @@ packages: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.75.0_webpack-cli@4.10.0 - webpack-cli: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi - webpack-dev-middleware: 5.3.3_webpack@5.75.0 + webpack: 5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0) + webpack-cli: 4.10.0(webpack-dev-server@4.11.1)(webpack@5.88.2) + webpack-dev-middleware: 5.3.3(webpack@5.88.2) ws: 8.9.0 transitivePeerDependencies: - bufferutil @@ -12313,7 +15832,7 @@ packages: - utf-8-validate dev: true - /webpack-merge/5.8.0: + /webpack-merge@5.8.0: resolution: {integrity: sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==} engines: {node: '>=10.0.0'} dependencies: @@ -12321,13 +15840,17 @@ packages: wildcard: 2.0.0 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/5.75.0_webpack-cli@4.10.0: - resolution: {integrity: sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==} + /webpack-virtual-modules@0.5.0: + resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} + dev: true + + /webpack@5.88.2(esbuild@0.19.0)(webpack-cli@4.10.0): + resolution: {integrity: sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -12337,16 +15860,16 @@ packages: optional: true dependencies: '@types/eslint-scope': 3.7.4 - '@types/estree': 0.0.51 - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/wasm-edit': 1.11.1 - '@webassemblyjs/wasm-parser': 1.11.1 - acorn: 8.8.0 - acorn-import-assertions: 1.8.0_acorn@8.8.0 - browserslist: 4.21.4 + '@types/estree': 1.0.0 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.10.0 + acorn-import-assertions: 1.9.0(acorn@8.10.0) + browserslist: 4.21.5 chrome-trace-event: 1.0.3 - enhanced-resolve: 5.10.0 - es-module-lexer: 0.9.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.3.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -12355,11 +15878,11 @@ packages: loader-runner: 4.3.0 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 3.1.1 + schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.6_webpack@5.75.0 + terser-webpack-plugin: 5.3.9(esbuild@0.19.0)(webpack@5.88.2) watchpack: 2.4.0 - webpack-cli: 4.10.0_uaydpeuxkjjcxdbyfgk36cjdxi + webpack-cli: 4.10.0(webpack-dev-server@4.11.1)(webpack@5.88.2) webpack-sources: 3.2.3 transitivePeerDependencies: - '@swc/core' @@ -12367,7 +15890,7 @@ packages: - uglify-js dev: true - /websocket-driver/0.7.4: + /websocket-driver@0.7.4: resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} engines: {node: '>=0.8.0'} dependencies: @@ -12376,24 +15899,24 @@ packages: websocket-extensions: 0.1.4 dev: true - /websocket-extensions/0.1.4: + /websocket-extensions@0.1.4: resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} engines: {node: '>=0.8.0'} dev: true - /whatwg-encoding/2.0.0: + /whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} dependencies: iconv-lite: 0.6.3 dev: true - /whatwg-mimetype/3.0.0: + /whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} dev: true - /whatwg-url/10.0.0: + /whatwg-url@10.0.0: resolution: {integrity: sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==} engines: {node: '>=12'} dependencies: @@ -12401,7 +15924,7 @@ packages: webidl-conversions: 7.0.0 dev: true - /whatwg-url/11.0.0: + /whatwg-url@11.0.0: resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} engines: {node: '>=12'} dependencies: @@ -12409,21 +15932,63 @@ packages: webidl-conversions: 7.0.0 dev: true - /whatwg-url/5.0.0: + /whatwg-url@12.0.1: + resolution: {integrity: sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ==} + engines: {node: '>=14'} + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + dev: true + + /whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 dev: true - /which/1.3.1: + /whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + 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==} + 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 + + /which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + dev: true + + /which-typed-array@1.1.9: + resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.2 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + is-typed-array: 1.1.10 + dev: true + + /which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true dependencies: isexe: 2.0.0 dev: true - /which/2.0.2: + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true @@ -12431,7 +15996,7 @@ packages: isexe: 2.0.0 dev: true - /why-is-node-running/2.2.2: + /why-is-node-running@2.2.2: resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} engines: {node: '>=8'} hasBin: true @@ -12440,20 +16005,173 @@ packages: stackback: 0.0.2 dev: true - /wildcard/2.0.0: + /widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + dependencies: + string-width: 4.2.3 + dev: true + + /wildcard@2.0.0: resolution: {integrity: sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==} dev: true - /word-wrap/1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} + /word-wrap@1.2.4: + resolution: {integrity: sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==} engines: {node: '>=0.10.0'} dev: true - /wordwrap/1.0.0: + /wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} dev: true - /wrap-ansi/6.2.0: + /workbox-background-sync@7.0.0: + resolution: {integrity: sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==} + dependencies: + idb: 7.1.1 + workbox-core: 7.0.0 + dev: true + + /workbox-broadcast-update@7.0.0: + resolution: {integrity: sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ==} + dependencies: + workbox-core: 7.0.0 + dev: true + + /workbox-build@7.0.0: + resolution: {integrity: sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==} + engines: {node: '>=16.0.0'} + dependencies: + '@apideck/better-ajv-errors': 0.3.6(ajv@8.12.0) + '@babel/core': 7.12.3 + '@babel/preset-env': 7.20.2(@babel/core@7.12.3) + '@babel/runtime': 7.21.0 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.12.3)(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) + '@surma/rollup-plugin-off-main-thread': 2.2.3 + ajv: 8.12.0 + 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) + 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 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + dev: true + + /workbox-cacheable-response@7.0.0: + resolution: {integrity: sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g==} + dependencies: + workbox-core: 7.0.0 + dev: true + + /workbox-core@7.0.0: + resolution: {integrity: sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ==} + dev: true + + /workbox-expiration@7.0.0: + resolution: {integrity: sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ==} + dependencies: + idb: 7.1.1 + workbox-core: 7.0.0 + dev: true + + /workbox-google-analytics@7.0.0: + resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==} + 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-navigation-preload@7.0.0: + resolution: {integrity: sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==} + dependencies: + workbox-core: 7.0.0 + dev: true + + /workbox-precaching@7.0.0: + resolution: {integrity: sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA==} + dependencies: + workbox-core: 7.0.0 + workbox-routing: 7.0.0 + workbox-strategies: 7.0.0 + dev: true + + /workbox-range-requests@7.0.0: + resolution: {integrity: sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ==} + dependencies: + workbox-core: 7.0.0 + dev: true + + /workbox-recipes@7.0.0: + resolution: {integrity: sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww==} + 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-routing@7.0.0: + resolution: {integrity: sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA==} + dependencies: + workbox-core: 7.0.0 + dev: true + + /workbox-strategies@7.0.0: + resolution: {integrity: sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA==} + dependencies: + workbox-core: 7.0.0 + dev: true + + /workbox-streams@7.0.0: + resolution: {integrity: sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ==} + dependencies: + workbox-core: 7.0.0 + workbox-routing: 7.0.0 + dev: true + + /workbox-sw@7.0.0: + resolution: {integrity: sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA==} + dev: true + + /workbox-window@7.0.0: + resolution: {integrity: sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==} + dependencies: + '@types/trusted-types': 2.0.2 + workbox-core: 7.0.0 + dev: true + + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} dependencies: @@ -12462,7 +16180,7 @@ packages: strip-ansi: 6.0.1 dev: true - /wrap-ansi/7.0.0: + /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} dependencies: @@ -12471,11 +16189,10 @@ packages: strip-ansi: 6.0.1 dev: true - /wrappy/1.0.2: + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - /write-file-atomic/3.0.3: + /write-file-atomic@3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} dependencies: imurmurhash: 0.1.4 @@ -12484,7 +16201,7 @@ packages: typedarray-to-buffer: 3.1.5 dev: true - /write-file-atomic/4.0.2: + /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} dependencies: @@ -12492,20 +16209,7 @@ packages: signal-exit: 3.0.7 dev: true - /ws/7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} - engines: {node: '>=8.3.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.12.0: + /ws@8.12.0: resolution: {integrity: sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==} engines: {node: '>=10.0.0'} peerDependencies: @@ -12518,7 +16222,20 @@ packages: optional: true dev: true - /ws/8.5.0: + /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.5.0: resolution: {integrity: sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==} engines: {node: '>=10.0.0'} peerDependencies: @@ -12531,7 +16248,7 @@ packages: optional: true dev: true - /ws/8.9.0: + /ws@8.9.0: resolution: {integrity: sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==} engines: {node: '>=10.0.0'} peerDependencies: @@ -12544,80 +16261,92 @@ packages: optional: true dev: true - /xdg-basedir/4.0.0: + /xdg-basedir@4.0.0: resolution: {integrity: sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==} engines: {node: '>=8'} dev: true - /xml-name-validator/4.0.0: + /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} 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 - /xregexp/2.0.0: - resolution: {integrity: sha512-xl/50/Cf32VsGq/1R8jJE5ajH1yMCQkpmoS10QbFZWl2Oor4H0Me64Pu2yxvsRWK3m6soJbmGfzSR7BYmDcWAA==} + /xxhashjs@0.2.2: + resolution: {integrity: sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==} + dependencies: + cuint: 0.2.2 dev: true - /y18n/5.0.8: + /y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + dev: true + + /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} dev: true - /yallist/3.1.1: + /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} dev: true - /yallist/4.0.0: + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true - /yaml/1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - dev: true - - /yaml/2.1.1: - resolution: {integrity: sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==} + /yaml@2.2.2: + resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==} engines: {node: '>= 14'} + + /yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 dev: true - /yargs-parser/20.2.9: + /yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} dev: true - /yargs-parser/21.1.1: + /yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} dev: true - /yargs/16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} + /yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} dependencies: - cliui: 7.0.4 - escalade: 3.1.1 + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 get-caller-file: 2.0.5 require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 dev: true - /yargs/17.4.1: - resolution: {integrity: sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==} + /yargs@17.6.2: + resolution: {integrity: sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==} engines: {node: '>=12'} dependencies: - cliui: 7.0.4 + cliui: 8.0.1 escalade: 3.1.1 get-caller-file: 2.0.5 require-directory: 2.1.1 @@ -12626,11 +16355,11 @@ packages: yargs-parser: 21.1.1 dev: true - /yargs/17.5.1: - resolution: {integrity: sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==} + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} dependencies: - cliui: 7.0.4 + cliui: 8.0.1 escalade: 3.1.1 get-caller-file: 2.0.5 require-directory: 2.1.1 @@ -12639,28 +16368,27 @@ packages: yargs-parser: 21.1.1 dev: true - /yauzl/2.10.0: + /yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} dependencies: buffer-crc32: 0.2.13 fd-slicer: 1.1.0 dev: true - /yn/3.1.1: + /yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} - dev: true - /yocto-queue/0.1.0: + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true - /yocto-queue/1.0.0: + /yocto-queue@1.0.0: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} dev: true - /zwitch/2.0.2: + /zwitch@2.0.2: resolution: {integrity: sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==} dev: true diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 4b8be5cdc..01e9fda24 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,4 +1,5 @@ packages: - # all packages in direct subdirs of packages/ - 'packages/*' + - 'packages/mermaid/src/docs' + - 'packages/mermaid/src/vitepress' - 'tests/*' diff --git a/renovate.json b/renovate.json index 548f5b5be..1a593ac20 100644 --- a/renovate.json +++ b/renovate.json @@ -2,7 +2,6 @@ "extends": [ "config:base", ":rebaseStalePrs", - "group:allNonMajor", "schedule:earlyMondays", ":automergeMinor", ":automergeTesters", @@ -14,6 +13,18 @@ { "matchUpdateTypes": ["minor", "patch", "digest"], "automerge": true + }, + { + "groupName": "all patch dependencies", + "groupSlug": "all-patch", + "matchPackagePatterns": ["*"], + "matchUpdateTypes": ["patch"] + }, + { + "groupName": "all minor dependencies", + "groupSlug": "all-minor", + "matchPackagePatterns": ["*"], + "matchUpdateTypes": ["minor"] } ], "dependencyDashboard": true, diff --git a/run b/run new file mode 100755 index 000000000..fbf437263 --- /dev/null +++ b/run @@ -0,0 +1,96 @@ +#!/bin/bash +RUN="docker-compose run --rm" + +ansi() { echo -e "\e[${1}m${*:2}\e[0m"; } +bold() { ansi 1 "$@"; } +# italic() { ansi 3 "$@"; } +underline() { ansi 4 "$@"; } +# strikethrough() { ansi 9 "$@"; } +# red() { ansi 31 "$@"; } + +name=$(basename $0) +command=$1 +args=${@:2} + +case $command in + +sh) +$RUN mermaid sh -c "npx $args" +;; + +pnpm) +$RUN mermaid sh -c "npx pnpm $args" +;; + +dev) +$RUN --service-ports mermaid sh -c "npx pnpm run dev" +;; + +docs:dev) +$RUN --service-ports mermaid sh -c "npx pnpm run --filter mermaid docs:dev:docker" +;; + +cypress) +$RUN cypress $args +;; + +help) + +# Alignment of help message must be as it is, it will be nice looking when printed +usage=$( +cat <<EOF + +$(bold MERMAID LOCAL DOCKER DEVELOPMENT) + +Welcome! Thank you for joining the development. +This is a script for running commands within docker containers at ease. +__________________________________________________________________________________________ + +Development quick start guide: + +$(bold ./$name pnpm install) # Install packages +$(bold ./$name dev) # Run dev server with examples, open http://localhost:9000 +$(bold ./$name pnpm vitest) # Run watcher for unit tests +$(bold ./$name cypress) # Run integration tests (after starting dev server) +$(bold ./$name pnpm build) # Prepare it for production +$(bold ./$name docs:dev) # Then add documentation, open http://localhost:3333 +__________________________________________________________________________________________ + +Commands: + +$(bold ./$name pnpm) # Run any 'pnpm' command +$(bold ./$name dev) # Run dev server with examples, open http://localhost:9000 +$(bold ./$name docs:dev) # For docs contributions, open http://localhost:3333 +$(bold ./$name cypress) # Run integration tests +$(bold ./$name sh) # Open 'sh' inside docker container for development +$(bold ./$name help) # Show this help +__________________________________________________________________________________________ + +Examples of frequiently used commands: + +$(bold ./$name pnpm add --filter mermaid) $(underline package) + Add package to mermaid + +$(bold git diff --name-only develop \| xargs ./$name pnpm prettier --write) + Prettify everything you added so far + +$(bold ./$name cypress open --project .) + Open cypress interactive GUI + +$(bold ./$name cypress run --spec cypress/integration/rendering/)$(underline test.spec.ts) + Run specific test in cypress\n + +$(bold xhost +local:) + Allow local connections for x11 server + +EOF +) + +echo -n -e "$usage" +;; + +*) +$name help +;; + +esac diff --git a/scripts/coverage.ts b/scripts/coverage.ts new file mode 100644 index 000000000..8cc8961da --- /dev/null +++ b/scripts/coverage.ts @@ -0,0 +1,19 @@ +import { execSync } from 'child_process'; +import { cp } from 'fs/promises'; + +const main = async () => { + const coverageDir = 'coverage'; + const coverageFiles = ['vitest', 'cypress'].map( + (dir) => `${coverageDir}/${dir}/coverage-final.json` + ); + + //copy coverage files from vitest and cypress to coverage folder + await Promise.all( + coverageFiles.map((file) => cp(file, `${coverageDir}/combined/${file.split('/')[1]}.json`)) + ); + + execSync('npx nyc merge coverage/combined coverage/combined-final.json'); + execSync('npx nyc report -t coverage --report-dir coverage/html --reporter=html-spa'); +}; + +void main(); diff --git a/scripts/editor.bash b/scripts/editor.bash new file mode 100755 index 000000000..3ae51ed33 --- /dev/null +++ b/scripts/editor.bash @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +set -euxo pipefail +pnpm build + +# Clone the Mermaid Live Editor repository +rm -rf mermaid-live-editor +git clone --single-branch https://github.com/mermaid-js/mermaid-live-editor.git + +cd mermaid-live-editor + +# We have to use npm instead of yarn because it causes trouble in netlify +# Install dependencies +npm install + +# Link local mermaid to live editor +npm link ../packages/mermaid + +# Force Build the site +npm run build -- --force + diff --git a/scripts/jison/lint.mts b/scripts/jison/lint.mts index 95edd4fb1..596ce308b 100644 --- a/scripts/jison/lint.mts +++ b/scripts/jison/lint.mts @@ -14,12 +14,17 @@ const lint = async (file: string): Promise<boolean> => { console.log(`Linting ${file}`); const jisonCode = await readFile(file, 'utf8'); // @ts-ignore no typings - const jsCode = new jison.Generator(jisonCode, { moduleType: 'amd' }).generate(); + const generator = new jison.Generator(jisonCode, { moduleType: 'amd' }); + const jsCode = generator.generate(); const [result] = await linter.lintText(jsCode); if (result.errorCount > 0) { console.error(`Linting failed for ${file}`); console.error(result.messages); } + if (generator.conflicts > 0) { + console.error(`Linting failed for ${file}. Conflicts found in grammar`); + return false; + } return result.errorCount === 0; }; diff --git a/tests/webpack/package.json b/tests/webpack/package.json index e51845399..7f7bb5634 100644 --- a/tests/webpack/package.json +++ b/tests/webpack/package.json @@ -12,7 +12,7 @@ "author": "", "license": "ISC", "devDependencies": { - "webpack": "^5.74.0", + "webpack": "^5.88.2", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.11.1" }, diff --git a/tsconfig.json b/tsconfig.json index c66d62784..4cbf209a3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,7 +14,7 @@ "target": "ES6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, "lib": [ "DOM", - "ES2021" + "ES2022" ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, // "jsx": "preserve", /* Specify what JSX code is generated. */ // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ @@ -27,9 +27,8 @@ // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ /* Modules */ - "module": "es2022" /* Specify what module code is generated. */, + "module": "nodenext", // "rootDir": "./packages" /* Specify the root folder within your source files. */, - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, // "baseUrl": "./src" /* Specify the base directory to resolve non-relative module names. */, // "paths": {} /* Specify a set of entries that re-map imports to additional lookup locations. */, // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ diff --git a/vite.config.ts b/vite.config.ts index e79295425..080ff981f 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,18 +1,28 @@ -import jison from './.vite/jisonPlugin'; +import jison from './.vite/jisonPlugin.js'; +import jsonSchemaPlugin from './.vite/jsonSchemaPlugin.js'; +import typescript from '@rollup/plugin-typescript'; import { defineConfig } from 'vitest/config'; export default defineConfig({ resolve: { - extensions: ['.jison', '.js', '.ts', '.json'], + extensions: ['.js'], }, - plugins: [jison()], + 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: { environment: 'jsdom', globals: true, // TODO: should we move this to a mermaid-core package? setupFiles: ['packages/mermaid/src/tests/setup.ts'], coverage: { + provider: 'v8', reporter: ['text', 'json', 'html', 'lcov'], + reportsDirectory: './coverage/vitest', + exclude: ['**/node_modules/**', '**/tests/**', '**/__mocks__/**'], }, }, build: {