-
-
Notifications
You must be signed in to change notification settings - Fork 258
/
Copy pathuml.js
147 lines (135 loc) · 4.59 KB
/
uml.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Notes (as of Mermaid 8.7.0):
* - Gantt: width is always relative to the parent, if you have a small parent, the chart will be squashed.
* Can't help it.
* - Journey: Suffers from the same issues that Gantt does.
* - Pie: These charts have no default height or width. Good luck pinning them down to a reasonable size.
* - Git: The render portion is agnostic to the size of the parent element. But padding of the SVG is relative
* to the parent element. You will never find a happy size.
*/
/**
* Targets special code or div blocks and converts them to UML.
* @param {string} className is the name of the class to target.
* @return {void}
*/
export default async className => {
// Custom element to encapsulate Mermaid content.
class MermaidDiv extends HTMLElement {
/**
* Creates a special Mermaid div shadow DOM.
* Works around issues of shared IDs.
* @return {void}
*/
constructor() {
super()
// Create the Shadow DOM and attach style
const shadow = this.attachShadow({mode: "open"})
const style = document.createElement("style")
style.textContent = `
:host {
display: block;
line-height: initial;
font-size: 16px;
}
div.diagram {
margin: 0;
overflow: visible;
}`
shadow.appendChild(style)
}
}
if (typeof customElements.get("diagram-div") === "undefined") {
customElements.define("diagram-div", MermaidDiv)
}
const getFromCode = parent => {
// Handles <pre><code> text extraction.
let text = ""
for (let j = 0; j < parent.childNodes.length; j++) {
const subEl = parent.childNodes[j]
if (subEl.tagName.toLowerCase() === "code") {
for (let k = 0; k < subEl.childNodes.length; k++) {
const child = subEl.childNodes[k]
const whitespace = /^\s*$/
if (child.nodeName === "#text" && !(whitespace.test(child.nodeValue))) {
text = child.nodeValue
break
}
}
}
}
return text
}
// We use this to determine if we want the dark or light theme.
// This is specific for our MkDocs Material environment.
// You should load your configs based on your own environment's needs.
const defaultConfig = {
startOnLoad: false,
theme: "default",
flowchart: {
htmlLabels: false
},
er: {
useMaxWidth: false
},
sequence: {
useMaxWidth: false,
noteFontWeight: "14px",
actorFontSize: "14px",
messageFontSize: "16px"
}
}
mermaid.mermaidAPI.globalReset()
// Non Material themes should just use "default"
let scheme = null
try {
scheme = document.querySelector("[data-md-color-scheme]").getAttribute("data-md-color-scheme")
} catch (err) {
scheme = "default"
}
const config = (typeof mermaidConfig === "undefined") ?
defaultConfig :
mermaidConfig[scheme] || (mermaidConfig.default || defaultConfig)
mermaid.initialize(config)
// Find all of our Mermaid sources and render them.
const blocks = document.querySelectorAll(`pre.${className}, diagram-div`)
const surrogate = document.querySelector("html body")
for (let i = 0; i < blocks.length; i++) {
const block = blocks[i]
const parentEl = (block.tagName.toLowerCase() === "diagram-div") ?
block.shadowRoot.querySelector(`pre.${className}`) :
block
// Create a temporary element with the typeset and size we desire.
// Insert it at the end of our parent to render the SVG.
const temp = document.createElement("div")
temp.style.visibility = "hidden"
temp.style.display = "display"
temp.style.padding = "0"
temp.style.margin = "0"
temp.style.lineHeight = "initial"
temp.style.fontSize = "16px"
surrogate.appendChild(temp)
try {
const res = await mermaid.render(`_diagram_${i}`, getFromCode(parentEl), temp)
const content = res.svg
const fn = res.bindFunctions
const el = document.createElement("div")
el.className = className
el.innerHTML = content
if (fn) {
fn(el)
}
// Insert the render where we want it and remove the original text source.
// Mermaid will clean up the temporary element.
const shadow = document.createElement("diagram-div")
shadow.shadowRoot.appendChild(el)
block.parentNode.insertBefore(shadow, block)
parentEl.style.display = "none"
shadow.shadowRoot.appendChild(parentEl)
if (parentEl !== block) {
block.parentNode.removeChild(block)
}
} catch (err) {} // eslint-disable-line no-empty
if (surrogate.contains(temp)) {
surrogate.removeChild(temp)
}
}
}