#xml #template #svg #html #format #generate

无std format_xml

为Rust提供快速、最小化、功能丰富的类似XML的格式化语法!

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值格式化

Download history 65/week @ 2024-03-11 48/week @ 2024-03-18 41/week @ 2024-03-25 131/week @ 2024-04-01 37/week @ 2024-04-08 61/week @ 2024-04-15 83/week @ 2024-04-22 48/week @ 2024-04-29 47/week @ 2024-05-06 53/week @ 2024-05-13 66/week @ 2024-05-20 71/week @ 2024-05-27 75/week @ 2024-06-03 75/week @ 2024-06-10 78/week @ 2024-06-17 71/week @ 2024-06-24

306 每月下载量
3 crate 中使用

MIT 许可证

41KB
706

类似XML的格式化

MIT License crates.io docs.rs Build status

为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="&quot;quote&quot;">&lt;script&gt;&amp;&lt;/script&gt;</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