Template Syntax

Caspian uses a Stack-Based Parser (Lexer) to render HTML. This ensures robust handling of deeply nested components, complex attribute logic, and dynamic expressions without the fragility of Regex.

Dynamic Expressions

Inject Python variables directly into your HTML using double square brackets [[ ]]. The parser strictly respects boundaries, allowing for complex logic and Python-style negation inside attributes.

index.html
<span> [[ user.name ]] </span>

<!-- Python Negation & Expressions -->
<div class="[[ 'hidden' if not is_visible else 'block' ]]">
  Conditional Visibility
</div>

Control Flow

Use the <template> tag with casp-* directives. Unlike regex-based engines, Caspian's stack parser handles infinite nesting of loops and conditionals correctly by tracking the opening and closing of tags in a stack.

Supported Directives

casp-for

Iterate over lists or dicts.

casp-if

Conditional rendering (fully supports not negation).

casp-elif

Else-If logic for complex branching.

casp-else

Fallback rendering when conditions aren't met.

Example: Negation & Nested Loops
<template casp-if="not user.is_authenticated">
  <button>Login</button>
</template>

<template casp-for="category in categories">
  <h3>[[ category.name ]]</h3>
  <template casp-for="item in category.items">
    <template casp-if="item.is_active">
      <span>[[ item.name ]]</span>
    </template>
  </template>
</template>

Under the Hood

Caspian transpiles semantic HTML tags into high-performance Jinja2 blocks. This allows you to maintain clean HTML while leveraging Python's full power. The CaspianParser converts [[ ]] to variable placeholders and <template> directives to block delimiters.

Caspian Syntax
<template casp-if="user.admin">
  <p>Access Denied</p>
</template>
Jinja2 Transpilation
[% if user.admin %]
  <p>Access Denied</p>
[% endif %]
Caspian Syntax
<template casp-if="not user.admin">
  <p>Access Denied</p>
</template>
Jinja2 Transpilation
[% if not user.admin %]
  <p>Access Denied</p>
[% endif %]
Caspian Syntax
<template casp-for="post in posts">
  <h1>[[ post.title ]]</h1>
</template>
Jinja2 Transpilation
[% for post in posts %]
  <h1>[[ post.title ]]</h1>
[% endfor %]

Smart Attributes

Caspian automatically normalizes attributes through html_attrs.py. You can use React-style camelCase props, and they will be converted to valid HTML kebab-case automatically.

Input (Python/JSX) Output (HTML)
className="foo" class="foo"
htmlFor="id" for="id"
dataTestId="123" data-test-id="123"
isDisabled={True} disabled="true"