Reputation: 1945
I am looking to wrap the first word in a string, for example:
var html = '<br> <br> Hello world!';
I have the following code:
html.replace(/^\s*\w+/, '<div class="underline">$&</div>');
This will output:
<div class="underline"><br></div> <br> Hello world!
How can I ignore HTML tags so that the output is like this, where the first word "Hello" gets wrapped in the DIV?:
<br> <br> <div class="underline">Hello</div> world!
Upvotes: 2
Views: 282
Reputation: 41
Try this
html.replace(/[^< ][A-Za-z]+[^> ]/, '<div class="underline">$&</div>');
or
html.replace(/([^< ][A-Za-z]+[^> ])/, '<div class="underline">$1</div>');
For reference, the same function in sed command is
echo '<br> <br> Hello world!' | sed -e 's/\([^< ][A-Za-z]\+[^> ]\)/<div class="underline">\1<\/div>/'
To support single body character,
html.replace(/([^<][A-Za-z]+[^>])/, '<div class="underline">$1</div>');
Although, if the html tag has some attributes like <p class="classname">
, it won't work. DOMParser will be necessary instead of regex or, consult this topic.
Upvotes: 0
Reputation: 370949
You can use DOMParser to create a document from the string, then look through text nodes in the document to find one whose trimmed text is not the empty string. Replace that node with a <div class="underline">
:
// https://stackoverflow.com/questions/2579666/getelementsbytagname-equivalent-for-textnodes
const getTextNodes = (parent) => {
const walker = document.createTreeWalker(
parent,
NodeFilter.SHOW_TEXT,
null,
false
);
let node;
const nodes = [];
while(node = walker.nextNode()) {
nodes.push(node);
}
return nodes;
};
const html = '<br> <br> Hello world!';
const doc = new DOMParser().parseFromString(html, 'text/html');
const nodes = getTextNodes(doc.body);
const node = nodes.find(node => node.textContent.trim() !== '');
const [, firstWord, rest] = node.textContent.match(/(\S+)(.*)/);
const newNode = document.createElement('div');
newNode.className = 'underline';
newNode.textContent = firstWord;
node.replaceWith(newNode);
newNode.insertAdjacentHTML('afterend', rest);
console.log(doc.body.innerHTML);
Upvotes: 5