Merge branch 'develop' into update-class-diagram

This commit is contained in:
Yari DeWalt 2024-10-16 09:43:58 -07:00 committed by GitHub
commit 86c7532f46
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 1072 additions and 577 deletions

View File

@ -1,3 +1,9 @@
export interface PackageOptions {
name: string;
packageName: string;
file: string;
}
/** /**
* Shared common options for both ESBuild and Vite * Shared common options for both ESBuild and Vite
*/ */
@ -27,4 +33,4 @@ export const packageOptions = {
packageName: 'mermaid-layout-elk', packageName: 'mermaid-layout-elk',
file: 'layouts.ts', file: 'layouts.ts',
}, },
} as const; } as const satisfies Record<string, PackageOptions>;

View File

@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Jagged edge fix for icon shape

View File

@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Icon color fix for colored icons.

View File

@ -8,7 +8,10 @@ import { defaultOptions, getBuildConfig } from './util.js';
const shouldVisualize = process.argv.includes('--visualize'); const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => { const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions: MermaidBuildOptions = { ...defaultOptions, entryName } as const; const commonOptions: MermaidBuildOptions = {
...defaultOptions,
options: packageOptions[entryName],
} as const;
const buildConfigs: MermaidBuildOptions[] = [ const buildConfigs: MermaidBuildOptions[] = [
// package.mjs // package.mjs
{ ...commonOptions }, { ...commonOptions },
@ -40,7 +43,7 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
continue; continue;
} }
const fileName = Object.keys(metafile.outputs) const fileName = Object.keys(metafile.outputs)
.find((file) => !file.includes('chunks') && file.endsWith('js')) .find((file) => !file.includes('chunks') && file.endsWith('js'))!
.replace('dist/', ''); .replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/ // Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile)); await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));

View File

@ -9,13 +9,18 @@ import { generateLangium } from '../.build/generateLangium.js';
import { defaultOptions, getBuildConfig } from './util.js'; import { defaultOptions, getBuildConfig } from './util.js';
const configs = Object.values(packageOptions).map(({ packageName }) => const configs = Object.values(packageOptions).map(({ packageName }) =>
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName }) getBuildConfig({
...defaultOptions,
minify: false,
core: false,
options: packageOptions[packageName],
})
); );
const mermaidIIFEConfig = getBuildConfig({ const mermaidIIFEConfig = getBuildConfig({
...defaultOptions, ...defaultOptions,
minify: false, minify: false,
core: false, core: false,
entryName: 'mermaid', options: packageOptions.mermaid,
format: 'iife', format: 'iife',
}); });
configs.push(mermaidIIFEConfig); configs.push(mermaidIIFEConfig);

View File

