diff --git a/src/components/Comment/Comment.spec.ts b/src/components/Comment/Comment.spec.ts index 9131c8d62..ff868fe1d 100644 --- a/src/components/Comment/Comment.spec.ts +++ b/src/components/Comment/Comment.spec.ts @@ -1,18 +1,76 @@ -import Comment from '../Comment/Comment'; +import Comment from "./Comment"; -describe('Comment', function () { +describe("Comment", function () { test.each([ - ['[red] comment1 \n', ' comment1', {color: 'red'}], - ['[red] comment \n multiple-line\n', ' comment \n multiple-line', {color: 'red'}], - ['comment \n', 'comment', {}], - ['[red] \n', '', {color: 'red'}], - ['[bold] \n', '', {fontWeight: 'bold'}], - ['[italic] \n', '', {fontStyle: 'italic'}], - ['[underline] \n', '', {textDecoration: 'underline'}], - ['[red, bold] \n', '', {color: 'red', fontWeight: 'bold'}], - ])('parse %s as text %s and color %s', function (raw, text, textStyle) { - const comment = new Comment(raw); - expect(comment.textStyle).toEqual(textStyle); - expect(comment.text).toBe(text); - }); + [ + "[red] comment1 \n", + "comment1", + { color: "red" }, + { color: "red" }, + [], + [], + ], + [ + "[red] comment \n multiple-line\n", + "[red] comment \n multiple-line", + {}, + {}, + [], + [], + ], + ["comment \n", "comment", {}, {}, [], []], + ["[red] \n", "", { color: "red" }, { color: "red" }, [], []], + ["[bold] \n", "", { fontWeight: "bold" }, { fontWeight: "bold" }, [], []], + [ + "[italic] \n", + "", + { fontStyle: "italic" }, + { fontStyle: "italic" }, + [], + [], + ], + [ + "[underline] \n", + "", + { textDecoration: "underline" }, + { textDecoration: "underline" }, + [], + [], + ], + [ + "[red, bold] \n", + "", + { color: "red", fontWeight: "bold" }, + { color: "red", fontWeight: "bold" }, + [], + [], + ], + [" (bold) \ncomment \n", " (bold) \ncomment", {}, {}, [], []], + [ + " (bold) comment \n", + "comment", + { color: "red" }, + { fontWeight: "bold" }, + [], + [], + ], + ["[color-red] comment \n", "comment", {}, {}, ["color-red"], ["color-red"]], + ])( + "parse %s as text %s and color %s", + function ( + raw, + text, + commentStyle, + messageStyle, + commentClassNames, + messageClassNames, + ) { + const comment = new Comment(raw); + expect(comment.commentStyle).toEqual(commentStyle); + expect(comment.messageStyle).toEqual(messageStyle); + expect(comment.commentClassNames).toEqual(commentClassNames); + expect(comment.messageClassNames).toEqual(messageClassNames); + expect(comment.text).toBe(text); + }, + ); }); diff --git a/src/components/Comment/Comment.ts b/src/components/Comment/Comment.ts index cf5799fb9..87ea98467 100644 --- a/src/components/Comment/Comment.ts +++ b/src/components/Comment/Comment.ts @@ -1,42 +1,84 @@ import { CSSProperties } from "vue"; import { getStyle } from "@/utils/messageStyling"; -function splitStringWithBrackets(input: string) { - const startIndex = input.indexOf("["); - const endIndex = input.indexOf("]", startIndex); - if (startIndex !== -1 && endIndex !== -1 && input.trim().indexOf("[") === 0) { - return [input.slice(startIndex + 1, endIndex), input.slice(endIndex + 1)]; +function parseLine(input: string): [string[], string[], string[], string] { + // controls comment only; + // (red) controls message only; + // [red] controls both comment and message. + const result = { + "<>": new Set(), + "()": new Set(), + "[]": new Set(), + }; + const pattern = /<([^>]*)>|\(([^)]*)\)|\[([^\]]*)\]|([^<>()[\]\s]+)/g; + let match; + let lastMatchIndex: number | undefined; + while ((match = pattern.exec(input))) { + if (match[4]) { + if (lastMatchIndex !== undefined) lastMatchIndex = match.index; + // non-empty character outside brackets is encountered + break; + } + lastMatchIndex = match.index + match[0].length; + if (match[1]) { + match[1].split(",").forEach((s) => result["<>"].add(s.trim())); + } + if (match[2]) { + match[2].split(",").forEach((s) => result["()"].add(s.trim())); + } + if (match[3]) { + match[3].split(",").forEach((s) => result["[]"].add(s.trim())); + } } - return ["", input]; -} + return [ + Array.from(result["<>"]), + Array.from(result["()"]), + Array.from(result["[]"]), + input.slice(lastMatchIndex), + ]; +} export default class Comment { // define properties color and text - public text: string; - public textStyle: CSSProperties = {}; + public text: string = ""; + /** @deprecated use commentStyle or messageStyle instead */ public classNames: string[] = []; + /** @deprecated use commentClassNames or messageClassNames instead */ + public textStyle: CSSProperties = {}; + + public commentStyle: CSSProperties = {}; + public messageStyle: CSSProperties = {}; + public commentClassNames: string[] = []; + public messageClassNames: string[] = []; // Raw comment contains all spaces and newlines constructor(raw: string) { - const lines = raw.split("\n"); + const lines = raw.slice(0, -1).split("\n"); + const lastLine = lines[lines.length - 1]; + const [commentOnlyStyles, messageOnlyStyles, commonStyles, text] = + parseLine(lastLine); - const styles = lines.reduce((acc, line) => { - const [style] = splitStringWithBrackets(line); - if (style) { - acc = [...acc, ...style.split(",").map((s) => s.trim())]; - } - return acc; - }, [] as string[]); - const { textStyle, classNames } = getStyle(styles); - this.textStyle = textStyle; - this.classNames = classNames; + const { textStyle: commentStyle, classNames: commentClassNames } = + getStyle(commentOnlyStyles); + const { textStyle: messageStyle, classNames: messageClassNames } = + getStyle(messageOnlyStyles); + const { textStyle: commonStyle, classNames: commonClassNames } = + getStyle(commonStyles); - this.text = lines.reduce((acc, line) => { - const [, text] = splitStringWithBrackets(line); - if (acc && text) { - return `${acc}\n${text}` - } - return acc || text; - }, '').trimEnd() + this.text = ( + lines.slice(0, lines.length - 1).join("\n") + + "\n" + + text + ).trim(); + this.textStyle = { ...commonStyle, ...commentStyle, ...messageStyle }; + this.classNames = [ + ...commonClassNames, + ...commentClassNames, + ...messageClassNames, + ]; + this.commentStyle = { ...commonStyle, ...commentStyle }; + this.messageStyle = { ...commonStyle, ...messageStyle }; + this.commentClassNames = [...commonClassNames, ...commentClassNames]; + this.messageClassNames = [...commonClassNames, ...messageClassNames]; } } diff --git a/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Comment/Comment.vue b/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Comment/Comment.vue index 9985f0f75..5d5f07e45 100644 --- a/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Comment/Comment.vue +++ b/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Comment/Comment.vue @@ -3,7 +3,7 @@
-
+
@@ -67,11 +67,11 @@ export default { (this.comment && marked.parse(this.comment)) ); }, - textStyle() { - return this.commentObj?.textStyle; + commentStyle() { + return this.commentObj?.commentStyle; }, classNames() { - return this.commentObj?.classNames; + return this.commentObj?.commentClassNames; }, }, }; diff --git a/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Creation/Creation.vue b/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Creation/Creation.vue index 857df8c94..3aff323f5 100644 --- a/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Creation/Creation.vue +++ b/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Creation/Creation.vue @@ -118,10 +118,10 @@ export default { return this.creation.isInitedFromOccurrence(this.from); }, messageTextStyle() { - return this.commentObj?.textStyle; + return this.commentObj?.messageStyle; }, messageClassNames() { - return this.commentObj?.classNames; + return this.commentObj?.messageClassNames; }, }, mounted() { diff --git a/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Fragment/FragmentAlt.vue b/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Fragment/FragmentAlt.vue index 53970c4b8..98a9cba26 100644 --- a/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Fragment/FragmentAlt.vue +++ b/src/components/DiagramFrame/SeqDiagram/MessageLayer/Block/Statement/Fragment/FragmentAlt.vue @@ -2,22 +2,35 @@
-
-
+
+
{{ number }}
-
+
- +
-