summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-09-25 18:20:39 +0200
committerLaurenz <laurmaedje@gmail.com>2022-09-25 18:20:39 +0200
commitf6adc45638409aaa0feb1f70883c11ed553efe4f (patch)
tree3691cec70698a1952f2b315ed8b602912739acce /src/library
parentfffb55f79a3369fa2dcf39371091c48ff61f55a8 (diff)
XML reading
Diffstat (limited to 'src/library')
-rw-r--r--src/library/mod.rs1
-rw-r--r--src/library/prelude.rs6
-rw-r--r--src/library/utility/data.rs45
3 files changed, 50 insertions, 2 deletions
diff --git a/src/library/mod.rs b/src/library/mod.rs
index d806f298..91e4671c 100644
--- a/src/library/mod.rs
+++ b/src/library/mod.rs
@@ -98,6 +98,7 @@ pub fn new() -> Scope {
std.def_fn("lorem", utility::lorem);
std.def_fn("csv", utility::csv);
std.def_fn("json", utility::json);
+ std.def_fn("xml", utility::xml);
// Predefined colors.
std.define("black", Color::BLACK);
diff --git a/src/library/prelude.rs b/src/library/prelude.rs
index 44d1af7f..03bef51e 100644
--- a/src/library/prelude.rs
+++ b/src/library/prelude.rs
@@ -9,10 +9,12 @@ pub use std::sync::Arc;
pub use comemo::Tracked;
pub use typst_macros::node;
-pub use crate::diag::{with_alternative, At, SourceError, SourceResult, StrResult};
+pub use crate::diag::{
+ with_alternative, At, FileError, FileResult, SourceError, SourceResult, StrResult,
+};
pub use crate::eval::{
Arg, Args, Array, Cast, Dict, Dynamic, Func, Node, RawAlign, RawLength, RawStroke,
- Scope, Smart, Value, Vm,
+ Scope, Smart, Str, Value, Vm,
};
pub use crate::frame::*;
pub use crate::geom::*;
diff --git a/src/library/utility/data.rs b/src/library/utility/data.rs
index e3efe6e7..0cff42c1 100644
--- a/src/library/utility/data.rs
+++ b/src/library/utility/data.rs
@@ -1,5 +1,6 @@
use std::fmt::Write;
+use crate::diag::format_xml_like_error;
use crate::library::prelude::*;
/// Read structured data from a CSV file.
@@ -84,3 +85,47 @@ fn format_json_error(error: serde_json::Error) -> String {
error.line()
)
}
+
+/// Read structured data from an XML file.
+pub fn xml(vm: &mut Vm, args: &mut Args) -> SourceResult<Value> {
+ let Spanned { v: path, span } =
+ args.expect::<Spanned<EcoString>>("path to xml file")?;
+
+ let path = vm.locate(&path).at(span)?;
+ let data = vm.world.file(&path).at(span)?;
+ let text = std::str::from_utf8(&data).map_err(FileError::from).at(span)?;
+
+ let document = roxmltree::Document::parse(text).map_err(format_xml_error).at(span)?;
+
+ Ok(convert_xml(document.root()))
+}
+
+/// Convert an XML node to a Typst value.
+fn convert_xml(node: roxmltree::Node) -> Value {
+ if node.is_text() {
+ return Value::Str(node.text().unwrap_or_default().into());
+ }
+
+ let children: Array = node.children().map(convert_xml).collect();
+ if node.is_root() {
+ return Value::Array(children);
+ }
+
+ let tag: Str = node.tag_name().name().into();
+ let attrs: Dict = node
+ .attributes()
+ .iter()
+ .map(|attr| (attr.name().into(), attr.value().into()))
+ .collect();
+
+ Value::Dict(dict! {
+ "tag" => tag,
+ "attrs" => attrs,
+ "children" => children,
+ })
+}
+
+/// Format the user-facing XML error message.
+fn format_xml_error(error: roxmltree::Error) -> String {
+ format_xml_like_error("xml file", error)
+}