markdown-it-any-block 3.2.12 → 3.3.1

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/docs/README.md CHANGED
@@ -38,6 +38,7 @@ import { ABConvertManager } from "ABConvertManager"
38
38
  // 加载所有转换器 (都是可选的)
39
39
  // (当然,如果A转换器依赖B转换器,那么你导入A必然导入B)
40
40
  import {} from "./ABConverter/converter/abc_text"
41
+ import {} from "./ABConverter/converter/abc_code"
41
42
  import {} from "./ABConverter/converter/abc_list"
42
43
  import {} from "./ABConverter/converter/abc_table"
43
44
  import {} from "./ABConverter/converter/abc_deco"
package/index_mdit.ts CHANGED
@@ -53,6 +53,7 @@ import { ABCSetting, ABReg } from "../ABConverter/ABReg"
53
53
  // 加载所有转换器 (都是可选的)
54
54
  // (当然,如果A转换器依赖B转换器,那么你导入A必然导入B)
55
55
  import "../ABConverter/converter/abc_text"
56
+ import "../ABConverter/converter/abc_code"
56
57
  import "../ABConverter/converter/abc_list"
57
58
  import "../ABConverter/converter/abc_c2list"
58
59
  import "../ABConverter/converter/abc_table"
@@ -61,7 +62,7 @@ import "../ABConverter/converter/abc_deco"
61
62
  import "../ABConverter/converter/abc_ex"
62
63
  import "../ABConverter/converter/abc_mdit_container"
63
64
  import "../ABConverter/converter/abc_plantuml" // 可选建议:
64
- import "../ABConverter/converter/abc_mermaid.min" // 可选建议:非 min 环境下 7.1MB
65
+ import "../ABConverter/converter/abc_mermaid" // 可选建议:新版无额外依赖,旧版非 min 环境下 7.1MB
65
66
  import "../ABConverter/converter/abc_markmap" // 可选建议:1.3MB
66
67
 
67
68
  interface Options {
@@ -97,7 +98,7 @@ function abSelector_squareInline(md: MarkdownIt, options?: Partial<Options>): vo
97
98
 
98
99
  // (2) 匹配ab块范围
99
100
  // const prefix // ab块 - 前缀,TODO 前缀功能以后再做,暂不支持。不过ob的mc要处理前缀避免嵌套问题,感觉mdit的token应该不需要处理?
100
- let ab_blankLine_counter = 0 // ab块 - 连续空行计数器,为1则跳到下行,为2则结束ab块
101
+ let ab_blankLine_counter = 0 // ab块 - 连续空行计数器,为1则跳到下行,为2则结束ab块 (仅列表)
101
102
  const ab_startLine: number = state.line // ab块 - 起始行
102
103
  let ab_content: string = "" // ab块 - 内容
103
104
  state.line += 1
@@ -138,14 +139,14 @@ function abSelector_squareInline(md: MarkdownIt, options?: Partial<Options>): vo
138
139
  return
139
140
  }
140
141
 