@ -3,7 +3,7 @@ import { fileURLToPath } from 'url';
import type { BuildOptions } from 'esbuild'; import type { BuildOptions } from 'esbuild';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import jsonSchemaPlugin from './jsonSchemaPlugin.js'; import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import { packageOptions } from '../.build/common.js'; import type { PackageOptions } from '../.build/common.js';
import { jisonPlugin } from './jisonPlugin.js'; import { jisonPlugin } from './jisonPlugin.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url)); const __dirname = fileURLToPath(new URL('.', import.meta.url));
@ -13,10 +13,10 @@ export interface MermaidBuildOptions extends BuildOptions {
core: boolean; core: boolean;
metafile: boolean; metafile: boolean;
format: 'esm' | 'iife'; format: 'esm' | 'iife';
entryName: keyof typeof packageOptions; options: PackageOptions;
} }
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = { export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = {
minify: false, minify: false,
metafile: false, metafile: false,
core: false, core: false,
@ -52,9 +52,14 @@ const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOpt
}; };
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const { core, entryName, metafile, format, minify } = options; const {
core,
metafile,
format,
minify,
options: { name, file, packageName },
} = options;
const external: string[] = ['require', 'fs', 'path']; const external: string[] = ['require', 'fs', 'path'];
const { name, file, packageName } = packageOptions[entryName];
const outFileName = getFileName(name, options); const outFileName = getFileName(name, options);
const output: BuildOptions = buildOptions({ const output: BuildOptions = buildOptions({
absWorkingDir: resolve(__dirname, `../packages/${packageName}`), absWorkingDir: resolve(__dirname, `../packages/${packageName}`),

View File

@ -124,3 +124,20 @@ describe('Test iconShape with different h', () => {
imgSnapshotTest(flowchartCode); imgSnapshotTest(flowchartCode);
}); });
}); });
describe('Test colored iconShape', () => {
it('with no styles', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fluent-emoji:tropical-fish';
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
imgSnapshotTest(flowchartCode);
});
it('with styles', () => {
let flowchartCode = `flowchart TB\n`;
const icon = 'fluent-emoji:tropical-fish';
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`;
imgSnapshotTest(flowchartCode);
});
});

File diff suppressed because one or more lines are too long

View File

@ -101,7 +101,7 @@ To add a new shape:
- **Example**: - **Example**:
```typescript ```typescript
import { Node, RenderOptions } from '../../types.d.ts'; import { Node, RenderOptions } from '../../types.ts';
export const myNewShape = async ( export const myNewShape = async (
parent: SVGAElement, parent: SVGAElement,
@ -117,7 +117,7 @@ To add a new shape:
### 2. Register the Shape ### 2. Register the Shape
- **Register the shape**: Add your shape to the `shapes` object in the main shapes module. This allows your shape to be recognized and used within the system. - **Register the shape**: Add your shape to the `shapes` object in the [main shapes module](../rendering-util/rendering-elements/shapes.ts). This allows your shape to be recognized and used within the system.
- **Example**: - **Example**:
@ -126,9 +126,14 @@ To add a new shape:
const shapes = { const shapes = {
..., ...,
'my-new-shape': myNewShape, {
// Shortened alias (if any). semanticName: 'My Shape',
'm-nsh': myNewShape name: 'Shape Name',
shortName: '<short-name>',
description: '<Description for the shape>',
aliases: ['<alias-one>', '<al-on>', '<alias-two>', '<al-two>'],
handler: myNewShape,
},
}; };
``` ```

55
docs/config/icons.md Normal file
View File

@ -0,0 +1,55 @@
> **Warning**
>
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/icons.md](../../packages/mermaid/src/docs/config/icons.md).
# Registering icon pack in mermaid
The icon packs available can be found at [icones.js.org](https://icones.js.org/).
We use the name defined when registering the icon pack, to override the prefix field of the iconify pack. This allows the user to use shorter names for the icons. It also allows us to load a particular pack only when it is used in a diagram.
Using JSON file directly from CDN:
```js
import mermaid from 'CDN/mermaid.esm.mjs';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()),
},
]);
```
Using packages and a bundler:
```bash
npm install @iconify-json/logos@1
```
With lazy loading
```js
import mermaid from 'mermaid';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () => import('@iconify-json/logos').then((module) => module.icons),
},
]);
```
Without lazy loading
```js
import mermaid from 'mermaid';
import { icons } from '@iconify-json/logos';
mermaid.registerIconPacks([
{
name: icons.prefix, // To use the prefix defined in the icon pack
icons,
},
]);
```

View File

@ -79,15 +79,15 @@ service {service id}({icon name})[{title}] (in {parent id})?
Put together: Put together:
``` ```
service database(db)[Database] service database1(database)[My Database]
``` ```
creates the service identified as `database`, using the icon `db`, with the label `Database`. creates the service identified as `database1`, using the icon `database`, with the label `My Database`.
If the service belongs to a group, it can be placed inside it through the optional `in` keyword If the service belongs to a group, it can be placed inside it through the optional `in` keyword
``` ```
service database(db)[Database] in private_api service database1(database)[My Database] in private_api
``` ```
### Edges ### Edges
@ -194,55 +194,7 @@ architecture-beta
## Icons ## Icons
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`. By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
Users can use any of the 200,000+ icons available in iconify.design, or add their own custom icons, by following the steps below. Users can use any of the 200,000+ icons available in iconify.design, or add their own custom icons, by following the steps [here](../config/icons.md).
The icon packs available can be found at [icones.js.org](https://icones.js.org/).
We use the name defined when registering the icon pack, to override the prefix field of the iconify pack. This allows the user to use shorter names for the icons. It also allows us to load a particular pack only when it is used in a diagram.
Using JSON file directly from CDN:
```js
import mermaid from 'CDN/mermaid.esm.mjs';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
]);
```
Using packages and a bundler:
```bash
npm install @iconify-json/logos
```
With lazy loading
```js
import mermaid from 'mermaid';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () => import('@iconify-json/logos').then((module) => module.icons),
},
]);
```
Without lazy loading
```js
import mermaid from 'mermaid';
import { icons } from '@iconify-json/logos';
mermaid.registerIconPacks([
{
name: icons.prefix, // To use the prefix defined in the icon pack
icons,
},
]);
```
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack. After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.

View File

@ -317,52 +317,52 @@ This syntax creates a node A as a rectangle. It renders in the same way as `A["A
Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases: Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases:
| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** | | **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** |
| ------------------------------------- | ---------------------- | -------------- | ------------------------------ | -------------------------------------------------------------- | | --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- |
| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` | | Card | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` |
| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` | | Collate | Hourglass | `hourglass` | Represents a collate operation | `collate`, `hourglass` |
| **Terminal Point** | Stadium | `stadium` | Terminal point | `terminal`, `pill` | | Com Link | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` |
| **Subprocess** | Framed Rectangle | `fr-rect` | Subprocess | `subprocess`,`subproc`, `framed-rectangle`, `subroutine` | | Comment | Curly Brace | `brace` | Adds a comment | `brace-l`, `comment` |
| **Database** | Cylinder | `cyl` | Database storage | `db`, `database`, `cylinder` | | Comment Right | Curly Brace | `brace-r` | Adds a comment | |
| **Start** | Circle | `circle` | Starting point | `circ` | | Comment with braces on both sides | Curly Braces | `braces` | Adds a comment | |
| **Odd** | Odd | `odd` | Odd shape | | | Data Input/Output | Lean Right | `lean-r` | Represents input or output | `in-out`, `lean-right` |
| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` | | Data Input/Output | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` |
| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` | | Database | Cylinder | `cyl` | Database storage | `cylinder`, `database`, `db` |
| **Data Input/Output** | Lean Right | `lean-r` | Represents input or output | `lean-right`, `in-out` | | Decision | Diamond | `diam` | Decision-making step | `decision`, `diamond`, `question` |
| **Data Input/Output** | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` | | Delay | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` |
| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom` | | Direct Access Storage | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` |
| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top` | | Disk Storage | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` |
| **Stop** | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` | | Display | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` |
| **Text Block** | Text Block | `text` | Text block | - | | Divided Process | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-process`, `divided-rectangle` |
| **Card** | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` | | Document | Document | `doc` | Represents a document | `doc`, `document` |
| **Lined/Shaded Process** | Lined Rectangle | `lin-rect` | Lined process shape | `lined-rectangle`,`lined-process`, `lin-proc`,`shaded-process` | | Event | Rounded Rectangle | `rounded` | Represents an event | `event` |
| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` | | Extract | Triangle | `tri` | Extraction process | `extract`, `triangle` |
| **Stop** | Framed Circle | `fr-circ` | Stop point | `stop`, `framed-circle` | | Fork/Join | Filled Rectangle | `fork` | Fork or join in process flow | `join` |
| **Fork/Join** | Filled Rectangle | `fork` | Fork or join in process flow | `join` | | Internal Storage | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` |
| **Collate** | Hourglass | `hourglass` | Represents a collate operation | `hourglass` | | Junction | Filled Circle | `f-circ` | Junction point | `filled-circle`, `junction` |
| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` | | Lined Document | Lined Document | `lin-doc` | Lined document | `lined-document` |
| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - | | Lined/Shaded Process | Lined Rectangle | `lin-rect` | Lined process shape | `lin-proc`, `lined-process`, `lined-rectangle`, `shaded-process` |
| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - | | Loop Limit | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` |
| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` | | Manual File | Flipped Triangle | `flip-tri` | Manual file operation | `flipped-triangle`, `manual-file` |
| **Document** | Document | `doc` | Represents a document | `doc`, `document` | | Manual Input | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` |
| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` | | Manual Operation | Trapezoid Base Top | `trap-t` | Represents a manual task | `inv-trapezoid`, `manual`, `trapezoid-top` |
| **Direct Access Storage** | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` | | Multi-Document | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` |
| **Disk Storage** | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` | | Multi-Process | Stacked Rectangle | `st-rect` | Multiple processes | `processes`, `procs`, `stacked-rectangle` |
| **Display** | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` | | Odd | Odd | `odd` | Odd shape | |
| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle`, `divided-process` | | Paper Tape | Flag | `flag` | Paper tape | `paper-tape` |
| **Extract** | Triangle | `tri` | Extraction process | `extract`, `triangle` | | Prepare Conditional | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` |
| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` | | Priority Action | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid`, `trapezoid-bottom` |
| **Junction** | Filled Circle | `f-circ` | Junction point | `junction`, `filled-circle` | | Process | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` |
| **Lined Document** | Lined Document | `lin-doc` | Lined document | `lined-document` | | Start | Circle | `circle` | Starting point | `circ` |
| **Loop Limit** | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` | | Start | Small Circle | `sm-circ` | Small starting point | `small-circle`, `start` |
| **Manual File** | Flipped Triangle | `flip-tri` | Manual file operation | `manual-file`, `flipped-triangle` | | Stop | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` |
| **Manual Input** | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` | | Stop | Framed Circle | `fr-circ` | Stop point | `framed-circle`, `stop` |
| **Multi-Document** | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` | | Stored Data | Bow Tie Rectangle | `bow-rect` | Stored data | `bow-tie-rectangle`, `stored-data` |
| **Multi-Process** | Stacked Rectangle | `st-rect` | Multiple processes | `procs`, `processes`, `stacked-rectangle` | | Subprocess | Framed Rectangle | `fr-rect` | Subprocess | `framed-rectangle`, `subproc`, `subprocess`, `subroutine` |
| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape` | | Summary | Crossed Circle | `cross-circ` | Summary | `crossed-circle`, `summary` |
| **Stored Data** | Bow Tie Rectangle | `bow-rect` | Stored data | `stored-data`, `bow-tie-rectangle` | | Tagged Document | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` |
| **Summary** | Crossed Circle | `cross-circ` | Summary | `summary`, `crossed-circle` | | Tagged Process | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-process`, `tagged-rectangle` |
| **Tagged Document** | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` | | Terminal Point | Stadium | `stadium` | Terminal point | `pill`, `terminal` |
| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tagged-rectangle`,`tag-proc`, `tagged-process` | | Text Block | Text Block | `text` | Text block | |
### Example Flowchart with New Shapes ### Example Flowchart with New Shapes
@ -926,6 +926,66 @@ flowchart TD
A@{ shape: tag-rect, label: "Tagged process" } A@{ shape: tag-rect, label: "Tagged process" }
``` ```
## Special shapes in Mermaid Flowcharts (v11.3.0+)
Mermaid also introduces 2 special shapes to enhance your flowcharts: **icon** and **image**. These shapes allow you to include icons and images directly within your flowcharts, providing more visual context and clarity.
### Icon Shape
You can use the `icon` shape to include an icon in your flowchart. To use icons, you need to register the icon pack first. Follow the instructions provided [here](../config/icons.md). The syntax for defining an icon shape is as follows:
```mermaid-example
flowchart TD
A@{ icon: "fa:user", form: "square", label: "User Icon", pos: "t", h: 60 }
```
```mermaid
flowchart TD
A@{ icon: "fa:user", form: "square", label: "User Icon", pos: "t", h: 60 }
```
### Parameters
- **icon**: The name of the icon from the registered icon pack.
- **form**: Specifies the background shape of the icon. If not defined there will be no background to icon. Options include:
- `square`
- `circle`
- `rounded`
- **label**: The text label associated with the icon. This can be any string. If not defined, no label will be displayed.
- **pos**: The position of the label. If not defined label will default to bottom of icon. Possible values are:
- `t`
- `b`
- **h**: The height of the icon. If not defined this will default to 48 which is minimum.
### Image Shape
You can use the `image` shape to include an image in your flowchart. The syntax for defining an image shape is as follows:
```mermaid-example
flowchart TD
A@{ img: "https://example.com/image.png", label: "Image Label", pos: "t", w: 60, h: 60, constraint: "off" }
```
```mermaid
flowchart TD
A@{ img: "https://example.com/image.png", label: "Image Label", pos: "t", w: 60, h: 60, constraint: "off" }
```
### Parameters
- **img**: The URL of the image to be displayed.
- **label**: The text label associated with the image. This can be any string. If not defined, no label will be displayed.
- **pos**: The position of the label. If not defined, the label will default to the bottom of the image. Possible values are:
- `t`
- `b`
- **w**: The width of the image. If not defined, this will default to the natural width of the image.
- **h**: The height of the image. If not defined, this will default to the natural height of the image.
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are:
- `on`
- `off`
These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging.
## Links between nodes ## Links between nodes
Nodes can be connected with links/edges. It is possible to have different types of links or attach a text string to a link. Nodes can be connected with links/edges. It is possible to have different types of links or attach a text string to a link.

View File

@ -35,8 +35,8 @@
"clean": "rimraf dist", "clean": "rimraf dist",
"dev": "pnpm -w dev", "dev": "pnpm -w dev",
"docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaid.ts && prettier --write ./src/docs/config/setup", "docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaid.ts && prettier --write ./src/docs/config/setup",
"docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && tsx scripts/docs.cli.mts", "docs:build": "rimraf ../../docs && pnpm docs:code && pnpm docs:spellcheck && tsx scripts/docs.cli.mts",
"docs:verify": "pnpm docs:spellcheck && pnpm docs:code && tsx scripts/docs.cli.mts --verify", "docs:verify": "pnpm docs:code && pnpm docs:spellcheck && tsx scripts/docs.cli.mts --verify",
"docs:pre:vitepress": "pnpm --filter ./src/docs prefetch && rimraf src/vitepress && pnpm docs:code && tsx scripts/docs.cli.mts --vitepress && pnpm --filter ./src/vitepress install --no-frozen-lockfile --ignore-scripts", "docs:pre:vitepress": "pnpm --filter ./src/docs prefetch && rimraf src/vitepress && pnpm docs:code && tsx scripts/docs.cli.mts --vitepress && pnpm --filter ./src/vitepress install --no-frozen-lockfile --ignore-scripts",
"docs:build:vitepress": "pnpm docs:pre:vitepress && (cd src/vitepress && pnpm run build) && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing", "docs:build:vitepress": "pnpm docs:pre:vitepress && (cd src/vitepress && pnpm run build) && cpy --flat src/docs/landing/ ./src/vitepress/.vitepress/dist/landing",
"docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev\" \"tsx scripts/docs.cli.mts --watch --vitepress\"", "docs:dev": "pnpm docs:pre:vitepress && concurrently \"pnpm --filter ./src/vitepress dev\" \"tsx scripts/docs.cli.mts --watch --vitepress\"",

View File

@ -41,7 +41,8 @@ import { exec } from 'child_process';
import { globby } from 'globby'; import { globby } from 'globby';
import { JSDOM } from 'jsdom'; import { JSDOM } from 'jsdom';
import { dump, load, JSON_SCHEMA } from 'js-yaml'; import { dump, load, JSON_SCHEMA } from 'js-yaml';
import type { Code, ListItem, Root, Text, YAML } from 'mdast'; import type { Code, ListItem, PhrasingContent, Root, Text, YAML } from 'mdast';
import { register } from 'node:module';
import { posix, dirname, relative, join } from 'path'; import { posix, dirname, relative, join } from 'path';
import prettier from 'prettier'; import prettier from 'prettier';
import { remark } from 'remark'; import { remark } from 'remark';
@ -53,6 +54,10 @@ import mm from 'micromatch';
import flatmap from 'unist-util-flatmap'; import flatmap from 'unist-util-flatmap';
import { visit } from 'unist-util-visit'; import { visit } from 'unist-util-visit';
// short-circuit `.schema.yaml` imports, so that we can safely import `shapes.js`
register('./loadHook.mjs', import.meta.url);
const { shapesDefs } = await import('../src/rendering-util/rendering-elements/shapes.js');
export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8')) export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8'))
.version as string; .version as string;
const MERMAID_MAJOR_VERSION = MERMAID_RELEASE_VERSION.split('.')[0]; const MERMAID_MAJOR_VERSION = MERMAID_RELEASE_VERSION.split('.')[0];
@ -103,6 +108,60 @@ const generateHeader = (file: string): string => {
> ## Please edit the corresponding file in [${filePathFromRoot}](${sourcePathRelativeToGenerated}).`; > ## Please edit the corresponding file in [${filePathFromRoot}](${sourcePathRelativeToGenerated}).`;
}; };
/**
* Builds a markdown list of shapes supported in flowcharts.
*/
export function buildShapeDoc() {
const data = shapesDefs
.sort((a, b) => a.semanticName.localeCompare(b.semanticName))
.map((shape): PhrasingContent[][] => {
const { name, semanticName, description, shortName, aliases = [] } = shape;
return [
[{ type: 'text', value: semanticName }],
[{ type: 'text', value: name }],
[{ type: 'inlineCode', value: shortName }],
[{ type: 'text', value: description }],
aliases.sort().flatMap((alias, index) => [
...(index !== 0 ? ([{ type: 'text', value: ', ' }] as const) : []),
{
type: 'inlineCode',
value: alias,
},
]),
];
});
// don't prettify this table, since we'd do it later
return remark()
.use(remarkGfm)
.stringify({
type: 'root',
children: [
{
type: 'table',
children: [
['Semantic Name', 'Shape Name', 'Short Name', 'Description', 'Alias Supported'].map(
(s): PhrasingContent[] => [
{
type: 'strong',
children: [{ type: 'text', value: s }],
},
]
),
...data,
].map((row) => ({
type: 'tableRow',
children: row.map((cell) => ({
type: 'tableCell',
children: cell,
})),
})),
},
],
})
.toString();
}
/** /**
* Given a source file name and path, return the documentation destination full path and file name * Given a source file name and path, return the documentation destination full path and file name
* Create the destination path if it does not already exist. * Create the destination path if it does not already exist.
@ -192,10 +251,22 @@ export const transformToBlockQuote = (
const injectPlaceholders = (text: string): string => const injectPlaceholders = (text: string): string =>
text.replace(/<MERMAID_VERSION>/g, MERMAID_MAJOR_VERSION).replace(/<CDN_URL>/g, CDN_URL); text.replace(/<MERMAID_VERSION>/g, MERMAID_MAJOR_VERSION).replace(/<CDN_URL>/g, CDN_URL);
const virtualGenerators: Record<string, () => string> = {
shapesTable: buildShapeDoc,
};
const transformIncludeStatements = (file: string, text: string): string => { const transformIncludeStatements = (file: string, text: string): string => {
// resolve includes - src https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L65-L76 // resolve includes - src https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L65-L76
return text.replace(includesRE, (m, m1) => { return text.replace(includesRE, (m, m1: string) => {
try { try {
if (m1.startsWith('virtual:')) {
const key = m1.replace('virtual:', '');
const generator = virtualGenerators[key];
if (!generator) {
throw new Error(`Unknown virtual generator: ${key} in "${file}"`);
}
return generator();
}
const includePath = join(dirname(file), m1).replaceAll('\\', '/'); const includePath = join(dirname(file), m1).replaceAll('\\', '/');
const content = readSyncedUTF8file(includePath); const content = readSyncedUTF8file(includePath);
includedFiles.add(changeToFinalDocDir(includePath)); includedFiles.add(changeToFinalDocDir(includePath));

View File

@ -1,4 +1,4 @@
import { transformMarkdownAst, transformToBlockQuote } from './docs.mjs'; import { buildShapeDoc, transformMarkdownAst, transformToBlockQuote } from './docs.mjs';
import { remark } from 'remark'; // import it this way so we can mock it import { remark } from 'remark'; // import it this way so we can mock it
import remarkFrontmatter from 'remark-frontmatter'; import remarkFrontmatter from 'remark-frontmatter';
@ -165,4 +165,59 @@ This Markdown should be kept.
}); });
}); });
}); });
describe('buildShapeDoc', () => {
it('should build shapesTable based on the shapeDefs', () => {
expect(buildShapeDoc()).toMatchInlineSnapshot(`
"| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** |
| --------------------------------- | ---------------------- | -------------- | ------------------------------ | ---------------------------------------------------------------- |
| Card | Notched Rectangle | \`notch-rect\` | Represents a card | \`card\`, \`notched-rectangle\` |
| Collate | Hourglass | \`hourglass\` | Represents a collate operation | \`collate\`, \`hourglass\` |
| Com Link | Lightning Bolt | \`bolt\` | Communication link | \`com-link\`, \`lightning-bolt\` |
| Comment | Curly Brace | \`brace\` | Adds a comment | \`brace-l\`, \`comment\` |
| Comment Right | Curly Brace | \`brace-r\` | Adds a comment | |
| Comment with braces on both sides | Curly Braces | \`braces\` | Adds a comment | |
| Data Input/Output | Lean Right | \`lean-r\` | Represents input or output | \`in-out\`, \`lean-right\` |
| Data Input/Output | Lean Left | \`lean-l\` | Represents output or input | \`lean-left\`, \`out-in\` |
| Database | Cylinder | \`cyl\` | Database storage | \`cylinder\`, \`database\`, \`db\` |
| Decision | Diamond | \`diam\` | Decision-making step | \`decision\`, \`diamond\`, \`question\` |
| Delay | Half-Rounded Rectangle | \`delay\` | Represents a delay | \`half-rounded-rectangle\` |
| Direct Access Storage | Horizontal Cylinder | \`h-cyl\` | Direct access storage | \`das\`, \`horizontal-cylinder\` |
| Disk Storage | Lined Cylinder | \`lin-cyl\` | Disk storage | \`disk\`, \`lined-cylinder\` |
| Display | Curved Trapezoid | \`curv-trap\` | Represents a display | \`curved-trapezoid\`, \`display\` |
| Divided Process | Divided Rectangle | \`div-rect\` | Divided process shape | \`div-proc\`, \`divided-process\`, \`divided-rectangle\` |
| Document | Document | \`doc\` | Represents a document | \`doc\`, \`document\` |
| Event | Rounded Rectangle | \`rounded\` | Represents an event | \`event\` |
| Extract | Triangle | \`tri\` | Extraction process | \`extract\`, \`triangle\` |
| Fork/Join | Filled Rectangle | \`fork\` | Fork or join in process flow | \`join\` |
| Internal Storage | Window Pane | \`win-pane\` | Internal storage | \`internal-storage\`, \`window-pane\` |
| Junction | Filled Circle | \`f-circ\` | Junction point | \`filled-circle\`, \`junction\` |
| Lined Document | Lined Document | \`lin-doc\` | Lined document | \`lined-document\` |
| Lined/Shaded Process | Lined Rectangle | \`lin-rect\` | Lined process shape | \`lin-proc\`, \`lined-process\`, \`lined-rectangle\`, \`shaded-process\` |
| Loop Limit | Trapezoidal Pentagon | \`notch-pent\` | Loop limit step | \`loop-limit\`, \`notched-pentagon\` |
| Manual File | Flipped Triangle | \`flip-tri\` | Manual file operation | \`flipped-triangle\`, \`manual-file\` |
| Manual Input | Sloped Rectangle | \`sl-rect\` | Manual input step | \`manual-input\`, \`sloped-rectangle\` |
| Manual Operation | Trapezoid Base Top | \`trap-t\` | Represents a manual task | \`inv-trapezoid\`, \`manual\`, \`trapezoid-top\` |
| Multi-Document | Stacked Document | \`docs\` | Multiple documents | \`documents\`, \`st-doc\`, \`stacked-document\` |
| Multi-Process | Stacked Rectangle | \`st-rect\` | Multiple processes | \`processes\`, \`procs\`, \`stacked-rectangle\` |
| Odd | Odd | \`odd\` | Odd shape | |
| Paper Tape | Flag | \`flag\` | Paper tape | \`paper-tape\` |
| Prepare Conditional | Hexagon | \`hex\` | Preparation or condition step | \`hexagon\`, \`prepare\` |
| Priority Action | Trapezoid Base Bottom | \`trap-b\` | Priority action | \`priority\`, \`trapezoid\`, \`trapezoid-bottom\` |
| Process | Rectangle | \`rect\` | Standard process shape | \`proc\`, \`process\`, \`rectangle\` |
| Start | Circle | \`circle\` | Starting point | \`circ\` |
| Start | Small Circle | \`sm-circ\` | Small starting point | \`small-circle\`, \`start\` |
| Stop | Double Circle | \`dbl-circ\` | Represents a stop point | \`double-circle\` |
| Stop | Framed Circle | \`fr-circ\` | Stop point | \`framed-circle\`, \`stop\` |
| Stored Data | Bow Tie Rectangle | \`bow-rect\` | Stored data | \`bow-tie-rectangle\`, \`stored-data\` |
| Subprocess | Framed Rectangle | \`fr-rect\` | Subprocess | \`framed-rectangle\`, \`subproc\`, \`subprocess\`, \`subroutine\` |
| Summary | Crossed Circle | \`cross-circ\` | Summary | \`crossed-circle\`, \`summary\` |
| Tagged Document | Tagged Document | \`tag-doc\` | Tagged document | \`tag-doc\`, \`tagged-document\` |
| Tagged Process | Tagged Rectangle | \`tag-rect\` | Tagged process | \`tag-proc\`, \`tagged-process\`, \`tagged-rectangle\` |
| Terminal Point | Stadium | \`stadium\` | Terminal point | \`pill\`, \`terminal\` |
| Text Block | Text Block | \`text\` | Text block | |
"
`);
});
});
}); });

View File

@ -0,0 +1,22 @@
import { fileURLToPath } from 'node:url';
/** @import import { LoadHook } from "node:module"; */
/**
* @type {LoadHook}
*
* Load hook that short circuits the loading of `.schema.yaml` files with `export default {}`.
* These would normally be loaded using ESBuild, but that doesn't work for these local scripts.
*
* @see https://nodejs.org/api/module.html#loadurl-context-nextload
*/
export const load = async (url, context, nextLoad) => {
const filePath = url.startsWith('file://') ? fileURLToPath(url) : url;
if (filePath.endsWith('.schema.yaml')) {
return {
format: 'module',
shortCircuit: true,
source: `export default {}`,
};
} else {
return await nextLoad(url, context);
}
};

