1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
import {visit} from 'unist-util-visit';
import {inspect} from 'unist-util-inspect';
/*
Admonitionのツリー構造
{
type: 'containerDirective',
name: 'info',
attributes: {},
children: [
{
type: 'paragraph',
data: { directiveLabel: true },
children: [
{
type: 'text',
value: '#### info title もしHTML等が入ると(ここにaタグを入れると)',
position: [Object]
},
{
type: 'mdxJsxTextElement',
name: 'a',
attributes: [],
position: [Object],
data: [Object],
children: [Array]
},
{ type: 'text', value: 'このようにタイトル部が別々の要素として配列に入っている。', position: [Object] }
],
position: {
start: { line: 1347, column: 8, offset: 34053 },
end: { line: 1347, column: 55, offset: 34100 }
}
},
{ type: 'paragraph', children: [Array], position: [Object] },
...
],
...
}
*/
const plugin = (options) => {
const transformer = async (ast) => {
let newBeginningText = "";
const visitor = ((node, index, parent) => {
if (node.type === 'containerDirective') {
// :::infoなどに続くタイトル冒頭Text部(冒頭#を含む(もしくは含まない)部分)を取得(:::info ##** )
// (タイトル全体にはHTML等が含まれる可能性があるため冒頭Text部だけ操作する、残りはシャロ―コピー)
const beginningText = node.children[0].children[0].value;
// タイトル冒頭Text部に#が2つ以上連続しているとき
if(/^##/.test(beginningText)) {
// タイトル冒頭部から#とそれに続く空白を削除
newBeginningText = beginningText.replace(/^#+/, '').trim();
// タイトル部冒頭だけ更新し、残りはシャロ―コピー
// まずタイトル部全体をシャロ―コピー
let titleNodes = [...node.children[0].children];
// 冒頭要素のvalueを更新(ほかはシャロ―コピー)
const newTitleBeginningNode = {
...titleNodes[0],
value: newBeginningText,
}
// タイトルノードの冒頭要素だけ更新(ほかはシャロ―コピー)
const newTitleNodes = [ ...titleNodes ];
newTitleNodes[0] = newTitleBeginningNode;
// visitしているcontainerDirectiveの前にheadingノードを追加
parent.children.splice(index, 0, {
type: 'heading',
depth: (beginningText.match(/^##+/) || [''])[0].length, // #の連続数がheadingの深さ
children: newTitleNodes,
});
// 次に検索するのはindexを2つ分飛ばしたノード
return index + 2;
}
}
});
visit(ast, 'containerDirective', visitor);
};
return transformer;
};
export default plugin;
|