{"id":47444104,"url":"https://github.com/JuliaWeb/Hyperscript.jl","last_synced_at":"2026-04-06T13:00:57.803Z","repository":{"id":37775557,"uuid":"115545562","full_name":"JuliaWeb/Hyperscript.jl","owner":"JuliaWeb","description":"Hyperscript: A lightweight DOM representation for Julia","archived":false,"fork":false,"pushed_at":"2024-01-16T12:23:20.000Z","size":248,"stargazers_count":104,"open_issues_count":15,"forks_count":11,"subscribers_count":4,"default_branch":"master","last_synced_at":"2026-03-19T18:43:16.888Z","etag":null,"topics":["css","dsl","html","hyperscript","svg"],"latest_commit_sha":null,"homepage":"","language":"Julia","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JuliaWeb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2017-12-27T18:02:44.000Z","updated_at":"2025-03-05T14:17:37.000Z","dependencies_parsed_at":"2024-06-21T17:39:49.592Z","dependency_job_id":"face0977-36e0-4470-9585-4505d4565ad0","html_url":"https://github.com/JuliaWeb/Hyperscript.jl","commit_stats":null,"previous_names":["yurivish/hyperscript.jl"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/JuliaWeb/Hyperscript.jl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FHyperscript.jl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FHyperscript.jl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FHyperscript.jl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FHyperscript.jl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JuliaWeb","download_url":"https://codeload.github.com/JuliaWeb/Hyperscript.jl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaWeb%2FHyperscript.jl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31473271,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T08:36:52.050Z","status":"ssl_error","status_checked_at":"2026-04-06T08:36:51.267Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["css","dsl","html","hyperscript","svg"],"created_at":"2026-03-23T06:00:59.902Z","updated_at":"2026-04-06T13:00:57.798Z","avatar_url":"https://github.com/JuliaWeb.png","language":"Julia","readme":"# Hyperscript\n\nHyperscript is a package for working with HTML, SVG, and CSS in Julia.\n\nWhen using this library you automatically get:\n\n* A concise DSL for writing HTML, SVG, and CSS.\n* Flexible ways to combine DOM pieces together into larger components.\n* Safe and automatic HTML-escaping.\n* Lightweight and optional support for scoped CSS.\n* Lightweight and optional support for CSS unit arithmetic.\n\n## Usage\n\nHyperscript introduces the `m` function for creating markup nodes:\n\n```julia\nm(\"div\", class=\"entry\",\n    m(\"h1\", \"An Important Announcement\"))\n```\n\nNodes can be used as a templates:\n\n```julia\nconst div = m(\"div\")\nconst h1 = m(\"h1\")\ndiv(class=\"entry\", h1(\"An Important Announcement\"))\n```\n\nDot syntax is supported for setting class attributes:\n\n```julia\nconst div = m(\"div\")\nconst h1 = m(\"h1\")\ndiv.entry(h1(\"An Important Announcement\"))\n```\n\nChained dot calls turn into multiple classes:\n\n```julia\nm(\"div\").header.entry\n```\n\nThe convenience macro `@tags` can be used to quickly declare common tags:\n\n```julia\n@tags div h1\nconst entry = div.entry\nentry(h1(\"An Important Announcement\"))\n```\n\nArrays, tuples, and generators are recursively flattened, linearizing nested structures for display:\n\n```julia\n@tags div h1\nconst entry = div.entry\ndiv(entry.([\"$n Fast $n Furious\" for n in 1:10])) # joke © Glen Chiacchieri\n```\n\nAttribute names with hyphens can be written using camelCase:\n\n```julia\nm(\"meta\", httpEquiv=\"refresh\")\n# turns into \u003cmeta http-equiv=\"refresh\" /\u003e\n```\n\nFor attributes that are _meant_ to be camelCase, Hyperscript still does the right thing:\n\n```julia\nm(\"svg\", viewBox=\"0 0 100 100\")\n# turns into \u003csvg viewBox=\"0 0 100 100\"\u003e\u003csvg\u003e\n```\n\nAttribute names that happen to be Julia keywords can be specified with `:attr =\u003e value` syntax:\n\n```julia\nm(\"input\"; :type =\u003e \"text\")\n# turns into \u003cinput type=\"text\" /\u003e\n```\n\nHyperscript automatically HTML-escapes children of DOM nodes:\n\n```julia\nm(\"p\", \"I am a paragraph with a \u003c inside it\")\n# turns into \u003cp\u003eI am a paragraph with a \u0026#60; inside it\u003c/p\u003e\n```\n\nYou can disable escaping using `@tags_noescape` for writing an inline style or script:\n\n```julia\n@tags_noescape script\nscript(\"console.log('\u003c(0_0\u003c) \u003c(0_0)\u003e (\u003e0_0)\u003e KIRBY DANCE')\")\n```\n\nNodes can be printed compactly with `print` or `show`, or pretty-printed by wrapping a node in `Pretty`:\n\n```julia\nnode = m(\"div\", class=\"entry\", m(\"h1\", \"An Important Announcement\"))\n\nprint(node)\n# \u003cdiv class=\"entry\"\u003e\u003ch1\u003eAn Important Announcement\u003c/h1\u003e\u003c/div\u003e\n\nprint(Pretty(node))\n# \u003cdiv class=\"entry\"\u003e\n#  \u003ch1\u003eAn Important Announcement\u003c/h1\u003e\n# \u003c/div\u003e\n```\n\nNote that the extra white space can affect layout, particularly in conjunction with CSS properties like [white-space](https://developer.mozilla.org/en-US/docs/Web/CSS/white-space).\n\nVectors of nodes can be written as an html-file using the `savehtml` function. Here's an example:\n\n```julia\n@tags head meta body h1 h2 ul li\n\ndoc = [\n    head(\n      meta(charset=\"UTF-8\"),\n      ),\n    body(\n         [\n          h1(\"My title\"),\n             \"Some text\",\n             h2(\"A list\"),\n             ul(li.([\"First point\", \"Second Point\"]))\n         ] )\n];\n\nsavehtml(\"/tmp/hyper.html\", doc);\n\nread(\"/tmp/hyper.html\", String)\n# \u003c!doctype html\u003e\n# \u003chtml\u003e\u003chead\u003e\u003cmeta charset=\"UTF-8\" /\u003e\u003c/head\u003e\u003cbody\u003e\u003ch1\u003eMy title\u003c/h1\u003eSome text\u003ch2\u003eA list\u003c/h2\u003e\u003cul\u003e\u003cli\u003eFirst point\u003c/li\u003e\u003cli\u003eSecond Point\u003c/li\u003e\u003c/ul\u003e\u003c/body\u003e\u003c/html\u003e\n```\n\n## CSS\n\nIn addition to HTML and SVG, Hyperscript also supports CSS:\n\n```julia\ncss(\".entry\", fontSize=\"14px\")\n# turns into .entry { font-size: 14px; }\n```\n\nCSS nodes can be nested inside each other:\n\n```julia\ncss(\".entry\",\n    fontSize=\"14px\",\n    css(\"h1\", textDecoration=\"underline\"),\n    css(\"\u003e p\", color=\"#999\"))\n# turns into\n# .entry { font-size: 14px; }\n# .entry h1 { text-decoration: underline; }\n# .entry \u003e p { color: #999; }\n```\n\n`@media` queries are also supported:\n\n```julia\ncss(\"@media (min-width: 1024px)\",\n    css(\"p\", color=\"red\"))\n# turns into\n# @media (min-width: 1024px) {\n#   p { color: red; }\n# }\n```\n\n## Scoped Styles\n\nHyperscript supports scoped styles. They are implemented by adding unique attributes to nodes and selecting them via [attribute selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors):\n\n```julia\n@tags p\n@tags_noescape style\n\n# Create a scoped `Style` object\ns1 = Style(css(\"p\", fontWeight=\"bold\"), css(\"span\", color=\"red\"))\n\n# Apply the style to a DOM node\ns1(p(\"hello\"))\n# turns into \u003cp v-style1\u003ehello\u003c/p\u003e\n\n# Insert the corresponding styles into a \u003cstyle\u003e tag\nstyle(styles(s1))\n# turns into\n# \u003cstyle\u003e\n#   p[v-style1] {font-weight: bold;}\n#   span[v-style1] {color: red;}\n# \u003c/style\u003e\n\n```\n\nScoped styles are scoped to the DOM subtree where they are applied. Styled nodes function as cascade barriers — parent styles do not leak into styled child nodes:\n\n```julia\n# Create a second scoped style\ns2 = Style(css(\"p\", color=\"blue\"))\n\n# Apply `s1` to the parent and `s2` to a child.\n# Note the `s1` style does not apply to the child styled with `s2`.\ns1(p(p(\"outer\"), s2(p(\"inner\"))))\n# turns into\n# \u003cp v-style1\u003e\n#   \u003cp v-style1\u003eouter\u003c/p\u003e\n#   \u003cp v-style2\u003einner\u003c/p\u003e\n# \u003c/p\u003e\n\nstyle(styles(s1), styles(s2))\n# turns into\n# \u003cstyle\u003e\n#   p[v-style1] {font-weight: bold;}\n#   span[v-style1] {color: red;}\n#   p[v-style2] {color: blue;}\n# \u003c/style\u003e\n```\n\n## CSS Units\n\nHyperscript supports a concise syntax for CSS unit arithmetic:\n\n```julia\nusing Hyperscript\n\ncss(\".foo\", width=50px)\n# turns into .foo {width: 50px;}\n\ncss(\".foo\", width=50px + 2 * 100px)\n# turns into .foo {width: 250px;}\n\ncss(\".foo\", width=(50px + 50px) + 2em)\n# turns into .foo {width: calc(100px + 2em);}\n```\n\nSupported units are `px`, `pt`, `em`,`vh`, `vw`, `vmin`, `vmax`, and `pc` for percent.\n\n---\n\nI'd like to create a more comprehensive guide to the full functionality available in Hyperscript at some point. For now here's a list of some of the finer points:\n\n* Nodes are immutable — any derivation of new nodes from existing nodes will leave existing nodes unchanged.\n* Calling an existing node with with more children creates a new node with the new children appended.\n* Calling an existing node with more attributes creates a new node whose attributes are the `merge` of the existing and new attributes.\n* `div.fooBar` adds the CSS class `foo-bar`. To add the camelCase class `fooBar` you can use the dot syntax with a string: `div.\"fooBar\"`\n* The dot syntax always _adds_ to the CSS class. This is why chaining (`div.foo.bar.baz`) adds all three classes in sequence. \n* Tags defined with `@tags_noescape` only \"noescape\" one level deep. Children of children will still be escaped according to their own rules.\n* Using `nothing` as the value of a DOM attribute creates a valueless attribute, e.g. `\u003cinput checked /\u003e`.\n","funding_links":[],"categories":["Web Security"],"sub_categories":["HTTP and Web Frameworks"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJuliaWeb%2FHyperscript.jl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJuliaWeb%2FHyperscript.jl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJuliaWeb%2FHyperscript.jl/lists"}