Skip to content
This repository was archived by the owner on Jun 13, 2026. It is now read-only.

Temme inheritance

Oussama Essamadi edited this page Jun 13, 2026 · 4 revisions

Description

Temme (Emmet in reverse) is a lightweight JavaScript library for generating and composing HTML structures from plain JavaScript objects.

Instead of writing imperative DOM manipulation code or injecting raw HTML strings, you describe your UI as a hierarchy object and let Temme turn it into real DOM nodes. The library is especially useful when you want a clean, data-driven way to create markup, reuse structure, and compose elements programmatically.

Temme currently exposes a modern named-export API:

  • parse(hierarchy, target, endCallback?, nodeCallback?)
  • validate(hierarchy)

It also supports advanced composition features such as templates, references, inheritance, include/exclude ranges, and controlled child inheritance.


How does it work?

With Temme, building DOM trees is done by describing elements as JavaScript objects.

A hierarchy can define things like:

  • element name
  • id
  • classes
  • attributes
  • dataset values
  • content
  • child nodes
  • reusable templates
  • inheritance from other nodes or templates

Once the hierarchy is defined, you pass it to parse(...) along with a target HTML element. Temme validates the structure, sanitizes it, resolves references and inheritance rules, and finally renders the resulting DOM tree into the target.

In practice, this means you can model complex HTML structures in a way that is:

  • readable
  • composable
  • reusable
  • easy to serialize as JSON

In fact, the documentation website itself is generated with Temme.


Advantages

You might ask: why use this instead of plain DOM APIs or Emmet-style shorthand?

1. Structured, data-first authoring

While Emmet is optimized for fast shorthand expansion, Temme is optimized for working with structured JavaScript data. That makes it a better fit for programmatic DOM generation.

2. Cleaner than manual DOM manipulation

Temme removes a lot of repetitive low-level DOM code such as:

  • repeated document.createElement(...)
  • repeated appendChild(...)
  • repetitive attribute and class assignment
  • manual nesting logic

3. Safer and clearer than raw HTML injection

For many use cases, describing content as objects is easier to read and maintain than assembling large HTML strings manually.

4. Reuse through templates and references

Temme supports reusable templates and inheritance rules, which makes it easier to share structure and styling across multiple nodes without duplicating configuration.

5. JSON-friendly

Because Temme works with plain object hierarchies, its structures can be serialized to and from JSON easily. This makes it useful for configuration-driven rendering and data-based UI generation workflows.

6. Validation support

The current version includes validate(hierarchy), which lets you check whether a hierarchy is valid before rendering it.


Current API

parse(
  hierarchy: object,
  target: HTMLElement,
  endCallback?: (hierarchy: Hierarchy) => void | Promise<void>,
  nodeCallback?: (temmeId: string, hierarchy: Hierarchy) => void
): object;

validate(hierarchy: object): {
  valid: boolean;
  error: Error | null;
};

Build

Building Temme locally is straightforward. Run:

pnpm prod

That command will:

  • remove previous build artifacts from dist and build
  • build the distributable package with tsup
  • generate the browser-ready documentation bundle at docs/assets/js/lib/temme.js

Available scripts

Command Description
pnpm clean Deletes the dist and build folders.
pnpm build Builds the package outputs into dist using tsup.
pnpm dev Runs tsup in watch mode for development.
pnpm build:docs Builds the browser bundle used by the docs website.
pnpm prod Runs clean, build, and build:docs.
pnpm test Runs the unit test suite.
pnpm typecheck Runs TypeScript type checking without emitting files.
pnpm lint Runs the linter.
pnpm lint:fix Runs the linter and applies automatic fixes where possible.

Inheritance

Description

Inheritance is one of Temme’s main composition features. It allows one hierarchy object to reuse options from another object or template so you can reduce duplication and keep your hierarchy definitions concise.

Temme supports three inheritance patterns:

  • Object to Object: a rendered hierarchy object inherits from another rendered hierarchy object in a valid scope.
  • Object to Template: a rendered hierarchy object inherits from a template.
  • Template to Template: a template inherits from another template.

