mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-15 06:19:24 +02:00
feat(katex): added KaTeX support to sequence diagrams
This commit is contained in:
@@ -16,134 +16,167 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>Sequence diagram demos</h1>
|
<h1>Sequence diagram demos</h1>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
accTitle: test the accTitle
|
accTitle: test the accTitle
|
||||||
accDescr: Test a description
|
accDescr: Test a description
|
||||||
|
|
||||||
participant Alice
|
participant Alice
|
||||||
participant Bob
|
participant Bob
|
||||||
participant John as John<br />Second Line
|
participant John as John<br />Second Line
|
||||||
autonumber 10 10
|
autonumber 10 10
|
||||||
rect rgb(200, 220, 100)
|
rect rgb(200, 220, 100)
|
||||||
rect rgb(200, 255, 200)
|
rect rgb(200, 255, 200)
|
||||||
|
|
||||||
Alice ->> Bob: Hello Bob, how are you?
|
Alice ->> Bob: Hello Bob, how are you?
|
||||||
Bob-->>John: How about you John?
|
Bob-->>John: How about you John?
|
||||||
end
|
end
|
||||||
|
|
||||||
Bob--x Alice: I am good thanks!
|
Bob--x Alice: I am good thanks!
|
||||||
Bob-x John: I am good thanks!
|
Bob-x John: I am good thanks!
|
||||||
Note right of John: John thinks a long<br />long time, so long<br />that the text does<br />not fit on a row.
|
Note right of John: John thinks a long<br />long time, so long<br />that the text does<br />not fit on a row.
|
||||||
|
|
||||||
Bob-->Alice: Checking with John...
|
Bob-->Alice: Checking with John...
|
||||||
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
|
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
|
||||||
Bob-x John: Hey John - we're still waiting to know<br />how you're doing
|
Bob-x John: Hey John - we're still waiting to know<br />how you're doing
|
||||||
Note over John:nowrap: John's trying hard not to break his train of thought.
|
Note over John:nowrap: John's trying hard not to break his train of thought.
|
||||||
Bob-x John:wrap: John! Are you still debating about how you're doing? How long does it take??
|
Bob-x John:wrap: John! Are you still debating about how you're doing? How long does it take??
|
||||||
Note over John: After a few more moments, John<br />finally snaps out of it.
|
Note over John: After a few more moments, John<br />finally snaps out of it.
|
||||||
end
|
end
|
||||||
|
|
||||||
autonumber off
|
autonumber off
|
||||||
alt either this
|
alt either this
|
||||||
Alice->>+John: Yes
|
Alice->>+John: Yes
|
||||||
John-->>-Alice: OK
|
John-->>-Alice: OK
|
||||||
else or this
|
else or this
|
||||||
autonumber
|
autonumber
|
||||||
Alice->>John: No
|
Alice->>John: No
|
||||||
else or this will happen
|
else or this will happen
|
||||||
Alice->John: Maybe
|
Alice->John: Maybe
|
||||||
end
|
end
|
||||||
autonumber 200
|
autonumber 200
|
||||||
par this happens in parallel
|
par this happens in parallel
|
||||||
Alice -->> Bob: Parallel message 1
|
Alice -->> Bob: Parallel message 1
|
||||||
and
|
and
|
||||||
Alice -->> John: Parallel message 2
|
Alice -->> John: Parallel message 2
|
||||||
end
|
end
|
||||||
</pre>
|
|
||||||
<hr />
|
|
||||||
<pre class="mermaid">
|
|
||||||
sequenceDiagram
|
|
||||||
accTitle: Sequence diagram title is here
|
|
||||||
accDescr: Hello friends
|
|
||||||
|
|
||||||
participant Alice
|
|
||||||
participant Bob
|
|
||||||
participant John as John<br />Second Line
|
|
||||||
rect rgb(200, 220, 100)
|
|
||||||
rect rgb(200, 255, 200)
|
|
||||||
Alice ->> Bob: Hello Bob, how are you?
|
|
||||||
Bob-->>John: How about you John?
|
|
||||||
end
|
|
||||||
Bob--x Alice: I am good thanks!
|
|
||||||
Bob-x John: I am good thanks!
|
|
||||||
Note right of John: John thinks a long<br />long time, so long<br />that the text does<br />not fit on a row.
|
|
||||||
Bob-->Alice: Checking with John...
|
|
||||||
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
|
|
||||||
Bob-x John: Hey John - we're still waiting to know<br />how you're doing
|
|
||||||
Note over John:nowrap: John's trying hard not to break his train of thought.
|
|
||||||
Bob-x John:wrap: John! Are you still debating about how you're doing? How long does it take??
|
|
||||||
Note over John: After a few more moments, John<br />finally snaps out of it.
|
|
||||||
end
|
|
||||||
alt either this
|
|
||||||
Alice->>John: Yes
|
|
||||||
else or this
|
|
||||||
Alice->>John: No
|
|
||||||
else or this will happen
|
|
||||||
Alice->John: Maybe
|
|
||||||
end
|
|
||||||
par this happens in parallel
|
|
||||||
Alice -->> Bob: Parallel message 1
|
|
||||||
and
|
|
||||||
Alice -->> John: Parallel message 2
|
|
||||||
end
|
|
||||||
</pre>
|
</pre>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
participant 1 as multiline<br>using #lt;br#gt;
|
accTitle: Sequence diagram title is here
|
||||||
participant 2 as multiline<br />using #lt;br/#gt;
|
accDescr: Hello friends
|
||||||
participant 3 as multiline<br />using #lt;br /#gt;
|
|
||||||
participant 4 as multiline<br />using #lt;br /#gt;
|
|
||||||
1->>2: multiline<br>using #lt;br#gt;
|
|
||||||
note right of 2: multiline<br>using #lt;br#gt;
|
|
||||||
2->>3: multiline<br />using #lt;br/#gt;
|
|
||||||
note right of 3: multiline<br />using #lt;br/#gt;
|
|
||||||
3->>4: multiline<br />using #lt;br /#gt;
|
|
||||||
note right of 4: multiline<br />using #lt;br /#gt;
|
|
||||||
4->>1: multiline<br />using #lt;br /#gt;
|
|
||||||
note right of 1: multiline<br />using #lt;br /#gt;
|
|
||||||
</pre>
|
|
||||||
<hr />
|
|
||||||
|
|
||||||
<pre class="mermaid">
|
participant Alice
|
||||||
sequenceDiagram
|
participant Bob
|
||||||
autonumber
|
participant John as John<br />Second Line
|
||||||
Alice->>John: Hello John,<br>how are you?
|
rect rgb(200, 220, 100)
|
||||||
autonumber 50 10
|
rect rgb(200, 255, 200)
|
||||||
Alice->>John: John,<br />can you hear me?
|
Alice ->> Bob: Hello Bob, how are you?
|
||||||
John-->>Alice: Hi Alice,<br />I can hear you!
|
Bob-->>John: How about you John?
|
||||||
autonumber off
|
end
|
||||||
John-->>Alice: I feel great!
|
Bob--x Alice: I am good thanks!
|
||||||
</pre>
|
Bob-x John: I am good thanks!
|
||||||
|
Note right of John: John thinks a long<br />long time, so long<br />that the text does<br />not fit on a row.
|
||||||
|
Bob-->Alice: Checking with John...
|
||||||
|
Note over John:wrap: John looks like he's still thinking, so Bob prods him a bit.
|
||||||
|
Bob-x John: Hey John - we're still waiting to know<br />how you're doing
|
||||||
|
Note over John:nowrap: John's trying hard not to break his train of thought.
|
||||||
|
Bob-x John:wrap: John! Are you still debating about how you're doing? How long does it take??
|
||||||
|
Note over John: After a few more moments, John<br />finally snaps out of it.
|
||||||
|
end
|
||||||
|
alt either this
|
||||||
|
Alice->>John: Yes
|
||||||
|
else or this
|
||||||
|
Alice->>John: No
|
||||||
|
else or this will happen
|
||||||
|
Alice->John: Maybe
|
||||||
|
end
|
||||||
|
par this happens in parallel
|
||||||
|
Alice -->> Bob: Parallel message 1
|
||||||
|
and
|
||||||
|
Alice -->> John: Parallel message 2
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
sequenceDiagram
|
sequenceDiagram
|
||||||
box lightgreen Alice & John
|
participant 1 as multiline<br>using #lt;br#gt;
|
||||||
participant A
|
participant 2 as multiline<br />using #lt;br/#gt;
|
||||||
participant J
|
participant 3 as multiline<br />using #lt;br /#gt;
|
||||||
end
|
participant 4 as multiline<br />using #lt;br /#gt;
|
||||||
box Another Group very very long description not wrapped
|
1->>2: multiline<br>using #lt;br#gt;
|
||||||
participant B
|
note right of 2: multiline<br>using #lt;br#gt;
|
||||||
end
|
2->>3: multiline<br />using #lt;br/#gt;
|
||||||
A->>J: Hello John, how are you?
|
note right of 3: multiline<br />using #lt;br/#gt;
|
||||||
J->>A: Great!
|
3->>4: multiline<br />using #lt;br /#gt;
|
||||||
A->>B: Hello Bob, how are you ?
|
note right of 4: multiline<br />using #lt;br /#gt;
|
||||||
</pre
|
4->>1: multiline<br />using #lt;br /#gt;
|
||||||
|
note right of 1: multiline<br />using #lt;br /#gt;
|
||||||
|
</pre>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
autonumber
|
||||||
|
Alice->>John: Hello John,<br>how are you?
|
||||||
|
autonumber 50 10
|
||||||
|
Alice->>John: John,<br />can you hear me?
|
||||||
|
John-->>Alice: Hi Alice,<br />I can hear you!
|
||||||
|
autonumber off
|
||||||
|
John-->>Alice: I feel great!
|
||||||
|
</pre>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
box lightgreen Alice & John
|
||||||
|
participant A
|
||||||
|
participant J
|
||||||
|
end
|
||||||
|
box Another Group very very long description not wrapped
|
||||||
|
participant B
|
||||||
|
end
|
||||||
|
A->>J: Hello John, how are you?
|
||||||
|
J->>A: Great!
|
||||||
|
A->>B: Hello Bob, how are you ?
|
||||||
|
</pre
|
||||||
>
|
>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
participant 1 as $$\frac{\lim_{x\rightarrow0}{\frac{1}{x}}}{\frac{-b\pm\sqrt{b^2-4ac}}{2a}}$$
|
||||||
|
participant 2 as $$\beta$$
|
||||||
|
participant 3 as $$\delta$$
|
||||||
|
participant 4 as $$\frac{\frac{\lim_{x\rightarrow0}{\frac{1}{x}}}{\frac{-b\pm\sqrt{b^2-4ac}}{2a}}}{\frac{\text{d}}{\text{d}x}{x^2}}$$
|
||||||
|
1->>2: $$\sqrt{2}$$
|
||||||
|
note right of 2: $$\frac{1+\frac{1+\frac{1+\frac{1}{2}}{2}}{2}}{2}+\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$
|
||||||
|
2->>3: $$\frac{\lim_{x\rightarrow0}{\frac{1}{x}}}{\frac{-b\pm\sqrt{b^2-4ac}}{2a}}$$
|
||||||
|
note right of 3: $$\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$
|
||||||
|
3->>4: $$\lim_{x\rightarrow0}{\frac{1}{x}}$$;
|
||||||
|
note right of 4: multiline
|
||||||
|
4->>1: multiline<br />using #lt;br /#gt;
|
||||||
|
note right of 1: multiline<br />$$\frac{1}{2}$$<br />3rd line
|
||||||
|
</pre>
|
||||||
|
<hr />
|
||||||
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
autonumber
|
||||||
|
participant 1 as $$\alpha$$lex
|
||||||
|
participant 2 as $$\beta$$ob
|
||||||
|
participant 3 as $$\theta$$iffany
|
||||||
|
1->>2: Hello John, does $$\frac{1}{2}+1=2$$?
|
||||||
|
loop $$\frac{1}{2}+1=2$$
|
||||||
|
2->>2: $$\frac{1}{2}+1=\frac{3}{2}$$
|
||||||
|
end
|
||||||
|
Note right of 2: $$x = \begin{cases} 1 &\text{if } \frac{1}{2}+1=2 \\ 0 &\text{if } \frac{1}{2}+1\ne2 \end{cases}$$
|
||||||
|
2-->>1: $$\frac{1}{2}+1\ne2\implies 1$$
|
||||||
|
2->>3: $$\frac{\text{d}}{\text{d}x}{3x^2+2x+1}$$
|
||||||
|
3-->>2: $$6x+2$$
|
||||||
|
</pre>
|
||||||
|
<hr />
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from './mermaid.esm.mjs';
|
import mermaid from './mermaid.esm.mjs';
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
|
@@ -195,7 +195,8 @@ export const hasKatex = (text: string): boolean => (text.match(katexRegex)?.leng
|
|||||||
* @returns Object containing {width, height}
|
* @returns Object containing {width, height}
|
||||||
*/
|
*/
|
||||||
export const calculateMathMLDimensions = (text: string, config: MermaidConfig) => {
|
export const calculateMathMLDimensions = (text: string, config: MermaidConfig) => {
|
||||||
text = renderKatex(text, config).split(lineBreakRegex).map((text) => hasKatex(text) ? renderKatex(text, config) : `<div>${text}</div>`).join('');
|
|
||||||
|
text = renderKatex(text, config);
|
||||||
const divElem = document.createElement('div')
|
const divElem = document.createElement('div')
|
||||||
divElem.innerHTML = text;
|
divElem.innerHTML = text;
|
||||||
divElem.id = 'katex-temp';
|
divElem.id = 'katex-temp';
|
||||||
@@ -209,6 +210,13 @@ export const calculateMathMLDimensions = (text: string, config: MermaidConfig) =
|
|||||||
return dim;
|
return dim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export const temp = (text: string, config: MermaidConfig) => {
|
||||||
|
// return renderKatex(text, config).split(lineBreakRegex).map((text) =>
|
||||||
|
// hasKatex(text) ?
|
||||||
|
// `<div style="display: flex;">${text}</div>` :
|
||||||
|
// `<div>${text}</div>`).join('');
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to render and return the KaTeX portion of a string with MathML
|
* Attempts to render and return the KaTeX portion of a string with MathML
|
||||||
*
|
*
|
||||||
@@ -218,14 +226,25 @@ export const calculateMathMLDimensions = (text: string, config: MermaidConfig) =
|
|||||||
*/
|
*/
|
||||||
export const renderKatex = (text: string, config: MermaidConfig): string => {
|
export const renderKatex = (text: string, config: MermaidConfig): string => {
|
||||||
if (isMathMLSupported || (!isMathMLSupported && config.legacyMathML)) {
|
if (isMathMLSupported || (!isMathMLSupported && config.legacyMathML)) {
|
||||||
return text.replace(/\$\$(.*)\$\$/g, (r, c) =>
|
return text
|
||||||
katex
|
.split(lineBreakRegex)
|
||||||
.renderToString(c, { throwOnError: true, displayMode: true, output: isMathMLSupported ? 'mathml' : 'htmlAndMathml' })
|
.map((line) => hasKatex(line) ?
|
||||||
.replace(/\n/g, ' ')
|
`
|
||||||
.replace(/<annotation.*<\/annotation>/g, '')
|
<div style="display: flex; align-items: center; justify-content: center; white-space: nowrap;">
|
||||||
);
|
${line}
|
||||||
|
</div>
|
||||||
|
` :
|
||||||
|
`<div>${line}</div>`
|
||||||
|
)
|
||||||
|
.join('')
|
||||||
|
.replace(katexRegex, (r, c) =>
|
||||||
|
katex
|
||||||
|
.renderToString(c, { throwOnError: true, displayMode: true, output: isMathMLSupported ? 'mathml' : 'htmlAndMathml' })
|
||||||
|
.replace(/\n/g, ' ')
|
||||||
|
.replace(/<annotation.*<\/annotation>/g, '')
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return text.replace(/\$\$(.*)\$\$/g, (r, c) => 'MathML is unsupported in this environment.');
|
return text.replace(katexRegex, 'MathML is unsupported in this environment.');
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
// @ts-nocheck TODO: fix file
|
// @ts-nocheck TODO: fix file
|
||||||
import { select, selectAll } from 'd3';
|
import { select, selectAll } from 'd3';
|
||||||
import svgDraw, { drawText, fixLifeLineHeights } from './svgDraw.js';
|
import svgDraw, { drawKatex, drawText, fixLifeLineHeights } from './svgDraw.js';
|
||||||
import { log } from '../../logger.js';
|
import { log } from '../../logger.js';
|
||||||
import common from '../common/common.js';
|
import common, { calculateMathMLDimensions, hasKatex } from '../common/common.js';
|
||||||
import * as configApi from '../../config.js';
|
import * as configApi from '../../config.js';
|
||||||
import assignWithDepth from '../../assignWithDepth.js';
|
import assignWithDepth from '../../assignWithDepth.js';
|
||||||
import utils from '../../utils.js';
|
import utils from '../../utils.js';
|
||||||
@@ -247,7 +247,7 @@ const drawNote = function (elem: any, noteModel: NoteModel) {
|
|||||||
textObj.textMargin = conf.noteMargin;
|
textObj.textMargin = conf.noteMargin;
|
||||||
textObj.valign = 'center';
|
textObj.valign = 'center';
|
||||||
|
|
||||||
const textElem = drawText(g, textObj);
|
const textElem = hasKatex(textObj.text) ? drawKatex(g, textObj) : drawText(g, textObj);
|
||||||
|
|
||||||
const textHeight = Math.round(
|
const textHeight = Math.round(
|
||||||
textElem
|
textElem
|
||||||
@@ -299,11 +299,16 @@ function boundMessage(_diagram, msgModel): number {
|
|||||||
bounds.bumpVerticalPos(10);
|
bounds.bumpVerticalPos(10);
|
||||||
const { startx, stopx, message } = msgModel;
|
const { startx, stopx, message } = msgModel;
|
||||||
const lines = common.splitBreaks(message).length;
|
const lines = common.splitBreaks(message).length;
|
||||||
const textDims = utils.calculateTextDimensions(message, messageFont(conf));
|
const isKatexMsg = hasKatex(message);
|
||||||
const lineHeight = textDims.height / lines;
|
const textDims = isKatexMsg ?
|
||||||
msgModel.height += lineHeight;
|
calculateMathMLDimensions(message, configApi.getConfig()) :
|
||||||
|
utils.calculateTextDimensions(message, messageFont(conf));
|
||||||
|
|
||||||
bounds.bumpVerticalPos(lineHeight);
|
if (!isKatexMsg) {
|
||||||
|
const lineHeight = textDims.height / lines;
|
||||||
|
msgModel.height += lineHeight;
|
||||||
|
bounds.bumpVerticalPos(lineHeight);
|
||||||
|
}
|
||||||
|
|
||||||
let lineStartY;
|
let lineStartY;
|
||||||
let totalOffset = textDims.height - 10;
|
let totalOffset = textDims.height - 10;
|
||||||
@@ -362,7 +367,7 @@ const drawMessage = function (diagram, msgModel, lineStartY: number, diagObj: Di
|
|||||||
textObj.textMargin = conf.wrapPadding;
|
textObj.textMargin = conf.wrapPadding;
|
||||||
textObj.tspan = false;
|
textObj.tspan = false;
|
||||||
|
|
||||||
drawText(diagram, textObj);
|
hasKatex(textObj.text) ? drawKatex(diagram, textObj, {startx, stopx, starty: lineStartY}) : drawText(diagram, textObj);
|
||||||
|
|
||||||
const textWidth = textDims.width;
|
const textWidth = textDims.width;
|
||||||
|
|
||||||
@@ -1005,7 +1010,9 @@ function getMaxMessageWidthPerActor(
|
|||||||
const wrappedMessage = msg.wrap
|
const wrappedMessage = msg.wrap
|
||||||
? utils.wrapLabel(msg.message, conf.width - 2 * conf.wrapPadding, textFont)
|
? utils.wrapLabel(msg.message, conf.width - 2 * conf.wrapPadding, textFont)
|
||||||
: msg.message;
|
: msg.message;
|
||||||
const messageDimensions = utils.calculateTextDimensions(wrappedMessage, textFont);
|
const messageDimensions = hasKatex(wrappedMessage) ?
|
||||||
|
calculateMathMLDimensions(msg.message, configApi.getConfig()) :
|
||||||
|
utils.calculateTextDimensions(wrappedMessage, textFont);
|
||||||
const messageWidth = messageDimensions.width + 2 * conf.wrapPadding;
|
const messageWidth = messageDimensions.width + 2 * conf.wrapPadding;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1116,7 +1123,10 @@ function calculateActorMargins(
|
|||||||
actorFont(conf)
|
actorFont(conf)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const actDims = utils.calculateTextDimensions(actor.description, actorFont(conf));
|
const actDims = hasKatex(actor.description) ?
|
||||||
|
calculateMathMLDimensions(actor.description, configApi.getConfig()) :
|
||||||
|
utils.calculateTextDimensions(actor.description, actorFont(conf));
|
||||||
|
|
||||||
actor.width = actor.wrap
|
actor.width = actor.wrap
|
||||||
? conf.width
|
? conf.width
|
||||||
: Math.max(conf.width, actDims.width + 2 * conf.wrapPadding);
|
: Math.max(conf.width, actDims.width + 2 * conf.wrapPadding);
|
||||||
@@ -1179,20 +1189,22 @@ const buildNoteModel = function (msg, actors, diagObj) {
|
|||||||
const stopx = actors[msg.to].x;
|
const stopx = actors[msg.to].x;
|
||||||
const shouldWrap = msg.wrap && msg.message;
|
const shouldWrap = msg.wrap && msg.message;
|
||||||
|
|
||||||
let textDimensions = utils.calculateTextDimensions(
|
let textDimensions: {width: number, height: number, lineHeight?: number} = hasKatex(msg.message) ?
|
||||||
shouldWrap ? utils.wrapLabel(msg.message, conf.width, noteFont(conf)) : msg.message,
|
calculateMathMLDimensions(msg.message, configApi.getConfig()) :
|
||||||
noteFont(conf)
|
utils.calculateTextDimensions(
|
||||||
);
|
shouldWrap ? utils.wrapLabel(msg.message, conf.width, noteFont(conf)) : msg.message,
|
||||||
|
noteFont(conf)
|
||||||
|
);
|
||||||
const noteModel = {
|
const noteModel = {
|
||||||
width: shouldWrap
|
width: shouldWrap
|
||||||
? conf.width
|
? conf.width
|
||||||
: Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin),
|
: Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin),
|
||||||
height: 0,
|
height: 0,
|
||||||
startx: actors[msg.from].x,
|
startx: actors[msg.from].x,
|
||||||
stopx: 0,
|
stopx: 0,
|
||||||
starty: 0,
|
starty: 0,
|
||||||
stopy: 0,
|
stopy: 0,
|
||||||
message: msg.message,
|
message: msg.message,
|
||||||
};
|
};
|
||||||
if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
|
if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
|
||||||
noteModel.width = shouldWrap
|
noteModel.width = shouldWrap
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import common from '../common/common.js';
|
import common, { calculateMathMLDimensions, hasKatex, renderKatex } from '../common/common.js';
|
||||||
import { addFunction } from '../../interactionDb.js';
|
import { addFunction } from '../../interactionDb.js';
|
||||||
import { parseFontSize } from '../../utils.js';
|
import { parseFontSize } from '../../utils.js';
|
||||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||||
|
import * as configApi from '../../config.js';
|
||||||
|
|
||||||
export const drawRect = function (elem, rectData) {
|
export const drawRect = function (elem, rectData) {
|
||||||
const rectElem = elem.append('rect');
|
const rectElem = elem.append('rect');
|
||||||
@@ -152,6 +153,48 @@ const popupMenuDownFunc = function (popupId) {
|
|||||||
pu.style.display = 'none';
|
pu.style.display = 'none';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const drawKatex = function (elem, textData, msgModel = null) {
|
||||||
|
let textElem = elem.append('foreignObject');
|
||||||
|
const lines = renderKatex(textData.text, configApi.getConfig());
|
||||||
|
|
||||||
|
const divElem = textElem
|
||||||
|
.append('xhtml:div')
|
||||||
|
.attr('style', 'width: fit-content;')
|
||||||
|
.attr('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||||
|
.html(lines);
|
||||||
|
const dim = divElem.node().getBoundingClientRect();
|
||||||
|
|
||||||
|
textElem.attr('height', Math.round(dim.height)).attr('width', Math.round(dim.width));
|
||||||
|
|
||||||
|
if (textData.class === 'noteText') {
|
||||||
|
const rectElem = elem.node().firstChild;
|
||||||
|
|
||||||
|
rectElem.setAttribute('height', dim.height + 2 * textData.textMargin);
|
||||||
|
const rectDim = rectElem.getBBox();
|
||||||
|
|
||||||
|
textElem
|
||||||
|
.attr('x', Math.round(rectDim.x + rectDim.width / 2 - dim.width / 2))
|
||||||
|
.attr('y', Math.round(rectDim.y + rectDim.height / 2 - dim.height / 2));
|
||||||
|
} else if (msgModel) {
|
||||||
|
let { startx, stopx, starty } = msgModel;
|
||||||
|
if (startx > stopx) {
|
||||||
|
const temp = startx;
|
||||||
|
startx = stopx;
|
||||||
|
stopx = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
textElem.attr('x', Math.round(startx + Math.abs(startx - stopx) / 2 - dim.width / 2))
|
||||||
|
if (textData.class === 'loopText') {
|
||||||
|
textElem.attr('y', Math.round(starty));
|
||||||
|
} else {
|
||||||
|
textElem.attr('y', Math.round(starty - dim.height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [textElem];
|
||||||
|
};
|
||||||
|
|
||||||
export const drawText = function (elem, textData) {
|
export const drawText = function (elem, textData) {
|
||||||
let prevTextHeight = 0,
|
let prevTextHeight = 0,
|
||||||
textHeight = 0;
|
textHeight = 0;
|
||||||
@@ -397,7 +440,7 @@ const drawActorTypeParticipant = function (elem, actor, conf, isFooter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_drawTextCandidateFunc(conf)(
|
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
|
||||||
actor.description,
|
actor.description,
|
||||||
g,
|
g,
|
||||||
rect.x,
|
rect.x,
|
||||||
@@ -487,7 +530,7 @@ const drawActorTypeActor = function (elem, actor, conf, isFooter) {
|
|||||||
const bounds = actElem.node().getBBox();
|
const bounds = actElem.node().getBBox();
|
||||||
actor.height = bounds.height;
|
actor.height = bounds.height;
|
||||||
|
|
||||||
_drawTextCandidateFunc(conf)(
|
_drawTextCandidateFunc(conf, hasKatex(actor.description))(
|
||||||
actor.description,
|
actor.description,
|
||||||
actElem,
|
actElem,
|
||||||
rect.x,
|
rect.x,
|
||||||
@@ -623,7 +666,8 @@ export const drawLoop = function (elem, loopModel, labelText, conf) {
|
|||||||
txt.fontWeight = fontWeight;
|
txt.fontWeight = fontWeight;
|
||||||
txt.wrap = true;
|
txt.wrap = true;
|
||||||
|
|
||||||
let textElem = drawText(g, txt);
|
|
||||||
|
let textElem = hasKatex(txt.text) ? drawKatex(g, txt, loopModel) : drawText(g, txt);
|
||||||
|
|
||||||
if (loopModel.sectionTitles !== undefined) {
|
if (loopModel.sectionTitles !== undefined) {
|
||||||
loopModel.sectionTitles.forEach(function (item, idx) {
|
loopModel.sectionTitles.forEach(function (item, idx) {
|
||||||
@@ -639,7 +683,13 @@ export const drawLoop = function (elem, loopModel, labelText, conf) {
|
|||||||
txt.fontSize = fontSize;
|
txt.fontSize = fontSize;
|
||||||
txt.fontWeight = fontWeight;
|
txt.fontWeight = fontWeight;
|
||||||
txt.wrap = loopModel.wrap;
|
txt.wrap = loopModel.wrap;
|
||||||
textElem = drawText(g, txt);
|
|
||||||
|
if (hasKatex(txt.text)) {
|
||||||
|
loopModel.starty = loopModel.sections[idx].y;
|
||||||
|
drawKatex(g, txt, loopModel);
|
||||||
|
} else {
|
||||||
|
drawText(g, txt);
|
||||||
|
}
|
||||||
let sectionHeight = Math.round(
|
let sectionHeight = Math.round(
|
||||||
textElem
|
textElem
|
||||||
.map((te) => (te._groups || te)[0][0].getBBox().height)
|
.map((te) => (te._groups || te)[0][0].getBBox().height)
|
||||||
@@ -930,6 +980,29 @@ const _drawTextCandidateFunc = (function () {
|
|||||||
_setTextAttrs(text, textAttrs);
|
_setTextAttrs(text, textAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function byKatex(content, g, x, y, width, height, textAttrs, conf) {
|
||||||
|
// TODO duplicate render calls, optimize
|
||||||
|
const dim = calculateMathMLDimensions(content, configApi.getConfig());
|
||||||
|
const s = g.append('switch');
|
||||||
|
const f = s
|
||||||
|
.append('foreignObject')
|
||||||
|
.attr('x', x + width / 2 - dim.width / 2)
|
||||||
|
.attr('y', y + height / 2 - dim.height / 2)
|
||||||
|
.attr('width', dim.width)
|
||||||
|
.attr('height', dim.height);
|
||||||
|
|
||||||
|
const text = f.append('xhtml:div').style('height', '100%').style('width', '100%');
|
||||||
|
|
||||||
|
text
|
||||||
|
.append('div')
|
||||||
|
.style('text-align', 'center')
|
||||||
|
.style('vertical-align', 'middle')
|
||||||
|
.html(renderKatex(content, configApi.getConfig()));
|
||||||
|
|
||||||
|
byTspan(content, s, x, y, width, height, textAttrs, conf);
|
||||||
|
_setTextAttrs(text, textAttrs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any} toText
|
* @param {any} toText
|
||||||
* @param {any} fromTextAttrsDict
|
* @param {any} fromTextAttrsDict
|
||||||
@@ -942,7 +1015,8 @@ const _drawTextCandidateFunc = (function () {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return function (conf) {
|
return function (conf, hasKatex = false) {
|
||||||
|
if (hasKatex) return byKatex;
|
||||||
return conf.textPlacement === 'fo' ? byFo : conf.textPlacement === 'old' ? byText : byTspan;
|
return conf.textPlacement === 'fo' ? byFo : conf.textPlacement === 'old' ? byText : byTspan;
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
Reference in New Issue
Block a user