Skip to content

KTBsomen/httl-s

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HTTL-S

HyperText Templating Language (Simple)

A lightweight client-side templating framework for building dynamic HTML pages without build tools or Node.js.

Features

  • For Loops - Iterate over arrays directly in HTML
  • Data Loops - Special loop for table rows (works in <tbody>)
  • Nested If-Else - Full support for deeply nested conditionals
  • State Elements - Simple reactive value display
  • Template Includes - Import HTML as reusable components with CSS isolation
  • State Watching - Auto-update UI when variables change
  • TypeScript Support - IntelliSense via .d.ts file
  • VS Code Support - Snippets and HTML custom data

Documentation

Read the full documentation here: https://ktbsomen.github.io/httl-s/


License CDN

Installation

Step 1: Include the script

<script src="https://cdn.jsdelivr.net/gh/KTBsomen/httl-s@main/statejs.js"></script>

Step 2: Set up watched variables

// Create reactive variables that trigger UI updates
watch('myVar', (propName, value) => {
  setState({ /* options */ });
}, initialValue);

Step 3: Initialize (LAST!)

// Call this AFTER all watch() calls and DOM setup
initState();

⚠️ Important: initState() must be called last, after all variables are set up.


Quick Reference

Syntax Purpose Example
{{expression}} Evaluate JS expression {{userName}}
${expression} Loop variable access ${item.name}
watch(name, cb, init) Create reactive variable watch('count', cb, 0)
setState(options) Update UI components setState({ loops: true })
initState() Initialize framework initState()

Custom Elements

1. For Loop (<for-loop>)

Iterate over an array and render content for each item.

<for-loop array="fruits" valueVar="fruit" indexVar="i" loopid="fruitList">
  <template loopid="fruitList">
    <p>${i + 1}. ${fruit}</p>
  </template>
</for-loop>

Attributes:

Attribute Required Description
array Yes Array variable name
loopid Yes Unique ID (must match template)
valueVar No Variable name for item (default: value)
indexVar No Variable name for index (default: index)
start No Start index (default: 0)
end No End index (default: array.length)
step No Step increment (default: 1)

2. Data Loop (data-loop attribute)

Use for table rows - custom elements can't be placed inside <tbody>.

<table>
  <thead>
    <tr><th>Name</th><th>Price</th></tr>
  </thead>
  <tbody data-loop="products" data-template="#rowTemplate" data-value="item" data-index="i">
  </tbody>
</table>

<!-- Template MUST be outside the table -->
<template id="rowTemplate">
  <tr>
    <td>${item.name}</td>
    <td>$${item.price}</td>
  </tr>
</template>

Attributes:

Attribute Required Description
data-loop Yes Array variable name
data-template Yes CSS selector for template
data-value No Variable name for item
data-index No Variable name for index

3. Condition Block (<condition-block>)

Container for if-else conditional rendering.

<condition-block ifid="loginCheck">
  <template ifid="loginCheck">
    <if-condition value="isLoggedIn" eq="true" elseid="notLoggedIn">
      <p>Welcome back!</p>
    </if-condition>
    <else-condition elseid="notLoggedIn">
      <p>Please log in</p>
    </else-condition>
  </template>
</condition-block>

Comparison Operators:

Operator Description Example
eq Equals (===) eq="true"
neq Not equals (!==) neq="'error'"
gt Greater than gt="10"
lt Less than lt="0"
gte Greater or equal gte="18"
lte Less or equal lte="100"
(none) Truthy check value="hasItems"

4. Nested Conditions

Fully supports if-else chains inside else blocks:

<condition-block ifid="check">
  <template ifid="check">
    <if-condition value="a && b" eq="true" elseid="onlyA">
      <p>Both A and B</p>
    </if-condition>
    <else-condition elseid="onlyA">
      <if-condition value="a" eq="true" elseid="onlyB">
        <p>Only A</p>
      </if-condition>
      <else-condition elseid="onlyB">
        <if-condition value="b" eq="true" elseid="neither">
          <p>Only B</p>
        </if-condition>
        <else-condition elseid="neither">
          <p>Neither</p>
        </else-condition>
      </else-condition>
    </else-condition>
  </template>
</condition-block>

5. State Element (<state-element>)

Simple reactive display for state values.

<state-element stateId="counter">
  <template stateId="counter">
    <span>Count: {{count}}</span>
  </template>
</state-element>

6. Include Template (<include-template>)

Import external HTML files as reusable components.

<!-- CSS is scoped by default (Shadow DOM) -->
<include-template file="components/header.html"></include-template>

