@anyblock/any-block-core 3.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,119 @@
1
+ /**
2
+ * AB转换器 - markmap相关
3
+ *
4
+ * (可选) 参考:在Ob插件中增加1.3MB
5
+ *
6
+ * 使用注意项:本文件搜索 `markmap渲染`,然后根据该注释在你的主代码中添加一部分代码
7
+ *
8
+ * 模块化难点,这个插件极难模块化
9
+ * 1. 内容不全体现在局部,局部渲染问题
10
+ * markmap是那种一个markdown文件渲染一个mindmap的类型,和我要局部渲染的不同。
11
+ * 调用api得到的html_str是包含 `<html>`、`<script>` 的,没法作用在局部div上。
12
+ * 然后我就想找一个有局部渲染mindmap的去参考:
13
+ * https://github.com/aleen42/gitbook-mindmaps/blob/master/src/mindmaps.js
14
+ * https://github.com/deiv/markdown-it-markmap/blob/master/src/index.js
15
+ * https://github.com/NeroBlackstone/markdown-it-mindmap/blob/main/index.js
16
+ * 2. 渲染时间若交由每个mindmap块处理一次则会出现重复渲染及慢的问题。这里提供了一个btn手动渲染,而要自动渲染:
17
+ * - 在Ob环境,需要在文章渲染完时出一个钩子调用 `Markmap.create`
18
+ * - 在VuePress-Mdit环境,没有真正的document元素,而打开文件的钩子在mdit里面又没有,可能需要要vuepress插件解决
19
+ */
20
+
21
+ import DOMPurify from "dompurify"
22
+ import { ABConvert_IOEnum, ABConvert } from "./ABConvert"
23
+ import { ABCSetting } from "../ABSetting"
24
+ import { markmap_event } from "../ABConvertEvent";
25
+
26
+ /**
27
+ * 生成一个随机id
28
+ *
29
+ * @detail 因为mermaid渲染块时需要一个id,不然多个mermaid块会发生冲突
30
+ */
31
+ function getID(length=16){
32
+ return Number(Math.random().toString().substr(3,length) + Date.now()).toString(36);
33
+ }
34
+
35
+ // markmap about
36
+ import { Transformer, builtInPlugins } from 'markmap-lib'
37
+ import type { C2ListItem } from "./abc_c2list";
38
+ import { abc_title2listdata } from "./abc_list";
39
+ const transformer = new Transformer();
40
+ //import { Markmap, loadCSS, loadJS } from 'markmap-view'
41
+
42
+ const _abc_list2mindmap = ABConvert.factory({
43
+ id: "list2markmap",
44
+ name: "列表到脑图 (markmap)",
45
+ process_param: ABConvert_IOEnum.text,
46
+ process_return: ABConvert_IOEnum.el,
47
+ process: (el, header, content: string): HTMLElement=>{
48
+ list2markmap(content, el)
49
+ markmap_event(el)
50
+ // setTimeout(()=>{abConvertEvent(el)}, 500);
51
+ return el
52
+ }
53
+ })
54
+
55
+ function list2markmap(markdown: string, div: HTMLDivElement) {
56
+ // markdown解析 (markmap-lib)
57
+ const { root, features } = transformer.transform(markdown.trim()); // 1. transform Markdown
58
+ const assets = transformer.getUsedAssets(features); // 2. get assets (option1)
59
+
60
+ // 渲染
61
+ // 1. 四选一。纯动态/手动渲染 (优缺点见abc_mermaid的相似方法)
62
+ // ob 选用
63
+ if (ABCSetting.env.startsWith("obsidian")) {
64
+ // 1. 新Ob使用,现在Ob的刷新按钮统一放在了外面
65
+ let height_adapt = 30 + markdown.split("\n").length*15; // 1. 仅大致估算px: 30 + (0~50)行 * 15 = [30~780]。2. 如果要准确估计,得自己解析一遍,麻烦。3. 并且后面会有个事件覆盖掉这个大致高度,所以这里不重要。4. 另外采用"偏小"策略,视觉效果好一些
66
+ if (height_adapt>1000) height_adapt = 1000;
67
+ const id = Math.random().toString(36).substring(2);
68
+ const svg_div = document.createElement("div"); div.appendChild(svg_div); svg_div.classList.add("ab-markmap-div"); svg_div.id = "ab-markmap-div-"+id
69
+ const html_str = `<svg class="ab-markmap-svg" id="ab-markmap-${id}" data-json='${JSON.stringify(root)}' style="height:${height_adapt}px"></svg>` // TODO 似乎是这里导致了`'`符号的异常
70
+ svg_div.innerHTML = DOMPurify.sanitize(html_str, {
71
+ USE_PROFILES: { svg: true }
72
+ })
73
+ }
74
+ // 2. 四选一。这里不渲,交给上一层让上一层渲 (优缺点见abc_mermaid的相似方法)
75
+ // 当前mdit (vuepress、app) 使用
76
+ else {
77
+ div.classList.add("ab-raw")
78
+ div.innerHTML = DOMPurify.sanitize(`<div class="ab-raw-data" type-data="markmap" content-data='${markdown}'></div>`)
79
+ }
80
+ // 1.2. 四选一。纯动态/手动渲染 (优缺点见abc_mermaid的相似方法)
81
+ // 旧Ob使用
82
+ {
83
+ // const svg_btn = document.createElement("button"); div.appendChild(svg_btn); svg_btn.textContent = "ChickMe ReRender Markmap";
84
+ // svg_btn.setAttribute("style", "background-color: argb(255, 125, 125, 0.5)");
85
+ // svg_btn.setAttribute("onclick", `
86
+ // console.log("markmap chick");
87
+ // let script_el = document.querySelector('script[script-id="ab-markmap-script"]');
88
+ // if (script_el) script_el.remove();
89
+ // script_el = document.createElement('script'); document.head.appendChild(script_el);
90
+ // script_el.type = "module";
91
+ // script_el.setAttribute("script-id", "ab-markmap-script");
92
+ // script_el.textContent = \`
93
+ // import { Markmap, } from 'https://jspm.dev/markmap-view';
94
+ // const mindmaps = document.querySelectorAll('.ab-markmap-svg');
95
+ // for(const mindmap of mindmaps) {
96
+ // mindmap.innerHTML = "";
97
+ // Markmap.create(mindmap,null,JSON.parse(mindmap.getAttribute('data-json')));
98
+ // }\``);
99
+ }
100
+ // 3. 四选一。自己渲 (优缺点见abc_mermaid的相似方法)
101
+ // npm mindmap-view 方法
102
+ {
103
+ // // if (assets.styles) loadCSS(assets.styles);
104
+ // // if (assets.scripts) loadJS(assets.scripts, { getMarkmap: () => {} });
105
+ // const mindmaps = document.querySelectorAll('.ab-markmap-svg'); // 注意一下这里的选择器
106
+ // for(const mindmap of mindmaps) {
107
+ // mindmap.innerHTML = "";
108
+ // const datajson: string|null = mindmap.getAttribute('data-json')
109
+ // if (datajson === null) { console.error("ab-markmap-svg without data-json") }
110
+ // g_markmap = Markmap.create(mindmap as SVGElement, undefined, JSON.parse(datajson as string));
111
+ // };
112
+ }
113
+ // 4. 四选一。这里给环境渲染 (优缺点见abc_mermaid的相似方法)
114
+ {
115
+ // ...
116
+ }
117
+
118
+ return div
119
+ }
@@ -0,0 +1,161 @@
1
+ /**
2
+ * AB转换器 - 仿 markdown-it-container 功能
3
+ */
4
+
5
+ import {ABConvert_IOEnum, ABConvert, type ABConvert_SpecSimp} from "./ABConvert"
6
+ import {ABConvertManager} from "../ABConvertManager"
7
+ import {C2ListProcess, type List_C2ListItem} from "./abc_c2list"
8
+ import {ABCSetting, ABReg} from "../ABSetting"
9
+
10
+ /// 按mdit-tabs的标准转化为二列列表数据
11
+ export function mditTabs2listdata(content:string, reg: RegExp): List_C2ListItem {
12
+ const list_line = content.split("\n")
13
+ let content_item: string = ""
14
+ const list_c2listItem: List_C2ListItem = []
15
+ for (let line_index=0; line_index<list_line.length; line_index++) {
16
+ const line_content = list_line[line_index]
17
+ const line_match = line_content.match(reg)
18
+ if (line_match) {
19
+ add_current_content()
20
+ list_c2listItem.push({
21
+ content: line_match[1].trim(),
22
+ level: 0
23
+ })
24
+ continue
25
+ }
26
+ else {
27
+ content_item += line_content + "\n"
28
+ }
29
+ }
30
+ add_current_content()
31
+
32
+ return list_c2listItem
33
+
34
+ function add_current_content() { // 刷新写入缓存的尾调用
35
+ if (content_item.trim() == "") return
36
+ list_c2listItem.push({
37
+ content: content_item,
38
+ level: 1
39
+ })
40
+ content_item = ""
41
+ }
42
+ }
43
+
44
+ const abc_mditTabs = ABConvert.factory({
45
+ id: "mditTabs",
46
+ name: "mdit标签页",
47
+ process_param: ABConvert_IOEnum.text,
48
+ process_return: ABConvert_IOEnum.el,
49
+ process: (el, header, content: string): HTMLElement=>{
50
+ const c2listdata: List_C2ListItem = mditTabs2listdata(content, /^@tab(.*)$/)
51
+ C2ListProcess.c2data2tab(c2listdata, el, false)
52
+ return el
53
+ }
54
+ })
55
+
56
+ const _abc_mditDemo = ABConvert.factory({
57
+ id: "mditDemo",
58
+ name: "mdit展示对比",
59
+ process_param: ABConvert_IOEnum.text,
60
+ process_return: ABConvert_IOEnum.el,
61
+ process: (el, header, content: string): HTMLElement=>{
62
+ const newContent = `@tab show\n${content}\n@tab mdSource\n~~~~~md\n${content}\n~~~~~`
63
+ abc_mditTabs.process(el, header, newContent)
64
+ return el
65
+ }
66
+ })
67
+
68
+ const _abc_mditABDemo = ABConvert.factory({
69
+ id: "mditABDemo",
70
+ name: "AnyBlock专用展示对比",
71
+ process_param: ABConvert_IOEnum.text,
72
+ process_return: ABConvert_IOEnum.el,
73
+ process: (el, header, content: string): HTMLElement=>{
74
+ // 无论哪个版本都有一个bug:
75
+ // 如果内部包含 mermaid/mermaid markmap/markmap 这三个图,会渲染失败或位置错误
76
+
77
+ // 二选一,markdown-it-tab 版本
78
+ if (ABCSetting.env == "markdown-it") {
79
+ ABConvertManager.getInstance().m_renderMarkdownFn(`::::: tabs
80
+
81
+ @tab show
82
+
83
+ ${content}
84
+
85
+ @tab withoutPlugin
86
+
87
+ (noPlugin)${content.trimStart()}
88
+
89
+ @tab mdSource
90
+
91
+ ~~~~~md
92
+ ${content}
93
+ ~~~~~
94
+
95
+ :::::`, el)
96
+ return el
97
+ }
98
+ // 二选一,anyblock 版本
99
+ else {
100
+ const newContent = `@tab show\n${content}\n@tab withoutPlugin\n(noPlugin)${content.trimStart()}\n@tab mdSource\n~~~~~md\n${content}\n~~~~~`
101
+ abc_mditTabs.process(el, header, newContent)
102
+ return el
103
+ }
104
+ }
105
+ })
106
+
107
+ /**
108
+ * 总结分栏方式:
109
+ * 1. 根据标签分栏 (手动分栏)
110
+ * 2. 指定分栏个数 (自动分栏)
111
+ */
112
+ const _abc_midt_col = ABConvert.factory({
113
+ id: "mditCol",
114
+ name: "mdit分栏",
115
+ process_param: ABConvert_IOEnum.text,
116
+ process_return: ABConvert_IOEnum.el,
117
+ process: (el, header, content: string): HTMLElement=>{
118
+ const c2listdata: List_C2ListItem = mditTabs2listdata(content, /^@col(.*)$/) // /^@[a-zA-Z]* (.*)$/
119
+ C2ListProcess.c2data2items(c2listdata, el)
120
+ el.querySelector("div")?.classList.add("ab-col")
121
+ return el
122
+ }
123
+ })
124
+
125
+ const _abc_midt_card = ABConvert.factory({
126
+ id: "mditCard",
127
+ name: "mdit卡片",
128
+ process_param: ABConvert_IOEnum.text,
129
+ process_return: ABConvert_IOEnum.el,
130
+ process: (el, header, content: string): HTMLElement=>{
131
+ const c2listdata: List_C2ListItem = mditTabs2listdata(content, /^@card(.*)$/) // /^@[a-zA-Z]* (.*)$/
132
+ C2ListProcess.c2data2items(c2listdata, el)
133
+ el.querySelector("div")?.classList.add("ab-card")
134
+ el.querySelector("div")?.classList.add("ab-lay-vfall")
135
+ return el
136
+ }
137
+ })
138
+
139
+ const _abc_midt_chat = ABConvert.factory({
140
+ id: "mditChat",
141
+ name: "mdit对话",
142
+ detail: "显示渲染对话,需要配合 obsidian-view-chat-qq 插件使用",
143
+ process_param: ABConvert_IOEnum.text,
144
+ process_return: ABConvert_IOEnum.text,
145
+ process: (el, header, content: string): string=>{
146
+ const content_list = content.split('\n')
147
+ let newContent = ''
148
+ for(let i=0; i<content_list.length; i++) {
149
+ const line = content_list[i]
150
+ if (/^@chat(.*)$/.test(line)) {
151
+ const match = line.match(/^@chat(.*)$/)
152
+ if (match && match[1]) {
153
+ newContent += '\n' + match[1] + ':\n'
154
+ continue
155
+ }
156
+ }
157
+ newContent += line + '\n'
158
+ }
159
+ return newContent
160
+ }
161
+ })
@@ -0,0 +1,343 @@
1
+ /**
2
+ * AB转换器 - mermaid相关
3
+ *
4
+ * (可选) 参考:在Ob插件中增加7.1MB
5
+ *
6
+ * 使用注意项:在ob/mdit中的写法不同,本文件搜索render_mermaidText函数。里面有三种策略。ob推荐策略1,mdit推荐策略3
7
+ */
8
+
9
+ import DOMPurify from "dompurify"
10
+ import { ABConvert_IOEnum, ABConvert } from "./ABConvert"
11
+ import { ListProcess, type List_ListItem } from "./abc_list"
12
+ import { ABCSetting } from "../ABSetting"
13
+
14
+ /**
15
+ * 生成一个随机id
16
+ *
17
+ * @detail 因为mermaid渲染块时需要一个id,不然多个mermaid块会发生冲突
18
+ */
19
+ function getID(length=16){
20
+ return Number(Math.random().toString().substr(3,length) + Date.now()).toString(36);
21
+ }
22
+
23
+ // 纯组合,后续用别名模块替代
24
+ const abc_title2mindmap = ABConvert.factory({
25
+ id: "title2mindmap",
26
+ name: "标题到脑图",
27
+ process_param: ABConvert_IOEnum.text,
28
+ process_return: ABConvert_IOEnum.el,
29
+ process: async (el, header, content: string): Promise<HTMLElement>=>{
30
+ const data = ListProcess.title2data(content) as List_ListItem
31
+ const el2 = await data2mindmap(data, el)
32
+ return el2
33
+ }
34
+ })
35
+
36
+ // 纯组合,后续用别名模块替代
37
+ const abc_list2mindmap = ABConvert.factory({
38
+ id: "list2mindmap",
39
+ name: "列表转mermaid思维导图",
40
+ process_param: ABConvert_IOEnum.text,
41
+ process_return: ABConvert_IOEnum.el,
42
+ process: async (el, header, content: string): Promise<HTMLElement>=>{
43
+ const data = ListProcess.list2data(content) as List_ListItem
44
+ const el2 = await data2mindmap(data, el)
45
+ return el2
46
+ }
47
+ })
48
+
49
+ const abc_list2mermaid = ABConvert.factory({
50
+ id: "list2mermaid",
51
+ name: "列表转mermaid流程图",
52
+ match: /^list2mermaid(\((.*)\))?$/,
53
+ process_param: ABConvert_IOEnum.text,
54
+ process_return: ABConvert_IOEnum.el,
55
+ process: (el, header, content: string): HTMLElement=>{
56
+ let matchs = header.match(/^list2mermaid(\((.*)\))?$/)
57
+ if (!matchs) { console.error('no match', matchs); return el }
58
+ let mermaid_head = "graph LR"
59
+ if (matchs[2]) mermaid_head = matchs[2]
60
+
61
+ const list_itemInfo = ListProcess.list2data(content)
62
+ const mermaidText = mermaid_head + '\n' + data2mermaidText(list_itemInfo)
63
+ render_mermaidText(mermaidText, el)
64
+ return el
65
+ }
66
+ })
67
+
68
+ const abc_list2mermaidText = ABConvert.factory({
69
+ id: "list2mermaidText",
70
+ name: "列表转mermaid文本",
71
+ match: /^list2mermaidText(\((.*)\))?$/,
72
+ detail: "列表转mermaid文本",
73
+ process_param: ABConvert_IOEnum.text,
74
+ process_return: ABConvert_IOEnum.text,
75
+ process: (el, header, content: string): string=>{
76
+ let matchs = header.match(/^list2mermaidText(\((.*)\))?$/)
77
+ if (!matchs) { console.error('no match', matchs); return 'error, no match' }
78
+ let mermaid_head = "graph LR"
79
+ if (matchs[2]) mermaid_head = matchs[2]
80
+
81
+ const list_itemInfo = ListProcess.list2data(content)
82
+ const mermaidText = mermaid_head + '\n' + data2mermaidText(list_itemInfo)
83
+ return mermaidText
84
+ }
85
+ })
86
+
87
+ const abc_list2mehrmaid = ABConvert.factory({
88
+ id: "list2mehrmaidText",
89
+ name: "列表转mehrmaid文本",
90
+ match: /^list2mehrmaidText(\((.*)\))?$/,
91
+ detail: "需要配合mehrmaid插件和code(mehrmaid)使用,或使用别名简化",
92
+ process_param: ABConvert_IOEnum.text,
93
+ process_return: ABConvert_IOEnum.text,
94
+ process: (el, header, content: string): string=>{
95
+ let matchs = header.match(/^list2mehrmaidText(\((.*)\))?$/)
96
+ if (!matchs) { console.error('no match', matchs); return 'error, no match' }
97
+ let mermaid_head = "flowchart LR"
98
+ if (matchs[2]) mermaid_head = matchs[2]
99
+
100
+ const list_itemInfo = ListProcess.list2data(content)
101
+ const mermaidText = mermaid_head + '\n' + data2mehrmaidText(list_itemInfo)
102
+ return mermaidText
103
+ }
104
+ })
105
+
106
+ const abc_mermaid = ABConvert.factory({
107
+ id: "mermaid-with",
108
+ name: "新mermaid",
109
+ match: /^mermaid(\((.*)\))?$/,
110
+ default: "mermaid(graph TB)",
111
+ detail: "由于需要兼容脑图,这里会使用插件内置的最新版mermaid",
112
+ process_param: ABConvert_IOEnum.text,
113
+ process_return: ABConvert_IOEnum.el,
114
+ process: async (el, header, content: string): Promise<HTMLElement>=>{
115
+ let matchs = header.match(/^mermaid(\((.*)\))?$/)
116
+ if (!matchs) return el
117
+ if (matchs[2]) content = matchs[2] + '\n' + content
118
+ const el2 = render_mermaidText(content, el)
119
+ return el2
120
+ }
121
+ })
122
+
123
+ // ----------- list and mermaid ------------
124
+
125
+ /** 列表数据转mermaid流程图
126
+ * ~~@bug 旧版bug(未内置mermaid)会闪一下~~
127
+ * 然后注意一下mermaid的(项)不能有空格,或非法字符。空格我处理掉了,字符我先不管。算了,还是不处理空格吧
128
+ *
129
+ * 注意:此处不添加mermaid头,要自己加
130
+ */
131
+ function data2mermaidText(
132
+ list_itemInfo: List_ListItem
133
+ ){
134
+ const html_mode = false // @todo 暂时没有设置来切换这个开关
135
+
136
+ let list_line_content:string[] = []
137
+ // let list_line_content:string[] = html_mode?['<pre class="mermaid">', "graph LR"]:["```mermaid", "graph LR"]
138
+ let prev_line_content = ""
139
+ let prev_level = 999
140
+ for (let i=0; i<list_itemInfo.length; i++){
141
+ if (list_itemInfo[i].level>prev_level){ // 向右正常加箭头
142
+ prev_line_content = prev_line_content+" --> "+list_itemInfo[i].content//.replace(/ /g, "_")
143
+ } else { // 换行,并……
144
+ list_line_content.push(prev_line_content)
145
+ prev_line_content = ""
146
+
147
+ for (let j=i; j>=0; j--){ // 回退到上一个比自己大的
148
+ if(list_itemInfo[j].level<list_itemInfo[i].level) {
149
+ prev_line_content = list_itemInfo[j].content//.replace(/ /g, "_")
150
+ break
151
+ }
152
+ }
153
+ if (prev_line_content) prev_line_content=prev_line_content+" --> " // 如果有比自己大的
154
+ prev_line_content=prev_line_content+list_itemInfo[i].content//.replace(/ /g, "_")
155
+ }
156
+ prev_level = list_itemInfo[i].level
157
+ }
158
+ list_line_content.push(prev_line_content)
159
+ // list_line_content.push(html_mode?"</pre>":"```")
160
+
161
+ let text = list_line_content.join("\n")
162
+ return text
163
+ }
164
+
165
+ /** 列表数据转mermaid流程图
166
+ * ~~@bug 旧版bug(未内置mermaid)会闪一下~~
167
+ * 然后注意一下mermaid的(项)不能有空格,或非法字符。空格我处理掉了,字符我先不管。算了,还是不处理空格吧
168
+ */
169
+ function data2mehrmaidText(
170
+ list_itemInfo: List_ListItem
171
+ ){
172
+ // mehrmaid较于mermaid的补充1:映射表。先将内容全部映射成数字(TODO 需要处理重名)
173
+ const mehrmaidMap = []
174
+ for (let i=0; i<list_itemInfo.length; i++) {
175
+ mehrmaidMap[i] = list_itemInfo[i].content
176
+ list_itemInfo[i].content = i.toString()
177
+ }
178
+
179
+ const html_mode = false // @todo 暂时没有设置来切换这个开关
180
+
181
+ let list_line_content:string[] = []
182
+ // let list_line_content:string[] = html_mode?['<pre class="mermaid">', "graph LR"]:["```mermaid", "graph LR"]
183
+ let prev_line_content = ""
184
+ let prev_level = 999
185
+ for (let i=0; i<list_itemInfo.length; i++) {
186
+ if (list_itemInfo[i].level>prev_level){ // 向右正常加箭头
187
+ prev_line_content = prev_line_content+" --> "+list_itemInfo[i].content//.replace(/ /g, "_")
188
+ } else { // 换行,并……
189
+ list_line_content.push(prev_line_content)
190
+ prev_line_content = ""
191
+
192
+ for (let j=i; j>=0; j--){ // 回退到上一个比自己大的
193
+ if(list_itemInfo[j].level<list_itemInfo[i].level) {
194
+ prev_line_content = list_itemInfo[j].content//.replace(/ /g, "_")
195
+ break
196
+ }
197
+ }
198
+ if (prev_line_content) prev_line_content=prev_line_content+" --> " // 如果有比自己大的
199
+ prev_line_content=prev_line_content+list_itemInfo[i].content//.replace(/ /g, "_")
200
+ }
201
+ prev_level = list_itemInfo[i].level
202
+ }
203
+ list_line_content.push(prev_line_content)
204
+ // list_line_content.push(html_mode?"</pre>":"```")
205
+
206
+ let text = list_line_content.join("\n")
207
+
208
+ // mehrmaid较于mermaid的补充2:映射回来
209
+ text += '\n\n'
210
+ for (let i=0; i<mehrmaidMap.length; i++) {
211
+ text += `${i}(("${mehrmaidMap[i]}"))\n`
212
+ }
213
+
214
+ return text
215
+ }
216
+
217
+ /** 列表数据转mermaid思维导图 */
218
+ async function data2mindmap(
219
+ list_itemInfo: List_ListItem,
220
+ div: HTMLDivElement
221
+ ){
222
+ // const subEl = document.createElement("div"); div.appendChild(subEl);
223
+ // subEl.textContent = "Disable, please replace `markmap` command"; subEl.setAttribute("style", "border: solid 2px red; padding: 10px;");
224
+ // return div
225
+
226
+ let list_newcontent:string[] = []
227
+ for (let item of list_itemInfo){
228
+ // 等级转缩进,以及"\n" 转化 <br/>
229
+ let str_indent = ""
230
+ for(let i=0; i<item.level; i++) str_indent+= " "
231
+ list_newcontent.push(str_indent+item.content.replace("\n","<br/>"))
232
+ }
233
+ const mermaidText = "mindmap\n"+list_newcontent.join("\n")
234
+ return render_mermaidText(mermaidText, div)
235
+ }
236
+
237
+ // 通过mermaid块里的内容来渲染mermaid块
238
+ async function render_mermaidText(mermaidText: string, div: HTMLElement) {
239
+ // 0. 四选一。使用obsidian的loadMermaid引入依赖
240
+ // 优点:无需自带mermaid依赖
241
+ // full-ob和min-ob选用
242
+ // 调试: 在 obsidian 控制台输入 `mermaid` 或 `mermaid.mermaidAPI.render("a-46485456", `graph TB\na\nbbb`).then(result => console.log("---", result))`
243
+ if ((ABCSetting.env.startsWith("obsidian")) && ABCSetting.obsidian.mermaid) {
244
+ ABCSetting.obsidian.mermaid.then(async mermaid => {
245
+ const { svg } = await mermaid.render("ab-mermaid-"+getID(), mermaidText)
246
+ const div_mermaid = document.createElement('div'); div.appendChild(div_mermaid); div_mermaid.classList.add("mermaid"); // 使用 obsidian 主题
247
+ div_mermaid.innerHTML = svg
248
+ })
249
+ }
250
+ // 1. 四选一。自己渲
251
+ // 旧full-ob使用
252
+ // - 优点: 最快,无需通过二次转换
253
+ // - 缺点: abc模块要内置mermaid,旧版插件使用是因为当时的obsidian内置的mermaid版本太老了
254
+ // - 选用:目前的ob环境中用是最好。vuepress-mdit中则有另一个bug,DOMPurify丢失:https://github.com/mermaid-js/mermaid/issues/5204
255
+ // - 补充:废弃函数:mermaid.mermaidAPI.renderAsync("ab-mermaid-"+getID(), mermaidText, (svgCode:string)=>{ div.innerHTML = svgCode })
256
+ // if (ABCSetting.env == "obsidian" || ABCSetting.env == "obsidian-pro") {
257
+ // await init_mermaid()
258
+ // const { svg } = await mermaid?.render("ab-mermaid-"+getID(), mermaidText)
259
+ // div.innerHTML = svg
260
+ // }
261
+ // 2. 四选一。在这里给环境渲
262
+ // - 优点:abc模块无需重复内置mermaid
263
+ // - 缺点:在ob里中,一个mermaid块的变更会导致所在页面内的所有mermaid一起变更,在mdit里似乎id会有问题
264
+ // 旧min-ob使用
265
+ // else if (ABCSetting.env == "obsidian-min") {
266
+ // ABConvertManager.getInstance().m_renderMarkdownFn("```mermaid\n"+mermaidText+"\n```", div)
267
+ // }
268
+ // 3. 四选一。这里不渲,交给上一层让上一层渲
269
+ // 当前mdit选用
270
+ // - 优点:abc模块无需重复内置mermaid。对于mdit,能避免输出格式必须为html
271
+ // - 缺点:这和ab的接口设计是冲突的,属于是取巧临时使用,后面要规范一下。另一方面,不知道为什么这种方案容易爆内存 (markmap那边也这样用也没事,就mermaid这边会)
272
+ // - 选用:mdit可以用这种,dev环境的最佳策略
273
+ else {
274
+ div.classList.add("ab-raw")
275
+ div.innerHTML = DOMPurify.sanitize(`<div class="ab-raw-data" type-data="mermaid" content-data='${mermaidText}'></div>`)
276
+ }
277
+ // 4. 四选一。纯动态/手动渲染
278
+ // - 优点:abc模块无需重复内置mermaid
279
+ // - 缺点:是不由ab转换的mermaid块自己不管,转换可能有延迟,还要手动触发
280
+ // - 选用:都可以用这种,虽然效果不太好,但省内存。方案3不知道为什么,会爆内存
281
+ {
282
+ // const div_btn = document.createElement("button"); div.appendChild(div_btn); div_btn.textContent = "ChickMe ReRender Mermaid";
283
+ // div_btn.setAttribute("style", "background-color: argb(255, 125, 125, 0.5)");
284
+ // div_btn.setAttribute("onclick", `
285
+ // console.log("mermaid chick");
286
+ // let script_el = document.querySelector('script[script-id="ab-mermaid-script"]');
287
+ // if (script_el) script_el.remove();
288
+ // script_el = document.createElement('script'); document.head.appendChild(script_el);
289
+ // script_el.type = "module";
290
+ // script_el.setAttribute("script-id", "ab-mermaid-script");
291
+ // script_el.textContent = \`
292
+ // import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
293
+ // mermaid.initialize({ startOnLoad: false });
294
+ // const el_mermaids = document.querySelectorAll('.ab-mermaid-raw');
295
+ // function getID(length=16){
296
+ // return Number(Math.random().toString().substr(3,length) + Date.now()).toString(36);
297
+ // }
298
+ // for(const el_mermaid of el_mermaids) {
299
+ // const { svg } = await mermaid.render("ab-mermaid-"+getID(), el_mermaid.textContent);
300
+ // el_mermaid.innerHTML = svg
301
+ // }
302
+ // \``);
303
+ // const pre_div = document.createElement("pre"); div.appendChild(pre_div); pre_div.classList.add("ab-mermaid-raw"); pre_div.textContent = mermaidText;
304
+ }
305
+
306
+ return div
307
+ }
308
+
309
+ /**
310
+ * mermaid依赖和初始化相关
311
+ *
312
+ * document依赖,不要根部执行
313
+ * 一是避免服务端渲染时jsdom创建document对象不及
314
+ * 二是动态引入,提升性能
315
+ *
316
+ * TODO 非条件编译,打包体积还是会变大
317
+ *
318
+ * @deprecated 使用 loadMermaid from obsidian 代替
319
+ */
320
+ /*async function init_mermaid () {
321
+ if (mermaid != null) return // 已经初始化过
322
+
323
+ // 二选一。mdit/min环境直接不执行这部分
324
+ if (ABCSetting.env.startsWith("obsidian")) return
325
+
326
+ // 二选一。这里是obsidian版本。
327
+ // 依赖和主题明暗检测也是ob才需要的
328
+ // const mermaid_str = 'mermaid' // 避免在此处形成包依赖,如果需要则要额外import来表示依赖该包
329
+ // const mindmap_str = '@mermaid-js/mermaid-mindmap'
330
+ const { default: mermaid_ } = await import('mermaid')
331
+ const { default: mindmap } = await import('@mermaid-js/mermaid-mindmap')
332
+
333
+ mermaid = mermaid_
334
+ const initialize = mermaid.registerExternalDiagrams([mindmap]) // 扩展mindmap功能
335
+ const isDarkTheme = document.body.classList.contains('theme-dark')
336
+ const theme = isDarkTheme ? 'dark' : 'light'
337
+ mermaid.initialize({
338
+ theme: theme
339
+ })
340
+ const mermaid_init = async () => {
341
+ await initialize;
342
+ }
343
+ }*/