{"id":13793536,"url":"https://github.com/davidjamesstone/hyperviews","last_synced_at":"2025-07-26T03:04:10.123Z","repository":{"id":69183794,"uuid":"118947250","full_name":"davidjamesstone/hyperviews","owner":"davidjamesstone","description":"Template language that produces `h` output","archived":false,"fork":false,"pushed_at":"2018-12-30T00:37:09.000Z","size":628,"stargazers_count":25,"open_issues_count":1,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-07-02T16:11:39.169Z","etag":null,"topics":["html","hyperapp","hyperscript","template-language"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/davidjamesstone.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-25T17:50:17.000Z","updated_at":"2022-05-20T03:22:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"c9486ebf-68f6-4692-99d4-9a88bc9e37c3","html_url":"https://github.com/davidjamesstone/hyperviews","commit_stats":{"total_commits":46,"total_committers":1,"mean_commits":46.0,"dds":0.0,"last_synced_commit":"eb9e33a12220f2952d70a74e0df1da148234d11c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/davidjamesstone/hyperviews","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjamesstone%2Fhyperviews","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjamesstone%2Fhyperviews/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjamesstone%2Fhyperviews/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjamesstone%2Fhyperviews/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidjamesstone","download_url":"https://codeload.github.com/davidjamesstone/hyperviews/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidjamesstone%2Fhyperviews/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267109941,"owners_count":24037627,"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","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["html","hyperapp","hyperscript","template-language"],"created_at":"2024-08-03T23:00:23.676Z","updated_at":"2025-07-26T03:04:10.070Z","avatar_url":"https://github.com/davidjamesstone.png","language":"JavaScript","readme":"# hyperviews\n\n`hyperviews` is a template language that transforms to hyperscript.\n\nUse it as a build tool with any `h(tag, props, children)` compliant framework e.g. React, preact or hyperapp.\n\n```js\nconst hv = require('hyperviews')\n\nhv(\"\u003cdiv id='foo'\u003e{state.name}\u003c/div\u003e\")\n// =\u003e h('div', { id: 'foo' }, (state.name))\n```\n\n### Installation\n\n`npm i hyperviews`\n\n### API\n\n`hyperviews(tmpl, mode, name, argstr)`\n\n- `tmpl` (required) - The template string.  \n- `mode` - The output format. Can be one of [`raw`, `esm`, `cjs`, `browser`], or if any other value is passed the function is exported as a variable with that name. The default is `raw`.\n- `name` - The default output function name. The default is `view`.\n- `args` - The default function arguments. The default is `props state`.\n\n\n### CLI\n\nReads the template from stdin, \n\n`cat examples/test.html | hyperviews --mode esm --name foo --args bar \u003e examples/test.js`\n\nSee [more CLI examples](./test/cli.js)\n\n\n\n## Template language\n\n\n### Interpolation\n\nUse curly braces in attributes and text.\n\n```html\n\u003cdiv\u003e\n  \u003ca class={state.class} href='http://www.google.co.uk?q={state.query}'\u003e\u003c/a\u003e\n  My name is {state.name} my age is {state.age} and I live at {state.address}\n\u003c/div\u003e\n```\n\nSee [more interpolation examples](./test/interpolation.js)\n\n\n\n### Conditionals\n\nThere are two forms of conditional.\n\nUsing an `if` attribute.\n\n```html\n\u003cspan if='state.bar === 1'\u003eShow Me!\u003c/span\u003e\n```\n\nOr using tags `\u003cif\u003e`, `\u003celseif\u003e` and `\u003celse\u003e`\n\n```html\n\u003cdiv\u003e\n  \u003cif condition='state.bar === 1'\u003e\n    \u003cspan\u003e1\u003c/span\u003e\n  \u003celseif condition='state.bar === 2'\u003e\n    \u003cspan\u003e2\u003c/span\u003e\n  \u003celse\u003e\n    \u003cspan\u003ebar is neither 1 or 2, it's {state.bar}!\u003c/span\u003e\n  \u003c/if\u003e\n\u003c/div\u003e\n```\n\n`if` tags can be [nested](./test/conditionals.js#L84).\n\nSee [more conditional examples](./test/conditionals.js)\n\n\n\n### Iteration\n\nThe `each` attribute can be used to repeat over items in an Array.\nThree additional variables are available during each iteration: `$value`, `$index` and `$target`.\n\nIt supports keyed elements as shown here.\n\n```html\n\u003cul\u003e\n  \u003cli each='post in state.posts' key={post.id}\u003e\n    \u003cspan\u003e{post.title} {$index}\u003c/span\u003e\n  \u003c/li\u003e\n\u003c/ul\u003e\n```\n\nproduces\n\n```js\nh('ul', {}, (state.posts || []).map(function ($value, $index, $target) {\n  const post = $value\n  return h('li', { key: (post.id) }, h('span', {}, (post.title) + ' ' + ($index)))\n}, this))\n```\n\nSee [more iteration examples](./test/iteration.js)\n\n\n\n### Events\n\n```html\n\u003ca href='http://example.com' onclick=this.onClick\u003e{state.foo}\u003c/a\u003e\n```\n\nproduces this output\n\n\n```js\nh('a', { href: 'http://example.com', onclick: this.onClick, (state.foo))\n```\n\nSee [more event examples](./test/events.js)\n\n### Style\n\nThe `style` attribute expects an object\n\n```html\n\u003cp style=\"{ color: state.color, fontSize: '12px' }\"\u003e\u003c/p\u003e\n```\n\nproduces this output\n\n```js\nh('p', { style: { color: state.color, fontSize: '12px' } })\n```\n\n\n\n### Literal\n\nThe `script` tag literally outputs it's contents.\n\n```html\n\u003cscript\u003e\n  import { h, Component } from 'preact'\n  import MyComponent from './component.js'\n\u003c/script\u003e\n```\n\nThis is also useful for recursive nodes, e.g. a tree\n\n```html\n\u003cif condition=state.children\u003e\n  \u003cdiv\u003e\n    \u003ca href='#{state.path}'\u003e{state.name}\u003c/a\u003e\n    \u003cul\u003e\n      \u003cli each='child in state.children'\u003e\n        \u003cscript\u003eview(props, child)\u003c/script\u003e\n      \u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/div\u003e\n\u003celse\u003e\n  \u003ca href='#{state.path}'\u003e{state.name}\u003c/a\u003e\n\u003c/if\u003e\n```\n\nproduces this output\n\n```js\nfunction view (props, state) {\n  return (function () {\n    if (state.children) {\n      return h('div', {}, [\n        h('a', { href: '#' + (state.path) }, (state.name)),\n        h('ul', {}, (state.children || []).map(function ($value, $index, $target) {\n          var child = $value\n          return h('li', {}, view(props, child))\n        }))\n      ])\n    } else {\n      return h('a', { href: '#' + (state.path) }, (state.name))\n    }\n  })()\n}\n```\n\nSee [more literal examples](./test/literal.js)\n\n\n\n### Function\n\nThe `function` tag outputs a function, returning it's contents.\nSupports `name` and `args` attributes.\n\n```html\n\u003cfunction name='MyComponent' args='x y z'\u003e\n  \u003cdiv\u003e{x}\u003c/div\u003e\n\u003c/script\u003e\n```\n\nproduces this output\n\n```js\nfunction MyComponent (x, y, z) {\n  return h('div', null, (x))\n}\n```\n\n\n\n### Components\n\nComponents are declared with if the tag starts with a capital letter.\n\n```html\n\u003cdiv\u003e\n  \u003cMyComponent foo='bar' /\u003e\n\u003c/div\u003e\n```\n\nproduces this output\n\n```js\nh('div', null, h(MyComponent, { foo: 'bar' }))\n```\n\n\n### Module example\n\nHow you structure your app is down to you.\nI like to keep js and html in separate files so a component might look like this:\n\n- MyComponent\n  - view.html (The template file e.g. `\u003cdiv\u003e{state.name}\u003c/div\u003e`)\n  - view.html.js (The transformed `h` output of the file above)\n  - index.js (Imports the transformed view and exports the component)\n\nbut if you want you could build entire modules in a html file like this:\n\n```html\n\u003cscript\u003e\n\n  import { h, Component } from 'preact'\n\n  export default class MyComponent extends Component {\n    constructor (props) {\n      super(props)\n      this.render = view\n\n      this.onSubmit = e =\u003e {\n        e.preventDefault()\n        // ...\n      }\n    }\n  }\n\n\u003c/script\u003e\n\n\u003cfunction\u003e\n  \u003csection\u003e\n    \u003cform onsubmit=this.onSubmit\u003e\n      \u003cinput type=text name=text value={state.text} /\u003e\n      \u003cinput type=text name=description value={state.description} /\u003e\n    \u003c/form\u003e\n  \u003c/section\u003e        \n\u003c/function\u003e\n```\n\nCompiles to\n\n```js\nimport { h, Component } from 'preact'\n\nexport default class MyComponent extends Component {\n  constructor (props) {\n    super(props)\n    this.render = view\n\n    this.onSubmit = e =\u003e {\n      e.preventDefault()\n    // ...\n    }\n  }\n}\n\nfunction view (props, state) {\n  return h('section', null, h('form', { onsubmit: this.onSubmit }, [\n    h('input', { type: 'text', name: 'text', value: (state.text) }),\n    h('input', { type: 'text', name: 'description', value: (state.description) })\n  ]))\n}\n```\n\nMore examples [here](https://github.com/davidjamesstone/hyperviews/tree/master/examples)\n\n\nUsing `browserify`?\nThen install the `hyperviewify` transform so you can simply require templates.\n\n`const view = require('./my-view.html')`\n\n`npm i hyperviewify`\n","funding_links":[],"categories":["Utilities V1"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidjamesstone%2Fhyperviews","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidjamesstone%2Fhyperviews","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidjamesstone%2Fhyperviews/lists"}