Need help with HTMLx?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

htmlx-org
469 Stars 5 Forks 6 Commits 10 Opened issues

Description

One Template to rule them all

Services available

!
?

Need anything else?

Contributors list

# 1,774
Svelte
node
TypeScr...
transit...
4 commits
# 144,501
Svelte
HTML
svelte-...
svelte3
1 commit

HTMLx

One Template to rule them all,
One Template to find them;
One Template to bring them all
and in the darkness bind() them

Jason Miller

Background

UI frameworks built around JSX — React, Preact, Inferno, Nerv and many others — have benefited from a shared set of tools for syntax highlighting, autocomplete, linting and so on.

Other frameworks, which use a template syntax built atop HTML — Svelte, Vue, Ractive, Glimmer etc — have historically been fragmented, meaning those tools need to be reinvented many times.

This (work-in-progress) document proposes a common language designed to meet the needs of all those frameworks. It is smaller in scope than the unity component specification, as it is only concerned with template syntax and has no opinions about behaviour.

Motivation and goals

A shared language would allow different frameworks to collaborate on tooling. It would also reduce friction for new users, who would no longer have to learn a new syntax for each new framework.

One key advantage of 'HTML-plus' languages is that you don't actually need tooling in order to be productive — most editors give you out-of-the-box support for things like syntax highlighting (though imperfect, as JavaScript expressions are treated as strings) and auto-closing tags. Tools like Emmet work with no additional setup. HTMLx should retain that benefit.

Syntax

Tags

A lowercase tag, like

, denotes a regular HTML element. A capitalised tag, such as
, indicates a component.

A framework might define its own special elements — these are namespaced with the framework's name. For example, Svelte provides a

 element for declaratively adding event listeners to 
window
.

Attributes

By default, attributes work exactly like their HTML counterparts:

can't touch this

As in HTML, values may be unquoted:


Attribute values can contain JavaScript expressions:

page {p}

Or they can be JavaScript expressions:

...

An expression might include characters that would cause syntax highlighting to fail in regular HTML, in which case quoting the value is permitted. The quotes do not affect how the value is parsed:

...

It's often necessary to pass a property to an element or component directly, so a shorthand is permitted — these two are equivalent:

...
...

Spread attributes allow many attributes or properties to be passed to an element or component at once:


An element or component can have multiple spread attributes, interspersed with regular ones.

Text expressions

Text can also contain JavaScript expressions:

Hello {name}!

{a} + {b} = {a + b}.

HTML expressions

In a text expression, characters like

<
and
>
are escaped. An expression can inject HTML with
{@html expression}
:

{post.title}

{@html post.content}

Whether or not

post.content
is sanitized is up to the framework, rather than a concern of HTMLx.

Control flow

Content that is conditionally rendered can be wrapped in an

{#if condition}
block, where
condition
is any valid JavaScript expression:
{#if answer === 42}
  

what was the question?

{/if}

Additional conditions can be added with

{:else if condition}
, optionally ending in an
{:else}
clause:
{#if porridge.temperature > 100}
  

too hot!

{:else if 80 > porridge.temperature}

too cold!

{:else}

just right!

{/if}

Iterating over lists of values can be done with an

{#each list as item}
block, where
list
is any valid JavaScript expression and
item
is a valid JavaScript identifier, or a destructuring pattern.

Cats of YouTube

An

#each
block can also specify an index, equivalent to the second argument in an
array.map(...)
callback:
{#each items as item, i}
  

{i}: {item.name}

{/each}

It can also specify a key expression in parentheses — again, any valid JavaScript expression — which is typically used for list diffing when items are added or removed from the middle of the list:

{#each items as item (item.id)}
  

{item.name}

{/each}

An

#each
block can also have an
{:else}
clause, which is rendered if the list is empty:
{#each shoppingCart as item}
  

{item.name}

{:else}

Your shopping cart is empty!

{/each}

TODO: Svelte also has

await
blocks — does this section need more flexibility?

Directives

A framework may support directives on elements and components for declaratively adding event listeners, transitions and so on. The general form is

type:name={value}
— the
:
character distinguishes directives from attributes.

For example, a

click
event listener could be added with an
on:click
directive:
click me!

As with attributes, the value can be quoted, and the quotes will not affect how the directive value is parsed:


script/style

An HTMLx string could include

 and 
 tags. The contents of these tags must not be interpolated, but must instead be preserved as typed.

What happens to the contents of those tags is up to the framework.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.