<!-- Use global styles (no isolation) -->
<include-template file="components/footer.html" scoped="false"></include-template>

Attributes:

Attribute Default Description
file Required Path to HTML file
scoped true true: CSS isolated, false: global

JavaScript API

watch(name, callback, defaultValue)

Creates a reactive global variable.

watch('inventory', (name, value) => {
  setState({ dataloops: true, conditions: true });
}, []);

// Now you can use: inventory = [...inventory, newItem];

setState(options)

Updates UI by re-rendering components.

// Update everything
setState();

// Update specific component by ID
setState({ loopid: 'myLoop' });
setState({ ifid: 'myCondition' });
setState({ stateId: 'myState' });

// Control what updates
setState({
  showloader: false,    // Don't show loading spinner
  loops: true,          // Update for-loop elements
  dataloops: true,      // Update data-loop elements
  conditions: true,     // Update condition-block elements
  states: true,         // Update state-element elements
  templates: false,     // Update include-template elements
  innerhtml: true,      // Update data-innerhtml elements
  datajs: true          // Execute data-js attributes
});

unsafeEval(expression, context)

Safely evaluate a JavaScript expression.

const result = unsafeEval('a + b', { a: 1, b: 2 }); // 3

parseTemplate(string)

Parse {{}} expressions in a string.

const html = parseTemplate('<p>Hello {{name}}</p>');

createRangeArray(start, end, step)

Create an array of numbers.

createRangeArray(1, 5);       // [1, 2, 3, 4, 5]
createRangeArray(0, 10, 2);   // [0, 2, 4, 6, 8, 10]

renderDataLoops()

Manually render all data-loop elements.

renderDataLoops();

parseURL(url?, global?)

Parse URL and extract components.

parseURL(); // Parses current URL
console.log(UrlDetails.params.id); // Access query params

loader

Loading spinner utility.

loader.show();                    // Show default spinner
loader.show('<div>Loading...</div>'); // Custom HTML
loader.hide();                    // Hide spinner

Data Attributes

Attribute Description
data-innerhtml="expr" Set element's innerHTML to expression result
data-js="code" Execute JavaScript on setState
<span data-innerhtml="items.length"></span>
<div data-js="this.style.color = count > 10 ? 'red' : 'green'"></div>

TypeScript / IntelliSense

For JS files

Download statejs.d.ts and reference locally:

/// <reference path="./statejs.d.ts" />

For HTML files (VS Code)

Copy .vscode/httls.html-data.json to your project and add to .vscode/settings.json:

{
  "html.customData": ["./.vscode/httls.html-data.json"]
}

Examples

See the example/ folder:

  • index.html - Inventory management app
  • test-nested-conditions.html - Nested if-else demos
  • test-table-rendering.html - Table with data-loop

Browser Support

Modern browsers with:

  • Custom Elements (Web Components)
  • ES6+ (template literals, arrow functions)

Security, CSP & Usage Guidelines

HTTL-S (HyperText Templating Language – Simple) is a lightweight client-side templating framework that evaluates JavaScript expressions directly in HTML templates.
This design choice enables flexibility and a small footprint, but it also comes with important security and CSP implications.


Security Notice (Read Carefully)

HTTL-S evaluates JavaScript expressions at runtime using new Function().

This means:

  • HTTL-S MUST NOT be used on unsanitized or user-generated HTML
  • HTTL-S MUST NOT process HTML coming from users, databases, CMS, or third-party sources without proper sanitization
  • HTTL-S is NOT safe against XSS when used on untrusted content

If your application renders user-submitted HTML, do not mount HTTL-S on those DOM regions.

HTTL-S is designed for developer-controlled templates only.


Content Security Policy (CSP)

HTTL-S uses new Function() for expression evaluation.

Because of this:

  • HTTL-S requires unsafe-eval in CSP
  • HTTL-S does NOT work with strict CSP policies
  • There is no CSP-safe build at the moment

Example CSP required:

Content-Security-Policy:
  script-src 'self' 'unsafe-eval';

Recommended For

  • Internal tools, dashboards, prototypes
  • Static or developer-authored templates
  • Projects without strict CSP requirements

Not Recommended For

  • Unsanitized user-generated content
  • Public apps with untrusted HTML
  • Security-critical or strict CSP environments

Future Improvements

  • Explicit mount targets
  • Safer expression evaluation mode
  • Deprecate data-js
  • Optional HTML sanitization
  • CSP-friendly build

License

Licensed under the Apache License, Version 2.0.
See the LICENSE file for details.

This library is safe to use via CDN and npm under Apache-2.0.

Copyright

Copyright © 2026 Somen Das

Releases

No releases published

Packages