Tag Syntax
The Component Markup Language has been heavily inspired by XML, while also making various domain-specific improvements as to reduce friction when trying to depict component-templates. The following overview will outline its features and facets one by one, all while explaining why these patterns are in place.
Special Characters
All text other than tags themselves which is also outside of placeholder-notation is not constrained in any way, besides the very few exceptions discussed below; keeping syntactic noise to a bare minimum is a conscious design-decision.
Opening Pointy-Brackets
Literal opening pointy-brackets are always to be marked by a leading backslash in order to avoid them erroneously being interpreted as the beginning of a tag. The input
Code-Blocks are only available within the browserbecomes
Code-Blocks are only available within the browseronce processed.
Curly-Brackets
Literal curly-brackets are always to be marked by a leading backslash in order to avoid them erroneously being interpreted as the premature end of a tag-attribute's markup-value or the beginning of a placeholder:
Code-Blocks are only available within the browserThe same holds true for opening curly-brackets:
Code-Blocks are only available within the browserIt's best to, in general, think of curly-brackets as special and reserved tokens within this templating-language, because that's what they are; if to be used literally, do so with care.
Newlines And Whitespace
All newlines and surrounding spaces, which includes indentation as well as trailing whitespace, will be removed and thus do not end up in the rendered result; this fact allows the user to format their markup in any way that is visually appealing to work with. In order to inject Linebreaks or surrounding Spaces, please check out the corresponding tags as linked to learn more about the details.
Placeholders
In order to substitute variables and various expressions in general into designated slots, said expressions are simply to be wrapped by a pair of matching curly-brackets. Let's assume that the variable Code-Blocks are only available within the browser holds a string-value of Code-Blocks are only available within the browser, then the markup
Code-Blocks are only available within the browserbecomes
Code-Blocks are only available within the browseronce processed.
If the value of a placeholder-expression evaluates to Code-Blocks are only available within the browser, no value will be substituted, allowing for convenient conditional displaying.
Placeholders must not span across multiple lines as to enforce readability and simplicity; expressions will always remain terse if employed as intended, in conjunction with intrinsic attributes and bindings.
Whenever the result of an expression, no matter its complexity, is an instance of a Code-Blocks are only available within the browser, said markup is immediately interpreted and thereby injected into its designated placeholder.
Code-Blocks are only available within the browserWith a user-changable value of
Code-Blocks are only available within the browserthe final result thus becomes

