Ok, here is my solution:
let str = `<h1>topic 1</h1>
<p>desc of topic 1</p>
<h1>topic 2</h1>
<p>desc of topic 2</p>`;
const innerHTMLarr = str.match(/<h1>.*(?=<\/h1>)/g).map(x => x.substring(4));
const result = str.replace(/<h1>/g, function() {
return `<h1 id="${innerHTMLarr.shift()}">`;
});
console.log(result)
First I match every <h1> in a regex. I have added a look-ahead to match the closing </h1> but without actually including it in the result. The same cannot be done for the opening <h1> since JavaScript doesn't support look-behinds (as far as I know), so we have to remove it manually with substring().
Once we have the innerHTML for each <h1> tag, we can do a replace() on the whole string by finding with regex "<h1>" and replacing it with "<h1 id=[x]>", where x the first result of the array we populated above. We do shift() here to remove used values.
NOTE: The above will generate an invalid id attribute since you can't have spaces in the attribute value. You may want to expand my answer for your specific use-case.
textareaand you want the innerHTML of the headers to be set as the value for theidattribute. Do you want this to happen at runtime (as you type) or when you submit the contents via some button press?