{"id":24332569,"url":"https://github.com/elgca/laminar-html","last_synced_at":"2026-05-29T08:03:00.911Z","repository":{"id":270583787,"uuid":"910736711","full_name":"elgca/laminar-html","owner":"elgca","description":"XHTML syntax support for Laminar","archived":false,"fork":false,"pushed_at":"2025-01-28T19:26:29.000Z","size":856,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-11T12:51:38.024Z","etag":null,"topics":["html","laminar","scala","scalajs","xhtml","xml"],"latest_commit_sha":null,"homepage":"","language":"Scala","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/elgca.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":"2025-01-01T08:50:09.000Z","updated_at":"2025-01-28T19:26:32.000Z","dependencies_parsed_at":"2025-01-01T15:31:50.196Z","dependency_job_id":"fce7b727-c619-457d-aac1-328e6d318d66","html_url":"https://github.com/elgca/laminar-html","commit_stats":null,"previous_names":["elgca/laminar-html"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/elgca/laminar-html","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgca%2Flaminar-html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgca%2Flaminar-html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgca%2Flaminar-html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgca%2Flaminar-html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elgca","download_url":"https://codeload.github.com/elgca/laminar-html/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elgca%2Flaminar-html/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33642318,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"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","laminar","scala","scalajs","xhtml","xml"],"created_at":"2025-01-18T02:28:51.247Z","updated_at":"2026-05-29T08:03:00.880Z","avatar_url":"https://github.com/elgca.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Laminar-html\n\n[English](readme_en.md)\n\n为Laminar提供 XHTML 语法支持, 通过scala的xml字面量创建Laminar节点. \n\n注意: \n1. 该库跟scala-xml是不兼容的\n2. html允许一些标签不需要手动闭合, 但是XML要求所有标签必须闭合\n\nInvalid:\n\n```xhtml\n\u003cbr\u003e\n\u003cimg src=\"image.jpg\" alt=\"image\"\u003e\n\u003cinput type=\"text\" name=\"username\"\u003e\n```\n\nValid:\n\n```xhtml\n\u003cbr /\u003e\n\u003cimg src=\"image.jpg\" alt=\"示例图片\" /\u003e\n\u003cinput type=\"text\" name=\"username\" /\u003e\n```\n\n\n# 使用\n\n```scala\n\"io.github.elgca\" %%% \"laminar-html\" % \"0.3.1\"\n```\n\n- 具备跟Laminar的完全互操作性\n  - 可以将XHTML、Laminar自由的组合在一起:\n    - `\u003cbutton\u003e {L.onClick --\u003e count.update(_ + 1)} \u003c/button\u003e`\n    - `L.div(\u003cbutton onclick={() =\u003e println(\"clicked\")} /\u003e)`\n    - `\u003cdiv\u003e{L.button(L.onClick --\u003e println(\"clicked\"))}\u003c/div\u003e`\n- Var[x]/Source[x]存储状态事件, 可以作为属性/子节点绑定到xhtml\n\n```scala\nval xhtmlElem = {\n  val count = Var(0)\n  \u003cdiv\u003e\n    \u003ch1 class=\"title\"\u003eHello World\u003c/h1\u003e\n    \u003cbutton \n      class=\"btn btn-primary\"\n      onclick={() =\u003e count.update(_ + 1) }\n    \u003e\n      xHtml Button\n    \u003c/button\u003e\n    \u003cp\u003eCount: {count}\u003c/p\u003e {/* Source[x] use as a child node */}\n    {\n      // this is a laimianr node.This is great, isn't it?\n      L.button(\n        className := \"btn btn-primary\",\n        onClick --\u003e count.update(_ + 1),\n        \"Laminar Button\"\n      )\n    }\n  \u003c/div\u003e\n}\n\nval laminarElem = {\n  L.div(\n    \"laminar element\",\n    xhtmlElem \n  )\n}\n\n// L.renderOnDomContentLoaded(document.getElementById(\"app\"), xhtmlElem)\nL.renderOnDomContentLoaded(document.getElementById(\"app\"), laminarElem)\n```\n\n## 编译时类型检查校验\n\n- 0.2.0开始,使用scala3的宏对属性节点进行处理,编译期间检查Events、htmlProp、htmlAttr参数类型\n- 根据属性key提供更精确的类型类型判断, 例如: value只接收string,checked只接收bool\n- 关闭/开启类型提示: build.sbt中配置 `val _ = System.setProperty(\"show_type_hints\", \"true\")`\n\n异常类型提示:\n![img.png](images/img.png)\n\n类型信息提示:\n![typehints.png](images/typehints.png)![typeinfo.png](images/typeinfo.png)\n\n\n## onmount/onunmount生命周期事件属性 \n\n属性名不区分大小写,所以可以写如果愿意可以使用例如: \nonMount/onUnmount\n\n```scala\nval element = () =\u003e {\n  val chart:Option[Chart] = None\n  \u003cdiv\n      class=\"container\"\n      onmount={(ref:dom.Element) =\u003e {chart = initChart(ref)} }\n      onunmount={() =\u003e chart.foreach(_.destory())}\n  /\u003e\n}\n```\n\n\n# 允许作为子节点嵌入\n\n1. RenderableNode, 可渲染的组件\n   1. 所有基础数据类型以及java.number.Number, 将会以_.toString的方式作为TextNode插入\n   2. Laminar的ChildNodeBase\n   3. xml节点\n   4. 以上类型的Union类型\n   4. 任意的Laminar Modifier\n   5. Tuple,`Tuple.Union \u003c: [RenderableNode|Modifier|Seq[...]]`\n5. `IterableOnce[CC]`:\n   1. `Option[RenderableNode/Modifier]`\n   7. `Seq[RenderableNode/Modifier]`\n   8. ...\n9. `Var/Signal`\n   1. `Source[RenderableNode]`\n   11. `Source[Collection[RenderableNode]]`,\n       12. `Collection \u003c: Seq | Array| js.Array| ew.JsArray | ew.JsVector | laminar.Seq`\n   13. `Source[Option[RenderableNode]]`\n   14. `js.Promise[RenderableNode]`\n1. 使用 js.dynamicImport时候很有用, 可以允许你先完成其他部分,当加载完成后再挂载\n\n# 自定义属性处理\n\n给定隐式 `UserDefinedAttributeHandler[PropName,DataType]` 实现可以自定义属性的处理逻辑\n\n```scala 3\ngiven UserDefinedAttributeHandler[\"ggccf\", String] with\n  override def withValue(....):Unit = {...}\n  override def withSourceValue(...):Unit = {...}\n```\n\n![udattr.png](images/udattr.png)\n\n# 可选编译配置\n\n编译配置可以通过sbt中添加`System.setProperty(\"show_type_hints\", \"true\")`设置\n\n- show_type_hints\n  - default true\n  - 是否显示类型提示,由report.info提供\n- strict_event_function \n  - default true\n  - 启用严格函数校验\n  - 例如:onclick不能接受类似`(dom.FetchEvent) =\u003e Unit`,因为`dom.FetchEvent`无法被视作`dom.MouseEvent`\n\n# xml interpolator\n\n`xhtml`中的字符串插值, scala3 计划移除 xml字面量,\n如果你开启了`--source future`则会禁止xml字面量\n\n这是一份来自 https://github.com/lampepfl/xml-interpolator 的修改\n\n```scala\n        val cnt          = Var(0)\n        val onclick      = () =\u003e cnt.update(_ + 1)\n        val reset        = () =\u003e cnt.update(_ =\u003e 0)\n        //        val c = summon[AcceptableNode[\"hello\"]]\n        //        println(c)\n        //        val _ = CompileCheck(\"========\u003e\" + c)\n        val cntttttttttt = Var(0)\n        html\"\"\"\n          \u003cdiv\u003e\n            \u003cbutton\n              onclick=${onclick}\n            \u003e\n              click me: ${cnt}\n            \u003c/button\u003e\n            \u003cbutton onclick=${reset} /\u003e\n            \u003cimg src=\"test/uri\"  alt=\"image\"\u003e\n          \u003c/div\u003e\n           \"\"\"\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felgca%2Flaminar-html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felgca%2Flaminar-html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felgca%2Flaminar-html/lists"}