Mohammad Amin
Mohammad Amin

Reputation: 62

String manipulation javascript

I am trying to figure out how to manipulate string like this:

string abc = "<p> Hello world <em> How are you? </em> abc <em> You there </em> </p>"

into

string def = "<p> Hello world </> <em> How are you? </> <p> abc </> <em> You there </>" 

Explanation: For every tag the closing tag will be </> this and I am not allowed to use nested tags as we do in normal HTML. That's why my string def has </> after every opening tag.

<p> hello world </> (tag closed) <em> how are you? </> (em tag closed) <p> abc </> (p tag closed) <em> You there </> (em tag closed)

I tried using exec on regex to find HTML closing tags and replace them with </>. It worked but unfortunately, I couldn't figure out how to work with opening tags.

I also tried splitting a string using space ' ' and looping through the array. But no luck.

Can anyone please guide me through this?

Upvotes: -1

Views: 102

Answers (2)

Raghav Garg
Raghav Garg

Reputation: 3707

Using regex in this case would be quite difficult, we can split the the array over " " and simply loop over it and decide the current state of the string and tags.

function changeHTMLEndTags(html_string = "") {
    // adding a space before '<' and after '>'
    html_string = html_string.replace(/(<)/g, ' <').replace(/(>)/g, '> ');

    // removing multiple spaces introduced due to above operation
    // and triming the start and end of the string
    html_string = html_string.replace(/\s\s+/g, ' ').trim();

    html_string_words = html_string.split(" ");
    
    final_html_string = "";
    
    last_opening_tag = null;
    
    for(i = 0; i < html_string_words.length; ++i) {
        
        current_word = html_string_words[i];
        
        // if the current_word is an opening tag
        if (current_word.match(/<\w+>/)) {
            if (last_opening_tag === null) {
                final_html_string += current_word + " ";
                last_opening_tag = current_word;
            }
            else {
                final_html_string += "</>" + " " + current_word + " ";
                last_opening_tag = current_word;
            }
        }
        
        // if the current_word is a closing tag
        else if (current_word.match(/<\/\w+>/)) {
            if (last_opening_tag !== null) {
                final_html_string += "</>" + " ";
                last_opening_tag = null;
            }
            else {
                // do nothing with the current_word,
                // let it get swallowed, we want to drop the dangling closing tags
            }
        }
        
        // else the current_word is a normal word
        else {
            if (last_opening_tag !== null) {
                final_html_string += current_word + " ";
            }
            else {
                // I took assumption here, 
                // that if we don't have any opening tag, we will use `<p>`
                final_html_string += "<p>" + " " + current_word + " ";
                last_opening_tag = "<p>";
            }
        }
    }
    
    return final_html_string.trim();
}

abc = "<p> Hello world <em> How are you? </em> abc <em> You there </em> </p>";
console.log(changeHTMLEndTags(abc));

abc = "<p> Hello world<em> How are you? </em> abc <em> You there </em> </p>";
console.log(changeHTMLEndTags(abc));

Upvotes: 2

Marc
Marc

Reputation: 11613

There might be a fancier way to do this, but this works to replace </em> and </p> with </>, which seems to be your goal (despite the inconsistencies in your question and sample output).

let string = "<p> Hello world <em> How are you? </em> abc <em> You there </em> </p>";
let def = string.replace(/<\/(em|p)>/g, "</>");
console.log(def);

Upvotes: 0

Related Questions