home ~ projects ~ socials

Basic HTML Pretty Printing In Rust

I haven't been able to find an HTML pretty-printer for Rust. It feels like I have to be missing something. I could call out to Prettier, but I need something for Neopoligen and don't want to embed it.

So, this is very simple formatter. There's a bunch of stuff it doesn't do and lots of cases it breaks on, but it's at least a starting point to try to 80/20 it.

The idea is to show this, but with a button that lets you see the unformatted stuff if it gets weird.

But seriously, probably don't use this.

```cargo
[dependencies]
regex = "1.10.4"
```

use regex::Regex;


fn main() {
  let code = r#"<div> <span>

thing</span>   </div>"#.to_string();

  let output = simple_format_html(&code);
  println!("{}", output);

}

fn simple_format_html(code: &String) -> String {
  let mut re = Regex::new(r"\n").unwrap();
  let output = re.replace_all(code, " ");
  re = Regex::new(r" \s+").unwrap();
  let output = re.replace_all(&output, " ");
  re = Regex::new(r"\s+<").unwrap();
  let output = re.replace_all(&output, "<");
  re = Regex::new(r">\s+").unwrap();
  let output = re.replace_all(&output, ">");
  let parts: Vec<&str> = output.split("<").collect();
  let mut assembler: Vec<String> = vec![];
  let mut level = 0i8;
  parts.iter().skip(1).for_each(|part| {
    if part.starts_with("/") {
      level -= 2;
    } 
    for _ in 0..level {
      assembler.push(" ".to_string());
    }
    assembler.push(format!("<{}\n", part));
    if !part.starts_with("/") {
      level += 2;
    }
  });
   assembler.join("").to_string()
}
Output:
<div>
  <span>thing
  </span>
</div>

Known Bugs

  • This has to start with a tag
  • Content inside pre tags
  • JavaScript or CSS that uses < or >
  • Inline closed tags (e.g. <br />) don't unindent
-- end of line --