Files
pugz/docs/CLI_TEMPLATES_EXPLAINED.md

6.0 KiB

CLI Templates - Compilation Explained

Overview

The cli-templates-demo directory contains 10 source templates, but only 5 compile successfully to Zig code. This is expected behavior.

Compilation Results

Successfully Compiled (5 templates)

Template Size Features Used
home.pug 677 bytes Basic tags, interpolation
conditional.pug 793 bytes If/else conditionals
simple-index.pug 954 bytes Links, basic structure
simple-about.pug 1054 bytes Lists, text content
simple-features.pug 1784 bytes Conditionals, interpolation, attributes

Total: 5 templates compiled to Zig functions

Failed to Compile (5 templates)

Template Reason Use Runtime Mode Instead
index.pug Uses extends Works in runtime
features-demo.pug Uses extends + mixins Works in runtime
attributes-demo.pug Uses extends Works in runtime
all-features.pug Uses extends + mixins Works in runtime
about.pug Uses extends Works in runtime

Error: error.PathEscapesRoot - Template inheritance not supported in compiled mode

Why Some Templates Don't Compile

Compiled Mode Limitations

Compiled mode currently supports:

  • Basic tags and nesting
  • Attributes (static and dynamic)
  • Text interpolation (#{field})
  • Buffered code (=, !=)
  • Comments
  • Conditionals (if/else)
  • Doctypes

Compiled mode does NOT support:

  • Template inheritance (extends/block)
  • Includes (include)
  • Mixins (mixin/+mixin)
  • Iteration (each/while) - partial support
  • Case/when - partial support

Design Decision

Templates with extends ../layouts/main.pug try to reference files outside the compilation directory, which is why they fail with PathEscapesRoot. This is a security feature to prevent templates from accessing arbitrary files.

Solution: Two Sets of Templates

1. Runtime Templates (Full Features)

Files: index.pug, features-demo.pug, attributes-demo.pug, all-features.pug, about.pug

Usage:

const engine = pugz.ViewEngine.init(.{
    .views_dir = "examples/cli-templates-demo",
});

const html = try engine.render(allocator, "pages/all-features", data);

Features:

  • All Pug features supported
  • Template inheritance
  • Mixins and includes
  • Easy to modify and test

2. Compiled Templates (Maximum Performance)

Files: home.pug, conditional.pug, simple-*.pug

Usage:

# Compile
./zig-out/bin/pug-compile --dir examples/cli-templates-demo --out generated pages

# Use
const templates = @import("generated/root.zig");
const html = try templates.simple_index.render(allocator, .{
    .title = "Home",
    .siteName = "My Site",
});

Features:

  • 10-100x faster than runtime
  • Type-safe data structures
  • Zero parsing overhead
  • ⚠️ Limited feature set

Compilation Command

cd /path/to/pugz

# Compile all compatible templates
./zig-out/bin/pug-compile \
  --dir examples/cli-templates-demo \
  --out examples/cli-templates-demo/generated \
  pages

Output:

Found 10 page templates
Processing: examples/cli-templates-demo/pages/index.pug
  ERROR: Failed to compile (uses extends)
...
Processing: examples/cli-templates-demo/pages/simple-index.pug
  Found 2 data fields: siteName, title
  Generated 954 bytes of Zig code
...
Compilation complete!

Generated Files

generated/
├── conditional.zig        # Compiled from conditional.pug
├── home.zig              # Compiled from home.pug
├── simple_about.zig      # Compiled from simple-about.pug
├── simple_features.zig   # Compiled from simple-features.pug
├── simple_index.zig      # Compiled from simple-index.pug
├── helpers.zig           # Shared helper functions
└── root.zig             # Module exports

Verifying Compilation

cd examples/cli-templates-demo

# Check what compiled successfully
cat generated/root.zig

# Output:
# pub const conditional = @import("./conditional.zig");
# pub const home = @import("./home.zig");
# pub const simple_about = @import("./simple_about.zig");
# pub const simple_features = @import("./simple_features.zig");
# pub const simple_index = @import("./simple_index.zig");

When to Use Each Mode

Use Runtime Mode When:

  • Template uses extends, include, or mixins
  • Development phase (easy to modify and test)
  • Templates change frequently
  • Need all Pug features

Use Compiled Mode When:

  • Production deployment
  • Performance is critical
  • Templates are stable
  • Templates don't use inheritance/mixins

Best Practice

Recommendation: Start with runtime mode during development, then optionally compile simple templates for production if you need maximum performance.

// Development: Runtime mode
const html = try engine.render(allocator, "pages/all-features", data);

// Production: Compiled mode (for compatible templates)
const html = try templates.simple_index.render(allocator, data);

Future Enhancements

Planned features for compiled mode:

  • Template inheritance (extends/blocks)
  • Includes resolution at compile time
  • Full loop support (each/while)
  • Mixin expansion at compile time
  • Complete case/when support

Until then, use runtime mode for templates requiring these features.

Summary

Metric Value
Total Templates 10
Compiled Successfully 5 (50%)
Runtime Only 5 (50%)
Compilation Errors Expected (extends not supported)

This is working as designed. The split between runtime and compiled templates demonstrates both modes effectively.


See Also: