From 5f99efa611f520b218422b660b67fe1cc61a8b29 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Tue, 25 Apr 2023 13:42:27 +0530 Subject: [PATCH] Remove suggestions --- package.json | 3 +- src/lib/components/Editor.svelte | 8 +- src/lib/util/monacoExtra.ts | 605 +++++++++++++++++++++++++++++++ yarn.lock | 2 +- 4 files changed, 613 insertions(+), 5 deletions(-) create mode 100644 src/lib/util/monacoExtra.ts diff --git a/package.json b/package.json index 02fbcb5a..fa5baebe 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "tailwindcss": "^3.3.1", "tslib": "^2.5.0", "typescript": "5.0.4", - "vite": "^4.3.0", + "vite": "^4.3.1", "vitest": "^0.30.1" }, "dependencies": { @@ -75,7 +75,6 @@ "js-base64": "3.7.5", "mermaid": "10.1.0", "monaco-editor": "0.37.1", - "monaco-mermaid": "1.0.8", "pako": "2.1.0", "random-word-slugs": "0.1.7", "svg-pan-zoom": "3.6.1", diff --git a/src/lib/components/Editor.svelte b/src/lib/components/Editor.svelte index 7e495b89..37d5658f 100644 --- a/src/lib/components/Editor.svelte +++ b/src/lib/components/Editor.svelte @@ -6,9 +6,8 @@ import * as monaco from 'monaco-editor'; import monacoJsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'; import monacoEditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'; - import { onMount } from 'svelte'; - import initEditor from 'monaco-mermaid'; + import { initEditor } from '$lib/util/monacoExtra'; import { logEvent } from '$lib/util/stats'; let divEl: HTMLDivElement | undefined = undefined; @@ -50,6 +49,11 @@ // Display/clear errors monaco.editor.setModelMarkers(model, 'mermaid', errorMarkers); + monaco.languages.registerCompletionItemProvider('mermaid', { + provideCompletionItems: (model, position) => { + return { suggestions: [] }; + } + }); }); themeStore.subscribe(({ isDark }) => { diff --git a/src/lib/util/monacoExtra.ts b/src/lib/util/monacoExtra.ts new file mode 100644 index 00000000..2a45d616 --- /dev/null +++ b/src/lib/util/monacoExtra.ts @@ -0,0 +1,605 @@ +// Modified from https://github.com/Yash-Singh1/monaco-mermaid/blob/main/index.ts + +import type * as Monaco from 'monaco-editor'; + +export const initEditor = (monacoEditor: typeof Monaco): void => { + monacoEditor.languages.register({ id: 'mermaid' }); + const requirementDiagrams = [ + 'requirement', + 'functionalRequirement', + 'interfaceRequirement', + 'performanceRequirement', + 'physicalRequirement', + 'designConstraint' + ]; + const keywords: Record< + string, + { + typeKeywords: string[]; + blockKeywords: string[]; + keywords: string[]; + } + > = { + flowchart: { + typeKeywords: ['flowchart', 'flowchart-v2', 'graph'], + blockKeywords: ['subgraph', 'end'], + keywords: [ + 'TB', + 'TD', + 'BT', + 'RL', + 'LR', + 'click', + 'call', + 'href', + '_self', + '_blank', + '_parent', + '_top', + 'linkStyle', + 'style', + 'classDef', + 'class', + 'direction', + 'interpolate' + ] + }, + sequenceDiagram: { + typeKeywords: ['sequenceDiagram'], + blockKeywords: ['alt', 'par', 'and', 'loop', 'else', 'end', 'rect', 'opt', 'alt', 'rect'], + keywords: [ + 'participant', + 'as', + 'Note', + 'note', + 'right of', + 'left of', + 'over', + 'activate', + 'deactivate', + 'autonumber', + 'title', + 'actor', + 'accDescription', + 'link', + 'links' + ] + }, + classDiagram: { + typeKeywords: ['classDiagram', 'classDiagram-v2'], + blockKeywords: ['class'], + keywords: [ + 'link', + 'click', + 'callback', + 'call', + 'href', + 'cssClass', + 'direction', + 'TB', + 'BT', + 'RL', + 'LR', + 'title', + 'accDescription', + 'order' + ] + }, + stateDiagram: { + typeKeywords: ['stateDiagram', 'stateDiagram-v2'], + blockKeywords: ['state', 'note', 'end'], + keywords: ['state', 'as', 'hide empty description', 'direction', 'TB', 'BT', 'RL', 'LR'] + }, + erDiagram: { + typeKeywords: ['erDiagram'], + blockKeywords: [], + keywords: ['title', 'accDescription'] + }, + journey: { + typeKeywords: ['journey'], + blockKeywords: ['section'], + keywords: ['title'] + }, + info: { + typeKeywords: ['info'], + blockKeywords: [], + keywords: ['showInfo'] + }, + gantt: { + typeKeywords: ['gantt'], + blockKeywords: [], + keywords: [ + 'title', + 'dateFormat', + 'axisFormat', + 'todayMarker', + 'section', + 'excludes', + 'inclusiveEndDates' + ] + }, + requirementDiagram: { + typeKeywords: ['requirement', 'requirementDiagram'], + blockKeywords: [...requirementDiagrams, 'element'], + keywords: [] + }, + gitGraph: { + typeKeywords: ['gitGraph'], + blockKeywords: [], + keywords: [ + 'accTitle', + 'accDescr', + 'commit', + 'cherry-pick', + 'branch', + 'merge', + 'reset', + 'checkout', + 'LR', + 'BT', + 'id', + 'msg', + 'type', + 'tag', + 'NORMAL', + 'REVERSE', + 'HIGHLIGHT' + ] + }, + pie: { + typeKeywords: ['pie'], + blockKeywords: [], + keywords: ['title', 'showData', 'title', 'accDescription'] + }, + c4Diagram: { + typeKeywords: ['C4Context', 'C4Container', 'C4Component', 'C4Dynamic', 'C4Deployment'], + blockKeywords: [ + 'Boundary', + 'Enterprise_Boundary', + 'System_Boundary', + 'Container_Boundary', + 'Node', + 'Node_L', + 'Node_R' + ], + keywords: [ + 'title', + 'accDescription', + 'direction', + 'TB', + 'BT', + 'RL', + 'LR', + 'Person_Ext', + 'Person', + 'SystemQueue_Ext', + 'SystemDb_Ext', + 'System_Ext', + 'SystemQueue', + 'SystemDb', + 'System', + 'ContainerQueue_Ext', + 'ContainerDb_Ext', + 'Container_Ext', + 'ContainerQueue', + 'ContainerDb', + 'Container', + 'ComponentQueue_Ext', + 'ComponentDb_Ext', + 'Component_Ext', + 'ComponentQueue', + 'ComponentDb', + 'Component', + 'Deployment_Node', + 'Rel', + 'BiRel', + 'Rel_Up', + 'Rel_U', + 'Rel_Down', + 'Rel_D', + 'Rel_Left', + 'Rel_L', + 'Rel_Right', + 'Rel_R', + 'Rel_Back', + 'RelIndex' + ] + } + }; + + const configDirectiveHandler = [ + /^\s*%%(?={)/, + { + token: 'string', + next: '@configDirective', + nextEmbedded: 'javascript' + } + ] as Monaco.languages.IShortMonarchLanguageRule1; + + // Register a tokens provider for the mermaid language + monacoEditor.languages.setMonarchTokensProvider('mermaid', { + ...Object.entries(keywords) + .map((entry) => + Object.fromEntries( + Object.entries(entry[1]).map((deepEntry) => [ + entry[0] + deepEntry[0][0].toUpperCase() + deepEntry[0].slice(1), + deepEntry[1] + ]) + ) + ) + // eslint-disable-next-line unicorn/no-array-reduce + .reduce( + (overallKeywords, nextKeyword) => ({ + ...overallKeywords, + ...nextKeyword + }), + {} + ), + tokenizer: { + root: [ + [/^\s*gitGraph/m, 'typeKeyword', 'gitGraph'], + [/^\s*info/m, 'typeKeyword', 'info'], + [/^\s*pie/m, 'typeKeyword', 'pie'], + [/^\s*(flowchart|flowchart-v2|graph)/m, 'typeKeyword', 'flowchart'], + [/^\s*sequenceDiagram/, 'typeKeyword', 'sequenceDiagram'], + [/^\s*classDiagram(-v2)?/, 'typeKeyword', 'classDiagram'], + [/^\s*journey/, 'typeKeyword', 'journey'], + [/^\s*gantt/, 'typeKeyword', 'gantt'], + [/^\s*stateDiagram(-v2)?/, 'typeKeyword', 'stateDiagram'], + [/^\s*er(Diagram)?/, 'typeKeyword', 'erDiagram'], + [/^\s*requirement(Diagram)?/, 'typeKeyword', 'requirementDiagram'], + [ + /^\s*(C4Context|C4Container|C4Component|C4Dynamic|C4Deployment)/m, + 'typeKeyword', + 'c4Diagram' + ], + configDirectiveHandler, + [/%%[^${].*$/, 'comment'] + ], + configDirective: [[/%%$/, { token: 'string', next: '@pop', nextEmbedded: '@pop' }]], + gitGraph: [ + configDirectiveHandler, + [/option(?=s)/, { token: 'typeKeyword', next: 'optionsGitGraph' }], + [/(accTitle|accDescr)(\s*:)(\s*[^\n\r]+$)/, ['keyword', 'delimiter.bracket', 'string']], + [ + /(^\s*branch)(.*?)(\s+order)(:\s*)(\d+\s*$)/, + ['keyword', 'variable', 'keyword', 'delimiter.bracket', 'number'] + ], + [/".*?"/, 'string'], + [ + /(^\s*)(branch|reset|merge|checkout)(\s*\S+)/m, + ['delimiter.bracket', 'keyword', 'variable'] + ], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@gitGraphBlockKeywords': 'typeKeyword', + '@gitGraphKeywords': 'keyword' + } + } + ], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'], + [/\^/, 'delimiter.bracket'] + ], + optionsGitGraph: [ + [ + /s$/, + { + token: 'typeKeyword', + nextEmbedded: 'json' + } + ], + ['end', { token: 'typeKeyword', next: '@pop', nextEmbedded: '@pop' }] + ], + info: [ + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@infoBlockKeywords': 'typeKeyword', + '@infoKeywords': 'keyword' + } + } + ] + ], + pie: [ + configDirectiveHandler, + [/(title|accDescription)(.*$)/, ['keyword', 'string']], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@pieBlockKeywords': 'typeKeyword', + '@pieKeywords': 'keyword' + } + } + ], + [/".*?"/, 'string'], + [/\s*\d+/, 'number'], + [/:/, 'delimiter.bracket'], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'] + ], + flowchart: [ + configDirectiveHandler, + [/[ox]?(--+|==+)[ox]/, 'transition'], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@flowchartBlockKeywords': 'typeKeyword', + '@flowchartKeywords': 'keyword', + '@default': 'variable' + } + } + ], + [/\|+.+?\|+/, 'string'], + [/\[+(\\.+?[/\\]|\/.+?[/\\])]+/, 'string'], + [/[>[]+[^[\]|]+?]+/, 'string'], + [/{+.+?}+/, 'string'], + [/\(+.+?\)+/, 'string'], + [/-\.+->?/, 'transition'], + [/(-[.-])([^>-][^-]+?)(-{3,}|-{2,}>|\.-+>)/, ['transition', 'string', 'transition']], + [/(==+)([^=]+?)(={3,}|={2,}>)/, ['transition', 'string', 'transition']], + [/|===+|---+/, 'transition'], + [/:::/, 'transition'], + [/[&;]/, 'delimiter.bracket'], + [/".*?"/, 'string'], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'] + ], + sequenceDiagram: [ + configDirectiveHandler, + [/(title:?|accDescription)([^\n\r;]*$)/, ['keyword', 'string']], + [/(autonumber)([^\S\n\r]+off[^\S\n\r]*$)/, ['keyword', 'keyword']], + [/(autonumber)((?:[^\S\n\r]+\d+){2}[^\S\n\r]*$)/, ['keyword', 'number']], + [/(autonumber)([^\S\n\r]+\d+[^\S\n\r]*$)/, ['keyword', 'number']], + [ + /(link\s+)(.*?)(:)(\s*.*?)(\s*@)(\s*[^\n\r;]+)/, + ['keyword', 'variable', 'delimiter.bracket', 'string', 'delimiter.bracket', 'string'] + ], + [ + /((?:links|properties)\s+)([^\n\r:]*?)(:\s+)/, + [ + { token: 'keyword' }, + { token: 'variable' }, + { + token: 'delimiter.bracket', + nextEmbedded: 'javascript', + next: '@sequenceDiagramLinksProps' + } + ] + ], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@sequenceDiagramBlockKeywords': 'typeKeyword', + '@sequenceDiagramKeywords': 'keyword', + '@default': 'variable' + } + } + ], + [/(--?>?>|--?[)x])[+-]?/, 'transition'], + [/(:)([^\n:]*?$)/, ['delimiter.bracket', 'string']], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'] + ], + sequenceDiagramLinksProps: [ + // [/^:/, { token: 'delimiter.bracket', nextEmbedded: 'json' }], + [/$|;/, { nextEmbedded: '@pop', next: '@pop', token: 'delimiter.bracket' }] + ], + classDiagram: [ + configDirectiveHandler, + [/(^\s*(?:title|accDescription))(\s+.*$)/, ['keyword', 'string']], + [ + /(\*|<\|?|o|)(--|\.\.)(\*|\|?>|o|)([\t ]*[A-Za-z]+[\t ]*)(:)(.*?$)/, + ['transition', 'transition', 'transition', 'variable', 'delimiter.bracket', 'string'] + ], + [/(?!class\s)([A-Za-z]+)(\s+[A-Za-z]+)/, ['type', 'variable']], + [/(\*|<\|?|o)?(--|\.\.)(\*|\|?>|o)?/, 'transition'], + [/^\s*class\s(?!.*{)/, 'keyword'], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@classDiagramBlockKeywords': 'typeKeyword', + '@classDiagramKeywords': 'keyword', + '@default': 'variable' + } + } + ], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'], + [/(<<)(.+?)(>>)/, ['delimiter.bracket', 'annotation', 'delimiter.bracket']], + [/".*?"/, 'string'], + [/:::/, 'transition'], + [/:|\+|-|#|~|\*\s*$|\$\s*$|\(|\)|{|}/, 'delimiter.bracket'] + ], + journey: [ + configDirectiveHandler, + [/(title)(.*)/, ['keyword', 'string']], + [/(section)(.*)/, ['typeKeyword', 'string']], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@journeyBlockKeywords': 'typeKeyword', + '@journeyKeywords': 'keyword', + '@default': 'variable' + } + } + ], + [ + /(^\s*.+?)(:)(.*?)(:)(.*?)([$,])/, + [ + 'string', + 'delimiter.bracket', + 'number', + 'delimiter.bracket', + 'variable', + 'delimiter.bracket' + ] + ], + [/,/, 'delimiter.bracket'], + [/(^\s*.+?)(:)([^:]*?)$/, ['string', 'delimiter.bracket', 'variable']], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'] + ], + gantt: [ + configDirectiveHandler, + [/(title)(.*)/, ['keyword', 'string']], + [/(section)(.*)/, ['typeKeyword', 'string']], + [/^\s*([^\n:]*?)(:)/, ['string', 'delimiter.bracket']], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@ganttBlockKeywords': 'typeKeyword', + '@ganttKeywords': 'keyword' + } + } + ], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'], + [/:/, 'delimiter.bracket'] + ], + stateDiagram: [ + configDirectiveHandler, + [/note[^:]*$/, { token: 'typeKeyword', next: 'stateDiagramNote' }], + ['hide empty description', 'keyword'], + [/^\s*state\s(?!.*{)/, 'keyword'], + [/(<<)(fork|join|choice)(>>)/, 'annotation'], + [/(\[\[)(fork|join|choice)(]])/, ['delimiter.bracket', 'annotation', 'delimiter.bracket']], + [ + /[A-Za-z][\w$]*/, + { + cases: { + '@stateDiagramBlockKeywords': 'typeKeyword', + '@stateDiagramKeywords': 'keyword', + '@default': 'variable' + } + } + ], + [/".*?"/, 'string'], + [/(:)([^\n:]*?$)/, ['delimiter.bracket', 'string']], + [/{|}/, 'delimiter.bracket'], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'], + [/-->/, 'transition'], + [/\[.*?]/, 'string'] + ], + stateDiagramNote: [ + [/^\s*end note$/, { token: 'typeKeyword', next: '@pop' }], + [/.*/, 'string'] + ], + erDiagram: [ + configDirectiveHandler, + [/(title|accDescription)(.*$)/, ['keyword', 'string']], + [/[|}][o|](--|\.\.)[o|][{|]/, 'transition'], + [/".*?"/, 'string'], + [/(:)(.*?$)/, ['delimiter.bracket', 'string']], + [/[:{}]/, 'delimiter.bracket'], + [/([A-Za-z]+)(\s+[A-Za-z]+)/, ['type', 'variable']], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'], + [/[A-Z_a-z-][\w$]*/, 'variable'] + ], + requirementDiagram: [ + configDirectiveHandler, + [/->|<-|-/, 'transition'], + [/(\d+\.)*\d+/, 'number'], + [ + /[A-Z_a-z-][\w$]*/, + { + cases: { + '@requirementDiagramBlockKeywords': 'typeKeyword', + '@default': 'variable' + } + } + ], + [/[/:{}]/, 'delimiter.bracket'], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'], + [/".*?"/, 'string'] + ], + c4Diagram: [ + configDirectiveHandler, + [/(title|accDescription)(.*$)/, ['keyword', 'string']], + [/\(/, { token: 'delimiter.bracket', next: 'c4DiagramParenthesis' }], + [ + /[A-Z_a-z-][\w$]*/, + { + cases: { + '@c4DiagramBlockKeywords': 'typeKeyword', + '@c4DiagramKeywords': 'keyword', + '@default': 'variable' + } + } + ], + [/%%[^$]([^%]*(?!%%$)%?)*$/, 'comment'] + ], + c4DiagramParenthesis: [ + [/,/, 'delimiter.bracket'], + [/\)/, { next: '@pop', token: 'delimiter.bracket' }], + [/[^),]/, 'string'] + ] + } + }); + + monacoEditor.editor.defineTheme('mermaid-dark', { + base: 'vs-dark', + inherit: true, + colors: {}, + rules: [ + { token: 'typeKeyword', foreground: '9650c8', fontStyle: 'bold' }, + { token: 'transition', foreground: '008800', fontStyle: 'bold' }, + { token: 'identifier', foreground: '9cdcfe' } + ] + }); + + monacoEditor.editor.defineTheme('mermaid', { + base: 'vs', + inherit: true, + colors: {}, + 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: 'annotation', foreground: '4b4b96' }, + { token: 'number', foreground: '4b4b96' }, + { token: 'comment', foreground: '888c89' }, + { token: 'variable', foreground: 'A22889' }, + { token: 'type', foreground: '2BDEA8' }, + { token: 'identifier', foreground: '9cdcfe' } + ] + }); + + monacoEditor.languages.registerCompletionItemProvider('mermaid', { + provideCompletionItems: () => { + return { + suggestions: [] + }; + } + }); + + monacoEditor.languages.setLanguageConfiguration('mermaid', { + autoClosingPairs: [ + { + open: '(', + close: ')' + }, + { + open: '{', + close: '}' + }, + { + open: '[', + close: ']' + } + ], + brackets: [ + ['(', ')'], + ['{', '}'], + ['[', ']'] + ], + comments: { + lineComment: '%%' + } + }); +}; diff --git a/yarn.lock b/yarn.lock index bd57cd05..3702be71 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5815,7 +5815,7 @@ vite-node@0.30.1: optionalDependencies: fsevents "~2.3.2" -vite@^4.3.0: +vite@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/vite/-/vite-4.3.1.tgz#9badb1377f995632cdcf05f32103414db6fbb95a" integrity sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==