141
- // 2. 连续空行结束
142
+ // 2. 空行 (如果是列表,且连续空行,则结束)
142
143
  if (text.trim() == "") {
143
- if (ab_blankLine_counter < 1) {
144
- ab_blankLine_counter++;
145
- ab_content += "\n"; state.line += 1; return findAbEnd()
144
+ if (ab_blockType == "list" && ab_blankLine_counter >= 1) {
145
+ return
146
146
  }
147
147
  else {
148
- return
148
+ ab_blankLine_counter++;
149
+ ab_content += "\n"; state.line += 1; return findAbEnd()
149
150
  }
150
151
  } else {
151
152
  ab_blankLine_counter = 0;
@@ -188,7 +189,7 @@ function abSelector_squareInline(md: MarkdownIt, options?: Partial<Options>): vo
188
189
  } else if (ab_blockType == "heading") { // TODO 这里需要跳过标题内的代码块 (python代码块的 `#` 会误截断)
189
190
  // heading和mdit类型 需要跳过代码块内的结束标志
190
191
  if (codeBlockFlag == '') {
191
- const match = text.match(/^((\s|>\s|-\s|\*\s|\+\s)*)(````*|~~~~*)(.*)/)
192
+ const match = text.match(ABReg.reg_code)
192
193
  if (match && match[3]) {
193
194
  codeBlockFlag = match[1]+match[3]
194
195
  ab_content += "\n" + text; state.line += 1; return findAbEnd()
@@ -267,96 +268,78 @@ function abSelector_container_vuepress(md: MarkdownIt, options?: Partial<Options
267
268
  * @param options 可选配置参数
268
269
  */
269
270
  function abSelector_container(md: MarkdownIt, options?: Partial<Options>): void {
270
- md.block.ruler.before('fence', 'AnyBlockMditContainer', (
271
- state, startLine, endLine, silent
272
- ): boolean => {
273
- const typeNames = ["mditABDemo"] // 在这里设置需要接管ab块类型,其余放行
274
- let start = state.bMarks[startLine];
275
- let max = state.eMarks[startLine];
276
-
277
- // 快速检查第一个字符,过滤掉非容器块
278
- if (state.src[start] !== ":") return false;
279
-
280
- let pos = start + 1;
281
-
282
- // 检查标记字符串的剩余部分
283
- while (pos <= max) {
284
- if (state.src[pos] !== ":") break;
285
- pos++;
271
+ md.block.ruler.before('fence', 'AnyBlockMditContainer', (state, startLine, endLine): boolean => {
272
+ // 黑白名单机制:白名单为空标注允许所有规则,黑名单会减少白名单的规则
273
+ const mdit_whitelist: string[] = ["mditABDemo"]
274
+ const mdit_blacklist: string[] = [
275
+ // "left", "center", "right", "justify", // https://mdit-plugins.github.io/zh/align.html
276
+ // "note", "warning", "tip", "info", // https://mdit-plugins.github.io/zh/container.html
277
+ // "demo", "md-demo", "codedemo",
278
+ // "tabs", // TODO: 可能是 `tabs#fruit` 这种形式的,应该改成手动循环判断,不能以这些开头
279
+ ]
280
+
281
+ // (1) 匹配 mdit 块头部
282
+ let mdit_header: string // 块 - 头部 (全行)
283
+ let mdit_match: RegExpMatchArray // 块 - 正则结果
284
+ {
285
+ state.line = startLine
286
+ const pos = state.bMarks[state.line] // 这行字符的初始位置
287
+ const max = state.eMarks[state.line] // 这行字符的结束位置
288
+ mdit_header = state.src.substring(pos, max) // 这一行的内容
289
+
290
+ mdit_match = mdit_header.match(ABReg.reg_mdit_head)
291
+ if (!mdit_match || !mdit_match.length) return false // 不匹配,则退出
292
+ if (mdit_whitelist.length && !mdit_whitelist.includes(mdit_match[4].split("|")[0].trim())) { // 检查白名单
293
+ return false;
294
+ }
295
+ if (mdit_blacklist.length && mdit_blacklist.includes(mdit_match[4].split("|")[0].trim())) { // 检查黑名单
296
+ return false;
297
+ }
286
298
  }
299
+ const mdit_flag:string = mdit_match[3]
300
+ const mdit_type:string = mdit_match[4]
287
301
 
288
- const markerCount = pos - start;
289
-
290
- // 需要至少3个冒号才视为有效标记
291
- if (markerCount < 3) return false;
302
+ // (2) 匹配 mdit 块范围
303
+ const mdit_startLine: number = state.line // mdit块 - 起始行
304
+ let mdit_content: string = "" // mdit块 - 内容 (不包含首尾 `:::`)
305
+ state.line += 1
306
+ findMditEnd()
307
+ const mdit_endLine: number = state.line // mdit块 - 结束行 (不包含)
292
308
 
293
- const markup = state.src.slice(start, pos);
294
- const ab_mdit_header = state.src.slice(pos, max);
309
+ // (3) 插入 mdit 块token
310
+ const token = state.push('fence', 'code', 0)
311
+ token.info = "AnyBlock"
312
+ token.content = `[${mdit_type}]\n${mdit_content}`
313
+ token.map = [mdit_startLine, mdit_endLine]
314
+ token.markup = mdit_flag;
315
+ token.nesting = 0;
316
+ return true
295
317
 
296
- // 检查是否在允许的类型列表中
297
- if (!typeNames.includes(ab_mdit_header.split("|")[0].trim())) return false;
318
+ // -------------------------- 子函数部分 ------------------------
298
319
 
299
- // 静默模式下直接返回验证成功
300
- if (silent) return true;
320
+ /// 找到ab块的结尾,迭代部分
321
+ function findMditEnd() {
322
+ const pos = state.bMarks[state.line] // 这行字符的初始位置
323
+ const max = state.eMarks[state.line] // 这行字符的结束位置
324
+ const text = state.src.substring(pos, max) // 这一行的内容
301
325
 
302
- const ab_startLine = startLine;
303
- let nextLine = startLine;
304
- let autoClosed = false;
326
+ // 1. 文章末行结束
327
+ if (state.line > endLine) {
328
+ state.line = endLine+1
329
+ return
330
+ }
305
331
 
306
- let ab_content = "";
332
+ // 2. 结束
333
+ if (text.trim() == mdit_flag) {
334
+ state.line += 1; return
335
+ }
307
336
 
308
- // 搜索块的结束标记
309
- while (
310
- // unclosed block should be auto closed by end of document.
311
- // also block seems to be auto closed by end of parent
312
- nextLine < endLine
313
- ) {
314
- nextLine++;
315
- start = state.bMarks[nextLine];
316
- max = state.eMarks[nextLine];
317
-
318
- if (start < max && state.sCount[nextLine] < state.blkIndent)
319
- // non-empty line with negative indent should stop the list:
320
- // - ```
321
- // test
322
- break;
323
- if (
324
- // match start
325
- state.src[start] === ":" &&
326
- // closing fence should be indented less than 4 spaces
327
- state.sCount[nextLine] - state.blkIndent < 4
328
- ) {
329
- // check rest of marker
330
- for (pos = start + 1; pos <= max; pos++)
331
- if (state.src[pos] !== ":") break;
332
-
333
- // closing code fence must be at least as long as the opening one
334
- if (pos - start >= markerCount) {
335
- // make sure tail has spaces only
336
- pos = state.skipSpaces(pos);
337
-
338
- if (pos >= max) {
339
- // found!
340
- autoClosed = true;
341
- break;
342
- }
343
-
344
- }
337
+ // 3. 未结束,继续递归寻找
338
+ else {
339
+ mdit_content += "\n" + text; state.line += 1; return findMditEnd()
345
340
  }
346
- ab_content += "\n" + state.src.substring(start, max);
347
341
  }
348
-
349
- state.line = nextLine + (autoClosed ? 1 : 0);
350
-
351
- const token = state.push('fence', 'code', 0)
352
- token.info = "AnyBlock"
353
- token.content = `[${ab_mdit_header}]\n${ab_content}`
354
- token.map = [ab_startLine, nextLine]
355
- token.markup = markup;
356
- token.nesting = 0;
357
-
358
- return true
359
- });
342
+ })
360
343
  }
361
344
 
362
345
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdown-it-any-block",
3
- "version": "3.2.12",
3
+ "version": "3.3.1",
4
4
  "description": "```typescript\r import { ABConvertManager } from \"ABConvertManager\"",
5
5
  "types": "@types/index_mdit.d.ts",
6
6
  "type": "module",
package/styles.css CHANGED
@@ -207,6 +207,7 @@ html[data-theme=dark] #app {
207
207
  padding-right: 20px;
208
208
  font-size: 0.9em;
209
209
  font-weight: bold;
210
+ cursor: pointer;
210
211
  }
211
212
  .ab-note .ab-tab-root .ab-tab-nav .ab-tab-nav-item[is_activate=false] {
212
213
  background-color: var(--ab-tab-root-bd-color);