Merge branch 'develop' into feature/6314_state-click

This commit is contained in:
BambioGaming
2025-05-09 13:51:51 +01:00
committed by GitHub
24 changed files with 676 additions and 326 deletions

View File

@@ -0,0 +1,6 @@
---
'mermaid': minor
'@mermaid-js/parser': minor
---
feat: Add shorter `+<count>: Label` syntax in packet diagram

View File

@@ -1,5 +1,5 @@
import { build } from 'esbuild'; import { build } from 'esbuild';
import { mkdir, writeFile } from 'node:fs/promises'; import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
import { packageOptions } from '../.build/common.js'; import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js'; import { generateLangium } from '../.build/generateLangium.js';
import type { MermaidBuildOptions } from './util.js'; import type { MermaidBuildOptions } from './util.js';
@@ -31,7 +31,15 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
// mermaid.js // mermaid.js
{ ...iifeOptions }, { ...iifeOptions },
// mermaid.min.js // mermaid.min.js
{ ...iifeOptions, minify: true, metafile: shouldVisualize } { ...iifeOptions, minify: true, metafile: shouldVisualize },
// mermaid.tiny.min.js
{
...iifeOptions,
minify: true,
includeLargeFeatures: false,
metafile: shouldVisualize,
sourcemap: false,
}
); );
} }
if (entryName === 'mermaid-zenuml') { if (entryName === 'mermaid-zenuml') {
@@ -70,6 +78,20 @@ const handler = (e) => {
process.exit(1); process.exit(1);
}; };
const buildTinyMermaid = async () => {
await mkdir('./packages/tiny/dist', { recursive: true });
await rename(
'./packages/mermaid/dist/mermaid.tiny.min.js',
'./packages/tiny/dist/mermaid.tiny.js'
);
// Copy version from mermaid's package.json to tiny's package.json
const mermaidPkg = JSON.parse(await readFile('./packages/mermaid/package.json', 'utf8'));
const tinyPkg = JSON.parse(await readFile('./packages/tiny/package.json', 'utf8'));
tinyPkg.version = mermaidPkg.version;
await writeFile('./packages/tiny/package.json', JSON.stringify(tinyPkg, null, 2) + '\n');
};
const main = async () => { const main = async () => {
await generateLangium(); await generateLangium();
await mkdir('stats', { recursive: true }); await mkdir('stats', { recursive: true });
@@ -78,6 +100,7 @@ const main = async () => {
for (const pkg of packageNames) { for (const pkg of packageNames) {
await buildPackage(pkg).catch(handler); await buildPackage(pkg).catch(handler);
} }
await buildTinyMermaid();
}; };
void main(); void main();

View File

@@ -14,6 +14,7 @@ export interface MermaidBuildOptions extends BuildOptions {
metafile: boolean; metafile: boolean;
format: 'esm' | 'iife'; format: 'esm' | 'iife';
options: PackageOptions; options: PackageOptions;
includeLargeFeatures: boolean;
} }
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = { export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = {
@@ -21,6 +22,7 @@ export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'>
metafile: false, metafile: false,
core: false, core: false,
format: 'esm', format: 'esm',
includeLargeFeatures: true,
} as const; } as const;
const buildOptions = (override: BuildOptions): BuildOptions => { const buildOptions = (override: BuildOptions): BuildOptions => {
@@ -39,12 +41,18 @@ const buildOptions = (override: BuildOptions): BuildOptions => {
}; };
}; };
const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOptions) => { const getFileName = (
fileName: string,
{ core, format, minify, includeLargeFeatures }: MermaidBuildOptions
) => {
if (core) { if (core) {
fileName += '.core'; fileName += '.core';
} else if (format === 'esm') { } else if (format === 'esm') {
fileName += '.esm'; fileName += '.esm';
} }
if (!includeLargeFeatures) {
fileName += '.tiny';
}
if (minify) { if (minify) {
fileName += '.min'; fileName += '.min';
} }
@@ -54,25 +62,27 @@ const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOpt
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const { const {
core, core,
metafile,
format, format,
minify,
options: { name, file, packageName }, options: { name, file, packageName },
globalName = 'mermaid', globalName = 'mermaid',
includeLargeFeatures,
...rest
} = options; } = options;
const external: string[] = ['require', 'fs', 'path']; const external: string[] = ['require', 'fs', 'path'];
const outFileName = getFileName(name, options); const outFileName = getFileName(name, options);
const output: BuildOptions = buildOptions({ const output: BuildOptions = buildOptions({
...rest,
absWorkingDir: resolve(__dirname, `../packages/${packageName}`), absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
entryPoints: { entryPoints: {
[outFileName]: `src/${file}`, [outFileName]: `src/${file}`,
}, },
metafile,
minify,
globalName, globalName,
logLevel: 'info', logLevel: 'info',
chunkNames: `chunks/${outFileName}/[name]-[hash]`, chunkNames: `chunks/${outFileName}/[name]-[hash]`,
define: { define: {
// This needs to be stringified for esbuild
includeLargeFeatures: `${includeLargeFeatures}`,
'import.meta.vitest': 'undefined', 'import.meta.vitest': 'undefined',
}, },
}); });

View File

@@ -58,7 +58,7 @@ jobs:
echo "EOF" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT
- name: Commit and create pull request - name: Commit and create pull request
uses: peter-evans/create-pull-request@3b1f4bffdc97d7b055dd96732d7348e585ad2c4e uses: peter-evans/create-pull-request@889dce9eaba7900ce30494f5e1ac7220b27e5c81
with: with:
add-paths: | add-paths: |
cypress/timings.json cypress/timings.json

View File

@@ -94,6 +94,10 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
}), }),
...visualizerOptions(packageName, core), ...visualizerOptions(packageName, core),
], ],
define: {
// Needs to be string
includeLargeFeatures: 'true',
},
}; };
if (watch && config.build) { if (watch && config.build) {

View File

@@ -98,6 +98,12 @@ Mermaid can load multiple diagrams, in the same page.
> Try it out, save this code as HTML and load it using any browser. > Try it out, save this code as HTML and load it using any browser.
> (Except Internet Explorer, please don't use Internet Explorer.) > (Except Internet Explorer, please don't use Internet Explorer.)
## Tiny Mermaid
We offer a smaller version of Mermaid that's approximately half the size of the full library. This tiny version doesn't support Mindmap Diagrams, Architecture Diagrams, KaTeX rendering, or lazy loading.
If you need a more lightweight version without these features, you can use [Mermaid Tiny](https://github.com/mermaid-js/mermaid/tree/develop/packages/tiny).
## Enabling Click Event and Tags in Nodes ## Enabling Click Event and Tags in Nodes
A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use. A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use.

View File

@@ -354,6 +354,7 @@ To Deploy Mermaid:
- [Mermaid Live Editor](https://github.com/mermaid-js/mermaid-live-editor) - [Mermaid Live Editor](https://github.com/mermaid-js/mermaid-live-editor)
- [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli) - [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli)
- [Mermaid Tiny](https://github.com/mermaid-js/mermaid/tree/develop/packages/tiny)
- [Mermaid Webpack Demo](https://github.com/mermaidjs/mermaid-webpack-demo) - [Mermaid Webpack Demo](https://github.com/mermaidjs/mermaid-webpack-demo)
- [Mermaid Parcel Demo](https://github.com/mermaidjs/mermaid-parcel-demo) - [Mermaid Parcel Demo](https://github.com/mermaidjs/mermaid-parcel-demo)

View File

@@ -16,13 +16,25 @@ This diagram type is particularly useful for developers, network engineers, educ
## Syntax ## Syntax
```md ```
packet-beta packet-beta
start: "Block name" %% Single-bit block start: "Block name" %% Single-bit block
start-end: "Block name" %% Multi-bit blocks start-end: "Block name" %% Multi-bit blocks
... More Fields ... ... More Fields ...
``` ```
### Bits Syntax (v\<MERMAID_RELEASE_VERSION>+)
Using start and end bit counts can be difficult, especially when modifying a design. For this we add a bit count field, which starts from the end of the previous field automagically. Use `+<count>` to set the number of bits, thus:
```
packet-beta
+1: "Block name" %% Single-bit block
+8: "Block name" %% 8-bit block
9-15: "Manually set start and end, it's fine to mix and match"
... More Fields ...
```
## Examples ## Examples
```mermaid-example ```mermaid-example
@@ -76,8 +88,8 @@ packet-beta
```mermaid-example ```mermaid-example
packet-beta packet-beta
title UDP Packet title UDP Packet
0-15: "Source Port" +16: "Source Port"
16-31: "Destination Port" +16: "Destination Port"
32-47: "Length" 32-47: "Length"
48-63: "Checksum" 48-63: "Checksum"
64-95: "Data (variable length)" 64-95: "Data (variable length)"
@@ -86,8 +98,8 @@ title UDP Packet
```mermaid ```mermaid
packet-beta packet-beta
title UDP Packet title UDP Packet
0-15: "Source Port" +16: "Source Port"
16-31: "Destination Port" +16: "Destination Port"
32-47: "Length" 32-47: "Length"
48-63: "Checksum" 48-63: "Checksum"
64-95: "Data (variable length)" 64-95: "Data (variable length)"

View File

@@ -69,7 +69,7 @@
"@changesets/cli": "^2.27.12", "@changesets/cli": "^2.27.12",
"@cspell/eslint-plugin": "^8.19.3", "@cspell/eslint-plugin": "^8.19.3",
"@cypress/code-coverage": "^3.12.49", "@cypress/code-coverage": "^3.12.49",
"@eslint/js": "^9.25.1", "@eslint/js": "^9.26.0",
"@rollup/plugin-typescript": "^12.1.2", "@rollup/plugin-typescript": "^12.1.2",
"@types/cors": "^2.8.17", "@types/cors": "^2.8.17",
"@types/express": "^5.0.0", "@types/express": "^5.0.0",
@@ -93,7 +93,7 @@
"cypress-image-snapshot": "^4.0.1", "cypress-image-snapshot": "^4.0.1",
"cypress-split": "^1.24.14", "cypress-split": "^1.24.14",
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"eslint": "^9.25.1", "eslint": "^9.26.0",
"eslint-config-prettier": "^10.1.1", "eslint-config-prettier": "^10.1.1",
"eslint-plugin-cypress": "^4.3.0", "eslint-plugin-cypress": "^4.3.0",
"eslint-plugin-html": "^8.1.2", "eslint-plugin-html": "^8.1.2",
@@ -126,7 +126,7 @@
"tslib": "^2.8.1", "tslib": "^2.8.1",
"tsx": "^4.7.3", "tsx": "^4.7.3",
"typescript": "~5.7.3", "typescript": "~5.7.3",
"typescript-eslint": "^8.31.1", "typescript-eslint": "^8.32.0",
"vite": "^6.1.1", "vite": "^6.1.1",
"vite-plugin-istanbul": "^7.0.0", "vite-plugin-istanbul": "^7.0.0",
"vitest": "^3.0.6" "vitest": "^3.0.6"

View File

@@ -27,6 +27,7 @@ import block from '../diagrams/block/blockDetector.js';
import architecture from '../diagrams/architecture/architectureDetector.js'; import architecture from '../diagrams/architecture/architectureDetector.js';
import { registerLazyLoadedDiagrams } from './detectType.js'; import { registerLazyLoadedDiagrams } from './detectType.js';
import { registerDiagram } from './diagramAPI.js'; import { registerDiagram } from './diagramAPI.js';
import '../type.d.ts';
let hasLoadedDiagrams = false; let hasLoadedDiagrams = false;
export const addDiagrams = () => { export const addDiagrams = () => {
@@ -69,6 +70,11 @@ export const addDiagrams = () => {
return text.toLowerCase().trimStart().startsWith('---'); return text.toLowerCase().trimStart().startsWith('---');
} }
); );
if (includeLargeFeatures) {
registerLazyLoadedDiagrams(flowchartElk, mindmap, architecture);
}
// Ordering of detectors is important. The first one to return true will be used. // Ordering of detectors is important. The first one to return true will be used.
registerLazyLoadedDiagrams( registerLazyLoadedDiagrams(
c4, c4,
@@ -81,10 +87,8 @@ export const addDiagrams = () => {
pie, pie,
requirement, requirement,
sequence, sequence,
flowchartElk,
flowchartV2, flowchartV2,
flowchart, flowchart,
mindmap,
timeline, timeline,
git, git,
stateV2, stateV2,
@@ -95,7 +99,6 @@ export const addDiagrams = () => {
packet, packet,
xychart, xychart,
block, block,
architecture,
radar radar
); );
}; };

View File

@@ -341,29 +341,36 @@ export const renderKatex = async (text: string, config: MermaidConfig): Promise<
return text.replace(katexRegex, 'MathML is unsupported in this environment.'); return text.replace(katexRegex, 'MathML is unsupported in this environment.');
} }
const { default: katex } = await import('katex'); if (includeLargeFeatures) {
const outputMode = const { default: katex } = await import('katex');
config.forceLegacyMathML || (!isMathMLSupported() && config.legacyMathML) const outputMode =
? 'htmlAndMathml' config.forceLegacyMathML || (!isMathMLSupported() && config.legacyMathML)
: 'mathml'; ? 'htmlAndMathml'
return text : 'mathml';
.split(lineBreakRegex) return text
.map((line) => .split(lineBreakRegex)
hasKatex(line) .map((line) =>
? `<div style="display: flex; align-items: center; justify-content: center; white-space: nowrap;">${line}</div>` hasKatex(line)
: `<div>${line}</div>` ? `<div style="display: flex; align-items: center; justify-content: center; white-space: nowrap;">${line}</div>`
) : `<div>${line}</div>`
.join('') )
.replace(katexRegex, (_, c) => .join('')
katex .replace(katexRegex, (_, c) =>
.renderToString(c, { katex
throwOnError: true, .renderToString(c, {
displayMode: true, throwOnError: true,
output: outputMode, displayMode: true,
}) output: outputMode,
.replace(/\n/g, ' ') })
.replace(/<annotation.*<\/annotation>/g, '') .replace(/\n/g, ' ')
); .replace(/<annotation.*<\/annotation>/g, '')
);
}
return text.replace(
katexRegex,
'Katex is not supported in @mermaid-js/tiny. Please use the full mermaid library.'
);
}; };
export default { export default {

View File

@@ -1,7 +1,9 @@
import type { InfoFields, InfoDB } from './infoTypes.js'; import type { InfoFields, InfoDB } from './infoTypes.js';
import packageJson from '../../../package.json' assert { type: 'json' }; import packageJson from '../../../package.json' assert { type: 'json' };
export const DEFAULT_INFO_DB: InfoFields = { version: packageJson.version } as const; export const DEFAULT_INFO_DB: InfoFields = {
version: packageJson.version + (includeLargeFeatures ? '' : '-tiny'),
} as const;
export const getVersion = (): string => DEFAULT_INFO_DB.version; export const getVersion = (): string => DEFAULT_INFO_DB.version;

View File

@@ -30,6 +30,7 @@ describe('packet diagrams', () => {
[ [
[ [
{ {
"bits": 11,
"end": 10, "end": 10,
"label": "test", "label": "test",
"start": 0, "start": 0,
@@ -49,11 +50,13 @@ describe('packet diagrams', () => {
[ [
[ [
{ {
"bits": 11,
"end": 10, "end": 10,
"label": "test", "label": "test",
"start": 0, "start": 0,
}, },
{ {
"bits": 1,
"end": 11, "end": 11,
"label": "single", "label": "single",
"start": 11, "start": 11,
@@ -63,6 +66,58 @@ describe('packet diagrams', () => {
`); `);
}); });
it('should handle bit counts', async () => {
const str = `packet-beta
+8: "byte"
+16: "word"
`;
await expect(parser.parse(str)).resolves.not.toThrow();
expect(getPacket()).toMatchInlineSnapshot(`
[
[
{
"bits": 8,
"end": 7,
"label": "byte",
"start": 0,
},
{
"bits": 16,
"end": 23,
"label": "word",
"start": 8,
},
],
]
`);
});
it('should handle bit counts with bit or bits', async () => {
const str = `packet-beta
+8: "byte"
+16: "word"
`;
await expect(parser.parse(str)).resolves.not.toThrow();
expect(getPacket()).toMatchInlineSnapshot(`
[
[
{
"bits": 8,
"end": 7,
"label": "byte",
"start": 0,
},
{
"bits": 16,
"end": 23,
"label": "word",
"start": 8,
},
],
]
`);
});
it('should split into multiple rows', async () => { it('should split into multiple rows', async () => {
const str = `packet-beta const str = `packet-beta
0-10: "test" 0-10: "test"
@@ -73,11 +128,13 @@ describe('packet diagrams', () => {
[ [
[ [
{ {
"bits": 11,
"end": 10, "end": 10,
"label": "test", "label": "test",
"start": 0, "start": 0,
}, },
{ {
"bits": 20,
"end": 31, "end": 31,
"label": "multiple", "label": "multiple",
"start": 11, "start": 11,
@@ -85,6 +142,7 @@ describe('packet diagrams', () => {
], ],
[ [
{ {
"bits": 31,
"end": 63, "end": 63,
"label": "multiple", "label": "multiple",
"start": 32, "start": 32,
@@ -92,6 +150,7 @@ describe('packet diagrams', () => {
], ],
[ [
{ {
"bits": 26,
"end": 90, "end": 90,
"label": "multiple", "label": "multiple",
"start": 64, "start": 64,
@@ -111,11 +170,13 @@ describe('packet diagrams', () => {
[ [
[ [
{ {
"bits": 17,
"end": 16, "end": 16,
"label": "test", "label": "test",
"start": 0, "start": 0,
}, },
{ {
"bits": 14,
"end": 31, "end": 31,
"label": "multiple", "label": "multiple",
"start": 17, "start": 17,
@@ -123,6 +184,7 @@ describe('packet diagrams', () => {
], ],
[ [
{ {
"bits": 31,
"end": 63, "end": 63,
"label": "multiple", "label": "multiple",
"start": 32, "start": 32,
@@ -142,6 +204,16 @@ describe('packet diagrams', () => {
); );
}); });
it('should throw error if numbers are not continuous with bit counts', async () => {
const str = `packet-beta
+16: "test"
18-20: "error"
`;
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Packet block 18 - 20 is not contiguous. It should start from 16.]`
);
});
it('should throw error if numbers are not continuous for single packets', async () => { it('should throw error if numbers are not continuous for single packets', async () => {
const str = `packet-beta const str = `packet-beta
0-16: "test" 0-16: "test"
@@ -152,6 +224,16 @@ describe('packet diagrams', () => {
); );
}); });
it('should throw error if numbers are not continuous for single packets with bit counts', async () => {
const str = `packet-beta
+16: "test"
18: "error"
`;
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Packet block 18 - 18 is not contiguous. It should start from 16.]`
);
});
it('should throw error if numbers are not continuous for single packets - 2', async () => { it('should throw error if numbers are not continuous for single packets - 2', async () => {
const str = `packet-beta const str = `packet-beta
0-16: "test" 0-16: "test"
@@ -172,4 +254,13 @@ describe('packet diagrams', () => {
`[Error: Packet block 25 - 20 is invalid. End must be greater than start.]` `[Error: Packet block 25 - 20 is invalid. End must be greater than start.]`
); );
}); });
it('should throw error if bit count is 0', async () => {
const str = `packet-beta
+0: "test"
`;
await expect(parser.parse(str)).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Packet block 0 is invalid. Cannot have a zero bit field.]`
);
});
}); });

View File

@@ -10,26 +10,33 @@ const maxPacketSize = 10_000;
const populate = (ast: Packet) => { const populate = (ast: Packet) => {
populateCommonDb(ast, db); populateCommonDb(ast, db);
let lastByte = -1; let lastBit = -1;
let word: PacketWord = []; let word: PacketWord = [];
let row = 1; let row = 1;
const { bitsPerRow } = db.getConfig(); const { bitsPerRow } = db.getConfig();
for (let { start, end, label } of ast.blocks) {
if (end && end < start) { for (let { start, end, bits, label } of ast.blocks) {
if (start !== undefined && end !== undefined && end < start) {
throw new Error(`Packet block ${start} - ${end} is invalid. End must be greater than start.`); throw new Error(`Packet block ${start} - ${end} is invalid. End must be greater than start.`);
} }
if (start !== lastByte + 1) { start ??= lastBit + 1;
if (start !== lastBit + 1) {
throw new Error( throw new Error(
`Packet block ${start} - ${end ?? start} is not contiguous. It should start from ${ `Packet block ${start} - ${end ?? start} is not contiguous. It should start from ${
lastByte + 1 lastBit + 1
}.` }.`
); );
} }
lastByte = end ?? start; if (bits === 0) {
log.debug(`Packet block ${start} - ${lastByte} with label ${label}`); throw new Error(`Packet block ${start} is invalid. Cannot have a zero bit field.`);
}
end ??= start + (bits ?? 1) - 1;
bits ??= end - start + 1;
lastBit = end;
log.debug(`Packet block ${start} - ${lastBit} with label ${label}`);
while (word.length <= bitsPerRow + 1 && db.getPacket().length < maxPacketSize) { while (word.length <= bitsPerRow + 1 && db.getPacket().length < maxPacketSize) {
const [block, nextBlock] = getNextFittingBlock({ start, end, label }, row, bitsPerRow); const [block, nextBlock] = getNextFittingBlock({ start, end, bits, label }, row, bitsPerRow);
word.push(block); word.push(block);
if (block.end + 1 === row * bitsPerRow) { if (block.end + 1 === row * bitsPerRow) {
db.pushWord(word); db.pushWord(word);
@@ -39,7 +46,7 @@ const populate = (ast: Packet) => {
if (!nextBlock) { if (!nextBlock) {
break; break;
} }
({ start, end, label } = nextBlock); ({ start, end, bits, label } = nextBlock);
} }
} }
db.pushWord(word); db.pushWord(word);
@@ -50,8 +57,11 @@ const getNextFittingBlock = (
row: number, row: number,
bitsPerRow: number bitsPerRow: number
): [Required<PacketBlock>, PacketBlock | undefined] => { ): [Required<PacketBlock>, PacketBlock | undefined] => {
if (block.start === undefined) {
throw new Error('start should have been set during first phase');
}
if (block.end === undefined) { if (block.end === undefined) {
block.end = block.start; throw new Error('end should have been set during first phase');
} }
if (block.start > block.end) { if (block.start > block.end) {
@@ -62,16 +72,20 @@ const getNextFittingBlock = (
return [block as Required<PacketBlock>, undefined]; return [block as Required<PacketBlock>, undefined];
} }
const rowEnd = row * bitsPerRow - 1;
const rowStart = row * bitsPerRow;
return [ return [
{ {
start: block.start, start: block.start,
end: row * bitsPerRow - 1, end: rowEnd,
label: block.label, label: block.label,
bits: rowEnd - block.start,
}, },
{ {
start: row * bitsPerRow, start: rowStart,
end: block.end, end: block.end,
label: block.label, label: block.label,
bits: block.end - rowStart,
}, },
]; ];
}; };

View File

@@ -92,6 +92,12 @@ Mermaid can load multiple diagrams, in the same page.
> Try it out, save this code as HTML and load it using any browser. > Try it out, save this code as HTML and load it using any browser.
> (Except Internet Explorer, please don't use Internet Explorer.) > (Except Internet Explorer, please don't use Internet Explorer.)
## Tiny Mermaid
We offer a smaller version of Mermaid that's approximately half the size of the full library. This tiny version doesn't support Mindmap Diagrams, Architecture Diagrams, KaTeX rendering, or lazy loading.
If you need a more lightweight version without these features, you can use [Mermaid Tiny](https://github.com/mermaid-js/mermaid/tree/develop/packages/tiny).
## Enabling Click Event and Tags in Nodes ## Enabling Click Event and Tags in Nodes
A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use. A `securityLevel` configuration has to first be cleared. `securityLevel` sets the level of trust for the parsed diagrams and limits click functionality. This was introduced in version 8.2 as a security improvement, aimed at preventing malicious use.

View File

@@ -109,6 +109,7 @@ To Deploy Mermaid:
- [Mermaid Live Editor](https://github.com/mermaid-js/mermaid-live-editor) - [Mermaid Live Editor](https://github.com/mermaid-js/mermaid-live-editor)
- [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli) - [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli)
- [Mermaid Tiny](https://github.com/mermaid-js/mermaid/tree/develop/packages/tiny)
- [Mermaid Webpack Demo](https://github.com/mermaidjs/mermaid-webpack-demo) - [Mermaid Webpack Demo](https://github.com/mermaidjs/mermaid-webpack-demo)
- [Mermaid Parcel Demo](https://github.com/mermaidjs/mermaid-parcel-demo) - [Mermaid Parcel Demo](https://github.com/mermaidjs/mermaid-parcel-demo)

View File

@@ -10,13 +10,25 @@ This diagram type is particularly useful for developers, network engineers, educ
## Syntax ## Syntax
```md ```
packet-beta packet-beta
start: "Block name" %% Single-bit block start: "Block name" %% Single-bit block
start-end: "Block name" %% Multi-bit blocks start-end: "Block name" %% Multi-bit blocks
... More Fields ... ... More Fields ...
``` ```
### Bits Syntax (v<MERMAID_RELEASE_VERSION>+)
Using start and end bit counts can be difficult, especially when modifying a design. For this we add a bit count field, which starts from the end of the previous field automagically. Use `+<count>` to set the number of bits, thus:
```
packet-beta
+1: "Block name" %% Single-bit block
+8: "Block name" %% 8-bit block
9-15: "Manually set start and end, it's fine to mix and match"
... More Fields ...
```
## Examples ## Examples
```mermaid-example ```mermaid-example
@@ -46,8 +58,8 @@ packet-beta
```mermaid-example ```mermaid-example
packet-beta packet-beta
title UDP Packet title UDP Packet
0-15: "Source Port" +16: "Source Port"
16-31: "Destination Port" +16: "Destination Port"
32-47: "Length" 32-47: "Length"
48-63: "Checksum" 48-63: "Checksum"
64-95: "Data (variable length)" 64-95: "Data (variable length)"

View File

@@ -5,7 +5,6 @@
// @ts-ignore TODO: Investigate D3 issue // @ts-ignore TODO: Investigate D3 issue
import { select } from 'd3'; import { select } from 'd3';
import { compile, serialize, stringify } from 'stylis'; import { compile, serialize, stringify } from 'stylis';
// @ts-ignore: TODO Fix ts errors
import DOMPurify from 'dompurify'; import DOMPurify from 'dompurify';
import isEmpty from 'lodash-es/isEmpty.js'; import isEmpty from 'lodash-es/isEmpty.js';
import packageJson from '../package.json' assert { type: 'json' }; import packageJson from '../package.json' assert { type: 'json' };

2
packages/mermaid/src/type.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
// eslint-disable-next-line no-var
declare var includeLargeFeatures: boolean;

View File

@@ -12,5 +12,10 @@ entry Packet:
; ;
PacketBlock: PacketBlock:
start=INT('-' end=INT)? ':' label=STRING EOL (
; start=INT('-' end=INT)?
| '+' bits=INT
)
':' label=STRING
EOL
;

35
packages/tiny/README.md Normal file
View File

@@ -0,0 +1,35 @@
# Tiny Mermaid
This is a tiny version of mermaid that is optimized for the web. It is a subset of the mermaid library and is designed to be used in the browser via CDN.
## Lazy loading
The original mermaid library supports lazy loading, so it will be faster on the initial load, and only load the required diagrams.
This is not supported in the tiny mermaid library. So it's always recommended to use the full mermaid library unless you have a very specific reason to reduce the bundle size.
## Removals from mermaid
This does not support
- Mindmap Diagram
- Architecture Diagram
- Katex rendering
- Lazy loading
## Usage via NPM
This package is not meant to be installed directly from npm. It is designed to be used via CDN.
If you need to use mermaid in your project, please install the full [`mermaid` package](https://www.npmjs.com/package/mermaid) instead.
## Usage via CDN
```html
<!-- Format -->
<script src="https://cdn.jsdelivr.net/npm/@mermaid-js/tiny@<MERMAID_MAJOR_VERSION>/dist/mermaid.tiny.js"></script>
<!-- Pinning major version -->
<script src="https://cdn.jsdelivr.net/npm/@mermaid-js/tiny@11/dist/mermaid.tiny.js"></script>
<!-- Pinning specific version -->
<script src="https://cdn.jsdelivr.net/npm/@mermaid-js/tiny@11.6.0/dist/mermaid.tiny.js"></script>
```

View File

@@ -0,0 +1,25 @@
{
"name": "@mermaid-js/tiny",
"version": "11.6.0",
"description": "Tiny version of mermaid",
"type": "commonjs",
"main": "./dist/mermaid.tiny.js",
"scripts": {
"clean": "rimraf dist"
},
"repository": {
"type": "git",
"url": "https://github.com/mermaid-js/mermaid"
},
"author": "Sidharth Vinod",
"license": "MIT",
"dependencies": {},
"devDependencies": {},
"files": [
"dist/",
"README.md"
],
"publishConfig": {
"access": "public"
}
}

614
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,8 @@ export default defineConfig({
}, },
}, },
define: { define: {
// Needs to be string
includeLargeFeatures: 'true',
'import.meta.vitest': 'undefined', 'import.meta.vitest': 'undefined',
}, },
}); });