mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-11 08:14:07 +01:00
merge from develop
This commit is contained in:
@@ -20,6 +20,7 @@ dagre-d3
|
|||||||
Deepdwn
|
Deepdwn
|
||||||
Docsify
|
Docsify
|
||||||
Docsy
|
Docsy
|
||||||
|
Doctave
|
||||||
DokuWiki
|
DokuWiki
|
||||||
dompurify
|
dompurify
|
||||||
elkjs
|
elkjs
|
||||||
|
|||||||
2
.github/workflows/build-docs.yml
vendored
2
.github/workflows/build-docs.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
|
|||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|||||||
2
.github/workflows/e2e-applitools.yml
vendored
2
.github/workflows/e2e-applitools.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|||||||
13
.github/workflows/e2e.yml
vendored
13
.github/workflows/e2e.yml
vendored
@@ -24,6 +24,7 @@ env:
|
|||||||
) ||
|
) ||
|
||||||
github.event.before
|
github.event.before
|
||||||
}}
|
}}
|
||||||
|
shouldRunParallel: ${{ secrets.CYPRESS_RECORD_KEY != '' && !(github.event_name == 'push' && github.ref == 'refs/heads/develop') }}
|
||||||
jobs:
|
jobs:
|
||||||
cache:
|
cache:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -32,7 +33,7 @@ jobs:
|
|||||||
options: --user 1001
|
options: --user 1001
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@@ -79,7 +80,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
@@ -116,7 +117,7 @@ jobs:
|
|||||||
id: cypress
|
id: cypress
|
||||||
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
|
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
|
||||||
# Otherwise (e.g. if running from fork), we run on a single container only
|
# Otherwise (e.g. if running from fork), we run on a single container only
|
||||||
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
|
if: ${{ env.shouldRunParallel == 'true' || ( matrix.containers == 1 ) }}
|
||||||
with:
|
with:
|
||||||
install: false
|
install: false
|
||||||
start: pnpm run dev:coverage
|
start: pnpm run dev:coverage
|
||||||
@@ -124,14 +125,14 @@ jobs:
|
|||||||
browser: chrome
|
browser: chrome
|
||||||
# Disable recording if we don't have an API key
|
# Disable recording if we don't have an API key
|
||||||
# e.g. if this action was run from a fork
|
# e.g. if this action was run from a fork
|
||||||
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
record: ${{ env.shouldRunParallel == 'true' }}
|
||||||
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
parallel: ${{ env.shouldRunParallel == 'true' }}
|
||||||
env:
|
env:
|
||||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||||
VITEST_COVERAGE: true
|
VITEST_COVERAGE: true
|
||||||
CYPRESS_COMMIT: ${{ github.sha }}
|
CYPRESS_COMMIT: ${{ github.sha }}
|
||||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
||||||
ARGOS_PARALLEL: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
ARGOS_PARALLEL: ${{ env.shouldRunParallel == 'true' }}
|
||||||
ARGOS_PARALLEL_TOTAL: 4
|
ARGOS_PARALLEL_TOTAL: 4
|
||||||
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|||||||
2
.github/workflows/publish-docs.yml
vendored
2
.github/workflows/publish-docs.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
|
|||||||
2
.github/workflows/release-publish.yml
vendored
2
.github/workflows/release-publish.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: fregante/setup-git-user@v2
|
- uses: fregante/setup-git-user@v2
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|||||||
2
.github/workflows/update-browserlist.yml
vendored
2
.github/workflows/update-browserlist.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v4
|
||||||
- run: npx update-browserslist-db@latest
|
- run: npx update-browserslist-db@latest
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: EndBug/add-and-commit@v9
|
uses: EndBug/add-and-commit@v9
|
||||||
|
|||||||
@@ -124,7 +124,9 @@ export const verifyScreenshot = (name: string): void => {
|
|||||||
cy.log(`Closing eyes ${Cypress.spec.name}`);
|
cy.log(`Closing eyes ${Cypress.spec.name}`);
|
||||||
cy.eyesClose();
|
cy.eyesClose();
|
||||||
} else if (useArgos) {
|
} else if (useArgos) {
|
||||||
cy.argosScreenshot(name);
|
cy.argosScreenshot(name, {
|
||||||
|
threshold: 0.01,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
cy.matchImageSnapshot(name);
|
cy.matchImageSnapshot(name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ describe('packet structure', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should render a simple packet diagram without ranges', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`packet-beta
|
||||||
|
0: "h"
|
||||||
|
1: "i"
|
||||||
|
`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should render a complex packet diagram', () => {
|
it('should render a complex packet diagram', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`packet-beta
|
`packet-beta
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ To add an integration to this list, see the [Integrations - create page](./integ
|
|||||||
- [CloudScript.io Mermaid Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
- [CloudScript.io Mermaid Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
||||||
- [Azure Devops](https://learn.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) ✅
|
- [Azure Devops](https://learn.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) ✅
|
||||||
- [Deepdwn](https://billiam.itch.io/deepdwn) ✅
|
- [Deepdwn](https://billiam.itch.io/deepdwn) ✅
|
||||||
|
- [Doctave](https://www.doctave.com/) ✅
|
||||||
|
- [Mermaid in Markdown code blocks](https://docs.doctave.com/components/mermaid) ✅
|
||||||
- [GitBook](https://gitbook.com)
|
- [GitBook](https://gitbook.com)
|
||||||
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
||||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||||
|
|||||||
@@ -483,8 +483,8 @@ a _[valid CSS property name](https://www.w3.org/TR/CSS/#properties)_ followed by
|
|||||||
|
|
||||||
Here is an example of a classDef with just one property-value pair:
|
Here is an example of a classDef with just one property-value pair:
|
||||||
|
|
||||||
```
|
```txt
|
||||||
classDef movement font-style:italic;
|
classDef movement font-style:italic;
|
||||||
```
|
```
|
||||||
|
|
||||||
where
|
where
|
||||||
@@ -496,8 +496,8 @@ If you want to have more than one _property-value pair_ then you put a comma (`,
|
|||||||
|
|
||||||
Here is an example with three property-value pairs:
|
Here is an example with three property-value pairs:
|
||||||
|
|
||||||
```
|
```txt
|
||||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||||
```
|
```
|
||||||
|
|
||||||
where
|
where
|
||||||
@@ -522,7 +522,7 @@ There are two ways to apply a `classDef` style to a state:
|
|||||||
A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is:
|
A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is:
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is an example applying the `badBadEvent` style to a state named `Crash`:
|
Here is an example applying the `badBadEvent` style to a state named `Crash`:
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@applitools/eyes-cypress": "^3.44.4",
|
"@applitools/eyes-cypress": "^3.44.4",
|
||||||
"@argos-ci/cypress": "^2.0.5",
|
"@argos-ci/cypress": "^2.1.0",
|
||||||
"@cspell/eslint-plugin": "^8.8.4",
|
"@cspell/eslint-plugin": "^8.8.4",
|
||||||
"@cypress/code-coverage": "^3.12.30",
|
"@cypress/code-coverage": "^3.12.30",
|
||||||
"@eslint/js": "^9.4.0",
|
"@eslint/js": "^9.4.0",
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"eslint-plugin-markdown": "^5.0.0",
|
"eslint-plugin-markdown": "^5.0.0",
|
||||||
"eslint-plugin-no-only-tests": "^3.1.0",
|
"eslint-plugin-no-only-tests": "^3.1.0",
|
||||||
"eslint-plugin-tsdoc": "^0.3.0",
|
"eslint-plugin-tsdoc": "^0.3.0",
|
||||||
"eslint-plugin-unicorn": "^53.0.0",
|
"eslint-plugin-unicorn": "^54.0.0",
|
||||||
"express": "^4.19.1",
|
"express": "^4.19.1",
|
||||||
"globals": "^15.4.0",
|
"globals": "^15.4.0",
|
||||||
"globby": "^14.0.1",
|
"globby": "^14.0.1",
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@zenuml/core": "^3.19.2"
|
"@zenuml/core": "^3.23.27"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mermaid": "workspace:^"
|
"mermaid": "workspace:^"
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
"katex": "^0.16.9",
|
"katex": "^0.16.9",
|
||||||
"khroma": "^2.1.0",
|
"khroma": "^2.1.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mdast-util-from-markdown": "^2.0.0",
|
"marked": "^13.0.2",
|
||||||
"roughjs": "^4.6.6",
|
"roughjs": "^4.6.6",
|
||||||
"stylis": "^4.3.1",
|
"stylis": "^4.3.1",
|
||||||
"ts-dedent": "^2.2.0",
|
"ts-dedent": "^2.2.0",
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ export const clear = function () {
|
|||||||
functions.push(setupToolTips);
|
functions.push(setupToolTips);
|
||||||
namespaces = new Map();
|
namespaces = new Map();
|
||||||
namespaceCounter = 0;
|
namespaceCounter = 0;
|
||||||
|
direction = 'TB';
|
||||||
commonClear();
|
commonClear();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -444,6 +444,17 @@ class C13["With Città foreign language"]
|
|||||||
]
|
]
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should revert direction to default once direction is removed', () => {
|
||||||
|
parser.parse(`classDiagram
|
||||||
|
direction RL
|
||||||
|
class A`);
|
||||||
|
expect(classDb.getDirection()).toBe('RL');
|
||||||
|
classDb.clear();
|
||||||
|
parser.parse(`classDiagram
|
||||||
|
class B`);
|
||||||
|
expect(classDb.getDirection()).toBe('TB');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('when parsing class defined in brackets', function () {
|
describe('when parsing class defined in brackets', function () {
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ To add an integration to this list, see the [Integrations - create page](./integ
|
|||||||
- [CloudScript.io Mermaid Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
- [CloudScript.io Mermaid Addon](https://marketplace.atlassian.com/apps/1219878/cloudscript-io-mermaid-addon?hosting=cloud&tab=overview)
|
||||||
- [Azure Devops](https://learn.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) ✅
|
- [Azure Devops](https://learn.microsoft.com/en-us/azure/devops/project/wiki/markdown-guidance?view=azure-devops#add-mermaid-diagrams-to-a-wiki-page) ✅
|
||||||
- [Deepdwn](https://billiam.itch.io/deepdwn) ✅
|
- [Deepdwn](https://billiam.itch.io/deepdwn) ✅
|
||||||
|
- [Doctave](https://www.doctave.com/) ✅
|
||||||
|
- [Mermaid in Markdown code blocks](https://docs.doctave.com/components/mermaid) ✅
|
||||||
- [GitBook](https://gitbook.com)
|
- [GitBook](https://gitbook.com)
|
||||||
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
|
||||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||||
|
|||||||
@@ -288,8 +288,8 @@ a _[valid CSS property name](https://www.w3.org/TR/CSS/#properties)_ followed by
|
|||||||
|
|
||||||
Here is an example of a classDef with just one property-value pair:
|
Here is an example of a classDef with just one property-value pair:
|
||||||
|
|
||||||
```
|
```txt
|
||||||
classDef movement font-style:italic;
|
classDef movement font-style:italic;
|
||||||
```
|
```
|
||||||
|
|
||||||
where
|
where
|
||||||
@@ -301,8 +301,8 @@ If you want to have more than one _property-value pair_ then you put a comma (`,
|
|||||||
|
|
||||||
Here is an example with three property-value pairs:
|
Here is an example with three property-value pairs:
|
||||||
|
|
||||||
```
|
```txt
|
||||||
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
|
||||||
```
|
```
|
||||||
|
|
||||||
where
|
where
|
||||||
@@ -327,7 +327,7 @@ There are two ways to apply a `classDef` style to a state:
|
|||||||
A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is:
|
A `class` statement tells Mermaid to apply the named classDef to one or more classes. The form is:
|
||||||
|
|
||||||
```txt
|
```txt
|
||||||
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
class [one or more state names, separated by commas] [name of a style defined with classDef]
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is an example applying the `badBadEvent` style to a state named `Crash`:
|
Here is an example applying the `badBadEvent` style to a state named `Crash`:
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) {
|
|||||||
wrappedLine.forEach((word, index) => {
|
wrappedLine.forEach((word, index) => {
|
||||||
const innerTspan = tspan
|
const innerTspan = tspan
|
||||||
.append('tspan')
|
.append('tspan')
|
||||||
.attr('font-style', word.type === 'emphasis' ? 'italic' : 'normal')
|
.attr('font-style', word.type === 'em' ? 'italic' : 'normal')
|
||||||
.attr('class', 'text-inner-tspan')
|
.attr('class', 'text-inner-tspan')
|
||||||
.attr('font-weight', word.type === 'strong' ? 'bold' : 'normal');
|
.attr('font-weight', word.type === 'strong' ? 'bold' : 'normal');
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-irregular-whitespace */
|
|
||||||
import { markdownToLines, markdownToHTML } from './handle-markdown-text.js';
|
import { markdownToLines, markdownToHTML } from './handle-markdown-text.js';
|
||||||
import { test, expect } from 'vitest';
|
import { test, expect } from 'vitest';
|
||||||
|
|
||||||
@@ -37,9 +36,9 @@ Here is a line *with an italic* section`;
|
|||||||
{ content: 'is', type: 'normal' },
|
{ content: 'is', type: 'normal' },
|
||||||
{ content: 'a', type: 'normal' },
|
{ content: 'a', type: 'normal' },
|
||||||
{ content: 'line', type: 'normal' },
|
{ content: 'line', type: 'normal' },
|
||||||
{ content: 'with', type: 'emphasis' },
|
{ content: 'with', type: 'em' },
|
||||||
{ content: 'an', type: 'emphasis' },
|
{ content: 'an', type: 'em' },
|
||||||
{ content: 'italic', type: 'emphasis' },
|
{ content: 'italic', type: 'em' },
|
||||||
{ content: 'section', type: 'normal' },
|
{ content: 'section', type: 'normal' },
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
@@ -143,7 +142,7 @@ test('markdownToLines - Only italic formatting', () => {
|
|||||||
{ content: 'This', type: 'normal' },
|
{ content: 'This', type: 'normal' },
|
||||||
{ content: 'is', type: 'normal' },
|
{ content: 'is', type: 'normal' },
|
||||||
{ content: 'an', type: 'normal' },
|
{ content: 'an', type: 'normal' },
|
||||||
{ content: 'italic', type: 'emphasis' },
|
{ content: 'italic', type: 'em' },
|
||||||
{ content: 'test', type: 'normal' },
|
{ content: 'test', type: 'normal' },
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
@@ -156,7 +155,7 @@ it('markdownToLines - Mixed formatting', () => {
|
|||||||
let input = `*Italic* and **bold** formatting`;
|
let input = `*Italic* and **bold** formatting`;
|
||||||
let expected = [
|
let expected = [
|
||||||
[
|
[
|
||||||
{ content: 'Italic', type: 'emphasis' },
|
{ content: 'Italic', type: 'em' },
|
||||||
{ content: 'and', type: 'normal' },
|
{ content: 'and', type: 'normal' },
|
||||||
{ content: 'bold', type: 'strong' },
|
{ content: 'bold', type: 'strong' },
|
||||||
{ content: 'formatting', type: 'normal' },
|
{ content: 'formatting', type: 'normal' },
|
||||||
@@ -167,9 +166,9 @@ it('markdownToLines - Mixed formatting', () => {
|
|||||||
input = `*Italic with space* and **bold ws** formatting`;
|
input = `*Italic with space* and **bold ws** formatting`;
|
||||||
expected = [
|
expected = [
|
||||||
[
|
[
|
||||||
{ content: 'Italic', type: 'emphasis' },
|
{ content: 'Italic', type: 'em' },
|
||||||
{ content: 'with', type: 'emphasis' },
|
{ content: 'with', type: 'em' },
|
||||||
{ content: 'space', type: 'emphasis' },
|
{ content: 'space', type: 'em' },
|
||||||
{ content: 'and', type: 'normal' },
|
{ content: 'and', type: 'normal' },
|
||||||
{ content: 'bold', type: 'strong' },
|
{ content: 'bold', type: 'strong' },
|
||||||
{ content: 'ws', type: 'strong' },
|
{ content: 'ws', type: 'strong' },
|
||||||
@@ -191,9 +190,9 @@ Word!`;
|
|||||||
{ content: 'the', type: 'strong' },
|
{ content: 'the', type: 'strong' },
|
||||||
{ content: 'hog...', type: 'normal' },
|
{ content: 'hog...', type: 'normal' },
|
||||||
{ content: 'a', type: 'normal' },
|
{ content: 'a', type: 'normal' },
|
||||||
{ content: 'very', type: 'emphasis' },
|
{ content: 'very', type: 'em' },
|
||||||
{ content: 'long', type: 'emphasis' },
|
{ content: 'long', type: 'em' },
|
||||||
{ content: 'text', type: 'emphasis' },
|
{ content: 'text', type: 'em' },
|
||||||
{ content: 'about', type: 'normal' },
|
{ content: 'about', type: 'normal' },
|
||||||
{ content: 'it', type: 'normal' },
|
{ content: 'it', type: 'normal' },
|
||||||
],
|
],
|
||||||
@@ -215,13 +214,13 @@ test('markdownToLines - No auto wrapping', () => {
|
|||||||
[
|
[
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"content": "Hello, how do",
|
"content": "Hello, how do",
|
||||||
"type": "normal",
|
"type": "normal",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"content": "you do?",
|
"content": "you do?",
|
||||||
"type": "normal",
|
"type": "normal",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -298,3 +297,13 @@ test('markdownToHTML - no auto wrapping', () => {
|
|||||||
)
|
)
|
||||||
).toMatchInlineSnapshot('"<p>Hello, how do<br/>you do?</p>"');
|
).toMatchInlineSnapshot('"<p>Hello, how do<br/>you do?</p>"');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('markdownToHTML - auto wrapping', () => {
|
||||||
|
expect(
|
||||||
|
markdownToHTML(
|
||||||
|
`Hello, how do
|
||||||
|
you do?`,
|
||||||
|
{ markdownAutoWrap: true }
|
||||||
|
)
|
||||||
|
).toMatchInlineSnapshot('"<p>Hello, how do<br/>you do?</p>"');
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Content } from 'mdast';
|
import type { MarkedToken, Token } from 'marked';
|
||||||
import { fromMarkdown } from 'mdast-util-from-markdown';
|
import { marked } from 'marked';
|
||||||
import { dedent } from 'ts-dedent';
|
import { dedent } from 'ts-dedent';
|
||||||
import type { MarkdownLine, MarkdownWordType } from './types.js';
|
import type { MarkdownLine, MarkdownWordType } from './types.js';
|
||||||
import type { MermaidConfig } from '../config.type.js';
|
import type { MermaidConfig } from '../config.type.js';
|
||||||
@@ -24,13 +24,13 @@ function preprocessMarkdown(markdown: string, { markdownAutoWrap }: MermaidConfi
|
|||||||
*/
|
*/
|
||||||
export function markdownToLines(markdown: string, config: MermaidConfig = {}): MarkdownLine[] {
|
export function markdownToLines(markdown: string, config: MermaidConfig = {}): MarkdownLine[] {
|
||||||
const preprocessedMarkdown = preprocessMarkdown(markdown, config);
|
const preprocessedMarkdown = preprocessMarkdown(markdown, config);
|
||||||
const { children } = fromMarkdown(preprocessedMarkdown);
|
const nodes = marked.lexer(preprocessedMarkdown);
|
||||||
const lines: MarkdownLine[] = [[]];
|
const lines: MarkdownLine[] = [[]];
|
||||||
let currentLine = 0;
|
let currentLine = 0;
|
||||||
|
|
||||||
function processNode(node: Content, parentType: MarkdownWordType = 'normal') {
|
function processNode(node: MarkedToken, parentType: MarkdownWordType = 'normal') {
|
||||||
if (node.type === 'text') {
|
if (node.type === 'text') {
|
||||||
const textLines = node.value.split('\n');
|
const textLines = node.text.split('\n');
|
||||||
textLines.forEach((textLine, index) => {
|
textLines.forEach((textLine, index) => {
|
||||||
if (index !== 0) {
|
if (index !== 0) {
|
||||||
currentLine++;
|
currentLine++;
|
||||||
@@ -42,17 +42,17 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (node.type === 'strong' || node.type === 'emphasis') {
|
} else if (node.type === 'strong' || node.type === 'em') {
|
||||||
node.children.forEach((contentNode) => {
|
node.tokens.forEach((contentNode) => {
|
||||||
processNode(contentNode, node.type);
|
processNode(contentNode as MarkedToken, node.type);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
children.forEach((treeNode) => {
|
nodes.forEach((treeNode) => {
|
||||||
if (treeNode.type === 'paragraph') {
|
if (treeNode.type === 'paragraph') {
|
||||||
treeNode.children.forEach((contentNode) => {
|
treeNode.tokens?.forEach((contentNode) => {
|
||||||
processNode(contentNode);
|
processNode(contentNode as MarkedToken);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -61,25 +61,25 @@ export function markdownToLines(markdown: string, config: MermaidConfig = {}): M
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) {
|
export function markdownToHTML(markdown: string, { markdownAutoWrap }: MermaidConfig = {}) {
|
||||||
const { children } = fromMarkdown(markdown);
|
const nodes = marked.lexer(markdown);
|
||||||
|
|
||||||
function output(node: Content): string {
|
function output(node: Token): string {
|
||||||
if (node.type === 'text') {
|
if (node.type === 'text') {
|
||||||
if (markdownAutoWrap === false) {
|
if (markdownAutoWrap === false) {
|
||||||
return node.value.replace(/\n/g, '<br/>').replace(/ /g, ' ');
|
return node.text.replace(/\n */g, '<br/>').replace(/ /g, ' ');
|
||||||
}
|
}
|
||||||
return node.value.replace(/\n/g, '<br/>');
|
return node.text.replace(/\n */g, '<br/>');
|
||||||
} else if (node.type === 'strong') {
|
} else if (node.type === 'strong') {
|
||||||
return `<strong>${node.children.map(output).join('')}</strong>`;
|
return `<strong>${node.tokens?.map(output).join('')}</strong>`;
|
||||||
} else if (node.type === 'emphasis') {
|
} else if (node.type === 'em') {
|
||||||
return `<em>${node.children.map(output).join('')}</em>`;
|
return `<em>${node.tokens?.map(output).join('')}</em>`;
|
||||||
} else if (node.type === 'paragraph') {
|
} else if (node.type === 'paragraph') {
|
||||||
return `<p>${node.children.map(output).join('')}</p>`;
|
return `<p>${node.tokens?.map(output).join('')}</p>`;
|
||||||
} else if (node.type === 'html') {
|
} else if (node.type === 'html') {
|
||||||
return `${node.value}`;
|
return `${node.text}`;
|
||||||
}
|
}
|
||||||
return `Unsupported markdown: ${node.type}`;
|
return `Unsupported markdown: ${node.type}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return children.map(output).join('');
|
return nodes.map(output).join('');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -563,6 +563,8 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
}
|
}
|
||||||
let svgPath;
|
let svgPath;
|
||||||
let linePath = lineFunction(lineData);
|
let linePath = lineFunction(lineData);
|
||||||
|
//convert to array (if not already)
|
||||||
|
const edgeStyles = Array.isArray(edge.style) ? edge.style : [edge.style];
|
||||||
if (edge.look === 'handdrawn') {
|
if (edge.look === 'handdrawn') {
|
||||||
const rc = rough.svg(elem);
|
const rc = rough.svg(elem);
|
||||||
Object.assign([], lineData);
|
Object.assign([], lineData);
|
||||||
@@ -583,7 +585,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
// .attr('d', lineFunction(lineData))
|
// .attr('d', lineFunction(lineData))
|
||||||
.attr('id', edge.id)
|
.attr('id', edge.id)
|
||||||
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
|
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
|
||||||
.attr('style', edge.style ? edge.style.reduce((acc, style) => acc + ';' + style, '') : '');
|
.attr('style', edgeStyles ? edgeStyles.reduce((acc, style) => acc + ';' + style, '') : '');
|
||||||
let d = svgPath.attr('d');
|
let d = svgPath.attr('d');
|
||||||
svgPath.attr('d', d);
|
svgPath.attr('d', d);
|
||||||
elem.node().appendChild(svgPath.node());
|
elem.node().appendChild(svgPath.node());
|
||||||
@@ -593,7 +595,7 @@ export const insertEdge = function (elem, edge, clusterDb, diagramType, startNod
|
|||||||
.attr('d', linePath)
|
.attr('d', linePath)
|
||||||
.attr('id', edge.id)
|
.attr('id', edge.id)
|
||||||
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
|
.attr('class', ' ' + strokeClasses + (edge.classes ? ' ' + edge.classes : ''))
|
||||||
.attr('style', edge.style ? edge.style.reduce((acc, style) => acc + ';' + style, '') : '');
|
.attr('style', edgeStyles ? edgeStyles.reduce((acc, style) => acc + ';' + style, '') : '');
|
||||||
}
|
}
|
||||||
// DEBUG code, adds a red circle at each edge coordinate
|
// DEBUG code, adds a red circle at each edge coordinate
|
||||||
// cornerPoints.forEach((point) => {
|
// cornerPoints.forEach((point) => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
export type MarkdownWordType = 'normal' | 'strong' | 'em';
|
||||||
import type { MermaidConfig } from '../../dist/config.type';
|
import type { MermaidConfig } from '../../dist/config.type';
|
||||||
export type MarkdownWordType = 'normal' | 'strong' | 'emphasis';
|
|
||||||
export interface MarkdownWord {
|
export interface MarkdownWord {
|
||||||
content: string;
|
content: string;
|
||||||
type: MarkdownWordType;
|
type: MarkdownWordType;
|
||||||
|
|||||||
482
pnpm-lock.yaml
generated
482
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -25,6 +25,7 @@ const formatBytes = (bytes: number): string => {
|
|||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
return '0 Bytes';
|
return '0 Bytes';
|
||||||
}
|
}
|
||||||
|
bytes = Math.abs(bytes);
|
||||||
const base = 1024;
|
const base = 1024;
|
||||||
const decimals = 2;
|
const decimals = 2;
|
||||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
|||||||
Reference in New Issue
Block a user