Home > Net >  Replace words in a string but ignore those which are a markdown link
Replace words in a string but ignore those which are a markdown link

Time:08-12

I wrote a function that replaces every string from a text that is mentioned in an array of strings to a mark down link linking to a word glossary page.

Example:

const text = "This is an example text with an [example](example.com) markdown link.";

const highlightedWords = ["xxx", "example", "yyy"];

const replaceWords = (text: string, highlightedWords: string[]) => {
  if (highlightedWords.length == 0 || text == null) {
    return text;
  }
  return text.replace(
    new RegExp(`\\b(${highlightedWords.join("|")})\\b`, "gi"),
    `[$1](/glossary#$1)`
  );
};

console.log(replaceWords(text, highlightedWords));
// Output: This is an [example](/glossary#example) text with an [[example](/glossary#example)]([example](/glossary#example).com) markdown link.

I think you see the problem. I want to achieve, that the regex function ignores the text fragments that already that are already enclosed by any markdown link syntax.

Thanks for your help!

CodePudding user response:

i'm not sure if you want that only the first match will be converted to markdown...

this is my solution:

const text = "This is an example text with an [example](example.com) markdown link.";

const highlightedWords = ["xxx", "example", "yyy"];

const replaceWords = (text, highlightedWords) => {
  if (highlightedWords.length == 0 || text == null) {
    return text;
  }
  return text.replace(
    new RegExp(`\\b(${highlightedWords.join("|")})[.*\][(].*[)]\\b`, "gi"),
    `[$1](/glossary#$1)`
  );
};

console.log(replaceWords(text, highlightedWords));

output:

"This is an example text with an [example](example.com) markdown link."

CodePudding user response:

You need to match the markdown links first, and then capture the words you need to convert. In the replacement, you need to apply conditional logic to only convert the match if Group 1 matched.

See the fixed code below:

const text = "This is an example text with an [example](example.com) markdown link.";

const highlightedWords = ["xxx", "example", "yyy"];

const replaceWords = (text, highlightedWords) => {
  if (highlightedWords.length == 0 || text == null) {
    return text;
  }
  return text.replace(
    new RegExp(String.raw`\[[^\][]*]\([^()]*\)|\b(${highlightedWords.join("|")})\b`, "gi"),
    (m, g1) => g1 ? `[${g1}](/glossary#${g1})` : m
  );
};

console.log(replaceWords(text, highlightedWords));

The \[[^\][]*]\([^()]*\) part matches

  • \[ - a [
  • [^\][]* - zero or more chars other than [ and ]
  • ]\( - a ]( string
  • [^()]* - zero or more chars other than ( and )
  • \) - a ) char

The | is an alternation operator.

(m, g1) => g1 ? ${g1} : m means that m is the match value and g1 is the highlightedWords match that will be converted if it is not already inside a markdown link.

  • Related