Templates are never rendered directly, which makes them ideal for reusable presets and shared definitions.

The primary inheritable options are:

  • attributes
  • childNodes
  • classes
  • content
  • dataset
  • id
  • name

Syntax

const hierarchy = {
  ref: "parent",
  childNodes: [
    {
      from: {
        ref: "parent"
      }
    }
  ]
};

A referencing hierarchy object uses the from option to describe what it inherits and how the inheritance should behave.

The from option supports:

  • ref: the referenced object or template
  • mode: inheritance mode (append or override)
  • include: inherit only specific options
  • exclude: ignore specific options
  • children: control whether inherited children are included and where they are placed

Object to Object inheritance

const hierarchy = {
  ref: "parent",
  attributes: { visible: true },
  classes: ["red", "blue"],
  childNodes: [
    {
      ref: "sibling",
      name: "h1",
      classes: ["yellow"],
      dataset: {
        id: 100,
        title: "Some title"
      },
      from: {
        ref: "parent"
      }
    },
    {
      name: "p",
      from: {
        ref: "sibling"
      }
    }
  ]
};

In this example:

  • the first child inherits from parent
  • the second child inherits from sibling
  • inherited values accumulate as references are resolved

Temme also normalizes inherited arrays such as classes by removing duplicates and sorting values.

Template to Template inheritance

const hierarchy = {
  templates: [
    {
      ref: "temp-1",
      classes: ["bold", "dup", "dup"]
    },
    {
      ref: "temp-2",
      from: {
        ref: "temp-1"
      },
      classes: ["orange", "dup"]
    }
  ],
  from: {
    ref: "temp-2"
  }
};

Here:

  • temp-2 inherits from temp-1
  • the root hierarchy inherits from temp-2
  • duplicate class values are removed during normalization

Templates can inherit from templates, but templates cannot reference non-template rendered objects.

Inheritance range

Temme lets you control inheritance scope through include and exclude.

Include only specific options

const hierarchy = {
  templates: [
    {
      ref: "temp-1",
      attributes: {
        visible: true,
        counter: 56
      },
      classes: ["some-class"],
      dataset: { id: 814 }
    }
  ],
  from: {
    ref: "temp-1",
    include: ["classes", "dataset"]
  }
};

This inherits only classes and dataset.

Exclude specific options

const hierarchy = {
  templates: [
    {
      ref: "temp-1",
      attributes: {
        visible: true,
        counter: 56
      },
      classes: ["some-class"],
      dataset: { id: 814 }
    }
  ],
  from: {
    ref: "temp-1",
    exclude: ["dataset"]
  }
};

This inherits everything except dataset.

include and exclude are mutually exclusive and should not be used together.

Children inheritance

Child inheritance is controlled through the children sub-option inside from.

const hierarchy = {
  childNodes: [
    {
      ref: "list",
      name: "ul",
      childNodes: [
        { name: "li" },
        { name: "li" }
      ]
    },
    {
      from: {
        ref: "list",
        children: {
          allow: true
        }
      },
      childNodes: [
        {
          name: "span"
        }
      ]
    }
  ]
};

When children.allow is true, the referenced node’s children are inherited as well.

You can also control placement:

from: {
  ref: "list",
  children: {
    allow: true,
    placement: "before"
  }
}

placement accepts:

  • "before"
  • "after"

The default is "after".

Inheritance mode

Temme supports two inheritance modes:

Append mode

This is the default mode.

  • primitive values are preserved on the inheriting object when already present
  • arrays are merged
  • objects are appended without overwriting existing keys in the inheriting object

Override mode

  • primitive values are overwritten by the referenced object
  • arrays are replaced by the referenced value
  • objects overwrite matching keys and keep non-conflicting ones

Example:

const hierarchy = {
  templates: [
    {
      ref: "base",
      id: "main-id",
      classes: ["one", "two"]
    }
  ],
  from: {
    ref: "base",
    mode: "override"
  }
};

Use append when you want additive composition, and override when you want the referenced structure to take precedence.


Summary

Temme gives you a declarative, object-based way to generate HTML with JavaScript.