You'd need a proper HTML parser to support nested tags, for example, blockquote
tags could be nested.
Here is a solution if you can live with the limitation of not supporting corner cases. It uses nested replaces, the outer one to identify blockquote
tags with its content, the inner one to take action on the blockquote
content:
const lessonText = "<div><blockquote>""</blockquote><p>Heni "</p><blockquote>no quotation</blockquote><span>hi</span><blockquote><span style=\"font-family:Courier New,Courier,monospace;\">row.names(vol) <- c("</span></blockquote></div>"
let result = lessonText.replace(/(<blockquote>)(.*?)(<\/blockquote>)/g, function(m, g1, g2, g3) {
return g1 + g2.replace(/"/g, '"') + g3;
});
console.log('Result: ' + result);
Result: <div><blockquote>""</blockquote><p>Heni "</p><blockquote>no quotation</blockquote><span>hi</span><blockquote><span style="font-family:Courier New,Courier,monospace;">row.names(vol) <- c("</span></blockquote></div>
Explanation of outer replace regex:
(<blockquote>)
-- capture group 1: opening blockquote
tag
(.*?)
-- capture group 2: non-greedy scan over content until:
(<\/blockquote>)
-- capture group 3: closing blockquote
tag
/g
flag -- replace all patterns
Note:
- Limitation: This fails with nested tags
- If you expect attributes for the
blockquote
you could use regex (<blockquote( [^>]*)?>)
instead (which does not support corner cases like <blockquote tile="<gotcha>!">
)
- If you expect newlines in the
blockquote
content you can use regex ([\s\S]*?)
instead.
Explanation of inner replace regex:
"
-- capture literal "
text (you could use string ""e"
instead)
/g
flag -- replace all patterns