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;