Files
mermaid-live-editor/src/lib/components/editor/util.ts
T
2021-08-22 10:57:20 -07:00

210 lines
5.7 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const initEditor = (monacoEditor): void => {
monacoEditor.languages.register({ id: 'mermaid' });
const orientations = ['TB', 'TD', 'BT', 'RL', 'LR'];
const typeKeywords = [
'flowchart',
'graph',
'stateDiagram-v2',
'stateDiagram',
'sequenceDiagram',
'classDiagram',
'pie',
'erDiagram',
'flowchart',
'gantt',
'gitGraph',
'journey',
'info'
];
const blockKeywords = [
'subgraph',
'rect',
'opt',
'class',
'alt',
'par',
'and',
'loop',
'else',
'end'
];
const keywords = [
'participant',
'as',
'showInfo',
'autonumber',
'rgba',
'rgb',
'hsla',
'hsl',
'linkStyle',
'style',
'classDef',
'direction',
'activate',
'deactivate',
'cssClass',
'link',
'callback',
'click',
'class',
'href',
'call'
];
// Register a tokens provider for the mermaid language
monacoEditor.languages.setMonarchTokensProvider('mermaid', {
typeKeywords,
blockKeywords,
keywords,
orientation: orientations,
noEatingSequenceArrows: ['-)', '--)', '->>', '-->>'].reduce(
(accumalator, arrow) => accumalator.concat(arrow, arrow + '+', arrow + '-'),
[]
),
eatingSequenceArrows: ['->', '-x'].reduce(
(accumalator, arrow) => accumalator.concat(arrow, arrow + '+', arrow + '-'),
[]
),
tokenizer: {
root: [
[/-{1,2}\)|-{1,2}>>/, { cases: { '@noEatingSequenceArrows': 'transition' } }],
[/\*--\*?|--\*/, 'transition'],
[/(<\|?)(\.{2}|-{2})(\|?>)?|(\.{2}|-{2})(\|?>)/, 'transition'],
[/[ox<]?(-{2,}|-+\.+-+|={2,})[ox>]?/, 'transition'],
[/[-+>]+/, { cases: { '@eatingSequenceArrows': 'transition' } }],
[':::', 'transition'],
[
/[a-z_$][\w$]*((?<=stateDiagram)-v2)?/,
{
cases: {
'@typeKeywords': 'typeKeyword',
'@blockKeywords': 'typeKeyword',
'@keywords': 'keyword'
}
}
],
[/[A-Z$][\w$]*/, { cases: { '@orientation': 'keyword' } }],
[/\[\[(fork|join|choice)\]\]/, 'annotation'],
[/[[{(}>]+.+?[)\]}]+/, 'string'],
[/[{}&]/, 'delimiter.bracket'],
[/".*"/, 'string'],
[/#(\d|[a-zA-Z])*;/, 'html.entity/hex-color-code'],
[/#(?:[0-9a-fA-F]{3}){1,2}/, 'html.entity/hex-color-code'],
[/<<.+>>/, 'annotation'],
[/%%.*(?<!%%)$/, 'comment']
]
},
whitespace: [[/[ \t\r\n]+/, 'white']]
});
monacoEditor.editor.defineTheme('mermaidTheme', {
base: 'vs',
inherit: false,
rules: [
{ token: 'typeKeyword', foreground: '9650c8', fontStyle: 'bold' },
{ token: 'keyword', foreground: '649696' },
{ token: 'custom-error', foreground: 'ff0000', fontStyle: 'bold' },
{ token: 'string', foreground: 'AA8500' },
{ token: 'transition', foreground: '008800', fontStyle: 'bold' },
{ token: 'delimiter.bracket', foreground: '000000', fontStyle: 'bold' },
{ token: 'html.entity/hex-color-code', foreground: 'f5b436' },
{ token: 'annotation', foreground: '4b4b96' },
{ token: 'comment', foreground: '888c89' }
]
});
// Register a completion item provider for the mermaid language
monacoEditor.languages.registerCompletionItemProvider('mermaid', {
provideCompletionItems: () => {
const suggestions = [
{
label: 'loop',
kind: monacoEditor.languages.CompletionItemKind.Snippet,
insertText: ['loop ${1:Loop text}', '\t$0', 'end'].join('\n'),
insertTextRules: monacoEditor.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'Sequence Diagram Loops'
},
{
label: 'alt',
kind: monacoEditor.languages.CompletionItemKind.Snippet,
insertText: ['alt ${1:Describing text}', '\t$0', 'else', '\t', 'end'].join('\n'),
insertTextRules: monacoEditor.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'Alternative Path'
},
{
label: 'opt',
kind: monacoEditor.languages.CompletionItemKind.Snippet,
insertText: ['opt ${1:Describing text}', '\t$0', 'end'].join('\n'),
insertTextRules: monacoEditor.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'Optional Path'
},
{
label: 'par',
kind: monacoEditor.languages.CompletionItemKind.Snippet,
insertText: [
'par ${1:[Action 1]}',
'\t$0',
'and ${2:[Action 2]}',
'\t',
'and ${3:[Action 3]}',
'\t',
'end'
].join('\n'),
insertTextRules: monacoEditor.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'Parallel Actions'
},
{
label: 'rect',
kind: monacoEditor.languages.CompletionItemKind.Snippet,
insertText: ['rect ${1:rgb(0, 255, 0)}', '\t$0', 'end'].join('\n'),
insertTextRules: monacoEditor.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'Background Color'
},
{
label: 'class',
kind: monacoEditor.languages.CompletionItemKind.Snippet,
insertText: ['class ${1:className} {', '\t$0', '}'].join('\n'),
insertTextRules: monacoEditor.languages.CompletionItemInsertTextRule.InsertAsSnippet,
documentation: 'Class'
},
...[...new Set([...orientations, ...typeKeywords, ...blockKeywords, ...keywords])].map(
(keyword) => ({
label: keyword,
kind: monacoEditor.languages.CompletionItemKind.Keyword,
insertText: keyword
})
)
];
return { suggestions: suggestions };
}
});
monacoEditor.languages.setLanguageConfiguration('mermaid', {
autoClosingPairs: [
{
open: '(',
close: ')'
},
{
open: '{',
close: '}'
},
{
open: '[',
close: ']'
}
],
brackets: [
['(', ')'],
['{', '}'],
['[', ']']
]
});
};