From 644bbf99145042266ea8cf2890cef5771bd04be4 Mon Sep 17 00:00:00 2001 From: MALO <57839069+MDLC01@users.noreply.github.com> Date: Tue, 30 May 2023 10:13:27 +0200 Subject: [PATCH] Add `fields` method to content (#1340) --- docs/src/reference/types.md | 7 +++++++ src/eval/methods.rs | 9 ++++++++- src/model/content.rs | 9 ++++++++- tests/typ/compiler/methods.typ | 5 +++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/docs/src/reference/types.md b/docs/src/reference/types.md index 13ca87204..715427f3b 100644 --- a/docs/src/reference/types.md +++ b/docs/src/reference/types.md @@ -604,6 +604,13 @@ field does not exist or fails with an error if no default value was specified. A default value to return if the field does not exist. - returns: any +### fields() +Return the fields of this content. + +```example +#repr(rect(width: 10cm, height: 10cm).fields()) +``` + ### location() The location of the content. This is only available on content returned by [query]($func/query), for other content it will fail with an error. The diff --git a/src/eval/methods.rs b/src/eval/methods.rs index 7de3bc20a..f57bf84d7 100644 --- a/src/eval/methods.rs +++ b/src/eval/methods.rs @@ -81,6 +81,7 @@ pub fn call( "at" => content .at(&args.expect::("field")?, args.named("default")?) .at(span)?, + "fields" => Value::Dict(content.dict()), "location" => content .location() .ok_or("this method can only be called on content returned by query(..)") @@ -332,7 +333,13 @@ pub fn methods_on(type_name: &str) -> &[(&'static str, bool)] { ("starts-with", true), ("trim", true), ], - "content" => &[("func", false), ("has", true), ("at", true), ("location", false)], + "content" => &[ + ("func", false), + ("has", true), + ("at", true), + ("fields", false), + ("location", false), + ], "array" => &[ ("all", true), ("any", true), diff --git a/src/model/content.rs b/src/model/content.rs index 8b60ab448..f262d0275 100644 --- a/src/model/content.rs +++ b/src/model/content.rs @@ -12,7 +12,7 @@ use super::{ }; use crate::diag::{SourceResult, StrResult}; use crate::doc::Meta; -use crate::eval::{Cast, Str, Value, Vm}; +use crate::eval::{Cast, Dict, Str, Value, Vm}; use crate::syntax::Span; use crate::util::pretty_array_like; @@ -251,6 +251,13 @@ impl Content { .ok_or_else(|| missing_field_no_default(field)) } + /// Return the fields of the content as a dict. + pub fn dict(&self) -> Dict { + self.fields() + .map(|(key, value)| (key.to_owned().into(), value)) + .collect() + } + /// The content's label. pub fn label(&self) -> Option<&Label> { match self.field_ref("label")? { diff --git a/tests/typ/compiler/methods.typ b/tests/typ/compiler/methods.typ index 8b36dea94..864ed8ada 100644 --- a/tests/typ/compiler/methods.typ +++ b/tests/typ/compiler/methods.typ @@ -48,3 +48,8 @@ --- // Error: 2-5 cannot mutate a constant: box #box.push(1) + +--- +// Test content fields method. +#test([a].fields(), (text: "a")) +#test([a *b*].fields(), (children: ([a], [ ], strong[b])))