9次发布
0.3.0 | 2022年7月28日 |
---|---|
0.2.0 | 2020年11月21日 |
0.1.6 | 2020年10月17日 |
0.1.5 | 2020年6月21日 |
0.1.2 | 2019年8月26日 |
#53 在 值格式化
306 每月下载量
在 3 crate 中使用
41KB
706 行
类似XML的格式化
为Rust提供快速、最小化、功能丰富的类似XML的格式化语法!
我们称之为类似XML,因为由于限制和灵活性,必须做出一些妥协;请参见下面的示例。
功能包括
- 格式化括号内的任意表达式
- 在编译时生成优化后的Rust代码
- 支持rust-analyzer自动完成、重构等功能!
- 支持Rust的标准格式化说明符
- 控制流允许条件性和重复的格式化
- 按值或按引用捕获变量
- 逃生门以注入自定义格式化代码
在您的Cargo.toml中添加
[dependencies]
format_xml = "0.2"
示例
基本用法
let point = (20, 30);
let name = "World";
let string = format_xml::format! {
<svg width="200" height="200">
<line x1="0" y1="0" x2={point.0} y2={point.1} stroke="black" stroke-width="2" />
<text x={point.1} y={point.0}>"Hello '"{name}"'!"</text>
</svg>
};
assert_eq!(string, r#"<svg width="200" height="200"><line x1="0" y1="0" x2="20" y2="30" stroke="black" stroke-width="2" /><text x="30" y="20">Hello 'World'!</text></svg>"#);
值参数可以是任意表达式。它们在格式化括号内内联,并在字符串字面量之外。
默认情况下,格式化括号内的值会被转义,文本字面量不会被转义。使用逃生门来绕过自动转义。
格式化说明符
let value = 42;
let string = format_xml::format! {
<span data-value={value}>{value:#x?}</span>
};
assert_eq!(string, r#"<span data-value="42">0x2a</span>"#);
说明符的规则与Rust标准库中的规则完全相同。
转义
let value = "\"quote\"";
let text = "<script>&</script>";
let string = format_xml::format! {
<p data-value={value}>{text}</p>
};
assert_eq!(string, r#"<p data-value=""quote""><script>&</script></p>"#);
默认情况下,格式化括号内的值会被转义,文本字面量不会被转义。
- 文本元素转义
<
、&
、>
。 - 属性值转义
<
、&
、>
、'
、"
。 - 注释节点通过移除它来转义
--
。 - CDATA部分通过转义
]]>
。
在某些HTML上下文中没有实现转义:在 <script>
、<style>
标签或它们各自的属性等效物(事件监听器和内联样式)内部,不要在这些位置格式化用户控制的值!
支持的语法
let string = format_xml::format! {
<!doctype html>
<?xml version="1.0" encoding="UTF-8"?>
<tag-name></tag-name>
<self-closing-tag />
<!-- "comment" -->
<![CDATA["cdata"]]>
};
assert_eq!(string, r#"<!doctype html><?xml version="1.0" encoding="UTF-8"?><tag-name></tag-name><self-closing-tag /><!-- comment --><![CDATA[cdata]]>"#);
元素命名和命名空间语法支持示例
let string = format_xml::format! {
<tag>
<tag-foo>
<tag.foo>
<ns:tag>
<"_t-0.z">
};
assert_eq!(string, r#"<tag><tag-foo><tag.foo><ns:tag><_t-0.z>"#);
对匹配开/闭标签或拒绝不能自闭合的标签没有限制。
未完成的实现
- 文档类型定义(DTD)未正确实现。标签
<!doctype>
几乎无功能。 - 处理指令未正确实现。标签
<?xml?>
几乎无功能。
控制流
let switch = true;
let opt = Some("World");
let string = format_xml::format! {
if let Some(name) = (opt) {
<h1>"Hello "{name}</h1>
}
else if (switch) {
<h1>"Hello User"</h1>
}
};
assert_eq!(string, "<h1>Hello World</h1>");
let string: Result<f32, i32> = Err(13);
let string = format_xml::format! {
match string {
Ok(f) => <i>{f}</i>,
Err(i) => <b>{i}</b>,
}
};
assert_eq!(string, "<b>13</b>");
let string = format_xml::format! {
<ul>
for i in (1..=5) {
let times_five = i * 5;
<li>{i}"*5="{times_five}</li>
}
</ul>
};
assert_eq!(string, "<ul><li>1*5=5</li><li>2*5=10</li><li>3*5=15</li><li>4*5=20</li><li>5*5=25</li></ul>");
控制流仅在标签外部受支持,不在属性内部。
逃生门
fn compose(f: &mut std::fmt::Formatter, a: i32) -> std::fmt::Result {
format_xml::write!(f, <span>{a}</span>)
}
let string = format_xml::format! {
<p>|f| compose(f, 42)?;</p>
};
assert_eq!(string, r#"<p><span>42</span></p>"#);
闭包语法提供了一个逃生门以在需要时注入代码。参数的类型是 &mut Formatter
。
重要!写入格式化器 f
的任何内容都不会转义。这使得它可以用来组合不同的组件,而这些组件无法使用 {}
完成。
许可
根据 MIT 许可证 许可,请参阅 license.txt。
贡献
除非您明确说明,否则您提交的任何旨在包含在作品中的贡献都应按上述方式许可,而不附加任何额外条款或条件。
依赖项
~32KB