User Rating 0.0
Total Usage 0 times
HTML Input
Jade Output
Is this tool helpful?

Your feedback helps us improve.

About

Jade (now Pug) eliminates closing tags, angle brackets, and attribute quoting through whitespace-significant syntax. Manual conversion introduces indentation errors that silently break template rendering. A single misplaced indent shifts an element's parent, changing DOM structure without any compiler warning. This tool parses raw HTML into an abstract syntax tree, then emits correct Jade output with consistent 2-space indentation. It preserves Meteor Handlebars block helpers ({{#if}}, {{#each}}, {{else}}, {{/if}}) as Jade mixin-style blocks, maintaining logical nesting that hand-conversion frequently corrupts.

The converter handles void elements (br, hr, img, input), boolean attributes, inline text vs. block text, class/id shorthand extraction, and multi-attribute formatting. It does not validate your HTML. Malformed input (unclosed tags, overlapping elements) produces best-effort output. For production Meteor templates, always verify the converted Jade renders identically in your Blaze engine before deploying.

html to jade html to pug jade converter meteor handlebars html2jade pug converter template converter

Formulas

The converter operates as a three-stage pipeline: Tokenize, Parse, Emit.

tokenize(HTML) tokens[] parse(tokens) AST emit(AST, depth) Jade

Indentation at each depth level is computed as:

indent = repeat(" ", depth × 2)

Where depth = 0 for root elements and increments by 1 for each nested child. Class shorthand extraction follows the pattern: if a tag has class and/or id attributes, they are extracted into dot/hash notation and removed from the attribute list. The remaining attributes are formatted as comma-separated key="value" pairs inside parentheses.

Handlebars block detection uses the regex pattern:

blockOpen = match(/\{\{#(\w+)\s*(.*?)\}\}/)
blockClose = match(/\{\{\/(\w+)\}\}/)

Where blockOpen captures the helper name and its arguments. The parser pushes a block node onto the stack, collects children until the matching blockClose, and pops. An {{else}} token splits the block's children into a consequent array and an alternate array.

Reference Data

HTML SyntaxJade/Pug EquivalentNotes
<div></div>divPlain tag, no closing needed
<div class="box">div.boxClass shorthand with dot notation
<div id="main">div#mainID shorthand with hash notation
<div id="app" class="container wide">div#app.container.wideCombined ID and multiple classes
<input type="text" required>input(type="text", required)Attributes in parentheses, boolean attrs
<a href="/">Home</a>a(href="/") HomeInline text after tag
<p>Line 1<br>Line 2</p>p
| Line 1
br
| Line 2
Mixed content uses pipe for text
<!-- comment -->// commentJade comment syntax
<!DOCTYPE html>doctype htmlDoctype declaration
{{#if isAdmin}}+if isAdminMeteor Handlebars block open
{{else}}+elseHandlebars else branch
{{/if}}(indentation closes block)No explicit close in Jade
{{#each items}}+each itemsHandlebars each loop
{{title}}= title or #{title}Expression interpolation
{{> header}}+headerPartial inclusion
<div class="a"><span>X</span></div>div.a
span X
2-space nested indentation
<img src="x.png" alt="">img(src="x.png", alt="")Self-closing / void element
<script>...</script>script.
(content indented)
Dot suffix for raw block content
<style>...</style>style.
(content indented)
Dot suffix for raw block content

Frequently Asked Questions

The tokenizer recognizes Handlebars block openers ({{#helper args}}), closers ({{/helper}}), else branches ({{else}}), partials ({{> name}}), and value expressions ({{value}}). Block openers become +helper args in Jade with their enclosed content indented as children. {{else}} creates a sibling +else node at the same indentation level. Simple {{value}} expressions inside text are converted to #{value} interpolation or standalone = value lines depending on context.
The parser uses a best-effort strategy. Unclosed tags are implicitly closed at the end of their parent scope or the document. Overlapping tags (like ) are resolved by closing the inner tag first. The output will be syntactically valid Jade but may not match the original browser rendering of the malformed HTML. Always compare rendered output in your target engine.
Yes. When a parent element contains both text and child elements (mixed content), the converter uses Jade pipe syntax (| text) for text nodes and normal indented tags for element nodes. For example,

Hello world!

becomes p with children | Hello, strong world, and | ! each on separate indented lines.
Jade's design philosophy uses .className and #idName as shorthand because class and id are the most commonly used attributes. This shorthand only works on the tag declaration line. All other attributes (href, src, data-*, aria-*, style, boolean attributes like required or disabled) must appear in parentheses. The converter extracts class and id automatically and formats remaining attributes as comma-separated key="value" pairs.
Tags like and that contain raw text content (not child elements) use Jade's dot-block syntax. The tag is followed by a period (script. or style.) and the content is placed on subsequent lines indented by 2 spaces. This tells the Jade compiler to treat the block as raw text rather than trying to parse it as Jade syntax.
All 16 HTML5 void elements (area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr, command, keygen) are recognized and rendered without closing tags. Boolean attributes (required, disabled, checked, readonly, autofocus, etc.) are emitted without values: input(type="text", required) rather than input(type="text", required="required").