Skip to content

Commit

Permalink
Merge pull request #108 from mermaid-js/feat/comment-styling
Browse files Browse the repository at this point in the history
feat: introduce separately styling in comments
  • Loading branch information
MrCoder authored Dec 15, 2023
2 parents a92f9d8 + cff049b commit be82a25
Show file tree
Hide file tree
Showing 13 changed files with 283 additions and 125 deletions.
88 changes: 73 additions & 15 deletions src/components/Comment/Comment.spec.ts
Original file line number Diff line number Diff line change
@@ -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" },
[],
[],
],
["<red> (bold) \ncomment \n", "<red> (bold) \ncomment", {}, {}, [], []],
[
"<red> (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);
},
);
});
96 changes: 69 additions & 27 deletions src/components/Comment/Comment.ts
Original file line number Diff line number Diff line change
@@ -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] {
// <red> controls comment only;
// (red) controls message only;
// [red] controls both comment and message.
const result = {
"<>": new Set<string>(),
"()": new Set<string>(),
"[]": new Set<string>(),
};
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];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div
class="comments text-skin-comment min-w-[100px] flex text-left text-sm opacity-50 hover:opacity-100"
>
<div v-html="markedComment" :class="classNames" :style="textStyle"></div>
<div v-html="markedComment" :class="classNames" :style="commentStyle"></div>
</div>
</template>

Expand Down Expand Up @@ -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;
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,35 @@
<div class="fragment alt border-skin-fragment rounded" :style="fragmentStyle">
<div class="segment">
<comment v-if="comment" :comment="comment" :commentObj="commentObj" />
<div class="header bg-skin-fragment-header text-skin-fragment-header text-base leading-4 rounded-t relative">
<div v-if="numbering" class="absolute right-[100%] top-0 pr-1 group-hover:hidden text-gray-500 text-sm font-thin leading-6">
<div
class="header bg-skin-fragment-header text-skin-fragment-header text-base leading-4 rounded-t relative"
>
<div
v-if="numbering"
class="absolute right-[100%] top-0 pr-1 group-hover:hidden text-gray-500 text-sm font-thin leading-6"
>
{{ number }}
</div>
<div class="name font-semibold p-1 border-b text-sm">
<label class="p-0">
<collapse-button label="Alt" :collapsed="collapsed" @click="this.toggle" :style="commentObj.textStyle" :class="commentObj.classNames"/>
<collapse-button
label="Alt"
:collapsed="collapsed"
@click="this.toggle"
:style="commentObj.messageStyle"
:class="commentObj.messageClassNames"
/>
</label>
</div>
</div>
</div>

<div :class="{hidden: collapsed}">
<div :class="{ hidden: collapsed }">
<div class="segment">
<div class="text-skin-fragment flex">
<label class="condition px-1 text-sm inline-block">[{{ condition }}]</label>
<label class="condition px-1 text-sm inline-block"
>[{{ condition }}]</label
>
</div>
<block
v-if="blockInIfBlock"
Expand All @@ -28,11 +41,16 @@
incremental
></block>
</div>
<template v-for="(elseIfBlock, index) in alt.elseIfBlock()" :key="index + 500">
<template
v-for="(elseIfBlock, index) in alt.elseIfBlock()"
:key="index + 500"
>
<div class="segment mt-2 border-t border-solid">
<div class="text-skin-fragment" :key="index + 1000">
<label class="else-if hidden">else if</label>
<label class="condition px-1">[{{ conditionFromIfElseBlock(elseIfBlock) }}]</label>
<label class="condition px-1"
>[{{ conditionFromIfElseBlock(elseIfBlock) }}]</label
>
</div>
<block
:style="{ paddingLeft: `${offsetX}px` }"
Expand All @@ -46,12 +64,16 @@
</template>
<template v-if="elseBlock">
<div class="segment mt-2 border-t border-solid">
<div class="text-skin-fragment"><label class="p-1">[else]</label></div>
<div class="text-skin-fragment">
<label class="p-1">[else]</label>
</div>
<block
:style="{ paddingLeft: `${offsetX}px` }"
:context="elseBlock"
:selfCallIndent="selfCallIndent"
:number="`${number}.${blockLengthAcc[blockLengthAcc.length - 1] + 1}`"
:number="`${number}.${
blockLengthAcc[blockLengthAcc.length - 1] + 1
}`"
incremental
></block>
</div>
Expand All @@ -61,16 +83,16 @@
</template>

<script>
import { mapState } from 'vuex';
import fragment from './FragmentMixin';
import {increaseNumber, blockLength} from '@/utils/Numbering'
import { mapState } from "vuex";
import fragment from "./FragmentMixin";
import { increaseNumber, blockLength } from "@/utils/Numbering";
export default {
name: 'fragment-alt',
props: ['context', 'comment', 'selfCallIndent', 'commentObj', 'number'],
name: "fragment-alt",
props: ["context", "comment", "selfCallIndent", "commentObj", "number"],
mixins: [fragment],
computed: {
...mapState(['numbering']),
...mapState(["numbering"]),
from: function () {
return this.context.Origin();
},
Expand All @@ -87,14 +109,16 @@ export default {
return this.alt?.elseBlock()?.braceBlock()?.block();
},
blockLengthAcc() {
const acc = [blockLength(this.blockInIfBlock)]
const acc = [blockLength(this.blockInIfBlock)];
if (this.alt?.elseIfBlock()) {
this.alt.elseIfBlock().forEach(block => {
acc.push(acc[acc.length - 1] + blockLength(this.blockInElseIfBlock(block)))
})
this.alt.elseIfBlock().forEach((block) => {
acc.push(
acc[acc.length - 1] + blockLength(this.blockInElseIfBlock(block)),
);
});
}
return acc
}
return acc;
},
},
methods: {
conditionFromIfElseBlock(ctx) {
Expand Down
Loading

0 comments on commit be82a25

Please sign in to comment.