I am trying to remove tags from a string but keeping the order in tact using Regular expression. The string I have is this
<p><span style="color: blue;">General Power</span></p><p>This contains some info.</p><p><br></p><p>!</p><p>enable</p><p>bus at</p><p>terminal: <span style="color: red;">Name Terminal</span></p><p>enable bus name <span style="color: red;">Switch Bus</span></p><p>no ip domain-lookup</p><p><span style="color: rgb(0, 0, 0);">ip domain name </span><span style="color: red;">region</span><span style="color: rgb(0, 0, 0);">.google.com</span></p><p><br></p><p>!</p>
What I have tried so far is
const [string, setString] = useState(
`<p><span style="color: blue;">General Power</span></p><p>This contains some info.</p><p><br></p><p>!</p><p>enable</p><p>bus at</p><p>terminal: <span style="color: red;">Name Terminal</span></p><p>enable bus name <span style="color: red;">Switch Bus</span></p><p>no ip domain-lookup</p><p><span style="color: rgb(0, 0, 0);">ip domain name </span><span style="color: red;">region</span><span style="color: rgb(0, 0, 0);">.google.com</span></p><p><br></p><p>!</p>`
);
useEffect(() => {
const regex = /(<([^>] )>)/gi;
const newString = string.replace(regex, " ");
setString(newString);
}, []);
What I get is this
General Power This contains some info. ! enable bus at terminal: Name Terminal enable bus name Switch Bus no ip domain-lookup ip domain name region .google.com !
The order I want is:
General Power
This contains some info.
!
enable
bus at
terminal: Name Terminal
enable bus name Switch Bus
no ip domain-lookup
ip domain name region.google.com
!
const [string, setString] = useState(
`<p><span style="color: blue;">General Power</span></p><p>This contains some info.</p><p><br></p><p>!</p><p>enable</p><p>bus at</p><p>terminal: <span style="color: red;">Name Terminal</span></p><p>enable bus name <span style="color: red;">Switch Bus</span></p><p>no ip domain-lookup</p><p><span style="color: rgb(0, 0, 0);">ip domain name </span><span style="color: red;">region</span><span style="color: rgb(0, 0, 0);">.google.com</span></p><p><br></p><p>!</p>`
);
useEffect(() => {
const regex = /(<([^>] )>)/gi;
const newString = string.replace(regex, " ");
setString(newString);
}, []);
This is what I have tried so far
CodePudding user response:
To preserve the order of the lines, you can use the String.prototype.split() method to split the string by the
tags, and then use String.prototype.replace() to remove the remaining HTML tags from each line.
Here is an example of how you could do this:
const [string, setString] = useState(
`<p><span style="color: blue;">General Power</span></p><p>This contains some info.</p><p><br></p><p>!</p><p>enable</p><p>bus at</p><p>terminal: <span style="color: red;">Name Terminal</span></p><p>enable bus name <span style="color: red;">Switch Bus</span></p><p>no ip domain-lookup</p><p><span style="color: rgb(0, 0, 0);">ip domain name </span><span style="color: red;">region</span><span style="color: rgb(0, 0, 0);">.google.com</span></p><p><br></p><p>!</p>`
);
useEffect(() => {
// Split the string by the `<p>` tags
const lines = string.split("<p>");
// Use `String.prototype.replace()` to remove the remaining HTML tags from each line
const newString = lines.map(line => line.replace(/(<([^>] )>)/gi, " ")).join("\n");
// Set the new string
setString(newString);
}, []);
This should give you the output you are looking for:
Copy code
General Power
This contains some info.
!
enable
bus at
terminal: Name Terminal
enable bus name Switch Bus
no ip domain-lookup
ip domain name region.google.com
!
CodePudding user response:
DOMParser combined with a method to retrieve all text nodes would be more appropriate. And rather than an effect hook for this, consider passing a function to useState
- that way, the state never gets set to the (undesirable) value with the HTML markup, but starts out as the replaced string without any re-renderings - or avoid state entirely now that it isn't being set anywhere.
const getTextContentOnly = (html) => {
const doc = new DOMParser().parseFromString(html, 'text/html');
const walker = document.createTreeWalker(
doc.body,
NodeFilter.SHOW_TEXT,
null,
false
);
const texts = [];
let node;
while(node = walker.nextNode()) {
texts.push(node.nodeValue);
}
return texts;
}
const App = () => {
const texts = React.useMemo(() => getTextContentOnly(
`<p><span style="color: blue;">General Power</span></p><p>This contains some info.</p><p><br></p><p>!</p><p>enable</p><p>bus at</p><p>terminal: <span style="color: red;">Name Terminal</span></p><p>enable bus name <span style="color: red;">Switch Bus</span></p><p>no ip domain-lookup</p><p><span style="color: rgb(0, 0, 0);">ip domain name </span><span style="color: red;">region</span><span style="color: rgb(0, 0, 0);">.google.com</span></p><p><br></p><p>!</p>`
), []);
return texts.map((text, i) => <div key={i}>{text}</div>);
};
ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>