diff --git a/README.md b/README.md new file mode 100644 index 0000000..58e24ea --- /dev/null +++ b/README.md @@ -0,0 +1,205 @@ +# mojofmt + +Formatter for Mojolicious Embedded Perl templates (.ep, .htm.ep, .html.ep) + +mojofmt formats HTML and Mojolicious EP templates without breaking embedded Perl. It understands line directives (% ...), inline tags (<% ... %>), raw HTML blocks, and can reformat multi-line Perl blocks inside <% ... %> using perltidy (with a safe fallback if perltidy isn’t available). + +## Features + +- Indents HTML structure and Mojolicious line directives consistently +- Preserves chomp markers (<%- ... -%>) and does not alter newline semantics +- Formats inline EP tags: + - <%= ... %> expressions (keeps them single-line) + - <% ... %> one-line statements +- Re-formats extended multi-line Perl blocks between lines with only <% and %> (or chomped variants), using perltidy or a naive brace-aware indenter +- Treats pre/script/style/textarea content as opaque (unchanged) +- Optional spacing normalization inside <% %> delimiters +- Optional aggressive spacing after common Perl keywords (--perl-keyword-spacing) +- End-of-line normalization (lf, crlf, or preserve) +- CLI with --write, --check, --diff, --out, --stdin/--stdout +- Self-test mode to sanity-check behavior and perltidy availability + +## Requirements + +- Python 3.8+ (3.11+ recommended) +- Optional but recommended: perltidy (Perl::Tidy) + - Debian/Ubuntu: apt-get install perltidy + - CPAN: cpanm Perl::Tidy + - mojofmt will fall back to a simple brace-based indenter for extended blocks if perltidy is absent or fails + +## Install + +- Clone this repository +- Make the script executable and put it on your PATH, or run it in place + +``` +chmod +x mojofmt.py +./mojofmt.py --version +``` + +## Usage + +Basic formatting to stdout: +- ./mojofmt.py path/to/template.html.ep +- cat file.ep | ./mojofmt.py --stdin --stdout + +Write changes in place (creates a .bak backup): +- ./mojofmt.py -w templates/ + +Check mode (exit 1 if any file would change): +- ./mojofmt.py --check templates/ + +Show a diff: +- ./mojofmt.py --diff path/to/file.ep + +Write output to a separate file: +- ./mojofmt.py -o formatted.ep path/to/file.ep +- cat file.ep | ./mojofmt.py --stdin -o formatted.ep + +Control indentation (spaces per level): +- ./mojofmt.py --indent 4 file.ep + +Normalize EOLs: +- ./mojofmt.py --eol lf file.ep +- ./mojofmt.py --eol crlf file.ep +- ./mojofmt.py --eol preserve file.ep + +Perl spacing knobs: +- Add spacing after common Perl keywords: ./mojofmt.py --perl-keyword-spacing file.ep +- Pass a specific perltidy binary: ./mojofmt.py --perltidy /usr/bin/perltidy file.ep +- See perltidy status: ./mojofmt.py --self-test + +Increase logging: +- ./mojofmt.py --log-level debug file.ep +- ./mojofmt.py --verbose file.ep (shorthand for info) + +## How it works + +- HTML indentation: + - Tracks opening/closing tags; avoids indenting void/self-closing tags + - pre/script/style/textarea bodies are untouched +- Mojolicious directives: + - Lines starting with % are indented relative to HTML and Perl block depth + - begin/end and { ... } braces adjust indentation depth +- Inline EP tags on a line: + - <%= ... %> expressions are normalized via perltidy in an expression-safe wrapper + - <% ... %> one-line statements are normalized via perltidy (or left as-is if perltidy is missing) + - Optional normalization of spaces inside <% %> delimiters can be disabled with --no-space-in-delims +- Extended multi-line Perl blocks: + - Detected when <% (or <%-) is on a line by itself, and %> (or -%>) is on a line by itself + - The inner Perl is dedented, wrapped in do { ... } and run through perltidy; if that fails or perltidy is missing, a brace-aware fallback indenter is used + - Inner lines are re-indented to match the opening/closing delimiter’s indentation +- EOL normalization: + - Input CRLF/CR are normalized internally; output can be forced to lf/crlf or preserve the original + +## Examples + +Before: +``` +