#html #jsx #html-macro

typed-html-macros

为Rust编写的类型检查JSX(proc_macro crate)

5个版本

0.2.2 2020年2月7日
0.2.1 2019年6月28日
0.2.0 2019年3月16日
0.1.1 2018年11月29日
0.1.0 2018年11月17日

#29#jsx

Download history 118/week @ 2024-03-11 133/week @ 2024-03-18 76/week @ 2024-03-25 153/week @ 2024-04-01 139/week @ 2024-04-08 95/week @ 2024-04-15 82/week @ 2024-04-22 45/week @ 2024-04-29 81/week @ 2024-05-06 92/week @ 2024-05-13 66/week @ 2024-05-20 71/week @ 2024-05-27 105/week @ 2024-06-03 37/week @ 2024-06-10 52/week @ 2024-06-17 57/week @ 2024-06-24

257 每月下载量
2 个crate中(通过 typed-html)使用

MPL-2.0+

47KB
1.5K SLoC

Build Status

typed-html

此crate提供了用于在Rust代码中使用类似JSX语法的宏html!来构建HTML文档。

快速预览

let mut doc: DOMTree<String> = html!(
    <html>
        <head>
            <title>"Hello Kitty"</title>
            <meta name=Metadata::Author content="Not Sanrio Co., Ltd"/>
        </head>
        <body>
            <h1>"Hello Kitty"</h1>
            <p class="official">
                "She is not a cat. She is a human girl."
            </p>
            { (0..3).map(|_| html!(
                <p class="emphasis">
                    "Her name is Kitty White."
                </p>
            )) }
            <p class="citation-needed">
                "We still don't know how she eats."
            </p>
        </body>
    </html>
);
let doc_str = doc.to_string();

语法

此宏主要遵循JSX语法,但有一些不同

  • 文本节点必须加引号,因为Rust的词法分析器只能处理字符串字面量之外的一定数量的内容。所以,你不需要写<p>Hello</p>,你需要写<p>"Hello"</p>。(如果忘记这样做,解析器会抛出一个错误。)
  • 元素属性将接受简单的Rust表达式,但解析器有其局限性,因为它不是一个完整的Rust解析器。你可以使用字面量、变量、点属性、类型构造函数和单个函数或方法调用。如果你使用解析器当前无法处理的内容,它会报错。如果解析器不理解表达式,你可以将表达式放在大括号或括号内。你可以在大括号或括号块中使用任何Rust代码。

有效的HTML5

此宏只接受有效的HTML5标签,不接受标记为实验性或过时的标签或属性。如果它不接受你想要的内容,我们可以在pull request中进行讨论(特别是实验性标签和属性,主要被省略以节省篇幅,你欢迎实现它们)。

由于结构验证依赖于类型系统,因此它是必要的,一些元素将有一个或多个必需的子元素,任何接受子元素的元素将对子元素类型有约束,通常是一个由HTML规范定义的广泛组。许多元素对子元素的子元素有约束,或要求可选元素有特定的顺序,这目前尚未验证。

属性值

属性值位置中的花括块应返回属性预期的类型。如果返回了不受支持的类型,类型检查器会报错。您还可以使用字面量或几个简单的Rust表达式作为属性值(见上面的语法部分)。

html! 宏将向值表达式添加一个 .into() 调用,这样您就可以使用为实际属性类型 A 定义的 Into<A> 特性定义的任何类型。

作为一个特殊情况,如果您使用字符串字面量,则宏将使用 FromStr<A> 特性尝试将字符串字面量解析为预期类型。这对于例如CSS类非常有用,允许您输入 class="css-class-1 css-class-2" 而不是麻烦地构建一个 SpacedSet<Class>。这个大问题是:当前,宏无法在编译时验证字符串,如果字符串无效,转换将在运行时引发恐慌。

示例

let classList: SpacedSet<Class> = ["foo", "bar", "baz"].into();
html!(
    <div>
        <div class="foo bar baz" />         // parses a string literal
        <div class=["foo", "bar", "baz"] /> // uses From<[&str, &str, &str]>
        <div class=classList />             // uses a variable in scope
        <div class={                        // evaluates a code block
            SpacedSet::from(["foo", "bar", "baz"])
        } />
    </div>
)

生成的节点

在子节点位置的花括块应返回 IntoIteratorDOMTree。您可以返回单个元素或文本节点,因为它们都实现了为自己实现 IntoIterator。宏将在运行时消耗此迭代器,并将生成的节点作为预期位置的孩子插入。

示例

html!(
    <ul>
        { (1..=5).map(|i| html!(
            <li>{ text!("{}", i) }</li>
        )) }
    </ul>
)

渲染

您有两个选项可以从宏输出的DOM树中实际生成一些有用的内容。

渲染为字符串

DOM树数据结构实现了 Display,因此您可以在其上调用 to_string() 来将其渲染为 String。如果您计划这样做,则树的类型应为 DOMTree<String>,以确保您没有使用任何无法打印的事件处理器。

let doc: DOMTree<String> = html!(
    <p>"Hello Kitty"</p>
);
let doc_str = doc.to_string();
assert_eq!("<p>Hello Kitty</p>", doc_str);

渲染为虚拟DOM

DOM树结构还实现了一个名为vnode()的方法,该方法将树渲染为Node的树,这是生成的树的镜像,每个属性值都渲染为String。您可以遍历这个虚拟DOM树,并使用它用stdweb构建实际的DOM树,或者将其传递给您喜欢的虚拟DOM系统。

许可证

版权所有 2018 Bodil Stokke

此软件受Mozilla公共许可证第2.0版条款的约束。如果没有随此文件分发MPL副本,您可以在此获得一个:http://mozilla.org/MPL/2.0/

行为准则

请注意,本项目发布时附有贡献者行为准则。通过参与本项目,您同意遵守其条款。

依赖项

~0.1–1.5MB
~26K SLoC