Compare commits

..

1 Commits

Author SHA1 Message Date
Steph
dc2373e94c add light syntax highlighting theme 2023-10-29 20:19:15 -07:00
147 changed files with 977 additions and 2741 deletions

View File

@@ -1,25 +0,0 @@
/**
* Shared common options for both ESBuild and Vite
*/
export const packageOptions = {
parser: {
name: 'mermaid-parser',
packageName: 'parser',
file: 'index.ts',
},
mermaid: {
name: 'mermaid',
packageName: 'mermaid',
file: 'mermaid.ts',
},
'mermaid-example-diagram': {
name: 'mermaid-example-diagram',
packageName: 'mermaid-example-diagram',
file: 'detector.ts',
},
'mermaid-zenuml': {
name: 'mermaid-zenuml',
packageName: 'mermaid-zenuml',
file: 'detector.ts',
},
} as const;

View File

@@ -1,5 +0,0 @@
import { generate } from 'langium-cli';
export async function generateLangium() {
await generate({ file: `./packages/parser/langium-config.json` });
}

View File

@@ -1,123 +0,0 @@
import { load, JSON_SCHEMA } from 'js-yaml';
import assert from 'node:assert';
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
/**
* All of the keys in the mermaid config that have a mermaid diagram config.
*/
const MERMAID_CONFIG_DIAGRAM_KEYS = [
'flowchart',
'sequence',
'gantt',
'journey',
'class',
'state',
'er',
'pie',
'quadrantChart',
'xyChart',
'requirement',
'mindmap',
'timeline',
'gitGraph',
'c4',
'sankey',
] as const;
/**
* Generate default values from the JSON Schema.
*
* AJV does not support nested default values yet (or default values with $ref),
* so we need to manually find them (this may be fixed in ajv v9).
*
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
* @returns The default mermaid config object.
*/
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
const ajv = new Ajv2019({
useDefaults: true,
allowUnionTypes: true,
strict: true,
});
ajv.addKeyword({
keyword: 'meta:enum', // used by jsonschema2md
errors: false,
});
ajv.addKeyword({
keyword: 'tsType', // used by json-schema-to-typescript
errors: false,
});
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
// (may be fixed in v9) so we need to manually use sub-schemas
const mermaidDefaultConfig = {};
assert.ok(mermaidConfigSchema.$defs);
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
const [root, defs, defName] = subSchemaRef.split('/');
assert.strictEqual(root, '#');
assert.strictEqual(defs, '$defs');
const subSchema = {
$schema: mermaidConfigSchema.$schema,
$defs: mermaidConfigSchema.$defs,
...mermaidConfigSchema.$defs[defName],
} as JSONSchemaType<BaseDiagramConfig>;
const validate = ajv.compile(subSchema);
mermaidDefaultConfig[key] = {};
for (const required of subSchema.required ?? []) {
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
}
}
if (!validate(mermaidDefaultConfig[key])) {
throw new Error(
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
}
const validate = ajv.compile(mermaidConfigSchema);
if (!validate(mermaidDefaultConfig)) {
throw new Error(
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
return mermaidDefaultConfig;
}
export const loadSchema = (src: string, filename: string): JSONSchemaType<MermaidConfig> => {
const jsonSchema = load(src, {
filename,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}) as JSONSchemaType<MermaidConfig>;
return jsonSchema;
};
export const getDefaults = (schema: JSONSchemaType<MermaidConfig>) => {
return `export default ${JSON.stringify(generateDefaults(schema), undefined, 2)};`;
};
export const getSchema = (schema: JSONSchemaType<MermaidConfig>) => {
return `export default ${JSON.stringify(schema, undefined, 2)};`;
};

View File

@@ -1,9 +0,0 @@
declare module 'langium-cli' {
export interface GenerateOptions {
file?: string;
mode?: 'development' | 'production';
watch?: boolean;
}
export function generate(options: GenerateOptions): Promise<boolean>;
}

View File

@@ -1,65 +0,0 @@
import { build } from 'esbuild';
import { mkdir, writeFile } from 'node:fs/promises';
import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions = { ...defaultOptions, entryName } as const;
const buildConfigs = [
// package.mjs
{ ...commonOptions },
// package.min.mjs
{
...commonOptions,
minify: true,
metafile: shouldVisualize,
},
// package.core.mjs
{ ...commonOptions, core: true },
];
if (entryName === 'mermaid') {
const iifeOptions: MermaidBuildOptions = { ...commonOptions, format: 'iife' };
buildConfigs.push(
// mermaid.js
{ ...iifeOptions },
// mermaid.min.js
{ ...iifeOptions, minify: true, metafile: shouldVisualize }
);
}
const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option))));
if (shouldVisualize) {
for (const { metafile } of results) {
if (!metafile) {
continue;
}
const fileName = Object.keys(metafile.outputs)
.filter((file) => !file.includes('chunks') && file.endsWith('js'))[0]
.replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
}
}
};
const handler = (e) => {
console.error(e);
process.exit(1);
};
const main = async () => {
await generateLangium();
await mkdir('stats').catch(() => {});
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
// it should build `parser` before `mermaid` because it's a dependecy
for (const pkg of packageNames) {
await buildPackage(pkg).catch(handler);
}
};
void main();

View File

@@ -1,15 +0,0 @@
import { readFile } from 'node:fs/promises';
import { transformJison } from '../.build/jisonTransformer.js';
import { Plugin } from 'esbuild';
export const jisonPlugin: Plugin = {
name: 'jison',
setup(build) {
build.onLoad({ filter: /\.jison$/ }, async (args) => {
// Load the file from the file system
const source = await readFile(args.path, 'utf8');
const contents = transformJison(source);
return { contents, warnings: [] };
});
},
};

View File

@@ -1,35 +0,0 @@
import type { JSONSchemaType } from 'ajv/dist/2019.js';
import type { MermaidConfig } from '../packages/mermaid/src/config.type.js';
import { readFile } from 'node:fs/promises';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
/**
* ESBuild plugin that handles JSON Schemas saved as a `.schema.yaml` file.
*
* Use `my-example.schema.yaml?only-defaults=true` to only load the default values.
*/
export const jsonSchemaPlugin = {
name: 'json-schema-plugin',
setup(build) {
let schema: JSONSchemaType<MermaidConfig> | undefined = undefined;
let content = '';
build.onLoad({ filter: /config\.schema\.yaml$/ }, async (args) => {
// Load the file from the file system
const source = await readFile(args.path, 'utf8');
const resolvedSchema: JSONSchemaType<MermaidConfig> =
content === source && schema ? schema : loadSchema(source, args.path);
if (content !== source) {
content = source;
schema = resolvedSchema;
}
const contents = args.suffix.includes('only-defaults')
? getDefaults(resolvedSchema)
: getSchema(resolvedSchema);
return { contents, warnings: [] };
});
},
};
export default jsonSchemaPlugin;

View File

@@ -1,116 +0,0 @@
import express from 'express';
import type { NextFunction, Request, Response } from 'express';
import cors from 'cors';
import { getBuildConfig, defaultOptions } from './util.js';
import { context } from 'esbuild';
import chokidar from 'chokidar';
import { generateLangium } from '../.build/generateLangium.js';
const parserCtx = await context(
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: 'parser' })
);
const mermaidCtx = await context(
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: 'mermaid' })
);
const mermaidIIFECtx = await context(
getBuildConfig({
...defaultOptions,
minify: false,
core: false,
entryName: 'mermaid',
format: 'iife',
})
);
const externalCtx = await context(
getBuildConfig({
...defaultOptions,
minify: false,
core: false,
entryName: 'mermaid-example-diagram',
})
);
const zenumlCtx = await context(
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: 'mermaid-zenuml' })
);
const contexts = [parserCtx, mermaidCtx, mermaidIIFECtx, externalCtx, zenumlCtx];
const rebuildAll = async () => {
console.time('Rebuild time');
await Promise.all(contexts.map((ctx) => ctx.rebuild()));
console.timeEnd('Rebuild time');
};
let clients: { id: number; response: Response }[] = [];
function eventsHandler(request: Request, response: Response, next: NextFunction) {
const headers = {
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
'Cache-Control': 'no-cache',
};
response.writeHead(200, headers);
const clientId = Date.now();
clients.push({
id: clientId,
response,
});
request.on('close', () => {
clients = clients.filter((client) => client.id !== clientId);
});
}
let timeoutId: NodeJS.Timeout | undefined = undefined;
/**
* Debounce file change events to avoid rebuilding multiple times.
*/
function handleFileChange() {
if (timeoutId !== undefined) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(async () => {
await rebuildAll();
sendEventsToAll();
timeoutId = undefined;
}, 100);
}
function sendEventsToAll() {
clients.forEach(({ response }) => response.write(`data: ${Date.now()}\n\n`));
}
async function createServer() {
await generateLangium();
handleFileChange();
const app = express();
chokidar
.watch('**/src/**/*.{js,ts,langium,yaml,json}', {
ignoreInitial: true,
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
})
.on('all', async (event, path) => {
// Ignore other events.
if (!['add', 'change'].includes(event)) {
return;
}
if (/\.langium$/.test(path)) {
await generateLangium();
}
console.log(`${path} changed. Rebuilding...`);
handleFileChange();
});
app.use(cors());
app.get('/events', eventsHandler);
app.use(express.static('./packages/parser/dist'));
app.use(express.static('./packages/mermaid/dist'));
app.use(express.static('./packages/mermaid-zenuml/dist'));
app.use(express.static('./packages/mermaid-example-diagram/dist'));
app.use(express.static('demos'));
app.use(express.static('cypress/platform'));
app.listen(9000, () => {
console.log(`Listening on http://localhost:9000`);
});
}
createServer();

