feat(remark-extend): allow globalReplaceFunction

This commit is contained in:
Thijs Louisse 2022-06-08 22:43:16 +02:00 committed by Thijs Louisse
parent 20af7a44ce
commit 63f8f6fd36
4 changed files with 63 additions and 4 deletions

View file

@ -0,0 +1,5 @@
---
'remark-extend': patch
---
feat: allow globalReplaceFunction in remark-extend

View file

@ -184,7 +184,7 @@ This function gets called with these nodes in order.
#### Adjustment Result #### Adjustment Result
```md ```md
# Below you will not find any read # Below you will not find any 'red'
### Green ### Green
@ -193,6 +193,21 @@ green is the fire
--- ---
It's also possible to globally define a replace function.
The example below shows the config object that is provided to the `remarkExtend` function.
Note that local replacements are run after global replacements.
```js
{ globalReplaceFunction: node => {
if (node.type === 'link') {
// All internal links to '/systems/' (like '(../../fundamentals/systems/overlays/configuration.md)'),
// will be changed into '/web-systems/' ('(../../fundamentals/web-systems/overlays/configuration.md)').
node.url = node.url.replace(/\systems\/g, '/web-systems/');
}
return node;
}};
```
## Import selection ## Import selection
For `::import` you can provide a start and end selector based on [unist-util-select](https://github.com/syntax-tree/unist-util-select#support). For `::import` you can provide a start and end selector based on [unist-util-select](https://github.com/syntax-tree/unist-util-select#support).

View file

@ -36,6 +36,7 @@ function handleImportedFile({
startSelector, startSelector,
endSelector, endSelector,
userFunction, userFunction,
globalReplaceFunction,
filePath, filePath,
missingEndSelectorMeansUntilEndOfFile = false, missingEndSelectorMeansUntilEndOfFile = false,
}) { }) {
@ -73,6 +74,9 @@ function handleImportedFile({
} }
if (insertIt) { if (insertIt) {
if (globalReplaceFunction) {
node = globalReplaceFunction(node, { index, parent, tree });
}
if (userFunction) { if (userFunction) {
node = userFunction(node, { index, parent, tree }); node = userFunction(node, { index, parent, tree });
} }
@ -87,7 +91,7 @@ function handleImportedFile({
// unified expect direct // unified expect direct
// eslint-disable-next-line consistent-return // eslint-disable-next-line consistent-return
function remarkExtend({ rootDir = process.cwd(), page } = {}) { function remarkExtend({ rootDir = process.cwd(), page, globalReplaceFunction } = {}) {
return tree => { return tree => {
visit(tree, (node, index, parent) => { visit(tree, (node, index, parent) => {
if ( if (
@ -178,6 +182,7 @@ function remarkExtend({ rootDir = process.cwd(), page } = {}) {
startSelector, startSelector,
endSelector, endSelector,
userFunction, userFunction,
globalReplaceFunction,
filePath, filePath,
fileImport, fileImport,
missingEndSelectorMeansUntilEndOfFile, missingEndSelectorMeansUntilEndOfFile,

View file

@ -28,11 +28,15 @@ async function expectThrowsAsync(method, { errorMatch, errorMessage } = {}) {
} }
} }
async function execute(input) { async function execute(input, { globalReplaceFunction } = {}) {
const parser = unified() const parser = unified()
// //
.use(markdown) .use(markdown)
.use(remarkExtend, { rootDir: __dirname, page: { inputPath: 'test-file.md' } }) .use(remarkExtend, {
rootDir: __dirname,
page: { inputPath: 'test-file.md' },
globalReplaceFunction,
})
.use(mdStringify); .use(mdStringify);
const result = await parser.process(input); const result = await parser.process(input);
return result.contents; return result.contents;
@ -147,6 +151,36 @@ describe('remarkExtend', () => {
); );
}); });
it('can do global replacements, that run before local replacements', async () => {
const result = await execute(
[
//
'# Red',
"```js ::import('./fixtures/three-sections-red.md', 'heading:has([value=More Red])', 'heading:has([value=More Red]) ~ heading[depth=2]')",
'module.exports.replaceSection = (node) => {',
' if (node.value) {',
" node.value = node.value.replace(/green/g, 'blue').replace(/Red/g, 'Blue');",
' }',
' return node;',
'};',
'```',
].join('\n'),
{
globalReplaceFunction: node => {
if (node.value) {
// eslint-disable-next-line no-param-reassign
node.value = node.value.replace(/red/g, 'green');
}
return node;
},
},
);
expect(result).to.equal(
['<h1>Red</h1>', '<h2>More Blue</h2>', '<p>the sun can get blue</p>', ''].join('\n'),
);
});
it('throws if an import file does not exist', async () => { it('throws if an import file does not exist', async () => {
await expectThrowsAsync(() => execute("```js ::import('./fixtures/not-available.md')\n```"), { await expectThrowsAsync(() => execute("```js ::import('./fixtures/not-available.md')\n```"), {
errorMatch: errorMatch: