Very particular situation results in some text not being replaced
0xR opened this issue · comments
Initial checklist
- I read the support docs
- I read the contributing guide
- I agree to follow the code of conduct
- I searched issues and couldn’t find anything (or linked relevant results below)
Affected packages and versions
3 and 4
Link to runnable example
https://codesandbox.io/s/hast-replace-error-fzuxo3?file=/error.spec.js
Steps to reproduce
The code sandbox has a broken test. It should not be broken.
Expected behavior
Both replaceme instances should be replaced.
Actual behavior
The first "replaceme" instance is replaced the 2nd bold instance of "replaceme" is not replaced. If I move the bold text earlier in the sentence there is no issue. If I make the text not bold there is also no issue.
I had trouble finding the bug in the sourcecode of this package. Maybe you can help out.
Runtime
Node v16, Node v14
Package manager
npm v7
OS
Linux
Build and bundle tools
Webpack, Parcel
Managed to narrow it down a bit.
- It also occurs in
mdast-util-find-and-replace
- Here are some more cases.
true
means works,false
means fails:
['x x', true],
['*x* x', true],
['*x* x x', true],
['x *x*', false],
['x *x* x', false],
['x x *x*', false]
- I believe the
index
that’s returned here after replacing is wrong: thetext
inside emphasis(/strong) is not checked.
Hi! This was marked as ready to be worked on! Note that while this is ready to be worked on, nothing is said about priority: it may take a while for this to be solved.
Is this something you can and want to work on?
Team: please use the area/*
(to describe the scope of the change), platform/*
(if this is related to a specific one), and semver/*
and type/*
labels to annotate this. If this is first-timers friendly, add good first issue
and if this could use help, add help wanted
.
I’m off for now and focussing on non-issues this month, so might be a while to get to this!
As a workaround I created my own plugin that does not seem to have the bug.
Maybe it's useful for someone reading this:
function isText(node: Node): node is Text {
return (node as Text).type === 'text';
}
function makeText(value: string): Text {
return {
type: 'text',
value,
};
}
export const rehypeReplaceRegex: Plugin<
[{ regex: RegExp; replacer: (match: string) => Element | string }]
> = ({ replacer, regex }) => (tree) => {
unistFlatMap(tree, (node, index, parent) => {
if (isText(node)) {
const match = node.value.match(regex);
if (!match) {
return [node];
}
const split = node.value.split(regex);
const result: (Text | Element)[] = [];
split.forEach((nonMatch, i) => {
const precedingMatch = match[i - 1];
if (precedingMatch) {
const replacement = replacer(precedingMatch);
if (typeof replacement === 'string') {
result.push(makeText(replacement));
} else {
result.push(replacement);
}
}
if (nonMatch) {
result.push(makeText(nonMatch));
}
});
return result;
}
return [node];
});
};
Hi! This was closed. Team: If this was fixed, please add phase/solved
. Otherwise, please add one of the no/*
labels.
Found it! P.S. Your deps are out of date!