View File

@@ -1,98 +0,0 @@
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import type { BuildOptions } from 'esbuild';
import { readFileSync } from 'fs';
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import { packageOptions } from '../.build/common.js';
import { jisonPlugin } from './jisonPlugin.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
export interface MermaidBuildOptions {
minify: boolean;
core: boolean;
metafile: boolean;
format: 'esm' | 'iife';
entryName: keyof typeof packageOptions;
}
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = {
minify: false,
metafile: false,
core: false,
format: 'esm',
} as const;
const buildOptions = (override: BuildOptions): BuildOptions => {
return {
bundle: true,
minify: true,
keepNames: true,
platform: 'browser',
tsconfig: 'tsconfig.json',
resolveExtensions: ['.ts', '.js', '.json', '.jison', '.yaml'],
external: ['require', 'fs', 'path'],
outdir: 'dist',
plugins: [jisonPlugin, jsonSchemaPlugin],
sourcemap: 'external',
...override,
};
};
const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOptions) => {
if (core) {
fileName += '.core';
} else if (format === 'esm') {
fileName += '.esm';
}
if (minify) {
fileName += '.min';
}
return fileName;
};
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const { core, entryName, metafile, format, minify } = options;
const external: string[] = ['require', 'fs', 'path'];
const { name, file, packageName } = packageOptions[entryName];
const outFileName = getFileName(name, options);
let output: BuildOptions = buildOptions({
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
entryPoints: {
[outFileName]: `src/${file}`,
},
metafile,
minify,
logLevel: 'info',
chunkNames: `chunks/${outFileName}/[name]-[hash]`,
});
if (core) {
const { dependencies } = JSON.parse(
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
);
// Core build is used to generate file without bundled dependencies.
// This is used by downstream projects to bundle dependencies themselves.
// Ignore dependencies and any dependencies of dependencies
external.push(...Object.keys(dependencies));
output.external = external;
}
if (format === 'iife') {
output.format = 'iife';
output.splitting = false;
output.globalName = '__esbuild_esm_mermaid';
// Workaround for removing the .default access in esbuild IIFE.
// https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396
output.footer = {
js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;',
};
output.outExtension = { '.js': '.js' };
} else {
output.format = 'esm';
output.splitting = true;
output.outExtension = { '.js': '.mjs' };
}
return output;
};

View File

@@ -6,6 +6,3 @@ cypress/plugins/index.js
coverage
*.json
node_modules
# autogenereated by langium-cli
generated/

View File

@@ -1,22 +1,4 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/release-drafter/release-drafter/master/schema.json
autolabeler:
- label: 'Type: Bug / Error'
branch:
- '/bug\/.+/'
- '/fix\/.+/'
- label: 'Type: Enhancement'
branch:
- '/feature\/.+/'
- '/feat\/.+/'
- label: 'Type: Other'
branch:
- '/other\/.+/'
- '/chore\/.+/'
- '/test\/.+/'
- '/refactor\/.+/'
- label: 'Area: Documentation'
branch:
- '/docs\/.+/'
template: |
This field is unused, as we only use this config file for labeling PRs.
'Type: Bug / Error': ['bug/*', fix/*]
'Type: Enhancement': ['feature/*', 'feat/*']
'Type: Other': ['other/*', 'chore/*', 'test/*', 'refactor/*']
'Area: Documentation': ['docs/*']

View File

@@ -25,6 +25,8 @@ categories:
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
sort-by: title
sort-direction: ascending
branches:
- develop
exclude-labels:
- 'Skip changelog'
no-changes-template: 'This release contains minor changes and bugfixes.'

View File

@@ -16,12 +16,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: 18
@@ -29,7 +29,7 @@ jobs:
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Verify release version
- name: Verify release verion
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release')) }}
run: pnpm --filter mermaid run docs:verify-version

View File

@@ -19,13 +19,13 @@ jobs:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: Check for difference in README.md and docs/README.md
run: |

View File

@@ -15,7 +15,7 @@ jobs:
name: check tests
if: github.repository_owner == 'mermaid-js'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: testomatio/check-tests@stable

View File

@@ -29,7 +29,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL

View File

@@ -1,6 +1,6 @@
# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
# This Action will scan dependency manifest files that change as part of a Pull Reqest, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
@@ -15,6 +15,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v3

View File

@@ -30,13 +30,13 @@ jobs:
run: |
echo "::error,title=Not using Applitols::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

View File

@@ -17,13 +17,13 @@ jobs:
node-version: [18.x]
containers: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}

View File

@@ -26,7 +26,7 @@ jobs:
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- name: Restore lychee cache
uses: actions/cache@v3

View File

@@ -20,13 +20,13 @@ jobs:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}

View File

@@ -0,0 +1,23 @@
name: Validate PR Labeler Configuration
on:
push:
paths:
- .github/workflows/pr-labeler-config-validator.yml
- .github/workflows/pr-labeler.yml
- .github/pr-labeler.yml
pull_request:
paths:
- .github/workflows/pr-labeler-config-validator.yml
- .github/workflows/pr-labeler.yml
- .github/pr-labeler.yml
jobs:
pr-labeler:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Validate Configuration
uses: Yash-Singh1/pr-labeler-config-validator@releases/v0.0.3
with:
configuration-path: .github/pr-labeler.yml

View File

@@ -1,31 +1,13 @@
name: Apply labels to PR
on:
pull_request_target:
# required for pr-labeler to support PRs from forks
# ===================== ⛔ ☢️ 🚫 ⚠️ Warning ⚠️ 🚫 ☢️ ⛔ =======================
# Be very careful what you put in this GitHub Action workflow file to avoid
# malicious PRs from getting access to the Mermaid-js repo.
#
# Please read the following first before reviewing/merging:
# - https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
# - https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
types: [opened, reopened, synchronize]
permissions:
contents: read
types: [opened]
jobs:
pr-labeler:
runs-on: ubuntu-latest
permissions:
contents: read # read permission is required to read config file
pull-requests: write # write permission is required to label PRs
steps:
- name: Label PR
uses: release-drafter/release-drafter@v5
with:
config-name: pr-labeler.yml
disable-autolabeler: false
disable-releaser: true
uses: TimonVS/pr-labeler-action@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: 18

View File

@@ -5,19 +5,11 @@ on:
branches:
- develop
permissions:
contents: read
jobs:
draft-release:
runs-on: ubuntu-latest
permissions:
contents: write # write permission is required to create a github release
pull-requests: read # required to read PR titles/labels
steps:
- name: Draft Release
uses: release-drafter/release-drafter@v5
with:
disable-autolabeler: true
uses: toolmantim/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -9,14 +9,14 @@ jobs:
publish-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: 18.x

View File

@@ -8,14 +8,14 @@ jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: fregante/setup-git-user@v2
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js v18
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: 18.x

View File

@@ -12,13 +12,13 @@ jobs:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
cache: pnpm
node-version: ${{ matrix.node-version }}

View File

@@ -8,7 +8,7 @@ jobs:
update-browser-list:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
- run: npx browserslist@latest --update-db
- name: Commit changes
uses: EndBug/add-and-commit@v9

4
.gitignore vendored
View File

@@ -46,7 +46,3 @@ stats/
demos/dev/**
!/demos/dev/example.html
!/demos/dev/reload.js
# autogenereated by langium-cli
generated/

View File

@@ -10,6 +10,3 @@ stats
.nyc_output
# Autogenerated by `pnpm run --filter mermaid types:build-config`
packages/mermaid/src/config.type.ts
# autogenereated by langium-cli
generated/

View File

@@ -3,12 +3,11 @@ import { resolve } from 'path';
import { fileURLToPath } from 'url';
import jisonPlugin from './jisonPlugin.js';
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import { readFileSync } from 'fs';
import typescript from '@rollup/plugin-typescript';
import { visualizer } from 'rollup-plugin-visualizer';
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js';
import istanbul from 'vite-plugin-istanbul';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
const visualize = process.argv.includes('--visualize');
const watch = process.argv.includes('--watch');
@@ -37,6 +36,24 @@ const visualizerOptions = (packageName: string, core = false): PluginOption[] =>
);
};
const packageOptions = {
mermaid: {
name: 'mermaid',
packageName: 'mermaid',
file: 'mermaid.ts',
},
'mermaid-example-diagram': {
name: 'mermaid-example-diagram',
packageName: 'mermaid-example-diagram',
file: 'detector.ts',
},
'mermaid-zenuml': {
name: 'mermaid-zenuml',
packageName: 'mermaid-zenuml',
file: 'detector.ts',
},
};
interface BuildOptions {
minify: boolean | 'esbuild';
core?: boolean;
@@ -55,8 +72,34 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
sourcemap,
entryFileNames: `${name}.esm${minify ? '.min' : ''}.mjs`,
},
{
name,
format: 'umd',
sourcemap,
entryFileNames: `${name}${minify ? '.min' : ''}.js`,
},
];
if (core) {
const { dependencies } = JSON.parse(
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
);
// Core build is used to generate file without bundled dependencies.
// This is used by downstream projects to bundle dependencies themselves.
// Ignore dependencies and any dependencies of dependencies
// Adapted from the RegEx used by `rollup-plugin-node`
external.push(new RegExp('^(?:' + Object.keys(dependencies).join('|') + ')(?:/.+)?$'));
// This needs to be an array. Otherwise vite will build esm & umd with same name and overwrite esm with umd.
output = [
{
name,
format: 'esm',
sourcemap,
entryFileNames: `${name}.core.mjs`,
},
];
}
const config: InlineConfig = {
configFile: false,
build: {
@@ -83,7 +126,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
typescript({ compilerOptions: { declaration: false } }),
istanbul({
exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
exclude: ['node_modules', 'test/', '__mocks__'],
extension: ['.js', '.ts'],
requireEnv: true,
forceBuildInstrument: coverage,
@@ -103,28 +146,24 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
const buildPackage = async (entryName: keyof typeof packageOptions) => {
await build(getBuildConfig({ minify: false, entryName }));
await build(getBuildConfig({ minify: 'esbuild', entryName }));
await build(getBuildConfig({ minify: false, core: true, entryName }));
};
const main = async () => {
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
for (const pkg of packageNames.filter(
(pkg) => !mermaidOnly || pkg === 'mermaid' || pkg === 'parser'
)) {
for (const pkg of packageNames.filter((pkg) => !mermaidOnly || pkg === 'mermaid')) {
await buildPackage(pkg);
}
};
await generateLangium();
if (watch) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
if (!mermaidOnly) {
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
}
} else if (visualize) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' }));
await build(getBuildConfig({ minify: false, core: false, entryName: 'mermaid' }));
} else {

View File

@@ -1,10 +1,10 @@
import { transformJison } from '../.build/jisonTransformer.js';
import { transformJison } from './jisonTransformer.js';
const fileRegex = /\.(jison)$/;
export default function jison() {
return {
name: 'jison',
transform(src: string, id: string) {
if (fileRegex.test(id)) {
return {

View File

@@ -1,5 +1,109 @@
import { load, JSON_SCHEMA } from 'js-yaml';
import assert from 'node:assert';
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
import { PluginOption } from 'vite';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
/**
* All of the keys in the mermaid config that have a mermaid diagram config.
*/
const MERMAID_CONFIG_DIAGRAM_KEYS = [
'flowchart',
'sequence',
'gantt',
'journey',
'class',
'state',
'er',
'pie',
'quadrantChart',
'xyChart',
'requirement',
'mindmap',
'timeline',
'gitGraph',
'c4',
'sankey',
] as const;
/**
* Generate default values from the JSON Schema.
*
* AJV does not support nested default values yet (or default values with $ref),
* so we need to manually find them (this may be fixed in ajv v9).
*
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
* @returns The default mermaid config object.
*/
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
const ajv = new Ajv2019({
useDefaults: true,
allowUnionTypes: true,
strict: true,
});
ajv.addKeyword({
keyword: 'meta:enum', // used by jsonschema2md
errors: false,
});
ajv.addKeyword({
keyword: 'tsType', // used by json-schema-to-typescript
errors: false,
});
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
// (may be fixed in v9) so we need to manually use sub-schemas
const mermaidDefaultConfig = {};
assert.ok(mermaidConfigSchema.$defs);
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
const [root, defs, defName] = subSchemaRef.split('/');
assert.strictEqual(root, '#');
assert.strictEqual(defs, '$defs');
const subSchema = {
$schema: mermaidConfigSchema.$schema,
$defs: mermaidConfigSchema.$defs,
...mermaidConfigSchema.$defs[defName],
} as JSONSchemaType<BaseDiagramConfig>;
const validate = ajv.compile(subSchema);
mermaidDefaultConfig[key] = {};
for (const required of subSchema.required ?? []) {
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
}
}
if (!validate(mermaidDefaultConfig[key])) {
throw new Error(
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
}
const validate = ajv.compile(mermaidConfigSchema);
if (!validate(mermaidDefaultConfig)) {
throw new Error(
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
return mermaidDefaultConfig;
}
/**
* Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file.
@@ -16,13 +120,32 @@ export default function jsonSchemaPlugin(): PluginOption {
return;
}
const jsonSchema = loadSchema(src, idAsUrl.pathname);
return {
code: idAsUrl.searchParams.get('only-defaults')
? getDefaults(jsonSchema)
: getSchema(jsonSchema),
map: null, // no source map
};
if (idAsUrl.searchParams.get('only-defaults')) {
const jsonSchema = load(src, {
filename: idAsUrl.pathname,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}) as JSONSchemaType<MermaidConfig>;
return {
code: `export default ${JSON.stringify(generateDefaults(jsonSchema), undefined, 2)};`,
map: null, // no source map
};
} else {
return {
code: `export default ${JSON.stringify(
load(src, {
filename: idAsUrl.pathname,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}),
undefined,
2
)};`,
map: null, // provide source map if available
};
}
},
};
}

View File

@@ -14,7 +14,6 @@ async function createServer() {
});
app.use(cors());
app.use(express.static('./packages/parser/dist'));
app.use(express.static('./packages/mermaid/dist'));
app.use(express.static('./packages/mermaid-zenuml/dist'));
app.use(express.static('./packages/mermaid-example-diagram/dist'));

View File

@@ -44,22 +44,6 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
<a href="https://mermaid-js.github.io/mermaid/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
## Table of content
<details>
<summary>Expand contents</summary>
- [About](#about)
- [Examples](#examples)
- [Release](#release)
- [Related projects](#related-projects)
- [Contributors](#contributors)
- [Security and safe diagrams](#security-and-safe-diagrams)
- [Reporting vulnerabilities](#reporting-vulnerabilities)
- [Appreciation](#appreciation)
</details>
## About
<!-- <Main description> -->
@@ -74,7 +58,7 @@ Mermaid addresses this problem by enabling users to create easily modifiable dia
<br/>
Mermaid allows even non-programmers to easily create detailed diagrams through the [Mermaid Live Editor](https://mermaid.live/).<br/>
For video tutorials, visit our [Tutorials](./docs/config/Tutorials.md) page.
[Tutorials](./docs/config/Tutorials.md) has video tutorials.
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md).
You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications—check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md).

View File

@@ -61,7 +61,6 @@
"gzipped",
"huynh",
"huynhicode",
"iife",
"inkdrop",
"jaoude",
"jgreywolf",
@@ -75,7 +74,6 @@
"knut",
"knutsveidqvist",
"laganeckas",
"langium",
"linetype",
"lintstagedrc",
"logmsg",
@@ -87,7 +85,6 @@
"mdbook",
"mermaidjs",
"mermerd",
"metafile",
"mindaugas",
"mindmap",
"mindmaps",
@@ -101,7 +98,6 @@
"nirname",
"npmjs",
"orlandoni",
"outdir",
"pathe",
"pbrolin",
"phpbb",

View File

@@ -1,11 +0,0 @@
describe('IIFE', () => {
beforeEach(() => {
cy.visit('http://localhost:9000/iife.html');
});
it('should render when using mermaid.min.js', () => {
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
cy.get('#d2').should('contain', 'Hello');
});
});

View File

@@ -0,0 +1,16 @@
describe('Sequencediagram', () => {
it('should render a simple sequence diagrams', () => {
const url = 'http://localhost:9000/webpackUsage.html';
cy.visit(url);
cy.get('body').find('svg').should('have.length', 1);
});
it('should handle html escapings properly', () => {
const url = 'http://localhost:9000/webpackUsage.html?test-html-escaping=true';
cy.visit(url);
cy.get('body').find('svg').should('have.length', 1);
cy.get('g.label > foreignobject > div').should('not.contain.text', '<b>');
});
});

View File

@@ -501,16 +501,4 @@ describe('Class diagram', () => {
B : -methods()
`);
});
it('should handle notes with anchor tag having target attribute', () => {
renderGraph(
`classDiagram
class test { }
note for test "<a href='https://mermaid.js.org/' target="_blank"><code>note about mermaid</code></a>"`
);
cy.get('svg').then((svg) => {
cy.get('a').should('have.attr', 'target', '_blank').should('have.attr', 'rel', 'noopener');
});
});
});

View File

@@ -1,7 +1,7 @@
<html>
<head>
<meta charset="utf-8" />
<script type="module" src="./viewer.js"></script>
<script src="./viewer.js" type="module"></script>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"

View File

@@ -11,7 +11,8 @@ example-diagram
<!-- <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> -->
<!-- <script type="module" src="./external-diagrams-mindmap.mjs" /> -->
<script type="module">
import exampleDiagram from './mermaid-example-diagram.esm.mjs';
import exampleDiagram from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
// import example from '../../packages/mermaid-example-diagram/src/detector';
import mermaid from './mermaid.esm.mjs';
await mermaid.registerExternalDiagrams([exampleDiagram]);

View File

@@ -1,29 +0,0 @@
<html>
<body>
<pre id="diagram" class="mermaid">
graph TB
a --> b
a --> c
b --> d
c --> d
</pre>
<div id="d2"></div>
<script src="/mermaid.min.js"></script>
<script>
mermaid.initialize({
startOnLoad: true,
});
const value = `graph TD\nHello --> World`;
const el = document.getElementById('d2');
mermaid.render('did', value).then(({ svg }) => {
console.log(svg);
el.innerHTML = svg;
if (window.Cypress) {
window.rendered = true;
}
});
</script>
</body>
</html>

View File

@@ -17,20 +17,20 @@
graph TB
Function-->URL
click Function clickByFlow "Add a div"
click URL "http://localhost:9000/info.html" "Visit <strong>mermaid docs</strong>"
click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</pre>
<pre id="FirstLine" class="mermaid2">
graph TB
1Function-->2URL
click 1Function clickByFlow "Add a div"
click 2URL "http://localhost:9000/info.html" "Visit <strong>mermaid docs</strong>"
click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</pre>
<pre id="FirstLine" class="mermaid2">
classDiagram
class Test
class ShapeLink
link ShapeLink "http://localhost:9000/info.html" "This is a tooltip for a link"
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback"
</pre>
@@ -42,7 +42,7 @@
<pre id="FirstLine" class="mermaid">
classDiagram-v2
class ShapeLink
link ShapeLink "http://localhost:9000/info.html" "This is a tooltip for a link"
link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
</pre>
</div>
@@ -77,7 +77,7 @@
Calling a Callback (look at the console log) :cl2, after cl1, 3d
Calling a Callback with args :cl3, after cl1, 3d
click cl1 href "http://localhost:9000/info.html"
click cl1 href "http://localhost:9000/webpackUsage.html"
click cl2 call clickByGantt()
click cl3 call clickByGantt("test1", test2, test3)
@@ -102,15 +102,9 @@
div.className = 'created-by-gant-click';
div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Gant';
if (arg1) {
div.innerText += ' ' + arg1;
}
if (arg2) {
div.innerText += ' ' + arg2;
}
if (arg3) {
div.innerText += ' ' + arg3;
}
if (arg1) div.innerText += ' ' + arg1;
if (arg2) div.innerText += ' ' + arg2;
if (arg3) div.innerText += ' ' + arg3;
document.getElementsByTagName('body')[0].appendChild(div);
}

View File

@@ -1,6 +1,6 @@
import mermaid from './mermaid.esm.mjs';
import externalExample from './mermaid-example-diagram.esm.mjs';
import zenUml from './mermaid-zenuml.esm.mjs';
import mermaid2 from './mermaid.esm.mjs';
import externalExample from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
import zenUml from '../../packages/mermaid-zenuml/dist/mermaid-zenuml.core.mjs';
function b64ToUtf8(str) {
return decodeURIComponent(escape(window.atob(str)));
@@ -45,9 +45,9 @@ const contentLoaded = async function () {
document.getElementsByTagName('body')[0].appendChild(div);
}
await mermaid.registerExternalDiagrams([externalExample, zenUml]);
mermaid.initialize(graphObj.mermaid);
await mermaid.run();
await mermaid2.registerExternalDiagrams([externalExample, zenUml]);
mermaid2.initialize(graphObj.mermaid);
await mermaid2.run();
}
};
@@ -95,14 +95,18 @@ const contentLoadedApi = async function () {
divs[i] = div;
}
const defaultE2eCnf = { theme: 'forest', startOnLoad: false };
const defaultE2eCnf = { theme: 'forest' };
const cnf = merge(defaultE2eCnf, graphObj.mermaid);
mermaid.initialize(cnf);
mermaid2.initialize(cnf);
for (let i = 0; i < numCodes; i++) {
const { svg, bindFunctions } = await mermaid.render('newid' + i, graphObj.code[i], divs[i]);
const { svg, bindFunctions } = await mermaid2.render(
'newid' + i,
graphObj.code[i],
divs[i]
);
div.innerHTML = svg;
bindFunctions(div);
}
@@ -110,21 +114,18 @@ const contentLoadedApi = async function () {
const div = document.createElement('div');
div.id = 'block';
div.className = 'mermaid';
console.warn('graphObj', graphObj);
console.warn('graphObj.mermaid', graphObj.mermaid);
document.getElementsByTagName('body')[0].appendChild(div);
mermaid.initialize(graphObj.mermaid);
const { svg, bindFunctions } = await mermaid.render('newid', graphObj.code, div);
mermaid2.initialize(graphObj.mermaid);
const { svg, bindFunctions } = await mermaid2.render('newid', graphObj.code, div);
div.innerHTML = svg;
console.log(div.innerHTML);
bindFunctions(div);
}
}
};
if (typeof document !== 'undefined') {
mermaid.initialize({
startOnLoad: false,
});
/*!
* Wait for document loaded before starting the execution
*/

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<style>
/* .mermaid {
font-family: "trebuchet ms", verdana, arial;;
} */
/* .mermaid {
font-family: 'arial';
} */
</style>
</head>
<body>
<div id="graph-to-be"></div>
<script type="module" charset="utf-8">
import './bundle-test.js';
</script>
</body>
</html>

View File

@@ -1,5 +1,6 @@
<html>
<head>
<script src="./viewer.js" type="module"></script>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<style>
.malware {
@@ -32,6 +33,12 @@
</script>
</head>
<body>
<script type="module" src="./viewer.js"></script>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
startOnLoad: false,
useMaxWidth: true,
});
</script>
</body>
</html>

View File

@@ -5,8 +5,6 @@
<title>Mermaid development page</title>
</head>
<body>
<pre class="mermaid">info</pre>
<pre id="diagram" class="mermaid">
graph TB
a --> b
@@ -32,7 +30,5 @@ graph TB
console.log(svg);
el.innerHTML = svg;
</script>
<script src="/dev/reload.js"></script>
</body>
</html>

View File

@@ -1,22 +0,0 @@
// Connect to the server and reload the page if the server sends a reload message
const connectToEvents = () => {
const events = new EventSource('/events');
const loadTime = Date.now();
events.onmessage = (event) => {
const time = JSON.parse(event.data);
if (time && time > loadTime) {
location.reload();
}
};
events.onerror = (error) => {
console.error(error);
events.close();
// Try to reconnect after 1 second in case of errors
setTimeout(connectToEvents, 1000);
};
events.onopen = () => {
console.log('Connected to live reload server');
};
};
setTimeout(connectToEvents, 500);

View File

@@ -37,7 +37,7 @@
</pre>
<script type="module">
import mermaid from '/mermaid.esm.mjs';
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
theme: 'forest',
logLevel: 3,

View File

@@ -164,13 +164,6 @@
end
</pre>
<pre class="mermaid">
sequenceDiagram
actor Alice
actor John
Alice-xJohn: Hello John, how are you?
John--xAlice: Great!
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({

View File

@@ -10,8 +10,9 @@
## First search to see if someone has already asked (and hopefully been answered) or suggested the same thing.
- [Search in Discussions](https://github.com/orgs/mermaid-js/discussions)
- [Search in Issues (Open & Closed)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue)
- Search in Discussions
- Search in open Issues
- Search in closed Issues
If you find an open issue or discussion thread that is similar to your question but isn't answered, you can let us know that you are also interested in it.
Use the GitHub reactions to add a thumbs-up to the issue or discussion thread.

View File

@@ -10,8 +10,8 @@ When mermaid starts, configuration is extracted to determine a configuration to
- The default configuration
- Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
- Frontmatter (v10.5.0+) - diagram authors can update selected configuration parameters in the frontmatter of the diagram. These are applied to the render config.
- Directives (Deprecated by Frontmatter) - diagram authors can update selected configuration parameters directly in the diagram code via directives. These are applied to the render config.
- Frontmatter (v10.5.0+) - diagram authors can update select configuration parameters in the frontmatter of the diagram. These are applied to the render config.
- Directives (Deprecated by Frontmatter) - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config.
**The render config** is configuration that is used when rendering by applying these configurations.

View File

@@ -16,4 +16,4 @@
#### Defined in
[mermaidAPI.ts:60](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L60)
[mermaidAPI.ts:59](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L59)

View File

@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in
[mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80)
[mermaidAPI.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L79)
---
@@ -51,4 +51,4 @@ The svg code for the rendered graph.
#### Defined in
[mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70)
[mermaidAPI.ts:69](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L69)

View File

@@ -25,7 +25,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
#### Defined in
[mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64)
[mermaidAPI.ts:63](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L63)
## Variables
@@ -96,7 +96,7 @@ mermaid.initialize(config);
#### Defined in
[mermaidAPI.ts:603](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L603)
[mermaidAPI.ts:641](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L641)
## Functions
@@ -127,7 +127,7 @@ Return the last node appended
#### Defined in
[mermaidAPI.ts:263](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L263)
[mermaidAPI.ts:299](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L299)
---
@@ -153,7 +153,7 @@ the cleaned up svgCode
#### Defined in
[mermaidAPI.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L209)
[mermaidAPI.ts:245](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L245)
---
@@ -178,7 +178,7 @@ the string with all the user styles
#### Defined in
[mermaidAPI.ts:139](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L139)
[mermaidAPI.ts:175](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L175)
---
@@ -201,7 +201,7 @@ the string with all the user styles
#### Defined in
[mermaidAPI.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L186)
[mermaidAPI.ts:222](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L222)
---
@@ -228,7 +228,47 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in
[mermaidAPI.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L124)
[mermaidAPI.ts:160](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L160)
---
### decodeEntities
**decodeEntities**(`text`): `string`
#### Parameters
| Name | Type | Description |
| :----- | :------- | :----------------- |
| `text` | `string` | text to be decoded |
#### Returns
`string`
#### Defined in
[mermaidAPI.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L146)
---
### encodeEntities
**encodeEntities**(`text`): `string`
#### Parameters
| Name | Type | Description |
| :----- | :------- | :----------------- |
| `text` | `string` | text to be encoded |
#### Returns
`string`
#### Defined in
[mermaidAPI.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L117)
---
@@ -254,7 +294,7 @@ Put the svgCode into an iFrame. Return the iFrame code
#### Defined in
[mermaidAPI.ts:240](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L240)
[mermaidAPI.ts:276](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L276)
---
@@ -279,4 +319,4 @@ Remove any existing elements from the given document
#### Defined in
[mermaidAPI.ts:313](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L313)
[mermaidAPI.ts:349](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L349)

View File

@@ -64,7 +64,7 @@ Example:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script>
```
@@ -83,7 +83,7 @@ Example:
B-->D(fa:fa-spinner);
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script>
</body>
</html>

View File

@@ -35,19 +35,12 @@ Below are a list of community plugins and integrations created with Mermaid.
- [Notion](https://notion.so) ✅
- [Observable](https://observablehq.com/@observablehq/mermaid) ✅
- [Obsidian](https://help.obsidian.md/Editing+and+formatting/Advanced+formatting+syntax#Diagram) ✅
- [NotesHub](https://noteshub.app) ✅
- [GitBook](https://gitbook.com)
- [Mermaid Plugin](https://github.com/JozoVilcek/gitbook-plugin-mermaid)
- [Markdown with Mermaid CLI](https://github.com/miao1007/gitbook-plugin-mermaid-cli)
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
- [LiveBook](https://livebook.dev) ✅
- [Atlassian Products](https://www.atlassian.com)
- [Mermaid for Confluence](https://marketplace.atlassian.com/apps/1224722/mermaid-for-confluence?hosting=cloud&tab=overview)
- [Mermaid Integration for Confluence](https://marketplace.atlassian.com/apps/1222792/mermaid-integration-for-confluence?hosting=cloud&tab=overview)
- [Mermaid Diagrams for Confluence](https://marketplace.atlassian.com/apps/1226945/mermaid-diagrams-for-confluence?hosting=cloud&tab=overview)
- [Mermaid Macro for Confluence](https://marketplace.atlassian.com/apps/1231150/mermaid-macro-for-confluence?hosting=cloud&tab=overview)
- [EliteSoft Mermaid Charts and Diagrams](https://marketplace.atlassian.com/apps/1227286/elitesoft-mermaid-charts-and-diagrams?hosting=cloud&tab=overview)
- [Mermaid for Jira Cloud - Draw UML diagrams easily](https://marketplace.atlassian.com/apps/1223053/mermaid-for-jira-cloud-draw-uml-diagrams-easily?hosting=cloud&tab=overview)
- [Mermaid Charts & Diagrams for Confluence](https://marketplace.atlassian.com/apps/1222572/)
- [Mermaid Charts & Diagrams for Jira](https://marketplace.atlassian.com/apps/1224537/)
- [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview)
@@ -106,8 +99,6 @@ Communication tools and platforms
- [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid)
- [NodeBB](https://nodebb.org)
- [Mermaid Plugin](https://www.npmjs.com/package/nodebb-plugin-mermaid)
- [Slack](https://slack.com)
- [Mermaid for Slack](https://github.com/JackuB/mermaid-for-slack)
### Wikis
@@ -178,7 +169,6 @@ Communication tools and platforms
### Document Generation
- [Docusaurus](https://docusaurus.io/docs/markdown-features/diagrams) ✅
- [Swimm - Up-to-date diagrams with Swimm, the knowledge management tool for code](https://docs.swimm.io/Features/diagrams-and-charts)
- [Sphinx](https://www.sphinx-doc.org/en/master/)
- [sphinxcontrib-mermaid](https://github.com/mgaitan/sphinxcontrib-mermaid)

View File

@@ -128,7 +128,7 @@ b. The importing of mermaid library through the `mermaid.esm.mjs` or `mermaid.es
```html
<body>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>
@@ -168,7 +168,7 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. However, doi
</pre>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
</body>

View File

@@ -317,7 +317,7 @@ To select a version:
Replace `<version>` with the desired version number.
Latest Version: <https://cdn.jsdelivr.net/npm/mermaid@11>
Latest Version: <https://cdn.jsdelivr.net/npm/mermaid@10>
## Deploying Mermaid
@@ -335,12 +335,12 @@ To Deploy Mermaid:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>
```
**Doing so commands the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags, mermaid tries to read the diagram/chart definitions and render them into SVG charts.**
**Doing so commands the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags, mermaid tries read the diagram/chart definitions and render them into SVG charts.**
**Examples can be found in** [Other examples](../syntax/examples.md)

View File

@@ -399,7 +399,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
title Component diagram for Internet Banking System - API Application
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile mobile device.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.")
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
@@ -439,7 +439,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
title Component diagram for Internet Banking System - API Application
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile mobile device.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.")
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")

View File

@@ -425,6 +425,8 @@ And `Link` can be one of:
A namespace groups classes.
Code:
```mermaid-example
classDiagram
namespace BaseShapes {

View File

@@ -467,7 +467,7 @@ flowchart TB
A & B--> C & D
```
If you describe the same diagram using the basic syntax, it will take four lines. A
If you describe the same diagram using the the basic syntax, it will take four lines. A
word of warning, one could go overboard with this making the flowchart harder to read in
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
This goes for expressive syntaxes as well.

View File

@@ -300,7 +300,7 @@ From version 9.4.0 you can simplify this code to:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script>
```

View File

@@ -469,7 +469,7 @@ You can use this method to add mermaid including the timeline diagram to a web p
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script>
```

View File

@@ -4,7 +4,7 @@
"version": "10.2.4",
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module",
"packageManager": "pnpm@8.10.4",
"packageManager": "pnpm@8.9.2",
"keywords": [
"diagram",
"markdown",
@@ -15,15 +15,15 @@
"git graph"
],
"scripts": {
"build": "pnpm build:esbuild && pnpm build:types",
"build:esbuild": "pnpm run -r clean && ts-node-esm --transpileOnly .esbuild/build.ts",
"build:mermaid": "pnpm build:esbuild --mermaid",
"build:viz": "pnpm build:esbuild --visualize",
"build:types": "tsc -p ./packages/parser/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-zenuml/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-example-diagram/tsconfig.json --emitDeclarationOnly",
"build:vite": "ts-node-esm --transpileOnly .vite/build.ts",
"build:mermaid": "pnpm build:vite --mermaid",
"build:viz": "pnpm build:mermaid --visualize",
"build:types": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-zenuml/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-example-diagram/tsconfig.json --emitDeclarationOnly",
"build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch",
"dev": "ts-node-esm --transpileOnly .esbuild/server.ts",
"dev:vite": "ts-node-esm --transpileOnly .vite/server.ts",
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev:vite",
"build:watch": "pnpm build:vite --watch",
"build": "pnpm run -r clean && pnpm build:types && pnpm build:vite",
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev",
"release": "pnpm build",
"lint": "eslint --cache --cache-strategy content --ignore-path .gitignore . && pnpm lint:jison && prettier --cache --check .",
"lint:fix": "eslint --cache --cache-strategy content --fix --ignore-path .gitignore . && prettier --write . && ts-node-esm scripts/fixCSpell.ts",
@@ -32,8 +32,8 @@
"cypress": "cypress run",
"cypress:open": "cypress open",
"e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"e2e:coverage": "start-server-and-test dev:coverage http://localhost:9000/ cypress",
"coverage:cypress:clean": "rimraf .nyc_output coverage/cypress",
"e2e:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm e2e",
"coverage:merge": "ts-node-esm scripts/coverage.ts",
"coverage": "pnpm test:coverage --run && pnpm e2e:coverage && pnpm coverage:merge",
"ci": "vitest run",
@@ -83,7 +83,6 @@
"@vitest/spy": "^0.34.0",
"@vitest/ui": "^0.34.0",
"ajv": "^8.12.0",
"chokidar": "^3.5.3",
"concurrently": "^8.0.1",
"cors": "^2.8.5",
"cypress": "^12.10.0",
@@ -108,7 +107,6 @@
"jison": "^0.4.18",
"js-yaml": "^4.1.0",
"jsdom": "^22.0.0",
"langium-cli": "2.0.1",
"lint-staged": "^13.2.1",
"nyc": "^15.1.0",
"path-browserify": "^1.0.1",

View File

@@ -43,7 +43,8 @@
"cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.1.0",
"d3": "^7.0.0",
"khroma": "^2.0.0"
"khroma": "^2.0.0",
"non-layered-tidy-tree-layout": "^2.0.2"
},
"devDependencies": {
"@types/cytoscape": "^3.19.9",

View File

@@ -1,12 +0,0 @@
{
"name": "@mermaid-js/flowchart-elk",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT"
}

View File

@@ -19,7 +19,6 @@
"mermaid"
],
"scripts": {
"clean": "rimraf dist",
"prepublishOnly": "pnpm -w run build"
},
"repository": {

View File

@@ -5,6 +5,7 @@
* This is a dummy parser that satisfies the mermaid API logic.
*/
export default {
parser: { yy: {} },
parse: () => {
// no op
},

View File

@@ -1,6 +1,6 @@
{
"name": "mermaid",
"version": "11.0.0-alpha.2",
"version": "10.6.0",
"description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module",
"module": "./dist/mermaid.core.mjs",
@@ -60,6 +60,8 @@
},
"dependencies": {
"@braintree/sanitize-url": "^6.0.1",
"@types/d3-scale": "^4.0.3",
"@types/d3-scale-chromatic": "^3.0.0",
"cytoscape": "^3.23.0",
"cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.1.0",
@@ -72,10 +74,11 @@
"khroma": "^2.0.0",
"lodash-es": "^4.17.21",
"mdast-util-from-markdown": "^1.3.0",
"mermaid-parser": "workspace:^",
"non-layered-tidy-tree-layout": "^2.0.2",
"stylis": "^4.1.3",
"ts-dedent": "^2.2.0",
"uuid": "^9.0.0"
"uuid": "^9.0.0",
"web-worker": "^1.2.0"
},
"devDependencies": {
"@adobe/jsonschema2md": "^7.1.4",
@@ -83,7 +86,6 @@
"@types/d3": "^7.4.0",
"@types/d3-sankey": "^0.12.1",
"@types/d3-scale": "^4.0.3",
"@types/d3-scale-chromatic": "^3.0.0",
"@types/d3-selection": "^3.0.5",
"@types/d3-shape": "^3.1.1",
"@types/dompurify": "^3.0.2",

View File

@@ -1,10 +1,8 @@
import * as configApi from './config.js';
import { log } from './logger.js';
import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js';
import { detectType, getDiagramLoaderAndPriority } from './diagram-api/detectType.js';
import { detectType, getDiagramLoader } from './diagram-api/detectType.js';
import { UnknownDiagramError } from './errors.js';
import { encodeEntities } from './utils.js';
import type { DetailedError } from './utils.js';
import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js';
@@ -23,7 +21,6 @@ export class Diagram {
private detectError?: UnknownDiagramError;
constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) {
this.text = encodeEntities(text);
this.text += '\n';
const cnf = configApi.getConfig();
try {
@@ -38,10 +35,7 @@ export class Diagram {
this.db = diagram.db;
this.renderer = diagram.renderer;
this.parser = diagram.parser;
if (this.parser.parser) {
// The parser.parser.yy is only present in JISON parsers. So, we'll only set if required.
this.parser.parser.yy = this.db;
}
this.parser.parser.yy = this.db;
this.init = diagram.init;
this.parse();
}
@@ -92,14 +86,14 @@ export const getDiagramFromText = async (
// Trying to find the diagram
getDiagram(type);
} catch (error) {
const { loader, priority } = getDiagramLoaderAndPriority(type);
const loader = getDiagramLoader(type);
if (!loader) {
throw new UnknownDiagramError(`Diagram ${type} not found.`);
}
// Diagram not available, loading it.
// new diagram will try getDiagram again and if fails then it is a valid throw
const { id, diagram } = await loader();
registerDiagram(id, diagram, priority);
registerDiagram(id, diagram);
}
return new Diagram(text, metadata);
};

View File

@@ -61,7 +61,7 @@ export interface MermaidConfig {
* You may also use `themeCSS` to override this value.
*
*/
theme?: 'default' | 'forest' | 'dark' | 'neutral' | 'null';
theme?: string | 'default' | 'forest' | 'dark' | 'neutral' | 'null';
themeVariables?: any;
themeCSS?: string;
/**
@@ -82,11 +82,26 @@ export interface MermaidConfig {
* This option decides the amount of logging to be used by mermaid.
*
*/
logLevel?: 'trace' | 0 | 'debug' | 1 | 'info' | 2 | 'warn' | 3 | 'error' | 4 | 'fatal' | 5;
logLevel?:
| number
| string
| 0
| 2
| 1
| 'trace'
| 'debug'
| 'info'
| 'warn'
| 'error'
| 'fatal'
| 3
| 4
| 5
| undefined;
/**
* Level of trust for parsed diagram
*/
securityLevel?: 'strict' | 'loose' | 'antiscript' | 'sandbox';
securityLevel?: string | 'strict' | 'loose' | 'antiscript' | 'sandbox' | undefined;
/**
* Dictates whether mermaid starts on Page load
*/
@@ -897,7 +912,7 @@ export interface ErDiagramConfig extends BaseDiagramConfig {
/**
* Directional bias for layout of entities
*/
layoutDirection?: 'TB' | 'BT' | 'LR' | 'RL';
layoutDirection?: string | 'TB' | 'BT' | 'LR' | 'RL';
/**
* The minimum width of an entity box. Expressed in pixels.
*/
@@ -962,7 +977,7 @@ export interface StateDiagramConfig extends BaseDiagramConfig {
* Decides which rendering engine that is to be used for the rendering.
*
*/
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk';
defaultRenderer?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
}
/**
* This interface was referenced by `MermaidConfig`'s JSON-Schema
@@ -986,7 +1001,7 @@ export interface ClassDiagramConfig extends BaseDiagramConfig {
* Decides which rendering engine that is to be used for the rendering.
*
*/
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk';
defaultRenderer?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
nodeSpacing?: number;
rankSpacing?: number;
/**
@@ -1046,7 +1061,7 @@ export interface JourneyDiagramConfig extends BaseDiagramConfig {
/**
* Multiline message alignment
*/
messageAlign?: 'left' | 'center' | 'right';
messageAlign?: string | 'left' | 'center' | 'right';
/**
* Prolongs the edge of the diagram downwards.
*
@@ -1125,7 +1140,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
/**
* Multiline message alignment
*/
messageAlign?: 'left' | 'center' | 'right';
messageAlign?: string | 'left' | 'center' | 'right';
/**
* Prolongs the edge of the diagram downwards.
*
@@ -1236,7 +1251,7 @@ export interface GanttDiagramConfig extends BaseDiagramConfig {
* Controls the display mode.
*
*/
displayMode?: '' | 'compact';
displayMode?: string | 'compact';
/**
* On which day a week-based interval should start
*
@@ -1295,7 +1310,7 @@ export interface SequenceDiagramConfig extends BaseDiagramConfig {
/**
* Multiline message alignment
*/
messageAlign?: 'left' | 'center' | 'right';
messageAlign?: string | 'left' | 'center' | 'right';
/**
* Mirror actors under diagram
*
@@ -1352,7 +1367,7 @@ export interface SequenceDiagramConfig extends BaseDiagramConfig {
/**
* This sets the text alignment of actor-attached notes
*/
noteAlign?: 'left' | 'center' | 'right';
noteAlign?: string | 'left' | 'center' | 'right';
/**
* This sets the font size of actor messages
*/
@@ -1428,7 +1443,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
* Defines how mermaid renders curves for flowcharts.
*
*/
curve?: 'basis' | 'linear' | 'cardinal';
curve?: string | 'basis' | 'linear' | 'cardinal';
/**
* Represents the padding between the labels and the shape
*
@@ -1440,7 +1455,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
* Decides which rendering engine that is to be used for the rendering.
*
*/
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk';
defaultRenderer?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
/**
* Width of nodes where text is wrapped.
*

View File

@@ -2,7 +2,7 @@ import { select } from 'd3';
import { log } from '../logger.js';
import { getConfig } from '../diagram-api/diagramAPI.js';
import { evaluate } from '../diagrams/common/common.js';
import { decodeEntities } from '../utils.js';
import { decodeEntities } from '../mermaidAPI.js';
/**
* @param dom

View File

@@ -1,9 +1,9 @@
import createLabel from '../createLabel.js';
import { createText } from '../../rendering-util/createText.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
import { decodeEntities } from '../../mermaidAPI.js';
import { select } from 'd3';
import { evaluate, sanitizeText } from '../../diagrams/common/common.js';
import { decodeEntities } from '../../utils.js';
export const labelHelper = async (parent, node, _classes, isNode) => {
let classes;

View File

@@ -61,37 +61,23 @@ export const detectType = function (text: string, config?: MermaidConfig): strin
* The first detector to return `true` is the diagram that will be loaded
* and used, so put more specific detectors at the beginning!
*
* If two diagrams are registered with the same id,
* the one with higher `priority` property will be used.
*
* @param diagrams - Diagrams to lazy load, and their detectors, in order of importance.
*/
export const registerLazyLoadedDiagrams = (...diagrams: ExternalDiagramDefinition[]) => {
for (const { id, detector, priority, loader } of diagrams) {
addDetector(id, detector, priority ?? 0, loader);
for (const { id, detector, loader } of diagrams) {
addDetector(id, detector, loader);
}
};
export const addDetector = (
key: string,
detector: DiagramDetector,
priority: number,
loader?: DiagramLoader
) => {
if (detectors[key] && priority <= detectors[key].priority) {
log.error(
`Detector with key ${key} already exists with priority ${detectors[key].priority}. Cannot add new detector with priority ${priority}`
);
return;
export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => {
if (detectors[key]) {
log.error(`Detector with key ${key} already exists`);
} else {
detectors[key] = { detector, loader };
}
detectors[key] = { detector, loader, priority };
log.debug(
`Detector with key ${key} added with priority ${priority} ${loader ? 'and loader' : ''}`
);
log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`);
};
export const getDiagramLoaderAndPriority = (key: string) => {
const { loader, priority } = detectors[key];
return { loader, priority };
export const getDiagramLoader = (key: string) => {
return detectors[key].loader;
};

View File

@@ -31,7 +31,7 @@ export const addDiagrams = () => {
// This is added here to avoid race-conditions.
// We could optimize the loading logic somehow.
hasLoadedDiagrams = true;
registerDiagram('error', errorDiagram, 0, (text) => {
registerDiagram('error', errorDiagram, (text) => {
return text.toLowerCase().trim() === 'error';
});
registerDiagram(
@@ -50,6 +50,7 @@ export const addDiagrams = () => {
},
},
parser: {
parser: { yy: {} },
parse: () => {
throw new Error(
'Diagrams beginning with --- are not valid. ' +
@@ -60,7 +61,6 @@ export const addDiagrams = () => {
},
init: () => null, // no op
},
0,
(text) => {
return text.toLowerCase().trimStart().startsWith('---');
}

View File

@@ -39,6 +39,7 @@ describe('DiagramAPI', () => {
parse: (_text) => {
return;
},
parser: { yy: {} },
},
renderer: {
draw: () => {
@@ -47,7 +48,6 @@ describe('DiagramAPI', () => {
},
styles: {},
},
0,
detector
);
expect(getDiagram('loki')).not.toBeNull();

View File

@@ -29,7 +29,7 @@ export const getCommonDb = () => {
return _commonDb;
};
const diagrams: Record<string, DiagramDefinition & { priority: number }> = {};
const diagrams: Record<string, DiagramDefinition> = {};
export interface Detectors {
[key: string]: DiagramDetector;
}
@@ -37,8 +37,7 @@ export interface Detectors {
/**
* Registers the given diagram with Mermaid.
*
* To be used internally by Mermaid.
* Use `mermaid.registerExternalDiagrams` to register external diagrams.
* Can be used for third-party custom diagrams.
*
* @param id - A unique ID for the given diagram.
* @param diagram - The diagram definition.
@@ -47,17 +46,14 @@ export interface Detectors {
export const registerDiagram = (
id: string,
diagram: DiagramDefinition,
priority: number,
detector?: DiagramDetector
) => {
if (diagrams[id] && priority <= diagrams[id].priority) {
throw new Error(
`Diagram ${id} already registered with priority ${diagrams[id].priority}. Cannot add new diagram with priority ${priority}`
);
if (diagrams[id]) {
throw new Error(`Diagram ${id} already registered.`);
}
diagrams[id] = { ...diagram, priority };
diagrams[id] = diagram;
if (detector) {
addDetector(id, detector, priority);
addDetector(id, detector);
}
addStylesForDiagram(id, diagram.styles);

View File

@@ -1,4 +1,4 @@
import type { GanttDiagramConfig, MermaidConfig } from '../config.type.js';
import type { MermaidConfig } from '../config.type.js';
import { frontMatterRegex } from './regexes.js';
// The "* as yaml" part is necessary for tree-shaking
import * as yaml from 'js-yaml';
@@ -6,7 +6,7 @@ import * as yaml from 'js-yaml';
interface FrontMatterMetadata {
title?: string;
// Allows custom display modes. Currently used for compact mode in gantt charts.
displayMode?: GanttDiagramConfig['displayMode'];
displayMode?: string;
config?: MermaidConfig;
}
@@ -44,7 +44,7 @@ export function extractFrontMatter(text: string): FrontMatterResult {
// Only add properties that are explicitly supported, if they exist
if (parsed.displayMode) {
metadata.displayMode = parsed.displayMode.toString() as GanttDiagramConfig['displayMode'];
metadata.displayMode = parsed.displayMode.toString();
}
if (parsed.title) {
metadata.title = parsed.title.toString();

View File

@@ -6,7 +6,7 @@ export const loadRegisteredDiagrams = async () => {
log.debug(`Loading registered diagrams`);
// Load all lazy loaded diagrams in parallel
const results = await Promise.allSettled(
Object.entries(detectors).map(async ([key, { detector, loader, priority }]) => {
Object.entries(detectors).map(async ([key, { detector, loader }]) => {
if (loader) {
try {
getDiagram(key);
@@ -14,7 +14,7 @@ export const loadRegisteredDiagrams = async () => {
try {
// Register diagram if it is not already registered
const { diagram, id } = await loader();
registerDiagram(id, diagram, priority, detector);
registerDiagram(id, diagram, detector);
} catch (err) {
// Remove failed diagram from detectors
log.error(`Failed to load external diagram with key ${key}. Removing from detectors.`);

View File

@@ -76,23 +76,13 @@ export interface DiagramDefinition {
export interface DetectorRecord {
detector: DiagramDetector;
priority: number;
loader?: DiagramLoader;
}
/**
* External diagrams, which are not bundled with mermaid should expose the following to be registered using the `mermaid.registerExternalDiagrams` function.
*
* @param id - An ID for the given diagram. If two diagrams are registered with the same ID, the one with the higher priority will be used.
* @param detector - Function that returns `true` if a given mermaid text satisfies with this diagram definition.
* @param loader - Function that returns a promise of the diagram definition.
* @param priority - The priority of the diagram. Optional, defaults to 0.
*/
export interface ExternalDiagramDefinition {
id: string;
detector: DiagramDetector;
loader: DiagramLoader;
priority?: number;
}
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
@@ -115,7 +105,7 @@ export type DrawDefinition = (
export interface ParserDefinition {
parse: (text: string) => void;
parser?: { yy: DiagramDB };
parser: { yy: DiagramDB };
}
export type HTML = d3.Selection<HTMLIFrameElement, unknown, Element | null, unknown>;

View File

@@ -21,7 +21,6 @@ describe('diagram detection', () => {
addDetector(
'loki',
(str) => str.startsWith('loki'),
0,
() =>
Promise.resolve({
id: 'loki',
@@ -31,6 +30,9 @@ describe('diagram detection', () => {
parse: () => {
// no-op
},
parser: {
yy: {},
},
},
renderer: {
draw: () => {
@@ -46,37 +48,6 @@ describe('diagram detection', () => {
expect(diagram.type).toBe('loki');
});
test('should allow external diagrams to override internal ones with same ID', async () => {
addDetector(
'flowchart-elk',
(str) => str.startsWith('flowchart-elk'),
1,
() =>
Promise.resolve({
id: 'flowchart-elk',
diagram: {
db: {
getDiagramTitle: () => 'overridden',
},
parser: {
parse: () => {
// no-op
},
},
renderer: {
draw: () => {
// no-op
},
},
styles: {},
},
})
);
const diagram = (await getDiagramFromText('flowchart-elk TD; A-->B')) as Diagram;
expect(diagram).toBeInstanceOf(Diagram);
expect(diagram.db.getDiagramTitle?.()).toBe('overridden');
});
test('should throw the right error for incorrect diagram', async () => {
await expect(getDiagramFromText('graph TD; A-->')).rejects.toThrowErrorMatchingInlineSnapshot(`
"Parse error on line 2:
@@ -98,18 +69,4 @@ Expecting 'TXT', got 'NEWLINE'"
'"No diagram type detected matching given configuration for text: thor TD; A-->B"'
);
});
test('should consider entity codes when present in diagram defination', async () => {
const diagram = await getDiagramFromText(`sequenceDiagram
A->>B: I #9829; you!
B->>A: I #9829; you #infin; times more!`);
// @ts-ignore: we need to add types for sequenceDb which will be done in separate PR
const messages = diagram.db?.getMessages?.();
if (!messages) {
throw new Error('Messages not found!');
}
expect(messages[0].message).toBe('I fl°°9829¶ß you!');
expect(messages[1].message).toBe('I fl°°9829¶ß you fl°infin¶ß times more!');
});
});

View File

@@ -231,7 +231,7 @@ export const addRelations = function (relations: ClassRelation[], g: graphlib.Gr
//Set relationship style and line type
classes: 'relation',
pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid',
id: `id_${edge.id1}_${edge.id2}_${cnt}`,
id: 'id' + cnt,
// Set link type for rendering
arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal',
//Set edge extra labels

View File

@@ -681,82 +681,3 @@ describe('given text representing a method, ', function () {
});
});
});
describe('given text representing an attribute', () => {
describe('when the attribute has no modifiers', () => {
it('should parse the display text correctly', () => {
const str = 'name String';
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
expect(displayDetails.displayText).toBe('name String');
expect(displayDetails.cssStyle).toBe('');
});
});
describe('when the attribute has public "+" modifier', () => {
it('should parse the display text correctly', () => {
const str = '+name String';
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
expect(displayDetails.displayText).toBe('+name String');
expect(displayDetails.cssStyle).toBe('');
});
});
describe('when the attribute has protected "#" modifier', () => {
it('should parse the display text correctly', () => {
const str = '#name String';
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
expect(displayDetails.displayText).toBe('#name String');
expect(displayDetails.cssStyle).toBe('');
});
});
describe('when the attribute has private "-" modifier', () => {
it('should parse the display text correctly', () => {
const str = '-name String';
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
expect(displayDetails.displayText).toBe('-name String');
expect(displayDetails.cssStyle).toBe('');
});
});
describe('when the attribute has internal "~" modifier', () => {
it('should parse the display text correctly', () => {
const str = '~name String';
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
expect(displayDetails.displayText).toBe('~name String');
expect(displayDetails.cssStyle).toBe('');
});
});
describe('when the attribute has static "$" modifier', () => {
it('should parse the display text correctly and apply static css style', () => {
const str = 'name String$';
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
expect(displayDetails.displayText).toBe('name String');
expect(displayDetails.cssStyle).toBe(staticCssStyle);
});
});
describe('when the attribute has abstract "*" modifier', () => {
it('should parse the display text correctly and apply abstract css style', () => {
const str = 'name String*';
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
expect(displayDetails.displayText).toBe('name String');
expect(displayDetails.cssStyle).toBe(abstractCssStyle);
});
});
});

View File

@@ -106,7 +106,7 @@ export class ClassMember {
this.visibility = firstChar as Visibility;
}
if (lastChar.match(/[$*]/)) {
if (lastChar.match(/[*?]/)) {
potentialClassifier = lastChar;
}

View File

@@ -38,20 +38,6 @@ describe('when securityLevel is antiscript, all script must be removed', () => {
compareRemoveScript(`<img onerror="alert('hello');">`, `<img>`);
});
it('should detect unsecured target attribute, if value is _blank then generate a secured link', () => {
compareRemoveScript(
`<a href="https://mermaid.js.org/" target="_blank">note about mermaid</a>`,
`<a href="https://mermaid.js.org/" target="_blank" rel="noopener">note about mermaid</a>`
);
});
it('should detect unsecured target attribute from links', () => {
compareRemoveScript(
`<a href="https://mermaid.js.org/" target="_self">note about mermaid</a>`,
`<a href="https://mermaid.js.org/" target="_self">note about mermaid</a>`
);
});
it('should detect iframes', () => {
compareRemoveScript(
`<iframe src="http://abc.com/script1.js"></iframe>

View File

@@ -25,27 +25,7 @@ export const getRows = (s?: string): string[] => {
* @returns The safer text
*/
export const removeScript = (txt: string): string => {
const TEMPORARY_ATTRIBUTE = 'data-temp-href-target';
DOMPurify.addHook('beforeSanitizeAttributes', (node: Element) => {
if (node.tagName === 'A' && node.hasAttribute('target')) {
node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') || '');
}
});
const sanitizedText = DOMPurify.sanitize(txt);
DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {
if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) {
node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) || '');
node.removeAttribute(TEMPORARY_ATTRIBUTE);
if (node.getAttribute('target') === '_blank') {
node.setAttribute('rel', 'noopener');
}
}
});
return sanitizedText;
return DOMPurify.sanitize(txt);
};
const sanitizeMore = (text: string, config: MermaidConfig) => {

View File

@@ -1,15 +0,0 @@
import type { DiagramAST } from 'mermaid-parser';
import type { DiagramDB } from '../../diagram-api/types.js';
export function populateCommonDb(ast: DiagramAST, db: DiagramDB) {
if (ast.accDescr) {
db.setAccDescription?.(ast.accDescr);
}
if (ast.accTitle) {
db.setAccTitle?.(ast.accTitle);
}
if (ast.title) {
db.setDiagramTitle?.(ast.title);
}
}

View File

@@ -5,6 +5,7 @@ const diagram: DiagramDefinition = {
db: {},
renderer,
parser: {
parser: { yy: {} },
parse: (): void => {
return;
},

View File

@@ -201,13 +201,6 @@ export const updateLinkInterpolate = function (positions, interp) {
*/
export const updateLink = function (positions, style) {
positions.forEach(function (pos) {
if (pos >= edges.length) {
throw new Error(
`The index ${pos} for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and ${
edges.length - 1
}. (Help: Ensure that the index is within the range of existing edges.)`
);
}
if (pos === 'default') {
edges.defaultStyle = style;
} else {
@@ -432,7 +425,7 @@ const setupToolTips = function (element) {
tooltipElem
.text(el.attr('title'))
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
.style('top', window.scrollY + rect.bottom + 'px');
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
tooltipElem.html(tooltipElem.html().replace(/&lt;br\/&gt;/g, '<br/>'));
el.classed('hover', true);
})

View File

@@ -286,30 +286,6 @@ describe('[Style] when parsing', () => {
expect(edges[0].type).toBe('arrow_point');
});
it('should handle style definitions within number of edges', function () {
expect(() =>
flow.parser
.parse(
`graph TD
A-->B
linkStyle 1 stroke-width:1px;`
)
.toThrow(
'The index 1 for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and 0. (Help: Ensure that the index is within the range of existing edges.)'
)
);
});
it('should handle style definitions within number of edges', function () {
const res = flow.parser.parse(`graph TD
A-->B
linkStyle 0 stroke-width:1px;`);
const edges = flow.parser.yy.getEdges();
expect(edges[0].style[0]).toBe('stroke-width:1px');
});
it('should handle multi-numbered style definitions with more then 1 digit in a row', function () {
const res = flow.parser.parse(
'graph TD\n' +

View File

@@ -535,10 +535,6 @@ describe('[Text] when parsing', () => {
expect(vert['A'].text).toBe('this is an ellipse');
});
it('should not freeze when ellipse text has a `(`', function () {
expect(() => flow.parser.parse('graph\nX(- My Text (')).toThrowError();
});
it('should handle text in diamond vertices with space', function () {
const res = flow.parser.parse('graph TD;A(chimpansen hoppar)-->C;');

View File

@@ -134,7 +134,7 @@ that id.
<*>\s*\~\~[\~]+\s* return 'LINK';
<ellipseText>[-/\)][\)] { this.popState(); return '-)'; }
<ellipseText>[^\(\)\[\]\{\}]|-\!\)+ return "TEXT"
<ellipseText>[^\(\)\[\]\{\}]|-/!\)+ return "TEXT"
<*>"(-" { this.pushState("ellipseText"); return '(-'; }
<text>"])" { this.popState(); return 'STADIUMEND'; }

View File

@@ -1,9 +1,9 @@
const getStyles = (options) =>
`
.mermaid-main-font {
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: "trebuchet ms", verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
}
.exclude-range {
fill: ${options.excludeBkgColor};
}
@@ -45,7 +45,11 @@ const getStyles = (options) =>
.sectionTitle {
text-anchor: start;
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
// font-size: ${options.ganttFontSize};
// text-height: 14px;
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
}
@@ -55,11 +59,10 @@ const getStyles = (options) =>
stroke: ${options.gridColor};
opacity: 0.8;
shape-rendering: crispEdges;
}
.grid .tick text {
font-family: ${options.fontFamily};
fill: ${options.textColor};
text {
font-family: ${options.fontFamily};
fill: ${options.textColor};
}
}
.grid path {
@@ -86,27 +89,33 @@ const getStyles = (options) =>
.taskText {
text-anchor: middle;
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
}
// .taskText:not([font-size]) {
// font-size: ${options.ganttFontSize};
// }
.taskTextOutsideRight {
fill: ${options.taskTextDarkColor};
text-anchor: start;
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
// font-size: ${options.ganttFontSize};
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
}
.taskTextOutsideLeft {
fill: ${options.taskTextDarkColor};
text-anchor: end;
// font-size: ${options.ganttFontSize};
}
/* Special case clickable */
.task.clickable {
cursor: pointer;
}
.taskText.clickable {
cursor: pointer;
fill: ${options.taskTextClickableColor} !important;
@@ -125,7 +134,6 @@ const getStyles = (options) =>
font-weight: bold;
}
/* Specific task settings for the sections*/
.taskText0,
@@ -247,8 +255,9 @@ const getStyles = (options) =>
.titleText {
text-anchor: middle;
font-size: 18px;
fill: ${options.titleColor || options.textColor};
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
fill: ${options.textColor} ;
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
}
`;

View File

@@ -1,31 +1,24 @@
import { parser } from './infoParser.js';
// @ts-ignore - jison doesn't export types
import { parser } from './parser/info.jison';
import { db } from './infoDb.js';
describe('info diagram', () => {
beforeEach(() => {
parser.yy = db;
parser.yy.clear();
});
describe('info', () => {
it('should handle an info definition', () => {
const str = `info`;
expect(() => {
parser.parse(str);
}).not.toThrow();
parser.parse(str);
expect(db.getInfo()).toBeFalsy();
});
it('should handle an info definition with showInfo', () => {
const str = `info showInfo`;
expect(() => {
parser.parse(str);
}).not.toThrow();
});
parser.parse(str);
it('should throw because of unsupported info grammar', () => {
const str = `info unsupported`;
expect(() => {
parser.parse(str);
}).toThrow('Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.');
});
it('should throw because of unsupported info grammar', () => {
const str = `info unsupported`;
expect(() => {
parser.parse(str);
}).toThrow('Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.');
expect(db.getInfo()).toBeTruthy();
});
});

View File

@@ -1,10 +1,23 @@
import type { InfoFields, InfoDB } from './infoTypes.js';
import { version } from '../../../package.json';
export const DEFAULT_INFO_DB: InfoFields = { version } as const;
export const DEFAULT_INFO_DB: InfoFields = {
info: false,
} as const;
export const getVersion = (): string => DEFAULT_INFO_DB.version;
let info: boolean = DEFAULT_INFO_DB.info;
export const setInfo = (toggle: boolean): void => {
info = toggle;
};
export const getInfo = (): boolean => info;
const clear = (): void => {
info = DEFAULT_INFO_DB.info;
};
export const db: InfoDB = {
getVersion,
clear,
setInfo,
getInfo,
};

View File

@@ -1,5 +1,6 @@
import type { DiagramDefinition } from '../../diagram-api/types.js';
import { parser } from './infoParser.js';
// @ts-ignore - jison doesn't export types
import parser from './parser/info.jison';
import { db } from './infoDb.js';
import { renderer } from './infoRenderer.js';

Some files were not shown because too many files have changed in this diff Show More