{"id":13452297,"url":"https://github.com/htmlx-org/HTMLx","last_synced_at":"2025-03-23T19:34:05.258Z","repository":{"id":37751886,"uuid":"131606285","full_name":"htmlx-org/HTMLx","owner":"htmlx-org","description":"One Template to rule them all","archived":false,"fork":false,"pushed_at":"2020-01-23T15:32:21.000Z","size":6,"stargazers_count":575,"open_issues_count":13,"forks_count":8,"subscribers_count":23,"default_branch":"master","last_synced_at":"2024-07-31T07:18:40.506Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/htmlx-org.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-04-30T14:31:52.000Z","updated_at":"2024-07-24T09:58:48.000Z","dependencies_parsed_at":"2022-09-01T04:12:37.011Z","dependency_job_id":null,"html_url":"https://github.com/htmlx-org/HTMLx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htmlx-org%2FHTMLx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htmlx-org%2FHTMLx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htmlx-org%2FHTMLx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htmlx-org%2FHTMLx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/htmlx-org","download_url":"https://codeload.github.com/htmlx-org/HTMLx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221900856,"owners_count":16898989,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T07:01:19.826Z","updated_at":"2024-10-28T18:31:00.808Z","avatar_url":"https://github.com/htmlx-org.png","language":null,"funding_links":[],"categories":["Others","others"],"sub_categories":[],"readme":"# HTMLx\n\n\u003cem\u003eOne Template to rule them all,\u003cbr\u003e\nOne Template to find them;\u003cbr\u003e\nOne Template to bring them all\u003cbr\u003e\nand in the darkness bind() them\u003c/em\u003e\n\n— [Jason Miller](https://twitter.com/_developit/status/990943081066217472)\n\n## Background\n\nUI 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.\n\nOther 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.\n\nThis (**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](https://github.com/TheLarkInn/unity-component-specification), as it is only concerned with template syntax and has no opinions about behaviour.\n\n## Motivation and goals\n\nA 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.\n\nOne 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.\n\n## Syntax\n\n### Tags\n\nA lowercase tag, like `\u003cdiv\u003e`, denotes a regular HTML element. A capitalised tag, such as `\u003cWidget\u003e`, indicates a *component*.\n\nA framework might define its own special elements — these are namespaced with the framework's name. For example, Svelte provides a `\u003csvelte:window\u003e` element for declaratively adding event listeners to `window`.\n\n### Attributes\n\nBy default, attributes work exactly like their HTML counterparts:\n\n```html\n\u003cdiv class=\"foo\"\u003e\n  \u003cbutton disabled\u003ecan't touch this\u003c/button\u003e\n\u003c/div\u003e\n```\n\nAs in HTML, values may be unquoted:\n\n```html\n\u003cinput type=checkbox\u003e\n```\n\nAttribute values can contain JavaScript expressions:\n\n```html\n\u003ca href=\"page/{p}\"\u003epage {p}\u003c/a\u003e\n```\n\nOr they can *be* JavaScript expressions:\n\n```html\n\u003cbutton disabled={!clickable}\u003e...\u003c/button\u003e\n```\n\nAn 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:\n\n```html\n\u003cbutton disabled=\"{number !== 42}\"\u003e...\u003c/button\u003e\n```\n\nIt's often necessary to pass a property to an element or component directly, so a shorthand is permitted — these two are equivalent:\n\n```html\n\u003cbutton disabled={disabled}\u003e...\u003c/button\u003e\n\u003cbutton {disabled}\u003e...\u003c/button\u003e\n```\n\n*Spread attributes* allow many attributes or properties to be passed to an element or component at once:\n\n```html\n\u003cWidget {...things}/\u003e\n```\n\nAn element or component can have multiple spread attributes, interspersed with regular ones.\n\n\n### Text expressions\n\nText can also contain JavaScript expressions:\n\n```html\n\u003ch1\u003eHello {name}!\u003c/h1\u003e\n\u003cp\u003e{a} + {b} = {a + b}.\u003c/p\u003e\n```\n\n### HTML expressions\n\nIn a text expression, characters like `\u003c` and `\u003e` are escaped. An expression can inject HTML with `{@html expression}`:\n\n```html\n\u003cdiv class=\"blog-post\"\u003e\n  \u003ch1\u003e{post.title}\u003c/h1\u003e\n  {@html post.content}\n\u003c/div\u003e\n```\n\nWhether or not `post.content` is sanitized is up to the framework, rather than a concern of HTMLx.\n\n\n### Control flow\n\nContent that is conditionally rendered can be wrapped in an `{#if condition}` block, where `condition` is any valid JavaScript expression:\n\n```html\n{#if answer === 42}\n  \u003cp\u003ewhat was the question?\u003c/p\u003e\n{/if}\n```\n\nAdditional conditions can be added with `{:else if condition}`, optionally ending in an `{:else}` clause:\n\n```html\n{#if porridge.temperature \u003e 100}\n  \u003cp\u003etoo hot!\u003c/p\u003e\n{:else if 80 \u003e porridge.temperature}\n  \u003cp\u003etoo cold!\u003c/p\u003e\n{:else}\n  \u003cp\u003ejust right!\u003c/p\u003e\n{/if}\n```\n\nIterating 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.\n\n```html\n\u003ch1\u003eCats of YouTube\u003c/h1\u003e\n\u003cul\u003e\n  {#each cats as cat}\n    \u003cli\u003e\u003ca target=\"_blank\" href={cat.video}\u003e{cat.name}\u003c/a\u003e\u003c/li\u003e\n  {/each}\n\u003c/ul\u003e\n```\n\nAn `#each` block can also specify an *index*, equivalent to the second argument in an `array.map(...)` callback:\n\n```html\n{#each items as item, i}\n  \u003cp\u003e{i}: {item.name}\u003c/p\u003e\n{/each}\n```\n\nIt 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:\n\n```html\n{#each items as item (item.id)}\n  \u003cp\u003e{item.name}\u003c/p\u003e\n{/each}\n```\n\nAn `#each` block can also have an `{:else}` clause, which is rendered if the list is empty:\n\n```html\n{#each shoppingCart as item}\n  \u003cp\u003e{item.name}\u003c/p\u003e\n{:else}\n  \u003cp\u003eYour shopping cart is empty!\u003c/p\u003e\n{/each}\n```\n\n*TODO: Svelte also has `await` blocks — does this section need more flexibility?*\n\n\n### Directives\n\nA 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.\n\nFor example, a `click` event listener could be added with an `on:click` directive:\n\n```html\n\u003cbutton on:click={handleClick}\u003eclick me!\u003c/button\u003e\n```\n\nAs with attributes, the value can be quoted, and the quotes will not affect how the directive value is parsed:\n\n```html\n\u003cinput on:change=\"{e =\u003e alert(`the value is ${e.target.value}`)}\"\u003e\n```\n\n### script/style\n\nAn HTMLx string could include `\u003cscript\u003e` and `\u003cstyle\u003e` tags. The contents of these tags must *not* be interpolated, but must instead be preserved as typed.\n\nWhat happens to the contents of those tags is up to the framework.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtmlx-org%2FHTMLx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhtmlx-org%2FHTMLx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtmlx-org%2FHTMLx/lists"}