Primes should not further raise next superscript's position (#4492)

Co-authored-by: Ian Wrzesinski <133046678+wrzian@users.noreply.github.com>
This commit is contained in:
Leedehai 2024-07-08 15:32:58 -04:00 committed by GitHub
parent 86af5b5f61
commit d1c7d08893
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 53 additions and 25 deletions

View File

@ -393,11 +393,6 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
continue;
}
// Separate primes and superscripts to different attachments.
if primed && p.current() == SyntaxKind::Hat {
p.wrap(m, SyntaxKind::MathAttach);
}
let Some((kind, stop, assoc, mut prec)) = math_op(p.current()) else {
// No attachments, so we need to wrap primes as attachment.
if primed {
@ -429,7 +424,7 @@ fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
math_expr_prec(p, prec, stop);
math_unparen(p, m2);
if p.eat_if(SyntaxKind::Underscore) || (!primed && p.eat_if(SyntaxKind::Hat)) {
if p.eat_if(SyntaxKind::Underscore) || p.eat_if(SyntaxKind::Hat) {
let m3 = p.marker();
math_expr_prec(p, prec, SyntaxKind::End);
math_unparen(p, m3);

View File

@ -54,7 +54,11 @@ impl Eval for ast::MathAttach<'_> {
if let Some(expr) = self.top() {
elem.push_t(Some(expr.eval_display(vm)?));
} else if let Some(primes) = self.primes() {
}
// Always attach primes in scripts style (not limits style),
// i.e. at the top-right corner.
if let Some(primes) = self.primes() {
elem.push_tr(Some(primes.eval(vm)?));
}

View File

@ -52,31 +52,47 @@ pub struct AttachElem {
impl LayoutMath for Packed<AttachElem> {
#[typst_macros::time(name = "math.attach", span = self.span())]
fn layout_math(&self, ctx: &mut MathContext, styles: StyleChain) -> SourceResult<()> {
type GetAttachment = fn(&AttachElem, styles: StyleChain) -> Option<Content>;
let layout_attachment =
|ctx: &mut MathContext, styles: StyleChain, getter: GetAttachment| {
getter(self, styles)
.map(|elem| ctx.layout_into_fragment(&elem, styles))
.transpose()
};
let base = ctx.layout_into_fragment(self.base(), styles)?;
let sup_style = style_for_superscript(styles);
let tl = layout_attachment(ctx, styles.chain(&sup_style), AttachElem::tl)?;
let tr = layout_attachment(ctx, styles.chain(&sup_style), AttachElem::tr)?;
let t = layout_attachment(ctx, styles.chain(&sup_style), AttachElem::t)?;
let sup_style_chain = styles.chain(&sup_style);
let tl = self.tl(sup_style_chain);
let tr = self.tr(sup_style_chain);
let primed = tr.as_ref().is_some_and(|content| content.is::<PrimesElem>());
let t = self.t(sup_style_chain);
let sub_style = style_for_subscript(styles);
let bl = layout_attachment(ctx, styles.chain(&sub_style), AttachElem::bl)?;
let br = layout_attachment(ctx, styles.chain(&sub_style), AttachElem::br)?;
let b = layout_attachment(ctx, styles.chain(&sub_style), AttachElem::b)?;
let sub_style_chain = styles.chain(&sub_style);
let bl = self.bl(sub_style_chain);
let br = self.br(sub_style_chain);
let b = self.b(sub_style_chain);
let limits = base.limits().active(styles);
let (t, tr) = if limits || tr.is_some() { (t, tr) } else { (None, t) };
let (t, tr) = match (t, tr) {
(Some(t), Some(tr)) if primed && !limits => (None, Some(tr + t)),
(Some(t), None) if !limits => (None, Some(t)),
(t, tr) => (t, tr),
};
let (b, br) = if limits || br.is_some() { (b, br) } else { (None, b) };
layout_attachments(ctx, styles, base, [tl, t, tr, bl, b, br])
macro_rules! layout {
($content:ident, $style_chain:ident) => {
$content
.map(|elem| ctx.layout_into_fragment(&elem, $style_chain))
.transpose()
};
}
let fragments = [
layout!(tl, sup_style_chain)?,
layout!(t, sup_style_chain)?,
layout!(tr, sup_style_chain)?,
layout!(bl, sub_style_chain)?,
layout!(b, sub_style_chain)?,
layout!(br, sub_style_chain)?,
];
layout_attachments(ctx, styles, base, fragments)
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

View File

@ -12,7 +12,11 @@ $a'_b^c$, $a_b'^c$, $a_b^c'$, $a_b'^c'^d'$
$(a'_b')^(c'_d')$, $a'/b'$, $a_b'/c_d'$
$'$, $'$, $ '_S' $
$'$, $'$, $a'^2^2$, $a'_2_2$
$f_n'^a'$, $f^a'_n'$
$ '_S' $
--- math-primes-attach ---
// Test attaching primes only
@ -48,3 +52,12 @@ $
#g''''''''''''''''' \
gg'
$
--- math-primes-with-superscript ---
// Test prime symbols don't raise the superscript position
$
sqrt(f)/f
sqrt(f^2)/f^2
sqrt(f'^2)/f'^2
sqrt(f''_n^2)/f''^2_n
$