utkarshkukreti / markup.rs

A blazing fast, type-safe template engine for Rust.
Apache License 2.0
350 stars 14 forks source link

Automatically pretty-print in debug builds #23

Open ssokolow opened 2 years ago

ssokolow commented 2 years ago

It occurs to me that it would be nice for developer egonomics if (via feature flag?) markup.rs would output pretty-printed HTML in debug builds, for situations where you've got JavaScript meddling with what the developer tools displays and you need to inspect the original form of the markup.

(It'd be a nice complement to how useful it is for JS/TS development that, in the default configuration, rust-embed will embed your assets in the binary in release builds but just serve up the editable source files in debug builds.)

ZaneHannanAU commented 2 years ago

while this could be done in a simple manner - ie an Indent(usize) - it may cause significant issues with variations between debug and release builds.

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
pub struct Indent(pub num::Wrapping<usize>);
impl fmt::Display for Indent {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    (0..*self.0).try_for_each(|| f.write_str("\t"))
  }
}
impl Indent {
  fn deeper(self) -> Self {
    Self(self.0 + 1)
  }
  fn higher(self) -> Self {
    Self(self.0 - 1)
  }
}

pretty nïeve and will generate bad code in many cases

ZaneHannanAU commented 2 years ago

Alt:

struct Indent<const N: usize>([(); N]);
impl<const N: usize> Indent<N> {
  fn new() -> Self { Self([(); N]) }
  fn deeper(self) -> Indent<{N + 1}> { unsafe { *&self } }
  fn higher(self) -> Indent<{N - 1}> { unsafe { *&self } }
}
impl fmt::Display for Indent<N> {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    let buf = [b'\t'; N];
    f.write_all(&buf);
  }
}
Kijewski commented 2 years ago

A proper HTML pretty-printer needs to know which elements are block elements, inline elements, or invisible. Which are space-preserving and which are not. And all that can be changed with CSS and attributes. So, such a feature would most likely be more often wrong than right.

ssokolow commented 2 years ago

It'd still be much easier to read than a minified blob. It doesn't have to be perfect... just analogous to something like the pretty_print=True option in Python modules like LXML and json.

ZaneHannanAU commented 2 years ago

Unfortunately, semantically html is significantly different to XML (data pure) and json (data pure). HTML is intended for display, and so has features which make it not as nice for unminified blobs.

I'd recommend the chrome dev tools for this btw.

ssokolow commented 2 years ago

Unfortunately, semantically html is significantly different to XML (data pure) and json (data pure). HTML is intended for display, and so has features which make it not as nice for unminified blobs.

Please elaborate. If markup.rs can't do at least as good a job as saving the HTML to disk and asking Vim to reindent (which is the slower, more annoying thing I currently do when I want to see it without JavaScript having meddled with it), I'll be very surprised. It's not as if Vim has a special HTML LSP that it calls out to.

ZaneHannanAU commented 2 years ago

In html, whitespace is somewhat important. pre, code, and other inline elements will be noticeably affected.

At best, it'd be a debug feature that requires an opt-in per-use.

ssokolow commented 2 years ago

In html, whitespace is somewhat important. pre, code, and other inline elements will be noticeably affected.

True... however I was imagining two things which would simplify it compared to other solutions:

  1. Assume default CSS whitespace rules are unaltered. If the feature is enabled, altered whitespace rules are out of scope.
  2. We don't need to parse and then re-generate. Haml-like syntax makes it simpler.

At best, it'd be a debug feature that requires an opt-in per-use.

When I said "(via feature flag?)", I should have been more clear that I always intended it to be optional... I just wasn't sure whether to propose it as a feature flag or runtime option.