View File

@ -174,6 +174,7 @@ function sidebarConfig() {
{ text: 'API-Usage', link: '/config/usage' }, { text: 'API-Usage', link: '/config/usage' },
{ text: 'Mermaid API Configuration', link: '/config/setup/README' }, { text: 'Mermaid API Configuration', link: '/config/setup/README' },
{ text: 'Mermaid Configuration Options', link: '/config/schema-docs/config' }, { text: 'Mermaid Configuration Options', link: '/config/schema-docs/config' },
{ text: 'Registering icons', link: '/config/icons' },
{ text: 'Directives', link: '/config/directives' }, { text: 'Directives', link: '/config/directives' },
{ text: 'Theming', link: '/config/theming' }, { text: 'Theming', link: '/config/theming' },
{ text: 'Math', link: '/config/math' }, { text: 'Math', link: '/config/math' },

View File

@ -95,7 +95,7 @@ To add a new shape:
- **Example**: - **Example**:
```typescript ```typescript
import { Node, RenderOptions } from '../../types.d.ts'; import { Node, RenderOptions } from '../../types.ts';
export const myNewShape = async ( export const myNewShape = async (
parent: SVGAElement, parent: SVGAElement,
@ -111,7 +111,7 @@ To add a new shape:
### 2. Register the Shape ### 2. Register the Shape
- **Register the shape**: Add your shape to the `shapes` object in the main shapes module. This allows your shape to be recognized and used within the system. - **Register the shape**: Add your shape to the `shapes` object in the [main shapes module](../rendering-util/rendering-elements/shapes.ts). This allows your shape to be recognized and used within the system.
- **Example**: - **Example**:
@ -120,9 +120,14 @@ To add a new shape:
const shapes = { const shapes = {
..., ...,
'my-new-shape': myNewShape, {
// Shortened alias (if any). semanticName: 'My Shape',
'm-nsh': myNewShape name: 'Shape Name',
shortName: '<short-name>',
description: '<Description for the shape>',
aliases: ['<alias-one>', '<al-on>', '<alias-two>', '<al-two>'],
handler: myNewShape,
},
}; };
``` ```

View File

@ -0,0 +1,49 @@
# Registering icon pack in mermaid
The icon packs available can be found at [icones.js.org](https://icones.js.org/).
We use the name defined when registering the icon pack, to override the prefix field of the iconify pack. This allows the user to use shorter names for the icons. It also allows us to load a particular pack only when it is used in a diagram.
Using JSON file directly from CDN:
```js
import mermaid from 'CDN/mermaid.esm.mjs';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()),
},
]);
```
Using packages and a bundler:
```bash
npm install @iconify-json/logos@1
```
With lazy loading
```js
import mermaid from 'mermaid';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () => import('@iconify-json/logos').then((module) => module.icons),
},
]);
```
Without lazy loading
```js
import mermaid from 'mermaid';
import { icons } from '@iconify-json/logos';
mermaid.registerIconPacks([
{
name: icons.prefix, // To use the prefix defined in the icon pack
icons,
},
]);
```

View File

@ -59,15 +59,15 @@ service {service id}({icon name})[{title}] (in {parent id})?
Put together: Put together:
``` ```
service database(db)[Database] service database1(database)[My Database]
``` ```
creates the service identified as `database`, using the icon `db`, with the label `Database`. creates the service identified as `database1`, using the icon `database`, with the label `My Database`.
If the service belongs to a group, it can be placed inside it through the optional `in` keyword If the service belongs to a group, it can be placed inside it through the optional `in` keyword
``` ```
service database(db)[Database] in private_api service database1(database)[My Database] in private_api
``` ```
### Edges ### Edges
@ -156,55 +156,7 @@ architecture-beta
## Icons ## Icons
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`. By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
Users can use any of the 200,000+ icons available in iconify.design, or add their own custom icons, by following the steps below. Users can use any of the 200,000+ icons available in iconify.design, or add their own custom icons, by following the steps [here](../config/icons.md).
The icon packs available can be found at [icones.js.org](https://icones.js.org/).
We use the name defined when registering the icon pack, to override the prefix field of the iconify pack. This allows the user to use shorter names for the icons. It also allows us to load a particular pack only when it is used in a diagram.
Using JSON file directly from CDN:
```js
import mermaid from 'CDN/mermaid.esm.mjs';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
]);
```
Using packages and a bundler:
```bash
npm install @iconify-json/logos
```
With lazy loading
```js
import mermaid from 'mermaid';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () => import('@iconify-json/logos').then((module) => module.icons),
},
]);
```
Without lazy loading
```js
import mermaid from 'mermaid';
import { icons } from '@iconify-json/logos';
mermaid.registerIconPacks([
{
name: icons.prefix, // To use the prefix defined in the icon pack
icons,
},
]);
```
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack. After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.

View File

@ -212,53 +212,7 @@ This syntax creates a node A as a rectangle. It renders in the same way as `A["A
Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases: Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases:
| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** | <!--@include: virtual:shapesTable -->
| ------------------------------------- | ---------------------- | -------------- | ------------------------------ | -------------------------------------------------------------- |
| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` |
| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` |
| **Terminal Point** | Stadium | `stadium` | Terminal point | `terminal`, `pill` |
| **Subprocess** | Framed Rectangle | `fr-rect` | Subprocess | `subprocess`,`subproc`, `framed-rectangle`, `subroutine` |
| **Database** | Cylinder | `cyl` | Database storage | `db`, `database`, `cylinder` |
| **Start** | Circle | `circle` | Starting point | `circ` |
| **Odd** | Odd | `odd` | Odd shape | |
| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` |
| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` |
| **Data Input/Output** | Lean Right | `lean-r` | Represents input or output | `lean-right`, `in-out` |
| **Data Input/Output** | Lean Left | `lean-l` | Represents output or input | `lean-left`, `out-in` |
| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom` |
| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top` |
| **Stop** | Double Circle | `dbl-circ` | Represents a stop point | `double-circle` |
| **Text Block** | Text Block | `text` | Text block | - |
| **Card** | Notched Rectangle | `notch-rect` | Represents a card | `card`, `notched-rectangle` |
| **Lined/Shaded Process** | Lined Rectangle | `lin-rect` | Lined process shape | `lined-rectangle`,`lined-process`, `lin-proc`,`shaded-process` |
| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` |
| **Stop** | Framed Circle | `fr-circ` | Stop point | `stop`, `framed-circle` |
| **Fork/Join** | Filled Rectangle | `fork` | Fork or join in process flow | `join` |
| **Collate** | Hourglass | `hourglass` | Represents a collate operation | `hourglass` |
| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` |
| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - |
| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - |
| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` |
| **Document** | Document | `doc` | Represents a document | `doc`, `document` |
| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rectangle` |
| **Direct Access Storage** | Horizontal Cylinder | `h-cyl` | Direct access storage | `das`, `horizontal-cylinder` |
| **Disk Storage** | Lined Cylinder | `lin-cyl` | Disk storage | `disk`, `lined-cylinder` |
| **Display** | Curved Trapezoid | `curv-trap` | Represents a display | `curved-trapezoid`, `display` |
| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle`, `divided-process` |
| **Extract** | Triangle | `tri` | Extraction process | `extract`, `triangle` |
| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` |
| **Junction** | Filled Circle | `f-circ` | Junction point | `junction`, `filled-circle` |
| **Lined Document** | Lined Document | `lin-doc` | Lined document | `lined-document` |
| **Loop Limit** | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` |
| **Manual File** | Flipped Triangle | `flip-tri` | Manual file operation | `manual-file`, `flipped-triangle` |
| **Manual Input** | Sloped Rectangle | `sl-rect` | Manual input step | `manual-input`, `sloped-rectangle` |
| **Multi-Document** | Stacked Document | `docs` | Multiple documents | `documents`, `st-doc`, `stacked-document` |
| **Multi-Process** | Stacked Rectangle | `st-rect` | Multiple processes | `procs`, `processes`, `stacked-rectangle` |
| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape` |
| **Stored Data** | Bow Tie Rectangle | `bow-rect` | Stored data | `stored-data`, `bow-tie-rectangle` |
| **Summary** | Crossed Circle | `cross-circ` | Summary | `summary`, `crossed-circle` |
| **Tagged Document** | Tagged Document | `tag-doc` | Tagged document | `tag-doc`, `tagged-document` |
| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tagged-rectangle`,`tag-proc`, `tagged-process` |
### Example Flowchart with New Shapes ### Example Flowchart with New Shapes
@ -588,6 +542,56 @@ flowchart TD
A@{ shape: tag-rect, label: "Tagged process" } A@{ shape: tag-rect, label: "Tagged process" }
``` ```
## Special shapes in Mermaid Flowcharts (v11.3.0+)
Mermaid also introduces 2 special shapes to enhance your flowcharts: **icon** and **image**. These shapes allow you to include icons and images directly within your flowcharts, providing more visual context and clarity.
### Icon Shape
You can use the `icon` shape to include an icon in your flowchart. To use icons, you need to register the icon pack first. Follow the instructions provided [here](../config/icons.md). The syntax for defining an icon shape is as follows:
```mermaid-example
flowchart TD
A@{ icon: "fa:user", form: "square", label: "User Icon", pos: "t", h: 60 }
```
### Parameters
- **icon**: The name of the icon from the registered icon pack.
- **form**: Specifies the background shape of the icon. If not defined there will be no background to icon. Options include:
- `square`
- `circle`
- `rounded`
- **label**: The text label associated with the icon. This can be any string. If not defined, no label will be displayed.
- **pos**: The position of the label. If not defined label will default to bottom of icon. Possible values are:
- `t`
- `b`
- **h**: The height of the icon. If not defined this will default to 48 which is minimum.
### Image Shape
You can use the `image` shape to include an image in your flowchart. The syntax for defining an image shape is as follows:
```mermaid-example
flowchart TD
A@{ img: "https://example.com/image.png", label: "Image Label", pos: "t", w: 60, h: 60, constraint: "off" }
```
### Parameters
- **img**: The URL of the image to be displayed.
- **label**: The text label associated with the image. This can be any string. If not defined, no label will be displayed.
- **pos**: The position of the label. If not defined, the label will default to the bottom of the image. Possible values are:
- `t`
- `b`
- **w**: The width of the image. If not defined, this will default to the natural width of the image.
- **h**: The height of the image. If not defined, this will default to the natural height of the image.
- **constraint**: Determines if the image should constrain the node size. This setting also ensures the image maintains its original aspect ratio, adjusting the height (`h`) accordingly to the width (`w`). If not defined, this will default to `off` Possible values are:
- `on`
- `off`
These new shapes provide additional flexibility and visual appeal to your flowcharts, making them more informative and engaging.
## Links between nodes ## Links between nodes
Nodes can be connected with links/edges. It is possible to have different types of links or attach a text string to a link. Nodes can be connected with links/edges. It is possible to have different types of links or attach a text string to a link.

View File

@ -1,307 +1,5 @@
import { log } from '../../logger.js'; import { log } from '../../logger.js';
import { state } from './shapes/state.ts'; import { shapes } from './shapes.js';
import { roundedRect } from './shapes/roundedRect.ts';
import { squareRect } from './shapes/squareRect.ts';
import { stateStart } from './shapes/stateStart.ts';
import { stateEnd } from './shapes/stateEnd.ts';
import { forkJoin } from './shapes/forkJoin.ts';
import { choice } from './shapes/choice.ts';
import { note } from './shapes/note.ts';
import { stadium } from './shapes/stadium.js';
import { rectWithTitle } from './shapes/rectWithTitle.js';
import { subroutine } from './shapes/subroutine.js';
import { cylinder } from './shapes/cylinder.js';
import { circle } from './shapes/circle.js';
import { doublecircle } from './shapes/doubleCircle.js';
import { rect_left_inv_arrow } from './shapes/rectLeftInvArrow.js';
import { question } from './shapes/question.js';
import { hexagon } from './shapes/hexagon.js';
import { text } from './shapes/text.js';
import { card } from './shapes/card.js';
import { shadedProcess } from './shapes/shadedProcess.js';
import { anchor } from './shapes/anchor.js';
import { lean_right } from './shapes/leanRight.js';
import { lean_left } from './shapes/leanLeft.js';
import { trapezoid } from './shapes/trapezoid.js';
import { inv_trapezoid } from './shapes/invertedTrapezoid.js';
import { labelRect } from './shapes/labelRect.js';
import { classBox } from './shapes/classBox.js';
import { triangle } from './shapes/triangle.js';
import { halfRoundedRectangle } from './shapes/halfRoundedRectangle.js';
import { curvedTrapezoid } from './shapes/curvedTrapezoid.js';
import { slopedRect } from './shapes/slopedRect.js';
import { bowTieRect } from './shapes/bowTieRect.js';
import { dividedRectangle } from './shapes/dividedRect.js';
import { crossedCircle } from './shapes/crossedCircle.js';
import { waveRectangle } from './shapes/waveRectangle.js';
import { tiltedCylinder } from './shapes/tiltedCylinder.js';
import { trapezoidalPentagon } from './shapes/trapezoidalPentagon.js';
import { flippedTriangle } from './shapes/flippedTriangle.js';
import { hourglass } from './shapes/hourglass.js';
import { taggedRect } from './shapes/taggedRect.js';
import { multiRect } from './shapes/multiRect.js';
import { linedCylinder } from './shapes/linedCylinder.js';
import { waveEdgedRectangle } from './shapes/waveEdgedRectangle.js';
import { lightningBolt } from './shapes/lightningBolt.js';
import { filledCircle } from './shapes/filledCircle.js';
import { multiWaveEdgedRectangle } from './shapes/multiWaveEdgedRectangle.js';
import { windowPane } from './shapes/windowPane.js';
import { linedWaveEdgedRect } from './shapes/linedWaveEdgedRect.js';
import { taggedWaveEdgedRectangle } from './shapes/taggedWaveEdgedRectangle.js';
import { curlyBraceLeft } from './shapes/curlyBraceLeft.js';
import { curlyBraceRight } from './shapes/curlyBraceRight.js';
import { curlyBraces } from './shapes/curlyBraces.js';
import { iconSquare } from './shapes/iconSquare.js';
import { iconCircle } from './shapes/iconCircle.js';
import { icon } from './shapes/icon.js';
import { imageSquare } from './shapes/imageSquare.js';
import { iconRounded } from './shapes/iconRounded.js';
//Use these names as the left side to render shapes.
export const shapes = {
// States
state,
stateStart,
stateEnd,
forkJoin,
choice,
note,
// Rectangles
rectWithTitle,
roundedRect,
squareRect,
// Rectangle with alias: 'process', 'rect', 'proc', 'rectangle'
rectangle: squareRect,
rect: squareRect,
process: squareRect,
proc: squareRect,
// Rounded Rectangle with alias: 'event', 'rounded'
rounded: roundedRect,
event: roundedRect,
// Stadium with alias: 'terminal','pill', 'stadium'
stadium,
pill: stadium,
terminal: stadium,
// Subprocess with alias: 'fr-rect', 'subproc', 'subprocess', 'framed-rectangle', 'subroutine'
subroutine,
'framed-rectangle': subroutine,
'fr-rect': subroutine,
subprocess: subroutine,
subproc: subroutine,
// Cylinder with alias: 'db', 'database', 'cylinder', 'cyl'
cylinder,
db: cylinder,
cyl: cylinder,
database: cylinder,
// Diamond with alias: 'diam', 'decision', 'diamond'
question,
diam: question,
diamond: question,
decision: question,
// Hexagon with alias: 'hex', 'hexagon', 'prepare'
hexagon,
hex: hexagon,
prepare: hexagon,
// Lean Right with alias: 'lean-r', 'lean-right', 'in-out'
lean_right, // used in old syntax for flowchart
'lean-r': lean_right,
'lean-right': lean_right,
'in-out': lean_right,
// Lean Left with alias: 'lean-l', 'lean-left', 'out-in'
lean_left, // used in old syntax for flowchart
'lean-l': lean_left,
'lean-left': lean_left,
'out-in': lean_left,
// Trapezoid with alias: 'trap-b', 'trapezoid-bottom', 'priority'
trapezoid, // used in old syntax for flowchart
'trap-b': trapezoid,
'trapezoid-bottom': trapezoid,
priority: trapezoid,
// Inverted Trapezoid with alias: 'inv-trapezoid', 'trapezoid-top', 'trap-t', 'manual'
inv_trapezoid, // used in old syntax for flowchart
'inv-trapezoid': inv_trapezoid,
'trapezoid-top': inv_trapezoid,
'trap-t': inv_trapezoid,
manual: inv_trapezoid,
// Double Circle with alias: 'dbl-circ', 'double-circle'
doublecircle, // used in old syntax for flowchart
'dbl-circ': doublecircle,
'double-circle': doublecircle,
// circle with alias: 'circ', 'circle'
circle,
circ: circle,
// Rect Left Inv Arrow with alias: 'odd', 'rect-left-inv-arrow'
rect_left_inv_arrow,
odd: rect_left_inv_arrow,
// Notched Rectangle with alias: 'notched-rectangle', 'notch-rect', 'card'
card,
'notched-rectangle': card,
'notch-rect': card,
// Lined rectangle with alias: 'lin-rect', 'lined-rectangle', 'lin-proc', lined-process', 'shaded-process'
'lined-rectangle': shadedProcess,
'lin-rect': shadedProcess,
'lin-proc': shadedProcess,
'lined-process': shadedProcess,
'shaded-process': shadedProcess,
// Small circle with alias: 'sm-circ', 'small-circle', 'start'
'small-circle': stateStart,
'sm-circ': stateStart,
start: stateStart,
// framed circle with alias: 'stop', 'framed-circle', 'fr-circ'
stop: stateEnd,
'framed-circle': stateEnd,
'fr-circ': stateEnd,
// fork with alias: 'join', 'fork'
join: forkJoin,
fork: forkJoin,
// comment with alias: 'comment', 'brace-l'
comment: curlyBraceLeft,
'brace-l': curlyBraceLeft,
// lightening bolt with alias: 'bolt', 'com-link', 'lightning-bolt'
bolt: lightningBolt,
'com-link': lightningBolt,
'lightning-bolt': lightningBolt,
// document with alias: 'doc', 'document'
doc: waveEdgedRectangle,
document: waveEdgedRectangle,
// delay with alias: 'delay', 'half-rounded-rectangle'
delay: halfRoundedRectangle,
'half-rounded-rectangle': halfRoundedRectangle,
// horizontal cylinder with alias: 'h-cyl', 'das', 'horizontal-cylinder'
'horizontal-cylinder': tiltedCylinder,
'h-cyl': tiltedCylinder,
das: tiltedCylinder,
// lined cylinder with alias: 'lin-cyl', 'lined-cylinder', 'disk'
'lined-cylinder': linedCylinder,
'lin-cyl': linedCylinder,
disk: linedCylinder,
// curved trapezoid with alias: 'curv-trap', 'curved-trapezoid', 'display'
'curved-trapezoid': curvedTrapezoid,
'curv-trap': curvedTrapezoid,
display: curvedTrapezoid,
// divided rectangle with alias: 'div-rect', 'divided-rectangle', 'div-proc', 'divided-process'
'divided-rectangle': dividedRectangle,
'div-rect': dividedRectangle,
'div-proc': dividedRectangle,
'divided-process': dividedRectangle,
// triangle with alias: 'tri', 'triangle', 'extract'
triangle,
tri: triangle,
extract: triangle,
// window pane with alias: 'window-pane', 'win-pane', 'internal-storage'
'window-pane': windowPane,
'win-pane': windowPane,
'internal-storage': windowPane,
// filled circle with alias: 'f-circ', 'filled-circle', 'junction'
'f-circ': filledCircle,
junction: filledCircle,
'filled-circle': filledCircle,
// lined document with alias: 'lin-doc', 'lined-document'
'lin-doc': linedWaveEdgedRect,
'lined-document': linedWaveEdgedRect,
// notched pentagon with alias: 'notch-pent', 'notched-pentagon', 'loop-limit'
'notched-pentagon': trapezoidalPentagon,
'notch-pent': trapezoidalPentagon,
'loop-limit': trapezoidalPentagon,
// flipped triangle with alias: 'flip-tri', 'flipped-triangle', 'manual-file'
'flipped-triangle': flippedTriangle,
'flip-tri': flippedTriangle,
'manual-file': flippedTriangle,
// sloped rectangle with alias: 'sl-rect', 'sloped-rectangle', 'manual-input'
'sloped-rectangle': slopedRect,
'sl-rect': slopedRect,
'manual-input': slopedRect,
// documents with alias: 'docs', 'documents', 'st-doc', 'stacked-document'
docs: multiWaveEdgedRectangle,
documents: multiWaveEdgedRectangle,
'st-doc': multiWaveEdgedRectangle,
'stacked-document': multiWaveEdgedRectangle,
// 'processes' with alias: 'procs', 'processes', 'st-rect', 'stacked-rectangle'
processes: multiRect,
procs: multiRect,
'stacked-rectangle': multiRect,
'st-rect': multiRect,
// flag with alias: 'flag', 'paper-tape'
flag: waveRectangle,
'paper-tape': waveRectangle,
// bow tie rectangle with alias: 'bow-rect', 'bow-tie-rectangle', 'stored-data'
'bow-tie-rectangle': bowTieRect,
'bow-rect': bowTieRect,
'stored-data': bowTieRect,
// crossed circle with alias: 'cross-circ', 'crossed-circle', 'summary'
'crossed-circle': crossedCircle,
'cross-circ': crossedCircle,
summary: crossedCircle,
// tagged document with alias: 'tag-doc', 'tagged-document'
'tag-doc': taggedWaveEdgedRectangle,
'tagged-document': taggedWaveEdgedRectangle,
// tagged rectangle with alias: 'tag-rect', 'tagged-rectangle', 'tag-proc', 'tagged-process'
'tag-rect': taggedRect,
'tagged-rectangle': taggedRect,
'tag-proc': taggedRect,
'tagged-process': taggedRect,
// hourglass with alias: 'hourglass', 'collate'
hourglass,
collate: hourglass,
text,
anchor,
brace: curlyBraceLeft,
labelRect,
classBox,
'brace-r': curlyBraceRight,
braces: curlyBraces,
iconSquare,
iconCircle,
icon,
iconRounded,
imageSquare,
};
const nodeElems = new Map(); const nodeElems = new Map();
@ -309,8 +7,6 @@ export const insertNode = async (elem, node, renderOptions) => {
let newEl; let newEl;
let el; let el;
// console.log("node is ", node.icon, node.shape)
//special check for rect shape (with or without rounded corners) //special check for rect shape (with or without rounded corners)
if (node.shape === 'rect') { if (node.shape === 'rect') {
if (node.rx && node.ry) { if (node.rx && node.ry) {
@ -320,7 +16,9 @@ export const insertNode = async (elem, node, renderOptions) => {
} }
} }
if (!shapes[node.shape]) { const shapeHandler = shapes[node.shape];
if (!shapeHandler) {
throw new Error(`No such shape: ${node.shape}. Please check your syntax.`); throw new Error(`No such shape: ${node.shape}. Please check your syntax.`);
} }
@ -333,9 +31,9 @@ export const insertNode = async (elem, node, renderOptions) => {
target = node.linkTarget || '_blank'; target = node.linkTarget || '_blank';
} }
newEl = elem.insert('svg:a').attr('xlink:href', node.link).attr('target', target); newEl = elem.insert('svg:a').attr('xlink:href', node.link).attr('target', target);
el = await shapes[node.shape](newEl, node, renderOptions); el = await shapeHandler(newEl, node, renderOptions);
} else { } else {
el = await shapes[node.shape](elem, node, renderOptions); el = await shapeHandler(elem, node, renderOptions);
newEl = el; newEl = el;
} }
if (node.tooltip) { if (node.tooltip) {
@ -349,9 +47,11 @@ export const insertNode = async (elem, node, renderOptions) => {
} }
return newEl; return newEl;
}; };
export const setNodeElem = (elem, node) => { export const setNodeElem = (elem, node) => {
nodeElems.set(node.id, elem); nodeElems.set(node.id, elem);
}; };
export const clear = () => { export const clear = () => {
nodeElems.clear(); nodeElems.clear();
}; };

View File

@ -1,5 +1,5 @@
import exp from 'constants'; import { shapes } from './shapes.js';
import { shapes } from './nodes.js'; import { describe, it, expect } from 'vitest';
describe('Test Alias for shapes', function () { describe('Test Alias for shapes', function () {
// for each shape in docs/syntax/flowchart.md, along with its semantic name, short name, and alias name, add a test case // for each shape in docs/syntax/flowchart.md, along with its semantic name, short name, and alias name, add a test case

View File

@ -0,0 +1,481 @@
import type { Node, ShapeRenderOptions } from '../types.js';
import { anchor } from './shapes/anchor.js';
import { bowTieRect } from './shapes/bowTieRect.js';
import { card } from './shapes/card.js';
import { choice } from './shapes/choice.js';
import { circle } from './shapes/circle.js';
import { crossedCircle } from './shapes/crossedCircle.js';
import { curlyBraceLeft } from './shapes/curlyBraceLeft.js';
import { curlyBraceRight } from './shapes/curlyBraceRight.js';
import { curlyBraces } from './shapes/curlyBraces.js';
import { curvedTrapezoid } from './shapes/curvedTrapezoid.js';
import { cylinder } from './shapes/cylinder.js';
import { dividedRectangle } from './shapes/dividedRect.js';
import { doublecircle } from './shapes/doubleCircle.js';
import { filledCircle } from './shapes/filledCircle.js';
import { flippedTriangle } from './shapes/flippedTriangle.js';
import { forkJoin } from './shapes/forkJoin.js';
import { halfRoundedRectangle } from './shapes/halfRoundedRectangle.js';
import { hexagon } from './shapes/hexagon.js';
import { hourglass } from './shapes/hourglass.js';
import { icon } from './shapes/icon.js';
import { iconCircle } from './shapes/iconCircle.js';
import { iconRounded } from './shapes/iconRounded.js';
import { iconSquare } from './shapes/iconSquare.js';
import { imageSquare } from './shapes/imageSquare.js';
import { inv_trapezoid } from './shapes/invertedTrapezoid.js';
import { labelRect } from './shapes/labelRect.js';
import { lean_left } from './shapes/leanLeft.js';
import { lean_right } from './shapes/leanRight.js';
import { lightningBolt } from './shapes/lightningBolt.js';
import { linedCylinder } from './shapes/linedCylinder.js';
import { linedWaveEdgedRect } from './shapes/linedWaveEdgedRect.js';
import { multiRect } from './shapes/multiRect.js';
import { multiWaveEdgedRectangle } from './shapes/multiWaveEdgedRectangle.js';
import { note } from './shapes/note.js';
import { question } from './shapes/question.js';
import { rect_left_inv_arrow } from './shapes/rectLeftInvArrow.js';
import { rectWithTitle } from './shapes/rectWithTitle.js';
import { roundedRect } from './shapes/roundedRect.js';
import { shadedProcess } from './shapes/shadedProcess.js';
import { slopedRect } from './shapes/slopedRect.js';
import { squareRect } from './shapes/squareRect.js';
import { stadium } from './shapes/stadium.js';
import { state } from './shapes/state.js';
import { stateEnd } from './shapes/stateEnd.js';
import { stateStart } from './shapes/stateStart.js';
import { subroutine } from './shapes/subroutine.js';
import { taggedRect } from './shapes/taggedRect.js';
import { taggedWaveEdgedRectangle } from './shapes/taggedWaveEdgedRectangle.js';
import { text } from './shapes/text.js';
import { tiltedCylinder } from './shapes/tiltedCylinder.js';
import { trapezoid } from './shapes/trapezoid.js';
import { trapezoidalPentagon } from './shapes/trapezoidalPentagon.js';
import { triangle } from './shapes/triangle.js';
import { waveEdgedRectangle } from './shapes/waveEdgedRectangle.js';
import { waveRectangle } from './shapes/waveRectangle.js';
import { windowPane } from './shapes/windowPane.js';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type ShapeHandler = (parent: any, node: Node, options: ShapeRenderOptions) => unknown;
export interface ShapeDefinition {
semanticName: string;
name: string;
shortName: string;
description: string;
/**
* Aliases can include descriptive names, other short names, etc.
*/
aliases?: string[];
/**
* These are names used by mermaid before the introduction of new shapes. These will not be in standard formats, and shouldn't be used by the users
*/
internalAliases?: string[];
handler: ShapeHandler;
}
export const shapesDefs: ShapeDefinition[] = [
{
semanticName: 'Process',
name: 'Rectangle',
shortName: 'rect',
description: 'Standard process shape',
aliases: ['proc', 'process', 'rectangle'],
internalAliases: ['squareRect'],
handler: squareRect,
},
{
semanticName: 'Event',
name: 'Rounded Rectangle',
shortName: 'rounded',
description: 'Represents an event',
aliases: ['event'],
internalAliases: ['roundedRect'],
handler: roundedRect,
},
{
semanticName: 'Terminal Point',
name: 'Stadium',
shortName: 'stadium',
description: 'Terminal point',
aliases: ['terminal', 'pill'],
handler: stadium,
},
{
semanticName: 'Subprocess',
name: 'Framed Rectangle',
shortName: 'fr-rect',
description: 'Subprocess',
aliases: ['subprocess', 'subproc', 'framed-rectangle', 'subroutine'],
handler: subroutine,
},
{
semanticName: 'Database',
name: 'Cylinder',
shortName: 'cyl',
description: 'Database storage',
aliases: ['db', 'database', 'cylinder'],
handler: cylinder,
},
{
semanticName: 'Start',
name: 'Circle',
shortName: 'circle',
description: 'Starting point',
aliases: ['circ'],
handler: circle,
},
{
semanticName: 'Decision',
name: 'Diamond',
shortName: 'diam',
description: 'Decision-making step',
aliases: ['decision', 'diamond', 'question'],
handler: question,
},
{
semanticName: 'Prepare Conditional',
name: 'Hexagon',
shortName: 'hex',
description: 'Preparation or condition step',
aliases: ['hexagon', 'prepare'],
handler: hexagon,
},
{
semanticName: 'Data Input/Output',
name: 'Lean Right',
shortName: 'lean-r',
description: 'Represents input or output',
aliases: ['lean-right', 'in-out'],
internalAliases: ['lean_right'],
handler: lean_right,
},
{
semanticName: 'Data Input/Output',
name: 'Lean Left',
shortName: 'lean-l',
description: 'Represents output or input',
aliases: ['lean-left', 'out-in'],
internalAliases: ['lean_left'],
handler: lean_left,
},
{
semanticName: 'Priority Action',
name: 'Trapezoid Base Bottom',
shortName: 'trap-b',
description: 'Priority action',
aliases: ['priority', 'trapezoid-bottom', 'trapezoid'],
handler: trapezoid,
},
{
semanticName: 'Manual Operation',
name: 'Trapezoid Base Top',
shortName: 'trap-t',
description: 'Represents a manual task',
aliases: ['manual', 'trapezoid-top', 'inv-trapezoid'],
internalAliases: ['inv_trapezoid'],
handler: inv_trapezoid,
},
{
semanticName: 'Stop',
name: 'Double Circle',
shortName: 'dbl-circ',
description: 'Represents a stop point',
aliases: ['double-circle'],
internalAliases: ['doublecircle'],
handler: doublecircle,
},
{
semanticName: 'Text Block',
name: 'Text Block',
shortName: 'text',
description: 'Text block',
handler: text,
},
{
semanticName: 'Card',
name: 'Notched Rectangle',
shortName: 'notch-rect',
description: 'Represents a card',
aliases: ['card', 'notched-rectangle'],
handler: card,
},
{
semanticName: 'Lined/Shaded Process',
name: 'Lined Rectangle',
shortName: 'lin-rect',
description: 'Lined process shape',
aliases: ['lined-rectangle', 'lined-process', 'lin-proc', 'shaded-process'],
handler: shadedProcess,
},
{
semanticName: 'Start',
name: 'Small Circle',
shortName: 'sm-circ',
description: 'Small starting point',
aliases: ['start', 'small-circle'],
internalAliases: ['stateStart'],
handler: stateStart,
},
{
semanticName: 'Stop',
name: 'Framed Circle',
shortName: 'fr-circ',
description: 'Stop point',
aliases: ['stop', 'framed-circle'],
internalAliases: ['stateEnd'],
handler: stateEnd,
},
{
semanticName: 'Fork/Join',
name: 'Filled Rectangle',
shortName: 'fork',
description: 'Fork or join in process flow',
aliases: ['join'],
internalAliases: ['forkJoin'],
handler: forkJoin,
},
{
semanticName: 'Collate',
name: 'Hourglass',
shortName: 'hourglass',
description: 'Represents a collate operation',
aliases: ['hourglass', 'collate'],
handler: hourglass,
},
{
semanticName: 'Comment',
name: 'Curly Brace',
shortName: 'brace',
description: 'Adds a comment',
aliases: ['comment', 'brace-l'],
handler: curlyBraceLeft,
},
{
semanticName: 'Comment Right',
name: 'Curly Brace',
shortName: 'brace-r',
description: 'Adds a comment',
handler: curlyBraceRight,
},
{
semanticName: 'Comment with braces on both sides',
name: 'Curly Braces',
shortName: 'braces',
description: 'Adds a comment',
handler: curlyBraces,
},
{
semanticName: 'Com Link',
name: 'Lightning Bolt',
shortName: 'bolt',
description: 'Communication link',
aliases: ['com-link', 'lightning-bolt'],
handler: lightningBolt,
},
{
semanticName: 'Document',
name: 'Document',
shortName: 'doc',
description: 'Represents a document',
aliases: ['doc', 'document'],
handler: waveEdgedRectangle,
},
{
semanticName: 'Delay',
name: 'Half-Rounded Rectangle',
shortName: 'delay',
description: 'Represents a delay',
aliases: ['half-rounded-rectangle'],
handler: halfRoundedRectangle,
},
{
semanticName: 'Direct Access Storage',
name: 'Horizontal Cylinder',
shortName: 'h-cyl',
description: 'Direct access storage',
aliases: ['das', 'horizontal-cylinder'],
handler: tiltedCylinder,
},
{
semanticName: 'Disk Storage',
name: 'Lined Cylinder',
shortName: 'lin-cyl',
description: 'Disk storage',
aliases: ['disk', 'lined-cylinder'],
handler: linedCylinder,
},
{
semanticName: 'Display',
name: 'Curved Trapezoid',
shortName: 'curv-trap',
description: 'Represents a display',
aliases: ['curved-trapezoid', 'display'],
handler: curvedTrapezoid,
},
{
semanticName: 'Divided Process',
name: 'Divided Rectangle',
shortName: 'div-rect',
description: 'Divided process shape',
aliases: ['div-proc', 'divided-rectangle', 'divided-process'],
handler: dividedRectangle,
},
{
semanticName: 'Extract',
name: 'Triangle',
shortName: 'tri',
description: 'Extraction process',
aliases: ['extract', 'triangle'],
handler: triangle,
},
{
semanticName: 'Internal Storage',
name: 'Window Pane',
shortName: 'win-pane',
description: 'Internal storage',
aliases: ['internal-storage', 'window-pane'],
handler: windowPane,
},
{
semanticName: 'Junction',
name: 'Filled Circle',
shortName: 'f-circ',
description: 'Junction point',
aliases: ['junction', 'filled-circle'],
handler: filledCircle,
},
{
semanticName: 'Loop Limit',
name: 'Trapezoidal Pentagon',
shortName: 'notch-pent',
description: 'Loop limit step',
aliases: ['loop-limit', 'notched-pentagon'],
handler: trapezoidalPentagon,
},
{
semanticName: 'Manual File',
name: 'Flipped Triangle',
shortName: 'flip-tri',
description: 'Manual file operation',
aliases: ['manual-file', 'flipped-triangle'],
handler: flippedTriangle,
},
{
semanticName: 'Manual Input',
name: 'Sloped Rectangle',
shortName: 'sl-rect',
description: 'Manual input step',
aliases: ['manual-input', 'sloped-rectangle'],
handler: slopedRect,
},
{
semanticName: 'Multi-Document',
name: 'Stacked Document',
shortName: 'docs',
description: 'Multiple documents',
aliases: ['documents', 'st-doc', 'stacked-document'],
handler: multiWaveEdgedRectangle,
},
{
semanticName: 'Multi-Process',
name: 'Stacked Rectangle',
shortName: 'st-rect',
description: 'Multiple processes',
aliases: ['procs', 'processes', 'stacked-rectangle'],
handler: multiRect,
},
{
semanticName: 'Stored Data',
name: 'Bow Tie Rectangle',
shortName: 'bow-rect',
description: 'Stored data',
aliases: ['stored-data', 'bow-tie-rectangle'],
handler: bowTieRect,
},
{
semanticName: 'Summary',
name: 'Crossed Circle',
shortName: 'cross-circ',
description: 'Summary',
aliases: ['summary', 'crossed-circle'],
handler: crossedCircle,
},
{
semanticName: 'Tagged Document',
name: 'Tagged Document',
shortName: 'tag-doc',
description: 'Tagged document',
aliases: ['tag-doc', 'tagged-document'],
handler: taggedWaveEdgedRectangle,
},
{
semanticName: 'Tagged Process',
name: 'Tagged Rectangle',
shortName: 'tag-rect',
description: 'Tagged process',
aliases: ['tagged-rectangle', 'tag-proc', 'tagged-process'],
handler: taggedRect,
},
{
semanticName: 'Paper Tape',
name: 'Flag',
shortName: 'flag',
description: 'Paper tape',
aliases: ['paper-tape'],
handler: waveRectangle,
},
{
semanticName: 'Odd',
name: 'Odd',
shortName: 'odd',
description: 'Odd shape',
internalAliases: ['rect_left_inv_arrow'],
handler: rect_left_inv_arrow,
},
{
semanticName: 'Lined Document',
name: 'Lined Document',
shortName: 'lin-doc',
description: 'Lined document',
aliases: ['lined-document'],
handler: linedWaveEdgedRect,
},
];
const generateShapeMap = () => {
// These are the shapes that didn't have documentation present
const shapeMap: Record<string, ShapeHandler> = {
// States
state,
choice,
note,
// Rectangles
rectWithTitle,
labelRect,
// Icons
iconSquare,
iconCircle,
icon,
iconRounded,
imageSquare,
anchor,
};
for (const shape of shapesDefs) {
for (const alias of [
shape.shortName,
...(shape.aliases ?? []),
...(shape.internalAliases ?? []),
]) {
shapeMap[alias] = shape.handler;
}
}
return shapeMap;
};
export const shapes = generateShapeMap();

View File

@ -1,7 +1,7 @@
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { updateNodeBounds, getNodeClasses } from './util.js'; import { updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,7 +1,7 @@
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { getNodeClasses, updateNodeBounds } from './util.js'; import { getNodeClasses, updateNodeBounds } from './util.js';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -6,7 +6,7 @@ import {
generateCirclePoints, generateCirclePoints,
} from './util.js'; } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,7 +1,7 @@
import rough from 'roughjs'; import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import type { Node, ShapeRenderOptions } from '../../types.d.ts'; import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { getNodeClasses, updateNodeBounds } from './util.js'; import { getNodeClasses, updateNodeBounds } from './util.js';

View File

@ -1,7 +1,7 @@
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import { createPathFromPoints } from './util.js'; import { createPathFromPoints } from './util.js';

View File

@ -7,7 +7,7 @@ import {
generateCirclePoints, generateCirclePoints,
} from './util.js'; } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,7 +1,7 @@
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -2,7 +2,7 @@ import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js'; import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.d.ts'; import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js'; import { labelHelper, updateNodeBounds } from './util.js';
@ -77,7 +77,7 @@ export const icon = async (
: -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY
})` })`
); );
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder); iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`);
} }
label.attr( label.attr(

View File

@ -2,7 +2,7 @@ import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js'; import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.d.ts'; import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js'; import { labelHelper, updateNodeBounds } from './util.js';
@ -26,10 +26,10 @@ export const iconCircle = async (
const topLabel = node.pos === 't'; const topLabel = node.pos === 't';
const { nodeBorder, mainBkg } = themeVariables; const { nodeBorder } = themeVariables;
const { stylesMap } = compileStyles(node); const { stylesMap } = compileStyles(node);
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg }); const options = userNodeOverrides(node, { stroke: 'transparent' });
if (node.look !== 'handDrawn') { if (node.look !== 'handDrawn') {
options.roughness = 0; options.roughness = 0;
@ -74,7 +74,7 @@ export const iconCircle = async (
: -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY
})` })`
); );
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') || nodeBorder); iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`);
label.attr( label.attr(
'transform', 'transform',
`translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${ `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${

View File

@ -2,7 +2,7 @@ import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js'; import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.d.ts'; import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { createRoundedRectPathD } from './roundedRectPath.js'; import { createRoundedRectPathD } from './roundedRectPath.js';
@ -30,7 +30,7 @@ export const iconRounded = async (
const height = iconSize + halfPadding * 2; const height = iconSize + halfPadding * 2;
const width = iconSize + halfPadding * 2; const width = iconSize + halfPadding * 2;
const { nodeBorder, mainBkg } = themeVariables; const { nodeBorder } = themeVariables;
const { stylesMap } = compileStyles(node); const { stylesMap } = compileStyles(node);
const x = -width / 2; const x = -width / 2;
@ -39,7 +39,7 @@ export const iconRounded = async (
const labelPadding = node.label ? 8 : 0; const labelPadding = node.label ? 8 : 0;
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg }); const options = userNodeOverrides(node, { stroke: 'transparent' });
if (node.look !== 'handDrawn') { if (node.look !== 'handDrawn') {
options.roughness = 0; options.roughness = 0;
@ -82,7 +82,7 @@ export const iconRounded = async (
: -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY
})` })`
); );
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') ?? nodeBorder); iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`);
} }
label.attr( label.attr(

View File

@ -2,7 +2,7 @@ import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { getIconSVG } from '../../icons.js'; import { getIconSVG } from '../../icons.js';
import type { Node, ShapeRenderOptions } from '../../types.d.ts'; import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js'; import { labelHelper, updateNodeBounds } from './util.js';
@ -29,7 +29,7 @@ export const iconSquare = async (
const height = iconSize + halfPadding * 2; const height = iconSize + halfPadding * 2;
const width = iconSize + halfPadding * 2; const width = iconSize + halfPadding * 2;
const { nodeBorder, mainBkg } = themeVariables; const { nodeBorder } = themeVariables;
const { stylesMap } = compileStyles(node); const { stylesMap } = compileStyles(node);
const x = -width / 2; const x = -width / 2;
@ -38,7 +38,7 @@ export const iconSquare = async (
const labelPadding = node.label ? 8 : 0; const labelPadding = node.label ? 8 : 0;
const rc = rough.svg(shapeSvg); const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg }); const options = userNodeOverrides(node, { stroke: 'transparent' });
if (node.look !== 'handDrawn') { if (node.look !== 'handDrawn') {
options.roughness = 0; options.roughness = 0;
@ -81,7 +81,7 @@ export const iconSquare = async (
: -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY : -bbox.height / 2 - labelPadding / 2 - iconHeight / 2 - iconY
})` })`
); );
iconElem.selectAll('path').attr('fill', stylesMap.get('stroke') ?? nodeBorder); iconElem.attr('style', `color: ${stylesMap.get('stroke') ?? nodeBorder};`);
} }
label.attr( label.attr(

View File

@ -1,7 +1,7 @@
import rough from 'roughjs'; import rough from 'roughjs';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import type { Node, ShapeRenderOptions } from '../../types.d.ts'; import type { Node, ShapeRenderOptions } from '../../types.ts';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import { labelHelper, updateNodeBounds } from './util.js'; import { labelHelper, updateNodeBounds } from './util.js';

View File

@ -1,6 +1,6 @@
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { getNodeClasses, updateNodeBounds } from './util.js'; import { getNodeClasses, updateNodeBounds } from './util.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import type { SVG } from '../../../diagram-api/types.js'; import type { SVG } from '../../../diagram-api/types.js';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -5,7 +5,7 @@ import {
generateFullSineWavePoints, generateFullSineWavePoints,
} from './util.js'; } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import rough from 'roughjs'; import rough from 'roughjs';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';