As becomes immediately apparent, this powerful feature allows to define reusable templates which then may be injected and augmented (conditions, loops, etc.) as needed; when evaluating said templates, they are granted access to all environment-variables and bindings which are available at their placeholder's position. Due to the fact that only pre-parsed nodes are renderable via this method, there's no additional computational burden caused by reusable partial templates in comparison to defining the whole template all in one place.
Tags
Tags represent calls to internally existing functionality, which then can modify and or generate content dynamically; see Built-In Tags to discover predefined features and check out the Extension API as to learn about creating your own. There are two types of notation: one being comprised of an opening- and a (optional) closing-tag, while the other self-closes within the opening-tag and thereby does not bear any content.
Opening And Closing
When invoking a tag which holds content, the tag becomes enabled to modify said members in order to implement various visual and/or generative transformations. The opening-tag is simply surrounded by pointy-brackets Code-Blocks are only available within the browser, while the closing-tag has to be equally named, with the addition of a slash right before said name Code-Blocks are only available within the browser.
Code-Blocks are only available within the browserIn the example above, both the Code-Blocks are only available within the browser and Code-Blocks are only available within the browser passages will be colored Code-Blocks are only available within the browser, as they are members of the corresponding invocation to colorise; as can be seen also, the Code-Blocks are only available within the browser-tag's closing has been omitted, which will be carried out implicitly once its parent closes, or the very end of the code has been reached. For simple scenarios, implicit closing can help with brevity, but for complex templates, it is not advised to rely on this feature, as unexpected implications may follow which add needless mental overhead regarding their reader and maintainer.
As a compromise between brevity and exactness, a shorthand-tag has been introduced, namely Code-Blocks are only available within the browser, which simply closes the last opened tag but does so without having to specify its name all over again. It is avised to employ this shorthand as much as possible within smaller areas of the template in order to avoid unexpected behaviour with auto-close, while as soon as an indented nesting-depth of three is exceeded, named closing-tags should instead be applied to parents, in order to visually aid the user in understanding the layout they're faced with.
Code-Blocks are only available within the browserIf a "hard-reset" is to be achieved, there also exists the close-all tag, namely Code-Blocks are only available within the browser, which will close every tag that is currently open and thus bring whatever follows after it right back to root-level scope. Again, it is strongly advised to handle this special feature with great care.
Code-Blocks are only available within the browserSelf-Closing
Tags which bear no content, as they simply insert data retrieved externally or mark special instructions, self-close by adding a slash right before the closing pointy-bracket Code-Blocks are only available within the browser.
Code-Blocks are only available within the browserIntrinsic Attributes
Attributes who are marked with a preceding asterisk Code-Blocks are only available within the browser or plus-symbol Code-Blocks are only available within the browser are always consumed by the system (thus never relayed to tag-definitions) and thereby considered intrinsic, meaning that they are natively supported on all tags as well as that they have been implemented directly within the engine itself. A leading asterisk will signal expression-mode, i.e. Code-Blocks are only available within the browser, while a leading plus-symbol enters literal-mode, in which values of all kinds are captured as-is, i.e. Code-Blocks are only available within the browser.
A list of supported intrinsic attributes can be found here:
Let-Bindings
Each tag, no matter its underlying implementation, supports binding the result of expressions to temporary variables whose lifetime spans the content of said tag. While there are many uses for this feature, one of the simplest will be to extract complex common expressions.
In order to introduce such a binding, make use of the intrinsic Code-Blocks are only available within the browser attribute namespace, where the identifier after the dash denotes the name of the newly introduced temporary variable. Please note that variables, by enforced convention, always follow the Code-Blocks are only available within the browser-style, meaning being all lower-case with spaces represented as underscores. In contrast, tag- as well as attribute-names enforce the same pattern, just with the alteration of them swapping out underscores for hyphens, making it become Code-Blocks are only available within the browser. By this simple yet effective differentiation, it is immediately visually obvious to which realm an identifier belongs to.
When providing immediate values which are not of type string, i.e. numbers and booleans, variables are directly bound to the specified constant, not requiring them to be wrapped by expressions artificially. Bindings are evaluated in top-down order, meaning that later bindings can access the results of their predecessors, allowing for dependent expressions, as follows:
Code-Blocks are only available within the browserwhich will display a value of Code-Blocks are only available within the browser. If bindings containing literal strings are to be created, simply employ the literal intrinsic attribute prefix Code-Blocks are only available within the browser instead of its expression counterpart Code-Blocks are only available within the browser, as follows:
Code-Blocks are only available within the browserNext to expressions and literals, markup-values may also be bound to temporary variables, effectively allowing to define reusable components.
Code-Blocks are only available within the browserIn order to parameterize these reusable components in a flexible manner, any placeholders within them will be fed with the data available at their usage-site.
Code-Blocks are only available within the browserWhile scoped let-bindings may suffice for most use-cases, components can be partially or even fully pre-parameterised in a safe way by using a capture, which will snapshot all variables existing at its place of residence, providing the guarantee of them not becoming shadowed later down the road. A capture is signalled by enclosing the let-binding's variable-name by matching parentheses Code-Blocks are only available within the browser. Its value need not necessarily be a direct markup-value, but it may also refer to other components, in order to clone them as a pre-parameterized version.
Code-Blocks are only available within the browserImmediate Attribute-Values
All opening-tags, including the self-closing kind, may support a variety of attributes - be they simple scalar values or more complex markup.
Code-Blocks are only available within the browserIn the example above,
- Code-Blocks are only available within the browser is of type string (sequence of characters) with double-quotes
- Code-Blocks are only available within the browser is also a string, this time with single-quotes (use as needed, e.g. to avoid having to escape quotes)
- Code-Blocks are only available within the browser is a so-called template-literal using string-interpolation
- Code-Blocks are only available within the browser of type whole number
- Code-Blocks are only available within the browser of type fractional number
- Code-Blocks are only available within the browser of type flag-style boolean (implicit Code-Blocks are only available within the browser-value)
- Code-Blocks are only available within the browser also of type boolean (Code-Blocks are only available within the browser-value)
- Code-Blocks are only available within the browser a Code-Blocks are only available within the browser-value and
- Code-Blocks are only available within the browser being a markup-value, delimited by curly-brackets.
Differentiation occurs between markup- and scalar-values: markup-attributes accept any value, which will be automatically converted to a plain-text component if needed, while markup cannot be assigned to attributes expecting scalar-values, since there is no sensible way of conversion.
Attributes which support multiple values may be assigned more than once - each occurrence will be collected and passed to the tag as a list when executing it, maintaining the top-down order of assignment.
Code-Blocks are only available within the browserIn the above example, the two values of Code-Blocks are only available within the browser will be matched with the two placeholders of the Code-Blocks are only available within the browser translation-message by the client; such messages may have a different number of slots, with component-markup allowing the user to specify as many values as necessary.
Dynamic Attribute-Values
Attributes also support dynamic values, meaning values which are not specified immediately but rather are to be retrieved by evaluating an expression; to indicate this behaviour, simply enclose the attribute-name by a pair of square-brackets Code-Blocks are only available within the browser.
Code-Blocks are only available within the browserNow, Code-Blocks are only available within the browser will be assigned to whatever value the expression Code-Blocks are only available within the browser evaluates to.
Whenever attributes support multiple values and are enclosed by square-brackets Code-Blocks are only available within the browser in order to be bound to an expression, the spread-operator Code-Blocks are only available within the browser may be prepended to the attribute-name within said brackets in order to evaluate the result of the expression and instantiate an attribute-value for each item of the list it returns (becomes a singleton-list if the expression returns a scalar).
Code-Blocks are only available within the browserIn the above example, the attribute Code-Blocks are only available within the browser of the tag Code-Blocks are only available within the browser will be instantiated once for each item of the Immediate Array Code-Blocks are only available within the browser, such that the resulting meaning effectively becomes:
Code-Blocks are only available within the browserThis can be very useful for data-driven rendering, where the environment holds lists of values which are to be individually bound to tag-attributes. Beware of the fact that if the spreading-operator is not employed on a multi-value attribute, results may vastly differ from expectations, because a single attribute-value holding the outermost list is not equivalent to multiple attribute-values each holding a single item of said list.
The features as described above also apply to attributes which require their values to be of type markup (Code-Blocks are only available within the browser), with the following rules of operation:
- Scalar non-markup values are interpreted as plain text
- Scalar markup values are interpreted as-is (rich components)
- Lists are:
- Interpreted item by item if not using the spread-operator Code-Blocks are only available within the browser
- Instantiating one attribute-value per item if using the spread-operator Code-Blocks are only available within the browser
The result of the input
Code-Blocks are only available within the browseris equivalent to that of (using Let-Bindings to introduce markup-variables; they could just as well come from the environment)
Code-Blocks are only available within the browsersince it assigns one list-item to one instance of the Code-Blocks are only available within the browser-attribute, due to the spread-operator being present.
In contrast to the above, if not using the spread-operator, components will simply be interpreted sequentially, with the result becoming the value of a single attribute-instance; the following example portrays said behaviour (the Code-Blocks are only available within the browser value was manually added because Code-Blocks are only available within the browser-components do not render if the count of their placeholders is not matched - that's a client-side limitation):
Code-Blocks are only available within the browserAs mentioned earlier, non-markup values will simply be interpreted as plain text:
Code-Blocks are only available within the browserIf-Conditionals
The simplest form of a conditional is represented by the intrinsic Code-Blocks are only available within the browser attribute, which is always treated as an expression (square brackets must not be added explicitly); if matching, the tag to which it is applied shows up and if not, the tag will not be evaluated.
Code-Blocks are only available within the browserOnce a conditional has been declared as can be seen above, the intrinsic attributes Code-Blocks are only available within the browser as well as Code-Blocks are only available within the browser are now available to its direct siblings, meaning elements which succeed it on the same level of nesting.
Code-Blocks are only available within the browserThe Code-Blocks are only available within the browser-branches are evaluated in the order they are specified in and only once the main Code-Blocks are only available within the browser-condition failed; once an Code-Blocks are only available within the browser-conditional matched, all others, including the Code-Blocks are only available within the browser-fallthrough will not evaluate; if all conditions fail, the Code-Blocks are only available within the browser-case will show up in the result (note that it has no value assigned and also does not accept one, for logical reasons).
These Code-Blocks are only available within the browser-/Code-Blocks are only available within the browser-/Code-Blocks are only available within the browser-sequences need to be organised as a single block of subsequent members, meaning that there cannot be any intermediate nodes not being part of the case-decision; if that is desired, simply use standalone Code-Blocks are only available within the browser-clauses.
Multiple such sequences may coexist one after another on the same level of depth, separated by their initial Code-Blocks are only available within the browser-conditional; they may also be nested to any arbitrary complexity. This way, nuanced decisions may be depicted with minimal syntactic effort.
Code-Blocks are only available within the browserWhen-Matching
In contrast to Code-Blocks are only available within the browser-conditionals, where expressions are evaluated to Code-Blocks are only available within the browser and Code-Blocks are only available within the browser in order to decide which branch to evaluate, processed in a top-down order, Code-Blocks are only available within the browser-matching is taking the value of an expression as an input and then tries to match it against one of the existing cases; cases cannot be expressions but are rather constrained to static string-values, such that internally, a hashing-algorithm can be applied in order to improve runtime performance - especially in comparison to the Code-Blocks are only available within the browser-equivalent. When-comparisons are always case-insensitive; Code-Blocks are only available within the browser-values always invoke the Code-Blocks are only available within the browser-fallback!
Code-Blocks are only available within the browserIf no specified Code-Blocks are only available within the browser-case applies, an optional Code-Blocks are only available within the browser-fallback may be provided to evaluate; if absent, nothing will be rendered. The above is functionally (but not computationally!) equivalent to the following Code-Blocks are only available within the browser-chain, which is absolutely advised against:
Code-Blocks are only available within the browserAs always, these intrinsic attributes may be applied to any tag, which means that if the cases are already wrapped in a parent-container due to the template at hand, one does not need to introduce an extra Code-Blocks are only available within the browser - it simply serves as an invisible wrapper for Code-Blocks are only available within the browser-cases. All children within the parent holding the Code-Blocks are only available within the browser-attribute are required to be members of the matching-process, meaning Code-Blocks are only available within the browser-cases or an Code-Blocks are only available within the browser, where the latter may only exist once; consider this whole block as atomic - it cannot be split up, cannot be injected with static content and always evaluates to a single branch within it.
In case it is ever truly needed, when-matching can be nested, as follows:
Code-Blocks are only available within the browserUse-Conditionals
If instead of disabling the applied-to element and its children altogether, the intrinsic Code-Blocks are only available within the browser attribute allows to only prevent the very tag it is applied to from taking effect, while still always rendering its content; that said, the Code-Blocks are only available within the browser condition takes precedence and when it itself evaluates to Code-Blocks are only available within the browser, the Code-Blocks are only available within the browser condition will not have any effect.
Code-Blocks are only available within the browserIn the example above, if Code-Blocks are only available within the browser evaluates to Code-Blocks are only available within the browser, the entire tag will not render, including its textual contents; otherwise, the value of Code-Blocks are only available within the browser dictates whether the rainbow is applied or not - if it evaluates to Code-Blocks are only available within the browser, the text Code-Blocks are only available within the browser will remain uncolorized.
Generative Loops
In order to generate content based on a sequence of data-points, the intrinsic Code-Blocks are only available within the browser attribute may be employed; it is a mere attribute that can be added to any existing tag, instantiating it once for each point of data. In order to assign the current item to an accessible variable, specify its name right after a hyphen attached to the intrinsic attribute, akin to Let-Bindings. The value is always interpreted as an expression (square brackets must not be added explicitly).
Once employed, the additional attributes become available:
- Code-Blocks are only available within the browser, accepting an optional markup-value to be injected inbetween iterations
- Code-Blocks are only available within the browser, accepting an optional markup-value to be injected if there are no items to iterate
- Code-Blocks are only available within the browser, accepting an optional boolean marking whether to iterate in reverse order
When there's no need to access the current item of iteration, simply drop the dash and use the attribute as-is; this shorter style is especially useful in combination with Ranges (the Code-Blocks are only available within the browser context is discussed further below).
Code-Blocks are only available within the browserWhen iteration-items are required, simply attach the desired variable-name with a hyphen to the attribute.
Code-Blocks are only available within the browserThe example above will generate the Code-Blocks are only available within the browser tag once for each name in the list, injecting the Code-Blocks are only available within the browser separators inbetween iterations. If items are to be skipped based on a Condition, simply also add in the corresponding Code-Blocks are only available within the browser intrinsic attribute.
Let's skip names equal to Code-Blocks are only available within the browser:
Code-Blocks are only available within the browserIn this context, meaning when combined with a loop, the Code-Blocks are only available within the browser-condition may not be chained with Code-Blocks are only available within the browser/Code-Blocks are only available within the browser intrinsic attributes, as it does not control whether the node is rendered, but whether an iteration is rendered, and thereby becomes attached with a completely different meaning. For more nuanced control, consider adding conditions on child-tags.
Let's render an alternate name for Code-Blocks are only available within the browser:
Code-Blocks are only available within the browserAdditional information is made available via the implicitly added temporary variable called Code-Blocks are only available within the browser; it also only exists for the duration of the tag-contents to which the Code-Blocks are only available within the browser intrinsic attribute has been applied to. It itself holds the following useful properties, updated for each iteration:
- Code-Blocks are only available within the browser: Zero-based sequence-number of the current element
- Code-Blocks are only available within the browser: Number of elements to be iterated over in total
- Code-Blocks are only available within the browser: Whether the Code-Blocks are only available within the browser is an even number
- Code-Blocks are only available within the browser: Whether the Code-Blocks are only available within the browser is an odd number
- Code-Blocks are only available within the browser: Whether the item is the first of the sequence
- Code-Blocks are only available within the browser: Whether the item is the last of the sequence
For single loops, accessing this variable directly marks the most straight-forward way; let's add positions (Code-Blocks are only available within the browser, Code-Blocks are only available within the browser, ...) to the prior example.
Code-Blocks are only available within the browserTo generate multiple elements per iteration, make use of the invisible Code-Blocks are only available within the browser-tag:
Code-Blocks are only available within the browserWhenever attribute-values are of type markup, as is the case with the Code-Blocks are only available within the browser, nesting may extend to any arbitrary depth; e.g. a separator which again displays Code-Blocks are only available within the browser:
Code-Blocks are only available within the browserComments
The insertion of comments makes sense whenever passages are either to be documented, or quickly disabled, without having to delete the underlying markup. Comments are not processed by the system, but are to be thought of as mere sticky-notes, available for additional aid in human understanding. They start with Code-Blocks are only available within the browser and end in Code-Blocks are only available within the browser - whatever comes inbetween is regarded as content of this comment and thus ignored.
As for documenting markup, the use-case should be rather straightforward:
Code-Blocks are only available within the browserWhen it comes to quickly disabling passages of code, simply wrap the desired passage in comment-markers.
Code-Blocks are only available within the browserIn order to guarantee convenience whenever passages including commented-out markup are to be themselves commented out, nested comments are fully supported.
Code-Blocks are only available within the browser