refactor: revert some changes to FrameItem::Link

This commit is contained in:
Tobias Schmitz 2025-06-25 15:08:08 +02:00
parent 2d6e3b6151
commit 4894a227d2
No known key found for this signature in database
7 changed files with 29 additions and 30 deletions

View File

@ -36,9 +36,9 @@ pub fn jump_from_click(
) -> Option<Jump> { ) -> Option<Jump> {
// Try to find a link first. // Try to find a link first.
for (pos, item) in frame.items() { for (pos, item) in frame.items() {
if let FrameItem::Link(link, size) = item { if let FrameItem::Link(dest, size) = item {
if is_in_rect(*pos, *size, click) { if is_in_rect(*pos, *size, click) {
return Some(match &link.dest { return Some(match dest {
Destination::Url(url) => Jump::Url(url.clone()), Destination::Url(url) => Jump::Url(url.clone()),
Destination::Position(pos) => Jump::Position(*pos), Destination::Position(pos) => Jump::Position(*pos),
Destination::Location(loc) => { Destination::Location(loc) => {

View File

@ -1,6 +1,6 @@
use typst_library::foundations::{LinkMarker, Packed, StyleChain}; use typst_library::foundations::StyleChain;
use typst_library::layout::{Abs, Fragment, Frame, FrameItem, HideElem, Point, Sides}; use typst_library::layout::{Abs, Fragment, Frame, FrameItem, HideElem, Point, Sides};
use typst_library::model::ParElem; use typst_library::model::{Destination, LinkElem, ParElem};
/// Frame-level modifications resulting from styles that do not impose any /// Frame-level modifications resulting from styles that do not impose any
/// layout structure. /// layout structure.
@ -20,7 +20,7 @@ use typst_library::model::ParElem;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct FrameModifiers { pub struct FrameModifiers {
/// A destination to link to. /// A destination to link to.
link: Option<Packed<LinkMarker>>, dest: Option<Destination>,
/// Whether the contents of the frame should be hidden. /// Whether the contents of the frame should be hidden.
hidden: bool, hidden: bool,
} }
@ -28,9 +28,8 @@ pub struct FrameModifiers {
impl FrameModifiers { impl FrameModifiers {
/// Retrieve all modifications that should be applied per-frame. /// Retrieve all modifications that should be applied per-frame.
pub fn get_in(styles: StyleChain) -> Self { pub fn get_in(styles: StyleChain) -> Self {
// TODO: maybe verify that an alt text was provided here
Self { Self {
link: LinkMarker::current_in(styles), dest: LinkElem::current_in(styles),
hidden: HideElem::hidden_in(styles), hidden: HideElem::hidden_in(styles),
} }
} }
@ -95,7 +94,7 @@ fn modify_frame(
modifiers: &FrameModifiers, modifiers: &FrameModifiers,
link_box_outset: Option<Sides<Abs>>, link_box_outset: Option<Sides<Abs>>,
) { ) {
if let Some(link) = &modifiers.link { if let Some(dest) = &modifiers.dest {
let mut pos = Point::zero(); let mut pos = Point::zero();
let mut size = frame.size(); let mut size = frame.size();
if let Some(outset) = link_box_outset { if let Some(outset) = link_box_outset {
@ -103,7 +102,7 @@ fn modify_frame(
pos.x -= outset.left; pos.x -= outset.left;
size += outset.sum_by_axis(); size += outset.sum_by_axis();
} }
frame.push(pos, FrameItem::Link(link.clone(), size)); frame.push(pos, FrameItem::Link(dest.clone(), size));
} }
if modifiers.hidden { if modifiers.hidden {
@ -130,8 +129,8 @@ where
let reset; let reset;
let outer = styles; let outer = styles;
let mut styles = styles; let mut styles = styles;
if modifiers.link.is_some() { if modifiers.dest.is_some() {
reset = LinkMarker::set_current(None).wrap(); reset = LinkElem::set_current(None).wrap();
styles = outer.chain(&reset); styles = outer.chain(&reset);
} }

View File

@ -21,7 +21,7 @@ use crate::foundations::{
}; };
use crate::introspection::{Locatable, Location}; use crate::introspection::{Locatable, Location};
use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides}; use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides};
use crate::model::{Destination, EmphElem, StrongElem}; use crate::model::{Destination, EmphElem, LinkElem, StrongElem};
use crate::pdf::{ArtifactElem, ArtifactKind}; use crate::pdf::{ArtifactElem, ArtifactKind};
use crate::text::UnderlineElem; use crate::text::UnderlineElem;
@ -506,11 +506,10 @@ impl Content {
/// Link the content somewhere. /// Link the content somewhere.
pub fn linked(self, dest: Destination, alt: Option<EcoString>) -> Self { pub fn linked(self, dest: Destination, alt: Option<EcoString>) -> Self {
let span = self.span(); let span = self.span();
let link = Packed::new(LinkMarker::new(self, dest, alt)); LinkMarker::new(self, dest.clone(), alt)
link.clone()
.pack() .pack()
.spanned(span) .spanned(span)
.styled(LinkMarker::set_current(Some(link))) .styled(LinkElem::set_current(Some(dest)))
} }
/// Set alignments for this content. /// Set alignments for this content.
@ -1002,11 +1001,6 @@ pub struct LinkMarker {
pub dest: Destination, pub dest: Destination,
#[required] #[required]
pub alt: Option<EcoString>, pub alt: Option<EcoString>,
/// A link style that should be applied to elements.
#[internal]
#[ghost]
pub current: Option<Packed<LinkMarker>>,
} }
impl Show for Packed<LinkMarker> { impl Show for Packed<LinkMarker> {

View File

@ -7,9 +7,10 @@ use std::sync::Arc;
use typst_syntax::Span; use typst_syntax::Span;
use typst_utils::{LazyHash, Numeric}; use typst_utils::{LazyHash, Numeric};
use crate::foundations::{cast, dict, Dict, Label, LinkMarker, Packed, Value}; use crate::foundations::{cast, dict, Dict, Label, Value};
use crate::introspection::{Location, Tag}; use crate::introspection::{Location, Tag};
use crate::layout::{Abs, Axes, FixedAlignment, Length, Point, Size, Transform}; use crate::layout::{Abs, Axes, FixedAlignment, Length, Point, Size, Transform};
use crate::model::Destination;
use crate::text::TextItem; use crate::text::TextItem;
use crate::visualize::{Color, Curve, FixedStroke, Geometry, Image, Paint, Shape}; use crate::visualize::{Color, Curve, FixedStroke, Geometry, Image, Paint, Shape};
@ -472,7 +473,7 @@ pub enum FrameItem {
/// An image and its size. /// An image and its size.
Image(Image, Size, Span), Image(Image, Size, Span),
/// An internal or external link to a destination. /// An internal or external link to a destination.
Link(Packed<LinkMarker>, Size), Link(Destination, Size),
/// An introspectable element that produced something within this frame. /// An introspectable element that produced something within this frame.
Tag(Tag), Tag(Tag),
} }
@ -484,7 +485,7 @@ impl Debug for FrameItem {
Self::Text(text) => write!(f, "{text:?}"), Self::Text(text) => write!(f, "{text:?}"),
Self::Shape(shape, _) => write!(f, "{shape:?}"), Self::Shape(shape, _) => write!(f, "{shape:?}"),
Self::Image(image, _, _) => write!(f, "{image:?}"), Self::Image(image, _, _) => write!(f, "{image:?}"),
Self::Link(link, _) => write!(f, "Link({:?}, {:?})", link.dest, link.alt), Self::Link(dest, _) => write!(f, "Link({dest:?})"),
Self::Tag(tag) => write!(f, "{tag:?}"), Self::Tag(tag) => write!(f, "{tag:?}"),
} }
} }

View File

@ -91,6 +91,11 @@ pub struct LinkElem {
_ => args.expect("body")?, _ => args.expect("body")?,
})] })]
pub body: Content, pub body: Content,
/// A destination style that should be applied to elements.
#[internal]
#[ghost]
pub current: Option<Destination>,
} }
impl LinkElem { impl LinkElem {

View File

@ -281,7 +281,7 @@ pub(crate) fn handle_frame(
FrameItem::Image(image, size, span) => { FrameItem::Image(image, size, span) => {
handle_image(gc, fc, image, *size, surface, *span)? handle_image(gc, fc, image, *size, surface, *span)?
} }
FrameItem::Link(link, size) => handle_link(fc, gc, link, *size), FrameItem::Link(dest, size) => handle_link(fc, gc, dest, *size),
FrameItem::Tag(Tag::Start(elem)) => tags::handle_start(gc, elem), FrameItem::Tag(Tag::Start(elem)) => tags::handle_start(gc, elem),
FrameItem::Tag(Tag::End(loc, _)) => tags::handle_end(gc, *loc), FrameItem::Tag(Tag::End(loc, _)) => tags::handle_end(gc, *loc),
} }

View File

@ -5,7 +5,6 @@ use krilla::action::{Action, LinkAction};
use krilla::annotation::Target; use krilla::annotation::Target;
use krilla::destination::XyzDestination; use krilla::destination::XyzDestination;
use krilla::geom as kg; use krilla::geom as kg;
use typst_library::foundations::LinkMarker;
use typst_library::layout::{Abs, Point, Position, Size}; use typst_library::layout::{Abs, Point, Position, Size};
use typst_library::model::Destination; use typst_library::model::Destination;
@ -24,10 +23,10 @@ pub(crate) struct LinkAnnotation {
pub(crate) fn handle_link( pub(crate) fn handle_link(
fc: &mut FrameContext, fc: &mut FrameContext,
gc: &mut GlobalContext, gc: &mut GlobalContext,
link: &LinkMarker, dest: &Destination,
size: Size, size: Size,
) { ) {
let target = match &link.dest { let target = match dest {
Destination::Url(u) => { Destination::Url(u) => {
Target::Action(Action::Link(LinkAction::new(u.to_string()))) Target::Action(Action::Link(LinkAction::new(u.to_string())))
} }
@ -51,14 +50,15 @@ pub(crate) fn handle_link(
}; };
let entry = gc.tags.stack.last_mut().expect("a link parent"); let entry = gc.tags.stack.last_mut().expect("a link parent");
let StackEntryKind::Link(link_id, _) = entry.kind else { let StackEntryKind::Link(link_id, link) = &entry.kind else {
unreachable!("expected a link parent") unreachable!("expected a link parent")
}; };
let alt = link.alt.as_ref().map(EcoString::to_string);
let rect = to_rect(fc, size); let rect = to_rect(fc, size);
let quadpoints = quadpoints(rect); let quadpoints = quadpoints(rect);
match fc.link_annotations.entry(link_id) { match fc.link_annotations.entry(*link_id) {
Entry::Occupied(occupied) => { Entry::Occupied(occupied) => {
// Update the bounding box and add the quadpoints of an existing link annotation. // Update the bounding box and add the quadpoints of an existing link annotation.
let annotation = occupied.into_mut(); let annotation = occupied.into_mut();
@ -73,7 +73,7 @@ pub(crate) fn handle_link(
placeholder, placeholder,
rect, rect,
quad_points: quadpoints.to_vec(), quad_points: quadpoints.to_vec(),
alt: link.alt.as_ref().map(EcoString::to_string), alt,
target, target,
}); });
} }