mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-02 11:54:15 +01:00
Merge branch 'sidv/viz' into sidv/dagre-es-viz
* sidv/viz: Fix Lodash import fix: Viz build feat: Add package visualization Ignore stats.html feat: Add bundle visualization style(docs): use `github-dark` hightlight theme refactor(docs): use default vitepress highlighter fix: Move redirection to router chore: Add docs to redirect.ts feat: Redirect old documentation links. comments in states are skipped now Remove extra arrow and adjust cross position
This commit is contained in:
@@ -90,7 +90,6 @@
|
||||
"prettier": "^2.7.1",
|
||||
"remark": "^14.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
"shiki": "^0.11.1",
|
||||
"start-server-and-test": "^1.14.0",
|
||||
"typedoc": "^0.23.18",
|
||||
"typedoc-plugin-markdown": "^3.13.6",
|
||||
|
||||
@@ -752,7 +752,7 @@ export const insertSequenceNumber = function (elem) {
|
||||
// .style("fill", '#f00');
|
||||
};
|
||||
/**
|
||||
* Setup arrow head and define the marker. The result is appended to the svg.
|
||||
* Setup cross head and define the marker. The result is appended to the svg.
|
||||
*
|
||||
* @param {any} elem
|
||||
*/
|
||||
@@ -764,26 +764,16 @@ export const insertArrowCrossHead = function (elem) {
|
||||
.attr('markerWidth', 15)
|
||||
.attr('markerHeight', 8)
|
||||
.attr('orient', 'auto')
|
||||
.attr('refX', 16)
|
||||
.attr('refY', 4);
|
||||
|
||||
// The arrow
|
||||
marker
|
||||
.append('path')
|
||||
.attr('fill', 'black')
|
||||
.attr('stroke', '#000000')
|
||||
.style('stroke-dasharray', '0, 0')
|
||||
.attr('stroke-width', '1px')
|
||||
.attr('d', 'M 9,2 V 6 L16,4 Z');
|
||||
|
||||
.attr('refX', 4)
|
||||
.attr('refY', 5);
|
||||
// The cross
|
||||
marker
|
||||
.append('path')
|
||||
.attr('fill', 'none')
|
||||
.attr('stroke', '#000000')
|
||||
.style('stroke-dasharray', '0, 0')
|
||||
.attr('stroke-width', '1px')
|
||||
.attr('d', 'M 0,1 L 6,7 M 6,1 L 0,7');
|
||||
.attr('stroke-width', '1pt')
|
||||
.attr('d', 'M 1,2 L 6,7 M 6,2 L 1,7');
|
||||
// this is actual shape for arrowhead
|
||||
};
|
||||
|
||||
|
||||
@@ -184,6 +184,27 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('comments parsing', () => {
|
||||
it('working inside states', function () {
|
||||
let diagram = '';
|
||||
diagram += 'stateDiagram-v2\n\n';
|
||||
diagram += '[*] --> Moving\n';
|
||||
diagram += 'Moving --> Still\n';
|
||||
diagram += 'Moving --> Crash\n';
|
||||
diagram += 'state Moving {\n';
|
||||
diagram += '%% comment inside state\n';
|
||||
diagram += 'slow --> fast\n';
|
||||
diagram += '}\n';
|
||||
|
||||
stateDiagram.parser.parse(diagram);
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const states = stateDiagram.parser.yy.getStates();
|
||||
|
||||
expect(states['Moving'].doc.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -109,6 +109,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
||||
<STATE>[^\n\s\{]+ {/*console.log('COMPOSIT_STATE', yytext);*/return 'COMPOSIT_STATE';}
|
||||
<STATE>\n {this.popState();}
|
||||
<INITIAL,STATE>\{ {this.popState();this.pushState('struct'); /*console.log('begin struct', yytext);*/return 'STRUCT_START';}
|
||||
<struct>\%\%(?!\{)[^\n]* /* skip comments inside state*/
|
||||
<struct>\} { /*console.log('Ending struct');*/ this.popState(); return 'STRUCT_STOP';}}
|
||||
<struct>[\n] /* nothing */
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ const transformHtml = (filename: string) => {
|
||||
};
|
||||
|
||||
const getGlobs = (globs: string[]): string[] => {
|
||||
globs.push('!**/dist');
|
||||
globs.push('!**/dist', '!**/redirect.spec.ts');
|
||||
if (!vitepress) {
|
||||
globs.push('!**/.vitepress', '!**/vite.config.ts', '!src/docs/index.md');
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import { MermaidMarkdown } from 'vitepress-plugin-mermaid';
|
||||
import { defineConfig, MarkdownOptions } from 'vitepress';
|
||||
|
||||
const allMarkdownTransformers: MarkdownOptions = {
|
||||
// the shiki theme to highlight code blocks
|
||||
theme: 'github-dark',
|
||||
config: async (md) => {
|
||||
await MermaidExample(md);
|
||||
MermaidMarkdown(md);
|
||||
@@ -35,7 +37,7 @@ function nav() {
|
||||
{ text: 'Intro', link: '/intro/', activeMatch: '/intro/' },
|
||||
{
|
||||
text: 'Configuration',
|
||||
link: '/config/Tutorials',
|
||||
link: '/config/configuration',
|
||||
activeMatch: '/config/',
|
||||
},
|
||||
{ text: 'Syntax', link: '/syntax/classDiagram', activeMatch: '/syntax/' },
|
||||
@@ -118,6 +120,7 @@ function sidebarConfig() {
|
||||
text: '⚙️ Deployment and Configuration',
|
||||
collapsible: true,
|
||||
items: [
|
||||
{ text: 'Configuration', link: '/config/configuration' },
|
||||
{ text: 'Tutorials', link: '/config/Tutorials' },
|
||||
{ text: 'API-Usage', link: '/config/usage' },
|
||||
{ text: 'Mermaid API Configuration', link: '/config/setup/README' },
|
||||
@@ -126,7 +129,6 @@ function sidebarConfig() {
|
||||
{ text: 'Accessibility', link: '/config/accessibility' },
|
||||
{ text: 'Mermaid CLI', link: '/config/mermaidCLI' },
|
||||
{ text: 'Advanced usage', link: '/config/n00b-advanced' },
|
||||
{ text: 'Configuration', link: '/config/configuration' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import type { MarkdownRenderer } from 'vitepress';
|
||||
|
||||
// Note: using "import shiki from 'shiki' and then "const highlighter = await shiki.getHighlighter(...) does not work 2022-11-15
|
||||
import { getHighlighter } from 'shiki';
|
||||
|
||||
const MermaidExample = async (md: MarkdownRenderer) => {
|
||||
const defaultRenderer = md.renderer.rules.fence;
|
||||
|
||||
@@ -10,26 +7,29 @@ const MermaidExample = async (md: MarkdownRenderer) => {
|
||||
throw new Error('defaultRenderer is undefined');
|
||||
}
|
||||
|
||||
const highlighter = await getHighlighter({
|
||||
theme: 'material-palenight',
|
||||
langs: ['mermaid'],
|
||||
});
|
||||
|
||||
md.renderer.rules.fence = (tokens, index, options, env, slf) => {
|
||||
const token = tokens[index];
|
||||
|
||||
if (token.info.trim() === 'mermaid-example') {
|
||||
const highlight = highlighter
|
||||
.codeToHtml(token.content, { lang: 'mermaid' })
|
||||
.replace(/<span/g, '<span v-pre')
|
||||
.replace('#2e3440ff', 'transparent')
|
||||
.replace('#292D3E', 'transparent');
|
||||
if (!md.options.highlight) {
|
||||
// this function is always created by vitepress, but we need to check it
|
||||
// anyway to make TypeScript happy
|
||||
throw new Error(
|
||||
'Missing MarkdownIt highlight function (should be automatically created by vitepress'
|
||||
);
|
||||
}
|
||||
|
||||
// doing ```mermaid-example {line-numbers=5 highlight=14-17} is not supported
|
||||
const langAttrs = '';
|
||||
return `<h5>Code:</h5>
|
||||
<div class="language-mermaid">
|
||||
<button class="copy"></button>
|
||||
<span class="lang">mermaid</span>
|
||||
${highlight}
|
||||
<button class="copy"></button>
|
||||
<span class="lang">mermaid</span>
|
||||
${
|
||||
// html is pre-escaped by the highlight function
|
||||
// (it also adds `v-pre` to ignore Vue template syntax)
|
||||
md.options.highlight(token.content, 'mermaid', langAttrs)
|
||||
}
|
||||
</div>
|
||||
<h5>Diagram:</h5>`;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,25 @@ import DefaultTheme from 'vitepress/theme';
|
||||
// @ts-ignore
|
||||
import Mermaid from 'vitepress-plugin-mermaid/Mermaid.vue';
|
||||
import './custom.css';
|
||||
import { getRedirect } from './redirect';
|
||||
|
||||
export default {
|
||||
...DefaultTheme,
|
||||
enhanceApp({ app }) {
|
||||
enhanceApp({ app, router }) {
|
||||
// register global components
|
||||
app.component('Mermaid', Mermaid);
|
||||
router.onBeforeRouteChange = (to) => {
|
||||
if (router.route.path !== '/') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const newPath = getRedirect(to);
|
||||
if (newPath) {
|
||||
console.log(`Redirecting to ${newPath} from ${window.location}`);
|
||||
// router.go isn't loading the ID properly.
|
||||
window.location.href = `/mermaid/${newPath}`;
|
||||
}
|
||||
} catch (e) {}
|
||||
};
|
||||
},
|
||||
};
|
||||
} as typeof DefaultTheme;
|
||||
|
||||
89
packages/mermaid/src/docs/.vitepress/theme/redirect.ts
Normal file
89
packages/mermaid/src/docs/.vitepress/theme/redirect.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
export interface Redirect {
|
||||
path: string;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the base slug from the old URL.
|
||||
* @param link - The old URL.
|
||||
*/
|
||||
const getBaseFile = (link: string): Redirect => {
|
||||
const url = new URL(link);
|
||||
if (
|
||||
(url.hostname !== 'mermaid-js.github.io' && url.hostname !== 'localhost') ||
|
||||
url.pathname !== '/mermaid/'
|
||||
) {
|
||||
throw new Error('Not mermaidjs url');
|
||||
}
|
||||
const [path, params, ...rest] = url.hash
|
||||
.toLowerCase()
|
||||
.replace('.md', '')
|
||||
.replace(/^#\/?/g, '')
|
||||
.replace(/^\.\//g, '')
|
||||
.split('?');
|
||||
|
||||
// Find id in params
|
||||
const id = params
|
||||
?.split('&')
|
||||
.find((param) => param.startsWith('id='))
|
||||
?.split('=')[1];
|
||||
|
||||
return { path, id };
|
||||
};
|
||||
|
||||
const redirectMap: Record<string, string> = {
|
||||
'8.6.0_docs': '',
|
||||
accessibility: 'config/theming',
|
||||
breakingchanges: '',
|
||||
c4c: 'syntax/c4c',
|
||||
classdiagram: 'syntax/classDiagram',
|
||||
configuration: 'config/configuration',
|
||||
demos: 'misc/integrations',
|
||||
development: 'community/development',
|
||||
directives: 'config/directives',
|
||||
entityrelationshipdiagram: 'syntax/entityRelationshipDiagram',
|
||||
examples: 'syntax/examples',
|
||||
faq: 'misc/faq',
|
||||
flowchart: 'syntax/flowchart',
|
||||
gantt: 'syntax/gantt',
|
||||
gitgraph: 'syntax/gitgraph',
|
||||
integrations: 'misc/integrations',
|
||||
'language-highlight': '',
|
||||
markdown: '',
|
||||
mermaidapi: 'config/usage',
|
||||
mermaidcli: 'config/mermaidCLI',
|
||||
mindmap: 'syntax/mindmap',
|
||||
'more-pages': '',
|
||||
'n00b-advanced': 'config/n00b-advanced',
|
||||
'n00b-gettingstarted': 'intro/n00b-gettingStarted',
|
||||
'n00b-overview': 'community/n00b-overview',
|
||||
'n00b-syntaxreference': '',
|
||||
newdiagram: 'community/newDiagram',
|
||||
pie: 'syntax/pie',
|
||||
plugins: '',
|
||||
quickstart: 'intro/n00b-gettingStarted',
|
||||
requirementdiagram: 'syntax/requirementDiagram',
|
||||
security: 'community/security',
|
||||
sequencediagram: 'syntax/sequenceDiagram',
|
||||
setup: 'config/setup/README',
|
||||
statediagram: 'syntax/stateDiagram',
|
||||
themes: 'config/theming',
|
||||
theming: 'config/theming',
|
||||
tutorials: 'config/Tutorials',
|
||||
upgrading: '',
|
||||
usage: 'config/usage',
|
||||
'user-journey': 'syntax/userJourney',
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param link - The old documentation URL.
|
||||
* @returns The new documentation path.
|
||||
*/
|
||||
export const getRedirect = (link: string): string | undefined => {
|
||||
const { path, id } = getBaseFile(link);
|
||||
if (!(path in redirectMap)) {
|
||||
return;
|
||||
}
|
||||
return `${redirectMap[path]}.html${id ? `#${id}` : ''}`;
|
||||
};
|
||||
@@ -32,6 +32,7 @@ features:
|
||||
|
||||
<script setup>
|
||||
import { VPTeamMembers } from 'vitepress/theme'
|
||||
|
||||
const websiteSVG = {
|
||||
svg: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-globe"><circle cx="12" cy="12" r="10"></circle><line x1="2" y1="12" x2="22" y2="12"></line><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path></svg>'
|
||||
}
|
||||
|
||||
37
packages/mermaid/src/docs/redirect.spec.ts
Normal file
37
packages/mermaid/src/docs/redirect.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
// This file should be moved into .vitepress folder once https://github.com/vitest-dev/vitest/issues/2344 is resolved.
|
||||
// Update https://github.com/mermaid-js/mermaid/blob/18c27c6f1d0537a738cbd95898df301b83c38ffc/packages/mermaid/src/docs.mts#L246 once fixed
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
import { getRedirect } from './.vitepress/theme/redirect';
|
||||
|
||||
test.each([
|
||||
['http://localhost:1234/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
||||
['http://localhost/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
||||
['https://mermaid-js.github.io/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
||||
['https://mermaid-js.github.io/mermaid/#/./flowchart', 'syntax/flowchart.html'],
|
||||
['https://mermaid-js.github.io/mermaid/#/flowchart', 'syntax/flowchart.html'],
|
||||
['https://mermaid-js.github.io/mermaid/#flowchart', 'syntax/flowchart.html'],
|
||||
['https://mermaid-js.github.io/mermaid/#/flowchart', 'syntax/flowchart.html'],
|
||||
['https://mermaid-js.github.io/mermaid/#/flowchart.md?id=my-id', 'syntax/flowchart.html#my-id'],
|
||||
['https://mermaid-js.github.io/mermaid/#/./flowchart.md?id=my-id', 'syntax/flowchart.html#my-id'],
|
||||
[
|
||||
'https://mermaid-js.github.io/mermaid/#/flowchart?another=test&id=my-id&one=more',
|
||||
'syntax/flowchart.html#my-id',
|
||||
],
|
||||
['https://mermaid-js.github.io/mermaid/#/n00b-advanced', 'config/n00b-advanced.html'],
|
||||
['https://mermaid-js.github.io/mermaid/#/n00b-advanced.md', 'config/n00b-advanced.html'],
|
||||
[
|
||||
'https://mermaid-js.github.io/mermaid/#/flowchart?id=a-node-in-the-form-of-a-circle',
|
||||
'syntax/flowchart.html#a-node-in-the-form-of-a-circle',
|
||||
],
|
||||
])('should process url %s to %s', (link: string, path: string) => {
|
||||
expect(getRedirect(link)).toBe(path);
|
||||
});
|
||||
|
||||
test('should throw for invalid URL', () => {
|
||||
// Not mermaid domain
|
||||
expect(() => getRedirect('https://www.google.com')).toThrowError();
|
||||
|
||||
// Not `/mermaid/` path
|
||||
expect(() => getRedirect('http://localhost/#/flowchart.md')).toThrowError();
|
||||
});
|
||||
@@ -29,7 +29,7 @@ import utils, { directiveSanitizer } from './utils';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { MermaidConfig } from './config.type';
|
||||
import { evaluate } from './diagrams/common/common';
|
||||
import { isEmpty } from 'lodash';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
// diagram names that support classDef statements
|
||||
const CLASSDEF_DIAGRAMS = ['graph', 'flowchart', 'flowchart-v2', 'stateDiagram', 'stateDiagram-v2'];
|
||||
|
||||
Reference in New Issue
Block a user