Skip to content

Commit 512bf91

Browse files
committed
fix: encode markmap source as base64 to avoid being handled by other plugins
1 parent dc844b1 commit 512bf91

File tree

3 files changed

+44
-22
lines changed

3 files changed

+44
-22
lines changed

mkdocs_markmap/extension.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import base64
12
import logging
23
import re
34
from functools import partial
@@ -49,29 +50,31 @@ def run(self, lines: List[str]) -> List[str]:
4950
included_paths.append(path)
5051
try:
5152
with open(path, "r", encoding=self.encoding) as r:
52-
markmap: List[str] = r.readlines()
53-
53+
markmap = r.read()
54+
5455
except Exception as e:
5556
log.error("unable to include file {}. Ignoring statement. Error: {}".format(path, e))
5657
lines[loc] = INCLUDE_SYNTAX.sub("",line)
5758
break
5859

5960
line_split: List[str] = INCLUDE_SYNTAX.split(line)
61+
output: List[str] = []
6062
if len(markmap) == 0:
61-
markmap.append("")
63+
output.append("")
6264
else:
63-
markmap.insert(0, "```markmap")
64-
markmap.append("```")
65-
65+
output.append('<pre class="language-markmap"><code encoding="base64">')
66+
output.append(base64.b64encode(markmap.encode()).decode())
67+
output.append("</code></pre>")
68+
6669
if line_split[0].strip() != "":
67-
markmap.insert(0, line_split[0])
70+
output.insert(0, line_split[0])
6871

6972
if line_split[2].strip() != "":
70-
markmap.append(line_split[2])
73+
output.append(line_split[2])
7174

72-
lines = lines[:loc] + markmap + lines[loc+1:]
75+
lines = lines[:loc] + output + lines[loc+1:]
7376
break
74-
77+
7578
else:
7679
done = True
7780

mkdocs_markmap/plugin.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
import base64
12
import logging
23
from pathlib import Path
34
import re
45
from typing import Dict, Tuple
56

67
from bs4 import BeautifulSoup, ResultSet, Tag
7-
88
from mkdocs.config.base import Config, load_config
99
from mkdocs.config.config_options import Type as PluginType
1010
from mkdocs.plugins import BasePlugin
1111
from mkdocs.structure.pages import Page
12+
1213
from mkdocs_markmap.extension import MarkmapExtension
1314

1415
from .defaults import MARKMAP
@@ -116,7 +117,6 @@ def on_page_content(self, html: str, page: Page, **kwargs) -> str:
116117

117118
for index, markmap in enumerate(markmaps):
118119
markmap: Tag
119-
tag_id: str = f"markmap-{index}"
120120
pre: Tag
121121
code: Tag
122122
if markmap.name == "pre":
@@ -129,5 +129,9 @@ def on_page_content(self, html: str, page: Page, **kwargs) -> str:
129129
pre["class"] = pre.get("class", []) + ["mkdocs-markmap"]
130130
code.name = "markmap-data"
131131
code.attrs["hidden"] = "true"
132+
if not code.attrs.get("encoding"):
133+
# Encode content as base64 to avoid being handled by other plugins like KaTeX
134+
code.attrs["encoding"] = "base64"
135+
code.string = base64.b64encode(code.get_text().strip().encode()).decode()
132136

133137
return str(soup)

mkdocs_markmap/static_files/mkdocs-markmap.js

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,39 @@
99
function parseData(content) {
1010
const { root, frontmatter } = transformer.transform(content);
1111
let options = markmap.deriveOptions(frontmatter?.markmap);
12-
options = Object.assign({
13-
fitRatio: 0.85,
14-
}, options);
12+
options = Object.assign(
13+
{
14+
fitRatio: 0.85,
15+
},
16+
options
17+
);
1518
return { root, options };
1619
}
1720

1821
function resetMarkmap(m, el) {
1922
const { minX, maxX, minY, maxY } = m.state;
20-
const height = el.clientWidth * (maxX - minX) / (maxY - minY);
23+
const height = (el.clientWidth * (maxX - minX)) / (maxY - minY);
2124
el.style.height = height + "px";
2225
m.fit();
2326
}
2427

28+
function decodeBase64(encoded) {
29+
const binary = atob(encoded);
30+
const bytes = new Uint8Array(binary.length);
31+
for (let i = 0; i < bytes.length; i++) {
32+
bytes[i] = binary.charCodeAt(i);
33+
}
34+
return new TextDecoder().decode(bytes);
35+
}
36+
2537
function renderMarkmap(el) {
26-
let svg = el.querySelector('svg');
27-
if (svg) return;
28-
const content = el.textContent;
29-
el.innerHTML = '<svg>';
38+
const dataEl = el.querySelector("markmap-data");
39+
if (!dataEl) return;
40+
let content = el.textContent;
41+
if (dataEl.getAttribute("encoding") === "base64") {
42+
content = decodeBase64(content);
43+
}
44+
el.innerHTML = "<svg>";
3045
svg = el.firstChild;
3146
const { root, options } = parseData(content);
3247
const m = markmap.Markmap.create(svg, options, root);
@@ -39,15 +54,15 @@
3954
}
4055

4156
function updateMarkmaps(node) {
42-
for (const el of node.querySelectorAll('.mkdocs-markmap')) {
57+
for (const el of node.querySelectorAll(".mkdocs-markmap")) {
4358
renderMarkmap(el);
4459
}
4560
}
4661

4762
loading.then(() => {
4863
const observer = new MutationObserver((mutationList) => {
4964
for (const mutation of mutationList) {
50-
if (mutation.type === 'childList') {
65+
if (mutation.type === "childList") {
5166
for (const node of mutation.addedNodes) {
5267
updateMarkmaps(node);
5368
}

0 commit comments

Comments
 (0)