Skip to content

Instantly share code, notes, and snippets.

@gary149
Created December 21, 2024 13:22
Show Gist options
  • Select an option

  • Save gary149/39081ef97c8d9faffaf7b2abcb3d415a to your computer and use it in GitHub Desktop.

Select an option

Save gary149/39081ef97c8d9faffaf7b2abcb3d415a to your computer and use it in GitHub Desktop.
# \*mizu

## Phase 1 — ELIGIBILITY

Enables *mizu.js* rendering for the element and its children.

```html
<main *mizu>   <!--...--> </main>

Simple Explanation

This directive must not have any [tag] or .modifiers. If it does, the directive will be ignored. You can choose whether to require this directive for mizu.js rendering with the implicit option when using the user API. By default, rendering is explicit in Client-Side APIs and implicit in Server-Side APIs.

Variables

$root: HTMLElement

The closest element that declares a *mizu directive.


*set="context"

Phase 11 — CONTEXT

Sets context values for an element and its children.

<div *set="{ foo: 'bar' }">   <!--<span *text="foo"></span>--> </div>

Simple Explanation

The context must resolve to a JavaScript Object. The context is initialized once and persists across renderings, but it can still be updated by other directives.


*ref="name"

Phase 82 — REFERENCE

Creates a reference to an element for later use.

<div *ref="foo" data-text="bar">   <!--<p *text="$refs.foo.dataset.text"></p>--> </div>

Simple Explanation

Redefining a reference will shadow its previous value within the current subtree, without affecting its value in the parent subtree.

Variables

$refs: Record<PropertyKey, HTMLElement>

A collection of all referenced elements within the current subtree.

Modifiers

.raw[boolean=true]

Skip expression evaluation if set.


*if="expression"

Phase 23 — TOGGLE

Conditionally renders an element.

<div *if="true">   <!--...--> </div>

Simple Explanation

There is currently no special handling for <template> elements, but future versions may introduce specific behavior for these elements.


*else="expression"

Default: true Phase 23 — TOGGLE

Conditionally renders an element placed after another *if or *else directive.

<div *if="false"></div> <div *else="false"></div> <div *else><!--...--></div>

Simple Explanation

Must be placed immediately after an element with an *if or *else directive. There is currently no special handling for <template> elements, but future versions may introduce specific behavior for these elements.


*show="expression"

Default: true Phase 71 — DISPLAY

Conditionally displays an element.

<div *show="true">   <!--...--> </div>

Simple Explanation

When hidden, the element's CSS display property is set to none !important. When shown and if initially hidden by a CSS stylesheet (display: none), the element's display property is reset to initial !important. Unlike *if and *else directives, the element remains in the DOM when hidden. You can take advantage of the default value being true to hide elements before mizu.js loads (e.g. <style>[*show]{display:none}</style>).


*for="expression"

Phase 21 — EXPAND

Renders an element for each iteration performed.

<!--<ul>--> <li *for="let item of items"></li> <!--</ul>-->

Simple Explanation

The expression can be:

  • Any syntax supported inside for, for...in and for...of loops.
  • Any iterable object that implements Symbol.iterator.
    • The iterated key is exposed as $key.
    • The iterated value is exposed as $value.
  • A finite number.
    • The directive is applied the specified number of times.

There is currently no distinction between let, const and var declarations inside for loops, but future versions may introduce specific behavior for these. There is currently no special handling for <template> elements, but future versions may introduce specific behavior for these elements.

Variables

$id: string

The evaluated value of the *id directive if present, or the auto-generated identifier.

$iterations: number

The total number of iterations.

$i: number

The current iteration index (0-based).

$I: number

The current iteration index (1-based, same as $i + 1).

$first: number

Whether this is the first iteration (same as $i === 0).

$last: number

Whether this is the last iteration (same as $i === ($iterations - 1))


*id="expression"

Phase 0 — META

Hint for *for directive to differentiate generated elements.

<!--<ol>--> <li *for="const {id} of items" *id="id"></li> <!--</ol>-->

Simple Explanation

Must be used on an element with a *for directive. Identifiers must be unique within the loop, any duplicates will be replaced by the last occurrence.


*empty

Phase 23 — TOGGLE

Conditionally render an element after a *for directive.

<article *for="const article of articles"></article> <p *empty.not *text="`${$generated} results`"></p> <p *empty><!-- No results.--></p>

Simple Explanation

Must be placed immediately after an element with a *for or another *empty directive. Elements generated by the *for directive do not apply to this restriction. There is currently no special handling for <template> elements, but future versions may introduce specific behavior for these elements.

Variables

$generated: number

The number of elements generated by the preceding *for directive. This value may differ from the actual number of iterations processed if conditional directives were applied.

Modifiers

.not[boolean]

Inverts the condition, rendering the element when at least one element is generated.


*text="content"

Default: this.innerHTML Phase 41 — CONTENT

Sets element's textContent.

<p *text="'...'">   <!--...--> </p>

Simple Explanation

HTML content is automatically escaped. Without an attribute value, this directive escapes the element's innerHTML (e.g., <a *text><b></b></a> becomes <a *text>&lt;b&gt;&lt;/b&gt;</a>).


*html="content"

Phase 41 — CONTENT

Sets element's innerHTML.

<template *html="'<p>...</p>'">   <!--<p>...</p>--> </template>

Simple Explanation

Raw HTML can introduce XSS vulnerabilities. Exercise caution when using expressions from untrusted sources.


*mustache

Multiple Phase 42 — CONTENT_INTERPOLATION

Enables content interpolation within mustaches ({{ and }}) from Text child nodes.

<p *mustache>   <!--{{ ... }}--> </p>

Simple Explanation

Interpolation occurs only within Text nodes, not the entire element. HTML content is automatically escaped. There is currently no distinction between double mustaches ({{ and }}) and triple mustaches ({{{ and }}}), but future versions may introduce specific behavior for these.


*code="content"

Default: this.textContent Phase 41 — CONTENT

Sets element's innerHTML after performing syntax highlighting.

<code *code[ts]="'...'">   <!--<span class="hljs-*">...</span>--> </code>

Simple Explanation

This directive dynamically imports highlight.js. Unsupported languages default to plaintext.

Modifiers

[string]

Any supported language identifier or alias.

.trim[boolean=true]

Remove leading/trailing whitespaces and shared indentation.


*markdown="content"

Default: this.textContent Phase 41 — CONTENT

Sets element's innerHTML after performing markdown rendering.

<div *markdown="'*...*'">   <!--<em>...</em>--> </div>

Simple Explanation

This directive dynamically imports @libs/markdown.

Modifiers

[string]

Load additional Markdown plugins by specifying a comma-separated list (e.g., *markdown[emojis,highlighting,sanitize] ). See the full list of supported plugins at @libs/markdown/plugins. Unsupported plugins will be silently ignored.


*toc="selector"

Default: 'main' Phase 41 — CONTENT

Create a table of contents from <h1>...<h6> elements found in selected target.

<nav *toc="'main'">   <!--<ul>...</ul>--> </nav>

Simple Explanation

Heading elements must meet these criteria:

  • Include an id attribute.
  • Contain an immediate <a> child with an anchor link pointing to its parent id.
  • Follow a descending order without skipping levels.

When a heading is found, the next level headings are searched within its parentElement. If the parent is an <hgroup> or has a *toc[ignore] attribute, the search moves to the grandparent element.

Modifiers

[string]

Define which heading levels to include:

  • Specify a single level (e.g., *toc[h2]).
    • Add a + to include higher levels (e.g., *toc[h2+]).
  • Use a range with a - to specify multiple levels (e.g., *toc[h2-h4]).
  • Use ignore to exclude an element from traversal (e.g., *toc[ignore]). No other modifiers or attribute value should be used with this.

*clean

Phase 49 — CONTENT_CLEANING

Cleans up the element and its children from specified content.

<div *clean>   <!--...--> </div>

Simple Explanation

Modifiers

.comments[boolean]

Remove all Comment nodes within the subtree.

.spaces[boolean]

Remove all spaces (except non-breaking spaces &nbsp;) within the subtree.

.templates[boolean]

Clear all <template> nodes from the subtree after fully processing it.

.directives[boolean]

Strip all known directives from the subtree after fully processing it. If the .comments modifier is also enabled, comments generated by directives will be removed as well.


*custom-element="tagname"

Phase 81 — CUSTOM_ELEMENT

Registers a new custom element.

<template *custom-element="my-element">   <ul><slot name="items"></slot></ul> </template>

Simple Explanation

Must be defined on a <template> element. The tagname must be a valid custom element name. Valid custom element names may be specified as is. Custom elements registered this way do not use Shadow DOM, their content is rendered directly.

Variables

$slots: Record<PropertyKey, HTMLSlotElement>

A record of #slot elements by <slot> name. The unnamed slot is accessible using $slots[""].

$attrs: Record<PropertyKey, string>

A record of HTML attributes specified on the custom element.

Modifiers

.flat[boolean]

Replace occurrences of this custom element with its content. Note that $slots and $attrs variables are not accessible when using this modifier.


#slot

Phase 0 — META

Specify target <slot> in an element defined by a *custom-element directive.

<my-element>   <li #items><!--...---></li> </my-element>

Simple Explanation

Elements without a #slot directive are appended to the default (unnamed) slot. Elements targeting the same slot are appended in the order they are defined.


*is="tagname"

Phase 22 — MORPHING

Set an element tagname.

<div *is="'section'">   <!--...--> </div>

Simple Explanation

If the tagname changes, the reference will also change. Equality checks with elements using this directive may not work as expected. Some directives may be incompatible with this directive.


@event="listener"

Default: null Multiple Phase 61 — INTERACTIVITY

Listens for a dispatched Event.

<button @click="this.value = 'Clicked!'">   <!--Not clicked yet.--> </button>

Simple Explanation

Attach multiple listeners in a single directive using the shorthand @="object" (e.g., @="{ foo() {}, bar() {} }").

  • Modifiers apply to all listeners in the directive (e.g., @.prevent="{}").
  • Use tags to attach listeners with different modifiers (e.g., @[1]="{}" @[1].prevent="{}").
  • HTML attributes are case-insensitive, so this is the only way to listen for events with uppercase letters or illegal attribute characters (e.g., @="{ FooBar() {}, Foobar() {} }").

To listen for events with dots . in their names, use brackets { } (e.g. @{my.event}).

Variables

$event: Event

(in listener only) The dispatched Event.

Modifiers

[string]

Optional tag to attach multiple listeners to the same event (e.g., @click[1], @click[2], etc.).

.prevent[boolean]

Call event.preventDefault() when triggered.

.stop[boolean]

Call event.stopPropagation() when triggered.

.once[boolean]

Register listener with { once: true }.

.passive[boolean]

Register listener with { passive: true }.

.capture[boolean]

Register listener with { capture: true }.

.self[boolean]

Trigger listener only if event.target is the element itself.

.attach["element" | "window" | "document"]

Attach listener to a different target (e.g., window or document).

.throttle[duration≈250ms]

Prevent listener from being called more than once during the specified time frame.

.debounce[duration≈250ms]

Delay listener execution until the specified time frame has passed without any activity.

.keys[string]

Specify which keys must be pressed for the listener to trigger on a KeyboardEvent.

  • The syntax for keys constraints is defined as follows:
    • Combine keys with a plus sign + (e.g., @keypress.keys[ctrl+space]).
    • Separate multiple combinations with a comma , (e.g., @keypress.keys[ctrl+space,shift+space]).
  • Supported keys and aliases:
    • alt for "Alt".
    • ctrl for "Control".
    • shift for "Shift".
    • meta for "Meta".
    • space for " ".
    • key for any key except "Alt", "Control", "Shift", and "Meta".
    • Any value returned by event.key.

:attribute="value"

Default: $<attribute> Multiple Phase 51 — ATTRIBUTE

Binds an element's attribute value.

<a :href="url">   <!--...--> </a>

Simple Explanation

Binding directives is not officially supported and is considered undefined behaviour. :class and :style have specific handling described below. Bind multiple attributes in a single directive using the shorthand :="object" (e.g. :="{ foo: 'bar', bar: true }"). The directive value may be omitted to bind an attribute to an identifier with the same name (after camelCase conversion if the attribute contains hyphens - ) in the current context. (e.g., :data-foo is equivalent to :data-foo="dataFoo"). Boolean attributes defined by the HTML spec are handled accordingly (removed when falsy). Attributes with null or undefined values are removed.


:class="value"

Default: $<attribute> Multiple Phase 51 — ATTRIBUTE

Binds an element's class attribute.

<p :class="{ foo: true, bar: false }">   <!--...--> </p>

Simple Explanation

The expression can be:

  • A string of space-separated class names (e.g., "foo bar").
  • A Record<PropertyKey, boolean> mapping class names to their state (e.g., { foo: true, bar: false }).
  • An Array of the supported types (e.g., [ "foo", { bar: false }, [] ])

The initial class attribute value is preserved. Class names with at least one truthy value are treated as active.


:style="value"

Default: $<attribute> Multiple Phase 51 — ATTRIBUTE

Binds an element's style attribute.

<p :style="{ color: 'salmon' }">   <!--...--> </p>

Simple Explanation

The expression can be:

  • A string supported by HTMLElement.style.cssText (e.g., "color: blue;").
  • A Record<PropertyKey, unknown> mapping CSS properties to their values (e.g., { backgroundColor: "red", "border-color": "green", width: 1 }).
    • Use camelCase instead of kebab-case to avoid escaping CSS property names.
    • Values of type number are implicitly converted to px units when applicable (HTMLElement.style.setProperty() will be called with "px" appended).
  • An Array of the supported types (e.g., [ "color: blue", { backgroundColor: "red" }, [] ])

The initial style attribute value is preserved. CSS properties are processed in the order they are defined, regardless of !important.


::value="model"

Default: value Phase 52 — ATTRIBUTE_MODEL_VALUE

Binds an <input>, <select> or <textarea> element's value attribute in a bi-directional manner.

<select ::value="foo">   <!--<option>...</option>--> </select>

Simple Explanation

<input type="checkbox"> and <select multiple> elements will bind to an array of values. Using a modeled value within @input or @change expressions can cause precedence issues, as the model relies on these events to update. To avoid this, listen to the :: event, which is always triggered after the model has been updated. Must be used on elements with a value property, such as <input>, <select>, or <textarea>. For other elements, use the :attribute directive. The .nullish, .boolean, .number, and .string modifiers are currently implemented as boolean modifiers, but future versions may change this behavior to offer more parsing features. You can use the shorthand syntax ::="model" instead of ::value="model".

Modifiers

.event[string="input"]

Change the Event that triggers the model update. Recommended events are "input" or "change".

.name[boolean]

Automatically set the input name attribute based on the attribute's value (e.g., <input ::.name="foo"> becomes <input name="foo">). The default is true for <input type="radio"> and <input type="checkbox">, and false for all other elements.

.value[boolean]

Initialize the model using the nullish coalescing operator and the input value attribute if present (e.g., <input ::.value="foo" value="bar"> assigns foo the value "bar" if it was nullish).

.throttle[duration≈250ms]

Prevent the listener from being called more than once during the specified time frame.

.debounce[duration≈250ms]

Delay listener execution until the specified time frame has passed without any activity.

.keys[string]

Specify which keys must be pressed for the listener to trigger on a KeyboardEvent. See @event.keys modifier for more information.

.nullish[boolean]

Set the model value to null if the value is empty.

.boolean[boolean]

Convert the model value using Boolean(). Additionally, any non-empty value matching the YAML 1.1 definition of falsy boolean values are set to false.

.number[boolean]

Convert the model value using Number().

.string[boolean]

Convert the model value using String().


%http="url"

Phase 33 — HTTP_REQUEST

Performs a fetch() call that can be handled by %response directives.

<div %http="https://example.com">   <!--...--> </div>

Simple Explanation

Without a %response directive, the request won't be performed automatically. Use %response.void if you want to trigger the request but ignore the response. Valid URLs may be specified as is. A new request is triggered for the same element if:

  • Its reference changes.
  • The evaluated URL changes.

Since predicting when a new request will be performed is challenging, use this directive only for read-only operations. For endpoints with side effects, consider the %@event directive.

Variables

$event: Event | null

(in url expression only) The dispatched Event if triggered by a %@event directive, or null.

Modifiers

.follow[boolean=true]

Control whether fetch() should follow redirections.

.history[boolean]

Whether to update the browser history with history.pushState() for the target URL (must be the same origin).

.method[string]

Set the HTTP method (the value is uppercased). This modifier should not be used with its aliases.

.get[boolean]

Alias for .method[get].

.head[boolean]

Alias for .method[head]

.post[boolean]

Alias for .method[post]

.put[boolean]

Alias for .method[put]

.patch[boolean]

Alias for .method[patch]

.delete[boolean]

Alias for .method[delete]


%header[name]="value"

Multiple Phase 31 — HTTP_HEADER

Set HTTP headers for a %http directive.

<div %header[x-foo]="'bar'">   <!--...--> </div>

Simple Explanation

Headers with undefined or null values are deleted. Headers with Array values are appended together.

Modifiers

[string]

Header name.


%body="content"

Phase 32 — HTTP_BODY

Set HTTP body for a %http directive.

<div %body.json="{foo:'bar'}">   <!--...--> </div>

Simple Explanation

Variables

$headers: Headers

A Headers object containing all registered headers from %header directives attached to the element.

Modifiers

.type["text" | "form" | "json" | "xml"]

Format the body with the specified type:

  • text: format body with toString().
  • form: format body with URLSearchParams.
  • json: format body with JSON.stringify().
  • xml: format body with stringify() from @libs/xml/stringify. Using this value will dynamically import @libs/xml.

This modifier should not be used with one of its aliases.

.header[boolean=true]

Automatically set the Content-Type header when using a .type modifier:

  • text: set Content-Type: text/plain.
  • form: set Content-Type: application/json.
  • json: set Content-Type: application/x-www-form-urlencoded.
  • xml: set Content-Type: application/xml.

If the header was already set, it is overwritten.

.text[boolean]

Alias for .type[text].

.form[boolean]

Alias for .type[form].

.json[boolean]

Alias for .type[json].

.xml[boolean]

Alias for .type[xml].


%response="expression"

Default: null Multiple Phase 34 — HTTP_CONTENT

Reacts to a %http directive's Response.

<div %http="'https://example.com'" %response.html>   <!--...--> </div>

Simple Explanation

Variables

$response: Response

A Response object containing the fetched data.

$content: unknown

Contains the response.body (type depends on the modifier used).

Modifiers

[string]

Specify which HTTP status codes trigger this directive:

  • The syntax for status code constraints is defined as follows:
    • Define a range using a minus sign - between two numbers (e.g., %response[200-299]).
    • Specify multiple ranges and statuses by separating them with a comma , (e.g., %response[200,201-204]).
  • Supported aliases:
    • 2XX for 200-299.
    • 3XX for 300-399.
    • 4XX for 400-499.
    • 5XX for 500-599.
.consume["void" | "text" | "html" | "json" | "xml"]

Consume the response.body:

  • void: discard body using response.body?.cancel().
  • text: consume body using response.text() and set element's textContent if no expression is provided.
  • html: consume body using response.text(), parse it into a <body> element, and set element's innerHTML if no expression is provided.
  • json: consume body using response.json().
  • xml: consume body using response.text() and parse it with parse from @libs/xml/parse. Using this value will dynamically import @libs/xml.

This modifier should not be used with one of its aliases.

.void[boolean]

Alias for .consume[void].

.text[boolean]

Alias for .consume[text].

.html[boolean]

Alias for .consume[html].

.json[boolean]

Alias for .consume[json].

.xml[boolean]

Alias for .consume[xml].

.swap[boolean]

Consume body using response.text() and set target's outerHTML. This modifier takes precedence over the .consume modifier and makes it effectless, although if .consume[text] is set, swapped content will be escaped.

Any non-directive HTML attributes on the target will be applied to the swapped content elements.


%@event="listener"

Default: null Multiple Phase 35 — HTTP_INTERACTIVITY

Listens for a dispatched Event and re-evaluates %http directive before reacting to its Response.

<button %http="https://example.com" %@click.html>   <!--...--> </button>

Simple Explanation

Must be defined on an element that also possess a %http directive. This is essentially a combination of %response and @event directives. Target URL is still set by %http directive. As it is re-evaluated, you can however use the $event value to dynamically compute the target URL (e.g.%http="$event ? '/foo' : '/bar'"). All modifiers from %http directive are inherited, along with the RequestInit prepared by %header and %body directives.

Variables

$event: Event

(in listener only) The dispatched Event.

$response: Response

A Response object that contains the fetched data.

$content: unknown

A variable that contains the response.body (typing depends on which modifier is used).

Modifiers

...

Inherited from @event and %response directives. See their respective documentation for more information.


*once

Phase 99 — POSTPROCESSING

Render an element once and skip subsequent updates.


*refresh="interval"

Phase 99 — POSTPROCESSING

Reprocess an element at a specified interval (in seconds).

<div *refresh="1.5">   <!--<time *text="new Date()"></time>--> </div>

Simple Explanation

Ensure proper context management to prevent unexpected errors. Avoid using with iterative directives like *for as *refresh will be duplicated for each generated element. The target element will be rendered regardless of detected changes. This is useful for updating content that cannot be directly observed, but use sparingly to avoid performance issues. Set the interval to null to stop refreshing. If the element is commented out by a directive, the refresh is automatically cleared. Refresh operations are performed using setTimeout. New calls are scheduled when the directive is processed again, ensuring a consistent interval.

Variables

$refresh: boolean

Indicates if the element is currently being refreshed.


*eval="expression"

Phase 89 — CUSTOM_PROCESSING

Evaluate a JavaScript expression in the context of the element.

<div *eval="console.log('$data')">   <!--...--> </div>

Simple Explanation

Use this directive sparingly, prefer alternative directives for better maintainability and security. This directive is intended for edge cases. The expression runs after the element and all its children have been fully processed.


*skip

Phase 2 — PREPROCESSING

Prevent an element from being processed.

<div *skip>   <!--<p *text="foo"></p>--> </div>

~test="expression"

Multiple Phase 10 — TESTING

Special directive for testing purposes.

<samp ~test[testing].text="'...'">   <!--...--> </samp>

Simple Explanation

For testing only. Use this directive to isolate and test custom directives without relying on others. The modifiers may not be compatible with each other.

Modifiers

[string]

Specify any existing Phase name (e.g., ~test[testing], defaults to Phase.TESTING). The directive will execute during the specified phase before any other directive in that phase, allowing you to simulate specific scenarios.

.text[boolean]

Set the element's textContent with the expression result.

.eval[boolean]

Evaluate a JavaScript expression within the element's context.

.comment[boolean]

Convert the element to a Comment if the expression is truthy, and revert it otherwise.

.throw[boolean]

Throw an EvalError if the expression is truthy.


*noop

Multiple Phase 10 — TESTING

This directive does nothing.

<div *noop></div>

Usage

Client-side

Set up mizu.js in your browser environment using one of two methods:

  • Immediately Invoked Function Expression (IIFE)
  • EcmaScript Module (ESM)

On the client-side...

  • Rendering is explicit, requiring the *mizu attribute to enable mizu.js on a subtree.
  • Reactivity is enabled, so changes to contexts will trigger a re-render.

IIFE (.js)

This setup automatically starts rendering the page once the script is loaded. It's the simplest way to get started but limited to the default configuration.

<script src="https://mizu.sh/client.js" defer></script>

ESM (.mjs)

This setup requires you to import and start mizu.js manually, allowing customization of the rendering process, such as setting the initial context and loading additional directives.

<script type="module">  import Mizu from "https://mizu.sh/client.mjs"  await Mizu.render(document.body, { context: { foo: "🌊 Yaa, mizu!" } })</script>

Looking to effortlessly theme your new web page? Check out matcha.css!

<link rel="stylesheet" href="https://matcha.mizu.sh/matcha.css">

Server-side

To set up mizu.js in a server environment, install it locally. mizu.js packages are hosted on jsr.io/@mizu.

On the server side...

  • Rendering is implicit, so the *mizu attribute is not required.
  • Reactivity is disabled, meaning changes to contexts are not tracked and will not trigger a re-render.

Deno

Deno supports the jsr: specifier natively, allowing you to import mizu.js directly.

import Mizu from "jsr:@mizu/render/server" await Mizu.render(`<div *text="foo"></div>`, { context: { foo: "🌊 Yaa, mizu!" } })

Alternatively, add it to your project using the Deno CLI.

deno add jsr:@mizu/render

Other runtimes (NodeJS, Bun, etc.)

Add mizu.js to your project using the JSR npm compatibility layer.

# NodeJS npx jsr add @mizu/render
# Bun bunx jsr add @mizu/render

Once installed, use it in your project.

import Mizu from "@mizu/render/server" await Mizu.render(`<div *text="foo"></div>`, { context: { foo: "🌊 Yaa, mizu!" } })

Concepts

Directive

A HTML attribute recognized by mizu.js which instructs how it should process the element.

The syntax is as follows:

<tag *name [ tag ]. modifier [ value ] =" expression " />

Name

Directives names often begin with special characters to prevent conflicts with standard HTML attributes and to clearly indicate their specific purpose:

  • * for generic directives.
  • # for directives targeting <slot> elements.
  • @ for directives related to Event handling.
  • : for binding HTML attributes.
    • :: for bi-directional binding.
  • % for HTTP directives.
    • %@ for combined HTTP and Event directives.
  • ~ for testing directives.

Tag

Typically, this serves as the directive's argument. At most one tag can be specified per directive.

Modifier(s)

Modifiers adjust the behavior of the directive. You can specify multiple modifiers on the same directive.

Repeating a modifier on a single directive is considered undefined behavior.

Modifier(s) value

The value of the modifier. The modifier may have an explicit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment