summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--library/src/compute/data.rs39
-rw-r--r--library/src/lib.rs1
-rw-r--r--tests/res/hello.txt1
-rw-r--r--tests/res/invalid-utf8.txtbin0 -> 70 bytes
-rw-r--r--tests/typ/compute/data.typ15
5 files changed, 54 insertions, 2 deletions
diff --git a/library/src/compute/data.rs b/library/src/compute/data.rs
index a018c09a..a519e8e6 100644
--- a/library/src/compute/data.rs
+++ b/library/src/compute/data.rs
@@ -4,6 +4,40 @@ use typst::diag::{format_xml_like_error, FileError};
use crate::prelude::*;
+/// # Read file
+/// Read plain text from a file.
+///
+/// The file will be read and returned as a string.
+///
+/// ## Example
+/// ```
+/// #let text = read("data.html")
+///
+/// An HTML file could look like this:
+/// #raw(text, lang: "html")
+/// ```
+///
+/// ## Parameters
+/// - path: EcoString (positional, required)
+/// Path to a file.
+///
+/// - returns: EcoString
+///
+/// ## Category
+/// data-loading
+#[func]
+pub fn read(vm: &Vm, args: &mut Args) -> SourceResult<Value> {
+ let Spanned { v: path, span } = args.expect::<Spanned<EcoString>>("path to file")?;
+
+ let path = vm.locate(&path).at(span)?;
+ let data = vm.world().file(&path).at(span)?;
+
+ let text = String::from_utf8(data.to_vec())
+ .map_err(|_| "file is not valid utf-8")
+ .at(span)?;
+ Ok(Value::Str(text.into()))
+}
+
/// # CSV
/// Read structured data from a CSV file.
///
@@ -184,7 +218,10 @@ fn convert_json(value: serde_json::Value) -> Value {
/// Format the user-facing JSON error message.
fn format_json_error(error: serde_json::Error) -> String {
assert!(error.is_syntax() || error.is_eof());
- format!("failed to parse json file: syntax error in line {}", error.line())
+ format!(
+ "failed to parse json file: syntax error in line {}",
+ error.line()
+ )
}
/// # XML
diff --git a/library/src/lib.rs b/library/src/lib.rs
index a4c6fc30..e345bbee 100644
--- a/library/src/lib.rs
+++ b/library/src/lib.rs
@@ -124,6 +124,7 @@ fn scope() -> Scope {
std.def_func::<compute::EvenFunc>("even");
std.def_func::<compute::OddFunc>("odd");
std.def_func::<compute::ModFunc>("mod");
+ std.def_func::<compute::ReadFunc>("read");
std.def_func::<compute::CsvFunc>("csv");
std.def_func::<compute::JsonFunc>("json");
std.def_func::<compute::XmlFunc>("xml");
diff --git a/tests/res/hello.txt b/tests/res/hello.txt
new file mode 100644
index 00000000..5dd01c17
--- /dev/null
+++ b/tests/res/hello.txt
@@ -0,0 +1 @@
+Hello, world! \ No newline at end of file
diff --git a/tests/res/invalid-utf8.txt b/tests/res/invalid-utf8.txt
new file mode 100644
index 00000000..71308112
--- /dev/null
+++ b/tests/res/invalid-utf8.txt
Binary files differ
diff --git a/tests/typ/compute/data.typ b/tests/typ/compute/data.typ
index c1def7d5..5a0f76c6 100644
--- a/tests/typ/compute/data.typ
+++ b/tests/typ/compute/data.typ
@@ -1,7 +1,20 @@
-// Test reading structured data.
+// Test reading structured data and files.
// Ref: false
---
+// Test reading plain text files
+#let data = read("../../res/hello.txt")
+#test(data, "Hello, world!")
+
+---
+// Error: 18-41 file not found (searched at res/missing.txt)
+#let data = read("../../res/missing.txt")
+
+---
+// Error: 18-46 file is not valid utf-8
+#let data = read("../../res/invalid-utf8.txt")
+
+---
// Test reading CSV data.
// Ref: true
#set page(width: auto)