View File

@ -1,5 +1,5 @@
import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';

View File

@ -6,7 +6,7 @@ import {
generateFullSineWavePoints, generateFullSineWavePoints,
} from './util.js'; } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import rough from 'roughjs'; import rough from 'roughjs';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,5 +1,5 @@
import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';

View File

@ -6,7 +6,7 @@ import {
createPathFromPoints, createPathFromPoints,
} from './util.js'; } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import rough from 'roughjs'; import rough from 'roughjs';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String } from './handDrawnShapeStyles.js'; import { styles2String } from './handDrawnShapeStyles.js';
export async function text(parent: SVGAElement, node: Node): Promise<SVGAElement> { export async function text(parent: SVGAElement, node: Node): Promise<SVGAElement> {

View File

@ -1,5 +1,5 @@
import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js'; import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';

View File

@ -1,6 +1,6 @@
import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,7 +1,7 @@
import { log } from '../../../logger.js'; import { log } from '../../../logger.js';
import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import { createPathFromPoints } from './util.js'; import { createPathFromPoints } from './util.js';

View File

@ -6,7 +6,7 @@ import {
createPathFromPoints, createPathFromPoints,
} from './util.js'; } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import rough from 'roughjs'; import rough from 'roughjs';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';

View File

@ -6,7 +6,7 @@ import {
generateFullSineWavePoints, generateFullSineWavePoints,
} from './util.js'; } from './util.js';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';

View File

@ -1,5 +1,5 @@
import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js'; import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js';
import type { Node } from '../../types.d.ts'; import type { Node } from '../../types.ts';
import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js';
import rough from 'roughjs'; import rough from 'roughjs';
import intersect from '../intersect/index.js'; import intersect from '../intersect/index.js';