Skip to content

Commit d2767b7

Browse files
committed
feat: improve markmap initialization with dynamic height calculation
1 parent 49a1764 commit d2767b7

File tree

4 files changed

+82
-28
lines changed

4 files changed

+82
-28
lines changed

README.md

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ Use mindmap in VS Code's built-in Markdown preview with markmap, seamlessly supp
3434
```markdown
3535
{% markmap %}
3636
---
37-
style: |
38-
#${id} {
39-
height: 300px; /* Equivalent to {% markmap 300px %} */
40-
}
4137
options:
4238
colorFreezeLevel: 2
4339
---
@@ -51,10 +47,6 @@ options:
5147
````markdown
5248
```markmap
5349
---
54-
style: |
55-
#${id} {
56-
height: 300px;
57-
}
5850
options:
5951
colorFreezeLevel: 2
6052
---
@@ -74,14 +66,15 @@ All frontmatter options are optional.
7466
- **`id`** : Used to define the ID of the `markmap-wrap` element.
7567
- If not specified, an unique ID will be generated.
7668

77-
- **`style`** : Used to define custom CSS styles for the mindmap.
78-
- The `${id}` placeholder can be used in the style field. During rendering, it will be replaced with the actual ID of the `markmap-wrap`, ensuring each mindmap element on the page has unique styles and behaviors.
79-
69+
- **`style`**: Defines custom CSS styles for the mindmap.
70+
- You can use the `${id}` placeholder in the `style` field, which will be replaced with the actual `markmap-wrap` ID during rendering. This ensures that each mindmap element on the page has unique styles and behaviors.
71+
> In previous versions, manually setting the mindmap height was necessary. However, the current version automatically calculates the height based on the content, making manual adjustment unnecessary. You can still use the `style` field to customize other aspects, such as fonts, colors, and more.
8072
- **`options`** : Correspond to the [`IMarkmapJSONOptions`](https://markmap.js.org/api/interfaces/markmap-view.IMarkmapJSONOptions.html) in the markmap project. For more details, please refer to [`jsonOptions`](https://markmap.js.org/docs/json-options#option-list).
8173

8274
#### Tag Options
8375

84-
You can also specify the height of the mindmap directly in the tag.
76+
You can also specify the height of the mindmap directly in the tag, by default it will be calculated based on the content.
77+
8578

8679
```markdown
8780
{% markmap 300px %}

README.zh_CN.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ options:
7474
- **`id`**:用于定义 `markmap-wrap` 元素的 ID。
7575
- 如果未指定,将生成一个唯一的 ID。
7676

77-
- **`style`**:用于定义思维导图的自定义 CSS 样式。
78-
- `${id}` 占位符可用于样式字段。在渲染时,它将被替换为 `markmap-wrap` 的实际 ID,确保页面上的每个思维导图元素具有唯一的样式和行为。
77+
- **`style`**:用于定义思维导图的自定义 CSS 样式。
78+
-`style` 字段中可以使用占位符 `${id}`,渲染时会被替换为实际的 `markmap-wrap` ID,以确保页面上的每个思维导图元素拥有独特的样式和行为。
79+
> 在旧版本中,需要手动设置思维导图的高度。但在当前版本中,高度会根据内容自动计算,因此无需手动调整。不过,你仍然可以使用 `style` 字段自定义字体、颜色等其他样式。
7980
8081
- **`options`**:对应 markmap 项目中的 [`IMarkmapJSONOptions`](https://markmap.js.org/api/interfaces/markmap-view.IMarkmapJSONOptions.html)。有关更多详细信息,请参考 [`jsonOptions`](https://markmap.js.org/docs/json-options#option-list)
8182

src/preview/markmap-init.ts

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,28 @@ import { debounce } from "radashi"
44

55
const resize = {
66
event: new Event('resize'),
7-
observer: new ResizeObserver((entries) =>
8-
entries.forEach((entry) => entry.target.dispatchEvent(resize.event))
9-
),
7+
observer: new ResizeObserver((entries) => {
8+
entries.forEach((entry) => {
9+
entry.target.dispatchEvent(resize.event)
10+
})
11+
}),
12+
listeners: new Map<Element, (event: Event) => void>(),
1013
observe: (el: Element, func: () => void) => {
11-
resize.observer.observe(el)
12-
el.addEventListener('resize', func)
14+
if (!(el instanceof Element) || typeof func !== "function") return
15+
16+
if (!resize.listeners.has(el)) {
17+
resize.listeners.set(el, func)
18+
el.addEventListener("resize", func)
19+
resize.observer.observe(el)
20+
}
1321
},
22+
destroyAll: () => {
23+
resize.listeners.forEach((func, el) => {
24+
el.removeEventListener("resize", func)
25+
resize.observer.unobserve(el)
26+
})
27+
resize.listeners.clear()
28+
}
1429
}
1530

1631
const toolbar = (markmapInstance: Markmap) => {
@@ -19,7 +34,14 @@ const toolbar = (markmapInstance: Markmap) => {
1934
return toolbar.el
2035
}
2136

22-
const init = () => {
37+
const updateMarkmapSize = (markmapInstance: Markmap) => {
38+
const svg: SVGSVGElement = markmapInstance.svg.node()
39+
const { y2: height } = markmapInstance.state.rect
40+
svg.style.height = `${height}`
41+
markmapInstance.fit()
42+
}
43+
44+
const render = () => {
2345
document.querySelectorAll<HTMLElement>('.markmap-wrap').forEach((wrapper) => {
2446
if (wrapper.children.length < 2) return
2547
const [root, jsonOptions] = Array.from(wrapper.children, (el) => {
@@ -32,15 +54,17 @@ const init = () => {
3254
})
3355
if (!root || !jsonOptions) return
3456
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
35-
const elements: Element[] = [svg]
57+
wrapper.replaceChildren(svg)
3658
const markmapInstance = Markmap.create(svg, deriveOptions(jsonOptions), root)
37-
if (wrapper.dataset?.toolbar !== 'false') elements.push(toolbar(markmapInstance))
38-
wrapper.replaceChildren(...elements)
39-
resize.observe(wrapper, debounce({ delay: 100 }, () => markmapInstance.fit()))
59+
if (wrapper.dataset?.toolbar !== 'false') wrapper.appendChild(toolbar(markmapInstance))
60+
resize.observe(wrapper, debounce({ delay: 100 }, () => updateMarkmapSize(markmapInstance)))
4061
})
4162
}
4263

43-
window.addEventListener('vscode.markdown.updateContent', init)
64+
window.addEventListener('vscode.markdown.updateContent', () => {
65+
resize.destroyAll()
66+
render()
67+
})
4468

45-
init()
69+
render()
4670

src/preview/style.css

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,55 @@
11
.markmap-wrap {
22
position: relative;
3-
height: 500px;
43
width: 100%;
4+
height: 100%;
5+
display: flex;
6+
justify-content: center;
57
}
68

79
.markmap-wrap>svg {
10+
display: block;
811
width: 100%;
9-
height: 100%;
12+
max-height: 100%;
13+
height: auto;
14+
min-height: 150px;
15+
margin: 0;
16+
padding: 0;
1017
}
1118

1219
.mm-toolbar {
1320
position: absolute;
1421
right: .5em;
1522
bottom: .5em;
23+
display: flex;
24+
align-items: center;
25+
border-width: 1px;
26+
border-radius: .25rem;
27+
border-style: solid;
28+
padding: .25rem;
29+
line-height: 1;
30+
}
31+
32+
.mm-toolbar-item {
33+
cursor: pointer;
34+
}
35+
36+
.mm-toolbar-brand.active,
37+
.mm-toolbar-brand:hover,
38+
.mm-toolbar-item.active,
39+
.mm-toolbar-item:hover {
40+
border-radius: 0.25rem;
41+
--un-bg-opacity: 1;
42+
background-color: rgb(228 228 231 / var(--un-bg-opacity));
43+
}
44+
.mm-toolbar-brand.active>*, .mm-toolbar-brand:hover>*, .mm-toolbar-item.active>*, .mm-toolbar-item:hover>* {
45+
--un-text-opacity: 1;
46+
color: rgb(39 39 42 / var(--un-text-opacity));
1647
}
48+
.mm-toolbar-brand.active, .mm-toolbar-item.active {
49+
--un-bg-opacity: 1;
50+
background-color: rgb(212 212 216 / var(--un-bg-opacity));
51+
}
52+
1753
/**
1854
Override of the default markmap styles.
1955
https://github.com/markmap/markmap/blob/master/packages/markmap-view/src/style.css

0 commit comments

Comments
 (0)