-
Notifications
You must be signed in to change notification settings - Fork 2.1k
关于同时使用markdown-it-container和markdown-it-attrs导致冲突的问题 #311
Description
测试 如下:
:::column {.column-container}
column test1 {.column-1}
---
column test2 {.column-2}
:::输出:
<div class="column-container column-2 grid">
<div class="column column-1">
<p>column test1 </p>
</div>
<div class="column">
<p>column test2 </p>
</div>
</div>预期输出:
<div class="column-container grid">
<div class="column column-1">
<p>column test1 </p>
</div>
<div class="column column-2">
<p>column test2 </p>
</div>
</div>不使用markdown-it-container时:
<p class="column-container">::::::column </p>
<p class="column-1">column test1 </p>
<hr />
<p class="column-2">column test2 </p>
<p>::::::</p>经过测试发现是由于markdown-it-container在添加column-container父容器Token时,默认会将container_column _close的nesting设置为-1.
……
state.lineMax = nextLine;
token = state.push('container_' + name + '_open', 'div', 1);
token.markup = markup;
token.block = true;
token.info = params;
token.map = [startLine, nextLine];
// 修正
let len = state.tokens.length - startLine;
state.md.block.tokenize(state, startLine + 1, nextLine);
147 > token = state.push('container_' + name + '_close', 'div', -1);
token.markup = state.src.slice(start, pos);
token.block = true;
token.info = params;
……这是按照markdown-it的官方文档设置的,原本是没有问题的。
/**
* Token#nesting -> Number
*
* Level change (number in {-1, 0, 1} set), where:
*
* - `1` means the tag is opening
* - `0` means the tag is self-closing
* - `-1` means the tag is closing
**/
this.nesting = nesting当同时使用markdown-it-container和markdown-it-attrs时,markdown-it-attrs在遍历寻找container_div _close时由于新添加的容器的container_column _close节点同样满足条件nesting等于-1的条件,这就会导致本来应该添加到column test2上的样式column-2会添加到column-container的父容器上。
……
{
/**
* end of {.block}
*/
name: 'end of block',
tests: [
{
shift: 0,
type: 'inline',
children: [
{
position: -1,
content: utils.hasDelimiters('end', options),
type: t => t !== 'code_inline'
}
]
}
],
transform: (tokens, i, j) => {
let token = tokens[i].children[j];
let content = token.content;
let attrs = utils.getAttrs(content, content.lastIndexOf(options.leftDelimiter), options);
let ii = i + 1;
475 > while (tokens[ii + 1] && tokens[ii + 1].nesting === -1) {
ii++;
}
> let openingToken = utils.getMatchingOpeningToken(tokens, ii);
utils.addAttrs(attrs, openingToken);
let trimmed = content.slice(0, content.lastIndexOf(options.leftDelimiter));
token.content = last(trimmed) !== ' ' ? trimmed : trimmed.slice(0, -1);
}
}
……经过对markdown-it-container和markdown-it-attrs两个组件的Issue查询,发现二者官方也没有对这个问题进行有效的解决。
# markdown-it-container issue#39 [Incompatibility with markdown-it-attrs]
# markdown-it-attrs issue#111 [Propagation of Attributes in Markdown-it-container]
# markdown-it-attrs issue#72 [Conflict with markdown-it-container]
可能因为这个原因导致的问题:
# markdown-it-attrs issue#150 [Unable to apply attributes to the last column of tables.]
# markdown-it-attrs issue#142 [Last column attribute setting results unexpectedly.]
对于这个问题的临时解决方法, 由于我目前是使用的NPM本地安装的Nodeppt,可以修改container.js#147中的代码,将 token = state.push('container_' + name + '_close', 'div', -1);修改为 token = state.push('container_' + name + '_close', 'div', -2);暂时使用,但是可能会对markdown-it-container和nodeppt产生未知无法预测的BUG,由于nodeppt项目更新时间久远,不知道作者是否还在维护这个项目,这里提供了问题的原因以及临时解决方法,希望能有更专业的解决方案。
临时解决方法:
修改container.js#147代码
……
state.lineMax = nextLine;
token = state.push('container_' + name + '_open', 'div', 1);
token.markup = markup;
token.block = true;
token.info = params;
token.map = [startLine, nextLine];
// 修正
let len = state.tokens.length - startLine;
state.md.block.tokenize(state, startLine + 1, nextLine);
147 > token = state.push('container_' + name + '_close', 'div', -2);
token.markup = state.src.slice(start, pos);
token.block = true;
token.info = params;
……