# Skill: Convert HTML to Waltzing Template

You are converting static HTML into a Waltzing template.

## Conversion Steps

### 1. Identify Dynamic Parts

Look for:
- Text that should be variables
- Repeated elements (lists, grids)
- Conditional elements (show/hide based on state)
- Data attributes with values

### 2. Add Parameters

Create a function with typed parameters:

**Before (HTML):**
```html
<h1>Welcome, John</h1>
<p>You have 5 messages</p>
```

**After (Waltzing):**
```waltzing
@fn apply(name: String, message_count: u32) {
    <h1>Welcome, @name</h1>
    <p>You have @message_count messages</p>
}
```

### 3. Convert Loops

**Before:**
```html
<ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>
```

**After:**
```waltzing
@fn apply(items: Vec<String>) {
    <ul>
        @for item in items {
            <li>@item</li>
        }
    </ul>
}
```

### 4. Convert Conditionals

**Before:**
```html
<div class="alert alert-error" style="display: none;">
    Error message here
</div>
```

**After:**
```waltzing
@fn apply(error: Option<String>) {
    @if let Some(msg) = error {
        <div class="alert alert-error">
            @msg
        </div>
    }
}
```

### 5. Convert Dynamic Attributes

**Before:**
```html
<button class="btn btn-primary" disabled>Submit</button>
```

**After:**
```waltzing
@fn apply(variant: String, disabled: bool, label: String) {
    <button
        class="btn btn-@variant"
        @if disabled { disabled }
    >
        @label
    </button>
}
```

### 6. Convert Alpine.js

**Before:**
```html
<div x-data="{ count: 0 }">
    <button @click="count++">Increment</button>
    <span x-text="count"></span>
</div>
```

**After:**
```waltzing
@fn apply(initial_count: i32) {
    <div x-data=@```json {
        count: @initial_count,
        increment() { this.count++ }
    } ```@>
        <button @click="increment">Increment</button>
        <span x-text="count"></span>
    </div>
}
```

### 7. Extract Components

If you see repeated patterns, extract them:

**Before:**
```html
<div class="card">
    <h3>Card 1</h3>
    <p>Content 1</p>
</div>
<div class="card">
    <h3>Card 2</h3>
    <p>Content 2</p>
</div>
```

**After (card.wtz):**
```waltzing
@fn apply(title: String, content: Content) {
    <div class="card">
        <h3>@title</h3>
        @content
    </div>
}
```

**After (page.wtz):**
```waltzing
@import "components/card.wtz" as card

@fn apply(cards: Vec<CardData>) {
    @for c in cards {
        <@card title=@c.title>
            <p>@c.content</p>
        </@>
    }
}
```

### 8. Convert Script Blocks with Comments

**Before:**
```html
<script>
    // Initialize theme
    if (localStorage.theme === 'dark') {
        document.documentElement.classList.add('dark');
    }
</script>
```

**After:**
```waltzing
<script>
    @* Initialize theme - this comment is stripped from output *@
    if (localStorage.theme === 'dark') {
        document.documentElement.classList.add('dark');
    }
</script>
```

### 9. Convert Style Blocks

**Before:**
```html
<style>
    /* Theme colors */
    :root {
        --primary: #3b82f6;
    }
</style>
```

**After (with dynamic values):**
```waltzing
<style>
@```css
@* Theme colors *@
:root {
    --primary: @theme.primary;
}

@for color in brand_colors {
    .color-@color.name { background: @color.value; }
}
```@
</style>
```

## Critical: Dynamic Attribute Values

**Do NOT put quotes around expressions in attributes.** This is the #1 mistake.

```waltzing
@* ❌ WRONG - quotes make it literal text, NOT evaluated *@
<div
    class="@cn(&[base, variant])"
    aria-expanded="@match state { Open => "true", Closed => "false" }"
/>
@* Output: class="@cn(&[base, variant])" - literal text! *@

@* ✅ CORRECT - no quotes, expression is evaluated *@
<div
    class=@cn(&[base, variant])
    aria-expanded=@match state { Open => "true", Closed => "false" }
/>
@* Output: class="btn primary" aria-expanded="true" *@
```

**Rule:**
- `attr="literal"` → literal string value
- `attr=@expression` → evaluated expression (no quotes!)
- `attr="prefix @var suffix"` → interpolation (quotes OK)

## Common Conversions

| HTML/Other | Waltzing |
|------------|----------|
| `{{ var }}` | `@var` |
| `{% if %}` | `@if cond { }` |
| `{% for %}` | `@for item in list { }` |
| `{# comment #}` | `@* comment *@` |
| `{{ var\|safe }}` | `@safe(var)` |
| `{{ var\|escape }}` | `@var` (default) |
| `{% include %}` | `<@component />` |
| `{% extends %}` | `@import` + `<@layout>` |

## Use Apply Shorthand

When using imported templates, prefer the shorthand:

```waltzing
@* Instead of: *@
<@layout::apply title="Home">content</@layout::apply>

@* Use: *@
<@layout title="Home">content</@layout>
```

## Built-in Helpers

Waltzing has 40+ helpers for common formatting tasks. Use them instead of custom logic:

```waltzing
@* Replace custom class logic with cn() *@
<div class="@cn(&["btn", "btn-primary", if active { "active" } else { "" }])">

@* Text formatting *@
@truncate(&text, 100)        @* Truncate with "..." *@
@slugify(&title)             @* URL-safe slug *@
@capitalize(&name)           @* First letter uppercase *@

@* Numbers & currency *@
@number(count)               @* 1234567 -> "1,234,567" *@
@currency(price, "USD")      @* "$1,234.50" *@
@percent(0.15)               @* "15%" *@
@bytes(file_size)            @* "1.5 MB" *@
@ordinal(position)           @* "1st", "2nd" *@

@* Pluralization *@
@pluralize(count, "item")    @* "1 item" / "5 items" *@

@* Conditional attributes *@
@class_if(selected, "selected")
@class_toggle(dark, "dark", "light")
@aria_if(expanded, "expanded", "true")

@* Time *@
@relative_time(secs)         @* "2 hours ago" *@

@* Unique IDs for form labels *@
@let id = unique_id("input")
<label for="@id">Name</label>
<input id="@id" />
```

**Categories:** security, text (15 helpers), numbers (6), formatting (5), pluralization (3), html-css (9), defaults (2), time (2)
