@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.
package/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # Any Block Converter
2
+
3
+ ## 使用
4
+
5
+ ### 使用流程
6
+
7
+ ```typescript
8
+ // 转换器模块
9
+ import { ABConvertManager } from "ABConvertManager"
10
+ // 加载所有转换器 (都是可选的)
11
+ // (当然,如果A转换器依赖B转换器,那么你导入A必然导入B)
12
+ import {} from "./ABConverter/converter/abc_text"
13
+ import {} from "./ABConverter/converter/abc_code"
14
+ import {} from "./ABConverter/converter/abc_list"
15
+ import {} from "./ABConverter/converter/abc_table"
16
+ import {} from "./ABConverter/converter/abc_deco"
17
+ import {} from "./ABConverter/converter/abc_ex"
18
+ import {} from "./ABConverter/converter/abc_echarts"
19
+ import {} from "./ABConverter/converter/abc_mermaid" // 可选建议:非 min 环境下 7.1MB
20
+ import {} from "./ABConverter/converter/abc_markmap" // 可选建议:1.3MB
21
+
22
+ // 先注册默认渲染行为
23
+ ABConvertManager.getInstance().redefine_renderMarkdown((markdown: string, el: HTMLElement): void => {...})
24
+
25
+ // 然后按下面这个原型正常使用即可
26
+ ABConvertManager.autoABConvert(el:HTMLDivElement, header:string, content:string): HTMLElement
27
+ ```
28
+
29
+ ### Obsidian 回调函数设置
30
+
31
+ ```typescript
32
+ ABConvertManager.getInstance().redefine_renderMarkdown((markdown: string, el: HTMLElement, ctx?: any): void => {
33
+ /**
34
+ * Renders markdown string to an HTML element.
35
+ * @deprecated - use {@link MarkdownRenderer.render}
36
+ *
37
+ * 原定义:
38
+ * @param markdown - The markdown source code
39
+ * @param el - The element to append to
40
+ * @param sourcePath - The normalized path of this markdown file, used to resolve relative internal links
41
+ * 此标记文件的规范化路径,用于解析相对内部链接
42
+ * TODO 我可能知道为什么重渲染图片会出现bug了,原因应该在这里
43
+ * @param component - A parent component to manage the lifecycle of the rendered child components, if any
44
+ * 一个父组件,用于管理呈现的子组件(如果有的话)的生命周期
45
+ * @public
46
+ *
47
+ */
48
+ //MarkdownRenderer.renderMarkdown(markdown, el, "", new MarkdownRenderChild(el))
49
+
50
+ const mdrc: MarkdownRenderChild = new MarkdownRenderChild(el);
51
+ if (ctx) ctx.addChild(mdrc);
52
+ else if (ABCSetting.global_ctx) ABCSetting.global_ctx.addChild(mdrc);
53
+ /**
54
+ * Renders markdown string to an HTML element.
55
+ * @param app - A reference to the app object
56
+ * @param markdown - The markdown source code
57
+ * @param el - The element to append to
58
+ * @param sourcePath - The normalized path of this markdown file, used to resolve relative internal links
59
+ * @param component - A parent component to manage the lifecycle of the rendered child components.
60
+ * @public
61
+ */
62
+ // @ts-ignore 新接口,但旧接口似乎不支持
63
+ MarkdownRenderer.render(app, markdown, el, app.workspace.activeLeaf?.view?.file?.path??"", mdrc)
64
+ })
65
+ ```
66
+
67
+ ### MarkdownIt 回调函数设置
68
+
69
+ ```typescript
70
+ ABConvertManager.getInstance().redefine_renderMarkdown((markdown: string, el: HTMLElement): void => {
71
+ const result: string = md.render(markdown)
72
+ const el_child = document.createElement("div"); el.appendChild(el_child); el_child.innerHTML = result;
73
+ })
74
+ ```
75
+
76
+ ## 开发/设计/架构补充
77
+
78
+ (先读src下的README)
79
+
80
+ ### 架构
81
+
82
+ 也叫 Any Block Render (text->html时)
83
+
84
+ 因为模块化内置了很多 Converter (text->text等),所以整体叫 Any Block Converter
85
+
86
+ ### 该模块设计不应依赖于Ob插件
87
+
88
+ **这个模块以前是依赖Ob插件接口的**,后来才改成可复用的 AnyBlock 转化器。
89
+
90
+ 为了高复用 (不仅仅在Ob插件上使用,还在md-it的等其他地方使用)
91
+
92
+ 1. 要与选择器解耦
93
+ 2. 相较于V2版本,为了不依赖于Ob底层,使用一个回调函数去替代 `MarkdownRenderer` 相关函数
94
+
95
+ ### 程序缩写
96
+
97
+ - `AnyBlock`:`AB`
98
+ - `AnyBlockConvert`:`ABC`
99
+ - `AnyBlockSelector`:`ABS`
100
+ - `AnyBlockRender`:`ABR`
101
+
102
+ ### 格式转换所在位置
103
+
104
+ > ##### 思考
105
+
106
+ 例如我有两个格式:格式1(有格式1解析渲染、将自己格式转别人格式,将别人格式转自己格式)、格式2(有格式2解析渲染、将别人的格式转自己式、将自己的格式转别人的格式)。问题在于:1转2和2转1的功能,应该怎么设置?
107
+
108
+ 1. 都放在两个文件中
109
+ - 优点:两模块互相独立
110
+ - 缺点:造成冗余,而非复用 —— 只写一遍,两个程序都用一份
111
+ 2. 只放格式2
112
+ - 思想:该方式视为先有的格式1后有的格式2扩展。或视为格式1是更通用更广泛的格式,格式2属于扩展格式,自然由格式2负责12的互转
113
+ - 采用:abc_mermaid、abc_markmap 与 list 的转换属于此类,后期增加的新格式也属于此类
114
+ 3. 1转2由2实现,2转1则由1实现
115
+ - 思想:该方式视为1和2是两个商业软件,他们乐意于让对方的用户转移到自己这边,但并不乐意让自己的用户转到对方那边
116
+ - 采用:list、table 的互相转换属于此类
117
+
118
+ > ##### 总结
119
+
120
+ 按格式的通用性分为:(越往上通用级别越高)
121
+
122
+ 1. str
123
+ 2. html
124
+ 3. list、table
125
+ 4. mermaid、mindmap、……以后的扩展
126
+
127
+ > ##### 策略
128
+
129
+ 1. 低通用级格式要实现对高通用级格式的互转
130
+ 2. 同通用级则实现其他同通用级格式对自己格式的转化
131
+
132
+ ## todo
133
+
134
+ 1. 别名模块,AnyBlockConverter 不应该最后强制输出html。最后补md的行为是ob的别名模块做的,不应该由abc来快
135
+ 2. PlantUML,感觉很多东西都好用多了
136
+
137
+ ## bug
138
+
139
+ ### mdit环境下onclick需要内嵌才生效
140
+
141
+ ```typescript
142
+ // TODO,onClick代码在mdit环境下按钮点击失效。测试代码如下
143
+ const btn = document.createElement("button"); table.appendChild(btn); btn.textContent = "测试按钮1";
144
+ btn.onclick = () => { console.log("btn.onclick") }
145
+ const btndiv = document.createElement("div"); table.appendChild(btndiv);
146
+ btndiv.innerHTML = `<button onclick="console.log('Button was clicked!')">测试按钮2</button>`
147
+ // 发现mdit环境下,按钮1无法正常按动,而按钮2可以
148
+ // 原因应该是:因为mdit环境下的document对象是jdsom创建的,假的。这个dom对象后面会被转化为html_str,onclick的信息就丢失了
149
+ ```
150
+
151
+ ### mermaid找不到DOMPurify
152
+
153
+ mermaid的一个未定义行为的报错 (不过修复了这个之后又说BBox找不到了)
154
+
155
+ ```typescript
156
+ // 见:https://github.com/kkomelin/isomorphic-dompurify
157
+
158
+ // 用
159
+ import DOMPurify from "isomorphic-dompurify"
160
+ // 替换
161
+ import DOMPurify from "dompurify"
162
+ ```
@@ -0,0 +1,158 @@
1
+ /**
2
+ * AB转换器的抽象基类
3
+ *
4
+ * @detail
5
+ * 被所有权:ABConvertManager
6
+ */
7
+
8
+ import { ABConvertManager } from "../ABConvertManager"
9
+ import type { List_C2ListItem } from "./abc_c2list"
10
+ import type { List_ListItem } from "./abc_list"
11
+ import type { List_TableItem } from "./abc_table"
12
+
13
+ /**
14
+ * ab处理器子接口 - 类型声明
15
+ *
16
+ * @detail
17
+ * TODO 待增加一个list和json专用格式
18
+ */
19
+ export enum ABConvert_IOEnum {
20
+ text = "string", // string
21
+ el = "HTMLElement", // HTMLElement
22
+ // el_text = "string", // string
23
+ json = "json_string", // string
24
+ list_stream = "array", // object
25
+ c2list_stream = "array2", // object
26
+ }
27
+ export type ABConvert_IOType =
28
+ string| // text/el_text
29
+ HTMLElement| // html元素
30
+ void| // TODO void是旧的别名系统,以后要删掉
31
+ List_ListItem| // 多叉树 数据流
32
+ List_C2ListItem| // 二层树 数据流
33
+ List_TableItem| // 表格用 数据流
34
+ Object // json对象
35
+
36
+ /**
37
+ * AB转换器的抽象基类
38
+ *
39
+ * @detail
40
+ * 被所有权:ABConvertManager
41
+ */
42
+ export class ABConvert {
43
+
44
+ /** --------------------------------- 静态参数 -------------------------- */
45
+
46
+ id: string // 唯一标识(当不填match时也会作为匹配项)
47
+ name: string // 处理器名字
48
+ match: RegExp|string // 处理器匹配正则(不填则为id,而不是name!name可以被翻译或是重复的)如果填写了且为正则类型,不会显示在下拉
49
+ default: string|null // 下拉选择的默认规则,不填的话:非正则默认为id,有正则则为空
50
+ detail: string // 处理器描述
51
+ process_alias: string // 组装,如果不为空串则会覆盖process方法,但扔需要给process一个空实现
52
+ process_param: ABConvert_IOEnum|null
53
+ process_return: ABConvert_IOEnum|null
54
+ process: (el:HTMLDivElement, header:string, content:ABConvert_IOType, ctx?:any)=> ABConvert_IOType // html->html的处理器不需要用到content参数
55
+ is_disable: boolean = false // 是否禁用,默认false
56
+ register_from: string = "内置" // 自带、其他插件、面板设置,如果是其他插件,则需要提供插件的名称(不知道能不能自动识别)
57
+ // TODO,这个词条应该修改成 “作者名” 鼓励二次开发
58
+
59
+ /** --------------------------------- 动态参数 -------------------------- */
60
+
61
+ // 非注册项:
62
+ // ~~is_inner:这个不可设置,用来区分是内部还是外部给的~~
63
+ is_enable: boolean = false // 加载后能禁用这个项
64
+
65
+ /** --------------------------------- 特殊函数 -------------------------- */
66
+
67
+ /// 构造 + 容器管理
68
+ public static factory(process: ABConvert_SpecSimp| ABConvert_SpecUser): ABConvert {
69
+ let ret: ABConvert = new ABConvert(process)
70
+ ABConvertManager.getInstance().list_abConvert.push(ret)
71
+ return ret
72
+ }
73
+
74
+ /// 构造函数
75
+ /// TODO 应该将注册修改为创建实例,因为里面有动态参数
76
+ /// TODO id冲突提醒
77
+ /// TODO 别名功能删除,由独立的别名模块负责,不集成在转换器里
78
+ /// (优点是转换器功能保持单一性和可复用性,二是允许无代码设置别名,缺点是二次开发者需要多注册一次或独立设置转换器)
79
+ constructor(process: ABConvert_SpecSimp| ABConvert_SpecUser) {
80
+ // 注册版
81
+ if ('process' in process) {
82
+ this.constructor_simp(process)
83
+ }
84
+ // 别名版
85
+ else {
86
+ this.constructor_user(process)
87
+ }
88
+ }
89
+
90
+ constructor_simp(sim: ABConvert_SpecSimp) {
91
+ this.id = sim.id
92
+ this.name = sim.name
93
+ this.match = sim.match??sim.id
94
+ this.default = sim.default??(!sim.match||typeof(sim.match)=="string")?sim.id:null
95
+ this.detail = sim.detail??""
96
+ this.process_alias = sim.process_alias??""
97
+ this.process_param = sim.process_param??null
98
+ this.process_return = sim.process_return??null
99
+ this.process = sim.process
100
+ this.is_disable = false
101
+ this.register_from = "内置"
102
+ }
103
+
104
+ constructor_user(sim: ABConvert_SpecUser) {
105
+ this.id = sim.id
106
+ this.name = sim.name
107
+ this.match = /^\//.test(sim.match)?RegExp(sim.match):sim.match
108
+ this.default = null
109
+ this.detail = ""
110
+ this.process_alias = sim.process_alias
111
+ this.process_param = null
112
+ this.process_return = null
113
+ this.process = ()=>{}
114
+ this.is_disable = false
115
+ this.register_from = "用户"
116
+ }
117
+
118
+ /// 析构函数
119
+ destructor() {
120
+ // ABConvertManager.getInstance().list_abConvert.remove(this) // 旧,remove接口是ob定义的
121
+
122
+ const index = ABConvertManager.getInstance().list_abConvert.indexOf(this)
123
+ if (index > -1) {
124
+ ABConvertManager.getInstance().list_abConvert.splice(index, 1)
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * ab转换器的注册参数类型
131
+ */
132
+ export interface ABConvert_SpecSimp{
133
+ id: string // 唯一标识(当不填match时也会作为匹配项)
134
+ name: string // 处理器名字
135
+ match?: RegExp|string // 处理器匹配正则(不填则为id,而不是name!name可以被翻译或是重复的)如果填写了且为正则类型,不会显示在下拉框中
136
+ default?: string|null // 下拉选择的默认规则,不填的话:非正则默认为id,有正则则为空
137
+ detail?: string // 处理器描述
138
+ process_alias?: string // 组装,如果不为空串则会覆盖process方法,但扔需要给process一个空实现
139
+ process_param?: ABConvert_IOEnum
140
+ process_return?: ABConvert_IOEnum
141
+ process: (el:HTMLDivElement, header:string, content:ABConvert_IOType, ctx?:any)=> ABConvert_IOType
142
+ // 处理器。话说第三个参数以前是只能接收string的,现在应该改为:上一次修改后的结果
143
+ }
144
+
145
+ /**
146
+ * ab转换器的注册参数类型 - 别名版
147
+ * TODO:后续删除,别名系统用另一个模块来处理
148
+ *
149
+ * @detail
150
+ * 使用 ab处理器接口 - 用户版(都是字符串存储)
151
+ * 特点:不能注册process(无法存储在txt中),只能注册别名
152
+ */
153
+ export interface ABConvert_SpecUser{
154
+ id:string
155
+ name:string
156
+ match:string
157
+ process_alias:string
158
+ }
@@ -0,0 +1,40 @@
1
+ /// 这个估计本来是想做可排序可筛选的数据表格
2
+ import {ABConvertManager} from "../ABConvertManager"
3
+ /*
4
+ import type {List_TableInfo} from "src/ab_converter/converter/listProcess"
5
+
6
+ export let list_tableInfo:List_TableInfo;
7
+ export let modeT:boolean;
8
+ export let prev_line: number;
9
+
10
+ let table:HTMLDivElement;
11
+ // 表格数据 组装成表格
12
+ table.addClasses(["ab-table", "ab-data-table"])
13
+ if (modeT) table.setAttribute("modeT", "true")
14
+ let thead
15
+ if(list_tableInfo[0].content.indexOf("< ")==0){ // 判断是否有表头
16
+ thead = table.createEl("thead")
17
+ list_tableInfo[0].content=list_tableInfo[0].content.replace(/^\<\s/,"")
18
+ }
19
+ const tbody = table.createEl("tbody")
20
+ for (let index_line=0; index_line<prev_line+1; index_line++){ // 遍历表格行,创建tr……
21
+ let is_head
22
+ let tr
23
+ if (index_line==0 && thead){ // 判断是否第一行&&是否有表头
24
+ tr = thead.createEl("tr")
25
+ is_head = true
26
+ }
27
+ else{
28
+ is_head = false
29
+ tr = tbody.createEl("tr")
30
+ }
31
+ for (let item of list_tableInfo){ // 遍历表格列,创建td
32
+ if (item.tableLine!=index_line) continue
33
+ // md版
34
+ let td = tr.createEl(is_head?"th":"td", {
35
+ attr:{"rowspan": item.tableRow}
36
+ })
37
+ ABConvertManager.getInstance().m_renderMarkdownFn(item.content, td)
38
+ }
39
+ }
40
+ */