summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst/src/realize/process.rs35
-rw-r--r--tests/ref/issue-3726-query-show-set.pngbin0 -> 2295 bytes
-rw-r--r--tests/suite/introspection/query.typ16
3 files changed, 36 insertions, 15 deletions
diff --git a/crates/typst/src/realize/process.rs b/crates/typst/src/realize/process.rs
index f5fcf1cb..7aa8b927 100644
--- a/crates/typst/src/realize/process.rs
+++ b/crates/typst/src/realize/process.rs
@@ -198,9 +198,14 @@ fn prepare(
// Generate a location for the element, which uniquely identifies it in
// the document. This has some overhead, so we only do it for elements
// that are explicitly marked as locatable and labelled elements.
- if target.can::<dyn Locatable>() || target.label().is_some() {
+ //
+ // The element could already have a location even if it is not prepared
+ // when it stems from a query.
+ let mut located = target.location().is_some();
+ if !located && (target.can::<dyn Locatable>() || target.label().is_some()) {
let location = engine.locator.locate(hash128(&target));
target.set_location(location);
+ located = true;
}
// Apply built-in show-set rules. User-defined show-set rules are already
@@ -220,24 +225,24 @@ fn prepare(
// available in rules.
target.materialize(styles.chain(map));
+ if located {
+ // Apply metadata to be able to find the element in the frames. Do this
+ // after synthesis and materialization, so that it includes the
+ // synthesized fields. Do it before marking as prepared so that show-set
+ // rules will apply to this element when queried. This adds a style to
+ // the whole element's subtree identifying it as belonging to the
+ // element.
+ map.set(MetaElem::set_data(smallvec![Meta::Elem(target.clone())]));
+ }
+
// Ensure that this preparation only runs once by marking the element as
// prepared.
target.mark_prepared();
- // Apply metadata be able to find the element in the frames.
- // Do this after synthesis, so that it includes the synthesized fields.
- if target.location().is_some() {
- // Add a style to the whole element's subtree identifying it as
- // belonging to the element.
- map.set(MetaElem::set_data(smallvec![Meta::Elem(target.clone())]));
-
- // Return an extra meta elem that will be attached so that the metadata
- // styles are not lost in case the element's show rule results in
- // nothing.
- return Ok(Some(Packed::new(MetaElem::new()).spanned(target.span())));
- }
-
- Ok(None)
+ // If the element is located, return an extra meta elem that will be
+ // attached so that the metadata styles are not lost in case the element's
+ // show rule results in nothing.
+ Ok(located.then(|| Packed::new(MetaElem::new()).spanned(target.span())))
}
/// Apply a step.
diff --git a/tests/ref/issue-3726-query-show-set.png b/tests/ref/issue-3726-query-show-set.png
new file mode 100644
index 00000000..3f5c8884
--- /dev/null
+++ b/tests/ref/issue-3726-query-show-set.png
Binary files differ
diff --git a/tests/suite/introspection/query.typ b/tests/suite/introspection/query.typ
index 3a4b4fbf..6cdd4bab 100644
--- a/tests/suite/introspection/query.typ
+++ b/tests/suite/introspection/query.typ
@@ -265,3 +265,19 @@
)),
([Frog], [GiraffeCat], [Iguana])
)
+
+--- issue-3726-query-show-set ---
+// Test that show rules apply to queried elements, i.e. that the content
+// returned from `query` isn't yet marked as prepared.
+#set heading(numbering: "1.")
+#show heading: underline
+= Hi
+
+#set heading(numbering: "I.")
+#show heading: set text(blue)
+#show heading: highlight.with(fill: aqua.lighten(50%))
+= Bye
+
+// New show rules apply to this, but its location and the materialized fields
+// from the original are retained.
+#context query(heading).join()