fix(remark-extend): task order is the same as in provided extend md
This commit is contained in:
parent
20146d54bf
commit
00176c6c5e
2 changed files with 155 additions and 137 deletions
|
|
@ -13,24 +13,27 @@ function addTask(file, newAction) {
|
||||||
file.data.remarkExtend.push(newAction);
|
file.data.remarkExtend.push(newAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findReplacementTasks(tree, file) {
|
function evaluateAsReplacementTask(node, file) {
|
||||||
visit(tree, 'code', node => {
|
if (
|
||||||
if (node.lang === 'js' && node.meta && node.meta.startsWith('::replaceFrom')) {
|
node.type === 'code' &&
|
||||||
const startSelector = node.meta.substring(
|
node.lang === 'js' &&
|
||||||
node.meta.indexOf("('") + 2,
|
node.meta &&
|
||||||
node.meta.indexOf("')"),
|
node.meta.startsWith('::replaceFrom')
|
||||||
);
|
) {
|
||||||
|
const startSelector = node.meta.substring(node.meta.indexOf("('") + 2, node.meta.indexOf("')"));
|
||||||
addTask(file, {
|
addTask(file, {
|
||||||
action: 'replaceFrom',
|
action: 'replaceFrom',
|
||||||
startSelector,
|
startSelector,
|
||||||
jsCode: node.value,
|
jsCode: node.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (node.lang === 'js' && node.meta && node.meta.startsWith('::replaceBetween')) {
|
if (
|
||||||
const startSelector = node.meta.substring(
|
node.type === 'code' &&
|
||||||
node.meta.indexOf("('") + 2,
|
node.lang === 'js' &&
|
||||||
node.meta.indexOf("',"),
|
node.meta &&
|
||||||
);
|
node.meta.startsWith('::replaceBetween')
|
||||||
|
) {
|
||||||
|
const startSelector = node.meta.substring(node.meta.indexOf("('") + 2, node.meta.indexOf("',"));
|
||||||
const endSelector = node.meta
|
const endSelector = node.meta
|
||||||
.substring(node.meta.indexOf("',") + 4, node.meta.indexOf("')"))
|
.substring(node.meta.indexOf("',") + 4, node.meta.indexOf("')"))
|
||||||
.trim();
|
.trim();
|
||||||
|
|
@ -41,65 +44,10 @@ function findReplacementTasks(tree, file) {
|
||||||
jsCode: node.value,
|
jsCode: node.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldFinishGathering(node) {
|
function evaluateAsRemoveTask(node, file) {
|
||||||
if (node.type === 'code' && node.lang === 'js' && node.meta && node.meta.startsWith('::')) {
|
if (node.type === 'code' && node.value && node.value.startsWith('::removeFrom')) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (node.value && node.value.startsWith('::')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findMdAdditionTasks(tree, file) {
|
|
||||||
let addNodes = [];
|
|
||||||
let gathering = false;
|
|
||||||
let startSelector;
|
|
||||||
let action = '';
|
|
||||||
visit(tree, (node, index, parent) => {
|
|
||||||
if (gathering === true && shouldFinishGathering(node)) {
|
|
||||||
gathering = false;
|
|
||||||
addTask(file, {
|
|
||||||
action,
|
|
||||||
startSelector,
|
|
||||||
addNodes,
|
|
||||||
});
|
|
||||||
addNodes = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gathering === true) {
|
|
||||||
if (parent.type === 'root') {
|
|
||||||
addNodes.push(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.type === 'code' && node.value && node.value.startsWith('::addMdAfter')) {
|
|
||||||
startSelector = node.value.substring(node.value.indexOf("('") + 2, node.value.indexOf("')"));
|
|
||||||
gathering = true;
|
|
||||||
action = 'addMdAfter';
|
|
||||||
}
|
|
||||||
if (node.type === 'code' && node.value && node.value.startsWith('::addMdBefore')) {
|
|
||||||
startSelector = node.value.substring(node.value.indexOf("('") + 2, node.value.indexOf("')"));
|
|
||||||
gathering = true;
|
|
||||||
action = 'addMdBefore';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (gathering === true) {
|
|
||||||
addTask(file, {
|
|
||||||
action,
|
|
||||||
startSelector,
|
|
||||||
addNodes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findRemoveTasks(tree, file) {
|
|
||||||
visit(tree, 'code', node => {
|
|
||||||
if (node.value && node.value.startsWith('::removeFrom')) {
|
|
||||||
const startSelector = node.value.substring(
|
const startSelector = node.value.substring(
|
||||||
node.value.indexOf("('") + 2,
|
node.value.indexOf("('") + 2,
|
||||||
node.value.indexOf("')"),
|
node.value.indexOf("')"),
|
||||||
|
|
@ -109,7 +57,7 @@ function findRemoveTasks(tree, file) {
|
||||||
startSelector,
|
startSelector,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (node.value && node.value.startsWith('::removeBetween')) {
|
if (node.type === 'code' && node.value && node.value.startsWith('::removeBetween')) {
|
||||||
const startSelector = node.value.substring(
|
const startSelector = node.value.substring(
|
||||||
node.value.indexOf("('") + 2,
|
node.value.indexOf("('") + 2,
|
||||||
node.value.indexOf("',"),
|
node.value.indexOf("',"),
|
||||||
|
|
@ -123,14 +71,75 @@ function findRemoveTasks(tree, file) {
|
||||||
endSelector,
|
endSelector,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldFinishGathering(node) {
|
||||||
|
if (node.type === 'code' && node.lang === 'js' && node.meta && node.meta.startsWith('::')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node.value && node.value.startsWith('::')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mdAdditionAddNodes = [];
|
||||||
|
let mdAdditionGathering = false;
|
||||||
|
let mdAdditionStartSelector;
|
||||||
|
let mdAdditionAction = '';
|
||||||
|
function evaluateAsMdAdditionTask(node, file, parent) {
|
||||||
|
if (mdAdditionGathering === true && shouldFinishGathering(node)) {
|
||||||
|
mdAdditionGathering = false;
|
||||||
|
addTask(file, {
|
||||||
|
action: mdAdditionAction,
|
||||||
|
startSelector: mdAdditionStartSelector,
|
||||||
|
addNodes: mdAdditionAddNodes,
|
||||||
});
|
});
|
||||||
|
mdAdditionAddNodes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mdAdditionGathering === true) {
|
||||||
|
if (parent.type === 'root') {
|
||||||
|
mdAdditionAddNodes.push(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.type === 'code' && node.value && node.value.startsWith('::addMdAfter')) {
|
||||||
|
mdAdditionStartSelector = node.value.substring(
|
||||||
|
node.value.indexOf("('") + 2,
|
||||||
|
node.value.indexOf("')"),
|
||||||
|
);
|
||||||
|
mdAdditionGathering = true;
|
||||||
|
mdAdditionAction = 'addMdAfter';
|
||||||
|
}
|
||||||
|
if (node.type === 'code' && node.value && node.value.startsWith('::addMdBefore')) {
|
||||||
|
mdAdditionStartSelector = node.value.substring(
|
||||||
|
node.value.indexOf("('") + 2,
|
||||||
|
node.value.indexOf("')"),
|
||||||
|
);
|
||||||
|
mdAdditionGathering = true;
|
||||||
|
mdAdditionAction = 'addMdBefore';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findExtendTasks() {
|
function findExtendTasks() {
|
||||||
return (tree, file) => {
|
return (tree, file) => {
|
||||||
findReplacementTasks(tree, file);
|
visit(tree, (node, index, parent) => {
|
||||||
findMdAdditionTasks(tree, file);
|
evaluateAsReplacementTask(node, file);
|
||||||
findRemoveTasks(tree, file);
|
evaluateAsMdAdditionTask(node, file, parent);
|
||||||
|
evaluateAsRemoveTask(node, file);
|
||||||
|
});
|
||||||
|
|
||||||
|
// for evaluateAsMdAdditionTask
|
||||||
|
if (mdAdditionGathering === true) {
|
||||||
|
mdAdditionGathering = false;
|
||||||
|
addTask(file, {
|
||||||
|
action: mdAdditionAction,
|
||||||
|
startSelector: mdAdditionStartSelector,
|
||||||
|
addNodes: mdAdditionAddNodes,
|
||||||
|
});
|
||||||
|
mdAdditionAddNodes = [];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,46 +88,6 @@ describe('remarkExtend', () => {
|
||||||
expect(result.contents).to.equal(output);
|
expect(result.contents).to.equal(output);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does replacements in order of extendMd', async () => {
|
|
||||||
const input = [
|
|
||||||
'### Red', // <-- start
|
|
||||||
'',
|
|
||||||
'red is the fire',
|
|
||||||
].join('\n');
|
|
||||||
const extendMd = [
|
|
||||||
"```js ::replaceFrom(':root')",
|
|
||||||
'module.exports.replaceSection = (node) => {',
|
|
||||||
' if (node.value) {',
|
|
||||||
" node.value = node.value.replace(/red/g, 'green').replace(/Red/g, 'Green');",
|
|
||||||
' }',
|
|
||||||
' return node;',
|
|
||||||
'};',
|
|
||||||
'```',
|
|
||||||
"```js ::replaceFrom(':root')",
|
|
||||||
'module.exports.replaceSection = (node) => {',
|
|
||||||
' if (node.value) {',
|
|
||||||
" node.value = node.value.replace(/green/g, 'yellow').replace(/Green/g, 'Yellow');",
|
|
||||||
' }',
|
|
||||||
' return node;',
|
|
||||||
'};',
|
|
||||||
'```',
|
|
||||||
].join('\n');
|
|
||||||
const output = [
|
|
||||||
'<h3>Yellow</h3>', // <-- start
|
|
||||||
'<p>yellow is the fire</p>',
|
|
||||||
'',
|
|
||||||
].join('\n');
|
|
||||||
|
|
||||||
const parser = unified()
|
|
||||||
//
|
|
||||||
.use(markdown)
|
|
||||||
.use(remarkExtend, { extendMd })
|
|
||||||
.use(mdStringify);
|
|
||||||
const result = await parser.process(input);
|
|
||||||
|
|
||||||
expect(result.contents).to.equal(output);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can replace from a starting point downward', async () => {
|
it('can replace from a starting point downward', async () => {
|
||||||
const input = [
|
const input = [
|
||||||
'### Red',
|
'### Red',
|
||||||
|
|
@ -622,4 +582,53 @@ describe('remarkExtend', () => {
|
||||||
|
|
||||||
expect(result.contents).to.equal(output);
|
expect(result.contents).to.equal(output);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does replacements in order of extendMd', async () => {
|
||||||
|
const input = [
|
||||||
|
'### Red', // <-- start
|
||||||
|
'',
|
||||||
|
'red is the fire',
|
||||||
|
'### More',
|
||||||
|
].join('\n');
|
||||||
|
const extendMd = [
|
||||||
|
'```',
|
||||||
|
"::removeBetween('heading:has([value=Red]) + *', 'heading:has([value=Red]) ~ heading')",
|
||||||
|
'```',
|
||||||
|
"```js ::replaceFrom(':root')",
|
||||||
|
'module.exports.replaceSection = (node) => {',
|
||||||
|
' if (node.value) {',
|
||||||
|
" node.value = node.value.replace(/red/g, 'green').replace(/Red/g, 'Green');",
|
||||||
|
' }',
|
||||||
|
' return node;',
|
||||||
|
'};',
|
||||||
|
'```',
|
||||||
|
"```js ::replaceFrom(':root')",
|
||||||
|
'module.exports.replaceSection = (node) => {',
|
||||||
|
' if (node.value) {',
|
||||||
|
" node.value = node.value.replace(/green/g, 'yellow').replace(/Green/g, 'Yellow');",
|
||||||
|
' }',
|
||||||
|
' return node;',
|
||||||
|
'};',
|
||||||
|
'```',
|
||||||
|
'```',
|
||||||
|
"::addMdAfter('heading:has([value=Yellow])')",
|
||||||
|
'```',
|
||||||
|
'This is added',
|
||||||
|
].join('\n');
|
||||||
|
const output = [
|
||||||
|
'<h3>Yellow</h3>', // <-- start
|
||||||
|
'<p>This is added</p>',
|
||||||
|
'<h3>More</h3>',
|
||||||
|
'',
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
|
const parser = unified()
|
||||||
|
//
|
||||||
|
.use(markdown)
|
||||||
|
.use(remarkExtend, { extendMd })
|
||||||
|
.use(mdStringify);
|
||||||
|
const result = await parser.process(input);
|
||||||
|
|
||||||
|
expect(result.contents).to.equal(output);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue