7
\$\begingroup\$

Given an inconsistently indented piece of html code your task is to return the same text but correctly indented

  • Indent space = 4
  • Assume input will be non-empty.
  • Input can be taken as string or array/list of lines
  • Opening and closing tags must be on the same line as long as there is not any other tag inside. <td></td>
  • Assume there will be only html tags, no text elements whatsoever
  • All opening tags that aren't self-closing will have closing tags, and will be given in the correct nesting order. Self-closing tags will be closed with />
  • Standard rules apply

Example and test-cases

Input
--------------
<table>
     <tr>
  <td>
</td>
      <td></td></tr></table> 

Output
----------
<table>
    <tr>
        <td></td>
        <td></td>
    </tr>
</table>

Input
------------
<div>
              <ul>
<li></li><li></li></ul>
        <ul>
              <li></li>
<li></li>
</ul><div><table>

<tbody>
  <thead>
 <tr>
        <th></th>
          <th></th>
             </tr>
       </thead>
   <tbody>
<tr>
    <td></td>
    <td></td>
</tr>
<tr>
    <td></td>
    <td></td>
</tr>
</tbody></tbody></table>
       </div>
</div>

Output
--------------------
<div>
    <ul>
        <li></li>
        <li></li>
    </ul>
    <ul>
        <li></li>
        <li></li>
    </ul>
    <div>
        <table>
            <tbody>
                <thead>
                    <tr>
                        <th></th>
                        <th></th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td></td>
                        <td></td>
                    </tr>
                </tbody>
            </tbody>
        </table>
    </div>
</div>

Input
--------------
<div><img src=""/><p></p><input/><input/></div>

Output
-------------
<div>
    <img src=""/>
    <p></p>
    <input/>
    <input/>
</div>
\$\endgroup\$
  • 2
    \$\begingroup\$ Do we need to support single-label tags like img or a? \$\endgroup\$ – AdmBorkBork Oct 23 '18 at 12:41
  • 5
    \$\begingroup\$ <p><p></p> is valid HTML (tag soup). Are you confusing HTML with XML? \$\endgroup\$ – nwellnhof Oct 23 '18 at 13:49
  • 1
    \$\begingroup\$ By specifying HTML I'm assuming that you do not care about significant whitespace? <foo></foo> can be meaningfully different than <foo>\n</foo> if we're just talking about XML in general. \$\endgroup\$ – Poke Oct 23 '18 at 13:52
  • 1
    \$\begingroup\$ @edc65: This question is not about xhtml \$\endgroup\$ – recursive Oct 23 '18 at 20:54
  • 1
    \$\begingroup\$ @LuisfelipeDejesusMunoz You can add a rule "Each tag that is not self-closing has a matching (open/close) tag", regarding <p><p></p>. \$\endgroup\$ – user202729 Oct 24 '18 at 15:12
1
\$\begingroup\$

Retina, 101 bytes

L`<.*?>
T`¶`_`<(.+)¶</\1
^.+
$&/
{`(( *)((?!.*(</|/>)))?.+)/¶(.+)
$1¶$2$#3*4* $5/
    (</.+>/)
$1
/$

Try it online! Explanation:

L`<.*?>

List just the tags.

T`¶`_`<(.+)¶</\1

Join matching pairs of tags.

^.+
$&/

Add a marker to the end of the first line.

{`(( *)((?!.*(</|/>)))?.+)/¶(.+)
$1¶$2$#3*4* $5/

Copy the indentation from each line to the next, adding 4 spaces if the current line is an opening tag.

    (</.+>/)
$1

But if the next line (which is now the current line) is a closing tag then delete 4 spaces.

/$

Delete the marker once it reaches the last line.

\$\endgroup\$
0
\$\begingroup\$

Python 2, 170 bytes

def f(o,i=-4):
 s,c,n,h,l=" <\n  "
 for t in"".join(o.split()).split(c):
	if'/'==t[:1]:i-=4;h+=(n+i*s)*(l!=t[1:])+c+t
	else:h+=n+i*s+c+t;i+=4-4*('/'in t);l=t
 print h[4:]

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ This removes the space between img and src in <img src="hey"/> \$\endgroup\$ – Nicholas Pipitone Oct 24 '18 at 23:41
0
\$\begingroup\$

Python 2, 174 bytes

import re
def F(I):
 m=x=0
 n,s,b='\n/<'
 for d in re.findall(r'<(.*?>)',I):
	if d[0]==s:print(n+' '*~-m*4)*x+b+d,;m-=1;x=1
	else:print n+' '*m*4+b+d,;x*=s in d;m+=not s in d

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript 115 Bytes

s=>(n=c=-1,m=f=>"\n"+" ".repeat(4*c)+f,s.replace(/<\/?|\/>/g,w=>w[1]?(n?k=m(w):k=w,n=1,c--,k):m(w,n=0*c++)).trim())

I lost the original code so whoops no explanation on this one. It's short though so think of it as a reversing challenge :)

Adds some newlines, but it is correctly tabbed.

\$\endgroup\$
0
\$\begingroup\$

PHP, 141bytes

preg_match_all("%(<.*>)%U",$argn,$m);foreach($m[1]as$t)echo!$p|($p=$t[1]!="/")?str_pad("\n",($t[-2]!="/"?$p?++$i:$i--:$i+!$p=0)*4-3):!$i--,$t;

Run as pipe with -nR or try it online.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.