Convert String That Contains <,> (Special Chars) To Html
Solution 1:
You have to replace <
by <
and >
by >
before replacing the te
.
innerHTML.replace('<', '<').replace('>', '>')...
Solution 2:
Regular expressions and HTML don't mix very well. In your case, if you're very careful you can manually escape all the proper values and produce valid HTML. If you're even a little careless you will have problems with malformed or unsafe content. This is not to say "you absolutely must never do it that way", but you should at least be aware of the pitfalls involved in doing so.
The recommended solution is never to programmatically manipulate HTML strings yourself. Instead, you should manipulate HTMLElement
objects and trust your JavaScript engine to handle the HTML.
In your case, I'd say there are two components to the question.
One: convert a string into a representation where pieces of the string are marked as "should-be-highlighted" or "should-not-be-highlighted". If you introduce the following interface (you used the TypeScript tag after all):
interface HighlightableString {
value: string;
highlighted: boolean;
}
Then a string with highlighted sections could be represented as Array<HighlightableString>
.
So you need a function to convert a string like "<some text>"
and the substring "te"
to something like
[
{value: "<some ", highlighted: false},
{value: "te", highlighted: true},
{value: "xt>", highlighted: false}
]
Here's one possible implementation of that function, but you can do it any way you want. And this is a perfectly valid place to use regular expressions, since there is no way to represent "unsafe" or "malformed" HTML here:
function highlightSubstring(s: string, substring: string): Array<HighlightableString> {
if (substring.length === 0) return [{ value: s, highlighted: false }]
const ret: Array<HighlightableString> = [];
for (
var prevPos = 0, pos = s.indexOf(substring);
pos >= 0;
prevPos = pos + substring.length, pos = s.indexOf(substring, prevPos)
) {
ret.push({ value: s.substring(prevPos, pos), highlighted: false });
ret.push({ value: substring, highlighted: true });
}
ret.push({ value: s.substring(prevPos), highlighted: false });
return ret;
}
Two: given an Array<HighlightableString>
, a parent HTMLElement
, and some way of highlighting text (e.g., an HTMLElement
representing such highlighting), add the properly highlighted text to that parent element. This is where you really don't want to be using regular expressions, or HTML text at all. Here is one possible implementation:
function appendHighlightedString(
highlightableStrings: Array<HighlightableString>,
parentElement: HTMLElement,
highlightElement: HTMLElement
) {
highlightableStrings.forEach(hs => {
const textNode = document.createTextNode(hs.value);
if (hs.highlighted) {
const highlightClone = highlightElement.cloneNode(true);
highlightClone.appendChild(textNode)
parentElement.appendChild(highlightClone)
} else {
parentElement.appendChild(textNode);
}
})
}
Notice how that function is using Text
nodes and element cloning and appending. It never looks at HTML directly.
Okay, let's see if it works. I will try it with the content <test content>
:
// make a highlight element
const highlightElement = document.createElement("span");
highlightElement.style.backgroundColor = '#FFFB00';
const wholeString = document.createElement("div"); // or whatever the parent element is
appendHighlightedString(
highlightSubstring("<test content>", "te"),
wholeString,
highlightElement
);
Let's see what it did in Firefox:
console.log(wholeString.innerHTML);
// <<span style="background-color: rgb(255, 251, 0);">te</span>st
// con<span style="background-color: rgb(255, 251, 0);">te</span>nt>
Well, the browser decided to use rgb(255, 251, 0)
instead of #FFFB00
. But that's the browser's prerogative; we are out of the HTML game. The point is if you add that element to your document,
document.body.appendChild(wholeString);
it will be highlighted the way you want.
Okay, hope that helps. Good luck!
Post a Comment for "Convert String That Contains <,> (Special Chars) To Html"