mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-31 02:44:17 +01:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			aggregatio
			...
			update-bro
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | e2df3525de | ||
|   | 035954c9ed | 
| @@ -1,9 +1,3 @@ | |||||||
| export interface PackageOptions { |  | ||||||
|   name: string; |  | ||||||
|   packageName: string; |  | ||||||
|   file: string; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Shared common options for both ESBuild and Vite |  * Shared common options for both ESBuild and Vite | ||||||
|  */ |  */ | ||||||
| @@ -33,9 +27,4 @@ export const packageOptions = { | |||||||
|     packageName: 'mermaid-layout-elk', |     packageName: 'mermaid-layout-elk', | ||||||
|     file: 'layouts.ts', |     file: 'layouts.ts', | ||||||
|   }, |   }, | ||||||
|   examples: { | } as const; | ||||||
|     name: 'mermaid-examples', |  | ||||||
|     packageName: 'examples', |  | ||||||
|     file: 'index.ts', |  | ||||||
|   }, |  | ||||||
| } as const satisfies Record<string, PackageOptions>; |  | ||||||
|   | |||||||
| @@ -19,15 +19,12 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [ | |||||||
|   'xyChart', |   'xyChart', | ||||||
|   'requirement', |   'requirement', | ||||||
|   'mindmap', |   'mindmap', | ||||||
|   'kanban', |  | ||||||
|   'timeline', |   'timeline', | ||||||
|   'gitGraph', |   'gitGraph', | ||||||
|   'c4', |   'c4', | ||||||
|   'sankey', |   'sankey', | ||||||
|   'block', |   'block', | ||||||
|   'packet', |   'packet', | ||||||
|   'architecture', |  | ||||||
|   'radar', |  | ||||||
| ] as const; | ] as const; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|   | |||||||
| @@ -10,16 +10,13 @@ const buildType = (packageName: string) => { | |||||||
|       console.log(out.toString()); |       console.log(out.toString()); | ||||||
|     } |     } | ||||||
|   } catch (e) { |   } catch (e) { | ||||||
|  |     console.error(e); | ||||||
|     if (e.stdout.length > 0) { |     if (e.stdout.length > 0) { | ||||||
|       console.error(e.stdout.toString()); |       console.error(e.stdout.toString()); | ||||||
|     } |     } | ||||||
|     if (e.stderr.length > 0) { |     if (e.stderr.length > 0) { | ||||||
|       console.error(e.stderr.toString()); |       console.error(e.stderr.toString()); | ||||||
|     } |     } | ||||||
|     // Exit the build process if we are in CI |  | ||||||
|     if (process.env.CI) { |  | ||||||
|       throw new Error(`Failed to build types for ${packageName}`); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +0,0 @@ | |||||||
| --- |  | ||||||
| 'mermaid': patch |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| fix: Handle arrows correctly when auto number is enabled |  | ||||||
| @@ -1,5 +0,0 @@ | |||||||
| --- |  | ||||||
| 'mermaid': minor |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`. |  | ||||||
| @@ -1,5 +0,0 @@ | |||||||
| --- |  | ||||||
| 'mermaid': minor |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| feat: Add support for aggregation relationships in ER diagram |  | ||||||
| @@ -26,7 +26,6 @@ concat | |||||||
| controlx | controlx | ||||||
| controly | controly | ||||||
| CSSCLASS | CSSCLASS | ||||||
| curv |  | ||||||
| CYLINDEREND | CYLINDEREND | ||||||
| CYLINDERSTART | CYLINDERSTART | ||||||
| DAGA | DAGA | ||||||
| @@ -47,16 +46,15 @@ edgesep | |||||||
| EMPTYSTR | EMPTYSTR | ||||||
| enddate | enddate | ||||||
| ERDIAGRAM | ERDIAGRAM | ||||||
| eslint |  | ||||||
| flatmap | flatmap | ||||||
| forwardable | forwardable | ||||||
| frontmatter | frontmatter | ||||||
| funs | funs | ||||||
| gantt | gantt | ||||||
| GENERICTYPE | GENERICTYPE | ||||||
|  | getBoundarys | ||||||
| grammr | grammr | ||||||
| graphtype | graphtype | ||||||
| halign |  | ||||||
| iife | iife | ||||||
| interp | interp | ||||||
| introdcued | introdcued | ||||||
| @@ -68,7 +66,6 @@ Kaufmann | |||||||
| keyify | keyify | ||||||
| LABELPOS | LABELPOS | ||||||
| LABELTYPE | LABELTYPE | ||||||
| layoutstop |  | ||||||
| lcov | lcov | ||||||
| LEFTOF | LEFTOF | ||||||
| Lexa | Lexa | ||||||
| @@ -88,7 +85,6 @@ NODIR | |||||||
| NSTR | NSTR | ||||||
| outdir | outdir | ||||||
| Qcontrolx | Qcontrolx | ||||||
| QSTR |  | ||||||
| reinit | reinit | ||||||
| rels | rels | ||||||
| reqs | reqs | ||||||
| @@ -142,7 +138,6 @@ tsdoc | |||||||
| typeof | typeof | ||||||
| typestr | typestr | ||||||
| unshift | unshift | ||||||
| urlsafe |  | ||||||
| verifymethod | verifymethod | ||||||
| VERIFYMTHD | VERIFYMTHD | ||||||
| WARN_DOCSDIR_DOESNT_MATCH | WARN_DOCSDIR_DOESNT_MATCH | ||||||
|   | |||||||
| @@ -2,11 +2,8 @@ | |||||||
| Ashish Jain | Ashish Jain | ||||||
| cpettitt | cpettitt | ||||||
| Dong Cai | Dong Cai | ||||||
| fourcube |  | ||||||
| knsv |  | ||||||
| Knut Sveidqvist |  | ||||||
| Nikolay Rozhkov | Nikolay Rozhkov | ||||||
| Peng Xiao | Peng Xiao | ||||||
| Per Brolin | Per Brolin | ||||||
| Sidharth Vinod |  | ||||||
| subhash-halder | subhash-halder | ||||||
|  | Vinod Sidharth | ||||||
|   | |||||||
| @@ -28,9 +28,6 @@ dictionaryDefinitions: | |||||||
|   - name: suggestions |   - name: suggestions | ||||||
|     words: |     words: | ||||||
|       - none |       - none | ||||||
|       - disp |  | ||||||
|       - subproc |  | ||||||
|       - tria |  | ||||||
|     suggestWords: |     suggestWords: | ||||||
|       - seperator:separator |       - seperator:separator | ||||||
|       - vertice:vertex |       - vertice:vertex | ||||||
|   | |||||||
| @@ -24,15 +24,11 @@ Doctave | |||||||
| DokuWiki | DokuWiki | ||||||
| dompurify | dompurify | ||||||
| elkjs | elkjs | ||||||
| fcose |  | ||||||
| fontawesome | fontawesome | ||||||
| Fonticons |  | ||||||
| Forgejo |  | ||||||
| Foswiki | Foswiki | ||||||
| Gitea | Gitea | ||||||
| graphlib | graphlib | ||||||
| Grav | Grav | ||||||
| icones |  | ||||||
| iconify | iconify | ||||||
| Inkdrop | Inkdrop | ||||||
| jiti | jiti | ||||||
|   | |||||||
| @@ -1,22 +1,20 @@ | |||||||
| Adamiecki | Adamiecki | ||||||
| arrowend | arrowend | ||||||
| Bendpoints |  | ||||||
| bmatrix | bmatrix | ||||||
| braintree | braintree | ||||||
| catmull | catmull | ||||||
| compositTitleSize | compositTitleSize | ||||||
| curv |  | ||||||
| doublecircle | doublecircle | ||||||
| elems | elems | ||||||
| gantt | gantt | ||||||
| gitgraph | gitgraph | ||||||
| gzipped | gzipped | ||||||
| handDrawn | handDrawn | ||||||
| kanban | knsv | ||||||
|  | Knut | ||||||
| marginx | marginx | ||||||
| marginy | marginy | ||||||
| Markdownish | Markdownish | ||||||
| mermaidchart |  | ||||||
| mermaidjs | mermaidjs | ||||||
| mindmap | mindmap | ||||||
| mindmaps | mindmaps | ||||||
| @@ -25,7 +23,6 @@ multigraph | |||||||
| nodesep | nodesep | ||||||
| NOTEGROUP | NOTEGROUP | ||||||
| Pinterest | Pinterest | ||||||
| procs |  | ||||||
| rankdir | rankdir | ||||||
| ranksep | ranksep | ||||||
| rect | rect | ||||||
| @@ -34,6 +31,7 @@ sandboxed | |||||||
| siebling | siebling | ||||||
| statediagram | statediagram | ||||||
| substate | substate | ||||||
|  | Sveidqvist | ||||||
| unfixable | unfixable | ||||||
| Viewbox | Viewbox | ||||||
| viewports | viewports | ||||||
|   | |||||||
| @@ -4,4 +4,3 @@ handDrawn | |||||||
| KOEPF | KOEPF | ||||||
| neato | neato | ||||||
| newbranch | newbranch | ||||||
| validify |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| import { build } from 'esbuild'; | import { build } from 'esbuild'; | ||||||
| import { cp, mkdir, readFile, rename, writeFile } from 'node:fs/promises'; | import { mkdir, 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'; | ||||||
| @@ -8,10 +8,7 @@ import { defaultOptions, getBuildConfig } from './util.js'; | |||||||
| const shouldVisualize = process.argv.includes('--visualize'); | const shouldVisualize = process.argv.includes('--visualize'); | ||||||
|  |  | ||||||
| const buildPackage = async (entryName: keyof typeof packageOptions) => { | const buildPackage = async (entryName: keyof typeof packageOptions) => { | ||||||
|   const commonOptions: MermaidBuildOptions = { |   const commonOptions: MermaidBuildOptions = { ...defaultOptions, entryName } as const; | ||||||
|     ...defaultOptions, |  | ||||||
|     options: packageOptions[entryName], |  | ||||||
|   } as const; |  | ||||||
|   const buildConfigs: MermaidBuildOptions[] = [ |   const buildConfigs: MermaidBuildOptions[] = [ | ||||||
|     // package.mjs |     // package.mjs | ||||||
|     { ...commonOptions }, |     { ...commonOptions }, | ||||||
| @@ -31,27 +28,6 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => { | |||||||
|       // mermaid.js |       // mermaid.js | ||||||
|       { ...iifeOptions }, |       { ...iifeOptions }, | ||||||
|       // mermaid.min.js |       // mermaid.min.js | ||||||
|       { ...iifeOptions, minify: true, metafile: shouldVisualize }, |  | ||||||
|       // mermaid.tiny.min.js |  | ||||||
|       { |  | ||||||
|         ...iifeOptions, |  | ||||||
|         minify: true, |  | ||||||
|         includeLargeFeatures: false, |  | ||||||
|         metafile: shouldVisualize, |  | ||||||
|         sourcemap: false, |  | ||||||
|       } |  | ||||||
|     ); |  | ||||||
|   } |  | ||||||
|   if (entryName === 'mermaid-zenuml') { |  | ||||||
|     const iifeOptions: MermaidBuildOptions = { |  | ||||||
|       ...commonOptions, |  | ||||||
|       format: 'iife', |  | ||||||
|       globalName: 'mermaid-zenuml', |  | ||||||
|     }; |  | ||||||
|     buildConfigs.push( |  | ||||||
|       // mermaid-zenuml.js |  | ||||||
|       { ...iifeOptions }, |  | ||||||
|       // mermaid-zenuml.min.js |  | ||||||
|       { ...iifeOptions, minify: true, metafile: shouldVisualize } |       { ...iifeOptions, minify: true, metafile: shouldVisualize } | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| @@ -64,7 +40,7 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => { | |||||||
|         continue; |         continue; | ||||||
|       } |       } | ||||||
|       const fileName = Object.keys(metafile.outputs) |       const fileName = Object.keys(metafile.outputs) | ||||||
|         .find((file) => !file.includes('chunks') && file.endsWith('js'))! |         .find((file) => !file.includes('chunks') && file.endsWith('js')) | ||||||
|         .replace('dist/', ''); |         .replace('dist/', ''); | ||||||
|       // Upload metafile into https://esbuild.github.io/analyze/ |       // Upload metafile into https://esbuild.github.io/analyze/ | ||||||
|       await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile)); |       await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile)); | ||||||
| @@ -78,21 +54,6 @@ 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'); |  | ||||||
|   await cp('./packages/mermaid/CHANGELOG.md', './packages/tiny/CHANGELOG.md'); |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| const main = async () => { | const main = async () => { | ||||||
|   await generateLangium(); |   await generateLangium(); | ||||||
|   await mkdir('stats', { recursive: true }); |   await mkdir('stats', { recursive: true }); | ||||||
| @@ -101,7 +62,6 @@ 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(); | ||||||
|   | |||||||
| @@ -9,18 +9,13 @@ import { generateLangium } from '../.build/generateLangium.js'; | |||||||
| import { defaultOptions, getBuildConfig } from './util.js'; | import { defaultOptions, getBuildConfig } from './util.js'; | ||||||
|  |  | ||||||
| const configs = Object.values(packageOptions).map(({ packageName }) => | const configs = Object.values(packageOptions).map(({ packageName }) => | ||||||
|   getBuildConfig({ |   getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName }) | ||||||
|     ...defaultOptions, |  | ||||||
|     minify: false, |  | ||||||
|     core: false, |  | ||||||
|     options: packageOptions[packageName], |  | ||||||
|   }) |  | ||||||
| ); | ); | ||||||
| const mermaidIIFEConfig = getBuildConfig({ | const mermaidIIFEConfig = getBuildConfig({ | ||||||
|   ...defaultOptions, |   ...defaultOptions, | ||||||
|   minify: false, |   minify: false, | ||||||
|   core: false, |   core: false, | ||||||
|   options: packageOptions.mermaid, |   entryName: 'mermaid', | ||||||
|   format: 'iife', |   format: 'iife', | ||||||
| }); | }); | ||||||
| configs.push(mermaidIIFEConfig); | configs.push(mermaidIIFEConfig); | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { fileURLToPath } from 'url'; | |||||||
| import type { BuildOptions } from 'esbuild'; | import type { BuildOptions } from 'esbuild'; | ||||||
| import { readFileSync } from 'fs'; | import { readFileSync } from 'fs'; | ||||||
| import jsonSchemaPlugin from './jsonSchemaPlugin.js'; | import jsonSchemaPlugin from './jsonSchemaPlugin.js'; | ||||||
| import type { PackageOptions } from '../.build/common.js'; | import { packageOptions } from '../.build/common.js'; | ||||||
| import { jisonPlugin } from './jisonPlugin.js'; | import { jisonPlugin } from './jisonPlugin.js'; | ||||||
|  |  | ||||||
| const __dirname = fileURLToPath(new URL('.', import.meta.url)); | const __dirname = fileURLToPath(new URL('.', import.meta.url)); | ||||||
| @@ -13,16 +13,14 @@ export interface MermaidBuildOptions extends BuildOptions { | |||||||
|   core: boolean; |   core: boolean; | ||||||
|   metafile: boolean; |   metafile: boolean; | ||||||
|   format: 'esm' | 'iife'; |   format: 'esm' | 'iife'; | ||||||
|   options: PackageOptions; |   entryName: keyof typeof packageOptions; | ||||||
|   includeLargeFeatures: boolean; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = { | export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = { | ||||||
|   minify: false, |   minify: false, | ||||||
|   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 => { | ||||||
| @@ -41,18 +39,12 @@ const buildOptions = (override: BuildOptions): BuildOptions => { | |||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const getFileName = ( | const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOptions) => { | ||||||
|   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'; | ||||||
|   } |   } | ||||||
| @@ -60,29 +52,20 @@ const getFileName = ( | |||||||
| }; | }; | ||||||
|  |  | ||||||
| export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { | export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { | ||||||
|   const { |   const { core, entryName, metafile, format, minify } = options; | ||||||
|     core, |  | ||||||
|     format, |  | ||||||
|     options: { name, file, packageName }, |  | ||||||
|     globalName = 'mermaid', |  | ||||||
|     includeLargeFeatures, |  | ||||||
|     ...rest |  | ||||||
|   } = options; |  | ||||||
|  |  | ||||||
|   const external: string[] = ['require', 'fs', 'path']; |   const external: string[] = ['require', 'fs', 'path']; | ||||||
|  |   const { name, file, packageName } = packageOptions[entryName]; | ||||||
|   const outFileName = getFileName(name, options); |   const outFileName = getFileName(name, options); | ||||||
|   const output: BuildOptions = buildOptions({ |   const output: BuildOptions = buildOptions({ | ||||||
|     ...rest, |  | ||||||
|     absWorkingDir: resolve(__dirname, `../packages/${packageName}`), |     absWorkingDir: resolve(__dirname, `../packages/${packageName}`), | ||||||
|     entryPoints: { |     entryPoints: { | ||||||
|       [outFileName]: `src/${file}`, |       [outFileName]: `src/${file}`, | ||||||
|     }, |     }, | ||||||
|     globalName, |     metafile, | ||||||
|  |     minify, | ||||||
|     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', | ||||||
|     }, |     }, | ||||||
|   }); |   }); | ||||||
| @@ -101,12 +84,11 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { | |||||||
|   if (format === 'iife') { |   if (format === 'iife') { | ||||||
|     output.format = 'iife'; |     output.format = 'iife'; | ||||||
|     output.splitting = false; |     output.splitting = false; | ||||||
|     const originalGlobalName = output.globalName ?? 'mermaid'; |     output.globalName = '__esbuild_esm_mermaid'; | ||||||
|     output.globalName = `__esbuild_esm_mermaid_nm[${JSON.stringify(originalGlobalName)}]`; |  | ||||||
|     // Workaround for removing the .default access in esbuild IIFE. |     // Workaround for removing the .default access in esbuild IIFE. | ||||||
|     // https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396 |     // https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396 | ||||||
|     output.footer = { |     output.footer = { | ||||||
|       js: `globalThis[${JSON.stringify(originalGlobalName)}] = globalThis.${output.globalName}.default;`, |       js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;', | ||||||
|     }; |     }; | ||||||
|     output.outExtension = { '.js': '.js' }; |     output.outExtension = { '.js': '.js' }; | ||||||
|   } else { |   } else { | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							| @@ -4,7 +4,7 @@ contact_links: | |||||||
|     url: https://github.com/mermaid-js/mermaid/discussions |     url: https://github.com/mermaid-js/mermaid/discussions | ||||||
|     about: Ask the Community questions or share your own graphs in our discussions. |     about: Ask the Community questions or share your own graphs in our discussions. | ||||||
|   - name: Discord |   - name: Discord | ||||||
|     url: https://discord.gg/sKeNQX4Wtj |     url: https://discord.gg/AgrbSrBer3 | ||||||
|     about: Join our Community on Discord for Help and a casual chat. |     about: Join our Community on Discord for Help and a casual chat. | ||||||
|   - name: Documentation |   - name: Documentation | ||||||
|     url: https://mermaid.js.org |     url: https://mermaid.js.org | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE/theme_proposal.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/ISSUE_TEMPLATE/theme_proposal.yml
									
									
									
									
										vendored
									
									
								
							| @@ -29,7 +29,7 @@ body: | |||||||
|       label: Colors |       label: Colors | ||||||
|       description: |- |       description: |- | ||||||
|         A detailed list of the different colour values to use. |         A detailed list of the different colour values to use. | ||||||
|         See the [list of currently used variable names](https://mermaid-js.github.io/mermaid/#/theming?id=theme-variables-reference-table) |         A list of currently used variable names can be found [here](https://mermaid-js.github.io/mermaid/#/theming?id=theme-variables-reference-table) | ||||||
|       placeholder: |- |       placeholder: |- | ||||||
|         - background: #f4f4f4 |         - background: #f4f4f4 | ||||||
|         - primaryColor: #fff4dd |         - primaryColor: #fff4dd | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								.github/lychee.toml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								.github/lychee.toml
									
									
									
									
										vendored
									
									
								
							| @@ -44,23 +44,7 @@ exclude = [ | |||||||
| "https://chromewebstore.google.com", | "https://chromewebstore.google.com", | ||||||
|  |  | ||||||
| # Drupal 403 | # Drupal 403 | ||||||
| "https://(www.)?drupal.org", | "https://(www.)?drupal.org" | ||||||
|  |  | ||||||
| # Phbpp 403 |  | ||||||
| "https://(www.)?phpbb.com", |  | ||||||
|  |  | ||||||
| # Swimm returns 404, even though the link is valid |  | ||||||
| "https://docs.swimm.io", |  | ||||||
|  |  | ||||||
| # Certificate Error |  | ||||||
| "https://noteshub.app", |  | ||||||
|  |  | ||||||
| # Timeout |  | ||||||
| "https://huehive.co", |  | ||||||
| "https://foswiki.org", |  | ||||||
| "https://www.gnu.org", |  | ||||||
| "https://redmine.org", |  | ||||||
| "https://mermaid-preview.com" |  | ||||||
| ] | ] | ||||||
|  |  | ||||||
| # Exclude all private IPs from checking. | # Exclude all private IPs from checking. | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
								
							| @@ -15,5 +15,5 @@ markComment: > | |||||||
|   If you are still interested in this issue and it is still relevant you can comment to revive it. |   If you are still interested in this issue and it is still relevant you can comment to revive it. | ||||||
| # Comment to post when closing a stale issue. Set to `false` to disable | # Comment to post when closing a stale issue. Set to `false` to disable | ||||||
| closeComment: > | closeComment: > | ||||||
|   This issue has been automatically closed due to a lack of activity.  |   This issue has been been automatically closed due to a lack of activity.  | ||||||
|   This is done to maintain a clean list of issues that the community is interested in developing. |   This is done to maintain a clean list of issues that the community is interested in developing. | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								.github/workflows/autofix.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/autofix.yml
									
									
									
									
										vendored
									
									
								
							| @@ -13,13 +13,13 @@ jobs: | |||||||
|   autofix: |   autofix: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|         # uses version from "packageManager" field in package.json |         # uses version from "packageManager" field in package.json | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           cache: pnpm |           cache: pnpm | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
| @@ -42,4 +42,4 @@ jobs: | |||||||
|         working-directory: ./packages/mermaid |         working-directory: ./packages/mermaid | ||||||
|         run: pnpm run docs:build |         run: pnpm run docs:build | ||||||
|  |  | ||||||
|       - uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27 # main |       - uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								.github/workflows/build-docs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/build-docs.yml
									
									
									
									
										vendored
									
									
								
							| @@ -18,12 +18,12 @@ jobs: | |||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - name: Checkout |       - name: Checkout | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |         uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           cache: pnpm |           cache: pnpm | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/check-readme-in-sync.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/check-readme-in-sync.yml
									
									
									
									
										vendored
									
									
								
							| @@ -18,7 +18,7 @@ jobs: | |||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - name: Checkout repository |       - name: Checkout repository | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |         uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - name: Check for difference in README.md and docs/README.md |       - name: Check for difference in README.md and docs/README.md | ||||||
|         run: | |         run: | | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/workflows/codeql.yml
									
									
									
									
										vendored
									
									
								
							| @@ -11,9 +11,6 @@ on: | |||||||
|       - synchronize |       - synchronize | ||||||
|       - ready_for_review |       - ready_for_review | ||||||
|  |  | ||||||
| permissions: # added using https://github.com/step-security/secure-repo |  | ||||||
|   contents: read |  | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   analyze: |   analyze: | ||||||
|     name: Analyze |     name: Analyze | ||||||
| @@ -32,11 +29,11 @@ jobs: | |||||||
|  |  | ||||||
|     steps: |     steps: | ||||||
|       - name: Checkout repository |       - name: Checkout repository | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |         uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       # Initializes the CodeQL tools for scanning. |       # Initializes the CodeQL tools for scanning. | ||||||
|       - name: Initialize CodeQL |       - name: Initialize CodeQL | ||||||
|         uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |         uses: github/codeql-action/init@v3 | ||||||
|         with: |         with: | ||||||
|           config-file: ./.github/codeql/codeql-config.yml |           config-file: ./.github/codeql/codeql-config.yml | ||||||
|           languages: ${{ matrix.language }} |           languages: ${{ matrix.language }} | ||||||
| @@ -48,7 +45,7 @@ jobs: | |||||||
|       # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java). |       # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java). | ||||||
|       # If this step fails, then you should remove it and run the build manually (see below) |       # If this step fails, then you should remove it and run the build manually (see below) | ||||||
|       - name: Autobuild |       - name: Autobuild | ||||||
|         uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |         uses: github/codeql-action/autobuild@v3 | ||||||
|  |  | ||||||
|       # ℹ️ Command-line programs to run using the OS shell. |       # ℹ️ Command-line programs to run using the OS shell. | ||||||
|       # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun |       # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun | ||||||
| @@ -62,4 +59,4 @@ jobs: | |||||||
|       #   make release |       #   make release | ||||||
|  |  | ||||||
|       - name: Perform CodeQL Analysis |       - name: Perform CodeQL Analysis | ||||||
|         uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |         uses: github/codeql-action/analyze@v3 | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								.github/workflows/dependency-review.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/dependency-review.yml
									
									
									
									
										vendored
									
									
								
							| @@ -15,6 +15,6 @@ jobs: | |||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - name: 'Checkout Repository' |       - name: 'Checkout Repository' | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |         uses: actions/checkout@v4 | ||||||
|       - name: 'Dependency Review' |       - name: 'Dependency Review' | ||||||
|         uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0 |         uses: actions/dependency-review-action@v4 | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								.github/workflows/e2e-applitools.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/e2e-applitools.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,37 +23,38 @@ env: | |||||||
| jobs: | jobs: | ||||||
|   e2e-applitools: |   e2e-applitools: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|  |     container: | ||||||
|  |       image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 | ||||||
|  |       options: --user 1001 | ||||||
|     steps: |     steps: | ||||||
|       - if: ${{ ! env.USE_APPLI }} |       - if: ${{ ! env.USE_APPLI }} | ||||||
|         name: Warn if not using Applitools |         name: Warn if not using Applitools | ||||||
|         run: | |         run: | | ||||||
|           echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run." |           echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run." | ||||||
|  |  | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|         # uses version from "packageManager" field in package.json |         # uses version from "packageManager" field in package.json | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
|  |  | ||||||
|       - if: ${{ env.USE_APPLI }} |       - if: ${{ env.USE_APPLI }} | ||||||
|         name: Notify applitools of new batch |         name: Notify applitools of new batch | ||||||
|         # Copied from docs https://applitools.com/docs/topics/integrations/github-integration-ci-setup.html |         # Copied from docs https://applitools.com/docs/topics/integrations/github-integration-ci-setup.html | ||||||
|  |         run: curl -L -d '' -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH" | ||||||
|         env: |         env: | ||||||
|           # e.g. mermaid-js/mermaid/my-branch |           # e.g. mermaid-js/mermaid/my-branch | ||||||
|           APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }} |           APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }} | ||||||
|           APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }} |           APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }} | ||||||
|           APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }} |           APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }} | ||||||
|           APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' |           APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' | ||||||
|         uses: wei/curl@012398a392d02480afa2720780031f8621d5f94c |  | ||||||
|         with: |  | ||||||
|           args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH" |  | ||||||
|  |  | ||||||
|       - name: Cypress run |       - name: Cypress run | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@v4 | ||||||
|         id: cypress |         id: cypress | ||||||
|         with: |         with: | ||||||
|           start: pnpm run dev |           start: pnpm run dev | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								.github/workflows/e2e-timings.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								.github/workflows/e2e-timings.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,70 +0,0 @@ | |||||||
| name: E2E - Generate Timings |  | ||||||
|  |  | ||||||
| on: |  | ||||||
|   # run this workflow every night at 3am |  | ||||||
|   schedule: |  | ||||||
|     - cron: '28 3 * * *' |  | ||||||
|   # or when the user triggers it from GitHub Actions page |  | ||||||
|   workflow_dispatch: |  | ||||||
|  |  | ||||||
| concurrency: ${{ github.workflow }}-${{ github.ref }} |  | ||||||
|  |  | ||||||
| permissions: |  | ||||||
|   contents: write |  | ||||||
|   pull-requests: write |  | ||||||
|  |  | ||||||
| jobs: |  | ||||||
|   timings: |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     container: |  | ||||||
|       image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 |  | ||||||
|       options: --user 1001 |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |  | ||||||
|       - name: Setup Node.js |  | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |  | ||||||
|         with: |  | ||||||
|           node-version-file: '.node-version' |  | ||||||
|       - name: Install dependencies |  | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |  | ||||||
|         with: |  | ||||||
|           runTests: false |  | ||||||
|  |  | ||||||
|       - name: Cypress run |  | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |  | ||||||
|         id: cypress |  | ||||||
|         with: |  | ||||||
|           install: false |  | ||||||
|           start: pnpm run dev:coverage |  | ||||||
|           wait-on: 'http://localhost:9000' |  | ||||||
|           browser: chrome |  | ||||||
|           publish-summary: false |  | ||||||
|         env: |  | ||||||
|           VITEST_COVERAGE: true |  | ||||||
|           CYPRESS_COMMIT: ${{ github.sha }} |  | ||||||
|           SPLIT: 1 |  | ||||||
|           SPLIT_INDEX: 0 |  | ||||||
|           SPLIT_FILE: 'cypress/timings.json' |  | ||||||
|  |  | ||||||
|       - name: Compare timings |  | ||||||
|         id: compare |  | ||||||
|         run: | |  | ||||||
|           OUTPUT=$(pnpm tsx scripts/compare-timings.ts) |  | ||||||
|           echo "$OUTPUT" >> $GITHUB_STEP_SUMMARY |  | ||||||
|  |  | ||||||
|           echo "output<<EOF" >> $GITHUB_OUTPUT |  | ||||||
|           echo "$OUTPUT" >> $GITHUB_OUTPUT |  | ||||||
|           echo "EOF" >> $GITHUB_OUTPUT |  | ||||||
|  |  | ||||||
|       - name: Commit and create pull request |  | ||||||
|         uses: peter-evans/create-pull-request@18e469570b1cf0dfc11d60ec121099f8ff3e617a |  | ||||||
|         with: |  | ||||||
|           add-paths: | |  | ||||||
|             cypress/timings.json |  | ||||||
|           commit-message: 'chore: update E2E timings' |  | ||||||
|           branch: update-timings |  | ||||||
|           title: Update E2E Timings |  | ||||||
|           body: ${{ steps.compare.outputs.output }} |  | ||||||
|           delete-branch: true |  | ||||||
|           sign-commits: true |  | ||||||
							
								
								
									
										52
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										52
									
								
								.github/workflows/e2e.yml
									
									
									
									
										vendored
									
									
								
							| @@ -28,8 +28,7 @@ env: | |||||||
|       ) ||  |       ) ||  | ||||||
|       github.event.before |       github.event.before | ||||||
|     }} |     }} | ||||||
|   RUN_VISUAL_TEST: >- |   shouldRunParallel: ${{ secrets.CYPRESS_RECORD_KEY != '' && !(github.event_name == 'push' && github.ref == 'refs/heads/develop') }} | ||||||
|     ${{ github.repository == 'mermaid-js/mermaid' && (github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/')) }} |  | ||||||
| jobs: | jobs: | ||||||
|   cache: |   cache: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
| @@ -37,29 +36,30 @@ jobs: | |||||||
|       image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 |       image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 | ||||||
|       options: --user 1001 |       options: --user 1001 | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
|       - name: Cache snapshots |       - name: Cache snapshots | ||||||
|         id: cache-snapshot |         id: cache-snapshot | ||||||
|         uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 |         uses: actions/cache@v4 | ||||||
|         with: |         with: | ||||||
|  |           save-always: true | ||||||
|           path: ./cypress/snapshots |           path: ./cypress/snapshots | ||||||
|           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} |           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} | ||||||
|  |  | ||||||
|       # If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots. |       # If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots. | ||||||
|       - name: Switch to base branch |       - name: Switch to base branch | ||||||
|         if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} |         if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |         uses: actions/checkout@v4 | ||||||
|         with: |         with: | ||||||
|           ref: ${{ env.targetHash }} |           ref: ${{ env.targetHash }} | ||||||
|  |  | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} |         if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@v6 | ||||||
|         with: |         with: | ||||||
|           # just perform install |           # just perform install | ||||||
|           runTests: false |           runTests: false | ||||||
| @@ -80,28 +80,28 @@ jobs: | |||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
|       matrix: |       matrix: | ||||||
|         containers: [1, 2, 3, 4, 5] |         containers: [1, 2, 3, 4] | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|         # uses version from "packageManager" field in package.json |         # uses version from "packageManager" field in package.json | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
|  |  | ||||||
|       # These cached snapshots are downloaded, providing the reference snapshots. |       # These cached snapshots are downloaded, providing the reference snapshots. | ||||||
|       - name: Cache snapshots |       - name: Cache snapshots | ||||||
|         id: cache-snapshot |         id: cache-snapshot | ||||||
|         uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 |         uses: actions/cache/restore@v4 | ||||||
|         with: |         with: | ||||||
|           path: ./cypress/snapshots |           path: ./cypress/snapshots | ||||||
|           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} |           key: ${{ runner.os }}-snapshots-${{ env.targetHash }} | ||||||
|  |  | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@v6 | ||||||
|         with: |         with: | ||||||
|           runTests: false |           runTests: false | ||||||
|  |  | ||||||
| @@ -117,8 +117,11 @@ jobs: | |||||||
|       # Install NPM dependencies, cache them correctly |       # Install NPM dependencies, cache them correctly | ||||||
|       # and run all Cypress tests |       # and run all Cypress tests | ||||||
|       - name: Cypress run |       - name: Cypress run | ||||||
|         uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12 |         uses: cypress-io/github-action@v6 | ||||||
|         id: cypress |         id: cypress | ||||||
|  |         # If CYPRESS_RECORD_KEY is set, run in parallel on all containers | ||||||
|  |         # Otherwise (e.g. if running from fork), we run on a single container only | ||||||
|  |         if: ${{ env.shouldRunParallel == 'true' || ( matrix.containers == 1 ) }} | ||||||
|         with: |         with: | ||||||
|           install: false |           install: false | ||||||
|           start: pnpm run dev:coverage |           start: pnpm run dev:coverage | ||||||
| @@ -126,20 +129,19 @@ jobs: | |||||||
|           browser: chrome |           browser: chrome | ||||||
|           # Disable recording if we don't have an API key |           # Disable recording if we don't have an API key | ||||||
|           # e.g. if this action was run from a fork |           # e.g. if this action was run from a fork | ||||||
|           record: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY != '' }} |           record: ${{ env.shouldRunParallel == 'true' }} | ||||||
|  |           parallel: ${{ env.shouldRunParallel == 'true' }} | ||||||
|         env: |         env: | ||||||
|           ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }} |           CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} | ||||||
|           ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }} |  | ||||||
|           ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }} |  | ||||||
|           CYPRESS_COMMIT: ${{ github.sha }} |  | ||||||
|           CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}} |  | ||||||
|           SPLIT: ${{ strategy.job-total }} |  | ||||||
|           SPLIT_INDEX: ${{ strategy.job-index }} |  | ||||||
|           SPLIT_FILE: 'cypress/timings.json' |  | ||||||
|           VITEST_COVERAGE: true |           VITEST_COVERAGE: true | ||||||
|  |           CYPRESS_COMMIT: ${{ github.sha }} | ||||||
|  |           ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }} | ||||||
|  |           ARGOS_PARALLEL: ${{ env.shouldRunParallel == 'true' }} | ||||||
|  |           ARGOS_PARALLEL_TOTAL: 4 | ||||||
|  |           ARGOS_PARALLEL_INDEX: ${{ matrix.containers }} | ||||||
|  |  | ||||||
|       - name: Upload Coverage to Codecov |       - name: Upload Coverage to Codecov | ||||||
|         uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 |         uses: codecov/codecov-action@v4 | ||||||
|         # Run step only pushes to develop and pull_requests |         # Run step only pushes to develop and pull_requests | ||||||
|         if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}} |         if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}} | ||||||
|         with: |         with: | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								.github/workflows/issue-triage.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/issue-triage.yml
									
									
									
									
										vendored
									
									
								
							| @@ -4,17 +4,11 @@ on: | |||||||
|   issues: |   issues: | ||||||
|     types: [opened] |     types: [opened] | ||||||
|  |  | ||||||
| permissions: # added using https://github.com/step-security/secure-repo |  | ||||||
|   contents: read |  | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   triage: |   triage: | ||||||
|     permissions: |  | ||||||
|       issues: write # for andymckay/labeler to label issues |  | ||||||
|       pull-requests: write # for andymckay/labeler to label PRs |  | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4 |       - uses: andymckay/labeler@1.0.4 | ||||||
|         with: |         with: | ||||||
|           repo-token: '${{ secrets.GITHUB_TOKEN }}' |           repo-token: '${{ secrets.GITHUB_TOKEN }}' | ||||||
|           add-labels: 'Status: Triage' |           add-labels: 'Status: Triage' | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								.github/workflows/link-checker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/link-checker.yml
									
									
									
									
										vendored
									
									
								
							| @@ -19,9 +19,6 @@ on: | |||||||
|     # * is a special character in YAML so you have to quote this string |     # * is a special character in YAML so you have to quote this string | ||||||
|     - cron: '30 8 * * *' |     - cron: '30 8 * * *' | ||||||
|  |  | ||||||
| permissions: # added using https://github.com/step-security/secure-repo |  | ||||||
|   contents: read |  | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   link-checker: |   link-checker: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
| @@ -29,17 +26,17 @@ jobs: | |||||||
|       # lychee only uses the GITHUB_TOKEN to avoid rate-limiting |       # lychee only uses the GITHUB_TOKEN to avoid rate-limiting | ||||||
|       contents: read |       contents: read | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - name: Restore lychee cache |       - name: Restore lychee cache | ||||||
|         uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 |         uses: actions/cache@v4 | ||||||
|         with: |         with: | ||||||
|           path: .lycheecache |           path: .lycheecache | ||||||
|           key: cache-lychee-${{ github.sha }} |           key: cache-lychee-${{ github.sha }} | ||||||
|           restore-keys: cache-lychee- |           restore-keys: cache-lychee- | ||||||
|  |  | ||||||
|       - name: Link Checker |       - name: Link Checker | ||||||
|         uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6 # v2.3.0 |         uses: lycheeverse/lychee-action@v1.9.3 | ||||||
|         with: |         with: | ||||||
|           args: >- |           args: >- | ||||||
|             --config .github/lychee.toml |             --config .github/lychee.toml | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							| @@ -12,24 +12,16 @@ permissions: | |||||||
|   contents: write |   contents: write | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   docker-lint: |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |  | ||||||
|  |  | ||||||
|       - uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0 |  | ||||||
|         with: |  | ||||||
|           verbose: true |  | ||||||
|   lint: |   lint: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|         # uses version from "packageManager" field in package.json |         # uses version from "packageManager" field in package.json | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           cache: pnpm |           cache: pnpm | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
| @@ -89,7 +81,7 @@ jobs: | |||||||
|         continue-on-error: ${{ github.event_name == 'push' }} |         continue-on-error: ${{ github.event_name == 'push' }} | ||||||
|         run: pnpm run docs:verify |         run: pnpm run docs:verify | ||||||
|  |  | ||||||
|       - uses: testomatio/check-tests@0ea638fcec1820cf2e7b9854fdbdd04128a55bd4 # stable |       - uses: testomatio/check-tests@stable | ||||||
|         with: |         with: | ||||||
|           framework: cypress |           framework: cypress | ||||||
|           tests: './cypress/e2e/**/**.spec.js' |           tests: './cypress/e2e/**/**.spec.js' | ||||||
|   | |||||||
							
								
								
									
										28
									
								
								.github/workflows/pr-labeler.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										28
									
								
								.github/workflows/pr-labeler.yml
									
									
									
									
										vendored
									
									
								
							| @@ -22,36 +22,10 @@ jobs: | |||||||
|       pull-requests: write # write permission is required to label PRs |       pull-requests: write # write permission is required to label PRs | ||||||
|     steps: |     steps: | ||||||
|       - name: Label PR |       - name: Label PR | ||||||
|         uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0 |         uses: release-drafter/release-drafter@v6 | ||||||
|         with: |         with: | ||||||
|           config-name: pr-labeler.yml |           config-name: pr-labeler.yml | ||||||
|           disable-autolabeler: false |           disable-autolabeler: false | ||||||
|           disable-releaser: true |           disable-releaser: true | ||||||
|         env: |         env: | ||||||
|           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |  | ||||||
|       - name: Add "Sponsored by MermaidChart" label |  | ||||||
|         uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 |  | ||||||
|         with: |  | ||||||
|           github-token: ${{ secrets.GITHUB_TOKEN }} |  | ||||||
|           script: | |  | ||||||
|             const prNumber = context.payload.pull_request.number; |  | ||||||
|             const { data: commits } = await github.rest.pulls.listCommits({ |  | ||||||
|               owner: context.repo.owner, |  | ||||||
|               repo: context.repo.repo, |  | ||||||
|               pull_number: prNumber, |  | ||||||
|             }); |  | ||||||
|  |  | ||||||
|             const isSponsored = commits.every( |  | ||||||
|               (c) => c.commit.author.email?.endsWith('@mermaidchart.com') |  | ||||||
|             ); |  | ||||||
|  |  | ||||||
|             if (isSponsored) { |  | ||||||
|               console.log('PR is sponsored. Adding label.'); |  | ||||||
|               await github.rest.issues.addLabels({ |  | ||||||
|                 owner: context.repo.owner, |  | ||||||
|                 repo: context.repo.repo, |  | ||||||
|                 issue_number: prNumber, |  | ||||||
|                 labels: ['Sponsored by MermaidChart'], |  | ||||||
|               }); |  | ||||||
|             } |  | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								.github/workflows/publish-docs.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/publish-docs.yml
									
									
									
									
										vendored
									
									
								
							| @@ -23,12 +23,12 @@ jobs: | |||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - name: Checkout |       - name: Checkout | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |         uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           cache: pnpm |           cache: pnpm | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
| @@ -37,13 +37,13 @@ jobs: | |||||||
|         run: pnpm install --frozen-lockfile |         run: pnpm install --frozen-lockfile | ||||||
|  |  | ||||||
|       - name: Setup Pages |       - name: Setup Pages | ||||||
|         uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 |         uses: actions/configure-pages@v4 | ||||||
|  |  | ||||||
|       - name: Run Build |       - name: Run Build | ||||||
|         run: pnpm --filter mermaid run docs:build:vitepress |         run: pnpm --filter mermaid run docs:build:vitepress | ||||||
|  |  | ||||||
|       - name: Upload artifact |       - name: Upload artifact | ||||||
|         uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 |         uses: actions/upload-pages-artifact@v3 | ||||||
|         with: |         with: | ||||||
|           path: packages/mermaid/src/vitepress/.vitepress/dist |           path: packages/mermaid/src/vitepress/.vitepress/dist | ||||||
|  |  | ||||||
| @@ -56,4 +56,4 @@ jobs: | |||||||
|     steps: |     steps: | ||||||
|       - name: Deploy to GitHub Pages |       - name: Deploy to GitHub Pages | ||||||
|         id: deployment |         id: deployment | ||||||
|         uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 |         uses: actions/deploy-pages@v4 | ||||||
|   | |||||||
| @@ -9,14 +9,14 @@ jobs: | |||||||
|   publish-preview: |   publish-preview: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|         with: |         with: | ||||||
|           fetch-depth: 0 |           fetch-depth: 0 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           cache: pnpm |           cache: pnpm | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
| @@ -28,7 +28,7 @@ jobs: | |||||||
|           CYPRESS_CACHE_FOLDER: .cache/Cypress |           CYPRESS_CACHE_FOLDER: .cache/Cypress | ||||||
|  |  | ||||||
|       - name: Install Json |       - name: Install Json | ||||||
|         run: npm i json@11.0.0 --global |         run: npm i json --global | ||||||
|  |  | ||||||
|       - name: Publish |       - name: Publish | ||||||
|         working-directory: ./packages/mermaid |         working-directory: ./packages/mermaid | ||||||
|   | |||||||
							
								
								
									
										43
									
								
								.github/workflows/release-preview.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										43
									
								
								.github/workflows/release-preview.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,43 +0,0 @@ | |||||||
| name: Preview release |  | ||||||
|  |  | ||||||
| on: |  | ||||||
|   pull_request: |  | ||||||
|     branches: [develop] |  | ||||||
|     types: [opened, synchronize, labeled, ready_for_review] |  | ||||||
|  |  | ||||||
| concurrency: |  | ||||||
|   group: ${{ github.workflow }}-${{ github.event.number }} |  | ||||||
|   cancel-in-progress: true |  | ||||||
|  |  | ||||||
| permissions: |  | ||||||
|   contents: read |  | ||||||
|   actions: write |  | ||||||
|  |  | ||||||
| jobs: |  | ||||||
|   preview: |  | ||||||
|     if: ${{ github.repository_owner == 'mermaid-js' }} |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     permissions: |  | ||||||
|       contents: read |  | ||||||
|       id-token: write |  | ||||||
|       issues: write |  | ||||||
|       pull-requests: write |  | ||||||
|     name: Publish preview release |  | ||||||
|     timeout-minutes: 5 |  | ||||||
|     steps: |  | ||||||
|       - name: Checkout Repo |  | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |  | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |  | ||||||
|  |  | ||||||
|       - name: Setup Node.js |  | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |  | ||||||
|         with: |  | ||||||
|           cache: pnpm |  | ||||||
|           node-version-file: '.node-version' |  | ||||||
|  |  | ||||||
|       - name: Install Packages |  | ||||||
|         run: pnpm install --frozen-lockfile |  | ||||||
|  |  | ||||||
|       - name: Publish packages |  | ||||||
|         run: pnpx pkg-pr-new publish --pnpm './packages/*' |  | ||||||
							
								
								
									
										16
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -7,26 +7,18 @@ on: | |||||||
|  |  | ||||||
| concurrency: ${{ github.workflow }}-${{ github.ref }} | concurrency: ${{ github.workflow }}-${{ github.ref }} | ||||||
|  |  | ||||||
| permissions: # added using https://github.com/step-security/secure-repo |  | ||||||
|   contents: read |  | ||||||
|  |  | ||||||
| jobs: | jobs: | ||||||
|   release: |   release: | ||||||
|     if: github.repository == 'mermaid-js/mermaid' |  | ||||||
|     permissions: |  | ||||||
|       contents: write # to create release (changesets/action) |  | ||||||
|       id-token: write # OpenID Connect token needed for provenance |  | ||||||
|       pull-requests: write # to create pull request (changesets/action) |  | ||||||
|     name: Release |     name: Release | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - name: Checkout Repo |       - name: Checkout Repo | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |         uses: actions/checkout@v3 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           cache: pnpm |           cache: pnpm | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
| @@ -36,7 +28,7 @@ jobs: | |||||||
|  |  | ||||||
|       - name: Create Release Pull Request or Publish to npm |       - name: Create Release Pull Request or Publish to npm | ||||||
|         id: changesets |         id: changesets | ||||||
|         uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9 |         uses: changesets/action@v1 | ||||||
|         with: |         with: | ||||||
|           version: pnpm changeset:version |           version: pnpm changeset:version | ||||||
|           publish: pnpm changeset:publish |           publish: pnpm changeset:publish | ||||||
|   | |||||||
							
								
								
									
										37
									
								
								.github/workflows/scorecard.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/scorecard.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,37 +0,0 @@ | |||||||
| name: Scorecard supply-chain security |  | ||||||
| on: |  | ||||||
|   branch_protection_rule: |  | ||||||
|   push: |  | ||||||
|     branches: |  | ||||||
|       - develop |  | ||||||
|   schedule: |  | ||||||
|     - cron: 29 15 * * 0 |  | ||||||
| permissions: read-all |  | ||||||
| jobs: |  | ||||||
|   analysis: |  | ||||||
|     name: Scorecard analysis |  | ||||||
|     permissions: |  | ||||||
|       id-token: write |  | ||||||
|       security-events: write |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     steps: |  | ||||||
|       - name: Checkout code |  | ||||||
|         uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |  | ||||||
|         with: |  | ||||||
|           persist-credentials: false |  | ||||||
|       - name: Run analysis |  | ||||||
|         uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 |  | ||||||
|         with: |  | ||||||
|           results_file: results.sarif |  | ||||||
|           results_format: sarif |  | ||||||
|           publish_results: true |  | ||||||
|       - name: Upload artifact |  | ||||||
|         uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1 |  | ||||||
|         with: |  | ||||||
|           name: SARIF file |  | ||||||
|           path: results.sarif |  | ||||||
|           retention-days: 5 |  | ||||||
|       - name: Upload to code-scanning |  | ||||||
|         uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10 |  | ||||||
|         with: |  | ||||||
|           sarif_file: results.sarif |  | ||||||
							
								
								
									
										12
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -9,13 +9,13 @@ jobs: | |||||||
|   unit-test: |   unit-test: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|         # uses version from "packageManager" field in package.json |         # uses version from "packageManager" field in package.json | ||||||
|  |  | ||||||
|       - name: Setup Node.js |       - name: Setup Node.js | ||||||
|         uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0 |         uses: actions/setup-node@v4 | ||||||
|         with: |         with: | ||||||
|           cache: pnpm |           cache: pnpm | ||||||
|           node-version-file: '.node-version' |           node-version-file: '.node-version' | ||||||
| @@ -38,12 +38,8 @@ jobs: | |||||||
|         run: | |         run: | | ||||||
|           pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage |           pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage | ||||||
|  |  | ||||||
|       - name: Verify out-of-tree build with TypeScript |  | ||||||
|         run: | |  | ||||||
|           pnpm test:check:tsc |  | ||||||
|  |  | ||||||
|       - name: Upload Coverage to Codecov |       - name: Upload Coverage to Codecov | ||||||
|         uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 |         uses: codecov/codecov-action@v4 | ||||||
|         # Run step only pushes to develop and pull_requests |         # Run step only pushes to develop and pull_requests | ||||||
|         if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }} |         if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }} | ||||||
|         with: |         with: | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/unlock-reopened-issues.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/unlock-reopened-issues.yml
									
									
									
									
										vendored
									
									
								
							| @@ -8,6 +8,6 @@ jobs: | |||||||
|   triage: |   triage: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1 |       - uses: Dunning-Kruger/unlock-issues@v1 | ||||||
|         with: |         with: | ||||||
|           repo-token: '${{ secrets.GITHUB_TOKEN }}' |           repo-token: '${{ secrets.GITHUB_TOKEN }}' | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								.github/workflows/update-browserlist.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/update-browserlist.yml
									
									
									
									
										vendored
									
									
								
							| @@ -8,18 +8,18 @@ jobs: | |||||||
|   update-browser-list: |   update-browser-list: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 |       - uses: actions/checkout@v4 | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |       - uses: pnpm/action-setup@v4 | ||||||
|       - run: npx update-browserslist-db@latest |       - run: npx update-browserslist-db@latest | ||||||
|       - name: Commit changes |       - name: Commit changes | ||||||
|         uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 |         uses: EndBug/add-and-commit@v9 | ||||||
|         with: |         with: | ||||||
|           author_name: ${{ github.actor }} |           author_name: ${{ github.actor }} | ||||||
|           author_email: ${{ github.actor }}@users.noreply.github.com |           author_email: ${{ github.actor }}@users.noreply.github.com | ||||||
|           message: 'chore: update browsers list' |           message: 'chore: update browsers list' | ||||||
|           push: false |           push: false | ||||||
|       - name: Create Pull Request |       - name: Create Pull Request | ||||||
|         uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6 |         uses: peter-evans/create-pull-request@v6 | ||||||
|         with: |         with: | ||||||
|           branch: update-browserslist |           branch: update-browserslist | ||||||
|           title: Update Browserslist |           title: Update Browserslist | ||||||
|   | |||||||
							
								
								
									
										70
									
								
								.github/workflows/validate-lockfile.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								.github/workflows/validate-lockfile.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,70 +0,0 @@ | |||||||
| name: Validate pnpm-lock.yaml |  | ||||||
|  |  | ||||||
| on: |  | ||||||
|   pull_request: |  | ||||||
|     paths: |  | ||||||
|       - 'pnpm-lock.yaml' |  | ||||||
|       - '**/package.json' |  | ||||||
|       - '.github/workflows/validate-lockfile.yml' |  | ||||||
|  |  | ||||||
| jobs: |  | ||||||
|   validate-lockfile: |  | ||||||
|     runs-on: ubuntu-latest |  | ||||||
|     steps: |  | ||||||
|       - name: Checkout code |  | ||||||
|         uses: actions/checkout@v4 |  | ||||||
|         with: |  | ||||||
|           fetch-depth: 0 |  | ||||||
|  |  | ||||||
|       - name: Set up Node.js |  | ||||||
|         uses: actions/setup-node@v4 |  | ||||||
|         with: |  | ||||||
|           node-version: 20 |  | ||||||
|  |  | ||||||
|       - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0 |  | ||||||
|  |  | ||||||
|       - name: Validate pnpm-lock.yaml entries |  | ||||||
|         id: validate # give this step an ID so we can reference its outputs |  | ||||||
|         run: | |  | ||||||
|           issues=() |  | ||||||
|  |  | ||||||
|           # 1) No tarball references |  | ||||||
|           if grep -qF 'tarball:' pnpm-lock.yaml; then |  | ||||||
|             issues+=("• Tarball references found (forbidden)") |  | ||||||
|           fi |  | ||||||
|  |  | ||||||
|           # 2) No unwanted vitepress paths |  | ||||||
|           if grep -qF 'packages/mermaid/src/vitepress' pnpm-lock.yaml; then |  | ||||||
|             issues+=("• Disallowed path 'packages/mermaid/src/vitepress' present. Run `rm -rf packages/mermaid/src/vitepress && pnpm install` to regenerate.") |  | ||||||
|           fi |  | ||||||
|  |  | ||||||
|           # 3) Lockfile only changes when package.json changes |  | ||||||
|           git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} > changed.txt |  | ||||||
|           if grep -q '^pnpm-lock.yaml$' changed.txt && ! grep -q 'package.json' changed.txt; then |  | ||||||
|             issues+=("• pnpm-lock.yaml changed without any package.json modification") |  | ||||||
|           fi |  | ||||||
|  |  | ||||||
|           # If any issues, output them and fail |  | ||||||
|           if [ ${#issues[@]} -gt 0 ]; then |  | ||||||
|             # Use the new GITHUB_OUTPUT approach to set a multiline output |  | ||||||
|             { |  | ||||||
|               echo "errors<<EOF" |  | ||||||
|               printf '%s\n' "${issues[@]}" |  | ||||||
|               echo "EOF" |  | ||||||
|             } >> $GITHUB_OUTPUT |  | ||||||
|             exit 1 |  | ||||||
|           fi |  | ||||||
|  |  | ||||||
|       - name: Comment on PR if validation failed |  | ||||||
|         if: failure() |  | ||||||
|         uses: peter-evans/create-or-update-comment@v4 |  | ||||||
|         with: |  | ||||||
|           token: ${{ secrets.GITHUB_TOKEN }} |  | ||||||
|           issue-number: ${{ github.event.pull_request.number }} |  | ||||||
|           body: | |  | ||||||
|             The following issue(s) were detected: |  | ||||||
|             ${{ steps.validate.outputs.errors }} |  | ||||||
|  |  | ||||||
|             Please address these and push an update. |  | ||||||
|  |  | ||||||
|             _Posted automatically by GitHub Actions_ |  | ||||||
| @@ -1,2 +0,0 @@ | |||||||
| ignored: |  | ||||||
|   - DL3002 # TODO: Last USER should not be root |  | ||||||
| @@ -1,2 +1,4 @@ | |||||||
| #!/usr/bin/env sh | #!/bin/sh | ||||||
|  | . "$(dirname "$0")/_/husky.sh" | ||||||
|  |  | ||||||
| NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit | NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| 22.14.0 | 20.12.2 | ||||||
|   | |||||||
| @@ -94,10 +94,6 @@ 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) { | ||||||
|   | |||||||
| @@ -1 +0,0 @@ | |||||||
| ./packages/mermaid/CHANGELOG.md |  | ||||||
							
								
								
									
										1005
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1005
									
								
								CHANGELOG.md
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										15
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,13 +1,2 @@ | |||||||
| FROM node:22.12.0-alpine3.19@sha256:40dc4b415c17b85bea9be05314b4a753f45a4e1716bb31c01182e6c53d51a654 | FROM node:20.12.2-alpine3.19 AS base | ||||||
|  | RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh - | ||||||
| USER 0:0 |  | ||||||
|  |  | ||||||
| RUN corepack enable \ |  | ||||||
|     && corepack enable pnpm |  | ||||||
|  |  | ||||||
| RUN apk add --no-cache git~=2.43.4 \ |  | ||||||
|     && git config --add --system safe.directory /mermaid |  | ||||||
|  |  | ||||||
| ENV NODE_OPTIONS="--max_old_space_size=8192" |  | ||||||
|  |  | ||||||
| EXPOSE 9000 3333 |  | ||||||
|   | |||||||
							
								
								
									
										45
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										45
									
								
								README.md
									
									
									
									
									
								
							| @@ -15,7 +15,7 @@ Generate diagrams from markdown-like text. | |||||||
| <a href="https://mermaid.live/"><b>Live Editor!</b></a> | <a href="https://mermaid.live/"><b>Live Editor!</b></a> | ||||||
| </p> | </p> | ||||||
| <p align="center"> | <p align="center"> | ||||||
|  <a href="https://mermaid.js.org">📖 Documentation</a> | <a href="https://mermaid.js.org/intro/">🚀 Getting Started</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/sKeNQX4Wtj" title="Discord invite">🙌 Join Us</a> |  <a href="https://mermaid.js.org">📖 Documentation</a> | <a href="https://mermaid.js.org/intro/">🚀 Getting Started</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/AgrbSrBer3" title="Discord invite">🙌 Join Us</a> | ||||||
| </p> | </p> | ||||||
| <p align="center"> | <p align="center"> | ||||||
| <a href="./README.zh-CN.md">简体中文</a> | <a href="./README.zh-CN.md">简体中文</a> | ||||||
| @@ -33,10 +33,9 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai | |||||||
| [](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop) | [](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop) | ||||||
| [](https://www.jsdelivr.com/package/npm/mermaid) | [](https://www.jsdelivr.com/package/npm/mermaid) | ||||||
| [](https://www.npmjs.com/package/mermaid) | [](https://www.npmjs.com/package/mermaid) | ||||||
| [](https://discord.gg/sKeNQX4Wtj) | [](https://discord.gg/AgrbSrBer3) | ||||||
| [](https://twitter.com/mermaidjs_) | [](https://twitter.com/mermaidjs_) | ||||||
| [](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss) | [](https://argos-ci.com) | ||||||
| [](https://securityscorecards.dev/viewer/?uri=github.com/mermaid-js/mermaid) |  | ||||||
|  |  | ||||||
| <img src="./img/header.png" alt="" /> | <img src="./img/header.png" alt="" /> | ||||||
|  |  | ||||||
| @@ -44,7 +43,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai | |||||||
|  |  | ||||||
| **Thanks to all involved, people committing pull requests, people answering questions! 🙏** | **Thanks to all involved, people committing pull requests, people answering questions! 🙏** | ||||||
|  |  | ||||||
| <a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt='Banner for "The Official Guide to Mermaid.js" book'></a> | <a href="https://mermaid.js.org/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 | ## Table of content | ||||||
|  |  | ||||||
| @@ -83,10 +82,6 @@ You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include- | |||||||
|  |  | ||||||
| For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html). | For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html). | ||||||
|  |  | ||||||
| Our PR Visual Regression Testing is powered by [Argos](https://argos-ci.com/?utm_source=mermaid&utm_campaign=oss) with their generous Open Source plan. It makes the process of reviewing PRs with visual changes a breeze. |  | ||||||
|  |  | ||||||
| [](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss) |  | ||||||
|  |  | ||||||
| In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests. | In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests. | ||||||
|  |  | ||||||
| <a href="https://applitools.com/"> | <a href="https://applitools.com/"> | ||||||
| @@ -253,34 +248,6 @@ pie | |||||||
|  |  | ||||||
| ### Git graph [experimental - <a href="https://mermaid.live/edit#pako:eNqNkMFugzAMhl8F-VyVAR1tOW_aA-zKxSSGRCMJCk6lCvHuNZPKZdM0n-zf3_8r8QIqaIIGMqnB8kfEybQ--y4VnLP8-9RF9Mpkmm40hmlnDKmvkPiH_kfS7nFo_VN0FAf6XwocQGgxa_nGsm1bYEOOWmik1dRjGrmF1q-Cpkkj07u2HCI0PY4zHQATh8-7V9BwTPSE3iwOEd1OjQE1iWkBvk_bzQY7s0Sq4Hs7bHqKo8iGeZqbPN_WR7mpSd1RHpvPVhuMbG7XOq_L-oJlRfW5wteq0qorrpe-PBW9Pr8UJcK6rg-BLYPQ">live editor</a>] | ### Git graph [experimental - <a href="https://mermaid.live/edit#pako:eNqNkMFugzAMhl8F-VyVAR1tOW_aA-zKxSSGRCMJCk6lCvHuNZPKZdM0n-zf3_8r8QIqaIIGMqnB8kfEybQ--y4VnLP8-9RF9Mpkmm40hmlnDKmvkPiH_kfS7nFo_VN0FAf6XwocQGgxa_nGsm1bYEOOWmik1dRjGrmF1q-Cpkkj07u2HCI0PY4zHQATh8-7V9BwTPSE3iwOEd1OjQE1iWkBvk_bzQY7s0Sq4Hs7bHqKo8iGeZqbPN_WR7mpSd1RHpvPVhuMbG7XOq_L-oJlRfW5wteq0qorrpe-PBW9Pr8UJcK6rg-BLYPQ">live editor</a>] | ||||||
|  |  | ||||||
| ``` |  | ||||||
| gitGraph |  | ||||||
|   commit |  | ||||||
|   commit |  | ||||||
|   branch develop |  | ||||||
|   checkout develop |  | ||||||
|   commit |  | ||||||
|   commit |  | ||||||
|   checkout main |  | ||||||
|   merge develop |  | ||||||
|   commit |  | ||||||
|   commit |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ```mermaid |  | ||||||
| gitGraph |  | ||||||
|   commit |  | ||||||
|   commit |  | ||||||
|   branch develop |  | ||||||
|   checkout develop |  | ||||||
|   commit |  | ||||||
|   commit |  | ||||||
|   checkout main |  | ||||||
|   merge develop |  | ||||||
|   commit |  | ||||||
|   commit |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ### Bar chart (using gantt chart) [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>] | ### Bar chart (using gantt chart) [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>] | ||||||
|  |  | ||||||
| ``` | ``` | ||||||
| @@ -447,7 +414,7 @@ For public sites, it can be precarious to retrieve text from users on the intern | |||||||
|  |  | ||||||
| As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing javascript in the code from being executed. This is a great step forward for better security. | As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing javascript in the code from being executed. This is a great step forward for better security. | ||||||
|  |  | ||||||
| _Unfortunately you cannot have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._ | _Unfortunately you can not have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._ | ||||||
|  |  | ||||||
| ## Reporting vulnerabilities | ## Reporting vulnerabilities | ||||||
|  |  | ||||||
| @@ -463,7 +430,7 @@ A quick note from Knut Sveidqvist: | |||||||
| > | > | ||||||
| > _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._ | > _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._ | ||||||
| > | > | ||||||
| > _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_ | > _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_ | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ Mermaid | |||||||
| <a href="https://mermaid.live/"><b>实时编辑器!</b></a> | <a href="https://mermaid.live/"><b>实时编辑器!</b></a> | ||||||
| </p> | </p> | ||||||
| <p align="center"> | <p align="center"> | ||||||
|  <a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/sKeNQX4Wtj" title="Discord invite">🙌 加入我们</a> |  <a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/AgrbSrBer3" title="Discord invite">🙌 加入我们</a> | ||||||
| </p> | </p> | ||||||
| <p align="center"> | <p align="center"> | ||||||
| <a href="./README.md">English</a> | <a href="./README.md">English</a> | ||||||
| @@ -34,7 +34,7 @@ Mermaid | |||||||
| [](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop) | [](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop) | ||||||
| [](https://www.jsdelivr.com/package/npm/mermaid) | [](https://www.jsdelivr.com/package/npm/mermaid) | ||||||
| [](https://www.npmjs.com/package/mermaid) | [](https://www.npmjs.com/package/mermaid) | ||||||
| [](https://discord.gg/sKeNQX4Wtj) | [](https://discord.gg/AgrbSrBer3) | ||||||
| [](https://twitter.com/mermaidjs_) | [](https://twitter.com/mermaidjs_) | ||||||
|  |  | ||||||
| <img src="./img/header.png" alt="" /> | <img src="./img/header.png" alt="" /> | ||||||
| @@ -43,13 +43,13 @@ Mermaid | |||||||
|  |  | ||||||
| **感谢所有参与进来提交 PR,解答疑问的人们! 🙏** | **感谢所有参与进来提交 PR,解答疑问的人们! 🙏** | ||||||
|  |  | ||||||
| <a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt='Banner for "The Official Guide to Mermaid.js" book'></a> | <a href="https://mermaid.js.org/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> | ||||||
|  |  | ||||||
| ## 关于 Mermaid | ## 关于 Mermaid | ||||||
|  |  | ||||||
| <!-- <Main description>   --> | <!-- <Main description>   --> | ||||||
|  |  | ||||||
| Mermaid 是一个基于 JavaScript 的图表绘制工具,通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。Mermaid 诞生的主要目的是让文档的更新能够及时跟上开发进度。 | Mermaid 是一个基于 Javascript 的图表绘制工具,通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。Mermaid 诞生的主要目的是让文档的更新能够及时跟上开发进度。 | ||||||
|  |  | ||||||
| > Doc-Rot 是 Mermaid 致力于解决的一个难题。 | > Doc-Rot 是 Mermaid 致力于解决的一个难题。 | ||||||
|  |  | ||||||
| @@ -358,7 +358,7 @@ _很不幸的是,鱼与熊掌不可兼得,在这个场景下它意味着在 | |||||||
|  |  | ||||||
| > _特别感谢 [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) 这两个优秀的项目,它们提供了图形布局和绘图工具库!_ > _同样感谢 [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提供了时序图语法的使用。 感谢 Jessica Peter 提供了甘特图渲染的灵感。_ > _感谢 [Tyler Long](https://github.com/tylerlong) 从 2017 年四月开始成为了项目的合作者。_ | > _特别感谢 [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) 这两个优秀的项目,它们提供了图形布局和绘图工具库!_ > _同样感谢 [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提供了时序图语法的使用。 感谢 Jessica Peter 提供了甘特图渲染的灵感。_ > _感谢 [Tyler Long](https://github.com/tylerlong) 从 2017 年四月开始成为了项目的合作者。_ | ||||||
| > | > | ||||||
| > _感谢越来越多的 [贡献者们](https://github.com/mermaid-js/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_ | > _感谢越来越多的 [贡献者们](https://github.com/knsv/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_ | ||||||
|  |  | ||||||
| --- | --- | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								__mocks__/d3.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								__mocks__/d3.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3.js'; | ||||||
|  |  | ||||||
|  | export const select = function () { | ||||||
|  |   return new MockedD3(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const selectAll = function () { | ||||||
|  |   return new MockedD3(); | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const curveBasis = 'basis'; | ||||||
|  | export const curveLinear = 'linear'; | ||||||
|  | export const curveCardinal = 'cardinal'; | ||||||
| @@ -1,9 +1,8 @@ | |||||||
|  | import { defineConfig } from 'cypress'; | ||||||
|  | import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin'; | ||||||
|  | import coverage from '@cypress/code-coverage/task'; | ||||||
| import eyesPlugin from '@applitools/eyes-cypress'; | import eyesPlugin from '@applitools/eyes-cypress'; | ||||||
| import { registerArgosTask } from '@argos-ci/cypress/task'; | import { registerArgosTask } from '@argos-ci/cypress/task'; | ||||||
| import coverage from '@cypress/code-coverage/task.js'; |  | ||||||
| import { defineConfig } from 'cypress'; |  | ||||||
| import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin.js'; |  | ||||||
| import cypressSplit from 'cypress-split'; |  | ||||||
|  |  | ||||||
| export default eyesPlugin( | export default eyesPlugin( | ||||||
|   defineConfig({ |   defineConfig({ | ||||||
| @@ -14,7 +13,6 @@ export default eyesPlugin( | |||||||
|       specPattern: 'cypress/integration/**/*.{js,ts}', |       specPattern: 'cypress/integration/**/*.{js,ts}', | ||||||
|       setupNodeEvents(on, config) { |       setupNodeEvents(on, config) { | ||||||
|         coverage(on, config); |         coverage(on, config); | ||||||
|         cypressSplit(on, config); |  | ||||||
|         on('before:browser:launch', (browser, launchOptions) => { |         on('before:browser:launch', (browser, launchOptions) => { | ||||||
|           if (browser.name === 'chrome' && browser.isHeadless) { |           if (browser.name === 'chrome' && browser.isHeadless) { | ||||||
|             launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1'); |             launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1'); | ||||||
| @@ -23,12 +21,11 @@ export default eyesPlugin( | |||||||
|         }); |         }); | ||||||
|         // copy any needed variables from process.env to config.env |         // copy any needed variables from process.env to config.env | ||||||
|         config.env.useAppli = process.env.USE_APPLI ? true : false; |         config.env.useAppli = process.env.USE_APPLI ? true : false; | ||||||
|         config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true'; |         config.env.useArgos = !!process.env.CI; | ||||||
|  |  | ||||||
|         if (config.env.useArgos) { |         if (config.env.useArgos) { | ||||||
|           registerArgosTask(on, config, { |           registerArgosTask(on, config, { | ||||||
|             // Enable upload to Argos only when it runs on CI. |             token: 'fc3a35cf5200db928d65b2047861582d9444032b', | ||||||
|             uploadToArgos: !!process.env.CI, |  | ||||||
|           }); |           }); | ||||||
|         } else { |         } else { | ||||||
|           addMatchImageSnapshotPlugin(on, config); |           addMatchImageSnapshotPlugin(on, config); | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ interface CodeObject { | |||||||
|   mermaid: CypressMermaidConfig; |   mermaid: CypressMermaidConfig; | ||||||
| } | } | ||||||
|  |  | ||||||
| export const utf8ToB64 = (str: string): string => { | const utf8ToB64 = (str: string): string => { | ||||||
|   return Buffer.from(decodeURIComponent(encodeURIComponent(str))).toString('base64'); |   return Buffer.from(decodeURIComponent(encodeURIComponent(str))).toString('base64'); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -22,14 +22,13 @@ const batchId: string = | |||||||
|   'mermaid-batch-' + |   'mermaid-batch-' + | ||||||
|   (Cypress.env('useAppli') |   (Cypress.env('useAppli') | ||||||
|     ? Date.now().toString() |     ? Date.now().toString() | ||||||
|     : (Cypress.env('CYPRESS_COMMIT') ?? Date.now().toString())); |     : Cypress.env('CYPRESS_COMMIT') || Date.now().toString()); | ||||||
|  |  | ||||||
| export const mermaidUrl = ( | export const mermaidUrl = ( | ||||||
|   graphStr: string | string[], |   graphStr: string | string[], | ||||||
|   options: CypressMermaidConfig, |   options: CypressMermaidConfig, | ||||||
|   api: boolean |   api: boolean | ||||||
| ): string => { | ): string => { | ||||||
|   options.handDrawnSeed = 1; |  | ||||||
|   const codeObject: CodeObject = { |   const codeObject: CodeObject = { | ||||||
|     code: graphStr, |     code: graphStr, | ||||||
|     mermaid: options, |     mermaid: options, | ||||||
| @@ -61,7 +60,9 @@ export const imgSnapshotTest = ( | |||||||
|     sequence: { |     sequence: { | ||||||
|       ...(_options.sequence ?? {}), |       ...(_options.sequence ?? {}), | ||||||
|       actorFontFamily: 'courier', |       actorFontFamily: 'courier', | ||||||
|       noteFontFamily: _options.sequence?.noteFontFamily ?? 'courier', |       noteFontFamily: _options.sequence?.noteFontFamily | ||||||
|  |         ? _options.sequence.noteFontFamily | ||||||
|  |         : 'courier', | ||||||
|       messageFontFamily: 'courier', |       messageFontFamily: 'courier', | ||||||
|     }, |     }, | ||||||
|   }; |   }; | ||||||
| @@ -72,7 +73,7 @@ export const imgSnapshotTest = ( | |||||||
|  |  | ||||||
| export const urlSnapshotTest = ( | export const urlSnapshotTest = ( | ||||||
|   url: string, |   url: string, | ||||||
|   options: CypressMermaidConfig = {}, |   options: CypressMermaidConfig, | ||||||
|   _api = false, |   _api = false, | ||||||
|   validation?: any |   validation?: any | ||||||
| ): void => { | ): void => { | ||||||
| @@ -130,10 +131,3 @@ export const verifyScreenshot = (name: string): void => { | |||||||
|     cy.matchImageSnapshot(name); |     cy.matchImageSnapshot(name); | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const verifyNumber = (value: number, expected: number, deltaPercent = 10): void => { |  | ||||||
|   expect(value).to.be.within( |  | ||||||
|     expected * (1 - deltaPercent / 100), |  | ||||||
|     expected * (1 + deltaPercent / 100) |  | ||||||
|   ); |  | ||||||
| }; |  | ||||||
|   | |||||||
| @@ -69,9 +69,7 @@ describe('Configuration', () => { | |||||||
|           .and('include', 'url(#'); |           .and('include', 'url(#'); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|     // This has been broken for a long time, but something about the Cypress environment was |     it('should handle arrowMarkerAbsolute explicitly set to "false" as false', () => { | ||||||
|     // rewriting the URL to be relative, causing the test to incorrectly pass. |  | ||||||
|     it.skip('should handle arrowMarkerAbsolute explicitly set to "false" as false', () => { |  | ||||||
|       renderGraph( |       renderGraph( | ||||||
|         `graph TD |         `graph TD | ||||||
|         A[Christmas] -->|Get money| B(Go shopping) |         A[Christmas] -->|Get money| B(Go shopping) | ||||||
| @@ -114,7 +112,7 @@ describe('Configuration', () => { | |||||||
|           .first() |           .first() | ||||||
|           .should('have.attr', 'marker-end') |           .should('have.attr', 'marker-end') | ||||||
|           .should('exist') |           .should('exist') | ||||||
|           .and('include', 'url(http\\:\\/\\/localhost'); |           .and('include', 'url(http://localhost'); | ||||||
|       }); |       }); | ||||||
|     }); |     }); | ||||||
|     it('should not taint the initial configuration when using multiple directives', () => { |     it('should not taint the initial configuration when using multiple directives', () => { | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ describe('Interaction', () => { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     it('Graph: should handle a click on a node with a bound url', () => { |     it('Graph: should handle a click on a node with a bound url', () => { | ||||||
|       // When there is a URL, `cy.contains()` selects the `a` tag instead of the `span` tag. The .node is a child of `a`, so we have to use `find()` instead of `parent`. |       // When there is a URL, cy.contains selects the a tag instead of the span. The .node is a child of a, so we have to use find instead of parent. | ||||||
|       cy.contains('URLTest1').find('.node').click(); |       cy.contains('URLTest1').find('.node').click(); | ||||||
|       cy.location().should(({ href }) => { |       cy.location().should(({ href }) => { | ||||||
|         expect(href).to.eq('http://localhost:9000/empty.html'); |         expect(href).to.eq('http://localhost:9000/empty.html'); | ||||||
| @@ -146,7 +146,7 @@ describe('Interaction', () => { | |||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   describe('Interaction - security level other, misspelling', () => { |   describe('Interaction - security level other, missspelling', () => { | ||||||
|     beforeEach(() => { |     beforeEach(() => { | ||||||
|       cy.visit('http://localhost:9000/click_security_other.html'); |       cy.visit('http://localhost:9000/click_security_other.html'); | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { imgSnapshotTest, mermaidUrl, utf8ToB64 } from '../../helpers/util.ts'; | import { mermaidUrl } from '../../helpers/util.ts'; | ||||||
| describe('XSS', () => { | describe('XSS', () => { | ||||||
|   it('should handle xss in tags', () => { |   it('should handle xss in tags', () => { | ||||||
|     const str = |     const str = | ||||||
| @@ -141,37 +141,4 @@ describe('XSS', () => { | |||||||
|     cy.wait(1000); |     cy.wait(1000); | ||||||
|     cy.get('#the-malware').should('not.exist'); |     cy.get('#the-malware').should('not.exist'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should sanitize icon labels in architecture diagrams', () => { |  | ||||||
|     const str = JSON.stringify({ |  | ||||||
|       code: `architecture-beta |  | ||||||
|     group api(cloud)[API] |  | ||||||
|     service db "<img src=x onerror=\\"xssAttack()\\">" [Database] in api`, |  | ||||||
|     }); |  | ||||||
|     imgSnapshotTest(utf8ToB64(str), {}, true); |  | ||||||
|     cy.wait(1000); |  | ||||||
|     cy.get('#the-malware').should('not.exist'); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should sanitize katex blocks', () => { |  | ||||||
|     const str = JSON.stringify({ |  | ||||||
|       code: `sequenceDiagram |  | ||||||
|     participant A as Alice<img src="x" onerror="xssAttack()">$$\\text{Alice}$$ |  | ||||||
|     A->>John: Hello John, how are you?`, |  | ||||||
|     }); |  | ||||||
|     imgSnapshotTest(utf8ToB64(str), {}, true); |  | ||||||
|     cy.wait(1000); |  | ||||||
|     cy.get('#the-malware').should('not.exist'); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should sanitize labels', () => { |  | ||||||
|     const str = JSON.stringify({ |  | ||||||
|       code: `erDiagram |  | ||||||
|     "<img src=x onerror=xssAttack()>" ||--|| ENTITY2 : "<img src=x onerror=xssAttack()>" |  | ||||||
|     `, |  | ||||||
|     }); |  | ||||||
|     imgSnapshotTest(utf8ToB64(str), {}, true); |  | ||||||
|     cy.wait(1000); |  | ||||||
|     cy.get('#the-malware').should('not.exist'); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,252 +0,0 @@ | |||||||
| import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| describe.skip('architecture diagram', () => { |  | ||||||
|   it('should render a simple architecture diagram with groups', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 group api(cloud)[API] |  | ||||||
|  |  | ||||||
|                 service db(database)[Database] in api |  | ||||||
|                 service disk1(disk)[Storage] in api |  | ||||||
|                 service disk2(disk)[Storage] in api |  | ||||||
|                 service server(server)[Server] in api |  | ||||||
|                 service gateway(internet)[Gateway]  |  | ||||||
|  |  | ||||||
|                 db L--R server |  | ||||||
|                 disk1 T--B server |  | ||||||
|                 disk2 T--B db |  | ||||||
|                 server T--B gateway |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render a simple architecture diagram with titleAndAccessibilities', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|           title Simple Architecture Diagram |  | ||||||
|           accTitle: Accessibility Title |  | ||||||
|           accDescr: Accessibility Description |  | ||||||
|           group api(cloud)[API] |  | ||||||
|  |  | ||||||
|           service db(database)[Database] in api |  | ||||||
|           service disk1(disk)[Storage] in api |  | ||||||
|           service disk2(disk)[Storage] in api |  | ||||||
|           service server(server)[Server] in api |  | ||||||
|  |  | ||||||
|           db:L -- R:server |  | ||||||
|           disk1:T -- B:server |  | ||||||
|           disk2:T -- B:db |  | ||||||
|       ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with groups within groups', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 group api[API] |  | ||||||
|                 group public[Public API] in api |  | ||||||
|                 group private[Private API] in api |  | ||||||
|          |  | ||||||
|                 service serv1(server)[Server] in public |  | ||||||
|          |  | ||||||
|                 service serv2(server)[Server] in private |  | ||||||
|                 service db(database)[Database] in private |  | ||||||
|          |  | ||||||
|                 service gateway(internet)[Gateway] in api |  | ||||||
|          |  | ||||||
|                 serv1 B--T serv2 |  | ||||||
|                 serv2 L--R db |  | ||||||
|                 serv1 L--R gateway |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with the fallback icon', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 service unknown(iconnamedoesntexist)[Unknown Icon] |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with split directioning', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 service db(database)[Database] |  | ||||||
|                 service s3(disk)[Storage] |  | ||||||
|                 service serv1(server)[Server 1] |  | ||||||
|                 service serv2(server)[Server 2] |  | ||||||
|                 service disk(disk)[Disk] |  | ||||||
|          |  | ||||||
|                 db L--R s3 |  | ||||||
|                 serv1 L--T s3 |  | ||||||
|                 serv2 L--B s3 |  | ||||||
|                 serv1 T--B disk |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with directional arrows', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 service servC(server)[Server 1] |  | ||||||
|                 service servL(server)[Server 2] |  | ||||||
|                 service servR(server)[Server 3] |  | ||||||
|                 service servT(server)[Server 4] |  | ||||||
|                 service servB(server)[Server 5] |  | ||||||
|          |  | ||||||
|                 servC (L--R) servL |  | ||||||
|                 servC (R--L) servR |  | ||||||
|                 servC (T--B) servT |  | ||||||
|                 servC (B--T) servB |  | ||||||
|          |  | ||||||
|                 servL (T--L) servT |  | ||||||
|                 servL (B--L) servB |  | ||||||
|                 servR (T--R) servT |  | ||||||
|                 servR (B--R) servB |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with group edges', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 group left_group(cloud)[Left] |  | ||||||
|                 group right_group(cloud)[Right] |  | ||||||
|                 group top_group(cloud)[Top] |  | ||||||
|                 group bottom_group(cloud)[Bottom] |  | ||||||
|                 group center_group(cloud)[Center] |  | ||||||
|          |  | ||||||
|                 service left_disk(disk)[Disk] in left_group |  | ||||||
|                 service right_disk(disk)[Disk] in right_group |  | ||||||
|                 service top_disk(disk)[Disk] in top_group |  | ||||||
|                 service bottom_disk(disk)[Disk] in bottom_group |  | ||||||
|                 service center_disk(disk)[Disk] in center_group |  | ||||||
|          |  | ||||||
|                 left_disk{group} (R--L) center_disk{group} |  | ||||||
|                 right_disk{group} (L--R) center_disk{group} |  | ||||||
|                 top_disk{group} (B--T) center_disk{group} |  | ||||||
|                 bottom_disk{group} (T--B) center_disk{group} |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with edge labels', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 service servC(server)[Server 1] |  | ||||||
|                 service servL(server)[Server 2] |  | ||||||
|                 service servR(server)[Server 3] |  | ||||||
|                 service servT(server)[Server 4] |  | ||||||
|                 service servB(server)[Server 5] |  | ||||||
|          |  | ||||||
|                 servC L-[Label]-R servL |  | ||||||
|                 servC R-[Label]-L servR |  | ||||||
|                 servC T-[Label]-B servT |  | ||||||
|                 servC B-[Label]-T servB |  | ||||||
|          |  | ||||||
|                 servL T-[Label]-L servT |  | ||||||
|                 servL B-[Label]-L servB |  | ||||||
|                 servR T-[Label]-R servT |  | ||||||
|                 servR B-[Label]-R servB |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with simple junction edges', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 service left_disk(disk)[Disk] |  | ||||||
|                 service top_disk(disk)[Disk] |  | ||||||
|                 service bottom_disk(disk)[Disk] |  | ||||||
|                 service top_gateway(internet)[Gateway] |  | ||||||
|                 service bottom_gateway(internet)[Gateway] |  | ||||||
|                 junction juncC |  | ||||||
|                 junction juncR |  | ||||||
|          |  | ||||||
|                 left_disk R--L juncC |  | ||||||
|                 top_disk B--T juncC |  | ||||||
|                 bottom_disk T--B juncC |  | ||||||
|                 juncC R--L juncR |  | ||||||
|                 top_gateway B--T juncR |  | ||||||
|                 bottom_gateway T--B juncR |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render an architecture diagram with complex junction edges', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|                 group left |  | ||||||
|                 group right |  | ||||||
|                 service left_disk(disk)[Disk] in left |  | ||||||
|                 service top_disk(disk)[Disk] in left |  | ||||||
|                 service bottom_disk(disk)[Disk] in left |  | ||||||
|                 service top_gateway(internet)[Gateway] in right |  | ||||||
|                 service bottom_gateway(internet)[Gateway] in right |  | ||||||
|                 junction juncC in left |  | ||||||
|                 junction juncR in right |  | ||||||
|          |  | ||||||
|                 left_disk R--L juncC |  | ||||||
|                 top_disk B--T juncC |  | ||||||
|                 bottom_disk T--B juncC |  | ||||||
|          |  | ||||||
|          |  | ||||||
|                 top_gateway (B--T juncR |  | ||||||
|                 bottom_gateway (T--B juncR |  | ||||||
|          |  | ||||||
|                 juncC{group} R--L) juncR{group} |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render an architecture diagram with a reasonable height', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `architecture-beta |  | ||||||
|               group federated(cloud)[Federated Environment] |  | ||||||
|                   service server1(server)[System] in federated |  | ||||||
|                   service edge(server)[Edge Device] in federated |  | ||||||
|                   server1:R -- L:edge |  | ||||||
|  |  | ||||||
|               group on_prem(cloud)[Hub] |  | ||||||
|                   service firewall(server)[Firewall Device] in on_prem |  | ||||||
|                   service server(server)[Server] in on_prem |  | ||||||
|                   firewall:R -- L:server |  | ||||||
|  |  | ||||||
|                   service db1(database)[db1] in on_prem |  | ||||||
|                   service db2(database)[db2] in on_prem |  | ||||||
|                   service db3(database)[db3] in on_prem |  | ||||||
|                   service db4(database)[db4] in on_prem |  | ||||||
|                   service db5(database)[db5] in on_prem |  | ||||||
|                   service db6(database)[db6] in on_prem |  | ||||||
|  |  | ||||||
|                   junction mid in on_prem |  | ||||||
|                   server:B -- T:mid |  | ||||||
|  |  | ||||||
|                   junction 1Leftofmid in on_prem |  | ||||||
|                   1Leftofmid:R -- L:mid |  | ||||||
|                   1Leftofmid:B -- T:db1 |  | ||||||
|  |  | ||||||
|                   junction 2Leftofmid in on_prem |  | ||||||
|                   2Leftofmid:R -- L:1Leftofmid |  | ||||||
|                   2Leftofmid:B -- T:db2 |  | ||||||
|  |  | ||||||
|                   junction 3Leftofmid in on_prem |  | ||||||
|                   3Leftofmid:R -- L:2Leftofmid |  | ||||||
|                   3Leftofmid:B -- T:db3 |  | ||||||
|  |  | ||||||
|                   junction 1RightOfMid in on_prem |  | ||||||
|                   mid:R -- L:1RightOfMid |  | ||||||
|                   1RightOfMid:B -- T:db4 |  | ||||||
|                    |  | ||||||
|                   junction 2RightOfMid in on_prem |  | ||||||
|                   1RightOfMid:R -- L:2RightOfMid |  | ||||||
|                   2RightOfMid:B -- T:db5         |  | ||||||
|                    |  | ||||||
|                   junction 3RightOfMid in on_prem |  | ||||||
|                   2RightOfMid:R -- L:3RightOfMid |  | ||||||
|                   3RightOfMid:B -- T:db6          |  | ||||||
|  |  | ||||||
|                   edge:R -- L:firewall |  | ||||||
|       ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // Skipped as the layout is not deterministic, and causes issues in E2E tests. |  | ||||||
| describe.skip('architecture - external', () => { |  | ||||||
|   it('should allow adding external icons', () => { |  | ||||||
|     urlSnapshotTest('http://localhost:9000/architecture-external.html'); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -14,9 +14,9 @@ describe('Block diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('BL2: should handle columns statement in sub-blocks', () => { |   it('BL2: should handle colums statement in sub-blocks', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   id1["Hello"] |   id1["Hello"] | ||||||
|   block |   block | ||||||
|     columns 3 |     columns 3 | ||||||
| @@ -30,9 +30,9 @@ describe('Block diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('BL3: should align block widths and handle columns statement in sub-blocks', () => { |   it('BL3: should align block widths and handle colums statement in sub-blocks', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   block |   block | ||||||
|     columns 1 |     columns 1 | ||||||
|     id1 |     id1 | ||||||
| @@ -46,9 +46,9 @@ describe('Block diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('BL4: should align block widths and handle columns statements in deeper sub-blocks then 1 level', () => { |   it('BL4: should align block widths and handle colums statements in deeper sub-blocks then 1 level', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   columns 1 |   columns 1 | ||||||
|   block |   block | ||||||
|     columns 1 |     columns 1 | ||||||
| @@ -66,9 +66,9 @@ describe('Block diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('BL5: should align block widths and handle columns statements in deeper sub-blocks then 1 level (alt)', () => { |   it('BL5: should align block widths and handle colums statements in deeper sub-blocks then 1 level (alt)', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   columns 1 |   columns 1 | ||||||
|   block |   block | ||||||
|     id1 |     id1 | ||||||
| @@ -87,7 +87,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL6: should handle block arrows and spece statements', () => { |   it('BL6: should handle block arrows and spece statements', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     columns 3 |     columns 3 | ||||||
|     space:3 |     space:3 | ||||||
|     ida idb idc |     ida idb idc | ||||||
| @@ -106,7 +106,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL7: should handle different types of edges', () => { |   it('BL7: should handle different types of edges', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       columns 3 |       columns 3 | ||||||
|       A space:5 |       A space:5 | ||||||
|       A --o B |       A --o B | ||||||
| @@ -119,7 +119,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL8: should handle sub-blocks without columns statements', () => { |   it('BL8: should handle sub-blocks without columns statements', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       columns 2 |       columns 2 | ||||||
|       C A B |       C A B | ||||||
|       block |       block | ||||||
| @@ -133,7 +133,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL9: should handle edges from blocks in sub blocks to other blocks', () => { |   it('BL9: should handle edges from blocks in sub blocks to other blocks', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       columns 3 |       columns 3 | ||||||
|       B space |       B space | ||||||
|       block |       block | ||||||
| @@ -147,7 +147,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL10: should handle edges from composite blocks', () => { |   it('BL10: should handle edges from composite blocks', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       columns 3 |       columns 3 | ||||||
|       B space |       B space | ||||||
|       block BL |       block BL | ||||||
| @@ -161,7 +161,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL11: should handle edges to composite blocks', () => { |   it('BL11: should handle edges to composite blocks', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       columns 3 |       columns 3 | ||||||
|       B space |       B space | ||||||
|       block BL |       block BL | ||||||
| @@ -175,7 +175,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL12: edges should handle labels', () => { |   it('BL12: edges should handle labels', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       A |       A | ||||||
|       space |       space | ||||||
|       A -- "apa" --> E |       A -- "apa" --> E | ||||||
| @@ -186,7 +186,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL13: should handle block arrows in different directions', () => { |   it('BL13: should handle block arrows in different directions', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       columns 3 |       columns 3 | ||||||
|       space blockArrowId1<["down"]>(down) space |       space blockArrowId1<["down"]>(down) space | ||||||
|       blockArrowId2<["right"]>(right) blockArrowId3<["Sync"]>(x, y) blockArrowId4<["left"]>(left) |       blockArrowId2<["right"]>(right) blockArrowId3<["Sync"]>(x, y) blockArrowId4<["left"]>(left) | ||||||
| @@ -199,7 +199,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL14: should style statements and class statements', () => { |   it('BL14: should style statements and class statements', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     A |     A | ||||||
|     B |     B | ||||||
|     classDef blue fill:#66f,stroke:#333,stroke-width:2px; |     classDef blue fill:#66f,stroke:#333,stroke-width:2px; | ||||||
| @@ -212,7 +212,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL15: width alignment - D and E should share available space', () => { |   it('BL15: width alignment - D and E should share available space', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   block |   block | ||||||
|     D |     D | ||||||
|     E |     E | ||||||
| @@ -225,7 +225,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL16: width alignment - C should be as wide as the composite block', () => { |   it('BL16: width alignment - C should be as wide as the composite block', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   block |   block | ||||||
|     A("This is the text") |     A("This is the text") | ||||||
|     B |     B | ||||||
| @@ -236,9 +236,9 @@ describe('Block diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('BL17: width alignment - blocks should be equal in width', () => { |   it('BL17: width alignment - blocks shold be equal in width', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     A("This is the text") |     A("This is the text") | ||||||
|     B |     B | ||||||
|     C |     C | ||||||
| @@ -249,7 +249,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL18: block types 1 - square, rounded and circle', () => { |   it('BL18: block types 1 - square, rounded and circle', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     A["square"] |     A["square"] | ||||||
|     B("rounded") |     B("rounded") | ||||||
|     C(("circle")) |     C(("circle")) | ||||||
| @@ -260,7 +260,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL19: block types 2 - odd, diamond and hexagon', () => { |   it('BL19: block types 2 - odd, diamond and hexagon', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     A>"rect_left_inv_arrow"] |     A>"rect_left_inv_arrow"] | ||||||
|     B{"diamond"} |     B{"diamond"} | ||||||
|     C{{"hexagon"}} |     C{{"hexagon"}} | ||||||
| @@ -271,7 +271,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL20: block types 3 - stadium', () => { |   it('BL20: block types 3 - stadium', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     A(["stadium"]) |     A(["stadium"]) | ||||||
|       `, |       `, | ||||||
|       {} |       {} | ||||||
| @@ -280,7 +280,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => { |   it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     A[/"lean right"/] |     A[/"lean right"/] | ||||||
|     B[\"lean left"\] |     B[\"lean left"\] | ||||||
|     C[/"trapezoid"\] |     C[/"trapezoid"\] | ||||||
| @@ -292,7 +292,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL22: block types 1 - square, rounded and circle', () => { |   it('BL22: block types 1 - square, rounded and circle', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|     A["square"] |     A["square"] | ||||||
|     B("rounded") |     B("rounded") | ||||||
|     C(("circle")) |     C(("circle")) | ||||||
| @@ -303,7 +303,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL23: sizing - it should be possible to make a block wider', () => { |   it('BL23: sizing - it should be possible to make a block wider', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       A("rounded"):2 |       A("rounded"):2 | ||||||
|       B:2 |       B:2 | ||||||
|       C |       C | ||||||
| @@ -314,7 +314,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL24: sizing - it should be possible to make a composite block wider', () => { |   it('BL24: sizing - it should be possible to make a composite block wider', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|       block:2 |       block:2 | ||||||
|         A |         A | ||||||
|       end |       end | ||||||
| @@ -326,7 +326,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL25: block in the middle with space on each side', () => { |   it('BL25: block in the middle with space on each side', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|         columns 3 |         columns 3 | ||||||
|         space |         space | ||||||
|         middle["In the middle"] |         middle["In the middle"] | ||||||
| @@ -337,7 +337,7 @@ describe('Block diagram', () => { | |||||||
|   }); |   }); | ||||||
|   it('BL26: space and an edge', () => { |   it('BL26: space and an edge', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   columns 5 |   columns 5 | ||||||
|     A space B |     A space B | ||||||
|     A --x B |     A --x B | ||||||
| @@ -347,7 +347,7 @@ describe('Block diagram', () => { | |||||||
|   }); |   }); | ||||||
|   it('BL27: block sizes for regular blocks', () => { |   it('BL27: block sizes for regular blocks', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   columns 3 |   columns 3 | ||||||
|     a["A wide one"] b:2 c:2 d |     a["A wide one"] b:2 c:2 d | ||||||
|       `, |       `, | ||||||
| @@ -356,7 +356,7 @@ describe('Block diagram', () => { | |||||||
|   }); |   }); | ||||||
|   it('BL28: composite block with a set width - f should use the available space', () => { |   it('BL28: composite block with a set width - f should use the available space', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   columns 3 |   columns 3 | ||||||
|   a:3 |   a:3 | ||||||
|   block:e:3 |   block:e:3 | ||||||
| @@ -370,7 +370,7 @@ describe('Block diagram', () => { | |||||||
|  |  | ||||||
|   it('BL29: composite block with a set width - f and g should split the available space', () => { |   it('BL29: composite block with a set width - f and g should split the available space', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `block |       `block-beta | ||||||
|   columns 3 |   columns 3 | ||||||
|   a:3 |   a:3 | ||||||
|   block:e:3 |   block:e:3 | ||||||
| @@ -384,28 +384,4 @@ describe('Block diagram', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('BL30: block should overflow if too wide for columns', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `block-beta |  | ||||||
|   columns 2 |  | ||||||
|   fit:2 |  | ||||||
|   overflow:3 |  | ||||||
|   short:1 |  | ||||||
|   also_overflow:2 |  | ||||||
| `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('BL31: edge without arrow syntax should render with no arrowheads', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `block-beta |  | ||||||
|   a |  | ||||||
|   b |  | ||||||
|   a --- b |  | ||||||
| `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -581,63 +581,4 @@ class C13["With Città foreign language"] | |||||||
|       { logLevel: 1, flowchart: { htmlLabels: false } } |       { logLevel: 1, flowchart: { htmlLabels: false } } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('renders a class diagram with a generic class in a namespace', () => { |  | ||||||
|     const diagramDefinition = ` |  | ||||||
|       classDiagram-v2 |  | ||||||
|       namespace Company.Project.Module { |  | ||||||
|         class GenericClass~T~ { |  | ||||||
|           +addItem(item: T) |  | ||||||
|           +getItem() T |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     `; |  | ||||||
|  |  | ||||||
|     imgSnapshotTest(diagramDefinition); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('renders a class diagram with nested namespaces and relationships', () => { |  | ||||||
|     const diagramDefinition = ` |  | ||||||
|       classDiagram-v2 |  | ||||||
|       namespace Company.Project.Module.SubModule { |  | ||||||
|         class Report { |  | ||||||
|           +generatePDF(data: List) |  | ||||||
|           +generateCSV(data: List) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       namespace Company.Project.Module { |  | ||||||
|         class Admin { |  | ||||||
|           +generateReport() |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       Admin --> Report : generates |  | ||||||
|     `; |  | ||||||
|  |  | ||||||
|     imgSnapshotTest(diagramDefinition); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('renders a class diagram with multiple classes and relationships in a namespace', () => { |  | ||||||
|     const diagramDefinition = ` |  | ||||||
|       classDiagram-v2 |  | ||||||
|       namespace Company.Project.Module { |  | ||||||
|         class User { |  | ||||||
|           +login(username: String, password: String) |  | ||||||
|           +logout() |  | ||||||
|         } |  | ||||||
|         class Admin { |  | ||||||
|           +addUser(user: User) |  | ||||||
|           +removeUser(user: User) |  | ||||||
|           +generateReport() |  | ||||||
|         } |  | ||||||
|         class Report { |  | ||||||
|           +generatePDF(reportData: List) |  | ||||||
|           +generateCSV(reportData: List) |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       Admin --> User : manages |  | ||||||
|       Admin --> Report : generates |  | ||||||
|     `; |  | ||||||
|  |  | ||||||
|     imgSnapshotTest(diagramDefinition); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -429,7 +429,7 @@ describe('Class diagram', () => { | |||||||
|     classDiagram |     classDiagram | ||||||
|       class \`This\nTitle\nHas\nMany\nNewlines\` { |       class \`This\nTitle\nHas\nMany\nNewlines\` { | ||||||
|         +String Also |         +String Also | ||||||
|         -String Many |         -Stirng Many | ||||||
|         #int Members |         #int Members | ||||||
|         +And() |         +And() | ||||||
|         -Many() |         -Many() | ||||||
| @@ -443,7 +443,7 @@ describe('Class diagram', () => { | |||||||
|     classDiagram |     classDiagram | ||||||
|       class \`This\nTitle\nHas\nMany\nNewlines\` { |       class \`This\nTitle\nHas\nMany\nNewlines\` { | ||||||
|         +String Also |         +String Also | ||||||
|         -String Many |         -Stirng Many | ||||||
|         #int Members |         #int Members | ||||||
|         +And() |         +And() | ||||||
|         -Many() |         -Many() | ||||||
| @@ -459,7 +459,7 @@ describe('Class diagram', () => { | |||||||
|       namespace testingNamespace { |       namespace testingNamespace { | ||||||
|       class \`This\nTitle\nHas\nMany\nNewlines\` { |       class \`This\nTitle\nHas\nMany\nNewlines\` { | ||||||
|         +String Also |         +String Also | ||||||
|         -String Many |         -Stirng Many | ||||||
|         #int Members |         #int Members | ||||||
|         +And() |         +And() | ||||||
|         -Many() |         -Many() | ||||||
| @@ -495,34 +495,4 @@ describe('Class diagram', () => { | |||||||
|       cy.get('a').should('have.attr', 'target', '_blank').should('have.attr', 'rel', 'noopener'); |       cy.get('a').should('have.attr', 'target', '_blank').should('have.attr', 'rel', 'noopener'); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   describe('Include char sequence "graph" in text (#6795)', () => { |  | ||||||
|     it('has a label with char sequence "graph"', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         classDiagram |  | ||||||
|           class Person { |  | ||||||
|             +String name |  | ||||||
|             -Int id |  | ||||||
|             #double age |  | ||||||
|             +Text demographicProfile |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { flowchart: { defaultRenderer: 'elk' } } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should handle backticks for namespace and class names', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|       classDiagram |  | ||||||
|           namespace \`A::B\` { |  | ||||||
|               class \`IPC::Sender\` |  | ||||||
|           } |  | ||||||
|           RenderProcessHost --|> \`IPC::Sender\` |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,652 +0,0 @@ | |||||||
| import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| const testOptions = [ |  | ||||||
|   { description: '', options: { logLevel: 1 } }, |  | ||||||
|   { description: 'ELK: ', options: { logLevel: 1, layout: 'elk' } }, |  | ||||||
|   { description: 'HD: ', options: { logLevel: 1, look: 'handDrawn' } }, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| describe('Entity Relationship Diagram Unified', () => { |  | ||||||
|   testOptions.forEach(({ description, options }) => { |  | ||||||
|     it(`${description}should render a simple ER diagram`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           ORDER ||--|{ LINE-ITEM : contains |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a simple ER diagram without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           ORDER ||--|{ LINE-ITEM : contains |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with a recursive relationship`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER ||..o{ CUSTOMER : refers |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           ORDER ||--|{ LINE-ITEM : contains |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with multiple relationships between the same two entities`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER ||--|{ ADDRESS : "invoiced at" |  | ||||||
|           CUSTOMER ||--|{ ADDRESS : "receives goods at" |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a cyclical ER diagram`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           A ||--|{ B : likes |  | ||||||
|           B ||--|{ C : likes |  | ||||||
|           C ||--|{ A : likes |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a not-so-simple ER diagram`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER }|..|{ DELIVERY-ADDRESS : has |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           CUSTOMER ||--o{ INVOICE : "liable for" |  | ||||||
|           DELIVERY-ADDRESS ||--o{ ORDER : receives |  | ||||||
|           INVOICE ||--|{ ORDER : covers |  | ||||||
|           ORDER ||--|{ ORDER-ITEM : includes |  | ||||||
|           PRODUCT-CATEGORY ||--|{ PRODUCT : contains |  | ||||||
|           PRODUCT ||--o{ ORDER-ITEM : "ordered in" |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a not-so-simple ER diagram without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER }|..|{ DELIVERY-ADDRESS : has |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           CUSTOMER ||--o{ INVOICE : "liable for" |  | ||||||
|           DELIVERY-ADDRESS ||--o{ ORDER : receives |  | ||||||
|           INVOICE ||--|{ ORDER : covers |  | ||||||
|           ORDER ||--|{ ORDER-ITEM : includes |  | ||||||
|           PRODUCT-CATEGORY ||--|{ PRODUCT : contains |  | ||||||
|           PRODUCT ||--o{ ORDER-ITEM : "ordered in" |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render multiple ER diagrams`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         [ |  | ||||||
|           ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           ORDER ||--|{ LINE-ITEM : contains |  | ||||||
|         `, |  | ||||||
|           ` |  | ||||||
|       erDiagram |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           ORDER ||--|{ LINE-ITEM : contains |  | ||||||
|         `, |  | ||||||
|         ], |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with blank or empty labels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           BOOK }|..|{ AUTHOR : "" |  | ||||||
|           BOOK }|..|{ GENRE : " " |  | ||||||
|           AUTHOR }|..|{ GENRE : "  " |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities that have no relationships`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           DEAD_PARROT |  | ||||||
|           HERMIT |  | ||||||
|           RECLUSE |  | ||||||
|           SOCIALITE }o--o{ SOCIALITE : "interacts with" |  | ||||||
|           RECLUSE }o--o{ SOCIALITE : avoids |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with and without attributes`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           BOOK { string title } |  | ||||||
|           AUTHOR }|..|{ BOOK : writes |  | ||||||
|           BOOK { float price } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with generic and array attributes`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           BOOK { |  | ||||||
|             string title |  | ||||||
|             string[] authors |  | ||||||
|             type~T~ type |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with generic and array attributes without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           BOOK { |  | ||||||
|             string title |  | ||||||
|             string[] authors |  | ||||||
|             type~T~ type |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with length in attributes type`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CLUSTER { |  | ||||||
|             varchar(99) name |  | ||||||
|             string(255) description |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with length in attributes type without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           CLUSTER { |  | ||||||
|             varchar(99) name |  | ||||||
|             string(255) description |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities and attributes with big and small entity names`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           PRIVATE_FINANCIAL_INSTITUTION { |  | ||||||
|             string name |  | ||||||
|             int    turnover |  | ||||||
|           } |  | ||||||
|           PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs |  | ||||||
|           EMPLOYEE { bool officer_of_firm } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities and attributes with big and small entity names without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           PRIVATE_FINANCIAL_INSTITUTION { |  | ||||||
|             string name |  | ||||||
|             int    turnover |  | ||||||
|           } |  | ||||||
|           PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs |  | ||||||
|           EMPLOYEE { bool officer_of_firm } |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with attributes that begin with asterisk`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           BOOK { |  | ||||||
|             int         *id |  | ||||||
|             string      name |  | ||||||
|             varchar(99) summary |  | ||||||
|           } |  | ||||||
|           BOOK }o..o{ STORE : soldBy |  | ||||||
|           STORE { |  | ||||||
|             int         *id |  | ||||||
|             string      name |  | ||||||
|             varchar(50) address |  | ||||||
|           } |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with attributes that begin with asterisk without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           BOOK { |  | ||||||
|             int         *id |  | ||||||
|             string      name |  | ||||||
|             varchar(99) summary |  | ||||||
|           } |  | ||||||
|           BOOK }o..o{ STORE : soldBy |  | ||||||
|           STORE { |  | ||||||
|             int         *id |  | ||||||
|             string      name |  | ||||||
|             varchar(50) address |  | ||||||
|           } |  | ||||||
|           `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with keys`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME { |  | ||||||
|           string name PK |  | ||||||
|         } |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes |  | ||||||
|         BOOK { |  | ||||||
|             float price |  | ||||||
|             string author FK |  | ||||||
|             string title PK |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with keys without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME { |  | ||||||
|           string name PK |  | ||||||
|         } |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes |  | ||||||
|         BOOK { |  | ||||||
|             float price |  | ||||||
|             string author FK |  | ||||||
|             string title PK |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with comments`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME { |  | ||||||
|           string name "comment" |  | ||||||
|         } |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes |  | ||||||
|         BOOK { |  | ||||||
|             string author |  | ||||||
|             string title "author comment" |  | ||||||
|             float price "price comment" |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with comments without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME { |  | ||||||
|           string name "comment" |  | ||||||
|         } |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes |  | ||||||
|         BOOK { |  | ||||||
|             string author |  | ||||||
|             string title "author comment" |  | ||||||
|             float price "price comment" |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with keys and comments`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME { |  | ||||||
|           string name PK "comment" |  | ||||||
|         } |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes |  | ||||||
|         BOOK { |  | ||||||
|             string description |  | ||||||
|             float price "price comment" |  | ||||||
|             string title PK "title comment" |  | ||||||
|             string author FK |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with keys and comments without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME { |  | ||||||
|           string name PK "comment" |  | ||||||
|         } |  | ||||||
|         AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes |  | ||||||
|         BOOK { |  | ||||||
|             string description |  | ||||||
|             float price "price comment" |  | ||||||
|             string title PK "title comment" |  | ||||||
|             string author FK |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with aliases`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         T1 one or zero to one or more T2 : test |  | ||||||
|         T2 one or many optionally to zero or one T3 : test |  | ||||||
|         T3 zero or more to zero or many T4 : test |  | ||||||
|         T4 many(0) to many(1) T5 : test |  | ||||||
|         T5 many optionally to one T6 : test |  | ||||||
|         T6 only one optionally to only one T1 : test |  | ||||||
|         T4 0+ to 1+ T6 : test |  | ||||||
|         T1 1 to 1 T3 : test |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a simple ER diagram with a title`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `--- |  | ||||||
|   title: simple ER diagram |  | ||||||
|   --- |  | ||||||
|   erDiagram |  | ||||||
|   CUSTOMER ||--o{ ORDER : places |  | ||||||
|   ORDER ||--|{ LINE-ITEM : contains |  | ||||||
|   `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with entity name aliases`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         p[Person] { |  | ||||||
|           varchar(64) firstName |  | ||||||
|           varchar(64) lastName |  | ||||||
|         } |  | ||||||
|         c["Customer Account"] { |  | ||||||
|           varchar(128) email |  | ||||||
|         } |  | ||||||
|         p ||--o| c : has |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render relationship labels with line breaks`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|         p[Person] { |  | ||||||
|             string firstName |  | ||||||
|             string lastName |  | ||||||
|         } |  | ||||||
|         a["Customer Account"] { |  | ||||||
|             string email |  | ||||||
|         } |  | ||||||
|    |  | ||||||
|         b["Customer Account Secondary"] { |  | ||||||
|           string email |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         c["Customer Account Tertiary"] { |  | ||||||
|           string email |  | ||||||
|         } |  | ||||||
|          |  | ||||||
|         d["Customer Account Nth"] { |  | ||||||
|           string email |  | ||||||
|         } |  | ||||||
|    |  | ||||||
|         p ||--o| a : "has<br />one" |  | ||||||
|         p ||--o| b : "has<br />one<br />two" |  | ||||||
|         p ||--o| c : "has<br />one<br/>two<br />three" |  | ||||||
|         p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth" |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with unicode text`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           _**testẽζ➕Ø😀㌕ぼ**_ { |  | ||||||
|               *__List~List~int~~sdfds__* **driversLicense** PK "***The l😀icense #***" |  | ||||||
|               *string(99)~T~~~~~~* firstName "Only __99__ <br>characters are a<br>llowed dsfsdfsdfsdfs" |  | ||||||
|               string last*Name* |  | ||||||
|               string __phone__ UK |  | ||||||
|               int _age_ |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with unicode text without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       erDiagram |  | ||||||
|           _**testẽζ➕Ø😀㌕ぼ**_ { |  | ||||||
|               *__List~List~int~~sdfds__* **driversLicense** PK "***The l😀icense #***" |  | ||||||
|               *string(99)~T~~~~~~* firstName "Only __99__ <br>characters are a<br>llowed dsfsdfsdfsdfs" |  | ||||||
|               string last*Name* |  | ||||||
|               string __phone__ UK |  | ||||||
|               int _age_ |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with relationships with unicode text`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|           erDiagram |  | ||||||
|             person[😀] { |  | ||||||
|                 string *first*Name |  | ||||||
|                 string _**last**Name_ |  | ||||||
|             } |  | ||||||
|             a["*Customer Account*"] { |  | ||||||
|                 **string** ema*i*l |  | ||||||
|             } |  | ||||||
|             person ||--o| a : __hẽ😀__ |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with relationships with unicode text without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|           erDiagram |  | ||||||
|             person[😀] { |  | ||||||
|                 string *first*Name |  | ||||||
|                 string _**last**Name_ |  | ||||||
|             } |  | ||||||
|             a["*Customer Account*"] { |  | ||||||
|                 **string** ema*i*l |  | ||||||
|             } |  | ||||||
|             person ||--o| a : __hẽ😀__ |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with TB direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|           erDiagram |  | ||||||
|           direction TB |  | ||||||
|           CAR ||--|{ NAMED-DRIVER : allows |  | ||||||
|           PERSON ||..o{ NAMED-DRIVER : is |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with BT direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|           erDiagram |  | ||||||
|           direction BT |  | ||||||
|           CAR ||--|{ NAMED-DRIVER : allows |  | ||||||
|           PERSON ||..o{ NAMED-DRIVER : is |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with LR direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|           erDiagram |  | ||||||
|           direction LR |  | ||||||
|           CAR ||--|{ NAMED-DRIVER : allows |  | ||||||
|           PERSON ||..o{ NAMED-DRIVER : is |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render an ER diagram with RL direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|           erDiagram |  | ||||||
|           direction RL |  | ||||||
|           CAR ||--|{ NAMED-DRIVER : allows |  | ||||||
|           PERSON ||..o{ NAMED-DRIVER : is |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with styles applied from style statement`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|             erDiagram |  | ||||||
|               c[CUSTOMER] |  | ||||||
|               p[PERSON] |  | ||||||
|               style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with styles applied from style statement without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|             erDiagram |  | ||||||
|               c[CUSTOMER] |  | ||||||
|               p[PERSON] |  | ||||||
|               style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with styles applied from class statement`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|             erDiagram |  | ||||||
|               c[CUSTOMER] |  | ||||||
|               p[PERSON]:::blue |  | ||||||
|               classDef bold font-size:24px, font-weight: bold |  | ||||||
|               classDef blue stroke:lightblue, color: #0000FF |  | ||||||
|               class c,p bold |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with styles applied from class statement without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|             erDiagram |  | ||||||
|               c[CUSTOMER] |  | ||||||
|               p[PERSON]:::blue |  | ||||||
|               classDef bold font-size:24px, font-weight: bold |  | ||||||
|               classDef blue stroke:lightblue, color: #0000FF |  | ||||||
|               class c,p bold |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render entities with styles applied from the default class and other styles`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|             erDiagram |  | ||||||
|               c[CUSTOMER] |  | ||||||
|               p[PERSON]:::blue |  | ||||||
|               classDef blue stroke:lightblue, color: #0000FF |  | ||||||
|               classDef default fill:pink |  | ||||||
|               style c color:green |  | ||||||
|         `, |  | ||||||
|         { ...options } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -109,8 +109,8 @@ describe('Entity Relationship Diagram', () => { | |||||||
|       const style = svg.attr('style'); |       const style = svg.attr('style'); | ||||||
|       expect(style).to.match(/^max-width: [\d.]+px;$/); |       expect(style).to.match(/^max-width: [\d.]+px;$/); | ||||||
|       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); |       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); | ||||||
|       // use within because the absolute value can be slightly different depending on the environment ±6% |       // use within because the absolute value can be slightly different depending on the environment ±5% | ||||||
|       expect(maxWidthValue).to.be.within(140 * 0.96, 140 * 1.06); |       expect(maxWidthValue).to.be.within(140 * 0.95, 140 * 1.05); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -125,8 +125,8 @@ describe('Entity Relationship Diagram', () => { | |||||||
|     ); |     ); | ||||||
|     cy.get('svg').should((svg) => { |     cy.get('svg').should((svg) => { | ||||||
|       const width = parseFloat(svg.attr('width')); |       const width = parseFloat(svg.attr('width')); | ||||||
|       // use within because the absolute value can be slightly different depending on the environment ±6% |       // use within because the absolute value can be slightly different depending on the environment ±5% | ||||||
|       expect(width).to.be.within(140 * 0.96, 140 * 1.06); |       expect(width).to.be.within(140 * 0.95, 140 * 1.05); | ||||||
|       // expect(svg).to.have.attr('height', '465'); |       // expect(svg).to.have.attr('height', '465'); | ||||||
|       expect(svg).to.not.have.attr('style'); |       expect(svg).to.not.have.attr('style'); | ||||||
|     }); |     }); | ||||||
| @@ -321,142 +321,4 @@ ORDER ||--|{ LINE-ITEM : contains | |||||||
|       { logLevel: 1 } |       { logLevel: 1 } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should render relationship labels with line breaks', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     erDiagram |  | ||||||
|       p[Person] { |  | ||||||
|           string firstName |  | ||||||
|           string lastName |  | ||||||
|       } |  | ||||||
|       a["Customer Account"] { |  | ||||||
|           string email |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       b["Customer Account Secondary"] { |  | ||||||
|         string email |  | ||||||
|       } |  | ||||||
|        |  | ||||||
|       c["Customer Account Tertiary"] { |  | ||||||
|         string email |  | ||||||
|       } |  | ||||||
|        |  | ||||||
|       d["Customer Account Nth"] { |  | ||||||
|         string email |  | ||||||
|       } |  | ||||||
|  |  | ||||||
|       p ||--o| a : "has<br />one" |  | ||||||
|       p ||--o| b : "has<br />one<br />two" |  | ||||||
|       p ||--o| c : "has<br />one<br/>two<br />three" |  | ||||||
|       p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth" |  | ||||||
|       `, |  | ||||||
|       { logLevel: 1 } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   describe('Include char sequence "graph" in text (#6795)', () => { |  | ||||||
|     it('has a label with char sequence "graph"', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         erDiagram |  | ||||||
|           p[Photograph] { |  | ||||||
|             varchar(12) jobId |  | ||||||
|             date dateCreated |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { flowchart: { defaultRenderer: 'elk' } } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   describe('Aggregation Relationships', () => { |  | ||||||
|     it('should render basic aggregation relationships', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         erDiagram |  | ||||||
|           DEPARTMENT <> EMPLOYEE : contains |  | ||||||
|           PROJECT <>.. TASK : manages |  | ||||||
|           TEAM <> MEMBER : consists_of |  | ||||||
|         `, |  | ||||||
|         { logLevel: 1 } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render aggregation with entity attributes', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         erDiagram |  | ||||||
|           DEPARTMENT <> EMPLOYEE : contains |  | ||||||
|           DEPARTMENT { |  | ||||||
|             int id PK |  | ||||||
|             string name |  | ||||||
|             string location |  | ||||||
|           } |  | ||||||
|           EMPLOYEE { |  | ||||||
|             int id PK |  | ||||||
|             string name |  | ||||||
|             int department_id FK |  | ||||||
|           } |  | ||||||
|         `, |  | ||||||
|         { logLevel: 1 } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render aggregation with quoted labels', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         erDiagram |  | ||||||
|           UNIVERSITY <> COLLEGE : "has multiple" |  | ||||||
|           COLLEGE <> DEPARTMENT : "contains" |  | ||||||
|           DEPARTMENT <> FACULTY : "employs" |  | ||||||
|         `, |  | ||||||
|         { logLevel: 1 } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render mixed relationship types', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         erDiagram |  | ||||||
|           CUSTOMER ||--o{ ORDER : places |  | ||||||
|           ORDER ||--|{ ORDER_ITEM : contains |  | ||||||
|           PRODUCT <> ORDER_ITEM : "aggregated in" |  | ||||||
|           WAREHOUSE <>.. PRODUCT : "stores" |  | ||||||
|         `, |  | ||||||
|         { logLevel: 1 } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render aggregation with entity aliases', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|        erDiagram |  | ||||||
|          d[DEPARTMENT] |  | ||||||
|          e[EMPLOYEE] |  | ||||||
|          p[PROJECT] |  | ||||||
|          t[TASK] |  | ||||||
|  |  | ||||||
|          d <> e : contains |  | ||||||
|          p <>.. t : manages |  | ||||||
|  |  | ||||||
|         `, |  | ||||||
|         { logLevel: 1 } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render complex aggregation scenarios', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         erDiagram |  | ||||||
|           COMPANY <> DEPARTMENT : owns |  | ||||||
|           DEPARTMENT <> EMPLOYEE : contains |  | ||||||
|           EMPLOYEE <> PROJECT : works_on |  | ||||||
|           PROJECT <> TASK : consists_of |  | ||||||
|           TASK <> SUBTASK : includes |  | ||||||
|         `, |  | ||||||
|         { logLevel: 1 } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| import { imgSnapshotTest, renderGraph, verifyNumber } from '../../helpers/util.ts'; | import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; | ||||||
|  |  | ||||||
| describe('Flowchart ELK', () => { | describe.skip('Flowchart ELK', () => { | ||||||
|   it('1-elk: should render a simple flowchart', () => { |   it('1-elk: should render a simple flowchart', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `flowchart-elk TD |       `flowchart-elk TD | ||||||
| @@ -109,7 +109,7 @@ describe('Flowchart ELK', () => { | |||||||
|       const style = svg.attr('style'); |       const style = svg.attr('style'); | ||||||
|       expect(style).to.match(/^max-width: [\d.]+px;$/); |       expect(style).to.match(/^max-width: [\d.]+px;$/); | ||||||
|       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); |       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); | ||||||
|       verifyNumber(maxWidthValue, 380); |       expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|   it('8-elk: should render a flowchart when useMaxWidth is false', () => { |   it('8-elk: should render a flowchart when useMaxWidth is false', () => { | ||||||
| @@ -128,7 +128,7 @@ describe('Flowchart ELK', () => { | |||||||
|       const width = parseFloat(svg.attr('width')); |       const width = parseFloat(svg.attr('width')); | ||||||
|       // use within because the absolute value can be slightly different depending on the environment ±5% |       // use within because the absolute value can be slightly different depending on the environment ±5% | ||||||
|       // expect(height).to.be.within(446 * 0.95, 446 * 1.05); |       // expect(height).to.be.within(446 * 0.95, 446 * 1.05); | ||||||
|       verifyNumber(width, 380); |       expect(width).to.be.within(230 * 0.95, 230 * 1.05); | ||||||
|       expect(svg).to.not.have.attr('style'); |       expect(svg).to.not.have.attr('style'); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| @@ -208,13 +208,13 @@ describe('Flowchart ELK', () => { | |||||||
|       `flowchart-elk TB |       `flowchart-elk TB | ||||||
|   internet |   internet | ||||||
|   nat |   nat | ||||||
|   router |   routeur | ||||||
|   lb1 |   lb1 | ||||||
|   lb2 |   lb2 | ||||||
|   compute1 |   compute1 | ||||||
|   compute2 |   compute2 | ||||||
|   subgraph project |   subgraph project | ||||||
|   router |   routeur | ||||||
|   nat |   nat | ||||||
|     subgraph subnet1 |     subgraph subnet1 | ||||||
|       compute1 |       compute1 | ||||||
| @@ -225,8 +225,8 @@ describe('Flowchart ELK', () => { | |||||||
|       lb2 |       lb2 | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   internet --> router |   internet --> routeur | ||||||
|   router --> subnet1 & subnet2 |   routeur --> subnet1 & subnet2 | ||||||
|   subnet1 & subnet2 --> nat --> internet |   subnet1 & subnet2 --> nat --> internet | ||||||
|       `, |       `, | ||||||
|       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } |       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } | ||||||
| @@ -443,7 +443,7 @@ flowchart-elk TD | |||||||
|       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } |       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('63-elk: title on subgraphs should be themeable', () => { |   it('63-elk: title on subgraphs should be themable', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%% |       %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%% | ||||||
| @@ -692,7 +692,7 @@ A --> B | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|     cy.get('svg').should((svg) => { |     cy.get('svg').should((svg) => { | ||||||
|       const edges = svg[0].querySelectorAll('.edges > path'); |       const edges = svg.querySelectorAll('.edges > path'); | ||||||
|       edges.forEach((edge) => { |       edges.forEach((edge) => { | ||||||
|         expect(edge).to.have.class('flowchart-link'); |         expect(edge).to.have.class('flowchart-link'); | ||||||
|       }); |       }); | ||||||
| @@ -739,7 +739,7 @@ NL\`") --"\`1o **bold**\`"--> c | |||||||
|           { flowchart: { titleTopMargin: 0 } } |           { flowchart: { titleTopMargin: 0 } } | ||||||
|         ); |         ); | ||||||
|       }); |       }); | ||||||
|       it.skip('Wrapping long text with a new line', () => { |       it('Wrapping long text with a new line', () => { | ||||||
|         imgSnapshotTest( |         imgSnapshotTest( | ||||||
|           `%%{init: {"flowchart": {"htmlLabels": true}} }%% |           `%%{init: {"flowchart": {"htmlLabels": true}} }%% | ||||||
| flowchart-elk LR | flowchart-elk LR | ||||||
| @@ -841,7 +841,7 @@ end | |||||||
|           { flowchart: { titleTopMargin: 0 } } |           { flowchart: { titleTopMargin: 0 } } | ||||||
|         ); |         ); | ||||||
|       }); |       }); | ||||||
|       it('Sub graphs', () => { |       it('Sub graphs and markdown strings', () => { | ||||||
|         imgSnapshotTest( |         imgSnapshotTest( | ||||||
|           `--- |           `--- | ||||||
| config: | config: | ||||||
| @@ -861,212 +861,7 @@ flowchart LR | |||||||
|           { flowchart: { titleTopMargin: 0 } } |           { flowchart: { titleTopMargin: 0 } } | ||||||
|         ); |         ); | ||||||
|       }); |       }); | ||||||
|       it('6080: should handle diamond shape intersections', () => { |  | ||||||
|         imgSnapshotTest( |  | ||||||
|           `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
| flowchart LR |  | ||||||
|  subgraph s1["Untitled subgraph"] |  | ||||||
|         n1["Evaluate"] |  | ||||||
|         n2["Option 1"] |  | ||||||
|         n3["Option 2"] |  | ||||||
|         n4["fa:fa-car Option 3"] |  | ||||||
|   end |  | ||||||
|  subgraph s2["Untitled subgraph"] |  | ||||||
|         n5["Evaluate"] |  | ||||||
|         n6["Option 1"] |  | ||||||
|         n7["Option 2"] |  | ||||||
|         n8["fa:fa-car Option 3"] |  | ||||||
|   end |  | ||||||
|     A["Start"] -- Some text --> B("Continue") |  | ||||||
|     B --> C{"Evaluate"} |  | ||||||
|     C -- One --> D["Option 1"] |  | ||||||
|     C -- Two --> E["Option 2"] |  | ||||||
|     C -- Three --> F["fa:fa-car Option 3"] |  | ||||||
|     n1 -- One --> n2 |  | ||||||
|     n1 -- Two --> n3 |  | ||||||
|     n1 -- Three --> n4 |  | ||||||
|     n5 -- One --> n6 |  | ||||||
|     n5 -- Two --> n7 |  | ||||||
|     n5 -- Three --> n8 |  | ||||||
|     n1@{ shape: diam} |  | ||||||
|     n2@{ shape: rect} |  | ||||||
|     n3@{ shape: rect} |  | ||||||
|     n4@{ shape: rect} |  | ||||||
|     n5@{ shape: diam} |  | ||||||
|     n6@{ shape: rect} |  | ||||||
|     n7@{ shape: rect} |  | ||||||
|     n8@{ shape: rect} |  | ||||||
|  |  | ||||||
| `, |  | ||||||
|           { flowchart: { titleTopMargin: 0 } } |  | ||||||
|         ); |  | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|       it('6088-1: should handle diamond shape intersections', () => { |  | ||||||
|         imgSnapshotTest( |  | ||||||
|           `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
|       flowchart LR |  | ||||||
|       subgraph S2 |  | ||||||
|       subgraph s1["APA"] |  | ||||||
|       D{"Use the editor"} |  | ||||||
|       end |  | ||||||
|  |  | ||||||
|  |  | ||||||
|       D -- Mermaid js --> I{"fa:fa-code Text"} |  | ||||||
|             D --> I |  | ||||||
|             D --> I |  | ||||||
|  |  | ||||||
|       end |  | ||||||
| `, |  | ||||||
|           { flowchart: { titleTopMargin: 0 } } |  | ||||||
|         ); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       it('6088-2: should handle diamond shape intersections', () => { |  | ||||||
|         imgSnapshotTest( |  | ||||||
|           `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
|       flowchart LR |  | ||||||
|       a |  | ||||||
|       subgraph s0["APA"] |  | ||||||
|       subgraph s8["APA"] |  | ||||||
|       subgraph s1["APA"] |  | ||||||
|         D{"X"} |  | ||||||
|         E[Q] |  | ||||||
|       end |  | ||||||
|       subgraph s3["BAPA"] |  | ||||||
|         F[Q] |  | ||||||
|         I |  | ||||||
|       end |  | ||||||
|             D --> I |  | ||||||
|             D --> I |  | ||||||
|             D --> I |  | ||||||
|  |  | ||||||
|       I{"X"} |  | ||||||
|       end |  | ||||||
|       end |  | ||||||
|  |  | ||||||
| `, |  | ||||||
|           { flowchart: { titleTopMargin: 0 } } |  | ||||||
|         ); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       it('6088-3: should handle diamond shape intersections', () => { |  | ||||||
|         imgSnapshotTest( |  | ||||||
|           `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
|       flowchart LR |  | ||||||
|       a |  | ||||||
|         D{"Use the editor"} |  | ||||||
|  |  | ||||||
|       D -- Mermaid js --> I{"fa:fa-code Text"} |  | ||||||
|       D-->I |  | ||||||
|       D-->I |  | ||||||
|  |  | ||||||
| `, |  | ||||||
|           { flowchart: { titleTopMargin: 0 } } |  | ||||||
|         ); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       it('6088-4: should handle diamond shape intersections', () => { |  | ||||||
|         imgSnapshotTest( |  | ||||||
|           `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
| flowchart LR |  | ||||||
|  subgraph s1["Untitled subgraph"] |  | ||||||
|         n1["Evaluate"] |  | ||||||
|         n2["Option 1"] |  | ||||||
|         n3["Option 2"] |  | ||||||
|         n4["fa:fa-car Option 3"] |  | ||||||
|   end |  | ||||||
|  subgraph s2["Untitled subgraph"] |  | ||||||
|         n5["Evaluate"] |  | ||||||
|         n6["Option 1"] |  | ||||||
|         n7["Option 2"] |  | ||||||
|         n8["fa:fa-car Option 3"] |  | ||||||
|   end |  | ||||||
|     A["Start"] -- Some text --> B("Continue") |  | ||||||
|     B --> C{"Evaluate"} |  | ||||||
|     C -- One --> D["Option 1"] |  | ||||||
|     C -- Two --> E["Option 2"] |  | ||||||
|     C -- Three --> F["fa:fa-car Option 3"] |  | ||||||
|     n1 -- One --> n2 |  | ||||||
|     n1 -- Two --> n3 |  | ||||||
|     n1 -- Three --> n4 |  | ||||||
|     n5 -- One --> n6 |  | ||||||
|     n5 -- Two --> n7 |  | ||||||
|     n5 -- Three --> n8 |  | ||||||
|     n1@{ shape: diam} |  | ||||||
|     n2@{ shape: rect} |  | ||||||
|     n3@{ shape: rect} |  | ||||||
|     n4@{ shape: rect} |  | ||||||
|     n5@{ shape: diam} |  | ||||||
|     n6@{ shape: rect} |  | ||||||
|     n7@{ shape: rect} |  | ||||||
|     n8@{ shape: rect} |  | ||||||
|  |  | ||||||
| `, |  | ||||||
|           { flowchart: { titleTopMargin: 0 } } |  | ||||||
|         ); |  | ||||||
|       }); |  | ||||||
|  |  | ||||||
|       it('6088-5: should handle diamond shape intersections', () => { |  | ||||||
|         imgSnapshotTest( |  | ||||||
|           `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
| flowchart LR |  | ||||||
|     A{A} --> B & C |  | ||||||
|  |  | ||||||
| `, |  | ||||||
|           { flowchart: { titleTopMargin: 0 } } |  | ||||||
|         ); |  | ||||||
|       }); |  | ||||||
|       it('6088-6: should handle diamond shape intersections', () => { |  | ||||||
|         imgSnapshotTest( |  | ||||||
|           `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
| flowchart LR |  | ||||||
|     A{A} --> B & C |  | ||||||
|     subgraph "subbe" |  | ||||||
|       A |  | ||||||
|     end |  | ||||||
|  |  | ||||||
| `, |  | ||||||
|           { flowchart: { titleTopMargin: 0 } } |  | ||||||
|         ); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('6647-elk: should keep node order when using elk layout unless it would add crossings', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   layout: elk |  | ||||||
| --- |  | ||||||
|       flowchart TB |  | ||||||
|         a --> a1 & a2 & a3 & a4 |  | ||||||
|         b --> b1 & b2 |  | ||||||
|         b2 --> b3 |  | ||||||
|         b1 --> b4 |  | ||||||
|       ` |  | ||||||
|     ); |  | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -29,6 +30,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -45,7 +47,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       C -->|Two| E[iPhone] |       C -->|Two| E[iPhone] | ||||||
|       C -->|Three| F[Car] |       C -->|Three| F[Car] | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -60,7 +62,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       C -->|Two| E[\\iPhone\\] |       C -->|Two| E[\\iPhone\\] | ||||||
|       C -->|Three| F[Car] |       C -->|Three| F[Car] | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -76,7 +78,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       classDef processHead fill:#888888,color:white,font-weight:bold,stroke-width:3px,stroke:#001f3f |       classDef processHead fill:#888888,color:white,font-weight:bold,stroke-width:3px,stroke:#001f3f | ||||||
|       class 1A,1B,D,E processHead |       class 1A,1B,D,E processHead | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -105,7 +107,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       35(SAM.CommonFA.PopulationFME)-->39(SAM.CommonFA.ChargeDetails) |       35(SAM.CommonFA.PopulationFME)-->39(SAM.CommonFA.ChargeDetails) | ||||||
|       36(SAM.CommonFA.PremetricCost)-->39(SAM.CommonFA.ChargeDetails) |       36(SAM.CommonFA.PremetricCost)-->39(SAM.CommonFA.ChargeDetails) | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -176,7 +178,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       9a072290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002 |       9a072290_1ec3_e711_8c5a_005056ad0002-->d6072290_1ec3_e711_8c5a_005056ad0002 | ||||||
|       9a072290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002 |       9a072290_1ec3_e711_8c5a_005056ad0002-->71082290_1ec3_e711_8c5a_005056ad0002 | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -185,7 +187,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       ` |       ` | ||||||
|     graph TB;subgraph "number as labels";1;end; |     graph TB;subgraph "number as labels";1;end; | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -197,7 +199,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|         a1-->a2 |         a1-->a2 | ||||||
|       end |       end | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -209,7 +211,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|         a1-->a2 |         a1-->a2 | ||||||
|       end |       end | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -244,7 +246,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred |       style foo fill:#F99,stroke-width:2px,stroke:#F0F,color:darkred | ||||||
|       style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue |       style bar fill:#999,stroke-width:10px,stroke:#0F0,color:blue | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -346,7 +348,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A; |       sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4DA958A0-26D9-4D47-93A7-70F39FD7D51A; | ||||||
|       sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22; |       sid-7CE72B24-E0C1-46D3-8132-8BA66BE05AA7-->sid-4FC27B48-A6F9-460A-A675-021F5854FE22; | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -362,6 +364,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         listUrl: false, |         listUrl: false, | ||||||
|         listId: 'color styling', |         listId: 'color styling', | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
| @@ -387,6 +390,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         listUrl: false, |         listUrl: false, | ||||||
|         listId: 'color styling', |         listId: 'color styling', | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
| @@ -407,6 +411,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -430,6 +435,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -451,6 +457,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -464,6 +471,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -477,6 +485,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -491,6 +500,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -517,6 +527,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       class A someclass;`, |       class A someclass;`, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -533,7 +544,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       C -->|Two| E[iPhone] |       C -->|Two| E[iPhone] | ||||||
|       C -->|Three| F[fa:fa-car Car] |       C -->|Three| F[fa:fa-car Car] | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', flowchart: { nodeSpacing: 50 }, fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, flowchart: { nodeSpacing: 50 }, fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -549,6 +560,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { rankSpacing: '100' }, |         flowchart: { rankSpacing: '100' }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -566,6 +578,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -590,7 +603,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       click E "notes://do-your-thing/id" "other protocol test" |       click E "notes://do-your-thing/id" "other protocol test" | ||||||
|       click F "javascript:alert('test')" "script test" |       click F "javascript:alert('test')" "script test" | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', securityLevel: 'loose', fontFamily: 'courier' } |       { look: 'handDrawn', handDrawnSeed: 1, securityLevel: 'loose', fontFamily: 'courier' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -610,7 +623,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       click B "index.html#link-clicked" "link test" |       click B "index.html#link-clicked" "link test" | ||||||
|       click D testClick "click test" |       click D testClick "click test" | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', flowchart: { htmlLabels: true } } |       { look: 'handDrawn', handDrawnSeed: 1, flowchart: { htmlLabels: true } } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -632,6 +645,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -650,7 +664,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       class A myClass1 |       class A myClass1 | ||||||
|       class D myClass2 |       class D myClass2 | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', flowchart: { htmlLabels: true } } |       { look: 'handDrawn', handDrawnSeed: 1, flowchart: { htmlLabels: true } } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -668,6 +682,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -696,6 +711,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -712,6 +728,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -735,6 +752,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: false }, |         flowchart: { htmlLabels: false }, | ||||||
|         fontFamily: 'courier', |         fontFamily: 'courier', | ||||||
|       } |       } | ||||||
| @@ -751,7 +769,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       C -->|Two| E[iPhone] |       C -->|Two| E[iPhone] | ||||||
|       C -->|Three| F[fa:fa-car Car] |       C -->|Three| F[fa:fa-car Car] | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', flowchart: { diagramPadding: 0 } } |       { look: 'handDrawn', handDrawnSeed: 1, flowchart: { diagramPadding: 0 } } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
| @@ -786,7 +804,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `graph TD |       `graph TD | ||||||
|         a["<strong>Haiya</strong>"]-->b |         a["<strong>Haiya</strong>"]-->b | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', htmlLabels: false, flowchart: { htmlLabels: false } } |       { look: 'handDrawn', handDrawnSeed: 1, htmlLabels: false, flowchart: { htmlLabels: false } } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('FDH37: should render non-escaped with html labels', () => { |   it('FDH37: should render non-escaped with html labels', () => { | ||||||
| @@ -796,6 +814,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -811,7 +830,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       C -->|Two| E[iPhone] |       C -->|Two| E[iPhone] | ||||||
|       C -->|Three| F[fa:fa-car Car] |       C -->|Three| F[fa:fa-car Car] | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', flowchart: { useMaxWidth: true } } |       { look: 'handDrawn', handDrawnSeed: 1, flowchart: { useMaxWidth: true } } | ||||||
|     ); |     ); | ||||||
|     cy.get('svg').should((svg) => { |     cy.get('svg').should((svg) => { | ||||||
|       expect(svg).to.have.attr('width', '100%'); |       expect(svg).to.have.attr('width', '100%'); | ||||||
| @@ -834,7 +853,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       C -->|Two| E[iPhone] |       C -->|Two| E[iPhone] | ||||||
|       C -->|Three| F[fa:fa-car Car] |       C -->|Three| F[fa:fa-car Car] | ||||||
|       `, |       `, | ||||||
|       { look: 'handDrawn', flowchart: { useMaxWidth: false } } |       { look: 'handDrawn', handDrawnSeed: 1, flowchart: { useMaxWidth: false } } | ||||||
|     ); |     ); | ||||||
|     cy.get('svg').should((svg) => { |     cy.get('svg').should((svg) => { | ||||||
|       // const height = parseFloat(svg.attr('height')); |       // const height = parseFloat(svg.attr('height')); | ||||||
| @@ -855,6 +874,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -884,6 +904,7 @@ describe('Flowchart HandDrawn', () => { | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -898,6 +919,7 @@ graph TD | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -915,6 +937,7 @@ graph TD | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -954,6 +977,7 @@ graph TD | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -975,6 +999,7 @@ graph TD | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -991,6 +1016,7 @@ graph TD | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -1006,6 +1032,7 @@ graph TD | |||||||
|       `, |       `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         htmlLabels: true, |         htmlLabels: true, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
| @@ -1024,6 +1051,7 @@ graph TD | |||||||
|     `, |     `, | ||||||
|       { |       { | ||||||
|         look: 'handDrawn', |         look: 'handDrawn', | ||||||
|  |         handDrawnSeed: 1, | ||||||
|         flowchart: { htmlLabels: true }, |         flowchart: { htmlLabels: true }, | ||||||
|         securityLevel: 'loose', |         securityLevel: 'loose', | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -1,28 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| const themes = ['default', 'forest', 'dark', 'base', 'neutral']; |  | ||||||
|  |  | ||||||
| describe('when rendering flowchart with icons', () => { |  | ||||||
|   for (const theme of themes) { |  | ||||||
|     it(`should render icons from fontawesome library on theme ${theme}`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart TD |  | ||||||
|             A("fab:fa-twitter Twitter") --> B("fab:fa-facebook Facebook") |  | ||||||
|             B --> C("fa:fa-coffee Coffee") |  | ||||||
|             C --> D("fa:fa-car Car") |  | ||||||
|             D --> E("fab:fa-github GitHub") |  | ||||||
|         `, |  | ||||||
|         { theme } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`should render registered icons on theme ${theme}`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart TD |  | ||||||
|             A("fa:fa-bell Bell")  |  | ||||||
|         `, |  | ||||||
|         { theme } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| }); |  | ||||||
| @@ -1,142 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| const aliasSet1 = ['process', 'rect', 'proc', 'rectangle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet2 = ['event', 'rounded'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet3 = ['stadium', 'pill', 'terminal'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet4 = ['fr-rect', 'subproc', 'subprocess', 'framed-rectangle', 'subroutine'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet5 = ['db', 'database', 'cylinder', 'cyl'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet6 = ['diam', 'decision', 'diamond'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet7 = ['hex', 'hexagon', 'prepare'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet8 = ['lean-r', 'lean-right', 'in-out'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet9 = ['lean-l', 'lean-left', 'out-in'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet10 = ['trap-b', 'trapezoid-bottom', 'priority'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet11 = ['trap-t', 'trapezoid-top', 'manual'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet12 = ['dbl-circ', 'double-circle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet13 = ['notched-rectangle', 'card', 'notch-rect'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet14 = [ |  | ||||||
|   'lin-rect', |  | ||||||
|   'lined-rectangle', |  | ||||||
|   'lin-proc', |  | ||||||
|   'lined-process', |  | ||||||
|   'shaded-process', |  | ||||||
| ] as const; |  | ||||||
|  |  | ||||||
| const aliasSet15 = ['sm-circ', 'small-circle', 'start'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet16 = ['fr-circ', 'framed-circle', 'stop'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet17 = ['fork', 'join'] as const; |  | ||||||
| // brace-r', 'braces' |  | ||||||
| const aliasSet18 = ['comment', 'brace-l'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet19 = ['bolt', 'com-link', 'lightning-bolt'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet20 = ['doc', 'document'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet21 = ['delay', 'half-rounded-rectangle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet22 = ['h-cyl', 'das', 'horizontal-cylinder'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet23 = ['lin-cyl', 'disk', 'lined-cylinder'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet24 = ['curv-trap', 'display', 'curved-trapezoid'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet25 = ['div-rect', 'div-proc', 'divided-rectangle', 'divided-process'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet26 = ['extract', 'tri', 'triangle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet27 = ['win-pane', 'internal-storage', 'window-pane'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet28 = ['f-circ', 'junction', 'filled-circle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet29 = ['lin-doc', 'lined-document'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet30 = ['notch-pent', 'loop-limit', 'notched-pentagon'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet31 = ['flip-tri', 'manual-file', 'flipped-triangle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet32 = ['sl-rect', 'manual-input', 'sloped-rectangle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet33 = ['docs', 'documents', 'st-doc', 'stacked-document'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet34 = ['procs', 'processes', 'st-rect', 'stacked-rectangle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet35 = ['flag', 'paper-tape'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet36 = ['bow-rect', 'stored-data', 'bow-tie-rectangle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet37 = ['cross-circ', 'summary', 'crossed-circle'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet38 = ['tag-doc', 'tagged-document'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet39 = ['tag-rect', 'tag-proc', 'tagged-rectangle', 'tagged-process'] as const; |  | ||||||
|  |  | ||||||
| const aliasSet40 = ['collate', 'hourglass'] as const; |  | ||||||
|  |  | ||||||
| // Aggregate all alias sets into a single array |  | ||||||
| const aliasSets = [ |  | ||||||
|   aliasSet1, |  | ||||||
|   aliasSet2, |  | ||||||
|   aliasSet3, |  | ||||||
|   aliasSet4, |  | ||||||
|   aliasSet5, |  | ||||||
|   aliasSet6, |  | ||||||
|   aliasSet7, |  | ||||||
|   aliasSet8, |  | ||||||
|   aliasSet9, |  | ||||||
|   aliasSet10, |  | ||||||
|   aliasSet11, |  | ||||||
|   aliasSet12, |  | ||||||
|   aliasSet13, |  | ||||||
|   aliasSet14, |  | ||||||
|   aliasSet15, |  | ||||||
|   aliasSet16, |  | ||||||
|   aliasSet17, |  | ||||||
|   aliasSet18, |  | ||||||
|   aliasSet19, |  | ||||||
|   aliasSet20, |  | ||||||
|   aliasSet21, |  | ||||||
|   aliasSet22, |  | ||||||
|   aliasSet23, |  | ||||||
|   aliasSet24, |  | ||||||
|   aliasSet25, |  | ||||||
|   aliasSet26, |  | ||||||
|   aliasSet27, |  | ||||||
|   aliasSet28, |  | ||||||
|   aliasSet29, |  | ||||||
|   aliasSet30, |  | ||||||
|   aliasSet31, |  | ||||||
|   aliasSet32, |  | ||||||
|   aliasSet33, |  | ||||||
|   aliasSet34, |  | ||||||
|   aliasSet35, |  | ||||||
|   aliasSet36, |  | ||||||
|   aliasSet37, |  | ||||||
|   aliasSet38, |  | ||||||
|   aliasSet39, |  | ||||||
| ] as const; |  | ||||||
|  |  | ||||||
| aliasSets.forEach((aliasSet) => { |  | ||||||
|   describe(`Test ${aliasSet.join(',')} `, () => { |  | ||||||
|     it(`All ${aliasSet.join(',')} should render same shape`, () => { |  | ||||||
|       let flowchartCode = `flowchart \n`; |  | ||||||
|       aliasSet.forEach((alias, index) => { |  | ||||||
|         flowchartCode += ` n${index}@{ shape: ${alias}, label: "${alias}" }\n`; |  | ||||||
|       }); |  | ||||||
|       imgSnapshotTest(flowchartCode); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -99,7 +99,7 @@ describe('Flowchart v2', () => { | |||||||
|       const style = svg.attr('style'); |       const style = svg.attr('style'); | ||||||
|       expect(style).to.match(/^max-width: [\d.]+px;$/); |       expect(style).to.match(/^max-width: [\d.]+px;$/); | ||||||
|       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); |       const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); | ||||||
|       expect(maxWidthValue).to.be.within(440 * 0.95, 440 * 1.05); |       expect(maxWidthValue).to.be.within(417 * 0.95, 417 * 1.05); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|   it('8: should render a flowchart when useMaxWidth is false', () => { |   it('8: should render a flowchart when useMaxWidth is false', () => { | ||||||
| @@ -118,7 +118,7 @@ describe('Flowchart v2', () => { | |||||||
|       const width = parseFloat(svg.attr('width')); |       const width = parseFloat(svg.attr('width')); | ||||||
|       // use within because the absolute value can be slightly different depending on the environment ±5% |       // use within because the absolute value can be slightly different depending on the environment ±5% | ||||||
|       // expect(height).to.be.within(446 * 0.95, 446 * 1.05); |       // expect(height).to.be.within(446 * 0.95, 446 * 1.05); | ||||||
|       expect(width).to.be.within(440 * 0.95, 440 * 1.05); |       expect(width).to.be.within(417 * 0.95, 417 * 1.05); | ||||||
|       expect(svg).to.not.have.attr('style'); |       expect(svg).to.not.have.attr('style'); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
| @@ -198,13 +198,13 @@ describe('Flowchart v2', () => { | |||||||
|       `flowchart TB |       `flowchart TB | ||||||
|   internet |   internet | ||||||
|   nat |   nat | ||||||
|   router |   routeur | ||||||
|   lb1 |   lb1 | ||||||
|   lb2 |   lb2 | ||||||
|   compute1 |   compute1 | ||||||
|   compute2 |   compute2 | ||||||
|   subgraph project |   subgraph project | ||||||
|   router |   routeur | ||||||
|   nat |   nat | ||||||
|     subgraph subnet1 |     subgraph subnet1 | ||||||
|       compute1 |       compute1 | ||||||
| @@ -215,8 +215,8 @@ describe('Flowchart v2', () => { | |||||||
|       lb2 |       lb2 | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|   internet --> router |   internet --> routeur | ||||||
|   router --> subnet1 & subnet2 |   routeur --> subnet1 & subnet2 | ||||||
|   subnet1 & subnet2 --> nat --> internet |   subnet1 & subnet2 --> nat --> internet | ||||||
|       `, |       `, | ||||||
|       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } |       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } | ||||||
| @@ -433,7 +433,7 @@ flowchart TD | |||||||
|       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } |       { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('63: title on subgraphs should be themeable', () => { |   it('63: title on subgraphs should be themable', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%% |       %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%% | ||||||
| @@ -699,7 +699,7 @@ A --> B | |||||||
|       { flowchart: { titleTopMargin: 10 } } |       { flowchart: { titleTopMargin: 10 } } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('3192: It should be possible to render flowcharts with invisible edges', () => { |   it('3192: It should be possieble to render flowcharts with invisible edges', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `--- |       `--- | ||||||
| title: Simple flowchart with invisible edges | title: Simple flowchart with invisible edges | ||||||
| @@ -1052,138 +1052,5 @@ end | |||||||
|         } |         } | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|     it('Should render self-loops', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart |  | ||||||
|           A --> A |  | ||||||
|           subgraph B |  | ||||||
|             B1 --> B1 |  | ||||||
|           end |  | ||||||
|           subgraph C |  | ||||||
|             subgraph C1 |  | ||||||
|               C2 --> C2 |  | ||||||
|               subgraph D |  | ||||||
|                 D1 --> D1 |  | ||||||
|               end |  | ||||||
|               D --> D |  | ||||||
|             end |  | ||||||
|             C1 --> C1 |  | ||||||
|           end |  | ||||||
|         `, |  | ||||||
|         { |  | ||||||
|           flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } }, |  | ||||||
|         } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|   describe('New @ syntax for node metadata edge cases', () => { |  | ||||||
|     it('should be possible to use @  syntax to add labels on multi nodes', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart TB |  | ||||||
|        n2["label for n2"] &   n4@{ label: "label for n4"}   & n5@{ label: "label for n5"} |  | ||||||
|         `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|     it('should be possible to use @  syntax to add labels with trail spaces and &', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart TB |  | ||||||
|        n2["label for n2"] &   n4@{ label: "label for n4"}   & n5@{ label: "label for n5"}    |  | ||||||
|         `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|     it('should be possible to use @  syntax to add labels with trail spaces', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart TB |  | ||||||
|        n2["label for n2"] |  | ||||||
|        n4@{ label: "label for n4"} |  | ||||||
|        n5@{ label: "label for n5"}   |  | ||||||
|         `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|     it('should be possible to use @  syntax to add labels with trail spaces and edge/link', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart TD |  | ||||||
|     A["A"] --> B["for B"] &    C@{ label: "for c"} & E@{label : "for E"}   |  | ||||||
|     D@{label: "for D"}      |  | ||||||
|         `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|   describe('Flowchart Node Shape Rendering', () => { |  | ||||||
|     it('should render a stadium-shaped node', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart TB |  | ||||||
|           A(["Start"]) --> n1["Untitled Node"] |  | ||||||
|           A --> n2["Untitled Node"] |  | ||||||
|         `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|     it('should render a diamond-shaped node using shape config', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart BT |  | ||||||
|           n2["Untitled Node"] --> n1["Diamond"] |  | ||||||
|           n1@{ shape: diam} |  | ||||||
|         `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|     it('should render a rounded rectangle and a normal rectangle', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `flowchart BT |  | ||||||
|         n2["Untitled Node"] --> n1["Rounded Rectangle"] |  | ||||||
|         n3["Untitled Node"] --> n1 |  | ||||||
|         n1@{ shape: rounded} |  | ||||||
|         n3@{ shape: rect} |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('6617: Per Link Curve Styling using edge Ids', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `flowchart TD |  | ||||||
|       A e1@-->B e5@--> E |  | ||||||
|       E e7@--> D |  | ||||||
|       B e3@-->D |  | ||||||
|       A e2@-->C e4@-->D |  | ||||||
|       C e6@--> F |  | ||||||
|       F e8@--> D |  | ||||||
|       e1@{ curve: natural } |  | ||||||
|       e2@{ curve: stepAfter } |  | ||||||
|       e3@{ curve: monotoneY } |  | ||||||
|       e4@{ curve: bumpY } |  | ||||||
|       e5@{ curve: linear } |  | ||||||
|       e6@{ curve: catmullRom } |  | ||||||
|       e7@{ curve: cardinal } |  | ||||||
|       ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   describe('when rendering unsuported markdown', () => { |  | ||||||
|     const graph = `flowchart TB |  | ||||||
|     mermaid{"What is\nyourmermaid version?"} --> v10["<11"] --"\`<**1**1\`"--> fine["No bug"] |  | ||||||
|     mermaid --> v11[">= v11"] -- ">= v11" --> broken["Affected by https://github.com/mermaid-js/mermaid/issues/5824"] |  | ||||||
|     subgraph subgraph1["\`How to fix **fix**\`"] |  | ||||||
|         broken --> B["B"] |  | ||||||
|     end |  | ||||||
|     githost["Github, Gitlab, BitBucket, etc."] |  | ||||||
|     githost2["\`Github, Gitlab, BitBucket, etc.\`"] |  | ||||||
|     a["1."] |  | ||||||
|     b["- x"] |  | ||||||
|       `; |  | ||||||
|  |  | ||||||
|     it('should render raw strings', () => { |  | ||||||
|       imgSnapshotTest(graph); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render raw strings with htmlLabels: false', () => { |  | ||||||
|       imgSnapshotTest(graph, { htmlLabels: false }); |  | ||||||
|     }); |  | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -917,60 +917,4 @@ graph TD | |||||||
|       } |       } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('#6369: edge color should affect arrow head', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     flowchart LR |  | ||||||
|         A --> B |  | ||||||
|         A --> C |  | ||||||
|         C --> D |  | ||||||
|  |  | ||||||
|         linkStyle 0 stroke:#D50000 |  | ||||||
|         linkStyle 2 stroke:#D50000 |  | ||||||
|     `, |  | ||||||
|       { |  | ||||||
|         flowchart: { htmlLabels: true }, |  | ||||||
|         securityLevel: 'loose', |  | ||||||
|       } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('68: should honor subgraph direction when inheritDir is false', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|       %%{init: {"flowchart": { "inheritDir": false }}}%% |  | ||||||
|       flowchart TB |  | ||||||
|         direction LR |  | ||||||
|         subgraph A |  | ||||||
|           direction TB |  | ||||||
|           a --> b |  | ||||||
|         end |  | ||||||
|         subgraph B |  | ||||||
|           c --> d |  | ||||||
|         end |  | ||||||
|       `, |  | ||||||
|       { |  | ||||||
|         fontFamily: 'courier', |  | ||||||
|       } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('69: should inherit global direction when inheritDir is true', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|       %%{init: {"flowchart": { "inheritDir": true }}}%% |  | ||||||
|       flowchart TB |  | ||||||
|         direction LR |  | ||||||
|         subgraph A |  | ||||||
|           direction TB |  | ||||||
|           a --> b |  | ||||||
|         end |  | ||||||
|         subgraph B |  | ||||||
|           c --> d |  | ||||||
|         end |  | ||||||
|       `, |  | ||||||
|       { |  | ||||||
|         fontFamily: 'courier', |  | ||||||
|       } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -117,7 +117,7 @@ describe('Gantt diagram', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should FAIL rendering a gantt chart for issue #1060 with invalid date', () => { |   it('should FAIL redering a gantt chart for issue #1060 with invalid date', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       gantt |       gantt | ||||||
| @@ -358,23 +358,6 @@ describe('Gantt diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should render a gantt diagram with a vert tag', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|       gantt |  | ||||||
|         title A Gantt Diagram |  | ||||||
|         dateFormat   ss |  | ||||||
|         axisFormat   %Ss |  | ||||||
|  |  | ||||||
|         section Section |  | ||||||
|         A task           : a1, 00, 6s |  | ||||||
|         Milestone     : vert, 01, |  | ||||||
|         section Another |  | ||||||
|         Task in sec      : 06, 3s |  | ||||||
|         another task     : 3s |  | ||||||
|       ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render a gantt diagram with tick is 2 milliseconds', () => { |   it('should render a gantt diagram with tick is 2 milliseconds', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
| @@ -565,18 +548,6 @@ describe('Gantt diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should render only the day when using dateFormat D', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     gantt |  | ||||||
|       title Test |  | ||||||
|       dateFormat D |  | ||||||
|       A :a, 1, 1d |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   // TODO: fix it |   // TODO: fix it | ||||||
|   // |   // | ||||||
|   // This test is skipped deliberately |   // This test is skipped deliberately | ||||||
| @@ -602,7 +573,7 @@ describe('Gantt diagram', () => { | |||||||
|       ` |       ` | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should render a gantt diagram excluding friday and saturday', () => { |   it('should render a gantt diagram exculding friday and saturday', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `gantt |       `gantt | ||||||
|       title A Gantt Diagram |       title A Gantt Diagram | ||||||
| @@ -613,7 +584,7 @@ describe('Gantt diagram', () => { | |||||||
|       A task :a1, 2024-02-28, 10d` |       A task :a1, 2024-02-28, 10d` | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should render a gantt diagram excluding saturday and sunday', () => { |   it('should render a gantt diagram exculding saturday and sunday', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `gantt |       `gantt | ||||||
|       title A Gantt Diagram |       title A Gantt Diagram | ||||||
| @@ -659,49 +630,6 @@ describe('Gantt diagram', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should render a gantt diagram excluding a specific date in YYYY-MM-DD HH:mm:ss format', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     gantt |  | ||||||
|       dateFormat  YYYY-MM-DD HH:mm:ss |  | ||||||
|       excludes    2025-07-07 |  | ||||||
|       section     Section |  | ||||||
|       A task      :a1, 2025-07-04 20:30:30, 2025-07-08 10:30:30 |  | ||||||
|       Another task:after a1, 20h |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render a gantt diagram excluding saturday and sunday in YYYY-MM-DD HH:mm:ss format', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|         gantt |  | ||||||
|       dateFormat  YYYY-MM-DD HH:mm:ss |  | ||||||
|       excludes    weekends |  | ||||||
|        weekend saturday |  | ||||||
|       section     Section |  | ||||||
|       A task      :a1, 2025-07-04 20:30:30, 2025-07-08 10:30:30 |  | ||||||
|       Another task:after a1, 20h |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render a gantt diagram excluding friday and saturday in YYYY-MM-DD HH:mm:ss format', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|         gantt |  | ||||||
|       dateFormat  YYYY-MM-DD HH:mm:ss |  | ||||||
|       excludes    weekends |  | ||||||
|        weekend friday |  | ||||||
|       section     Section |  | ||||||
|       A task      :a1, 2025-07-04 20:30:30, 2025-07-08 10:30:30 |  | ||||||
|       Another task:after a1, 20h |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it("should render when there's a semicolon in the title", () => { |   it("should render when there's a semicolon in the title", () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
| @@ -743,7 +671,7 @@ describe('Gantt diagram', () => { | |||||||
|       title Gantt Digram |       title Gantt Digram | ||||||
|       dateFormat  YYYY-MM-DD |       dateFormat  YYYY-MM-DD | ||||||
|       section Section |       section Section | ||||||
|       ;A task with a semicolon           :a1, 2014-01-01, 30d |       ;A task with a semiclon           :a1, 2014-01-01, 30d | ||||||
|       Another task     :after a1  , 20d |       Another task     :after a1  , 20d | ||||||
|       section Another |       section Another | ||||||
|       Task in sec      :2014-01-12  , 12d |       Task in sec      :2014-01-12  , 12d | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ describe('Git Graph diagram', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('2: should render a simple gitgraph with commit on main branch with id', () => { |   it('2: should render a simple gitgraph with commit on main branch with Id', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `gitGraph |       `gitGraph | ||||||
|        commit id: "One" |        commit id: "One" | ||||||
| @@ -253,7 +253,7 @@ describe('Git Graph diagram', () => { | |||||||
|       ` |       ` | ||||||
|       gitGraph |       gitGraph | ||||||
|       checkout main |       checkout main | ||||||
|       %% Make sure to manually set the id of all commits, for consistent visual tests |       %% Make sure to manually set the ID of all commits, for consistent visual tests | ||||||
|       commit id: "1-abcdefg" |       commit id: "1-abcdefg" | ||||||
|       checkout main |       checkout main | ||||||
|       branch branch1 |       branch branch1 | ||||||
| @@ -343,7 +343,7 @@ gitGraph | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('16: should render a simple gitgraph with commit on main branch with id | Vertical Branch', () => { |   it('16: should render a simple gitgraph with commit on main branch with Id | Vertical Branch', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `gitGraph TB: |       `gitGraph TB: | ||||||
|        commit id: "One" |        commit id: "One" | ||||||
| @@ -585,7 +585,7 @@ gitGraph | |||||||
|       ` |       ` | ||||||
|       gitGraph TB: |       gitGraph TB: | ||||||
|       checkout main |       checkout main | ||||||
|       %% Make sure to manually set the id of all commits, for consistent visual tests |       %% Make sure to manually set the ID of all commits, for consistent visual tests | ||||||
|       commit id: "1-abcdefg" |       commit id: "1-abcdefg" | ||||||
|       checkout main |       checkout main | ||||||
|       branch branch1 |       branch branch1 | ||||||
| @@ -1024,7 +1024,7 @@ gitGraph TB: | |||||||
|         {} |         {} | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|     it('51: should render a simple gitgraph with commit on main branch with id | Vertical Branch - Bottom-to-top', () => { |     it('51: should render a simple gitgraph with commit on main branch with Id | Vertical Branch - Bottom-to-top', () => { | ||||||
|       imgSnapshotTest( |       imgSnapshotTest( | ||||||
|         `gitGraph BT: |         `gitGraph BT: | ||||||
|          commit id: "One" |          commit id: "One" | ||||||
| @@ -1266,7 +1266,7 @@ gitGraph TB: | |||||||
|         ` |         ` | ||||||
|         gitGraph BT: |         gitGraph BT: | ||||||
|         checkout main |         checkout main | ||||||
|         %% Make sure to manually set the id of all commits, for consistent visual tests |         %% Make sure to manually set the ID of all commits, for consistent visual tests | ||||||
|         commit id: "1-abcdefg" |         commit id: "1-abcdefg" | ||||||
|         checkout main |         checkout main | ||||||
|         branch branch1 |         branch branch1 | ||||||
| @@ -1491,7 +1491,7 @@ gitGraph TB: | |||||||
|         ` |         ` | ||||||
|         gitGraph |         gitGraph | ||||||
|         switch main |         switch main | ||||||
|         %% Make sure to manually set the id of all commits, for consistent visual tests |         %% Make sure to manually set the ID of all commits, for consistent visual tests | ||||||
|         commit id: "1-abcdefg" |         commit id: "1-abcdefg" | ||||||
|         switch main |         switch main | ||||||
|         branch branch1 |         branch branch1 | ||||||
|   | |||||||
| @@ -1,143 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util'; |  | ||||||
|  |  | ||||||
| const looks = ['classic', 'handDrawn'] as const; |  | ||||||
| const directions = [ |  | ||||||
|   'TB', |  | ||||||
|   //'BT', |  | ||||||
|   'LR', |  | ||||||
|   //  'RL' |  | ||||||
| ] as const; |  | ||||||
| const forms = [undefined, 'square', 'circle', 'rounded'] as const; |  | ||||||
| const labelPos = [undefined, 't', 'b'] as const; |  | ||||||
|  |  | ||||||
| looks.forEach((look) => { |  | ||||||
|   directions.forEach((direction) => { |  | ||||||
|     forms.forEach((form) => { |  | ||||||
|       labelPos.forEach((pos) => { |  | ||||||
|         describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { |  | ||||||
|           it(`without label`, () => { |  | ||||||
|             let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|             flowchartCode += `  nA --> nAA@{ icon: 'fa:bell'`; |  | ||||||
|             if (form) { |  | ||||||
|               flowchartCode += `, form: '${form}'`; |  | ||||||
|             } |  | ||||||
|             flowchartCode += ` }\n`; |  | ||||||
|             imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|           }); |  | ||||||
|  |  | ||||||
|           it(`with label`, () => { |  | ||||||
|             let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|             flowchartCode += `  nA --> nAA@{ icon: 'fa:bell', label: 'This is a label for icon shape'`; |  | ||||||
|             if (form) { |  | ||||||
|               flowchartCode += `, form: '${form}'`; |  | ||||||
|             } |  | ||||||
|             if (pos) { |  | ||||||
|               flowchartCode += `, pos: '${pos}'`; |  | ||||||
|             } |  | ||||||
|             flowchartCode += ` }\n`; |  | ||||||
|             imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|           }); |  | ||||||
|  |  | ||||||
|           it(`with very long label`, () => { |  | ||||||
|             let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|             flowchartCode += `  nA --> nAA@{ icon: 'fa:bell', label: 'This is a very very very very very long long long label for icon shape'`; |  | ||||||
|             if (form) { |  | ||||||
|               flowchartCode += `, form: '${form}'`; |  | ||||||
|             } |  | ||||||
|             if (pos) { |  | ||||||
|               flowchartCode += `, pos: '${pos}'`; |  | ||||||
|             } |  | ||||||
|             flowchartCode += ` }\n`; |  | ||||||
|             imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|           }); |  | ||||||
|  |  | ||||||
|           it(`with markdown htmlLabels:true`, () => { |  | ||||||
|             let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|             flowchartCode += `  nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`; |  | ||||||
|             if (form) { |  | ||||||
|               flowchartCode += `, form: '${form}'`; |  | ||||||
|             } |  | ||||||
|             if (pos) { |  | ||||||
|               flowchartCode += `, pos: '${pos}'`; |  | ||||||
|             } |  | ||||||
|             flowchartCode += ` }\n`; |  | ||||||
|             imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|           }); |  | ||||||
|  |  | ||||||
|           it(`with markdown htmlLabels:false`, () => { |  | ||||||
|             let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|             flowchartCode += `  nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`; |  | ||||||
|             if (form) { |  | ||||||
|               flowchartCode += `, form: '${form}'`; |  | ||||||
|             } |  | ||||||
|             if (pos) { |  | ||||||
|               flowchartCode += `, pos: '${pos}'`; |  | ||||||
|             } |  | ||||||
|             flowchartCode += ` }\n`; |  | ||||||
|             imgSnapshotTest(flowchartCode, { |  | ||||||
|               look, |  | ||||||
|               htmlLabels: false, |  | ||||||
|               flowchart: { htmlLabels: false }, |  | ||||||
|             }); |  | ||||||
|           }); |  | ||||||
|  |  | ||||||
|           it(`with styles`, () => { |  | ||||||
|             let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|             flowchartCode += `  nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; |  | ||||||
|             if (form) { |  | ||||||
|               flowchartCode += `, form: '${form}'`; |  | ||||||
|             } |  | ||||||
|             if (pos) { |  | ||||||
|               flowchartCode += `, pos: '${pos}'`; |  | ||||||
|             } |  | ||||||
|             flowchartCode += ` }\n`; |  | ||||||
|             flowchartCode += `  style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`; |  | ||||||
|             imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|           }); |  | ||||||
|  |  | ||||||
|           it(`with classDef`, () => { |  | ||||||
|             let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|             flowchartCode += `  classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; |  | ||||||
|             flowchartCode += `  nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; |  | ||||||
|             if (form) { |  | ||||||
|               flowchartCode += `, form: '${form}'`; |  | ||||||
|             } |  | ||||||
|             if (pos) { |  | ||||||
|               flowchartCode += `, pos: '${pos}'`; |  | ||||||
|             } |  | ||||||
|             flowchartCode += ` }\n`; |  | ||||||
|             flowchartCode += `  nAA:::customClazz\n`; |  | ||||||
|             imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|           }); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| describe('Test iconShape with different h', () => { |  | ||||||
|   it('with different h', () => { |  | ||||||
|     let flowchartCode = `flowchart TB\n`; |  | ||||||
|     const icon = 'fa:bell'; |  | ||||||
|     const iconHeight = 64; |  | ||||||
|     flowchartCode += `  nA --> nAA@{ icon: '${icon}', label: 'icon with different h', h: ${iconHeight} }\n`; |  | ||||||
|     imgSnapshotTest(flowchartCode); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| describe('Test colored iconShape', () => { |  | ||||||
|   it('with no styles', () => { |  | ||||||
|     let flowchartCode = `flowchart TB\n`; |  | ||||||
|     const icon = 'fluent-emoji:tropical-fish'; |  | ||||||
|     flowchartCode += `  nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`; |  | ||||||
|     imgSnapshotTest(flowchartCode); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('with styles', () => { |  | ||||||
|     let flowchartCode = `flowchart TB\n`; |  | ||||||
|     const icon = 'fluent-emoji:tropical-fish'; |  | ||||||
|     flowchartCode += `  nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`; |  | ||||||
|     flowchartCode += `  style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`; |  | ||||||
|     imgSnapshotTest(flowchartCode); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -1,103 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util'; |  | ||||||
|  |  | ||||||
| const looks = ['classic', 'handDrawn'] as const; |  | ||||||
| const directions = [ |  | ||||||
|   'TB', |  | ||||||
|   //'BT', |  | ||||||
|   'LR', |  | ||||||
|   //  'RL' |  | ||||||
| ] as const; |  | ||||||
| const labelPos = [undefined, 't', 'b'] as const; |  | ||||||
|  |  | ||||||
| looks.forEach((look) => { |  | ||||||
|   directions.forEach((direction) => { |  | ||||||
|     labelPos.forEach((pos) => { |  | ||||||
|       describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { |  | ||||||
|         it(`without label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }\n`; |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`; |  | ||||||
|  |  | ||||||
|           flowchartCode += `, w: '100', h: '200'`; |  | ||||||
|           if (pos) { |  | ||||||
|             flowchartCode += `, pos: '${pos}'`; |  | ||||||
|           } |  | ||||||
|           flowchartCode += ` }\n`; |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with very long label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`; |  | ||||||
|  |  | ||||||
|           flowchartCode += `, w: '100', h: '250'`; |  | ||||||
|           if (pos) { |  | ||||||
|             flowchartCode += `, pos: '${pos}'`; |  | ||||||
|           } |  | ||||||
|           flowchartCode += ` }\n`; |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with markdown htmlLabels:true`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`; |  | ||||||
|  |  | ||||||
|           flowchartCode += `, w: '550', h: '200'`; |  | ||||||
|           if (pos) { |  | ||||||
|             flowchartCode += `, pos: '${pos}'`; |  | ||||||
|           } |  | ||||||
|           flowchartCode += ` }\n`; |  | ||||||
|           imgSnapshotTest(flowchartCode, { look, htmlLabels: true }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with markdown htmlLabels:false`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`; |  | ||||||
|           flowchartCode += `, w: '250', h: '200'`; |  | ||||||
|  |  | ||||||
|           if (pos) { |  | ||||||
|             flowchartCode += `, pos: '${pos}'`; |  | ||||||
|           } |  | ||||||
|           flowchartCode += ` }\n`; |  | ||||||
|           imgSnapshotTest(flowchartCode, { |  | ||||||
|             look, |  | ||||||
|             htmlLabels: false, |  | ||||||
|             flowchart: { htmlLabels: false }, |  | ||||||
|           }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with styles`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; |  | ||||||
|           flowchartCode += `, w: '550', h: '200'`; |  | ||||||
|  |  | ||||||
|           if (pos) { |  | ||||||
|             flowchartCode += `, pos: '${pos}'`; |  | ||||||
|           } |  | ||||||
|           flowchartCode += ` }\n`; |  | ||||||
|           flowchartCode += `  style A fill:#f9f,stroke:#333,stroke-width:4px \n`; |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with classDef`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#000000,stroke-dasharray: 5 5\n`; |  | ||||||
|           flowchartCode += `  nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; |  | ||||||
|  |  | ||||||
|           flowchartCode += `, w: '500', h: '550'`; |  | ||||||
|           if (pos) { |  | ||||||
|             flowchartCode += `, pos: '${pos}'`; |  | ||||||
|           } |  | ||||||
|           flowchartCode += ` }\n`; |  | ||||||
|           flowchartCode += `  A:::customClazz\n`; |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -63,199 +63,4 @@ section Checkout from website | |||||||
|       { journey: { useMaxWidth: false } } |       { journey: { useMaxWidth: false } } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should initialize with a left margin of 150px for user journeys', () => { |  | ||||||
|     renderGraph( |  | ||||||
|       ` |  | ||||||
|       --- |  | ||||||
|       config: |  | ||||||
|         journey: |  | ||||||
|           maxLabelWidth: 320 |  | ||||||
|       --- |  | ||||||
|       journey |  | ||||||
|         title User Journey Example |  | ||||||
|         section Onboarding |  | ||||||
|             Sign Up: 5: |  | ||||||
|             Browse Features: 3: |  | ||||||
|             Use Core Functionality: 4: |  | ||||||
|         section Engagement |  | ||||||
|             Browse Features: 3 |  | ||||||
|             Use Core Functionality: 4 |  | ||||||
|       `, |  | ||||||
|       { journey: { useMaxWidth: true } } |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     let diagramStartX; |  | ||||||
|  |  | ||||||
|     cy.contains('foreignobject', 'Sign Up').then(($diagram) => { |  | ||||||
|       diagramStartX = parseFloat($diagram.attr('x')); |  | ||||||
|       expect(diagramStartX).to.be.closeTo(150, 2); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should maintain sufficient space between legend and diagram when legend labels are longer', () => { |  | ||||||
|     renderGraph( |  | ||||||
|       `journey |  | ||||||
|       title  Web hook life cycle |  | ||||||
|       section Darkoob |  | ||||||
|         Make preBuilt:5: Darkoob user |  | ||||||
|         register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is  maintained |  | ||||||
|         Map slug to a Prebuilt Job:5: Darkoob user |  | ||||||
|       section External Service |  | ||||||
|         set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty |  | ||||||
|         listen to the events : 5 :  External Service |  | ||||||
|         call darkoob endpoint : 5 : External Service |  | ||||||
|       section Darkoob |  | ||||||
|         check for inputs : 5 : DarkoobAPI |  | ||||||
|         run the prebuilt job : 5 : DarkoobAPI |  | ||||||
|         `, |  | ||||||
|       { journey: { useMaxWidth: true } } |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     let LabelEndX, diagramStartX; |  | ||||||
|  |  | ||||||
|     // Get right edge of the legend |  | ||||||
|     cy.contains('tspan', 'Darkoob userf').then((textBox) => { |  | ||||||
|       const bbox = textBox[0].getBBox(); |  | ||||||
|       LabelEndX = bbox.x + bbox.width; |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // Get left edge of the diagram |  | ||||||
|     cy.contains('foreignobject', 'Make preBuilt').then((rect) => { |  | ||||||
|       diagramStartX = parseFloat(rect.attr('x')); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // Assert right edge of the diagram is greater than or equal to the right edge of the label |  | ||||||
|     cy.then(() => { |  | ||||||
|       expect(diagramStartX).to.be.gte(LabelEndX); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should wrap a single long word with hyphenation', () => { |  | ||||||
|     renderGraph( |  | ||||||
|       ` |  | ||||||
|       --- |  | ||||||
|       config: |  | ||||||
|         journey: |  | ||||||
|           maxLabelWidth: 100 |  | ||||||
|       --- |  | ||||||
|       journey |  | ||||||
|         title Long Word Test |  | ||||||
|         section Test |  | ||||||
|           VeryLongWord: 5: Supercalifragilisticexpialidocious |  | ||||||
|       `, |  | ||||||
|       { journey: { useMaxWidth: true } } |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     // Verify that the line ends with a hyphen, indicating proper hyphenation for words exceeding maxLabelWidth. |  | ||||||
|     cy.get('tspan').then((tspans) => { |  | ||||||
|       const hasHyphen = [...tspans].some((t) => t.textContent.trim().endsWith('-')); |  | ||||||
|       return expect(hasHyphen).to.be.true; |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should wrap text on whitespace without adding hyphens', () => { |  | ||||||
|     renderGraph( |  | ||||||
|       ` |  | ||||||
|       --- |  | ||||||
|       config: |  | ||||||
|         journey: |  | ||||||
|           maxLabelWidth: 200 |  | ||||||
|       --- |  | ||||||
|       journey |  | ||||||
|         title Whitespace Test |  | ||||||
|         section Test |  | ||||||
|           TextWithSpaces: 5: Gustavo Fring is played by Giancarlo Esposito and is a character in Breaking Bad. |  | ||||||
|       `, |  | ||||||
|       { journey: { useMaxWidth: true } } |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     // Verify that none of the text spans end with a hyphen. |  | ||||||
|     cy.get('tspan').each(($el) => { |  | ||||||
|       const text = $el.text(); |  | ||||||
|       expect(text.trim()).not.to.match(/-$/); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should wrap long labels into multiple lines, keep them under max width, and maintain margins', () => { |  | ||||||
|     renderGraph( |  | ||||||
|       ` |  | ||||||
|       --- |  | ||||||
|       config: |  | ||||||
|         journey: |  | ||||||
|           maxLabelWidth: 320 |  | ||||||
|       --- |  | ||||||
|       journey |  | ||||||
|         title User Journey Example |  | ||||||
|         section Onboarding |  | ||||||
|             Sign Up: 5: This is a long label that will be split into multiple lines to test the wrapping functionality |  | ||||||
|             Browse Features: 3: This is another long label that will be split into multiple lines to test the wrapping functionality |  | ||||||
|             Use Core Functionality: 4: This is yet another long label that will be split into multiple lines to test the wrapping functionality |  | ||||||
|         section Engagement |  | ||||||
|             Browse Features: 3 |  | ||||||
|             Use Core Functionality: 4 |  | ||||||
|       `, |  | ||||||
|       { journey: { useMaxWidth: true } } |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     let diagramStartX, maxLineWidth; |  | ||||||
|  |  | ||||||
|     // Get the diagram's left edge x-coordinate |  | ||||||
|     cy.contains('foreignobject', 'Sign Up') |  | ||||||
|       .then(($diagram) => { |  | ||||||
|         diagramStartX = parseFloat($diagram.attr('x')); |  | ||||||
|       }) |  | ||||||
|       .then(() => { |  | ||||||
|         cy.get('text.legend').then(($lines) => { |  | ||||||
|           // Check that there are multiple lines |  | ||||||
|           expect($lines.length).to.be.equal(9); |  | ||||||
|  |  | ||||||
|           // Check that all lines are under the maxLabelWidth |  | ||||||
|           $lines.each((index, el) => { |  | ||||||
|             const bbox = el.getBBox(); |  | ||||||
|             expect(bbox.width).to.be.lte(320); |  | ||||||
|             maxLineWidth = Math.max(maxLineWidth || 0, bbox.width); |  | ||||||
|           }); |  | ||||||
|  |  | ||||||
|           /** The expected margin between the diagram and the legend is 150px, as defined by |  | ||||||
|            *  conf.leftMargin in user-journey-config.js |  | ||||||
|            */ |  | ||||||
|           expect(diagramStartX - maxLineWidth).to.be.closeTo(150, 2); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should correctly render the user journey diagram title with the specified styling', () => { |  | ||||||
|     renderGraph( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   journey: |  | ||||||
|     titleColor: "#2900A5" |  | ||||||
|     titleFontFamily: "Times New Roman" |  | ||||||
|     titleFontSize: "5rem" |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| journey |  | ||||||
|     title User Journey Example |  | ||||||
|     section Onboarding |  | ||||||
|         Sign Up: 5: John, Shahir |  | ||||||
|         Complete Profile: 4: John |  | ||||||
|     section Engagement |  | ||||||
|         Browse Features: 3: John |  | ||||||
|         Use Core Functionality: 4: John |  | ||||||
|     section Retention |  | ||||||
|         Revisit Application: 5: John |  | ||||||
|         Invite Friends: 3: John |  | ||||||
|  |  | ||||||
|         size: 2rem |  | ||||||
|     ` |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     cy.get('text').contains('User Journey Example').as('title'); |  | ||||||
|     cy.get('@title').then(($title) => { |  | ||||||
|       expect($title).to.have.attr('fill', '#2900A5'); |  | ||||||
|       expect($title).to.have.attr('font-family', 'Times New Roman'); |  | ||||||
|       expect($title).to.have.attr('font-size', '5rem'); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,136 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| describe('Kanban diagram', () => { |  | ||||||
|   it('1: should render a kanban with a single section', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     docs[Create Documentation] |  | ||||||
|     docs[Create Blog about the new diagram] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('2: should render a kanban with multiple sections', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     docs[Create Documentation] |  | ||||||
|   id2 |  | ||||||
|     docs[Create Blog about the new diagram] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('3: should render a kanban with a single wrapping node', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('4: should handle the height of a section with a wrapping node at the end', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     id2[One line] |  | ||||||
|     id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('5: should handle the height of a section with a wrapping node at the top', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] |  | ||||||
|     id3[One line] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('6: should handle the height of a section with a wrapping node in the middle', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     id2[One line] |  | ||||||
|     id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] |  | ||||||
|     id4[One line] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('6: should handle assignments', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     docs[Create Documentation] |  | ||||||
|   id2[In progress] |  | ||||||
|     docs[Create Blog about the new diagram]@{ assigned: 'knsv' } |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('7: should handle prioritization', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id2[In progress] |  | ||||||
|     vh[Very High]@{ priority: 'Very High' } |  | ||||||
|     h[High]@{ priority: 'High' } |  | ||||||
|     m[Default priority] |  | ||||||
|     l[Low]@{ priority: 'Low' } |  | ||||||
|     vl[Very Low]@{ priority: 'Very Low' } |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('7: should handle external tickets', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     docs[Create Documentation] |  | ||||||
|   id2[In progress] |  | ||||||
|     docs[Create Blog about the new diagram]@{ ticket: MC-2037 } |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('8: should handle assignments, prioritization and tickets ids in the same item', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `kanban |  | ||||||
|   id2[In progress] |  | ||||||
|     docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' } |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('10: Full example', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   kanban: |  | ||||||
|     ticketBaseUrl: 'https://abc123.atlassian.net/browse/#TICKET#' |  | ||||||
| --- |  | ||||||
| kanban |  | ||||||
|   id1[Todo] |  | ||||||
|     docs[Create Documentation] |  | ||||||
|     docs[Create Blog about the new diagram] |  | ||||||
|   id7[In progress] |  | ||||||
|     id6[Create renderer so that it works in all cases. We also add some extra text here for testing purposes. And some more just for the extra flare.] |  | ||||||
|     id8[Design grammar]@{ assigned: 'knsv' } |  | ||||||
|   id9[Ready for deploy] |  | ||||||
|   id10[Ready for test] |  | ||||||
|   id11[Done] |  | ||||||
|     id5[define getData] |  | ||||||
|     id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'} |  | ||||||
|     id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' } |  | ||||||
|     id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' } |  | ||||||
|     id66[last item]@{ priority: 'Very Low', assigned: 'knsv' } |  | ||||||
|   id12[Can't reproduce] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -146,7 +146,7 @@ root | |||||||
|       shouldHaveRoot |       shouldHaveRoot | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('text should wrap with icon', () => { |   it('text shouhld wrap with icon', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `mindmap |       `mindmap | ||||||
| root | root | ||||||
| @@ -246,22 +246,5 @@ Word!\`] | |||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|   describe('Include char sequence "graph" in text (#6795)', () => { |  | ||||||
|     it('has a label with char sequence "graph"', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         mindmap |  | ||||||
|           root |  | ||||||
|             Photograph |  | ||||||
|               Waterfall |  | ||||||
|               Landscape |  | ||||||
|             Geography |  | ||||||
|               Mountains |  | ||||||
|               Rocks |  | ||||||
|         `, |  | ||||||
|         { flowchart: { defaultRenderer: 'elk' } } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|   /* The end */ |   /* The end */ | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,146 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| const looks = ['classic', 'handDrawn'] as const; |  | ||||||
| const directions = [ |  | ||||||
|   'TB', |  | ||||||
|   //'BT', |  | ||||||
|   'LR', |  | ||||||
|   //'RL' |  | ||||||
| ] as const; |  | ||||||
| const newShapesSet1 = [ |  | ||||||
|   'triangle', |  | ||||||
|   'sloped-rectangle', |  | ||||||
|   'horizontal-cylinder', |  | ||||||
|   'flipped-triangle', |  | ||||||
|   'hourglass', |  | ||||||
| ] as const; |  | ||||||
| const newShapesSet2 = [ |  | ||||||
|   'tagged-rectangle', |  | ||||||
|   'documents', |  | ||||||
|   'lightning-bolt', |  | ||||||
|   'filled-circle', |  | ||||||
|   'window-pane', |  | ||||||
| ] as const; |  | ||||||
|  |  | ||||||
| const newShapesSet3 = [ |  | ||||||
|   'curved-trapezoid', |  | ||||||
|   'bow-rect', |  | ||||||
|   'tagged-document', |  | ||||||
|   'divided-rectangle', |  | ||||||
|   'crossed-circle', |  | ||||||
| ] as const; |  | ||||||
|  |  | ||||||
| const newShapesSet4 = [ |  | ||||||
|   'document', |  | ||||||
|   'notched-pentagon', |  | ||||||
|   'lined-cylinder', |  | ||||||
|   'stacked-document', |  | ||||||
|   'half-rounded-rectangle', |  | ||||||
| ] as const; |  | ||||||
|  |  | ||||||
| const newShapesSet5 = [ |  | ||||||
|   'lined-document', |  | ||||||
|   'tagged-document', |  | ||||||
|   'brace-l', |  | ||||||
|   'comment', |  | ||||||
|   'braces', |  | ||||||
|   'brace-r', |  | ||||||
| ] as const; |  | ||||||
|  |  | ||||||
| const newShapesSet6 = ['brace-r', 'braces'] as const; |  | ||||||
| // Aggregate all shape sets into a single array |  | ||||||
| const newShapesSets = [ |  | ||||||
|   newShapesSet1, |  | ||||||
|   newShapesSet2, |  | ||||||
|   newShapesSet3, |  | ||||||
|   newShapesSet4, |  | ||||||
|   newShapesSet5, |  | ||||||
|   newShapesSet6, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| looks.forEach((look) => { |  | ||||||
|   directions.forEach((direction) => { |  | ||||||
|     newShapesSets.forEach((newShapesSet) => { |  | ||||||
|       describe(`Test ${newShapesSet.join(', ')} in ${look} look and dir ${direction}`, () => { |  | ||||||
|         it(`without label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape} }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`connect all shapes with each other`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           for (let i = 0; i < newShapesSet.length; i++) { |  | ||||||
|             for (let j = i + 1; j < newShapesSet.length; j++) { |  | ||||||
|               flowchartCode += `  n${i}${i} --> n${j}${j}\n`; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|           if (!(direction === 'TB' && look === 'handDrawn' && newShapesSet === newShapesSet1)) { |  | ||||||
|             //skip this test, works in real. Need to look |  | ||||||
|             imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with very long label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with markdown htmlLabels:true`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with markdown htmlLabels:false`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { |  | ||||||
|             look, |  | ||||||
|             htmlLabels: false, |  | ||||||
|             flowchart: { htmlLabels: false }, |  | ||||||
|           }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with styles`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; |  | ||||||
|             flowchartCode += `  style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with classDef`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; |  | ||||||
|           newShapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; |  | ||||||
|             flowchartCode += `  n${index}${index}:::customClazz\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -1,107 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util'; |  | ||||||
|  |  | ||||||
| const looks = ['classic', 'handDrawn'] as const; |  | ||||||
| const directions = [ |  | ||||||
|   'TB', |  | ||||||
|   //'BT', |  | ||||||
|   'LR', |  | ||||||
|   //'RL' |  | ||||||
| ] as const; |  | ||||||
|  |  | ||||||
| const shapesSet1 = ['text', 'card', 'lin-rect', 'diamond', 'hexagon'] as const; |  | ||||||
|  |  | ||||||
| // removing labelRect, need have alias for it |  | ||||||
| const shapesSet2 = ['rounded', 'rect', 'start', 'stop'] as const; |  | ||||||
|  |  | ||||||
| const shapesSet3 = ['fork', 'choice', 'note', 'stadium', 'odd'] as const; |  | ||||||
|  |  | ||||||
| const shapesSet4 = ['subroutine', 'cylinder', 'circle', 'doublecircle', 'odd'] as const; |  | ||||||
|  |  | ||||||
| const shapesSet5 = ['anchor', 'lean-r', 'lean-l', 'trap-t', 'trap-b'] as const; |  | ||||||
|  |  | ||||||
| // Aggregate all shape sets into a single array |  | ||||||
| const shapesSets = [shapesSet1, shapesSet2, shapesSet3, shapesSet4, shapesSet5] as const; |  | ||||||
|  |  | ||||||
| looks.forEach((look) => { |  | ||||||
|   directions.forEach((direction) => { |  | ||||||
|     shapesSets.forEach((shapesSet) => { |  | ||||||
|       describe(`Test ${shapesSet.join(', ')} in ${look} look and dir ${direction}`, () => { |  | ||||||
|         it(`without label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape} }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`connect all shapes with each other`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           for (let i = 0; i < shapesSet.length; i++) { |  | ||||||
|             for (let j = i + 1; j < shapesSet.length; j++) { |  | ||||||
|               flowchartCode += `  n${i}${i} --> n${j}${j}\n`; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with very long label`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with markdown htmlLabels:true`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with markdown htmlLabels:false`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { |  | ||||||
|             look, |  | ||||||
|             htmlLabels: false, |  | ||||||
|             flowchart: { htmlLabels: false }, |  | ||||||
|           }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with styles`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; |  | ||||||
|             flowchartCode += `  style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         it(`with classDef`, () => { |  | ||||||
|           let flowchartCode = `flowchart ${direction}\n`; |  | ||||||
|           flowchartCode += `  classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; |  | ||||||
|           shapesSet.forEach((newShape, index) => { |  | ||||||
|             flowchartCode += `  n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`; |  | ||||||
|             flowchartCode += `  n${index}${index}:::customClazz\n`; |  | ||||||
|           }); |  | ||||||
|           imgSnapshotTest(flowchartCode, { look }); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util'; | import { imgSnapshotTest } from '../../helpers/util'; | ||||||
|  |  | ||||||
| describe('packet structure', () => { | describe('packet structure', () => { | ||||||
|   it('should render a simple packet-beta diagram', () => { |   it('should render a simple packet diagram', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `packet-beta |       `packet-beta | ||||||
|   title Hello world |   title Hello world | ||||||
| @@ -10,18 +10,9 @@ describe('packet structure', () => { | |||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should render a simple packet diagram', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `packet |  | ||||||
|   title Hello world |  | ||||||
|   0-10: "hello" |  | ||||||
| ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render a simple packet diagram without ranges', () => { |   it('should render a simple packet diagram without ranges', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `packet |       `packet-beta | ||||||
|   0: "h" |   0: "h" | ||||||
|   1: "i" |   1: "i" | ||||||
| ` | ` | ||||||
| @@ -30,7 +21,7 @@ describe('packet structure', () => { | |||||||
|  |  | ||||||
|   it('should render a complex packet diagram', () => { |   it('should render a complex packet diagram', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `packet |       `packet-beta | ||||||
|         0-15: "Source Port" |         0-15: "Source Port" | ||||||
|         16-31: "Destination Port" |         16-31: "Destination Port" | ||||||
|         32-63: "Sequence Number" |         32-63: "Sequence Number" | ||||||
| @@ -61,7 +52,7 @@ describe('packet structure', () => { | |||||||
|         packet: |         packet: | ||||||
|           showBits: false |           showBits: false | ||||||
|       --- |       --- | ||||||
|       packet |       packet-beta | ||||||
|         0-15: "Source Port" |         0-15: "Source Port" | ||||||
|         16-31: "Destination Port" |         16-31: "Destination Port" | ||||||
|         32-63: "Sequence Number" |         32-63: "Sequence Number" | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ describe('pie chart', () => { | |||||||
|     }); |     }); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should render a pie diagram when textPosition is set', () => { |   it('should render a pie diagram when textPosition is setted', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       `pie |       `pie | ||||||
|         "Dogs": 50 |         "Dogs": 50 | ||||||
| @@ -82,13 +82,4 @@ describe('pie chart', () => { | |||||||
|       ` |       ` | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should render pie slices only for non-zero values but shows all legends', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `   pie title Pets adopted by volunteers |  | ||||||
|     "Dogs" : 386 |  | ||||||
|     "Cats" : 85 |  | ||||||
|     "Rats" : 1 |  | ||||||
|       ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ describe('Quadrant Chart', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should able to render y-axis on right side', () => { |   it('should able to render y-axix on right side', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|   %%{init: {"quadrantChart": {"yAxisPosition": "right"}}}%% |   %%{init: {"quadrantChart": {"yAxisPosition": "right"}}}%% | ||||||
| @@ -61,7 +61,7 @@ describe('Quadrant Chart', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should able to render x-axis on bottom', () => { |   it('should able to render x-axix on bottom', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|   %%{init: {"quadrantChart": {"xAxisPosition": "bottom"}}}%% |   %%{init: {"quadrantChart": {"xAxisPosition": "bottom"}}}%% | ||||||
| @@ -77,7 +77,7 @@ describe('Quadrant Chart', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should able to render x-axis on bottom and y-axis on right', () => { |   it('should able to render x-axix on bottom and y-axis on right', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|   %%{init: {"quadrantChart": {"xAxisPosition": "bottom", "yAxisPosition": "right"}}}%% |   %%{init: {"quadrantChart": {"xAxisPosition": "bottom", "yAxisPosition": "right"}}}%% | ||||||
|   | |||||||
| @@ -1,79 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util'; |  | ||||||
|  |  | ||||||
| describe('radar structure', () => { |  | ||||||
|   it('should render a simple radar diagram', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `radar-beta |  | ||||||
|                 title Best Radar Ever |  | ||||||
|                 axis A, B, C |  | ||||||
|                 curve c1{1, 2, 3} |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render a radar diagram with multiple curves', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `radar-beta |  | ||||||
|                 title Best Radar Ever |  | ||||||
|                 axis A, B, C |  | ||||||
|                 curve c1{1, 2, 3} |  | ||||||
|                 curve c2{2, 3, 1} |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render a complex radar diagram', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `radar-beta  |  | ||||||
|                 title My favorite ninjas |  | ||||||
|                 axis Agility, Speed, Strength |  | ||||||
|                 axis Stam["Stamina"] , Intel["Intelligence"] |  | ||||||
|  |  | ||||||
|                 curve Ninja1["Naruto Uzumaki"]{ |  | ||||||
|                     Agility 2, Speed 2, |  | ||||||
|                     Strength 3, Stam 5, |  | ||||||
|                     Intel 0 |  | ||||||
|                 } |  | ||||||
|                 curve Ninja2["Sasuke"]{2, 3, 4, 1, 5} |  | ||||||
|                 curve Ninja3 {3, 2, 1, 5, 4} |  | ||||||
|  |  | ||||||
|                 showLegend true |  | ||||||
|                 ticks 3 |  | ||||||
|                 max 8 |  | ||||||
|                 min 0 |  | ||||||
|                 graticule polygon |  | ||||||
|             ` |  | ||||||
|     ); |  | ||||||
|     cy.get('svg').should((svg) => { |  | ||||||
|       expect(svg).to.have.length(1); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render radar diagram with config override', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `radar-beta |  | ||||||
|                 title Best Radar Ever |  | ||||||
|                 axis A,B,C |  | ||||||
|                 curve mycurve{1,2,3}`, |  | ||||||
|       { radar: { marginTop: 100, axisScaleFactor: 0.5 } } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should parse radar diagram with theme override', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `radar-beta |  | ||||||
|                 axis A,B,C |  | ||||||
|                 curve mycurve{1,2,3}`, |  | ||||||
|       { theme: 'base', themeVariables: { fontSize: 80, cScale0: '#FF0000' } } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should handle radar diagram with radar style override', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `radar-beta |  | ||||||
|                 axis A,B,C |  | ||||||
|                 curve mycurve{1,2,3}`, |  | ||||||
|       { theme: 'base', themeVariables: { radar: { axisColor: '#FF0000' } } } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -1,703 +0,0 @@ | |||||||
| import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| const testOptions = [ |  | ||||||
|   { description: '', options: { logLevel: 1 } }, |  | ||||||
|   { description: 'ELK: ', options: { logLevel: 1, layout: 'elk' } }, |  | ||||||
|   { description: 'HD: ', options: { logLevel: 1, look: 'handDrawn' } }, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| describe('Requirement Diagram Unified', () => { |  | ||||||
|   testOptions.forEach(({ description, options }) => { |  | ||||||
|     it(`${description}should render a simple Requirement diagram`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|         requirement test_req { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         test_entity - satisfies -> test_req |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a simple Requirement diagram without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|         requirement test_req { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         test_entity - satisfies -> test_req |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a not-so-simple Requirement diagram`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|  |  | ||||||
|         requirement test_req { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         functionalRequirement test_req2 { |  | ||||||
|         id: 1.1 |  | ||||||
|         text: the second test text. |  | ||||||
|         risk: low |  | ||||||
|         verifymethod: inspection |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         performanceRequirement test_req3 { |  | ||||||
|         id: 1.2 |  | ||||||
|         text: the third test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: demonstration |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         interfaceRequirement test_req4 { |  | ||||||
|         id: 1.2.1 |  | ||||||
|         text: the fourth test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: analysis |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         physicalRequirement test_req5 { |  | ||||||
|         id: 1.2.2 |  | ||||||
|         text: the fifth test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: analysis |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         designConstraint test_req6 { |  | ||||||
|         id: 1.2.3 |  | ||||||
|         text: the sixth test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: analysis |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity2 { |  | ||||||
|         type: word doc |  | ||||||
|         docRef: reqs/test_entity |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity3 { |  | ||||||
|         type: "test suite" |  | ||||||
|         docRef: github.com/all_the_tests |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         test_entity - satisfies -> test_req2 |  | ||||||
|         test_req - traces -> test_req2 |  | ||||||
|         test_req - contains -> test_req3 |  | ||||||
|         test_req3 - contains -> test_req4 |  | ||||||
|         test_req4 - derives -> test_req5 |  | ||||||
|         test_req5 - refines -> test_req6 |  | ||||||
|         test_entity3 - verifies -> test_req5 |  | ||||||
|         test_req <- copies - test_entity2 |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a not-so-simple Requirement diagram without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|  |  | ||||||
|         requirement test_req { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         functionalRequirement test_req2 { |  | ||||||
|         id: 1.1 |  | ||||||
|         text: the second test text. |  | ||||||
|         risk: low |  | ||||||
|         verifymethod: inspection |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         performanceRequirement test_req3 { |  | ||||||
|         id: 1.2 |  | ||||||
|         text: the third test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: demonstration |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         interfaceRequirement test_req4 { |  | ||||||
|         id: 1.2.1 |  | ||||||
|         text: the fourth test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: analysis |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         physicalRequirement test_req5 { |  | ||||||
|         id: 1.2.2 |  | ||||||
|         text: the fifth test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: analysis |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         designConstraint test_req6 { |  | ||||||
|         id: 1.2.3 |  | ||||||
|         text: the sixth test text. |  | ||||||
|         risk: medium |  | ||||||
|         verifymethod: analysis |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity2 { |  | ||||||
|         type: word doc |  | ||||||
|         docRef: reqs/test_entity |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         element test_entity3 { |  | ||||||
|         type: "test suite" |  | ||||||
|         docRef: github.com/all_the_tests |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         test_entity - satisfies -> test_req2 |  | ||||||
|         test_req - traces -> test_req2 |  | ||||||
|         test_req - contains -> test_req3 |  | ||||||
|         test_req3 - contains -> test_req4 |  | ||||||
|         test_req4 - derives -> test_req5 |  | ||||||
|         test_req5 - refines -> test_req6 |  | ||||||
|         test_entity3 - verifies -> test_req5 |  | ||||||
|         test_req <- copies - test_entity2 |  | ||||||
|         `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render multiple Requirement diagrams`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         [ |  | ||||||
|           ` |  | ||||||
|     requirementDiagram |  | ||||||
|  |  | ||||||
|     requirement test_req { |  | ||||||
|     id: 1 |  | ||||||
|     text: the test text. |  | ||||||
|     risk: high |  | ||||||
|     verifymethod: test |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     element test_entity { |  | ||||||
|     type: simulation |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     test_entity - satisfies -> test_req |  | ||||||
|     `, |  | ||||||
|           ` |  | ||||||
|     requirementDiagram |  | ||||||
|  |  | ||||||
|     requirement test_req { |  | ||||||
|     id: 1 |  | ||||||
|     text: the test text. |  | ||||||
|     risk: high |  | ||||||
|     verifymethod: test |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     element test_entity { |  | ||||||
|     type: simulation |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     test_entity - satisfies -> test_req |  | ||||||
|     `, |  | ||||||
|         ], |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a Requirement diagram with empty information`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|         requirement test_req { |  | ||||||
|         } |  | ||||||
|         element test_entity { |  | ||||||
|         } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with and without information`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|         requirement test_req { |  | ||||||
|             id: 1 |  | ||||||
|             text: the test text. |  | ||||||
|             risk: high |  | ||||||
|             verifymethod: test |  | ||||||
|         } |  | ||||||
|         element test_entity { |  | ||||||
|         } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with long and short text`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|         requirement test_req { |  | ||||||
|             id: 1 |  | ||||||
|             text: the test text that is long and takes up a lot of space. |  | ||||||
|             risk: high |  | ||||||
|             verifymethod: test |  | ||||||
|         } |  | ||||||
|         element test_entity_name_that_is_extra_long { |  | ||||||
|         } |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with long and short text without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|           requirement test_req { |  | ||||||
|               id: 1 |  | ||||||
|               text: the test text that is long and takes up a lot of space. |  | ||||||
|               risk: high |  | ||||||
|               verifymethod: test |  | ||||||
|           } |  | ||||||
|           element test_entity_name_that_is_extra_long { |  | ||||||
|           } |  | ||||||
|           `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with quoted text for spaces`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|           requirement "test req name with spaces" { |  | ||||||
|               id: 1 |  | ||||||
|               text: the test text that is long and takes up a lot of space. |  | ||||||
|               risk: high |  | ||||||
|               verifymethod: test |  | ||||||
|           } |  | ||||||
|           element "test entity name that is extra long with spaces" { |  | ||||||
|           } |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with markdown text`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|           requirement "__my bolded name__" { |  | ||||||
|               id: 1 |  | ||||||
|               text: "**Bolded text** _italicized text_" |  | ||||||
|               risk: high |  | ||||||
|               verifymethod: test |  | ||||||
|           } |  | ||||||
|           element "*my italicized name*" { |  | ||||||
|             type: "**Bolded type** _italicized type_" |  | ||||||
|             docref: "*Italicized* __Bolded__" |  | ||||||
|           } |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with markdown text without htmlLabels`, () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|           requirement "__my bolded name__" { |  | ||||||
|               id: 1 |  | ||||||
|               text: "**Bolded text** _italicized text_" |  | ||||||
|               risk: high |  | ||||||
|               verifymethod: test |  | ||||||
|           } |  | ||||||
|           element "*my italicized name*" { |  | ||||||
|             type: "**Bolded type** _italicized type_" |  | ||||||
|             docref: "*Italicized* __Bolded__" |  | ||||||
|           } |  | ||||||
|           `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a simple Requirement diagram with a title`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         `--- |  | ||||||
|   title: simple Requirement diagram |  | ||||||
|   --- |  | ||||||
|     requirementDiagram |  | ||||||
|  |  | ||||||
|     requirement test_req { |  | ||||||
|     id: 1 |  | ||||||
|     text: the test text. |  | ||||||
|     risk: high |  | ||||||
|     verifymethod: test |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     element test_entity { |  | ||||||
|     type: simulation |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     test_entity - satisfies -> test_req |  | ||||||
|   `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a Requirement diagram with TB direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|     direction TB |  | ||||||
|  |  | ||||||
|     requirement test_req { |  | ||||||
|     id: 1 |  | ||||||
|     text: the test text. |  | ||||||
|     risk: high |  | ||||||
|     verifymethod: test |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     element test_entity { |  | ||||||
|     type: simulation |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     test_entity - satisfies -> test_req |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a Requirement diagram with BT direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|       direction BT |  | ||||||
|    |  | ||||||
|       requirement test_req { |  | ||||||
|       id: 1 |  | ||||||
|       text: the test text. |  | ||||||
|       risk: high |  | ||||||
|       verifymethod: test |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       element test_entity { |  | ||||||
|       type: simulation |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       test_entity - satisfies -> test_req |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a Requirement diagram with LR direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|       direction LR |  | ||||||
|    |  | ||||||
|       requirement test_req { |  | ||||||
|       id: 1 |  | ||||||
|       text: the test text. |  | ||||||
|       risk: high |  | ||||||
|       verifymethod: test |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       element test_entity { |  | ||||||
|       type: simulation |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       test_entity - satisfies -> test_req |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a Requirement diagram with RL direction`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|       direction RL |  | ||||||
|    |  | ||||||
|       requirement test_req { |  | ||||||
|       id: 1 |  | ||||||
|       text: the test text. |  | ||||||
|       risk: high |  | ||||||
|       verifymethod: test |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       element test_entity { |  | ||||||
|       type: simulation |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       test_entity - satisfies -> test_req |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from style statement`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|     requirementDiagram |  | ||||||
|  |  | ||||||
|     requirement test_req { |  | ||||||
|     id: 1 |  | ||||||
|     text: the test text. |  | ||||||
|     risk: high |  | ||||||
|     verifymethod: test |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     element test_entity { |  | ||||||
|     type: simulation |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     test_entity - satisfies -> test_req |  | ||||||
|  |  | ||||||
|     style test_req,test_entity fill:#f9f,stroke:blue, color:grey, font-weight:bold |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from style statement without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       requirementDiagram |  | ||||||
|    |  | ||||||
|       requirement test_req { |  | ||||||
|       id: 1 |  | ||||||
|       text: the test text. |  | ||||||
|       risk: high |  | ||||||
|       verifymethod: test |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       element test_entity { |  | ||||||
|       type: simulation |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       test_entity - satisfies -> test_req |  | ||||||
|    |  | ||||||
|       style test_req,test_entity fill:#f9f,stroke:blue, color:grey, font-weight:bold |  | ||||||
|           `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from class statement`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
| requirementDiagram |  | ||||||
|    |  | ||||||
|       requirement test_req { |  | ||||||
|       id: 1 |  | ||||||
|       text: the test text. |  | ||||||
|       risk: high |  | ||||||
|       verifymethod: test |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       element test_entity { |  | ||||||
|       type: simulation |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       test_entity - satisfies -> test_req |  | ||||||
|       classDef bold font-weight: bold |  | ||||||
|       classDef blue stroke:lightblue, color: #0000FF |  | ||||||
|       class test_entity bold |  | ||||||
|       class test_req blue, bold |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from class statement without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|   requirementDiagram |  | ||||||
|      |  | ||||||
|         requirement test_req { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         test_entity - satisfies -> test_req |  | ||||||
|         classDef bold font-weight: bold |  | ||||||
|         classDef blue stroke:lightblue, color: #0000FF |  | ||||||
|         class test_entity bold |  | ||||||
|         class test_req blue, bold |  | ||||||
|           `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from classes with shorthand syntax`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|   requirementDiagram |  | ||||||
|      |  | ||||||
|         requirement test_req:::blue { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         test_entity - satisfies -> test_req |  | ||||||
|         classDef bold font-weight: bold |  | ||||||
|         classDef blue stroke:lightblue, color: #0000FF |  | ||||||
|         test_entity:::bold |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from classes with shorthand syntax without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|   requirementDiagram |  | ||||||
|      |  | ||||||
|         requirement test_req:::blue { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         test_entity - satisfies -> test_req |  | ||||||
|         classDef bold font-weight: bold |  | ||||||
|         classDef blue stroke:lightblue, color: #0000FF |  | ||||||
|         test_entity:::bold |  | ||||||
|           `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from the default class and other styles`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
| requirementDiagram |  | ||||||
|    |  | ||||||
|       requirement test_req:::blue { |  | ||||||
|       id: 1 |  | ||||||
|       text: the test text. |  | ||||||
|       risk: high |  | ||||||
|       verifymethod: test |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       element test_entity { |  | ||||||
|       type: simulation |  | ||||||
|       } |  | ||||||
|    |  | ||||||
|       test_entity - satisfies -> test_req |  | ||||||
|       classDef blue stroke:lightblue, color:blue |  | ||||||
|       classDef default fill:pink |  | ||||||
|       style test_entity color:green |  | ||||||
|         `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render requirements and elements with styles applied from the default class and other styles without htmlLabels`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|   requirementDiagram |  | ||||||
|      |  | ||||||
|         requirement test_req:::blue { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         test_entity - satisfies -> test_req |  | ||||||
|         classDef blue stroke:lightblue, color:blue |  | ||||||
|         classDef default fill:pink |  | ||||||
|         style test_entity color:green |  | ||||||
|           `, |  | ||||||
|         { ...options, htmlLabels: false } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it(`${description}should render a Requirement diagram with a theme`, () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
| --- |  | ||||||
|   theme: forest |  | ||||||
| --- |  | ||||||
|   requirementDiagram |  | ||||||
|      |  | ||||||
|         requirement test_req:::blue { |  | ||||||
|         id: 1 |  | ||||||
|         text: the test text. |  | ||||||
|         risk: high |  | ||||||
|         verifymethod: test |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         element test_entity { |  | ||||||
|         type: simulation |  | ||||||
|         } |  | ||||||
|      |  | ||||||
|         test_entity - satisfies -> test_req |  | ||||||
|           `, |  | ||||||
|         options |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -15,7 +15,7 @@ describe('Sankey Diagram', () => { | |||||||
|   describe('when given a linkColor', function () { |   describe('when given a linkColor', function () { | ||||||
|     this.beforeAll(() => { |     this.beforeAll(() => { | ||||||
|       cy.wrap( |       cy.wrap( | ||||||
|         `sankey |         `sankey-beta | ||||||
|       a,b,10 |       a,b,10 | ||||||
|       ` |       ` | ||||||
|       ).as('graph'); |       ).as('graph'); | ||||||
| @@ -62,7 +62,7 @@ describe('Sankey Diagram', () => { | |||||||
|     this.beforeAll(() => { |     this.beforeAll(() => { | ||||||
|       cy.wrap( |       cy.wrap( | ||||||
|         ` |         ` | ||||||
|         sankey |         sankey-beta | ||||||
|          |          | ||||||
|         a,b,8 |         a,b,8 | ||||||
|         b,c,8 |         b,c,8 | ||||||
|   | |||||||
| @@ -1,659 +0,0 @@ | |||||||
| import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| const looks = ['classic']; |  | ||||||
| const participantTypes = [ |  | ||||||
|   { type: 'participant', display: 'participant' }, |  | ||||||
|   { type: 'actor', display: 'actor' }, |  | ||||||
|   { type: 'boundary', display: 'boundary' }, |  | ||||||
|   { type: 'control', display: 'control' }, |  | ||||||
|   { type: 'entity', display: 'entity' }, |  | ||||||
|   { type: 'database', display: 'database' }, |  | ||||||
|   { type: 'collections', display: 'collections' }, |  | ||||||
|   { type: 'queue', display: 'queue' }, |  | ||||||
| ]; |  | ||||||
|  |  | ||||||
| const restrictedTypes = ['boundary', 'control', 'entity', 'database', 'collections', 'queue']; |  | ||||||
|  |  | ||||||
| const interactionTypes = ['->>', '-->>', '->', '-->', '-x', '--x', '->>+', '-->>+']; |  | ||||||
|  |  | ||||||
| const notePositions = ['left of', 'right of', 'over']; |  | ||||||
|  |  | ||||||
| function getParticipantLine(name, type, alias) { |  | ||||||
|   if (restrictedTypes.includes(type)) { |  | ||||||
|     return `  participant ${name}@{ "type" : "${type}" }\n`; |  | ||||||
|   } else if (alias) { |  | ||||||
|     return `  participant ${name}@{ "type" : "${type}" } \n`; |  | ||||||
|   } else { |  | ||||||
|     return `  participant ${name}@{ "type" : "${type}" }\n`; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| looks.forEach((look) => { |  | ||||||
|   describe(`Sequence Diagram Tests - ${look} look`, () => { |  | ||||||
|     it('should render all participant types', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       participantTypes.forEach((pt, index) => { |  | ||||||
|         const name = `${pt.display}${index}`; |  | ||||||
|         diagramCode += getParticipantLine(name, pt.type); |  | ||||||
|       }); |  | ||||||
|       for (let i = 0; i < participantTypes.length - 1; i++) { |  | ||||||
|         diagramCode += `  ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`; |  | ||||||
|       } |  | ||||||
|       imgSnapshotTest(diagramCode, { look, sequence: { diagramMarginX: 50, diagramMarginY: 10 } }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render all interaction types', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       diagramCode += getParticipantLine('A', 'actor'); |  | ||||||
|       diagramCode += getParticipantLine('B', 'boundary'); |  | ||||||
|       interactionTypes.forEach((interaction, index) => { |  | ||||||
|         diagramCode += `  A ${interaction} B: ${interaction} message ${index}\n`; |  | ||||||
|       }); |  | ||||||
|       imgSnapshotTest(diagramCode, { look }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render participant creation and destruction', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       participantTypes.forEach((pt, index) => { |  | ||||||
|         const name = `${pt.display}${index}`; |  | ||||||
|         diagramCode += getParticipantLine('A', pt.type); |  | ||||||
|         diagramCode += getParticipantLine('B', pt.type); |  | ||||||
|         diagramCode += `  create participant ${name}@{ "type" : "${pt.type}" }\n`; |  | ||||||
|         diagramCode += `  A ->> ${name}: Hello ${pt.display}\n`; |  | ||||||
|         if (index % 2 === 0) { |  | ||||||
|           diagramCode += `  destroy ${name}\n`; |  | ||||||
|         } |  | ||||||
|       }); |  | ||||||
|       imgSnapshotTest(diagramCode, { look }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render notes in all positions', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       diagramCode += getParticipantLine('A', 'actor'); |  | ||||||
|       diagramCode += getParticipantLine('B', 'boundary'); |  | ||||||
|       notePositions.forEach((position, index) => { |  | ||||||
|         diagramCode += `  Note ${position} A: Note ${position} ${index}\n`; |  | ||||||
|       }); |  | ||||||
|       diagramCode += `  A ->> B: Message with notes\n`; |  | ||||||
|       imgSnapshotTest(diagramCode, { look }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render parallel interactions', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       participantTypes.slice(0, 4).forEach((pt, index) => { |  | ||||||
|         diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type); |  | ||||||
|       }); |  | ||||||
|       diagramCode += `  par Parallel actions\n`; |  | ||||||
|       for (let i = 0; i < 3; i += 2) { |  | ||||||
|         diagramCode += `    ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`; |  | ||||||
|         if (i < participantTypes.length - 2) { |  | ||||||
|           diagramCode += `    and\n`; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       diagramCode += `  end\n`; |  | ||||||
|       imgSnapshotTest(diagramCode, { look }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render alternative flows', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       diagramCode += getParticipantLine('A', 'actor'); |  | ||||||
|       diagramCode += getParticipantLine('B', 'boundary'); |  | ||||||
|       diagramCode += `  alt Successful case\n`; |  | ||||||
|       diagramCode += `    A ->> B: Request\n`; |  | ||||||
|       diagramCode += `    B -->> A: Success\n`; |  | ||||||
|       diagramCode += `  else Failure case\n`; |  | ||||||
|       diagramCode += `    A ->> B: Request\n`; |  | ||||||
|       diagramCode += `    B --x A: Failure\n`; |  | ||||||
|       diagramCode += `  end\n`; |  | ||||||
|       imgSnapshotTest(diagramCode, { look }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render loops', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       participantTypes.slice(0, 3).forEach((pt, index) => { |  | ||||||
|         diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type); |  | ||||||
|       }); |  | ||||||
|       diagramCode += `  loop For each participant\n`; |  | ||||||
|       for (let i = 0; i < 3; i++) { |  | ||||||
|         diagramCode += `    ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Message ${i}\n`; |  | ||||||
|       } |  | ||||||
|       diagramCode += `  end\n`; |  | ||||||
|       imgSnapshotTest(diagramCode, { look }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render boxes around groups', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       diagramCode += `  box Group 1\n`; |  | ||||||
|       participantTypes.slice(0, 3).forEach((pt, index) => { |  | ||||||
|         diagramCode += `    ${getParticipantLine(`${pt.display}${index}`, pt.type)}`; |  | ||||||
|       }); |  | ||||||
|       diagramCode += `  end\n`; |  | ||||||
|       diagramCode += `  box rgb(200,220,255) Group 2\n`; |  | ||||||
|       participantTypes.slice(3, 6).forEach((pt, index) => { |  | ||||||
|         diagramCode += `    ${getParticipantLine(`${pt.display}${index}`, pt.type)}`; |  | ||||||
|       }); |  | ||||||
|       diagramCode += `  end\n`; |  | ||||||
|       diagramCode += `  ${participantTypes[0].display}0 ->> ${participantTypes[3].display}0: Cross-group message\n`; |  | ||||||
|       imgSnapshotTest(diagramCode, { look }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render with different font settings', () => { |  | ||||||
|       let diagramCode = `sequenceDiagram\n`; |  | ||||||
|       participantTypes.slice(0, 3).forEach((pt, index) => { |  | ||||||
|         diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type); |  | ||||||
|       }); |  | ||||||
|       diagramCode += `  ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Regular message\n`; |  | ||||||
|       diagramCode += `  Note right of ${participantTypes[1].display}1: Regular note\n`; |  | ||||||
|       imgSnapshotTest(diagramCode, { |  | ||||||
|         look, |  | ||||||
|         sequence: { |  | ||||||
|           actorFontFamily: 'courier', |  | ||||||
|           actorFontSize: 14, |  | ||||||
|           messageFontFamily: 'Arial', |  | ||||||
|           messageFontSize: 12, |  | ||||||
|           noteFontFamily: 'times', |  | ||||||
|           noteFontSize: 16, |  | ||||||
|           noteAlign: 'left', |  | ||||||
|         }, |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| // Additional tests for specific combinations |  | ||||||
| describe('Sequence Diagram Special Cases', () => { |  | ||||||
|   it('should render complex sequence with all features', () => { |  | ||||||
|     const diagramCode = ` |  | ||||||
|       sequenceDiagram |  | ||||||
|         box rgb(200,220,255) Authentication |  | ||||||
|           actor User |  | ||||||
|           participant LoginUI@{ "type": "boundary" } |  | ||||||
|           participant AuthService@{ "type": "control" } |  | ||||||
|           participant UserDB@{ "type": "database" } |  | ||||||
|         end |  | ||||||
|  |  | ||||||
|         box rgb(200,255,220) Order Processing |  | ||||||
|           participant Order@{ "type": "entity" } |  | ||||||
|           participant OrderQueue@{ "type": "queue" } |  | ||||||
|           participant AuditLogs@{ "type": "collections" } |  | ||||||
|         end |  | ||||||
|          |  | ||||||
|         User ->> LoginUI: Enter credentials |  | ||||||
|         LoginUI ->> AuthService: Validate |  | ||||||
|         AuthService ->> UserDB: Query user |  | ||||||
|         UserDB -->> AuthService: User data |  | ||||||
|         alt Valid credentials |  | ||||||
|           AuthService -->> LoginUI: Success |  | ||||||
|           LoginUI -->> User: Welcome |  | ||||||
|            |  | ||||||
|           par Place order |  | ||||||
|             User ->> Order: New order |  | ||||||
|             Order ->> OrderQueue: Process |  | ||||||
|             and |  | ||||||
|             Order ->> AuditLogs: Record |  | ||||||
|           end |  | ||||||
|            |  | ||||||
|           loop Until confirmed |  | ||||||
|             OrderQueue ->> Order: Update status |  | ||||||
|             Order -->> User: Notification |  | ||||||
|           end |  | ||||||
|         else Invalid credentials |  | ||||||
|           AuthService --x LoginUI: Failure |  | ||||||
|           LoginUI --x User: Retry |  | ||||||
|         end |  | ||||||
|     `; |  | ||||||
|     imgSnapshotTest(diagramCode, {}); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render with wrapped messages and notes', () => { |  | ||||||
|     const diagramCode = ` |  | ||||||
|       sequenceDiagram |  | ||||||
|         participant A |  | ||||||
|         participant B |  | ||||||
|          |  | ||||||
|         A ->> B: This is a very long message that should wrap properly in the diagram rendering |  | ||||||
|         Note over A,B: This is a very long note that should also wrap properly when rendered in the diagram |  | ||||||
|          |  | ||||||
|         par Wrapped parallel |  | ||||||
|           A ->> B: Parallel message 1<br>with explicit line break |  | ||||||
|           and |  | ||||||
|           B ->> A: Parallel message 2<br>with explicit line break |  | ||||||
|         end |  | ||||||
|          |  | ||||||
|         loop Wrapped loop |  | ||||||
|           Note right of B: This is a long note<br>in a loop |  | ||||||
|           A ->> B: Message in loop |  | ||||||
|         end |  | ||||||
|     `; |  | ||||||
|     imgSnapshotTest(diagramCode, { sequence: { wrap: true } }); |  | ||||||
|   }); |  | ||||||
|   describe('Sequence Diagram Rendering with Different Participant Types', () => { |  | ||||||
|     it('should render a sequence diagram with various participant types', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|         sequenceDiagram |  | ||||||
|           participant User@{ "type": "actor" } |  | ||||||
|           participant AuthService@{ "type": "control" } |  | ||||||
|           participant UI@{ "type": "boundary" } |  | ||||||
|           participant OrderController@{ "type": "control" } |  | ||||||
|           participant Product@{ "type": "entity" } |  | ||||||
|           participant MongoDB@{ "type": "database" } |  | ||||||
|           participant Products@{ "type": "collections" } |  | ||||||
|           participant OrderQueue@{ "type": "queue" } |  | ||||||
|           User ->> UI: Login request |  | ||||||
|           UI ->> AuthService: Validate credentials |  | ||||||
|           AuthService -->> UI: Authentication token |  | ||||||
|           UI ->> OrderController: Place order |  | ||||||
|           OrderController ->> Product: Check availability |  | ||||||
|           Product -->> OrderController: Available |  | ||||||
|           OrderController ->> MongoDB: Save order |  | ||||||
|           MongoDB -->> OrderController: Order saved |  | ||||||
|           OrderController ->> OrderQueue: Process payment |  | ||||||
|           OrderQueue -->> User: Order confirmation |  | ||||||
|       ` |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render participant creation and destruction with different types', () => { |  | ||||||
|       imgSnapshotTest(` |  | ||||||
|       sequenceDiagram |  | ||||||
|           participant Alice@{ "type" : "boundary" } |  | ||||||
|           Alice->>Bob: Hello Bob, how are you ? |  | ||||||
|           Bob->>Alice: Fine, thank you. And you? |  | ||||||
|           create participant Carl@{ "type" : "control" } |  | ||||||
|           Alice->>Carl: Hi Carl! |  | ||||||
|           create actor D as Donald |  | ||||||
|           Carl->>D: Hi! |  | ||||||
|           destroy Carl |  | ||||||
|           Alice-xCarl: We are too many |  | ||||||
|           destroy Bob |  | ||||||
|           Bob->>Alice: I agree |  | ||||||
|       `); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should handle complex interactions between different participant types', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|      sequenceDiagram |  | ||||||
|         box rgb(200,220,255) Authentication |  | ||||||
|           participant User@{ "type": "actor" } |  | ||||||
|           participant LoginUI@{ "type": "boundary" } |  | ||||||
|           participant AuthService@{ "type": "control" } |  | ||||||
|           participant UserDB@{ "type": "database" } |  | ||||||
|         end |  | ||||||
|  |  | ||||||
|         box rgb(200,255,220) Order Processing |  | ||||||
|           participant Order@{ "type": "entity" } |  | ||||||
|           participant OrderQueue@{ "type": "queue" } |  | ||||||
|           participant AuditLogs@{ "type": "collections" } |  | ||||||
|         end |  | ||||||
|  |  | ||||||
|         User ->> LoginUI: Enter credentials |  | ||||||
|         LoginUI ->> AuthService: Validate |  | ||||||
|         AuthService ->> UserDB: Query user |  | ||||||
|         UserDB -->> AuthService: User data |  | ||||||
|  |  | ||||||
|         alt Valid credentials |  | ||||||
|           AuthService -->> LoginUI: Success |  | ||||||
|           LoginUI -->> User: Welcome |  | ||||||
|  |  | ||||||
|           par Place order |  | ||||||
|             User ->> Order: New order |  | ||||||
|             Order ->> OrderQueue: Process |  | ||||||
|             and |  | ||||||
|             Order ->> AuditLogs: Record |  | ||||||
|           end |  | ||||||
|  |  | ||||||
|           loop Until confirmed |  | ||||||
|             OrderQueue ->> Order: Update status |  | ||||||
|             Order -->> User: Notification |  | ||||||
|           end |  | ||||||
|         else Invalid credentials |  | ||||||
|           AuthService --x LoginUI: Failure |  | ||||||
|           LoginUI --x User: Retry |  | ||||||
|         end |  | ||||||
|       `, |  | ||||||
|         { sequence: { useMaxWidth: false } } |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render parallel processes with different participant types', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|        sequenceDiagram |  | ||||||
|         participant Customer@{ "type": "actor" } |  | ||||||
|         participant Frontend@{ "type": "participant" } |  | ||||||
|         participant PaymentService@{ "type": "boundary" } |  | ||||||
|         participant InventoryManager@{ "type": "control" } |  | ||||||
|         participant Order@{ "type": "entity" } |  | ||||||
|         participant OrdersDB@{ "type": "database" } |  | ||||||
|         participant NotificationQueue@{ "type": "queue" } |  | ||||||
|  |  | ||||||
|         Customer ->> Frontend: Place order |  | ||||||
|         Frontend ->> Order: Create order |  | ||||||
|         par Parallel Processing |  | ||||||
|           Order ->> PaymentService: Process payment |  | ||||||
|           and |  | ||||||
|           Order ->> InventoryManager: Reserve items |  | ||||||
|         end |  | ||||||
|         PaymentService -->> Order: Payment confirmed |  | ||||||
|         InventoryManager -->> Order: Items reserved |  | ||||||
|         Order ->> OrdersDB: Save finalized order |  | ||||||
|         OrdersDB -->> Order: Order saved |  | ||||||
|         Order ->> NotificationQueue: Send confirmation |  | ||||||
|         NotificationQueue -->> Customer: Order confirmation |  | ||||||
|       ` |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|   it('should render different participant types with notes and loops', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     sequenceDiagram |  | ||||||
|     actor Admin |  | ||||||
|     participant Dashboard |  | ||||||
|     participant AuthService@{ "type" : "boundary" } |  | ||||||
|     participant UserManager@{ "type" : "control" } |  | ||||||
|     participant UserProfile@{ "type" : "entity" } |  | ||||||
|     participant UserDB@{ "type" : "database" } |  | ||||||
|     participant Logs@{ "type" : "database" } |  | ||||||
|      |  | ||||||
|     Admin ->> Dashboard: Open user management |  | ||||||
|     loop Authentication check |  | ||||||
|       Dashboard ->> AuthService: Verify admin rights |  | ||||||
|       AuthService ->> Dashboard: Access granted |  | ||||||
|     end |  | ||||||
|     Dashboard ->> UserManager: List users |  | ||||||
|     UserManager ->> UserDB: Query users |  | ||||||
|     UserDB ->> UserManager: Return user data |  | ||||||
|     Note right of UserDB: Encrypted data<br/>requires decryption |  | ||||||
|     UserManager ->> UserProfile: Format profiles |  | ||||||
|     UserProfile ->> UserManager: Formatted data |  | ||||||
|     UserManager ->> Dashboard: Display users |  | ||||||
|     Dashboard ->> Logs: Record access |  | ||||||
|     Logs ->> Admin: Audit trail |  | ||||||
|     ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render different participant types with alternative flows', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     sequenceDiagram |  | ||||||
|       actor Client |  | ||||||
|       participant MobileApp |  | ||||||
|       participant CloudService@{ "type" : "boundary" } |  | ||||||
|       participant DataProcessor@{ "type" : "control" } |  | ||||||
|       participant Transaction@{ "type" : "entity" } |  | ||||||
|       participant TransactionsDB@{ "type" : "database" } |  | ||||||
|       participant EventBus@{ "type" : "queue" } |  | ||||||
|        |  | ||||||
|       Client ->> MobileApp: Initiate transaction |  | ||||||
|       MobileApp ->> CloudService: Authenticate |  | ||||||
|       alt Authentication successful |  | ||||||
|         CloudService -->> MobileApp: Auth token |  | ||||||
|         MobileApp ->> DataProcessor: Process data |  | ||||||
|         DataProcessor ->> Transaction: Create transaction |  | ||||||
|         Transaction ->> TransactionsDB: Save record |  | ||||||
|         TransactionsDB -->> Transaction: Confirmation |  | ||||||
|         Transaction ->> EventBus: Publish event |  | ||||||
|         EventBus -->> Client: Notification |  | ||||||
|       else Authentication failed |  | ||||||
|         CloudService -->> MobileApp: Error |  | ||||||
|         MobileApp -->> Client: Show error |  | ||||||
|       end |  | ||||||
|     ` |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render different participant types with wrapping text', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|   sequenceDiagram |  | ||||||
|       participant B@{ "type" : "boundary" } |  | ||||||
|       participant C@{ "type" : "control" } |  | ||||||
|       participant E@{ "type" : "entity" } |  | ||||||
|       participant DB@{ "type" : "database" } |  | ||||||
|       participant COL@{ "type" : "collections" } |  | ||||||
|       participant Q@{ "type" : "queue" } |  | ||||||
|      |  | ||||||
|       FE ->> B: Another long message<br/>with explicit<br/>line breaks |  | ||||||
|       B -->> FE: Response message that is also quite long and needs to wrap |  | ||||||
|       FE ->> C: Process data |  | ||||||
|       C ->> E: Validate |  | ||||||
|       E -->> C: Validation result |  | ||||||
|       C ->> DB: Save |  | ||||||
|       DB -->> C: Save result |  | ||||||
|       C ->> COL: Log |  | ||||||
|       COL -->> Q: Forward |  | ||||||
|       Q -->> LongNameUser: Final response with confirmation of all actions taken |  | ||||||
|     `, |  | ||||||
|       { sequence: { wrap: true } } |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   describe('Sequence Diagram - New Participant Types with Long Notes and Messages', () => { |  | ||||||
|     it('should render long notes left of boundary', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|         participant Alice@{ "type" : "boundary" } |  | ||||||
|         actor Bob |  | ||||||
|         Alice->>Bob: Hola |  | ||||||
|         Note left of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|         Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render wrapped long notes left of control', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "control" } |  | ||||||
|       actor Bob |  | ||||||
|       Alice->>Bob: Hola |  | ||||||
|       Note left of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|       Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render long notes right of entity', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "entity" } |  | ||||||
|       actor Bob |  | ||||||
|       Alice->>Bob: Hola |  | ||||||
|       Note right of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|       Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render wrapped long notes right of database', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "database" } |  | ||||||
|       actor Bob |  | ||||||
|       Alice->>Bob: Hola |  | ||||||
|       Note right of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|       Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render long notes over collections', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "collections" } |  | ||||||
|       actor Bob |  | ||||||
|       Alice->>Bob: Hola |  | ||||||
|       Note over Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|       Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render wrapped long notes over queue', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "queue" } |  | ||||||
|       actor Bob |  | ||||||
|       Alice->>Bob: Hola |  | ||||||
|       Note over Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|       Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render notes over actor and boundary', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       actor Alice |  | ||||||
|       participant Charlie@{ "type" : "boundary" } |  | ||||||
|       note over Alice: Some note |  | ||||||
|       note over Charlie: Other note |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render long messages from database to collections', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "database" } |  | ||||||
|       participant Bob@{ "type" : "collections" } |  | ||||||
|       Alice->>Bob: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|       Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render wrapped long messages from control to entity', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "control" } |  | ||||||
|       participant Bob@{ "type" : "entity" } |  | ||||||
|       Alice->>Bob:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|       Bob->>Alice: I'm short though |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render long messages from queue to boundary', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       participant Alice@{ "type" : "queue" } |  | ||||||
|       participant Bob@{ "type" : "boundary" } |  | ||||||
|       Alice->>Bob: I'm short |  | ||||||
|       Bob->>Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render wrapped long messages from actor to database', () => { |  | ||||||
|       imgSnapshotTest( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|       actor Alice |  | ||||||
|       participant Bob@{ "type" : "database" } |  | ||||||
|       Alice->>Bob: I'm short |  | ||||||
|       Bob->>Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be |  | ||||||
|     `, |  | ||||||
|         {} |  | ||||||
|       ); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   describe('svg size', () => { |  | ||||||
|     it('should render a sequence diagram when useMaxWidth is true (default)', () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|         actor Alice |  | ||||||
|         participant Bob@{ "type" : "boundary" } |  | ||||||
|         participant John@{ "type" : "control" } |  | ||||||
|         Alice ->> Bob: Hello Bob, how are you? |  | ||||||
|         Bob-->>John: How about you John? |  | ||||||
|         Bob--x Alice: I am good thanks! |  | ||||||
|         Bob-x John: I am good thanks! |  | ||||||
|         Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row. |  | ||||||
|         Bob-->Alice: Checking with John... |  | ||||||
|         alt either this |  | ||||||
|           Alice->>John: Yes |  | ||||||
|         else or this |  | ||||||
|           Alice->>John: No |  | ||||||
|         else or this will happen |  | ||||||
|           Alice->John: Maybe |  | ||||||
|         end |  | ||||||
|         par this happens in parallel |  | ||||||
|           Alice -->> Bob: Parallel message 1 |  | ||||||
|         and |  | ||||||
|           Alice -->> John: Parallel message 2 |  | ||||||
|         end |  | ||||||
|       `, |  | ||||||
|         { sequence: { useMaxWidth: true } } |  | ||||||
|       ); |  | ||||||
|       cy.get('svg').should((svg) => { |  | ||||||
|         expect(svg).to.have.attr('width', '100%'); |  | ||||||
|         const style = svg.attr('style'); |  | ||||||
|         expect(style).to.match(/^max-width: [\d.]+px;$/); |  | ||||||
|         const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); |  | ||||||
|         expect(maxWidthValue).to.be.within(820 * 0.95, 820 * 1.05); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should render a sequence diagram when useMaxWidth is false', () => { |  | ||||||
|       renderGraph( |  | ||||||
|         ` |  | ||||||
|       sequenceDiagram |  | ||||||
|         actor Alice |  | ||||||
|         participant Bob@{ "type" : "boundary" } |  | ||||||
|         participant John@{ "type" : "control" } |  | ||||||
|         Alice ->> Bob: Hello Bob, how are you? |  | ||||||
|         Bob-->>John: How about you John? |  | ||||||
|         Bob--x Alice: I am good thanks! |  | ||||||
|         Bob-x John: I am good thanks! |  | ||||||
|         Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row. |  | ||||||
|         Bob-->Alice: Checking with John... |  | ||||||
|         alt either this |  | ||||||
|           Alice->>John: Yes |  | ||||||
|         else or this |  | ||||||
|           Alice->>John: No |  | ||||||
|         else or this will happen |  | ||||||
|           Alice->John: Maybe |  | ||||||
|         end |  | ||||||
|         par this happens in parallel |  | ||||||
|           Alice -->> Bob: Parallel message 1 |  | ||||||
|         and |  | ||||||
|           Alice -->> John: Parallel message 2 |  | ||||||
|         end |  | ||||||
|       `, |  | ||||||
|         { sequence: { useMaxWidth: false } } |  | ||||||
|       ); |  | ||||||
|       cy.get('svg').should((svg) => { |  | ||||||
|         const width = parseFloat(svg.attr('width')); |  | ||||||
|         expect(width).to.be.within(820 * 0.95, 820 * 1.05); |  | ||||||
|         expect(svg).to.not.have.attr('style'); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @@ -893,17 +893,6 @@ describe('Sequence diagram', () => { | |||||||
|         } |         } | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     it('should handle bidirectional arrows with autonumber', () => { |  | ||||||
|       imgSnapshotTest(` |  | ||||||
|        sequenceDiagram |  | ||||||
|        autonumber |  | ||||||
|        participant A |  | ||||||
|        participant B |  | ||||||
|        A<<->>B: This is a bidirectional message |  | ||||||
|        A->B: This is a normal message`); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => { |     it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => { | ||||||
|       //Be aware that the syntax for "properties" is likely to be changed. |       //Be aware that the syntax for "properties" is likely to be changed. | ||||||
|       imgSnapshotTest( |       imgSnapshotTest( | ||||||
|   | |||||||
| @@ -138,8 +138,8 @@ describe('State diagram', () => { | |||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|     stateDiagram-v2 |     stateDiagram-v2 | ||||||
|     State1: This a single line description |     State1: This a a single line description | ||||||
|     State2: This a multi line description |     State2: This a a multi line description | ||||||
|     State2: here comes the multi part |     State2: here comes the multi part | ||||||
|     [*] --> State1 |     [*] --> State1 | ||||||
|     State1 --> State2 |     State1 --> State2 | ||||||
| @@ -345,7 +345,7 @@ stateDiagram | |||||||
|       } |       } | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('v2 width of compound state should grow with title if title is wider', () => { |   it('v2 width of compond state should grow with title if title is wider', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
| stateDiagram-v2 | stateDiagram-v2 | ||||||
| @@ -402,8 +402,8 @@ stateDiagram-v2 | |||||||
|       ` |       ` | ||||||
| stateDiagram-v2 | stateDiagram-v2 | ||||||
|     MyState |     MyState | ||||||
|     note left of MyState : I am a lefty |     note left of MyState : I am a leftie | ||||||
|     note right of MyState : I am a righty |     note right of MyState : I am a rightie | ||||||
|     `, |     `, | ||||||
|       { |       { | ||||||
|         logLevel: 0, |         logLevel: 0, | ||||||
| @@ -552,7 +552,7 @@ style AState fill:#636,border:1px solid red,color:white; | |||||||
|         { logLevel: 0, fontFamily: 'courier' } |         { logLevel: 0, fontFamily: 'courier' } | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|     it(' should let styles take precedence over classes', () => { |     it(' should let styles take preceedence over classes', () => { | ||||||
|       imgSnapshotTest( |       imgSnapshotTest( | ||||||
|         ` |         ` | ||||||
| stateDiagram-v2 | stateDiagram-v2 | ||||||
| @@ -565,7 +565,7 @@ style AState fill:#636,border:1px solid red,color:white; | |||||||
|         { logLevel: 0, fontFamily: 'courier' } |         { logLevel: 0, fontFamily: 'courier' } | ||||||
|       ); |       ); | ||||||
|     }); |     }); | ||||||
|     it(' should allow styles to take effect in subgraphs', () => { |     it(' should allow styles to take effect in stubgraphs', () => { | ||||||
|       imgSnapshotTest( |       imgSnapshotTest( | ||||||
|         ` |         ` | ||||||
|   stateDiagram |   stateDiagram | ||||||
| @@ -602,231 +602,6 @@ State1 --> [*] | |||||||
|       -- |       -- | ||||||
|       55 |       55 | ||||||
|   } |   } | ||||||
| `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render edge labels correctly', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| title: On The Way To Something Something DarkSide |  | ||||||
| config: |  | ||||||
|   look: default |  | ||||||
|   theme: default |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| stateDiagram-v2 |  | ||||||
|  |  | ||||||
|    state State1_____________ |  | ||||||
|    { |  | ||||||
|       c0 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State2_____________ |  | ||||||
|    { |  | ||||||
|       c1 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State3_____________ |  | ||||||
|    { |  | ||||||
|       c7 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State4_____________ |  | ||||||
|    { |  | ||||||
|       c2 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State5_____________ |  | ||||||
|    { |  | ||||||
|       c3 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State6_____________ |  | ||||||
|    { |  | ||||||
|       c4 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State7_____________ |  | ||||||
|    { |  | ||||||
|       c5 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State8_____________ |  | ||||||
|    { |  | ||||||
|       c6 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| [*] --> State1_____________ |  | ||||||
| State1_____________ --> State2_____________   : Transition1_____ |  | ||||||
| State2_____________ --> State4_____________   : Transition2_____ |  | ||||||
| State2_____________ --> State3_____________   : Transition3_____ |  | ||||||
| State3_____________ --> State2_____________ |  | ||||||
| State4_____________ --> State2_____________   : Transition5_____ |  | ||||||
| State4_____________ --> State5_____________   : Transition6_____ |  | ||||||
| State5_____________ --> State6_____________   : Transition7_____ |  | ||||||
| State6_____________ --> State4_____________   : Transition8_____ |  | ||||||
| State2_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State4_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State5_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State6_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State7_____________ --> State1_____________   : Transition9_____ |  | ||||||
| State5_____________ --> State8_____________   : Transition10____ |  | ||||||
| State8_____________ --> State5_____________   : Transition11____ |  | ||||||
| `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('should render edge labels correctly with multiple transitions', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| title: Multiple Transitions |  | ||||||
| config: |  | ||||||
|   look: default |  | ||||||
|   theme: default |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| stateDiagram-v2 |  | ||||||
|  |  | ||||||
|    state State1_____________ |  | ||||||
|    { |  | ||||||
|       c0 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State2_____________ |  | ||||||
|    { |  | ||||||
|       c1 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State3_____________ |  | ||||||
|    { |  | ||||||
|       c7 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State4_____________ |  | ||||||
|    { |  | ||||||
|       c2 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State5_____________ |  | ||||||
|    { |  | ||||||
|       c3 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State6_____________ |  | ||||||
|    { |  | ||||||
|       c4 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State7_____________ |  | ||||||
|    { |  | ||||||
|       c5 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State8_____________ |  | ||||||
|    { |  | ||||||
|       c6 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State9_____________ |  | ||||||
|    { |  | ||||||
|       c9 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
| [*] --> State1_____________ |  | ||||||
| State1_____________ --> State2_____________   : Transition1_____ |  | ||||||
| State2_____________ --> State4_____________   : Transition2_____ |  | ||||||
| State2_____________ --> State3_____________   : Transition3_____ |  | ||||||
| State3_____________ --> State2_____________ |  | ||||||
| State4_____________ --> State2_____________   : Transition5_____ |  | ||||||
| State4_____________ --> State5_____________   : Transition6_____ |  | ||||||
| State5_____________ --> State6_____________   : Transition7_____ |  | ||||||
| State6_____________ --> State4_____________   : Transition8_____ |  | ||||||
| State2_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State4_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State5_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State6_____________ --> State7_____________   : Transition4_____ |  | ||||||
| State7_____________ --> State1_____________   : Transition9_____ |  | ||||||
| State5_____________ --> State8_____________   : Transition10____ |  | ||||||
| State8_____________ --> State5_____________   : Transition11____ |  | ||||||
| State9_____________ --> State8_____________   : Transition12____ |  | ||||||
| `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render edge labels correctly with multiple states', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| title: Multiple States |  | ||||||
| config: |  | ||||||
|   look: default |  | ||||||
|   theme: default |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| stateDiagram-v2 |  | ||||||
|  |  | ||||||
|    state State1_____________ |  | ||||||
|    { |  | ||||||
|       c0 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State2_____________ |  | ||||||
|    { |  | ||||||
|       c1 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State3_____________ |  | ||||||
|    { |  | ||||||
|       c7 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State4_____________ |  | ||||||
|    { |  | ||||||
|       c2 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State5_____________ |  | ||||||
|    { |  | ||||||
|       c3 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State6_____________ |  | ||||||
|    { |  | ||||||
|       c4 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State7_____________ |  | ||||||
|    { |  | ||||||
|       c5 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State8_____________ |  | ||||||
|    { |  | ||||||
|       c6 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State9_____________ |  | ||||||
|    { |  | ||||||
|       c9 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
|    state State10_____________ |  | ||||||
|    { |  | ||||||
|       c10 |  | ||||||
|    } |  | ||||||
|  |  | ||||||
| [*] --> State1_____________ |  | ||||||
| State1_____________ --> State2_____________   : Transition1_____ |  | ||||||
| State2_____________ --> State3_____________   : Transition2_____ |  | ||||||
| State3_____________ --> State4_____________   : Transition3_____ |  | ||||||
| State4_____________ --> State5_____________   : Transition4_____ |  | ||||||
| State5_____________ --> State6_____________   : Transition5_____ |  | ||||||
| State6_____________ --> State7_____________   : Transition6_____ |  | ||||||
| State7_____________ --> State8_____________   : Transition7_____ |  | ||||||
| State8_____________ --> State9_____________   : Transition8_____ |  | ||||||
| State9_____________ --> State10_____________   : Transition9_____ |  | ||||||
| `, | `, | ||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -129,8 +129,8 @@ describe('State diagram', () => { | |||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|     stateDiagram |     stateDiagram | ||||||
|     State1: This a single line description |     State1: This a a single line description | ||||||
|     State2: This a multi line description |     State2: This a a multi line description | ||||||
|     State2: here comes the multi part |     State2: here comes the multi part | ||||||
|     [*] --> State1 |     [*] --> State1 | ||||||
|     State1 --> State2 |     State1 --> State2 | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ describe('Timeline diagram', () => { | |||||||
|     title History of Social Media Platform |     title History of Social Media Platform | ||||||
|     2002 : LinkedIn |     2002 : LinkedIn | ||||||
|     2004 : Facebook : Google |     2004 : Facebook : Google | ||||||
|     2005 : YouTube |     2005 : Youtube | ||||||
|     2006 : Twitter |     2006 : Twitter | ||||||
|       `, |       `, | ||||||
|       {} |       {} | ||||||
| @@ -35,7 +35,7 @@ describe('Timeline diagram', () => { | |||||||
|         section Stone Age |         section Stone Age | ||||||
|           7600 BC : Britain's oldest known house was built in Orkney, Scotland |           7600 BC : Britain's oldest known house was built in Orkney, Scotland | ||||||
|           6000 BC : Sea levels rise and Britain becomes an island.<br> The people who live here are hunter-gatherers. |           6000 BC : Sea levels rise and Britain becomes an island.<br> The people who live here are hunter-gatherers. | ||||||
|         section Bronze Age |         section Broze Age | ||||||
|           2300 BC : People arrive from Europe and settle in Britain. <br>They bring farming and metalworking. |           2300 BC : People arrive from Europe and settle in Britain. <br>They bring farming and metalworking. | ||||||
|                   : New styles of pottery and ways of burying the dead appear. |                   : New styles of pottery and ways of burying the dead appear. | ||||||
|           2200 BC : The last major building works are completed at Stonehenge.<br> People now bury their dead in stone circles. |           2200 BC : The last major building works are completed at Stonehenge.<br> People now bury their dead in stone circles. | ||||||
| @@ -51,7 +51,7 @@ describe('Timeline diagram', () => { | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|       `, |       `, | ||||||
|       {} |       {} | ||||||
| @@ -68,7 +68,7 @@ describe('Timeline diagram', () => { | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008 : Instagram |           2008 : Instagram | ||||||
| @@ -84,7 +84,7 @@ describe('Timeline diagram', () => { | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008 : Instagram |           2008 : Instagram | ||||||
| @@ -101,7 +101,7 @@ describe('Timeline diagram', () => { | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008 : Instagram |           2008 : Instagram | ||||||
| @@ -118,7 +118,7 @@ describe('Timeline diagram', () => { | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008 : Instagram |           2008 : Instagram | ||||||
| @@ -135,7 +135,7 @@ describe('Timeline diagram', () => { | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008 : Instagram |           2008 : Instagram | ||||||
| @@ -152,7 +152,7 @@ describe('Timeline diagram', () => { | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008 : Instagram |           2008 : Instagram | ||||||
| @@ -161,68 +161,4 @@ describe('Timeline diagram', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('11: should render timeline with many stacked events and proper timeline line length', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `timeline |  | ||||||
|         title Medical Device Lifecycle |  | ||||||
|         section Pre-Development |  | ||||||
|           Quality Management System : Regulatory Compliance : Risk Management |  | ||||||
|         section Development |  | ||||||
|           Management Responsibility : Planning Activities : Human Resources |  | ||||||
|           Resource Management : Management Reviews : Infrastructure |  | ||||||
|         section Post-Development |  | ||||||
|           Product Realization Activities : Planning Activities : Customer-related Processes |  | ||||||
|           Post-Production Activities : Feedback : Complaints : Adverse Events |  | ||||||
|                                     : Research and Development : Purchasing Activities |  | ||||||
|                                     : Production Activities : Installation Activities |  | ||||||
|                                     : Servicing Activities : Post-Market Surveillance |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('12: should render timeline with proper vertical line lengths for all columns', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|     theme: base |  | ||||||
|     themeVariables: |  | ||||||
|         fontFamily: Fira Sans |  | ||||||
|         fontSize: 17px |  | ||||||
|         cScale0: '#b3cde0' |  | ||||||
|         cScale1: '#f49090' |  | ||||||
|         cScale2: '#85d5b8' |  | ||||||
| --- |  | ||||||
|  |  | ||||||
| timeline |  | ||||||
|     title Medical Device Lifecycle |  | ||||||
|     section Planning |  | ||||||
|         Quality Management System (4): Regulatory Compliance (4.1.1) |  | ||||||
|             : Risk Management (4.1.2) |  | ||||||
|         Management Resposibility (5): Planning Activities (5.4) |  | ||||||
|             : Management Reviews (5.6) |  | ||||||
|          Resource Management (6): Human Resources (6.2) |  | ||||||
|             : Infrastructure (6.3) |  | ||||||
|     section Realization |  | ||||||
|         Research and Development (7.3): RnD Planning (7.3.2) |  | ||||||
|             : Inputs (7.3.3) |  | ||||||
|             : Outputs (7.3.4) |  | ||||||
|             : Review (7.3.5) |  | ||||||
|             : Verification (7.3.6) |  | ||||||
|             : Validation (7.3.7) |  | ||||||
|         Purchasing (7.4): Purchasing Process (7.4.1) |  | ||||||
|             : Purchasing Information (7.4.2) |  | ||||||
|         Production (7.5): Production Activities (7.5.1) |  | ||||||
|             : Production Feedback (8.2.1) |  | ||||||
|         Installation (7.5.3): Installation Activities (7.5.3) |  | ||||||
|         Servicing (7.5.4): Servicing Activities (7.5.4) |  | ||||||
|     section Post-Production |  | ||||||
|         Post-Market Activities (8): Feedback (8.2.1) |  | ||||||
|             : Complaints (8.2.2) |  | ||||||
|             : Adverse Events (8.2.3) |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,382 +0,0 @@ | |||||||
| import { imgSnapshotTest } from '../../helpers/util.ts'; |  | ||||||
|  |  | ||||||
| describe('Treemap Diagram', () => { |  | ||||||
|   it('1: should render a basic treemap', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `treemap-beta |  | ||||||
| "Category A" |  | ||||||
|     "Item A1": 10 |  | ||||||
|     "Item A2": 20 |  | ||||||
| "Category B" |  | ||||||
|     "Item B1": 15 |  | ||||||
|     "Item B2": 25 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('2: should render a hierarchical treemap', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `treemap-beta |  | ||||||
| "Products" |  | ||||||
|     "Electronics" |  | ||||||
|         "Phones": 50 |  | ||||||
|         "Computers": 30 |  | ||||||
|         "Accessories": 20 |  | ||||||
|     "Clothing" |  | ||||||
|         "Men's" |  | ||||||
|             "Shirts": 10 |  | ||||||
|             "Pants": 15 |  | ||||||
|         "Women's" |  | ||||||
|             "Dresses": 20 |  | ||||||
|             "Skirts": 10 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('3: should render a treemap with styling using classDef', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `treemap-beta |  | ||||||
| "Section 1" |  | ||||||
|     "Leaf 1.1": 12 |  | ||||||
|     "Section 1.2":::class1 |  | ||||||
|       "Leaf 1.2.1": 12 |  | ||||||
| "Section 2" |  | ||||||
|     "Leaf 2.1": 20:::class1 |  | ||||||
|     "Leaf 2.2": 25 |  | ||||||
|     "Leaf 2.3": 12 |  | ||||||
|  |  | ||||||
| classDef class1 fill:red,color:blue,stroke:#FFD600; |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('4: should handle long text that wraps', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `treemap-beta |  | ||||||
| "Main Category" |  | ||||||
|     "This is a very long item name that should wrap to the next line when rendered in the treemap diagram": 50 |  | ||||||
|     "Short item": 20 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('5: should render with a forest theme', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   theme: forest |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Category A" |  | ||||||
|     "Item A1": 10 |  | ||||||
|     "Item A2": 20 |  | ||||||
| "Category B" |  | ||||||
|     "Item B1": 15 |  | ||||||
|     "Item B2": 25 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('6: should handle multiple levels of nesting', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `treemap-beta |  | ||||||
| "Level 1" |  | ||||||
|     "Level 2A" |  | ||||||
|         "Level 3A": 10 |  | ||||||
|         "Level 3B": 15 |  | ||||||
|     "Level 2B" |  | ||||||
|         "Level 3C": 20 |  | ||||||
|         "Level 3D" |  | ||||||
|             "Level 4A": 5 |  | ||||||
|             "Level 4B": 5 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('7: should handle classDef with multiple styles', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `treemap-beta |  | ||||||
| "Main" |  | ||||||
|     "A": 20 |  | ||||||
|     "B":::important |  | ||||||
|         "B1": 10 |  | ||||||
|         "B2": 15 |  | ||||||
|     "C": 5:::secondary |  | ||||||
|  |  | ||||||
| classDef important fill:#f96,stroke:#333,stroke-width:2px; |  | ||||||
| classDef secondary fill:#6cf,stroke:#333,stroke-dasharray:5 5; |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8: should handle dollar value formatting with thousands separator', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: "$0,0" |  | ||||||
| --- |  | ||||||
| treemap |  | ||||||
| "Budget" |  | ||||||
|     "Operations" |  | ||||||
|         "Salaries": 700000 |  | ||||||
|         "Equipment": 200000 |  | ||||||
|         "Supplies": 100000 |  | ||||||
|     "Marketing" |  | ||||||
|         "Advertising": 400000 |  | ||||||
|         "Events": 100000 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8a: should handle percentage formatting', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: ".1%" |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Market Share" |  | ||||||
|     "Company A": 0.35 |  | ||||||
|     "Company B": 0.25 |  | ||||||
|     "Company C": 0.15 |  | ||||||
|     "Others": 0.25 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8b: should handle decimal formatting', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: ".2f" |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Metrics" |  | ||||||
|     "Conversion Rate": 0.0567 |  | ||||||
|     "Bounce Rate": 0.6723 |  | ||||||
|     "Click-through Rate": 0.1289 |  | ||||||
|     "Engagement": 0.4521 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8c: should handle dollar sign with decimal places', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: "$.2f" |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Product Prices" |  | ||||||
|     "Basic": 19.99 |  | ||||||
|     "Standard": 49.99 |  | ||||||
|     "Premium": 99.99 |  | ||||||
|     "Enterprise": 199.99 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8d: should handle dollar sign with thousands separator and decimal places', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: "$,.2f" |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Revenue" |  | ||||||
|     "Q1": 1250345.75 |  | ||||||
|     "Q2": 1645789.25 |  | ||||||
|     "Q3": 1845123.50 |  | ||||||
|     "Q4": 2145678.75 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8e: should handle simple thousands separator', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: "," |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "User Counts" |  | ||||||
|     "Active Users": 1250345 |  | ||||||
|     "New Signups": 45789 |  | ||||||
|     "Churned": 12350 |  | ||||||
|     "Converted": 78975 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8f: should handle valueFormat set via directive with dollar and thousands separator', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: "$,.0f" |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Sales by Region" |  | ||||||
|     "North": 1234567 |  | ||||||
|     "South": 7654321 |  | ||||||
|     "East": 4567890 |  | ||||||
|     "West": 9876543 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('8g: should handle scientific notation format', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: ".2e" |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Scientific Values" |  | ||||||
|     "Value 1": 1234567 |  | ||||||
|     "Value 2": 0.0000123 |  | ||||||
|     "Value 3": 1000000000 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('9: should handle a complex example with multiple features', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       `--- |  | ||||||
| config: |  | ||||||
|   theme: dark |  | ||||||
|   treemap: |  | ||||||
|     valueFormat: "$0,0" |  | ||||||
| --- |  | ||||||
| treemap-beta |  | ||||||
| "Company Budget" |  | ||||||
|     "Engineering":::engineering |  | ||||||
|         "Frontend": 300000 |  | ||||||
|         "Backend": 400000 |  | ||||||
|         "DevOps": 200000 |  | ||||||
|     "Marketing":::marketing |  | ||||||
|         "Digital": 250000 |  | ||||||
|         "Print": 100000 |  | ||||||
|         "Events": 150000 |  | ||||||
|     "Sales":::sales |  | ||||||
|         "Direct": 500000 |  | ||||||
|         "Channel": 300000 |  | ||||||
|  |  | ||||||
| classDef engineering fill:#6b9bc3,stroke:#333; |  | ||||||
| classDef marketing fill:#c36b9b,stroke:#333; |  | ||||||
| classDef sales fill:#c3a66b,stroke:#333; |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('10: should render the example from documentation', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     treemap-beta |  | ||||||
|       "Section 1" |  | ||||||
|           "Leaf 1.1": 12 |  | ||||||
|           "Section 1.2":::class1 |  | ||||||
|             "Leaf 1.2.1": 12 |  | ||||||
|       "Section 2" |  | ||||||
|           "Leaf 2.1": 20:::class1 |  | ||||||
|           "Leaf 2.2": 25 |  | ||||||
|           "Leaf 2.3": 12 |  | ||||||
|  |  | ||||||
|       classDef class1 fill:red,color:blue,stroke:#FFD600; |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('11: should handle comments', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     treemap-beta |  | ||||||
|       %% This is a comment |  | ||||||
|       "Category A" |  | ||||||
|           "Item A1": 10 |  | ||||||
|           "Item A2": 20 |  | ||||||
|       %% Another comment |  | ||||||
|       "Category B" |  | ||||||
|           "Item B1": 15 |  | ||||||
|           "Item B2": 25 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   /* |  | ||||||
|   it.skip('12: should render a treemap with title', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     treemap-beta |  | ||||||
|       title Treemap with Title |  | ||||||
|       "Category A" |  | ||||||
|           "Item A1": 10 |  | ||||||
|           "Item A2": 20 |  | ||||||
|       "Category B" |  | ||||||
|           "Item B1": 15 |  | ||||||
|           "Item B2": 25 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it.skip('13: should render a treemap with accessibility attributes', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     treemap-beta |  | ||||||
|       accTitle: Accessible Treemap Title |  | ||||||
|       accDescr: This is a description of the treemap for accessibility purposes |  | ||||||
|       "Category A" |  | ||||||
|           "Item A1": 10 |  | ||||||
|           "Item A2": 20 |  | ||||||
|       "Category B" |  | ||||||
|           "Item B1": 15 |  | ||||||
|           "Item B2": 25 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it.skip('14: should render a treemap with title and accessibility attributes', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     treemap |  | ||||||
|       title Treemap with Title and Accessibility |  | ||||||
|       accTitle: Accessible Treemap Title |  | ||||||
|       accDescr: This is a description of the treemap for accessibility purposes |  | ||||||
|       "Category A" |  | ||||||
|           "Item A1": 10 |  | ||||||
|           "Item A2": 20 |  | ||||||
|       "Category B" |  | ||||||
|           "Item B1": 15 |  | ||||||
|           "Item B2": 25 |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   */ |  | ||||||
| }); |  | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; | import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; | ||||||
|  |  | ||||||
| describe('XY Chart', () => { | describe('XY Chart', () => { | ||||||
|   it('should render the simplest possible xy-beta chart', () => { |   it('should render the simplest possible chart', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart-beta |       xychart-beta | ||||||
| @@ -10,19 +10,10 @@ describe('XY Chart', () => { | |||||||
|       {} |       {} | ||||||
|     ); |     ); | ||||||
|   }); |   }); | ||||||
|   it('should render the simplest possible xy chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|       xychart |  | ||||||
|         line [10, 30, 20] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|   it('Should render a complete chart', () => { |   it('Should render a complete chart', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -35,7 +26,7 @@ describe('XY Chart', () => { | |||||||
|   it('Should render a chart without title', () => { |   it('Should render a chart without title', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
|         bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] |         bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] | ||||||
| @@ -47,7 +38,7 @@ describe('XY Chart', () => { | |||||||
|   it('y-axis title not required', () => { |   it('y-axis title not required', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis 4000 --> 11000 |         y-axis 4000 --> 11000 | ||||||
|         bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] |         bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] | ||||||
| @@ -59,7 +50,7 @@ describe('XY Chart', () => { | |||||||
|   it('Should render a chart without y-axis with different range', () => { |   it('Should render a chart without y-axis with different range', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000] |         bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000] | ||||||
|         line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800] |         line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800] | ||||||
| @@ -70,7 +61,7 @@ describe('XY Chart', () => { | |||||||
|   it('x axis title not required', () => { |   it('x axis title not required', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000] |         bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000] | ||||||
|         line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800] |         line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800] | ||||||
| @@ -81,7 +72,7 @@ describe('XY Chart', () => { | |||||||
|   it('Multiple plots can be rendered', () => { |   it('Multiple plots can be rendered', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         line [23, 46, 77, 34] |         line [23, 46, 77, 34] | ||||||
|         line [45, 32, 33, 12] |         line [45, 32, 33, 12] | ||||||
|         bar [87, 54, 99, 85] |         bar [87, 54, 99, 85] | ||||||
| @@ -95,7 +86,7 @@ describe('XY Chart', () => { | |||||||
|   it('Decimals and negative numbers are supported', () => { |   it('Decimals and negative numbers are supported', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         y-axis -2.4 --> 3.5 |         y-axis -2.4 --> 3.5 | ||||||
|         line [+1.3, .6, 2.4, -.34] |         line [+1.3, .6, 2.4, -.34] | ||||||
|       `, |       `, | ||||||
| @@ -113,7 +104,7 @@ describe('XY Chart', () => { | |||||||
|           height: 20 |           height: 20 | ||||||
|           plotReservedSpacePercent: 100 |           plotReservedSpacePercent: 100 | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800] |         line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800] | ||||||
|       `, |       `, | ||||||
|       {} |       {} | ||||||
| @@ -139,7 +130,7 @@ describe('XY Chart', () => { | |||||||
|             showTick: false |             showTick: false | ||||||
|             showAxisLine: false |             showAxisLine: false | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800] |         bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800] | ||||||
|       `, |       `, | ||||||
|       {} |       {} | ||||||
| @@ -149,7 +140,7 @@ describe('XY Chart', () => { | |||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       %%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5},  "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60  }}}%% |       %%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5},  "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60  }}}%% | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -188,9 +179,8 @@ describe('XY Chart', () => { | |||||||
|             axisLineWidth: 5 |             axisLineWidth: 5 | ||||||
|           chartOrientation: horizontal |           chartOrientation: horizontal | ||||||
|           plotReservedSpacePercent: 60 |           plotReservedSpacePercent: 60 | ||||||
|           showDataLabel: true |  | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -211,7 +201,7 @@ describe('XY Chart', () => { | |||||||
|           yAxis: |           yAxis: | ||||||
|             showTitle: false |             showTitle: false | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -232,7 +222,7 @@ describe('XY Chart', () => { | |||||||
|           yAxis: |           yAxis: | ||||||
|             showLabel: false |             showLabel: false | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -253,7 +243,7 @@ describe('XY Chart', () => { | |||||||
|           yAxis: |           yAxis: | ||||||
|             showTick: false |             showTick: false | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -274,7 +264,7 @@ describe('XY Chart', () => { | |||||||
|           yAxis: |           yAxis: | ||||||
|             showAxisLine: false |             showAxisLine: false | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -303,7 +293,7 @@ describe('XY Chart', () => { | |||||||
|             xAxisLineColor: "#87ceeb" |             xAxisLineColor: "#87ceeb" | ||||||
|             plotColorPalette: "#008000, #faba63" |             plotColorPalette: "#008000, #faba63" | ||||||
|       --- |       --- | ||||||
|       xychart |       xychart-beta | ||||||
|         title "Sales Revenue" |         title "Sales Revenue" | ||||||
|         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |         x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] | ||||||
|         y-axis "Revenue (in $)" 4000 --> 11000 |         y-axis "Revenue (in $)" 4000 --> 11000 | ||||||
| @@ -316,7 +306,7 @@ describe('XY Chart', () => { | |||||||
|   it('should use the correct distances between data points', () => { |   it('should use the correct distances between data points', () => { | ||||||
|     imgSnapshotTest( |     imgSnapshotTest( | ||||||
|       ` |       ` | ||||||
|       xychart |       xychart-beta | ||||||
|         x-axis 0 --> 2 |         x-axis 0 --> 2 | ||||||
|         line [0, 1, 0, 1] |         line [0, 1, 0, 1] | ||||||
|         bar [1, 0, 1, 0] |         bar [1, 0, 1, 0] | ||||||
| @@ -325,516 +315,4 @@ describe('XY Chart', () => { | |||||||
|     ); |     ); | ||||||
|     cy.get('svg'); |     cy.get('svg'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   it('should render vertical bar chart with labels', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|       title "Sales Revenue" |  | ||||||
|       x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |  | ||||||
|       y-axis "Revenue (in $)" 4000 --> 11000 |  | ||||||
|       bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render horizontal bar chart with labels', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|       title "Sales Revenue" |  | ||||||
|       x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |  | ||||||
|       y-axis "Revenue (in $)" 4000 --> 11000 |  | ||||||
|       bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render vertical bar chart without labels by default', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     xychart |  | ||||||
|       title "Sales Revenue" |  | ||||||
|       x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |  | ||||||
|       y-axis "Revenue (in $)" 4000 --> 11000 |  | ||||||
|       bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render horizontal bar chart without labels by default', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|       title "Sales Revenue" |  | ||||||
|       x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] |  | ||||||
|       y-axis "Revenue (in $)" 4000 --> 11000 |  | ||||||
|       bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render multiple bar plots vertically with labels correctly', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|     --- |  | ||||||
|       xychart |  | ||||||
|         title "Multiple Bar Plots" |  | ||||||
|         x-axis Categories [A, B, C] |  | ||||||
|         y-axis "Values" 0 --> 100 |  | ||||||
|         bar [10, 50, 90] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render multiple bar plots horizontally with labels correctly', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|       xychart |  | ||||||
|         title "Multiple Bar Plots" |  | ||||||
|         x-axis Categories [A, B, C] |  | ||||||
|         y-axis "Values" 0 --> 100 |  | ||||||
|         bar [10, 50, 90] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render a single bar with label for a vertical xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|     --- |  | ||||||
|       xychart |  | ||||||
|         title "Single Bar Chart" |  | ||||||
|         x-axis Categories [A] |  | ||||||
|         y-axis "Value" 0 --> 100 |  | ||||||
|         bar [75] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render a single bar with label for a horizontal xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|       xychart |  | ||||||
|         title "Single Bar Chart" |  | ||||||
|         x-axis Categories [A] |  | ||||||
|         y-axis "Value" 0 --> 100 |  | ||||||
|         bar [75] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render negative and decimal values with correct labels for vertical xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|     --- |  | ||||||
|       xychart |  | ||||||
|         title "Decimal and Negative Values" |  | ||||||
|         x-axis Categories [A, B, C] |  | ||||||
|         y-axis -10 --> 10 |  | ||||||
|         bar [ -2.5, 0.75, 5.1 ] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render negative and decimal values with correct labels for horizontal xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|       xychart |  | ||||||
|         title "Decimal and Negative Values" |  | ||||||
|         x-axis Categories [A, B, C] |  | ||||||
|         y-axis -10 --> 10 |  | ||||||
|         bar [ -2.5, 0.75, 5.1 ] |  | ||||||
|       `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render data labels within each bar in the vertical xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|             title "Sales Revenue" |  | ||||||
|             x-axis Months [jan,b,c] |  | ||||||
|             y-axis "Revenue (in $)" 4000 --> 12000 |  | ||||||
|             bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 3000, 2000, 500, 2000, 3000, 11000, 5000, 6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     cy.get('g.bar-plot-0').within(() => { |  | ||||||
|       cy.get('rect').each(($rect, index) => { |  | ||||||
|         // Extract bar properties |  | ||||||
|         const barProps = { |  | ||||||
|           x: parseFloat($rect.attr('x')), |  | ||||||
|           y: parseFloat($rect.attr('y')), |  | ||||||
|           width: parseFloat($rect.attr('width')), |  | ||||||
|           height: parseFloat($rect.attr('height')), |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         // Get the text element corresponding to this bar by index. |  | ||||||
|         cy.get('text') |  | ||||||
|           .eq(index) |  | ||||||
|           .then(($text) => { |  | ||||||
|             const bbox = $text[0].getBBox(); |  | ||||||
|             const textProps = { |  | ||||||
|               x: bbox.x, |  | ||||||
|               y: bbox.y, |  | ||||||
|               width: bbox.width, |  | ||||||
|               height: bbox.height, |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             // Verify that the text label is positioned within the boundaries of the bar. |  | ||||||
|             expect(textProps.x).to.be.greaterThan(barProps.x); |  | ||||||
|             expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); |  | ||||||
|  |  | ||||||
|             // Check horizontal alignment (within tolerance) |  | ||||||
|             expect(textProps.x + textProps.width / 2).to.be.closeTo( |  | ||||||
|               barProps.x + barProps.width / 2, |  | ||||||
|               5 |  | ||||||
|             ); |  | ||||||
|  |  | ||||||
|             expect(textProps.y).to.be.greaterThan(barProps.y); |  | ||||||
|             expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); |  | ||||||
|           }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render data labels within each bar in the horizontal xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|             title "Sales Revenue" |  | ||||||
|             x-axis Months [jan,b,c] |  | ||||||
|             y-axis "Revenue (in $)" 4000 --> 12000 |  | ||||||
|             bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 3000, 2000, 500, 2000, 3000, 11000, 5000, 6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     cy.get('g.bar-plot-0').within(() => { |  | ||||||
|       cy.get('rect').each(($rect, index) => { |  | ||||||
|         // Extract bar properties |  | ||||||
|         const barProps = { |  | ||||||
|           x: parseFloat($rect.attr('x')), |  | ||||||
|           y: parseFloat($rect.attr('y')), |  | ||||||
|           width: parseFloat($rect.attr('width')), |  | ||||||
|           height: parseFloat($rect.attr('height')), |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         // Get the text element corresponding to this bar by index. |  | ||||||
|         cy.get('text') |  | ||||||
|           .eq(index) |  | ||||||
|           .then(($text) => { |  | ||||||
|             const bbox = $text[0].getBBox(); |  | ||||||
|             const textProps = { |  | ||||||
|               x: bbox.x, |  | ||||||
|               y: bbox.y, |  | ||||||
|               width: bbox.width, |  | ||||||
|               height: bbox.height, |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             // Verify that the text label is positioned within the boundaries of the bar. |  | ||||||
|             expect(textProps.x).to.be.greaterThan(barProps.x); |  | ||||||
|             expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); |  | ||||||
|  |  | ||||||
|             expect(textProps.y).to.be.greaterThan(barProps.y); |  | ||||||
|             expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); |  | ||||||
|             expect(textProps.y + textProps.height / 2).to.be.closeTo( |  | ||||||
|               barProps.y + barProps.height / 2, |  | ||||||
|               5 |  | ||||||
|             ); |  | ||||||
|           }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render data labels within each bar in the vertical xy-chart with a lot of bars of different sizes', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|       --- |  | ||||||
|       config: |  | ||||||
|         xyChart: |  | ||||||
|           showDataLabel: true |  | ||||||
|       --- |  | ||||||
|       xychart |  | ||||||
|         title "Sales Revenue" |  | ||||||
|         x-axis Months [jan,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s] |  | ||||||
|         y-axis "Revenue (in $)" 4000 --> 12000 |  | ||||||
|         bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 8000, 10000, 5000, 7600, 4999,11000 ,5000,6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     cy.get('g.bar-plot-0').within(() => { |  | ||||||
|       cy.get('rect').each(($rect, index) => { |  | ||||||
|         // Extract bar properties |  | ||||||
|         const barProps = { |  | ||||||
|           x: parseFloat($rect.attr('x')), |  | ||||||
|           y: parseFloat($rect.attr('y')), |  | ||||||
|           width: parseFloat($rect.attr('width')), |  | ||||||
|           height: parseFloat($rect.attr('height')), |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         // Get the text element corresponding to this bar by index. |  | ||||||
|         cy.get('text') |  | ||||||
|           .eq(index) |  | ||||||
|           .then(($text) => { |  | ||||||
|             const bbox = $text[0].getBBox(); |  | ||||||
|             const textProps = { |  | ||||||
|               x: bbox.x, |  | ||||||
|               y: bbox.y, |  | ||||||
|               width: bbox.width, |  | ||||||
|               height: bbox.height, |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             // Verify that the text label is positioned within the boundaries of the bar. |  | ||||||
|             expect(textProps.x).to.be.greaterThan(barProps.x); |  | ||||||
|             expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); |  | ||||||
|  |  | ||||||
|             // Check horizontal alignment (within tolerance) |  | ||||||
|             expect(textProps.x + textProps.width / 2).to.be.closeTo( |  | ||||||
|               barProps.x + barProps.width / 2, |  | ||||||
|               5 |  | ||||||
|             ); |  | ||||||
|  |  | ||||||
|             expect(textProps.y).to.be.greaterThan(barProps.y); |  | ||||||
|             expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); |  | ||||||
|           }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render data labels within each bar in the horizontal xy-chart with a lot of bars of different sizes', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|       title "Sales Revenue" |  | ||||||
|       x-axis Months [jan,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s] |  | ||||||
|       y-axis "Revenue (in $)" 4000 --> 12000 |  | ||||||
|       bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000, 8000, 10000, 5000, 7600, 4999,11000 ,5000,6000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     cy.get('g.bar-plot-0').within(() => { |  | ||||||
|       cy.get('rect').each(($rect, index) => { |  | ||||||
|         // Extract bar properties |  | ||||||
|         const barProps = { |  | ||||||
|           x: parseFloat($rect.attr('x')), |  | ||||||
|           y: parseFloat($rect.attr('y')), |  | ||||||
|           width: parseFloat($rect.attr('width')), |  | ||||||
|           height: parseFloat($rect.attr('height')), |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         // Get the text element corresponding to this bar by index. |  | ||||||
|         cy.get('text') |  | ||||||
|           .eq(index) |  | ||||||
|           .then(($text) => { |  | ||||||
|             const bbox = $text[0].getBBox(); |  | ||||||
|             const textProps = { |  | ||||||
|               x: bbox.x, |  | ||||||
|               y: bbox.y, |  | ||||||
|               width: bbox.width, |  | ||||||
|               height: bbox.height, |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             // Verify that the text label is positioned within the boundaries of the bar. |  | ||||||
|             expect(textProps.x).to.be.greaterThan(barProps.x); |  | ||||||
|             expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); |  | ||||||
|  |  | ||||||
|             expect(textProps.y).to.be.greaterThan(barProps.y); |  | ||||||
|             expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); |  | ||||||
|             expect(textProps.y + textProps.height / 2).to.be.closeTo( |  | ||||||
|               barProps.y + barProps.height / 2, |  | ||||||
|               5 |  | ||||||
|             ); |  | ||||||
|           }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render data labels correctly for a bar in the vertical xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|             title "Sales Revenue" |  | ||||||
|             x-axis Months [jan] |  | ||||||
|             y-axis "Revenue (in $)" 3000 --> 12000 |  | ||||||
|             bar [4000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     cy.get('g.bar-plot-0').within(() => { |  | ||||||
|       cy.get('rect').each(($rect, index) => { |  | ||||||
|         // Extract bar properties |  | ||||||
|         const barProps = { |  | ||||||
|           x: parseFloat($rect.attr('x')), |  | ||||||
|           y: parseFloat($rect.attr('y')), |  | ||||||
|           width: parseFloat($rect.attr('width')), |  | ||||||
|           height: parseFloat($rect.attr('height')), |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         // Get the text element corresponding to this bar by index. |  | ||||||
|         cy.get('text') |  | ||||||
|           .eq(index) |  | ||||||
|           .then(($text) => { |  | ||||||
|             const bbox = $text[0].getBBox(); |  | ||||||
|             const textProps = { |  | ||||||
|               x: bbox.x, |  | ||||||
|               y: bbox.y, |  | ||||||
|               width: bbox.width, |  | ||||||
|               height: bbox.height, |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             // Verify that the text label is positioned within the boundaries of the bar. |  | ||||||
|             expect(textProps.x).to.be.greaterThan(barProps.x); |  | ||||||
|             expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); |  | ||||||
|  |  | ||||||
|             // Check horizontal alignment (within tolerance) |  | ||||||
|             expect(textProps.x + textProps.width / 2).to.be.closeTo( |  | ||||||
|               barProps.x + barProps.width / 2, |  | ||||||
|               5 |  | ||||||
|             ); |  | ||||||
|  |  | ||||||
|             expect(textProps.y).to.be.greaterThan(barProps.y); |  | ||||||
|             expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); |  | ||||||
|           }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   it('should render data labels correctly for a bar in the horizontal xy-chart', () => { |  | ||||||
|     imgSnapshotTest( |  | ||||||
|       ` |  | ||||||
|     --- |  | ||||||
|     config: |  | ||||||
|       xyChart: |  | ||||||
|         showDataLabel: true |  | ||||||
|         chartOrientation: horizontal |  | ||||||
|     --- |  | ||||||
|     xychart |  | ||||||
|             title "Sales Revenue" |  | ||||||
|             x-axis Months [jan] |  | ||||||
|             y-axis "Revenue (in $)" 3000 --> 12000 |  | ||||||
|             bar [4000] |  | ||||||
|     `, |  | ||||||
|       {} |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     cy.get('g.bar-plot-0').within(() => { |  | ||||||
|       cy.get('rect').each(($rect, index) => { |  | ||||||
|         // Extract bar properties |  | ||||||
|         const barProps = { |  | ||||||
|           x: parseFloat($rect.attr('x')), |  | ||||||
|           y: parseFloat($rect.attr('y')), |  | ||||||
|           width: parseFloat($rect.attr('width')), |  | ||||||
|           height: parseFloat($rect.attr('height')), |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         // Get the text element corresponding to this bar by index. |  | ||||||
|         cy.get('text') |  | ||||||
|           .eq(index) |  | ||||||
|           .then(($text) => { |  | ||||||
|             const bbox = $text[0].getBBox(); |  | ||||||
|             const textProps = { |  | ||||||
|               x: bbox.x, |  | ||||||
|               y: bbox.y, |  | ||||||
|               width: bbox.width, |  | ||||||
|               height: bbox.height, |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             // Verify that the text label is positioned within the boundaries of the bar. |  | ||||||
|             expect(textProps.x).to.be.greaterThan(barProps.x); |  | ||||||
|             expect(textProps.x + textProps.width).to.be.lessThan(barProps.x + barProps.width); |  | ||||||
|  |  | ||||||
|             expect(textProps.y).to.be.greaterThan(barProps.y); |  | ||||||
|             expect(textProps.y + textProps.height).to.be.lessThan(barProps.y + barProps.height); |  | ||||||
|             expect(textProps.y + textProps.height / 2).to.be.closeTo( |  | ||||||
|               barProps.y + barProps.height / 2, |  | ||||||
|               5 |  | ||||||
|             ); |  | ||||||
|           }); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -1,52 +0,0 @@ | |||||||
| <!doctype html> |  | ||||||
| <html lang="en"> |  | ||||||
|   <head> |  | ||||||
|     <meta charset="utf-8" /> |  | ||||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |  | ||||||
|     <title>Architecture Mermaid Test Page</title> |  | ||||||
|     <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" /> |  | ||||||
|     <style> |  | ||||||
|       div.mermaid { |  | ||||||
|         /* font-family: 'trebuchet ms', verdana, arial; */ |  | ||||||
|         font-family: 'Courier New', Courier, monospace !important; |  | ||||||
|       } |  | ||||||
|     </style> |  | ||||||
|   </head> |  | ||||||
|  |  | ||||||
|   <body> |  | ||||||
|     <h2>External Icons Demo</h2> |  | ||||||
|     <pre class="mermaid"> |  | ||||||
|     architecture-beta |  | ||||||
|       service s3(logos:aws-s3)[Cloud Store] |  | ||||||
|       service ec2(logos:aws-ec2)[Server] |  | ||||||
|       service api(logos:aws-api-gateway)[Api Gateway] |  | ||||||
|       service fa(fa:image)[Font Awesome Icon] |  | ||||||
|     </pre> |  | ||||||
|  |  | ||||||
|     <script type="module"> |  | ||||||
|       import mermaid from './mermaid.esm.mjs'; |  | ||||||
|       mermaid.initialize({ |  | ||||||
|         startOnLoad: false, |  | ||||||
|         logLevel: 0, |  | ||||||
|       }); |  | ||||||
|       mermaid.registerIconPacks([ |  | ||||||
|         { |  | ||||||
|           name: 'logos', |  | ||||||
|           loader: () => |  | ||||||
|             fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()), |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|           name: 'fa', |  | ||||||
|           loader: () => |  | ||||||
|             fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) => |  | ||||||
|               res.json() |  | ||||||
|             ), |  | ||||||
|         }, |  | ||||||
|       ]); |  | ||||||
|       await mermaid.run(); |  | ||||||
|       if (window.Cypress) { |  | ||||||
|         window.rendered = true; |  | ||||||
|       } |  | ||||||
|     </script> |  | ||||||
|   </body> |  | ||||||
| </html> |  | ||||||
| @@ -4,7 +4,7 @@ | |||||||
|     <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> |     <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> | ||||||
|     <link |     <link | ||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" |       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css" | ||||||
|     /> |     /> | ||||||
|     <link |     <link | ||||||
|       href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" |       href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" | ||||||
| @@ -30,8 +30,8 @@ | |||||||
|       .mermaid svg { |       .mermaid svg { | ||||||
|         /* font-size: 18px !important; */ |         /* font-size: 18px !important; */ | ||||||
|         background-color: #eee; |         background-color: #eee; | ||||||
|         background-image: |         background-image: radial-gradient(#fff 1%, transparent 11%), | ||||||
|           radial-gradient(#fff 1%, transparent 11%), radial-gradient(#fff 1%, transparent 11%); |           radial-gradient(#fff 1%, transparent 11%); | ||||||
|         background-size: 20px 20px; |         background-size: 20px 20px; | ||||||
|         background-position: |         background-position: | ||||||
|           0 0, |           0 0, | ||||||
| @@ -60,7 +60,7 @@ | |||||||
|     <pre id="diagram" class="mermaid2"> |     <pre id="diagram" class="mermaid2"> | ||||||
|  timeline |  timeline | ||||||
|         title My day |         title My day | ||||||
|         section Section with no tasks |         section section with no tasks | ||||||
|         section Go to work at the dog office |         section Go to work at the dog office | ||||||
|           1930 : first step : second step is a long step |           1930 : first step : second step is a long step | ||||||
|                : third step |                : third step | ||||||
| @@ -70,18 +70,18 @@ | |||||||
|           1960 : India fights poverty, looses war to China and gets nuclear weapons from USA and USSR |           1960 : India fights poverty, looses war to China and gets nuclear weapons from USA and USSR | ||||||
|           1970 : Green Revolution comes to india |           1970 : Green Revolution comes to india | ||||||
|         section Another section with no tasks |         section Another section with no tasks | ||||||
|           I am a very, very big task |           I am a big big big tasks | ||||||
|           I am not so big task |           I am not so big tasks | ||||||
|     </pre> |     </pre> | ||||||
|     <pre id="diagram" class="mermaid"> |     <pre id="diagram" class="mermaid"> | ||||||
|  timeline |  timeline | ||||||
|         title MermaidChart 2023 Timeline |         title MermaidChart 2023 Timeline | ||||||
|         section 2023 Q1 <br> Release Personal Tier |         section 2023 Q1 <br> Release Personal Tier | ||||||
|           Bullet 1 : sub-point 1a : sub-point 1b |           Buttet 1 : sub-point 1a : sub-point 1b | ||||||
|                : sub-point 1c |                : sub-point 1c | ||||||
|           Bullet 2 : sub-point 2a : sub-point 2b |           Bullet 2 : sub-point 2a : sub-point 2b | ||||||
|         section 2023 Q2 <br> Release XYZ Tier |         section 2023 Q2 <br> Release XYZ Tier | ||||||
|           Bullet 3 : sub-point <br> 3a : sub-point 3b |           Buttet 3 : sub-point <br> 3a : sub-point 3b | ||||||
|                : sub-point 3c |                : sub-point 3c | ||||||
|           Bullet 4 : sub-point 4a : sub-point 4b |           Bullet 4 : sub-point 4a : sub-point 4b | ||||||
|  |  | ||||||
| @@ -93,7 +93,7 @@ | |||||||
|         section Stone Age |         section Stone Age | ||||||
|           7600 BC : Britain's oldest known house was built in Orkney, Scotland |           7600 BC : Britain's oldest known house was built in Orkney, Scotland | ||||||
|           6000 BC : Sea levels rise and Britain becomes an island. The people who live here are hunter-gatherers. |           6000 BC : Sea levels rise and Britain becomes an island. The people who live here are hunter-gatherers. | ||||||
|         section Bronze Age |         section Broze Age | ||||||
|           2300 BC : People arrive from Europe and settle in Britain. They bring farming and metalworking. |           2300 BC : People arrive from Europe and settle in Britain. They bring farming and metalworking. | ||||||
|                : New styles of pottery and ways of burying the dead appear. |                : New styles of pottery and ways of burying the dead appear. | ||||||
|           2200 BC : The last major building works are completed at Stonehenge. People now bury their dead in stone circles. |           2200 BC : The last major building works are completed at Stonehenge. People now bury their dead in stone circles. | ||||||
| @@ -106,7 +106,7 @@ | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google : Pixar |           2004 : Facebook : Google : Pixar | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008s : Instagram |           2008s : Instagram | ||||||
| @@ -122,7 +122,7 @@ | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google : Pixar |           2004 : Facebook : Google : Pixar | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008s : Instagram |           2008s : Instagram | ||||||
| @@ -139,7 +139,7 @@ | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008 : Instagram |           2008 : Instagram | ||||||
| @@ -152,7 +152,7 @@ | |||||||
|         title History of Social Media Platform |         title History of Social Media Platform | ||||||
|           2002 : LinkedIn |           2002 : LinkedIn | ||||||
|           2004 : Facebook : Google |           2004 : Facebook : Google | ||||||
|           2005 : YouTube |           2005 : Youtube | ||||||
|           2006 : Twitter |           2006 : Twitter | ||||||
|           2007 : Tumblr |           2007 : Tumblr | ||||||
|           2008s : Instagram |           2008s : Instagram | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
|     <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> |     <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> | ||||||
|     <link |     <link | ||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" |       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css" | ||||||
|     /> |     /> | ||||||
|     <link |     <link | ||||||
|       href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" |       href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" | ||||||
| @@ -37,7 +37,7 @@ | |||||||
|         +String owner |         +String owner | ||||||
|         +BigDecimal balance |         +BigDecimal balance | ||||||
|         +deposit(amount) bool |         +deposit(amount) bool | ||||||
|         +withdrawal(amount) int |         +withdrawl(amount) int | ||||||
|        } |        } | ||||||
|        cssClass "BankAccount" customCss |        cssClass "BankAccount" customCss | ||||||
|  |  | ||||||
| @@ -56,7 +56,7 @@ classE o-- classF : aggregation | |||||||
|           +String owner |           +String owner | ||||||
|           +BigDecimal balance |           +BigDecimal balance | ||||||
|           +deposit(amount) bool |           +deposit(amount) bool | ||||||
|           +withdrawal(amount) int |           +withdrawl(amount) int | ||||||
|         } |         } | ||||||
|           Class01~T~ <|-- AveryLongClass : Cool |           Class01~T~ <|-- AveryLongClass : Cool | ||||||
|           Class03~T~ *-- Class04~T~ |           Class03~T~ *-- Class04~T~ | ||||||
|   | |||||||
| @@ -77,7 +77,7 @@ | |||||||
|  |  | ||||||
|         document.getElementsByTagName('body')[0].appendChild(div); |         document.getElementsByTagName('body')[0].appendChild(div); | ||||||
|       } |       } | ||||||
|       mermaid.initialize({ startOnLoad: true, securityLevel: 'strict_', logLevel: 1 }); |       mermaid.initialize({ startOnLoad: true, securityLevel: 'strct', logLevel: 1 }); | ||||||
|     </script> |     </script> | ||||||
|   </body> |   </body> | ||||||
| </html> | </html> | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|     <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> |     <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> | ||||||
|     <link |     <link | ||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" |       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css" | ||||||
|     /> |     /> | ||||||
|     <link |     <link | ||||||
|       href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" |       href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" | ||||||
| @@ -31,7 +31,7 @@ | |||||||
|         flowchart BT subgraph S1 sub1 -->sub2 end subgraph S2 sub4 end S1 --> S2 sub1 --> sub4 |         flowchart BT subgraph S1 sub1 -->sub2 end subgraph S2 sub4 end S1 --> S2 sub1 --> sub4 | ||||||
|       </div> |       </div> | ||||||
|       <div class="mermaid2" style="width: 50%; height: 200px"> |       <div class="mermaid2" style="width: 50%; height: 200px"> | ||||||
|         sequenceDiagram Alice->>Bob:Extremely utterly long line of longness which had previously |         sequenceDiagram Alice->>Bob:Extremely utterly long line of longness which had preivously | ||||||
|         overflown the actor box as it is much longer than what it should be Bob->>Alice: I'm short |         overflown the actor box as it is much longer than what it should be Bob->>Alice: I'm short | ||||||
|         though |         though | ||||||
|       </div> |       </div> | ||||||
| @@ -61,9 +61,9 @@ | |||||||
|       #quot;elit#quot;."}} |       #quot;elit#quot;."}} | ||||||
|     </div> |     </div> | ||||||
|     <div class="mermaid2" style="width: 50%; height: 50%"> |     <div class="mermaid2" style="width: 50%; height: 50%"> | ||||||
|       flowchart TB internet nat router lb1 lb2 compute1 compute2 subgraph project router nat |       flowchart TB internet nat routeur lb1 lb2 compute1 compute2 subgraph project routeur nat | ||||||
|       subgraph subnet1 compute1 lb1 end subgraph subnet2 compute2 lb2 end end internet --> router |       subgraph subnet1 compute1 lb1 end subgraph subnet2 compute2 lb2 end end internet --> routeur | ||||||
|       router --> subnet1 & subnet2 subnet1 & subnet2 --> nat --> internet |       routeur --> subnet1 & subnet2 subnet1 & subnet2 --> nat --> internet | ||||||
|     </div> |     </div> | ||||||
|     <div class="mermaid2" style="width: 50%; height: 50%"> |     <div class="mermaid2" style="width: 50%; height: 50%"> | ||||||
|       flowchart TD subgraph one[One] subgraph sub_one[Sub One] _sub_one end end subgraph two[Two] |       flowchart TD subgraph one[One] subgraph sub_one[Sub One] _sub_one end end subgraph two[Two] | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|     <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> |     <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> | ||||||
|     <link |     <link | ||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/font-awesome.min.css" |       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css" | ||||||
|     /> |     /> | ||||||
|     <link |     <link | ||||||
|       href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" |       href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" | ||||||
|   | |||||||
| @@ -1,35 +0,0 @@ | |||||||
| <!doctype html> |  | ||||||
| <html lang="en"> |  | ||||||
|   <head> |  | ||||||
|     <meta charset="utf-8" /> |  | ||||||
|     <meta http-equiv="X-UA-Compatible" content="IE=edge" /> |  | ||||||
|     <title>Mermaid Quick Test Page</title> |  | ||||||
|     <link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" /> |  | ||||||
|     <style> |  | ||||||
|       div.mermaid { |  | ||||||
|         font-family: 'Courier New', Courier, monospace !important; |  | ||||||
|       } |  | ||||||
|     </style> |  | ||||||
|   </head> |  | ||||||
|  |  | ||||||
|   <body> |  | ||||||
|     <h1>Pie chart demos</h1> |  | ||||||
|     <pre class="mermaid"> |  | ||||||
|      pie title Default text position: Animal adoption |  | ||||||
|         accTitle: simple pie char demo |  | ||||||
|         accDescr: pie chart with 3 sections: dogs, cats, rats. Most are dogs. |  | ||||||
|          "dogs" : -60.67 |  | ||||||
|         "rats" : 40.12 |  | ||||||
|     </pre> |  | ||||||
|  |  | ||||||
|     <hr /> |  | ||||||
|     <script type="module"> |  | ||||||
|       import mermaid from '/mermaid.esm.mjs'; |  | ||||||
|       mermaid.initialize({ |  | ||||||
|         theme: 'forest', |  | ||||||
|         logLevel: 3, |  | ||||||
|         securityLevel: 'loose', |  | ||||||
|       }); |  | ||||||
|     </script> |  | ||||||
|   </body> |  | ||||||
| </html> |  | ||||||
| @@ -7,7 +7,7 @@ | |||||||
|       rel="stylesheet" |       rel="stylesheet" | ||||||
|     /> |     /> | ||||||
|     <style> |     <style> | ||||||
|       svg:not(svg svg) { |       svg { | ||||||
|         border: 2px solid darkred; |         border: 2px solid darkred; | ||||||
|       } |       } | ||||||
|       .exClass2 > rect, |       .exClass2 > rect, | ||||||
|   | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user