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

Temme inheritance

Oussama Essamadi edited this page Oct 25, 2026 · 5 revisions

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 four 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.
  • Outer element: an object or a template inherits from an element already in the page, with @ followed by a CSS selector.

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.

Outer element inheritance

from.ref values starting with @ reference an element outside the hierarchy, found with a CSS selector in the target's document:

<nav id="menu" class="dark" aria-label="Main">Links</nav>
const hierarchy = {
  childNodes: [
    {
      name: "nav",
      from: {
        ref: "@#menu",
        exclude: ["id"]
      }
    }
  ]
};

The new nav inherits the classes, attributes, dataset and content (as HTML) of #menu. include and exclude work as usual, but the tag name and the child nodes are never read from the page. If no element matches, Temme throws an InvalidReferenceOptionValueError.

Resolution order and scope

References are resolved in dependency order, whatever the declaration order: if a inherits from b and b inherits from c, b first inherits from c, then a inherits the result.

const hierarchy = {
  childNodes: [
    { name: "i", from: { ref: "b" } },
    { ref: "b", from: { ref: "c" } },
    { ref: "c", classes: ["shared"] }
  ]
};
// All three elements end up with the "shared" class.

Some references are rejected:

  • a reference to an object nested deeper than the referencing one throws a ReferenceOutOfScopeError (templates count as being at the depth of the object that declares them)
  • circular inheritance, such as a inheriting from b inheriting from a, throws a CircularReferenceError; so does inheriting the children of an ancestor, which would include the object itself
  • a template referencing a rendered object throws an InvalidTemplateReferencingError

Inherited values are copies, so changing one object never changes another.

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 can't both restrict inheritance: giving both with entries throws an InvalidReferencingOptionError.

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. The inherited children are copies of the fully resolved originals, without their ref, so they never shadow the originals.

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.

  • the tag name and an existing id are preserved
  • classes are merged
  • attributes and dataset entries are added without overwriting existing keys
  • content is appended after the existing content, separated by a space (an empty content simply takes the inherited one)
  • children are added before or after the existing ones, when allowed

Override mode

  • the tag name, the id and the content are replaced
  • classes are replaced
  • attributes and dataset entries overwrite matching keys and keep the others
  • children are replaced, when allowed

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.

Clone this wiki locally