{"id":20170303,"url":"https://github.com/marcodpt/h","last_synced_at":"2026-05-31T01:31:21.209Z","repository":{"id":111252287,"uuid":"474198547","full_name":"marcodpt/h","owner":"marcodpt","description":"Yet another hyperscript function","archived":false,"fork":false,"pushed_at":"2022-07-04T14:41:51.000Z","size":27,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-13T15:27:38.207Z","etag":null,"topics":["dom","dom-manipulation","es6-modules","frontend","html-tags","hyperapp","hyperscript","microfrontends","mithril","server-side","server-side-rendering","tags"],"latest_commit_sha":null,"homepage":"https://marcodpt.github.io/h/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/marcodpt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2022-03-26T00:09:20.000Z","updated_at":"2022-04-08T22:19:30.000Z","dependencies_parsed_at":"2023-03-10T20:15:47.051Z","dependency_job_id":null,"html_url":"https://github.com/marcodpt/h","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcodpt%2Fh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcodpt%2Fh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcodpt%2Fh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcodpt%2Fh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcodpt","download_url":"https://codeload.github.com/marcodpt/h/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241605820,"owners_count":19989612,"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":["dom","dom-manipulation","es6-modules","frontend","html-tags","hyperapp","hyperscript","microfrontends","mithril","server-side","server-side-rendering","tags"],"created_at":"2024-11-14T01:18:13.396Z","updated_at":"2026-05-31T01:31:21.202Z","avatar_url":"https://github.com/marcodpt.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# h\nYet another hyperscript function \n\n## Examples\n - [alert](https://marcodpt.github.io/h/)\n - [chart](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fchart%2Fsamples.js)\n - [graph](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fgraph%2Fsamples.js)\n - [navbar](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fnavbar%2Fsamples.js)\n - [SPA](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fspa%2Fsamples.js)\n\n## Motivation\n - Present hyperscript as an es6 module\n - Allow to be used in server side in text mode\n - Allow to be used in frontend in DOM mode\n - Wrap any h function (\n   [react](https://github.com/facebook/react),\n   [hyperapp](https://github.com/jorgebucaran/hyperapp),\n   [mithril](https://github.com/MithrilJS/mithril.js/)...)\n   in the same consistent API\n - Generate all HTML tags as functions\n - Generate your own custom elements with great experience\n\n## Definition\nAn `element` is a function with the following signature\n\n### element(params, children) -\u003e node\n - object `params`: is the params that element recieve as attributes\n - array `children`: is the children nodes of element\n - return DOM `node`: the DOM node representing the element\n\n## Usage\n### DOM mode\n```js\nimport {hDom as h} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'\n\nconst e = h('button', {\n  click: () =\u003e console.log('Hi!') \n}, 'Click me!')\n\nconsole.log(e.outerHTML)\n//\u003cbutton\u003eClick me!\u003c/button\u003e\n\ne.click()\n//Hi!\n```\n\n### DOM mode with HTML tags\n```js\nimport {hDom as h} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'\n\nconst e = h(({button}) =\u003e {\n  button({\n    click: () =\u003e console.log('Hi!') \n  }, 'Click me!')\n})\n\nconsole.log(e.outerHTML)\n//\u003cbutton\u003eClick me!\u003c/button\u003e\n\ne.click()\n//Hi!\n```\n\n### Text mode\n```js\nimport {hText as h} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'\n\nconsole.log(h('button', {\n  type: 'button'\n  disabled: true\n}, [\n  h('i', {\n    class: 'icon-check'\n  }),\n  h('span', 'Submit!')\n]))\n//\u003cbutton type=\"button\" disabled\u003e\n//  \u003ci class=\"icon-check\" /\u003e\n//  \u003cspan\u003eSubmit!\u003c/span\u003e\n//\u003c/button\n```\n\n### Text mode with HTML tags\n```js\nimport {hText as h} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'\n\nconsole.log(h(({\n  button, i, span\n}) =\u003e button({\n  type: 'button'\n  disabled: true\n}, [\n  i({\n    class: 'icon-check'\n  }),\n  span('Submit!')\n])))\n//\u003cbutton type=\"button\" disabled\u003e\n//  \u003ci class=\"icon-check\" /\u003e\n//  \u003cspan\u003eSubmit!\u003c/span\u003e\n//\u003c/button\n```\n\n### Create your own html elements\n```js\nimport {hDom as html} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'\n\nconst myButton = (attributes, children) =\u003e html(({\n  button, i\n}, resolvedAttrs, resolvedChildren) =\u003e {\n  //NO MATTER WHAT USER PUTS IN ATTRIBUTES OR CHILDREN\n\n  //resolvedAttrs is always an object\n  //with kebab case keys\n  //with string or functions values \n\n  //resolvedChildren is always a DOM array\n\n  return button({\n    class: \"btn btn-\"+resolvedAttrs.btn\n  }, [\n    resolvedAttrs.icon ? i({class: resolvedAttrs.icon}) : null\n  ].concat(children))\n}, attributes, children)\n\nconsole.log(myButton({\n  btn: 'primary',\n  icon: 'fas fa-play'\n}, ' Run!').outerHTML)\n//\u003cbutton class=\"btn btn-primary\"\u003e\u003ci class=\"fas fa-play\"\u003e\u003c/i\u003e Run!\u003c/button\u003e\n```\n\n### Syntax sugar\n```js\nimport {hText as html} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'\n\n//attributes are optional, text nodes are handled automatic\nconsole.log(html(({div}) =\u003e div(\"Hello!\")))\n//\u003cdiv\u003eHello!\u003c/div\u003e\n\n//class might be an array\nconsole.log(html(({div}) =\u003e div({\n  class: 'container mx-auto'\n}, \"Hello!\")))\n//\u003cdiv class=\"container mx-auto\"\u003eHello!\u003c/div\u003e\nconsole.log(html(({div}) =\u003e div({\n  class: [\n    'container',\n    'mx-auto'\n  ]\n}, \"Hello!\")))\n//\u003cdiv class=\"container mx-auto\"\u003eHello!\u003c/div\u003e\n\n//style might be an object with case conversion\nconsole.log(html(({div}) =\u003e div({\n  style: 'white-space: pre-wrap'\n}, \"Hello!\")))\n//\u003cdiv style=\"white-space: pre-wrap\"\u003eHello!\u003c/div\u003e\nconsole.log(html(({div}) =\u003e div({\n  style: {\n    'white-space': 'pre-wrap'\n  }\n}, \"Hello!\")))\n//\u003cdiv style=\"white-space: pre-wrap\"\u003eHello!\u003c/div\u003e\nconsole.log(html(({div}) =\u003e div({\n  style: {\n    whiteSpace: 'pre-wrap'\n  }\n}, \"Hello!\")))\n//\u003cdiv style=\"white-space: pre-wrap\"\u003eHello!\u003c/div\u003e\n\n//attributes have case conversion too\nconsole.log(html(({div}) =\u003e div({\n  'data-bind': 'some data...'\n}, \"Hello!\")))\n//\u003cdiv data-bind=\"some data...\"\u003eHello!\u003c/div\u003e\nconsole.log(html(({div}) =\u003e div({\n  dataBind: 'some data...'\n}, \"Hello!\")))\n//\u003cdiv data-bind=\"some data...\"\u003eHello!\u003c/div\u003e\n```\n\n### Wrapping hyperapp with this API\n```js\nimport {h, text, app} from \"https://unpkg.com/hyperapp\"\nimport {wrapper} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'\n\nconst html = wrapper(h, text)\n\nconst AddTodo = (state) =\u003e ({\n  ...state,\n  value: \"\",\n  todos: state.todos.concat(state.value),\n})\n\nconst NewValue = (state, event) =\u003e ({\n  ...state,\n  value: event.target.value,\n})\n\napp({\n  init: { todos: [], value: \"\" },\n  view: ({ todos, value }) =\u003e html(({\n    main, h1, input, ul, li, button\n  }) =\u003e main([\n    h1(\"To do list\"),\n    input({ type: \"text\", oninput: NewValue, value }),\n    ul(todos.map((todo) =\u003e li(todo))),\n    button({ onclick: AddTodo }, \"New!\"),\n  ])),\n  node: document.getElementById(\"app\"),\n})\n```\n\n## Tests\n - [wrapper](https://marcodpt.github.io/h/tests.html?url=.%2Ftests%2Fwrapper.js)\n - [hDom](https://marcodpt.github.io/h/tests.html?url=.%2Ftests%2Fdom.js)\n - [hText](https://marcodpt.github.io/h/tests.html?url=.%2Ftests%2Ftext.js)\n\n## Contributing\nYes please! It is a very simple project, no guidelines, any contribution is\ngreatly appreciated!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcodpt%2Fh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcodpt%2Fh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcodpt%2Fh/lists"}