🧱 HTML Blocks

In Mustela, HTML blocks are where raw data meets design. While Markdown handles your content, HTML blocks define the structure and logic of your site.

💡 Pro Tip

Variables (prefixed with @) cannot be rendered directly in raw Markdown. For the system to know it should replace @author with an actual name, the code must be wrapped inside an HTML block.

1. The Two Types of HTML Blocks

Mustela recognizes two ways to define HTML, each serving a different purpose in your workflow.

1.1 Direct Injection (html do)

The standard html do block is used directly inside your .md files. It acts as a portal that allows you to use variables and custom tags right in the middle of your content.

article.md
html do
<div class="author-card">
  <p>Written by: <strong>@author</strong></p>
</div>
end

1.2 Named Templates (html as <name> do)

Named blocks are the building blocks of your theme. Once defined (usually in your templates/ folder), they can be summoned anywhere using the @html[name] syntax.

layout.mu
html as footer do
<footer class="site-footer">
  <p>&copy; @current_year @title</p>
</footer>
end

1.3 Local Template Definitions (Testing Only)

While named blocks (html as name do) are typically defined in your template files, Mustela allows you to define them directly inside a Markdown file.

⚠️ However, this is strongly discouraged for production use.

Defining templates inside Markdown is intended strictly for rapid prototyping and testing. It allows you to experiment with a new component's logic without jumping between directories.

CLI Warnings

Mustela's engine prioritizes clarity. If you define a named block within a Markdown file, the CLI will issue a warning during the build process:

10:23:32 AM [mustela] TRANSLATE | ./content/doc/html-blocks.md
[WARNING] Local template "pro_tip_start" defined in Markdown (doc/html-blocks.md).

Why you should avoid this:

  • Global Namespace Pollution: You might accidentally overwrite a global template, leading to inconsistent behavior across your site.
  • Maintenance Debt: Logic hidden inside content files is hard to find and update later.
  • Architectural Purity: Keep your design in templates/ and your stories in content/.
  • Recommendation: Once your locally defined block works exactly how you want, move its definition to your global template files and remove it from the Markdown.

1.4 The Magic @view Variable

The @view variable is a special, engine-reserved constant. It acts as the ultimate placeholder where your transpiled Markdown content is injected into the HTML structure. Without @view, your templates would be empty shells.

How it works:

  • Mustela converts your Markdown into a "clean" HTML string in RAM.
  • It looks for the @view placeholder in your entry-point template (defined by index).
  • It injects the content directly into that spot.

Practical Usage:

Typically, you will place @view inside your main body block:

main.mu
html as body do
<body>
  @html[navigation]
  <main class="content-wrapper">
    @view  <!-- Your Markdown article appears here -->
  </main>
  @html[footer]
</body>
end

Multi-Block Power:

You can call @view inside any number of different HTML blocks. This is useful when you need to render the same content into different parts of your layout (e.g., a desktop view, a mobile-specific container, or a specialized SEO-only block).

responsive.mu
html as desktop_layout do
  <div class="desktop">@view</div>
end
html as mobile_layout do <div class="mobile">@view</div> end

Important Restrictions:

  • Context Only: @view is only available within HTML blocks.
  • Immutable: You cannot overwrite the value of @view in your meta or config blocks. It is strictly managed by the Mustela engine.
  • Recursion: You can pass @view into other named blocks, but it still counts towards the 20-level recursion limit.

2. The "Sandwich" Pattern (Structural Wrappers)

Because Mustela processes files as a continuous data stream, you can split a single HTML element across two blocks. This allows you to "wrap" standard Markdown content inside complex HTML structures.

Example:

snippets.mu
html as callout_start do
<div class="custom-callout" style="border-left: 4px solid @accent_color;">
  <div class="callout-inner">
end
html as callout_end do </div> </div> end
article.md
html do
@html[callout_start]
end
**This is Markdown!** Even though it's physically between two HTML calls, Mustela renders it perfectly because the stream remains open.
html do @html[callout_end] end

3. Variable Injection

HTML blocks are the only place where variables are resolved. As defined in the Metadata Reference, Mustela pulls values from local meta, global config, or system constants.

Key Rule: Within an HTML block, any string starting with @ is treated as a potential variable and will be swapped for its value during the Processing Stage.

4. Technical Guardrails

To maintain its extreme performance, Mustela’s HTML parser follows a few strict rules:

  • Line-Based Parsing: Each html do and end must reside on its own line.
  • Recursive Depth: You can nest @html[] calls, but the engine limits recursion to 20 levels to prevent infinite loops.
  • Zero Sanity Checks: Mustela trusts you. It will output exactly what you write. If you forget to close a <div> in a "sandwich", the engine won't stop you—giving you total control (and total responsibility).

5. Beyond HTML: Meta-Programming Power

Don't let the name fool you. While called "HTML Blocks", the engine treats them as agnostic text processors. Because Mustela doesn't sanitize your output, you can use these blocks to generate almost any text-based code.

5.1 JavaScript Constant Injection

You can "bake" metadata directly into your scripts at build-time. This is extremely powerful for creating secure, self-contained scripts for critical infrastructure where external API calls are forbidden.

scripts.mu
html as security_init do
const SYSTEM_CONFIG = {
    buildId: "@build_hash",
    origin: "@origin_node",
    timestamp: "@current_date"
};
end

5.2 Pure Logic vs. Visual Representation

The separation of blocks allows you to distinguish between what the user see and how the application behaves. By using blocks to inject variables into <script> tags, you eliminate the need for client-side fetching of static data.

example.md
html do
<script>
  console.log('Build by: @author');
</script>
end

Architectural Note: Mustela strictly separates content from logic. Keeping scripts within html blocks prevents the common "Markdown corruption" (where parsers interfere with JS syntax). This ensures your logic remains bit-perfect and fully debuggable in production.

6. Template Shadowing & Global Namespace

Mustela uses a single, flat global namespace for all named blocks. The engine does not isolate templates by file; once a block is defined, it is registered globally in RAM.

  • Last-In-Wins Strategy: If you define html as footer do in base.mu and then define it again in override.mu, the second definition will overwrite the first one for the remainder of the build.
  • Linear Execution: The engine processes files and blocks from top to bottom. A re-definition only affects calls that occur after the change. Anything already rendered to the output remains unchanged.
  • The Power of Shadowing: This isn't a bug; it's a feature for advanced users. It allows you to "shadow" global templates with specialized logic for specific parts of your project without touching the core files.
  • Architectural Guardrail: To prevent accidental overwrites, it is recommended to use unique prefixes (e.g., doc_footer, blog_footer) unless you are intentionally trying to hijack a global component.