【发布时间】:2021-04-10 20:26:27
【问题描述】:
TLDR
我想转换下面的代码
<nav id="TableOfContents">
<ul>
<li><a href="#js">JS</a>
<ul>
<li><a href="#h3-1">H3-1</a></li>
<li><a href="#h3-2">H3-2</a></li>
</ul>
</li>
<li><a href="#python">Python</a>
<ul>
<li><a href="#h3-1-1">H3-1</a></li>
<li><a href="#h3-2-1">H3-2</a></li>
</ul>
</li>
</ul>
</nav>
使用 Javascript(或 Hugo)转为以下 JSON 格式
{"t": "root", "d": 0, "v": "", "c": [
{"t": "h", "d": 1, "v": "<a href=\"#js\">JS</a>", "c": [
{"t": "h", "d": 2, "v": "<a href=\"#h3-1\">H3-1</a>"},
{"t": "h", "d": 2, "v": "<a href=\"#h3-2\">H3-2</a>"}
]
},
{"t": "h", "d": 1, "v": "<a href=\"#python\">Python</a>", "c": [
{"t": "h", "d": 2, "v": "<a href=\"#h3-1-1\">H3-1</a>"},
{"t": "h", "d": 2, "v": "<a href=\"#h3-2-1\">H3-2</a>"}
]
}
]}
以上只是一个例子,你提供的函数应该可以毫无问题地将任何类似的结构转换为 JSON 字符串(其实唯一的要求就是不要使用硬编码完成)
你可以像下面这样输出你的代码
<!DOCTYPE html>
<html>
<head>
<script>
(()=>{
var input_text = `<nav id="TableOfContents">...`;
var output = my_func(input_text);
console.log(output); /* expected result: {"t": "root", "d": 0, "v": "", "c": [ ... */
}
)()
function my_func(text) {
/* ... */
}
</script>
</head>
</html>
长篇大论
我想做什么?
我想在Hugo 上使用思维导图(markmap,markmap-github)并将其应用于文章(single.html)作为目录
Hugo 已经通过TableOfContents提供了目录
即我的.md
## JS
### H3-1
### H3-2
## Python
### H3-1
### H3-2
然后{{ .TableOfContents }}会输出
<nav id="TableOfContents">
<ul>
<li><a href="#js">JS</a>
<ul>
<li><a href="#h3-1">H3-1</a></li>
<li><a href="#h3-2">H3-2</a></li>
</ul>
</li>
<li><a href="#python">Python</a>
<ul>
<li><a href="#h3-1-1">H3-1</a></li>
<li><a href="#h3-2-1">H3-2</a></li>
</ul>
</li>
</ul>
</nav>
但是,如果我使用markmap,那么我必须向它提供一个 JSON 字符串,如下所示,
{"t": "root", "d": 0, "v": "", "c": [
{"t": "h", "d": 1, "v": "<a href=\"#js\">JS</a>", "c": [
{"t": "h", "d": 2, "v": "<a href=\"#h3-1\">H3-1</a>"},
{"t": "h", "d": 2, "v": "<a href=\"#h3-2\">H3-2</a>"}
]
},
{"t": "h", "d": 1, "v": "<a href=\"#python\">Python</a>", "c": [
{"t": "h", "d": 2, "v": "<a href=\"#h3-1-1\">H3-1</a>"},
{"t": "h", "d": 2, "v": "<a href=\"#h3-2-1\">H3-2</a>"}
]
}
]}
我做了什么?
我试图只用 Hugo 的 functions 来做,但失败了 (逻辑上可行,但语法上难以实现)
所以我把希望寄托在了javascript上,但一直以来,我的js都是找别人的代码来修改,而 这个例子对我来说是一个全新的例子;启动不了(坦白说,我是个JS外行)。
以下是我用Python实现的。
from bs4 import BeautifulSoup, Tag
from typing import Union
import os
from pathlib import Path
import json
def main():
data = """<nav id="TableOfContents">
<ul>
<li><a href="#js">JS</a>
<ul>
<li><a href="#h3-1">H3-1</a></li>
<li><a href="#h3-2">H3-2</a></li>
</ul>
</li>
<li><a href="#python">Python</a>
<ul>
<li><a href="#h3-1-1">H3-1</a></li>
<li><a href="#h3-2-1">H3-2</a></li>
</ul>
</li>
</ul>
</nav>"""
soup = BeautifulSoup(data, "lxml")
sub_list = []
cur_level = 0
dict_tree = dict(t='root', d=cur_level, v='', c=sub_list)
root_ul: Tag = soup.find('ul')
toc2json(root_ul, cur_level + 1, sub_list) # <-- core
toc_json: str = json.dumps(dict_tree)
print(toc_json)
output_file = Path('test.temp.html')
create_markmap_html(toc_json, output_file)
os.startfile(output_file)
def toc2json(tag: Tag, cur_level: int, sub_list):
for li in tag:
if not isinstance(li, Tag):
continue
a: Tag = li.find('a')
ul: Union[Tag, None] = li.find('ul')
if ul:
new_sub_list = []
toc2json(ul, cur_level + 1, new_sub_list)
cur_obj = dict(t='h', d=cur_level, v=str(a), c=new_sub_list)
else:
cur_obj = dict(t='h', d=cur_level, v=str(a))
sub_list.append(cur_obj)
def create_markmap_html(json_string: str, output_file: Path):
import jinja2
markmap_template = jinja2.Template("""
<!DOCTYPE html>
<html lang=en>
<head>
<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/markmap-view@0.2.0"></script>
<style>
.mindmap {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<main>
<svg id="mindmap-test" class="mindmap"></svg>
</main>
<script>
(
(e, json_data)=>{
const{Markmap:r}=e();
window.mm=r.create("svg#mindmap-test",null,json_data);
}
)(
()=>window.markmap,
{{ input_json }}
);
</script>
</body>
</html>
""")
html_string = markmap_template.render(dict(input_json=json_string))
with open(output_file, 'w', encoding='utf-8') as f:
f.write(html_string)
if __name__ == '__main__':
main()
为了这个小小的努力,请帮帮我。
【问题讨论】:
-
你想把python代码转换成js代码吗?
-
嗨@DaniilLoban,如果你能做到这一点会很好,但这不是必需的。最低要求是能够将无序列表转换为 JSON。 (不一定限于JS,任何前端技术(即使有些浏览器不支持也没关系)我可以接受)
-
那么我们的输入(变量或文件)和我们期望的输出(我猜你想得到一个文件) *.json 或 *.htm ? JSON的无序列表 - 你能解释一下吗?另外你想如何在本地计算机上手动运行这个转换器作为 python 脚本或在网络上?
-
设置一个变量作为输入(硬编码也可以)就可以了,输出可以使用字符串。一般情况下,输入是由 Hugo 提供的,然后在用户打开页面时自动执行代码,但这无所谓;您可以使用硬编码编写输入。如果您对这个成品感兴趣,并且将来有人帮我写这个答案,我会发布一个成品页面供您参考:)
标签: javascript python json hugo