mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Add toml support (#807)
This commit is contained in:
parent
7cb63d1aae
commit
6134e3f4ee
53
Cargo.lock
generated
53
Cargo.lock
generated
@ -1848,6 +1848,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yaml"
|
name = "serde_yaml"
|
||||||
version = "0.8.26"
|
version = "0.8.26"
|
||||||
@ -2139,6 +2148,40 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.38"
|
version = "0.1.38"
|
||||||
@ -2348,6 +2391,7 @@ dependencies = [
|
|||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"syntect",
|
"syntect",
|
||||||
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"ttf-parser 0.18.1",
|
"ttf-parser 0.18.1",
|
||||||
"typed-arena",
|
"typed-arena",
|
||||||
@ -2882,6 +2926,15 @@ version = "0.48.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wyz"
|
name = "wyz"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
1
assets/files/bad.toml
Normal file
1
assets/files/bad.toml
Normal file
@ -0,0 +1 @@
|
|||||||
|
"only a string"
|
11
assets/files/informations.toml
Normal file
11
assets/files/informations.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
authors = ["Mr Robert", "Miss Enola", "Mr Jonathan"]
|
||||||
|
version = "1.0.3"
|
||||||
|
|
||||||
|
series = [
|
||||||
|
{ name = "attack on titan", fans = 500},
|
||||||
|
{ name = "demon slayer", fans = 10}
|
||||||
|
]
|
||||||
|
|
||||||
|
[informations]
|
||||||
|
location = "room A204"
|
||||||
|
pages = 47
|
11
assets/files/toml_types.toml
Normal file
11
assets/files/toml_types.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
string = "wonderful"
|
||||||
|
integer = 42
|
||||||
|
float = 3.14
|
||||||
|
boolean = true
|
||||||
|
date_time = 2023-02-01T15:38:57Z
|
||||||
|
array = [1, "string", 3.0, false]
|
||||||
|
inline_table = { first = "amazing", second = "greater" }
|
||||||
|
|
||||||
|
[table]
|
||||||
|
element = 5
|
||||||
|
others = [false, "indeed", 7]
|
@ -40,3 +40,4 @@ unicode-segmentation = "1"
|
|||||||
xi-unicode = "0.3"
|
xi-unicode = "0.3"
|
||||||
chinese-number = { version = "0.7.2", default-features = false, features = ["number-to-chinese"] }
|
chinese-number = { version = "0.7.2", default-features = false, features = ["number-to-chinese"] }
|
||||||
tracing = "0.1.37"
|
tracing = "0.1.37"
|
||||||
|
toml = { version = "0.7.3", default-features = false, features = ["parse"]}
|
||||||
|
@ -207,6 +207,87 @@ fn format_json_error(error: serde_json::Error) -> EcoString {
|
|||||||
eco_format!("failed to parse json file: syntax error in line {}", error.line())
|
eco_format!("failed to parse json file: syntax error in line {}", error.line())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read structured data from a TOML file.
|
||||||
|
///
|
||||||
|
/// The file must contain a valid TOML table. Tables will be
|
||||||
|
/// converted into Typst dictionaries, and TOML arrays will be converted into
|
||||||
|
/// Typst arrays. Strings and booleans will be converted into the Typst
|
||||||
|
/// equivalents, numbers will be converted to floats or integers depending on
|
||||||
|
/// whether they are whole numbers. TOML DateTim will be converted to strings.
|
||||||
|
///
|
||||||
|
/// The function returns a dictionary.
|
||||||
|
///
|
||||||
|
/// The JSON files in the example contain objects with the keys `temperature`,
|
||||||
|
/// `unit`, and `weather`.
|
||||||
|
///
|
||||||
|
/// ## Example
|
||||||
|
/// ```example
|
||||||
|
/// #let informations(content) = {
|
||||||
|
/// [This work is made by #content.authors.join(", ", last: " and "). We are currently at version #content.version.
|
||||||
|
/// The favorites series of the audience are ]
|
||||||
|
/// for serie in content.series [
|
||||||
|
/// - #serie.name with #serie.fans fans.
|
||||||
|
/// ]
|
||||||
|
/// [We need to submit our work in #content.informations.location, we currently have #content.informations.pages pages.]
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// #informations(toml("informations.toml"))
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Display: TOML
|
||||||
|
/// Category: data-loading
|
||||||
|
/// Returns: dictionary
|
||||||
|
#[func]
|
||||||
|
pub fn toml(
|
||||||
|
/// Path to a TOML file.
|
||||||
|
path: Spanned<EcoString>,
|
||||||
|
) -> Value {
|
||||||
|
let Spanned { v: path, span } = path;
|
||||||
|
let path = vm.locate(&path).at(span)?;
|
||||||
|
let data = vm.world().file(&path).at(span)?;
|
||||||
|
|
||||||
|
let raw = std::str::from_utf8(&data)
|
||||||
|
.map_err(|_| "file is not valid utf-8")
|
||||||
|
.at(span)?;
|
||||||
|
|
||||||
|
let value: toml::Value = toml::from_str(raw).map_err(format_toml_error).at(span)?;
|
||||||
|
convert_toml(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a TOML value to a Typst value.
|
||||||
|
fn convert_toml(value: toml::Value) -> Value {
|
||||||
|
match value {
|
||||||
|
toml::Value::String(v) => Value::Str(v.into()),
|
||||||
|
toml::Value::Integer(v) => Value::Int(v),
|
||||||
|
toml::Value::Float(v) => Value::Float(v),
|
||||||
|
toml::Value::Boolean(v) => Value::Bool(v),
|
||||||
|
toml::Value::Array(v) => Value::Array(v.into_iter().map(convert_toml).collect()),
|
||||||
|
toml::Value::Table(v) => Value::Dict(
|
||||||
|
v.into_iter()
|
||||||
|
.map(|(key, value)| (key.into(), convert_toml(value)))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
// Todo: make it use native date/time object(s) once it is implemented.
|
||||||
|
toml::Value::Datetime(v) => Value::Str(v.to_string().into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Format the user-facing TOML error message.
|
||||||
|
#[track_caller]
|
||||||
|
fn format_toml_error(error: toml::de::Error) -> String {
|
||||||
|
if let Some(range) = error.span() {
|
||||||
|
format!(
|
||||||
|
"failed to parse toml file: {message}, index {start}-{end}",
|
||||||
|
message = error.message(),
|
||||||
|
start = range.start,
|
||||||
|
end = range.end
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!("failed to parse toml file: {message}", message = error.message())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Read structured data from a YAML file.
|
/// Read structured data from a YAML file.
|
||||||
///
|
///
|
||||||
/// The file must contain a valid YAML object or array. YAML mappings will be
|
/// The file must contain a valid YAML object or array. YAML mappings will be
|
||||||
|
@ -131,6 +131,7 @@ fn global(math: Module, calc: Module) -> Module {
|
|||||||
global.define("read", compute::read);
|
global.define("read", compute::read);
|
||||||
global.define("csv", compute::csv);
|
global.define("csv", compute::csv);
|
||||||
global.define("json", compute::json);
|
global.define("json", compute::json);
|
||||||
|
global.define("toml", compute::toml);
|
||||||
global.define("yaml", compute::yaml);
|
global.define("yaml", compute::yaml);
|
||||||
global.define("xml", compute::xml);
|
global.define("xml", compute::xml);
|
||||||
|
|
||||||
|
@ -41,6 +41,23 @@
|
|||||||
// Error: 7-18 failed to parse json file: syntax error in line 3
|
// Error: 7-18 failed to parse json file: syntax error in line 3
|
||||||
#json("/bad.json")
|
#json("/bad.json")
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test reading TOML data.
|
||||||
|
#let data = toml("/toml_types.toml")
|
||||||
|
#test(data.string, "wonderful")
|
||||||
|
#test(data.integer, 42)
|
||||||
|
#test(data.float, 3.14)
|
||||||
|
#test(data.boolean, true)
|
||||||
|
#test(data.date_time, "2023-02-01T15:38:57Z")
|
||||||
|
#test(data.array, (1, "string", 3.0, false))
|
||||||
|
#test(data.inline_table, ("first": "amazing", "second": "greater") )
|
||||||
|
#test(data.table.element, 5)
|
||||||
|
#test(data.table.others, (false, "indeed", 7))
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 7-18 failed to parse toml file: expected `.`, `=`, index 15-15
|
||||||
|
#toml("/bad.toml")
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test reading YAML data
|
// Test reading YAML data
|
||||||
#let data = yaml("/yamltypes.yaml")
|
#let data = yaml("/yamltypes.yaml")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user