mirror of
https://github.com/typst/typst
synced 2025-06-19 11:52:51 +08:00
WIP [no ci]
This commit is contained in:
parent
4a64a717e8
commit
616c626acb
@ -16,12 +16,12 @@ use crate::diag::{SourceResult, StrResult};
|
||||
use crate::engine::Engine;
|
||||
use crate::foundations::{
|
||||
elem, func, scope, ty, Context, Dict, Element, Fields, IntoValue, Label,
|
||||
NativeElement, Recipe, RecipeIndex, Repr, Selector, Str, Style, StyleChain, Styles,
|
||||
Value,
|
||||
NativeElement, Recipe, RecipeIndex, Repr, Selector, Show, Str, Style, StyleChain,
|
||||
Styles, Value,
|
||||
};
|
||||
use crate::introspection::Location;
|
||||
use crate::introspection::{Locatable, Location};
|
||||
use crate::layout::{AlignElem, Alignment, Axes, Length, MoveElem, PadElem, Rel, Sides};
|
||||
use crate::model::{Destination, EmphElem, LinkElem, StrongElem};
|
||||
use crate::model::{Destination, EmphElem, StrongElem};
|
||||
use crate::pdf::{ArtifactElem, ArtifactKind};
|
||||
use crate::text::UnderlineElem;
|
||||
|
||||
@ -504,9 +504,9 @@ impl Content {
|
||||
}
|
||||
|
||||
/// Link the content somewhere.
|
||||
pub fn linked(self, alt: Option<EcoString>, dest: Destination) -> Self {
|
||||
self.styled(LinkElem::set_alt(alt))
|
||||
.styled(LinkElem::set_current(Some(dest)))
|
||||
pub fn linked(self, dest: Destination, alt: Option<EcoString>) -> Self {
|
||||
let span = self.span();
|
||||
LinkMarker::new(self, dest, alt).pack().spanned(span)
|
||||
}
|
||||
|
||||
/// Set alignments for this content.
|
||||
@ -988,6 +988,26 @@ pub trait PlainText {
|
||||
fn plain_text(&self, text: &mut EcoString);
|
||||
}
|
||||
|
||||
|
||||
// TODO: remove `FrameItem::Link` and `FrameModifiers::dest`, then handle links by looking at tags
|
||||
/// An element that associates the body of a link with the destination.
|
||||
#[elem(Show, Locatable)]
|
||||
pub struct LinkMarker {
|
||||
/// The content.
|
||||
#[required]
|
||||
pub body: Content,
|
||||
#[required]
|
||||
pub dest: Destination,
|
||||
#[required]
|
||||
pub alt: Option<EcoString>,
|
||||
}
|
||||
|
||||
impl Show for Packed<LinkMarker> {
|
||||
fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult<Content> {
|
||||
Ok(self.body.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// An error arising when trying to access a field of content.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
pub enum FieldAccessError {
|
||||
|
@ -523,6 +523,8 @@ pub struct StyleChain<'a> {
|
||||
}
|
||||
|
||||
impl<'a> StyleChain<'a> {
|
||||
pub const EMPTY: Self = Self { head: &[], tail: None };
|
||||
|
||||
/// Start a new style chain with root styles.
|
||||
pub fn new(root: &'a Styles) -> Self {
|
||||
Self { head: &root.0, tail: None }
|
||||
|
@ -874,7 +874,7 @@ impl<'a> Generator<'a> {
|
||||
if let Some(location) = first_occurrences.get(item.key.as_str()) {
|
||||
let dest = Destination::Location(*location);
|
||||
// TODO: accept user supplied alt text
|
||||
content = content.linked(None, dest);
|
||||
content = content.linked(dest, None);
|
||||
}
|
||||
StrResult::Ok(content)
|
||||
})
|
||||
@ -1010,7 +1010,7 @@ impl ElemRenderer<'_> {
|
||||
if let Some(location) = (self.link)(i) {
|
||||
let dest = Destination::Location(location);
|
||||
// TODO: accept user supplied alt text
|
||||
content = content.linked(None, dest);
|
||||
content = content.linked(dest, None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ impl Show for Packed<FootnoteElem> {
|
||||
let loc = loc.variant(1);
|
||||
// Add zero-width weak spacing to make the footnote "sticky".
|
||||
// TODO: accept user supplied alt text
|
||||
Ok(HElem::hole().pack() + sup.linked(None, Destination::Location(loc)))
|
||||
Ok(HElem::hole().pack() + sup.linked(Destination::Location(loc), None))
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,7 +298,7 @@ impl Show for Packed<FootnoteEntry> {
|
||||
.pack()
|
||||
.spanned(span)
|
||||
// TODO: accept user supplied alt text
|
||||
.linked(None, Destination::Location(loc))
|
||||
.linked(Destination::Location(loc), None)
|
||||
.located(loc.variant(1));
|
||||
|
||||
Ok(Content::sequence([
|
||||
|
@ -91,11 +91,6 @@ pub struct LinkElem {
|
||||
_ => args.expect("body")?,
|
||||
})]
|
||||
pub body: Content,
|
||||
|
||||
/// A destination style that should be applied to elements.
|
||||
#[internal]
|
||||
#[ghost]
|
||||
pub current: Option<Destination>,
|
||||
}
|
||||
|
||||
impl LinkElem {
|
||||
@ -128,11 +123,11 @@ impl Show for Packed<LinkElem> {
|
||||
} else {
|
||||
let alt = self.alt(styles);
|
||||
match &self.dest {
|
||||
LinkTarget::Dest(dest) => body.linked(alt, dest.clone()),
|
||||
LinkTarget::Dest(dest) => body.linked(dest.clone(), alt),
|
||||
LinkTarget::Label(label) => {
|
||||
let elem = engine.introspector.query_label(*label).at(self.span())?;
|
||||
let dest = Destination::Location(elem.location().unwrap());
|
||||
body.clone().linked(alt, dest)
|
||||
body.clone().linked(dest, alt)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -446,7 +446,7 @@ impl Show for Packed<OutlineEntry> {
|
||||
};
|
||||
|
||||
let loc = self.element_location().at(span)?;
|
||||
Ok(block.linked(Some(alt), Destination::Location(loc)))
|
||||
Ok(block.linked(Destination::Location(loc), Some(alt)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ fn show_reference(
|
||||
}
|
||||
|
||||
// TODO: accept user supplied alt text
|
||||
Ok(content.linked(None, Destination::Location(loc)))
|
||||
Ok(content.linked(Destination::Location(loc), None))
|
||||
}
|
||||
|
||||
/// Turn a reference into a citation.
|
||||
|
@ -30,10 +30,6 @@ pub(crate) fn handle_image(
|
||||
|
||||
let interpolate = image.scaling() == Smart::Custom(ImageScaling::Smooth);
|
||||
|
||||
if let Some(alt) = image.alt() {
|
||||
surface.start_alt_text(alt);
|
||||
}
|
||||
|
||||
gc.image_spans.insert(span);
|
||||
|
||||
match image.kind() {
|
||||
@ -62,10 +58,6 @@ pub(crate) fn handle_image(
|
||||
}
|
||||
}
|
||||
|
||||
if image.alt().is_some() {
|
||||
surface.end_alt_text();
|
||||
}
|
||||
|
||||
surface.pop();
|
||||
surface.reset_location();
|
||||
|
||||
|
@ -9,10 +9,11 @@ use krilla::tagging::{
|
||||
use typst_library::foundations::{Content, StyleChain};
|
||||
use typst_library::introspection::Location;
|
||||
use typst_library::model::{
|
||||
CiteElem, FigureCaption, FigureElem, HeadingElem, LinkElem, OutlineElem,
|
||||
CiteElem, FigureCaption, FigureElem, HeadingElem, LinkElem, Outlinable, OutlineElem,
|
||||
OutlineEntry, RefElem,
|
||||
};
|
||||
use typst_library::pdf::{ArtifactElem, ArtifactKind, PdfTagElem, PdfTagKind};
|
||||
use typst_library::visualize::ImageElem;
|
||||
|
||||
use crate::convert::GlobalContext;
|
||||
|
||||
@ -177,7 +178,7 @@ pub(crate) fn handle_start(
|
||||
_ => todo!(),
|
||||
}
|
||||
} else if let Some(heading) = elem.to_packed::<HeadingElem>() {
|
||||
let level = heading.resolve_level(StyleChain::default());
|
||||
let level = heading.level();
|
||||
let name = heading.body.plain_text().to_string();
|
||||
match level.get() {
|
||||
1 => Tag::H1(Some(name)),
|
||||
@ -195,6 +196,25 @@ pub(crate) fn handle_start(
|
||||
} else if let Some(_) = elem.to_packed::<FigureElem>() {
|
||||
let alt = None; // TODO
|
||||
Tag::Figure(alt)
|
||||
} else if let Some(image) = elem.to_packed::<ImageElem>() {
|
||||
let alt = image.alt(StyleChain::default()).map(|s| s.to_string());
|
||||
|
||||
end_open(gc, surface);
|
||||
let id = surface.start_tagged(ContentTag::Other);
|
||||
let mut node = TagNode::Leaf(id);
|
||||
|
||||
if let Some(Tag::Figure(alt_text)) = gc.tags.parent().0 {
|
||||
// HACK: set alt text of outer figure tag, if the contained image
|
||||
// has alt text specified
|
||||
if alt_text.is_none() {
|
||||
*alt_text = alt;
|
||||
}
|
||||
} else {
|
||||
node = TagNode::Group(Tag::Figure(alt), vec![node]);
|
||||
}
|
||||
gc.tags.push(node);
|
||||
|
||||
return;
|
||||
} else if let Some(_) = elem.to_packed::<FigureCaption>() {
|
||||
Tag::Caption
|
||||
} else if let Some(_) = elem.to_packed::<LinkElem>() {
|
||||
@ -212,9 +232,7 @@ pub(crate) fn handle_start(
|
||||
}
|
||||
|
||||
// close previous marked-content and open a nested tag.
|
||||
if !gc.tags.stack.is_empty() {
|
||||
surface.end_tagged();
|
||||
}
|
||||
end_open(gc, surface);
|
||||
let id = surface.start_tagged(krilla::tagging::ContentTag::Other);
|
||||
gc.tags.stack.push((loc, tag, vec![TagNode::Leaf(id)]));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user