mirror of
https://github.com/typst/typst
synced 2025-05-20 20:15:29 +08:00
Handle Finalize
alongside Synthesize
This commit is contained in:
parent
1612913f8f
commit
a3684352ea
@ -14,8 +14,8 @@ use smallvec::smallvec;
|
|||||||
use crate::diag::{SourceResult, StrResult};
|
use crate::diag::{SourceResult, StrResult};
|
||||||
use crate::engine::Engine;
|
use crate::engine::Engine;
|
||||||
use crate::foundations::{
|
use crate::foundations::{
|
||||||
elem, func, scope, ty, Dict, Element, Fields, Guard, IntoValue, Label, NativeElement,
|
elem, func, scope, ty, Dict, Element, Fields, Finalize, Guard, IntoValue, Label,
|
||||||
Recipe, Repr, Selector, Str, Style, Styles, Synthesize, Value,
|
NativeElement, Recipe, Repr, Selector, Str, Style, Styles, Synthesize, Value,
|
||||||
};
|
};
|
||||||
use crate::introspection::{Locatable, Location, Meta, MetaElem};
|
use crate::introspection::{Locatable, Location, Meta, MetaElem};
|
||||||
use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides};
|
use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides};
|
||||||
@ -147,10 +147,11 @@ impl Content {
|
|||||||
|
|
||||||
/// Whether the content needs to be realized specially.
|
/// Whether the content needs to be realized specially.
|
||||||
pub fn needs_preparation(&self) -> bool {
|
pub fn needs_preparation(&self) -> bool {
|
||||||
(self.can::<dyn Locatable>()
|
!self.inner.prepared
|
||||||
|| self.can::<dyn Synthesize>()
|
&& (self.can::<dyn Locatable>()
|
||||||
|| self.label().is_some())
|
|| self.can::<dyn Synthesize>()
|
||||||
&& !self.inner.prepared
|
|| self.can::<dyn Finalize>()
|
||||||
|
|| self.label().is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether a show rule recipe is disabled.
|
/// Check whether a show rule recipe is disabled.
|
||||||
|
@ -107,58 +107,53 @@ pub fn realize(
|
|||||||
elem.set_location(location);
|
elem.set_location(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(elem) = elem.with_mut::<dyn Synthesize>() {
|
if let Some(synthesizable) = elem.with_mut::<dyn Synthesize>() {
|
||||||
elem.synthesize(engine, styles)?;
|
synthesizable.synthesize(engine, styles)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
elem.mark_prepared();
|
elem.mark_prepared();
|
||||||
|
|
||||||
if elem.location().is_some() {
|
let span = elem.span();
|
||||||
let span = elem.span();
|
let meta = elem.location().is_some().then(|| Meta::Elem(elem.clone()));
|
||||||
let meta = Meta::Elem(elem.clone());
|
|
||||||
return Ok(Some(
|
let mut content = elem;
|
||||||
(elem + MetaElem::new().pack().spanned(span))
|
if let Some(finalizable) = target.with::<dyn Finalize>() {
|
||||||
.styled(MetaElem::set_data(smallvec![meta])),
|
content = finalizable.finalize(content, styles);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(Some(elem));
|
if let Some(meta) = meta {
|
||||||
|
return Ok(Some(
|
||||||
|
(content + MetaElem::new().pack().spanned(span))
|
||||||
|
.styled(MetaElem::set_data(smallvec![meta])),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return Ok(Some(content));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find out how many recipes there are.
|
// Find out how many recipes there are.
|
||||||
let mut n = styles.recipes().count();
|
let mut n = styles.recipes().count();
|
||||||
|
|
||||||
// Find an applicable recipe.
|
// Find an applicable show rule recipe.
|
||||||
let mut realized = None;
|
|
||||||
for recipe in styles.recipes() {
|
for recipe in styles.recipes() {
|
||||||
let guard = Guard::Nth(n);
|
let guard = Guard::Nth(n);
|
||||||
if recipe.applicable(target) && !target.is_guarded(guard) {
|
if recipe.applicable(target) && !target.is_guarded(guard) {
|
||||||
if let Some(content) = try_apply(engine, target, recipe, guard)? {
|
if let Some(content) = try_apply(engine, target, recipe, guard)? {
|
||||||
realized = Some(content);
|
return Ok(Some(content));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
n -= 1;
|
n -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Realize if there was no matching recipe.
|
// Apply the built-in show rule if there was no matching recipe.
|
||||||
if let Some(showable) = target.with::<dyn Show>() {
|
let guard = Guard::Base(target.func());
|
||||||
let guard = Guard::Base(target.func());
|
if !target.is_guarded(guard) {
|
||||||
if realized.is_none() && !target.is_guarded(guard) {
|
if let Some(showable) = target.with::<dyn Show>() {
|
||||||
realized = Some(showable.show(engine, styles)?);
|
return Ok(Some(showable.show(engine, styles)?));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize only if this is the first application for this element.
|
Ok(None)
|
||||||
if let Some(elem) = target.with::<dyn Finalize>() {
|
|
||||||
if target.is_pristine() {
|
|
||||||
if let Some(already) = realized {
|
|
||||||
realized = Some(elem.finalize(already, styles));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(realized)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to apply a recipe to the target.
|
/// Try to apply a recipe to the target.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user