feat(remark-extend): allow globalReplaceFunction
This commit is contained in:
parent
20af7a44ce
commit
63f8f6fd36
4 changed files with 63 additions and 4 deletions
5
.changeset/unlucky-games-double.md
Normal file
5
.changeset/unlucky-games-double.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'remark-extend': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: allow globalReplaceFunction in remark-extend
|
||||||
|
|
@ -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).
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue