https://github.com/elgca/laminar-html
XHTML syntax support for Laminar
https://github.com/elgca/laminar-html
html laminar scala scalajs xhtml xml
Last synced: about 1 month ago
JSON representation
XHTML syntax support for Laminar
- Host: GitHub
- URL: https://github.com/elgca/laminar-html
- Owner: elgca
- License: mit
- Created: 2025-01-01T08:50:09.000Z (about 1 year ago)
- Default Branch: master
- Last Pushed: 2025-01-28T19:26:29.000Z (12 months ago)
- Last Synced: 2025-03-11T12:51:38.024Z (10 months ago)
- Topics: html, laminar, scala, scalajs, xhtml, xml
- Language: Scala
- Homepage:
- Size: 836 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: readme.md
- License: LICENSE
Awesome Lists containing this project
README
# Laminar-html
[English](readme_en.md)
为Laminar提供 XHTML 语法支持, 通过scala的xml字面量创建Laminar节点.
注意:
1. 该库跟scala-xml是不兼容的
2. html允许一些标签不需要手动闭合, 但是XML要求所有标签必须闭合
Invalid:
```xhtml

```
Valid:
```xhtml

```
# 使用
```scala
"io.github.elgca" %%% "laminar-html" % "0.3.1"
```
- 具备跟Laminar的完全互操作性
- 可以将XHTML、Laminar自由的组合在一起:
- ` {L.onClick --> count.update(_ + 1)} `
- `L.div( println("clicked")} />)`
- `
{L.button(L.onClick --> println("clicked"))}`
- Var[x]/Source[x]存储状态事件, 可以作为属性/子节点绑定到xhtml
```scala
val xhtmlElem = {
val count = Var(0)
Hello World
count.update(_ + 1) }
>
xHtml Button
Count: {count}
{/* Source[x] use as a child node */}
{
// this is a laimianr node.This is great, isn't it?
L.button(
className := "btn btn-primary",
onClick --> count.update(_ + 1),
"Laminar Button"
)
}
}
val laminarElem = {
L.div(
"laminar element",
xhtmlElem
)
}
// L.renderOnDomContentLoaded(document.getElementById("app"), xhtmlElem)
L.renderOnDomContentLoaded(document.getElementById("app"), laminarElem)
```
## 编译时类型检查校验
- 0.2.0开始,使用scala3的宏对属性节点进行处理,编译期间检查Events、htmlProp、htmlAttr参数类型
- 根据属性key提供更精确的类型类型判断, 例如: value只接收string,checked只接收bool
- 关闭/开启类型提示: build.sbt中配置 `val _ = System.setProperty("show_type_hints", "true")`
异常类型提示:

类型信息提示:

## onmount/onunmount生命周期事件属性
属性名不区分大小写,所以可以写如果愿意可以使用例如:
onMount/onUnmount
```scala
val element = () => {
val chart:Option[Chart] = None
{chart = initChart(ref)} }
onunmount={() => chart.foreach(_.destory())}
/>
}
```
# 允许作为子节点嵌入
1. RenderableNode, 可渲染的组件
1. 所有基础数据类型以及java.number.Number, 将会以_.toString的方式作为TextNode插入
2. Laminar的ChildNodeBase
3. xml节点
4. 以上类型的Union类型
4. 任意的Laminar Modifier
5. Tuple,`Tuple.Union <: [RenderableNode|Modifier|Seq[...]]`
5. `IterableOnce[CC]`:
1. `Option[RenderableNode/Modifier]`
7. `Seq[RenderableNode/Modifier]`
8. ...
9. `Var/Signal`
1. `Source[RenderableNode]`
11. `Source[Collection[RenderableNode]]`,
12. `Collection <: Seq | Array| js.Array| ew.JsArray | ew.JsVector | laminar.Seq`
13. `Source[Option[RenderableNode]]`
14. `js.Promise[RenderableNode]`
1. 使用 js.dynamicImport时候很有用, 可以允许你先完成其他部分,当加载完成后再挂载
# 自定义属性处理
给定隐式 `UserDefinedAttributeHandler[PropName,DataType]` 实现可以自定义属性的处理逻辑
```scala 3
given UserDefinedAttributeHandler["ggccf", String] with
override def withValue(....):Unit = {...}
override def withSourceValue(...):Unit = {...}
```

# 可选编译配置
编译配置可以通过sbt中添加`System.setProperty("show_type_hints", "true")`设置
- show_type_hints
- default true
- 是否显示类型提示,由report.info提供
- strict_event_function
- default true
- 启用严格函数校验
- 例如:onclick不能接受类似`(dom.FetchEvent) => Unit`,因为`dom.FetchEvent`无法被视作`dom.MouseEvent`
# xml interpolator
`xhtml`中的字符串插值, scala3 计划移除 xml字面量,
如果你开启了`--source future`则会禁止xml字面量
这是一份来自 https://github.com/lampepfl/xml-interpolator 的修改
```scala
val cnt = Var(0)
val onclick = () => cnt.update(_ + 1)
val reset = () => cnt.update(_ => 0)
// val c = summon[AcceptableNode["hello"]]
// println(c)
// val _ = CompileCheck("========>" + c)
val cntttttttttt = Var(0)
html"""
click me: ${cnt}
"""
```