@anyblock/remark-any-block 1.0.0-beta1 → 1.0.0-beta11
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 +1 -1
- package/anyblock.ts +66 -83
- package/dist/remark-any-block.cjs +51216 -0
- package/dist/remark-any-block.js +51194 -0
- package/index.ts +5 -1
- package/package.json +45 -36
- package/vite.config.ts +3 -3
package/README.md
CHANGED
package/anyblock.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
// import { unified } from 'unified';
|
|
2
|
-
// import remarkParse from 'remark-parse';
|
|
3
|
-
// import remarkRehype from 'remark-rehype';
|
|
4
|
-
// import rehypeStringify from 'rehype-stringify';
|
|
5
|
-
|
|
6
|
-
// import { remove } from "unist-util-remove"
|
|
7
1
|
import { Plugin } from "unified"
|
|
8
2
|
import { Root, RootContent, Paragraph, Text, Code, Html } from "mdast"
|
|
9
3
|
import type { VFile } from "vfile"
|
|
@@ -60,15 +54,18 @@ export interface AnyBlockOptions {
|
|
|
60
54
|
*/
|
|
61
55
|
function matchAbHeader(node: RootContent): string | null {
|
|
62
56
|
if (node.type !== "paragraph") return null;
|
|
57
|
+
|
|
63
58
|
const text = (node.children as RootContent[])
|
|
64
59
|
.map((c) => (c.type === "text" ? (c as Text).value : ""))
|
|
65
60
|
.join("");
|
|
66
|
-
const
|
|
67
|
-
|
|
61
|
+
const match = text.match(ABReg.reg_header_noprefix);
|
|
62
|
+
if (!match || !match.length) return null
|
|
63
|
+
|
|
64
|
+
return match[5]
|
|
68
65
|
}
|
|
69
66
|
|
|
70
67
|
/**
|
|
71
|
-
* 检测 `:::container`
|
|
68
|
+
* 检测 `:::container` 首段落
|
|
72
69
|
* 匹配时返回 `{flag, type}`
|
|
73
70
|
*/
|
|
74
71
|
function matchContainerStart(node: RootContent):
|
|
@@ -85,9 +82,9 @@ function matchContainerStart(node: RootContent):
|
|
|
85
82
|
}
|
|
86
83
|
|
|
87
84
|
/**
|
|
88
|
-
*
|
|
85
|
+
* 检测 `:::container` 尾段落
|
|
89
86
|
*/
|
|
90
|
-
function
|
|
87
|
+
function matchContainerEnd(node: RootContent, flag: string): boolean {
|
|
91
88
|
if (node.type !== "paragraph") return false;
|
|
92
89
|
const text = (node.children as RootContent[])
|
|
93
90
|
.map((c) => (c.type === "text" ? (c as Text).value : ""))
|
|
@@ -97,7 +94,7 @@ function isContainerEnd(node: RootContent, flag: string): boolean {
|
|
|
97
94
|
}
|
|
98
95
|
|
|
99
96
|
/**
|
|
100
|
-
* 将一组 mdast
|
|
97
|
+
* 将一组 mdast 节点反序列化为 markdown 格式
|
|
101
98
|
*/
|
|
102
99
|
function nodesToMarkdown(nodes: RootContent[]): string {
|
|
103
100
|
return toMarkdown(
|
|
@@ -113,85 +110,73 @@ function nodesToMarkdown(nodes: RootContent[]): string {
|
|
|
113
110
|
* - `:::type ... :::`
|
|
114
111
|
*/
|
|
115
112
|
export const remark_anyblock_to_codeblock: Plugin<[Partial<AnyBlockOptions>?], Root> =
|
|
116
|
-
(_options = {}) =>
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
113
|
+
(_options = {}) => (tree) =>
|
|
114
|
+
{
|
|
115
|
+
const children = [...tree.children] as RootContent[];
|
|
116
|
+
|
|
117
|
+
const out: RootContent[] = [];
|
|
118
|
+
for (let i = 0; i < children.length; i++) {
|
|
119
|
+
const node = children[i];
|
|
120
|
+
|
|
121
|
+
// step1. 检测 `[]` 语法
|
|
122
|
+
const header = matchAbHeader(node);
|
|
123
|
+
if (header) {
|
|
124
|
+
const node_next = children[i+1];
|
|
125
|
+
if (
|
|
126
|
+
node_next.type === "list" ||
|
|
127
|
+
node_next.type === "heading" ||
|
|
128
|
+
node_next.type === "code" ||
|
|
129
|
+
node_next.type === "blockquote" ||
|
|
130
|
+
node_next.type === "table"
|
|
131
|
+
) {
|
|
132
|
+
const codeValue = `[${header}]\n${nodesToMarkdown([node_next])}`;
|
|
133
|
+
out.push({
|
|
134
|
+
type: "code",
|
|
135
|
+
lang: "anyblock",
|
|
136
|
+
value: codeValue,
|
|
137
|
+
data: { markup: "[]" },
|
|
138
|
+
} as Code);
|
|
139
|
+
i++; continue;
|
|
140
|
+
} else {}
|
|
141
|
+
}
|
|
123
142
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
n.type === "list" ||
|
|
133
|
-
n.type === "heading" ||
|
|
134
|
-
n.type === "code" ||
|
|
135
|
-
n.type === "blockquote" ||
|
|
136
|
-
n.type === "table"
|
|
137
|
-
) {
|
|
138
|
-
body.push(n);
|
|
139
|
-
continue;
|
|
140
|
-
}
|
|
141
|
-
// stop when first non-matching block is hit
|
|
143
|
+
// step2. 检测 `:::` 语法
|
|
144
|
+
const container = matchContainerStart(node);
|
|
145
|
+
if (container) {
|
|
146
|
+
const body: RootContent[] = [];
|
|
147
|
+
let j = i + 1;
|
|
148
|
+
for (; j < children.length; j++) {
|
|
149
|
+
const n = children[j];
|
|
150
|
+
if (matchContainerEnd(n, container.flag)) {
|
|
142
151
|
break;
|
|
143
152
|
}
|
|
144
|
-
|
|
145
|
-
const codeValue = `[${header}]\n${nodesToMarkdown(body)}`;
|
|
146
|
-
out.push({
|
|
147
|
-
type: "code",
|
|
148
|
-
lang: "AnyBlock",
|
|
149
|
-
value: codeValue,
|
|
150
|
-
data: { markup: "[]" },
|
|
151
|
-
} as Code);
|
|
152
|
-
i = j - 1;
|
|
153
|
-
continue;
|
|
154
|
-
}
|
|
153
|
+
body.push(n);
|
|
155
154
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
body.push(n);
|
|
168
|
-
}
|
|
169
|
-
if (j < children.length) {
|
|
170
|
-
const codeValue = `[${container.type}]\n${nodesToMarkdown(body)}`;
|
|
171
|
-
out.push({
|
|
172
|
-
type: "code",
|
|
173
|
-
lang: "AnyBlock",
|
|
174
|
-
value: codeValue,
|
|
175
|
-
data: { markup: container.flag },
|
|
176
|
-
} as Code);
|
|
177
|
-
i = j; // skip closing line
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
155
|
+
if (j < children.length) {
|
|
156
|
+
const codeValue = `[${container.type}]\n${nodesToMarkdown(body)}`;
|
|
157
|
+
out.push({
|
|
158
|
+
type: "code",
|
|
159
|
+
lang: "anyblock",
|
|
160
|
+
value: codeValue,
|
|
161
|
+
data: { markup: container.flag },
|
|
162
|
+
} as Code);
|
|
163
|
+
i = j; continue;
|
|
180
164
|
}
|
|
181
|
-
|
|
182
|
-
// default passthrough
|
|
183
|
-
out.push(node);
|
|
184
165
|
}
|
|
185
166
|
|
|
186
|
-
|
|
167
|
+
// step3. 不处理的节点,保持不变
|
|
168
|
+
out.push(node)
|
|
187
169
|
}
|
|
188
170
|
|
|
171
|
+
(tree as Root).children = out;
|
|
172
|
+
}
|
|
173
|
+
|
|
189
174
|
// 渲染 anyblock 代码块
|
|
190
|
-
const remark_anyblock_render_codeblock = () => {
|
|
175
|
+
export const remark_anyblock_render_codeblock = () => {
|
|
176
|
+
if (typeof document == "undefined") return
|
|
191
177
|
return (tree: Root, _file: VFile) => {
|
|
192
178
|
visit(tree, "code", (node: Code, index: number|undefined, parent: any|undefined) => { // 遍历所有的 code 类型节点
|
|
193
|
-
|
|
194
|
-
if (node.lang != "anyblock") return
|
|
179
|
+
if (node.lang.toLowerCase() != "anyblock") return
|
|
195
180
|
if (!parent || !index) return
|
|
196
181
|
|
|
197
182
|
const lines = node.value.split("\n")
|
|
@@ -208,8 +193,6 @@ const remark_anyblock_render_codeblock = () => {
|
|
|
208
193
|
ABConvertManager.autoABConvert(el, header, content, markup.startsWith(":::") ? "mdit" : "");
|
|
209
194
|
|
|
210
195
|
// new node
|
|
211
|
-
console.log("\nanyblock codeblock transformer visit2:", header, 'c==', content)
|
|
212
|
-
console.log("\nanyblock codeblock transformer visit3:", el.outerHTML, el)
|
|
213
196
|
const new_node: Html = {
|
|
214
197
|
type: 'html',
|
|
215
198
|
value: el.outerHTML,
|
|
@@ -222,7 +205,7 @@ const remark_anyblock_render_codeblock = () => {
|
|
|
222
205
|
|
|
223
206
|
{
|
|
224
207
|
// 定义环境条件
|
|
225
|
-
ABCSetting.env = "
|
|
208
|
+
ABCSetting.env = "remark";
|
|
226
209
|
|
|
227
210
|
// 定义默认渲染行为 // [!code hl] risk 同步适配异步,可能会存在问题
|
|
228
211
|
ABConvertManager.getInstance().redefine_renderMarkdown((markdown: string, el: HTMLElement):void => {
|
|
@@ -250,7 +233,7 @@ export const transformer_anyblock: QuartzTransformerPlugin = (/*options: any*/)
|
|
|
250
233
|
name: "AnyBlock",
|
|
251
234
|
markdownPlugins(_ctx: BuildCtx) {
|
|
252
235
|
return [
|
|
253
|
-
|
|
236
|
+
remark_anyblock_to_codeblock,
|
|
254
237
|
remark_anyblock_render_codeblock, // last
|
|
255
238
|
]
|
|
256
239
|
},
|