From 1bd8ff0e0fa7966f4bd2a4426241781bed168df7 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 23 Jan 2025 11:16:04 +0100 Subject: [PATCH 1/9] Methods on elements (#5733) --- crates/typst-eval/src/call.rs | 24 ++++++++++++++++++++++-- tests/suite/scripting/methods.typ | 2 +- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/crates/typst-eval/src/call.rs b/crates/typst-eval/src/call.rs index 0a9e1c486..69b274bbc 100644 --- a/crates/typst-eval/src/call.rs +++ b/crates/typst-eval/src/call.rs @@ -325,6 +325,13 @@ fn eval_field_call( } else if let Some(callee) = target.ty().scope().get(&field) { args.insert(0, target_expr.span(), target); Ok(FieldCall::Normal(callee.clone(), args)) + } else if let Value::Content(content) = &target { + if let Some(callee) = content.elem().scope().get(&field) { + args.insert(0, target_expr.span(), target); + Ok(FieldCall::Normal(callee.clone(), args)) + } else { + bail!(missing_field_call_error(target, field)) + } } else if matches!( target, Value::Symbol(_) | Value::Func(_) | Value::Type(_) | Value::Module(_) @@ -341,8 +348,20 @@ fn eval_field_call( /// Produce an error when we cannot call the field. fn missing_field_call_error(target: Value, field: Ident) -> SourceDiagnostic { - let mut error = - error!(field.span(), "type {} has no method `{}`", target.ty(), field.as_str()); + let mut error = match &target { + Value::Content(content) => error!( + field.span(), + "element {} has no method `{}`", + content.elem().name(), + field.as_str(), + ), + _ => error!( + field.span(), + "type {} has no method `{}`", + target.ty(), + field.as_str() + ), + }; match target { Value::Dict(ref dict) if matches!(dict.get(&field), Ok(Value::Func(_))) => { @@ -360,6 +379,7 @@ fn missing_field_call_error(target: Value, field: Ident) -> SourceDiagnostic { } _ => {} } + error } diff --git a/tests/suite/scripting/methods.typ b/tests/suite/scripting/methods.typ index 5deea2cfa..566e9d9a5 100644 --- a/tests/suite/scripting/methods.typ +++ b/tests/suite/scripting/methods.typ @@ -31,7 +31,7 @@ #numbers.fun() --- method-unknown-but-field-exists --- -// Error: 2:4-2:10 type content has no method `stroke` +// Error: 2:4-2:10 element line has no method `stroke` // Hint: 2:4-2:10 did you mean to access the field `stroke`? #let l = line(stroke: red) #l.stroke() From 52ee33a275063369673d8802fb820db3825a661f Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 23 Jan 2025 12:50:51 +0100 Subject: [PATCH 2/9] Rework outline (#5735) --- crates/typst-library/src/layout/repeat.rs | 2 +- crates/typst-library/src/math/equation.rs | 37 +- crates/typst-library/src/model/figure.rs | 61 +- crates/typst-library/src/model/heading.rs | 54 +- crates/typst-library/src/model/outline.rs | 817 +++++++++++------- crates/typst-library/src/model/terms.rs | 11 +- crates/typst-utils/src/lib.rs | 9 + tests/ref/heading-hanging-indent-auto.png | Bin 0 -> 849 bytes tests/ref/heading-hanging-indent-length.png | Bin 0 -> 1396 bytes tests/ref/heading-hanging-indent-zero.png | Bin 0 -> 859 bytes .../ref/issue-1041-smartquotes-in-outline.png | Bin 3467 -> 3412 bytes tests/ref/issue-2048-outline-multiline.png | Bin 0 -> 1634 bytes ...6-outline-rtl-title-ending-in-ltr-text.png | Bin 0 -> 3341 bytes ...ssue-4476-rtl-title-ending-in-ltr-text.png | Bin 6307 -> 0 bytes .../ref/issue-4859-outline-entry-show-set.png | Bin 0 -> 749 bytes tests/ref/issue-5176-cjk-title.png | Bin 1246 -> 0 bytes tests/ref/issue-5176-outline-cjk-title.png | Bin 0 -> 1218 bytes ...-5370-figure-caption-separator-outline.png | Bin 2078 -> 0 bytes tests/ref/issue-622-hide-meta-outline.png | Bin 2109 -> 2061 bytes tests/ref/issue-785-cite-locate.png | Bin 9191 -> 9441 bytes tests/ref/outline-bookmark.png | Bin 1030 -> 474 bytes tests/ref/outline-entry-complex.png | Bin 14460 -> 8461 bytes tests/ref/outline-entry-inner.png | Bin 0 -> 462 bytes tests/ref/outline-entry.png | Bin 10099 -> 5890 bytes tests/ref/outline-first-line-indent.png | Bin 10837 -> 5539 bytes tests/ref/outline-heading-start-of-page.png | Bin 0 -> 6935 bytes ...outline-indent-auto-mixed-prefix-short.png | Bin 0 -> 1045 bytes .../ref/outline-indent-auto-mixed-prefix.png | Bin 0 -> 5712 bytes tests/ref/outline-indent-auto-no-prefix.png | Bin 0 -> 3101 bytes tests/ref/outline-indent-auto.png | Bin 0 -> 5176 bytes tests/ref/outline-indent-fixed.png | Bin 0 -> 3018 bytes tests/ref/outline-indent-func.png | Bin 0 -> 2884 bytes tests/ref/outline-indent-no-numbering.png | Bin 2924 -> 0 bytes tests/ref/outline-indent-numbering.png | Bin 7101 -> 0 bytes tests/ref/outline-indent-zero.png | Bin 0 -> 3465 bytes tests/ref/outline-spacing.png | Bin 0 -> 2553 bytes tests/ref/outline-styled-text.png | Bin 1481 -> 1416 bytes tests/ref/outline.png | Bin 6743 -> 0 bytes tests/ref/query-running-header.png | Bin 9302 -> 9064 bytes tests/suite/model/figure.typ | 6 - tests/suite/model/heading.typ | 12 + tests/suite/model/outline.typ | 344 +++++--- 42 files changed, 831 insertions(+), 522 deletions(-) create mode 100644 tests/ref/heading-hanging-indent-auto.png create mode 100644 tests/ref/heading-hanging-indent-length.png create mode 100644 tests/ref/heading-hanging-indent-zero.png create mode 100644 tests/ref/issue-2048-outline-multiline.png create mode 100644 tests/ref/issue-4476-outline-rtl-title-ending-in-ltr-text.png delete mode 100644 tests/ref/issue-4476-rtl-title-ending-in-ltr-text.png create mode 100644 tests/ref/issue-4859-outline-entry-show-set.png delete mode 100644 tests/ref/issue-5176-cjk-title.png create mode 100644 tests/ref/issue-5176-outline-cjk-title.png delete mode 100644 tests/ref/issue-5370-figure-caption-separator-outline.png create mode 100644 tests/ref/outline-entry-inner.png create mode 100644 tests/ref/outline-heading-start-of-page.png create mode 100644 tests/ref/outline-indent-auto-mixed-prefix-short.png create mode 100644 tests/ref/outline-indent-auto-mixed-prefix.png create mode 100644 tests/ref/outline-indent-auto-no-prefix.png create mode 100644 tests/ref/outline-indent-auto.png create mode 100644 tests/ref/outline-indent-fixed.png create mode 100644 tests/ref/outline-indent-func.png delete mode 100644 tests/ref/outline-indent-no-numbering.png delete mode 100644 tests/ref/outline-indent-numbering.png create mode 100644 tests/ref/outline-indent-zero.png create mode 100644 tests/ref/outline-spacing.png delete mode 100644 tests/ref/outline.png diff --git a/crates/typst-library/src/layout/repeat.rs b/crates/typst-library/src/layout/repeat.rs index e423410ab..9579f1856 100644 --- a/crates/typst-library/src/layout/repeat.rs +++ b/crates/typst-library/src/layout/repeat.rs @@ -10,7 +10,7 @@ use crate::layout::{BlockElem, Length}; /// Space may be inserted between the instances of the body parameter, so be /// sure to adjust the [`justify`]($repeat.justify) parameter accordingly. /// -/// Errors if there no bounds on the available space, as it would create +/// Errors if there are no bounds on the available space, as it would create /// infinite content. /// /// # Example diff --git a/crates/typst-library/src/math/equation.rs b/crates/typst-library/src/math/equation.rs index a9173c433..1e346280a 100644 --- a/crates/typst-library/src/math/equation.rs +++ b/crates/typst-library/src/math/equation.rs @@ -229,35 +229,20 @@ impl Refable for Packed { } impl Outlinable for Packed { - fn outline( - &self, - engine: &mut Engine, - styles: StyleChain, - ) -> SourceResult> { - if !self.block(StyleChain::default()) { - return Ok(None); - } - let Some(numbering) = self.numbering() else { - return Ok(None); - }; - - // After synthesis, this should always be custom content. - let mut supplement = match (**self).supplement(StyleChain::default()) { - Smart::Custom(Some(Supplement::Content(content))) => content, - _ => Content::empty(), - }; + fn outlined(&self) -> bool { + self.block(StyleChain::default()) && self.numbering().is_some() + } + fn prefix(&self, numbers: Content) -> Content { + let supplement = self.supplement(); if !supplement.is_empty() { - supplement += TextElem::packed("\u{a0}"); + supplement + TextElem::packed('\u{a0}') + numbers + } else { + numbers } + } - let numbers = self.counter().display_at_loc( - engine, - self.location().unwrap(), - styles, - numbering, - )?; - - Ok(Some(supplement + numbers)) + fn body(&self) -> Content { + Content::empty() } } diff --git a/crates/typst-library/src/model/figure.rs b/crates/typst-library/src/model/figure.rs index 52dca966d..ce7460c9b 100644 --- a/crates/typst-library/src/model/figure.rs +++ b/crates/typst-library/src/model/figure.rs @@ -156,6 +156,7 @@ pub struct FigureElem { pub scope: PlacementScope, /// The figure's caption. + #[borrowed] pub caption: Option>, /// The kind of figure this is. @@ -305,7 +306,7 @@ impl Synthesize for Packed { )); // Fill the figure's caption. - let mut caption = elem.caption(styles); + let mut caption = elem.caption(styles).clone(); if let Some(caption) = &mut caption { caption.synthesize(engine, styles)?; caption.push_kind(kind.clone()); @@ -331,7 +332,7 @@ impl Show for Packed { let mut realized = self.body.clone(); // Build the caption, if any. - if let Some(caption) = self.caption(styles) { + if let Some(caption) = self.caption(styles).clone() { let (first, second) = match caption.position(styles) { OuterVAlignment::Top => (caption.pack(), realized), OuterVAlignment::Bottom => (realized, caption.pack()), @@ -423,46 +424,26 @@ impl Refable for Packed { } impl Outlinable for Packed { - fn outline( - &self, - engine: &mut Engine, - styles: StyleChain, - ) -> SourceResult> { - if !self.outlined(StyleChain::default()) { - return Ok(None); + fn outlined(&self) -> bool { + (**self).outlined(StyleChain::default()) + && (self.caption(StyleChain::default()).is_some() + || self.numbering().is_some()) + } + + fn prefix(&self, numbers: Content) -> Content { + let supplement = self.supplement(); + if !supplement.is_empty() { + supplement + TextElem::packed('\u{a0}') + numbers + } else { + numbers } + } - let Some(caption) = self.caption(StyleChain::default()) else { - return Ok(None); - }; - - let mut realized = caption.body.clone(); - if let ( - Smart::Custom(Some(Supplement::Content(mut supplement))), - Some(Some(counter)), - Some(numbering), - ) = ( - (**self).supplement(StyleChain::default()).clone(), - (**self).counter(), - self.numbering(), - ) { - let numbers = counter.display_at_loc( - engine, - self.location().unwrap(), - styles, - numbering, - )?; - - if !supplement.is_empty() { - supplement += TextElem::packed('\u{a0}'); - } - - let separator = caption.get_separator(StyleChain::default()); - - realized = supplement + numbers + separator + caption.body.clone(); - } - - Ok(Some(realized)) + fn body(&self) -> Content { + self.caption(StyleChain::default()) + .as_ref() + .map(|caption| caption.body.clone()) + .unwrap_or_default() } } diff --git a/crates/typst-library/src/model/heading.rs b/crates/typst-library/src/model/heading.rs index db131afec..00931c815 100644 --- a/crates/typst-library/src/model/heading.rs +++ b/crates/typst-library/src/model/heading.rs @@ -1,7 +1,7 @@ use std::num::NonZeroUsize; use ecow::eco_format; -use typst_utils::NonZeroExt; +use typst_utils::{Get, NonZeroExt}; use crate::diag::{warning, SourceResult}; use crate::engine::Engine; @@ -13,8 +13,8 @@ use crate::html::{attr, tag, HtmlElem}; use crate::introspection::{ Count, Counter, CounterUpdate, Locatable, Locator, LocatorLink, }; -use crate::layout::{Abs, Axes, BlockBody, BlockElem, Em, HElem, Length, Region}; -use crate::model::{Numbering, Outlinable, ParElem, Refable, Supplement}; +use crate::layout::{Abs, Axes, BlockBody, BlockElem, Em, HElem, Length, Region, Sides}; +use crate::model::{Numbering, Outlinable, Refable, Supplement}; use crate::text::{FontWeight, LocalName, SpaceElem, TextElem, TextSize}; /// A section heading. @@ -264,10 +264,6 @@ impl Show for Packed { realized = numbering + spacing + realized; } - if indent != Abs::zero() && !html { - realized = realized.styled(ParElem::set_hanging_indent(indent.into())); - } - Ok(if html { // HTML's h1 is closer to a title element. There should only be one. // Meanwhile, a level 1 Typst heading is a section heading. For this @@ -294,8 +290,17 @@ impl Show for Packed { HtmlElem::new(t).with_body(Some(realized)).pack().spanned(span) } } else { - let realized = BlockBody::Content(realized); - BlockElem::new().with_body(Some(realized)).pack().spanned(span) + let block = if indent != Abs::zero() { + let body = HElem::new((-indent).into()).pack() + realized; + let inset = Sides::default() + .with(TextElem::dir_in(styles).start(), Some(indent.into())); + BlockElem::new() + .with_body(Some(BlockBody::Content(body))) + .with_inset(inset) + } else { + BlockElem::new().with_body(Some(BlockBody::Content(realized))) + }; + block.pack().spanned(span) }) } } @@ -351,32 +356,21 @@ impl Refable for Packed { } impl Outlinable for Packed { - fn outline( - &self, - engine: &mut Engine, - styles: StyleChain, - ) -> SourceResult> { - if !self.outlined(StyleChain::default()) { - return Ok(None); - } - - let mut content = self.body.clone(); - if let Some(numbering) = (**self).numbering(StyleChain::default()).as_ref() { - let numbers = Counter::of(HeadingElem::elem()).display_at_loc( - engine, - self.location().unwrap(), - styles, - numbering, - )?; - content = numbers + SpaceElem::shared().clone() + content; - }; - - Ok(Some(content)) + fn outlined(&self) -> bool { + (**self).outlined(StyleChain::default()) } fn level(&self) -> NonZeroUsize { (**self).resolve_level(StyleChain::default()) } + + fn prefix(&self, numbers: Content) -> Content { + numbers + } + + fn body(&self) -> Content { + self.body.clone() + } } impl LocalName for Packed { diff --git a/crates/typst-library/src/model/outline.rs b/crates/typst-library/src/model/outline.rs index 84661c1c2..0db056e40 100644 --- a/crates/typst-library/src/model/outline.rs +++ b/crates/typst-library/src/model/outline.rs @@ -1,50 +1,61 @@ use std::num::NonZeroUsize; use std::str::FromStr; -use comemo::Track; +use comemo::{Track, Tracked}; +use smallvec::SmallVec; use typst_syntax::Span; -use typst_utils::NonZeroExt; +use typst_utils::{Get, NonZeroExt}; -use crate::diag::{bail, At, SourceResult}; +use crate::diag::{bail, error, At, HintedStrResult, SourceResult, StrResult}; use crate::engine::Engine; use crate::foundations::{ - cast, elem, scope, select_where, Content, Context, Func, LocatableSelector, - NativeElement, Packed, Show, ShowSet, Smart, StyleChain, Styles, + cast, elem, func, scope, select_where, Args, Construct, Content, Context, Func, + LocatableSelector, NativeElement, Packed, Resolve, Show, ShowSet, Smart, StyleChain, + Styles, +}; +use crate::introspection::{ + Counter, CounterKey, Introspector, Locatable, Location, Locator, LocatorLink, }; -use crate::introspection::{Counter, CounterKey, Locatable}; use crate::layout::{ - BoxElem, Dir, Em, Fr, HElem, HideElem, Length, Rel, RepeatElem, Spacing, + Abs, Axes, BlockBody, BlockElem, BoxElem, Dir, Em, Fr, HElem, Length, Region, Rel, + RepeatElem, Sides, }; -use crate::model::{ - Destination, HeadingElem, NumberingPattern, ParElem, ParbreakElem, Refable, -}; -use crate::text::{LinebreakElem, LocalName, SpaceElem, TextElem}; +use crate::math::EquationElem; +use crate::model::{Destination, HeadingElem, NumberingPattern, ParElem, Refable}; +use crate::text::{LocalName, SpaceElem, TextElem}; /// A table of contents, figures, or other elements. /// /// This function generates a list of all occurrences of an element in the -/// document, up to a given depth. The element's numbering and page number will -/// be displayed in the outline alongside its title or caption. By default this -/// generates a table of contents. +/// document, up to a given [`depth`]($outline.depth). The element's numbering +/// and page number will be displayed in the outline alongside its title or +/// caption. /// /// # Example /// ```example +/// #set heading(numbering: "1.") /// #outline() /// /// = Introduction /// #lorem(5) /// -/// = Prior work +/// = Methods +/// == Setup /// #lorem(10) /// ``` /// /// # Alternative outlines +/// In its default configuration, this function generates a table of contents. /// By setting the `target` parameter, the outline can be used to generate a -/// list of other kinds of elements than headings. In the example below, we list -/// all figures containing images by setting `target` to `{figure.where(kind: -/// image)}`. We could have also set it to just `figure`, but then the list -/// would also include figures containing tables or other material. For more -/// details on the `where` selector, [see here]($function.where). +/// list of other kinds of elements than headings. +/// +/// In the example below, we list all figures containing images by setting +/// `target` to `{figure.where(kind: image)}`. Just the same, we could have set +/// it to `{figure.where(kind: table)}` to generate a list of tables. +/// +/// We could also set it to just `figure`, without using a [`where`]($function.where) +/// selector, but then the list would contain _all_ figures, be it ones +/// containing images, tables, or other material. /// /// ```example /// #outline( @@ -59,16 +70,89 @@ use crate::text::{LinebreakElem, LocalName, SpaceElem, TextElem}; /// ``` /// /// # Styling the outline -/// The outline element has several options for customization, such as its -/// `title` and `indent` parameters. If desired, however, it is possible to have -/// more control over the outline's look and style through the -/// [`outline.entry`]($outline.entry) element. -#[elem(scope, keywords = ["Table of Contents"], Show, ShowSet, LocalName)] +/// At the most basic level, you can style the outline by setting properties on +/// it and its entries. This way, you can customize the outline's +/// [title]($outline.title), how outline entries are +/// [indented]($outline.indent), and how the space between an entry's text and +/// its page number should be [filled]($outline.entry.fill). +/// +/// Richer customization is possible through configuration of the outline's +/// [entries]($outline.entry). The outline generates one entry for each outlined +/// element. +/// +/// ## Spacing the entries { #entry-spacing } +/// Outline entries are [blocks]($block), so you can adjust the spacing between +/// them with normal block-spacing rules: +/// +/// ```example +/// #show outline.entry.where( +/// level: 1 +/// ): set block(above: 1.2em) +/// +/// #outline() +/// +/// = About ACME Corp. +/// == History +/// === Origins +/// = Products +/// == ACME Tools +/// ``` +/// +/// ## Building an outline entry from its parts { #building-an-entry } +/// For full control, you can also write a transformational show rule on +/// `outline.entry`. However, the logic for properly formatting and indenting +/// outline entries is quite complex and the outline entry itself only contains +/// two fields: The level and the outlined element. +/// +/// For this reason, various helper functions are provided. You can mix and +/// match these to compose an entry from just the parts you like. +/// +/// The default show rule for an outline entry looks like this[^1]: +/// ```typ +/// #show outline.entry: it => link( +/// it.element.location(), +/// it.indented(it.prefix(), it.inner()), +/// ) +/// ``` +/// +/// - The [`indented`]($outline.entry.indented) function takes an optional +/// prefix and inner content and automatically applies the proper indentation +/// to it, such that different entries align nicely and long headings wrap +/// properly. +/// +/// - The [`prefix`]($outline.entry.prefix) function formats the element's +/// numbering (if any). It also appends a supplement for certain elements. +/// +/// - The [`inner`]($outline.entry.inner) function combines the element's +/// [`body`]($outline.entry.body), the filler, and the +/// [`page` number]($outline.entry.page). +/// +/// You can use these individual functions to format the outline entry in +/// different ways. Let's say, you'd like to fully remove the filler and page +/// numbers. To achieve this, you could write a show rule like this: +/// +/// ```example +/// #show outline.entry: it => link( +/// it.element.location(), +/// // Keep just the body, dropping +/// // the fill and the page. +/// it.indented(it.prefix(), it.body()), +/// ) +/// +/// #outline() +/// +/// = About ACME Corp. +/// == History +/// ``` +/// +/// [^1]: The outline of equations is the exception to this rule as it does not +/// have a body and thus does not use indented layout. +#[elem(scope, keywords = ["Table of Contents", "toc"], Show, ShowSet, LocalName, Locatable)] pub struct OutlineElem { /// The title of the outline. /// /// - When set to `{auto}`, an appropriate title for the - /// [text language]($text.lang) will be used. This is the default. + /// [text language]($text.lang) will be used. /// - When set to `{none}`, the outline will not have a title. /// - A custom title can be set by passing content. /// @@ -79,8 +163,10 @@ pub struct OutlineElem { /// The type of element to include in the outline. /// - /// To list figures containing a specific kind of element, like a table, you - /// can write `{figure.where(kind: table)}`. + /// To list figures containing a specific kind of element, like an image or + /// a table, you can specify the desired kind in a [`where`]($function.where) + /// selector. See the section on [alternative outlines]($outline/#alternative-outlines) + /// for more details. /// /// ```example /// #outline( @@ -97,7 +183,7 @@ pub struct OutlineElem { /// caption: [Experiment results], /// ) /// ``` - #[default(LocatableSelector(select_where!(HeadingElem, Outlined => true)))] + #[default(LocatableSelector(HeadingElem::elem().select()))] #[borrowed] pub target: LocatableSelector, @@ -121,21 +207,22 @@ pub struct OutlineElem { /// How to indent the outline's entries. /// - /// - `{none}`: No indent - /// - `{auto}`: Indents the numbering of the nested entry with the title of - /// its parent entry. This only has an effect if the entries are numbered - /// (e.g., via [heading numbering]($heading.numbering)). - /// - [Relative length]($relative): Indents the item by this length - /// multiplied by its nesting level. Specifying `{2em}`, for instance, - /// would indent top-level headings (not nested) by `{0em}`, second level + /// - `{auto}`: Indents the numbering/prefix of a nested entry with the + /// title of its parent entry. If the entries are not numbered (e.g., via + /// [heading numbering]($heading.numbering)), this instead simply inserts + /// a fixed amount of `{1.2em}` indent per level. + /// + /// - [Relative length]($relative): Indents the entry by the specified + /// length per nesting level. Specifying `{2em}`, for instance, would + /// indent top-level headings by `{0em}` (not nested), second level /// headings by `{2em}` (nested once), third-level headings by `{4em}` /// (nested twice) and so on. - /// - [Function]($function): You can completely customize this setting with - /// a function. That function receives the nesting level as a parameter - /// (starting at 0 for top-level headings/elements) and can return a - /// relative length or content making up the indent. For example, - /// `{n => n * 2em}` would be equivalent to just specifying `{2em}`, while - /// `{n => [→ ] * n}` would indent with one arrow per nesting level. + /// + /// - [Function]($function): You can further customize this setting with a + /// function. That function receives the nesting level as a parameter + /// (starting at 0 for top-level headings/elements) and should return a + /// (relative) length. For example, `{n => n * 2em}` would be equivalent + /// to just specifying `{2em}`. /// /// ```example /// #set heading(numbering: "1.a.") @@ -150,11 +237,6 @@ pub struct OutlineElem { /// indent: 2em, /// ) /// - /// #outline( - /// title: [Contents (Function)], - /// indent: n => [→ ] * n, - /// ) - /// /// = About ACME Corp. /// == History /// === Origins @@ -163,20 +245,7 @@ pub struct OutlineElem { /// == Products /// #lorem(10) /// ``` - #[default(None)] - #[borrowed] - pub indent: Option>, - - /// Content to fill the space between the title and the page number. Can be - /// set to `{none}` to disable filling. - /// - /// ```example - /// #outline(fill: line(length: 100%)) - /// - /// = A New Beginning - /// ``` - #[default(Some(RepeatElem::new(TextElem::packed(".")).pack()))] - pub fill: Option, + pub indent: Smart, } #[scope] @@ -188,79 +257,52 @@ impl OutlineElem { impl Show for Packed { #[typst_macros::time(name = "outline", span = self.span())] fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult { - let mut seq = vec![ParbreakElem::shared().clone()]; + let span = self.span(); + // Build the outline title. + let mut seq = vec![]; if let Some(title) = self.title(styles).unwrap_or_else(|| { - Some(TextElem::packed(Self::local_name_in(styles)).spanned(self.span())) + Some(TextElem::packed(Self::local_name_in(styles)).spanned(span)) }) { seq.push( HeadingElem::new(title) .with_depth(NonZeroUsize::ONE) .pack() - .spanned(self.span()), + .spanned(span), ); } - let indent = self.indent(styles); - let depth = self.depth(styles).unwrap_or(NonZeroUsize::new(usize::MAX).unwrap()); - - let mut ancestors: Vec<&Content> = vec![]; let elems = engine.introspector.query(&self.target(styles).0); + let depth = self.depth(styles).unwrap_or(NonZeroUsize::MAX); - for elem in &elems { - let Some(entry) = OutlineEntry::from_outlinable( - engine, - self.span(), - elem.clone(), - self.fill(styles), - styles, - )? - else { - continue; + // Build the outline entries. + for elem in elems { + let Some(outlinable) = elem.with::() else { + bail!(span, "cannot outline {}", elem.func().name()); }; - if depth < entry.level { - continue; + let level = outlinable.level(); + if outlinable.outlined() && level <= depth { + let entry = OutlineEntry::new(level, elem); + seq.push(entry.pack().spanned(span)); } - - // Deals with the ancestors of the current element. - // This is only applicable for elements with a hierarchy/level. - while ancestors - .last() - .and_then(|ancestor| ancestor.with::()) - .is_some_and(|last| last.level() >= entry.level) - { - ancestors.pop(); - } - - OutlineIndent::apply( - indent, - engine, - &ancestors, - &mut seq, - styles, - self.span(), - )?; - - // Add the overridable outline entry, followed by a line break. - seq.push(entry.pack().spanned(self.span())); - seq.push(LinebreakElem::shared().clone()); - - ancestors.push(elem); } - seq.push(ParbreakElem::shared().clone()); - Ok(Content::sequence(seq)) } } impl ShowSet for Packed { - fn show_set(&self, _: StyleChain) -> Styles { + fn show_set(&self, styles: StyleChain) -> Styles { let mut out = Styles::new(); out.set(HeadingElem::set_outlined(false)); out.set(HeadingElem::set_numbering(None)); out.set(ParElem::set_first_line_indent(Em::new(0.0).into())); + out.set(ParElem::set_justify(false)); + out.set(BlockElem::set_above(Smart::Custom(ParElem::leading_in(styles).into()))); + // Makes the outline itself available to its entries. Should be + // superseded by a proper ancestry mechanism in the future. + out.set(OutlineEntry::set_parent(Some(self.clone()))); out } } @@ -269,93 +311,29 @@ impl LocalName for Packed { const KEY: &'static str = "outline"; } -/// Marks an element as being able to be outlined. This is used to implement the -/// `#outline()` element. -pub trait Outlinable: Refable { - /// Produce an outline item for this element. - fn outline( - &self, - engine: &mut Engine, - - styles: StyleChain, - ) -> SourceResult>; - - /// Returns the nesting level of this element. - fn level(&self) -> NonZeroUsize { - NonZeroUsize::ONE - } -} - /// Defines how an outline is indented. #[derive(Debug, Clone, PartialEq, Hash)] pub enum OutlineIndent { - Rel(Rel), + /// Indents by the specified length per level. + Rel(Rel), + /// Resolve the indent for a specific level through the given function. Func(Func), } impl OutlineIndent { - fn apply( - indent: &Option>, + /// Resolve the indent for an entry with the given level. + fn resolve( + &self, engine: &mut Engine, - ancestors: &Vec<&Content>, - seq: &mut Vec, - styles: StyleChain, + context: Tracked, + level: NonZeroUsize, span: Span, - ) -> SourceResult<()> { - match indent { - // 'none' | 'false' => no indenting - None => {} - - // 'auto' | 'true' => use numbering alignment for indenting - Some(Smart::Auto) => { - // Add hidden ancestors numberings to realize the indent. - let mut hidden = Content::empty(); - for ancestor in ancestors { - let ancestor_outlinable = ancestor.with::().unwrap(); - - if let Some(numbering) = ancestor_outlinable.numbering() { - let numbers = ancestor_outlinable.counter().display_at_loc( - engine, - ancestor.location().unwrap(), - styles, - numbering, - )?; - - hidden += numbers + SpaceElem::shared().clone(); - }; - } - - if !ancestors.is_empty() { - seq.push(HideElem::new(hidden).pack().spanned(span)); - seq.push(SpaceElem::shared().clone().spanned(span)); - } - } - - // Length => indent with some fixed spacing per level - Some(Smart::Custom(OutlineIndent::Rel(length))) => { - seq.push( - HElem::new(Spacing::Rel(*length)) - .pack() - .spanned(span) - .repeat(ancestors.len()), - ); - } - - // Function => call function with the current depth and take - // the returned content - Some(Smart::Custom(OutlineIndent::Func(func))) => { - let depth = ancestors.len(); - let LengthOrContent(content) = func - .call(engine, Context::new(None, Some(styles)).track(), [depth])? - .cast() - .at(span)?; - if !content.is_empty() { - seq.push(content); - } - } - }; - - Ok(()) + ) -> SourceResult { + let depth = level.get() - 1; + match self { + Self::Rel(length) => Ok(*length * depth as f64), + Self::Func(func) => func.call(engine, context, [depth])?.cast().at(span), + } } } @@ -365,46 +343,33 @@ cast! { Self::Rel(v) => v.into_value(), Self::Func(v) => v.into_value() }, - v: Rel => OutlineIndent::Rel(v), - v: Func => OutlineIndent::Func(v), + v: Rel => Self::Rel(v), + v: Func => Self::Func(v), } -struct LengthOrContent(Content); +/// Marks an element as being able to be outlined. +pub trait Outlinable: Refable { + /// Whether this element should be included in the outline. + fn outlined(&self) -> bool; -cast! { - LengthOrContent, - v: Rel => Self(HElem::new(Spacing::Rel(v)).pack()), - v: Content => Self(v), + /// The nesting level of this element. + fn level(&self) -> NonZeroUsize { + NonZeroUsize::ONE + } + + /// Constructs the default prefix given the formatted numbering. + fn prefix(&self, numbers: Content) -> Content; + + /// The body of the entry. + fn body(&self) -> Content; } -/// Represents each entry line in an outline, including the reference to the -/// outlined element, its page number, and the filler content between both. +/// Represents an entry line in an outline. /// -/// This element is intended for use with show rules to control the appearance -/// of outlines. To customize an entry's line, you can build it from scratch by -/// accessing the `level`, `element`, `body`, `fill` and `page` fields on the -/// entry. -/// -/// ```example -/// #set heading(numbering: "1.") -/// -/// #show outline.entry.where( -/// level: 1 -/// ): it => { -/// v(12pt, weak: true) -/// strong(it) -/// } -/// -/// #outline(indent: auto) -/// -/// = Introduction -/// = Background -/// == History -/// == State of the Art -/// = Analysis -/// == Setup -/// ``` -#[elem(name = "entry", title = "Outline Entry", Show)] +/// With show-set and show rules on outline entries, you can richly customize +/// the outline's appearance. See the +/// [section on styling the outline]($outline/#styling-the-outline) for details. +#[elem(scope, name = "entry", title = "Outline Entry", Show)] pub struct OutlineEntry { /// The nesting level of this outline entry. Starts at `{1}` for top-level /// entries. @@ -412,90 +377,206 @@ pub struct OutlineEntry { pub level: NonZeroUsize, /// The element this entry refers to. Its location will be available - /// through the [`location`]($content.location) method on content + /// through the [`location`]($content.location) method on the content /// and can be [linked]($link) to. #[required] pub element: Content, - /// The content which is displayed in place of the referred element at its - /// entry in the outline. For a heading, this would be its number followed - /// by the heading's title, for example. - #[required] - pub body: Content, - - /// The content used to fill the space between the element's outline and - /// its page number, as defined by the outline element this entry is - /// located in. When `{none}`, empty space is inserted in that gap instead. + /// Content to fill the space between the title and the page number. Can be + /// set to `{none}` to disable filling. /// - /// Note that, when using show rules to override outline entries, it is - /// recommended to wrap the filling content in a [`box`] with fractional - /// width. For example, `{box(width: 1fr, repeat[-])}` would show precisely - /// as many `-` characters as necessary to fill a particular gap. - #[required] + /// The `fill` will be placed into a fractionally sized box that spans the + /// space between the entry's body and the page number. When using show + /// rules to override outline entries, it is thus recommended to wrap the + /// fill in a [`box`] with fractional width, i.e. + /// `{box(width: 1fr, it.fill}`. + /// + /// When using [`repeat`], the [`gap`]($repeat.gap) property can be useful + /// to tweak the visual weight of the fill. + /// + /// ```example + /// #set outline.entry(fill: line(length: 100%)) + /// #outline() + /// + /// = A New Beginning + /// ``` + #[borrowed] + #[default(Some( + RepeatElem::new(TextElem::packed(".")) + .with_gap(Em::new(0.15).into()) + .pack() + ))] pub fill: Option, - /// The page number of the element this entry links to, formatted with the - /// numbering set for the referenced page. - #[required] - pub page: Content, -} - -impl OutlineEntry { - /// Generates an OutlineEntry from the given element, if possible (errors if - /// the element does not implement `Outlinable`). If the element should not - /// be outlined (e.g. heading with 'outlined: false'), does not generate an - /// entry instance (returns `Ok(None)`). - fn from_outlinable( - engine: &mut Engine, - span: Span, - elem: Content, - fill: Option, - styles: StyleChain, - ) -> SourceResult> { - let Some(outlinable) = elem.with::() else { - bail!(span, "cannot outline {}", elem.func().name()); - }; - - let Some(body) = outlinable.outline(engine, styles)? else { - return Ok(None); - }; - - let location = elem.location().unwrap(); - let page_numbering = engine - .introspector - .page_numbering(location) - .cloned() - .unwrap_or_else(|| NumberingPattern::from_str("1").unwrap().into()); - - let page = Counter::new(CounterKey::Page).display_at_loc( - engine, - location, - styles, - &page_numbering, - )?; - - Ok(Some(Self::new(outlinable.level(), elem, body, fill, page))) - } + /// Lets outline entries access the outline they are part of. This is a bit + /// of a hack and should be superseded by a proper ancestry mechanism. + #[ghost] + #[internal] + pub parent: Option>, } impl Show for Packed { #[typst_macros::time(name = "outline.entry", span = self.span())] - fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult { - let mut seq = vec![]; - let elem = &self.element; + fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult { + let span = self.span(); + let context = Context::new(None, Some(styles)); + let context = context.track(); - // In case a user constructs an outline entry with an arbitrary element. - let Some(location) = elem.location() else { - if elem.can::() && elem.can::() { - bail!( - self.span(), "{} must have a location", elem.func().name(); - hint: "try using a query or a show rule to customize the outline.entry instead", - ) - } else { - bail!(self.span(), "cannot outline {}", elem.func().name()) + let prefix = self.prefix(engine, context, span)?; + let inner = self.inner(engine, context, span)?; + let block = if self.element.is::() { + let body = prefix.unwrap_or_default() + inner; + BlockElem::new() + .with_body(Some(BlockBody::Content(body))) + .pack() + .spanned(span) + } else { + self.indented(engine, context, span, prefix, inner, Em::new(0.5).into())? + }; + + let loc = self.element_location().at(span)?; + Ok(block.linked(Destination::Location(loc))) + } +} + +#[scope] +impl OutlineEntry { + /// A helper function for producing an indented entry layout: Lays out a + /// prefix and the rest of the entry in an indent-aware way. + /// + /// If the parent outline's [`indent`]($outline.indent) is `{auto}`, the + /// inner content of all entries at level `N` is aligned with the prefix of + /// all entries at with level `N + 1`, leaving at least `gap` space between + /// the prefix and inner parts. Furthermore, the `inner` contents of all + /// entries at the same level are aligned. + /// + /// If the outline's indent is a fixed value or a function, the prefixes are + /// indented, but the inner contents are simply inset from the prefix by the + /// specified `gap`, rather than aligning outline-wide. + #[func(contextual)] + pub fn indented( + &self, + engine: &mut Engine, + context: Tracked, + span: Span, + /// The `prefix` is aligned with the `inner` content of entries that + /// have level one less. + /// + /// In the default show rule, this is just to `it.prefix()`, but it can + /// be freely customized. + prefix: Option, + /// The formatted inner content of the entry. + /// + /// In the default show rule, this is just to `it.inner()`, but it can + /// be freely customized. + inner: Content, + /// The gap between the prefix and the inner content. + #[named] + #[default(Em::new(0.5).into())] + gap: Length, + ) -> SourceResult { + let styles = context.styles().at(span)?; + let outline = Self::parent_in(styles) + .ok_or("must be called within the context of an outline") + .at(span)?; + let outline_loc = outline.location().unwrap(); + + let prefix_width = prefix + .as_ref() + .map(|prefix| measure_prefix(engine, prefix, outline_loc, styles)) + .transpose()?; + let prefix_inset = prefix_width.map(|w| w + gap.resolve(styles)); + + let indent = outline.indent(styles); + let (base_indent, hanging_indent) = match &indent { + Smart::Auto => compute_auto_indents( + engine.introspector, + outline_loc, + styles, + self.level, + prefix_inset, + ), + Smart::Custom(amount) => { + let base = amount.resolve(engine, context, self.level, span)?; + (base, prefix_inset) } }; + let body = if let ( + Some(prefix), + Some(prefix_width), + Some(prefix_inset), + Some(hanging_indent), + ) = (prefix, prefix_width, prefix_inset, hanging_indent) + { + // Save information about our prefix that other outline entries + // can query for (within `compute_auto_indent`) to align + // themselves). + let mut seq = Vec::with_capacity(5); + if indent.is_auto() { + seq.push(PrefixInfo::new(outline_loc, self.level, prefix_inset).pack()); + } + + // Dedent the prefix by the amount of hanging indent and then skip + // ahead so that the inner contents are aligned. + seq.extend([ + HElem::new((-hanging_indent).into()).pack(), + prefix, + HElem::new((hanging_indent - prefix_width).into()).pack(), + inner, + ]); + Content::sequence(seq) + } else { + inner + }; + + let inset = Sides::default().with( + TextElem::dir_in(styles).start(), + Some(base_indent + Rel::from(hanging_indent.unwrap_or_default())), + ); + + Ok(BlockElem::new() + .with_inset(inset) + .with_body(Some(BlockBody::Content(body))) + .pack() + .spanned(span)) + } + + /// Formats the element's numbering (if any). + /// + /// This also appends the element's supplement in case of figures or + /// equations. For instance, it would output `1.1` for a heading, but + /// `Figure 1` for a figure, as is usual for outlines. + #[func(contextual)] + pub fn prefix( + &self, + engine: &mut Engine, + context: Tracked, + span: Span, + ) -> SourceResult> { + let outlinable = self.outlinable().at(span)?; + let Some(numbering) = outlinable.numbering() else { return Ok(None) }; + let loc = self.element_location().at(span)?; + let styles = context.styles().at(span)?; + let numbers = + outlinable.counter().display_at_loc(engine, loc, styles, numbering)?; + Ok(Some(outlinable.prefix(numbers))) + } + + /// Creates the default inner content of the entry. + /// + /// This includes the body, the fill, and page number. + #[func(contextual)] + pub fn inner( + &self, + engine: &mut Engine, + context: Tracked, + span: Span, + ) -> SourceResult { + let styles = context.styles().at(span)?; + + let mut seq = vec![]; + // Isolate the entry body in RTL because the page number is typically // LTR. I'm not sure whether LTR should conceptually also be isolated, // but in any case we don't do it for now because the text shaping @@ -511,32 +592,174 @@ impl Show for Packed { seq.push(TextElem::packed("\u{202B}")); } - seq.push(self.body.clone().linked(Destination::Location(location))); + seq.push(self.body().at(span)?); if rtl { // "Pop Directional Formatting" seq.push(TextElem::packed("\u{202C}")); } - // Add filler symbols between the section name and page number. - if let Some(filler) = &self.fill { + // Add the filler between the section name and page number. + if let Some(filler) = self.fill(styles) { seq.push(SpaceElem::shared().clone()); seq.push( BoxElem::new() .with_body(Some(filler.clone())) .with_width(Fr::one().into()) .pack() - .spanned(self.span()), + .spanned(span), ); seq.push(SpaceElem::shared().clone()); } else { - seq.push(HElem::new(Fr::one().into()).pack().spanned(self.span())); + seq.push(HElem::new(Fr::one().into()).pack().spanned(span)); } - // Add the page number. - let page = self.page.clone().linked(Destination::Location(location)); - seq.push(page); + // Add the page number. The word joiner in front ensures that the page + // number doesn't stand alone in its line. + seq.push(TextElem::packed("\u{2060}")); + seq.push(self.page(engine, context, span)?); Ok(Content::sequence(seq)) } + + /// The content which is displayed in place of the referred element at its + /// entry in the outline. For a heading, this is its + /// [`body`]($heading.body), for a figure a caption, and for equations it is + /// empty. + #[func] + pub fn body(&self) -> StrResult { + Ok(self.outlinable()?.body()) + } + + /// The page number of this entry's element, formatted with the numbering + /// set for the referenced page. + #[func(contextual)] + pub fn page( + &self, + engine: &mut Engine, + context: Tracked, + span: Span, + ) -> SourceResult { + let loc = self.element_location().at(span)?; + let styles = context.styles().at(span)?; + let numbering = engine + .introspector + .page_numbering(loc) + .cloned() + .unwrap_or_else(|| NumberingPattern::from_str("1").unwrap().into()); + Counter::new(CounterKey::Page).display_at_loc(engine, loc, styles, &numbering) + } +} + +impl OutlineEntry { + fn outlinable(&self) -> StrResult<&dyn Outlinable> { + self.element + .with::() + .ok_or_else(|| error!("cannot outline {}", self.element.func().name())) + } + + fn element_location(&self) -> HintedStrResult { + let elem = &self.element; + elem.location().ok_or_else(|| { + if elem.can::() && elem.can::() { + error!( + "{} must have a location", elem.func().name(); + hint: "try using a show rule to customize the outline.entry instead", + ) + } else { + error!("cannot outline {}", elem.func().name()) + } + }) + } +} + +cast! { + OutlineEntry, + v: Content => v.unpack::().map_err(|_| "expected outline entry")? +} + +/// Measures the width of a prefix. +fn measure_prefix( + engine: &mut Engine, + prefix: &Content, + loc: Location, + styles: StyleChain, +) -> SourceResult { + let pod = Region::new(Axes::splat(Abs::inf()), Axes::splat(false)); + let link = LocatorLink::measure(loc); + Ok((engine.routines.layout_frame)(engine, prefix, Locator::link(&link), styles, pod)? + .width()) +} + +/// Compute the base indent and hanging indent for an auto-indented outline +/// entry of the given level, with the given prefix inset. +fn compute_auto_indents( + introspector: Tracked, + outline_loc: Location, + styles: StyleChain, + level: NonZeroUsize, + prefix_inset: Option, +) -> (Rel, Option) { + let indents = query_prefix_widths(introspector, outline_loc); + + let fallback = Em::new(1.2).resolve(styles); + let get = |i: usize| indents.get(i).copied().flatten().unwrap_or(fallback); + + let last = level.get() - 1; + let base: Abs = (0..last).map(get).sum(); + let hang = prefix_inset.map(|p| p.max(get(last))); + + (base.into(), hang) +} + +/// Determines the maximum prefix inset (prefix width + gap) at each outline +/// level, for the outline with the given `loc`. Levels for which there is no +/// information available yield `None`. +#[comemo::memoize] +fn query_prefix_widths( + introspector: Tracked, + outline_loc: Location, +) -> SmallVec<[Option; 4]> { + let mut widths = SmallVec::<[Option; 4]>::new(); + let elems = introspector.query(&select_where!(PrefixInfo, Key => outline_loc)); + for elem in &elems { + let info = elem.to_packed::().unwrap(); + let level = info.level.get(); + if widths.len() < level { + widths.resize(level, None); + } + widths[level - 1].get_or_insert(info.inset).set_max(info.inset); + } + widths +} + +/// Helper type for introspection-based prefix alignment. +#[elem(Construct, Locatable, Show)] +struct PrefixInfo { + /// The location of the outline this prefix is part of. This is used to + /// scope prefix computations to a specific outline. + #[required] + key: Location, + + /// The level of this prefix's entry. + #[required] + #[internal] + level: NonZeroUsize, + + /// The width of the prefix, including the gap. + #[required] + #[internal] + inset: Abs, +} + +impl Construct for PrefixInfo { + fn construct(_: &mut Engine, args: &mut Args) -> SourceResult { + bail!(args.span, "cannot be constructed manually"); + } +} + +impl Show for Packed { + fn show(&self, _: &mut Engine, _: StyleChain) -> SourceResult { + Ok(Content::empty()) + } } diff --git a/crates/typst-library/src/model/terms.rs b/crates/typst-library/src/model/terms.rs index 1261ea4f4..c91eeb17a 100644 --- a/crates/typst-library/src/model/terms.rs +++ b/crates/typst-library/src/model/terms.rs @@ -1,4 +1,4 @@ -use typst_utils::Numeric; +use typst_utils::{Get, Numeric}; use crate::diag::{bail, SourceResult}; use crate::engine::Engine; @@ -7,7 +7,7 @@ use crate::foundations::{ Styles, TargetElem, }; use crate::html::{tag, HtmlElem}; -use crate::layout::{Dir, Em, HElem, Length, Sides, StackChild, StackElem, VElem}; +use crate::layout::{Em, HElem, Length, Sides, StackChild, StackElem, VElem}; use crate::model::{ListItemLike, ListLike, ParElem}; use crate::text::TextElem; @@ -160,12 +160,7 @@ impl Show for Packed { children.push(StackChild::Block(Content::sequence(seq))); } - let mut padding = Sides::default(); - if TextElem::dir_in(styles) == Dir::LTR { - padding.left = pad.into(); - } else { - padding.right = pad.into(); - } + let padding = Sides::default().with(TextElem::dir_in(styles).start(), pad.into()); let mut realized = StackElem::new(children) .with_spacing(Some(gutter.into())) diff --git a/crates/typst-utils/src/lib.rs b/crates/typst-utils/src/lib.rs index d392e4093..f3fe79d2c 100644 --- a/crates/typst-utils/src/lib.rs +++ b/crates/typst-utils/src/lib.rs @@ -276,6 +276,15 @@ pub trait Get { fn set(&mut self, index: Index, component: Self::Component) { *self.get_mut(index) = component; } + + /// Builder-style method for setting a component. + fn with(mut self, index: Index, component: Self::Component) -> Self + where + Self: Sized, + { + self.set(index, component); + self + } } /// A numeric type. diff --git a/tests/ref/heading-hanging-indent-auto.png b/tests/ref/heading-hanging-indent-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..823feb145eac4422dec40e50ce855ff14cb7346f GIT binary patch literal 849 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 delta 3465 zcmV;44R-R>8jBl{B!5y#L_t(|+U%KENM2bG$FIg1NnJ@Hg)~SbArO*~gcL#uAt8xf zv4H(SM063AMNxcGv9YVGC<=lIR;;*IEQkeEu%L*ds|Ysiy{_&L4qQHhE$&0edj1cG zxpQXj{l4?RGv~})WlQ2Gha#6iQYaxQl#mok3MC|k5|Tm*Nq?cFaDP}^TkGxZU0ht0 ztM>CzSYKcN^5x6-@85@phT7QJ+`W4@Iy!pmpjcX3nwgn7u=~)^kfiPVC@d{4J#yrT zhlhu%si~=f(X9g^KR^HE$&-0`c?WZU{`~o~XU`;U-$CKV#>UmFS6TGsguYdW`BKseR6UVVP$1yY-~)`2L=XeX=xP{6cCH563cJ$GcIb(@f(E9Beb=( z-@JK)v8o&y8JU`zk`(TU#>Pfg?Zt~1I~gP=C*Qnz)6dWE{{8#r=H?3v3n*=EZI2&6 z{_fqokdP4G0PYYR9E`rKtnA^#hfqjPc64+^GdDN);eW#iH#fHj4<0x>J3~xmW#z3~ zw{VG%kN@)J3&M>XHzp<~Fm`fs!uR6EizM@+q9Tkxefq?Gco088Qn)>0V`EuF6BCnd zXIooa$*}IMSXkV-a|apO`;H){HCL$!^Vl`^y$-R2p3p9apJ_KOP5G@!iCUL-N}cAg@ybGFE6jo z&Q7>FbLI?s;m)4Nc>DHkM%-0j>=}i@`Sa&pU4LC68`hP>3Z31jIX>v=>Gk*b_w@7- zF5k?;8F4@|L?#^d_4Nq|vBWz8f>j#&`uYegGHqmJq-wBFUjW~2ZEg1U_Czq@o{^EE z97^mFg=f#6rG7wQdm|+ZWlKv7?>Bu9F}1d~7QLoBzKpyj;*H_v!Wa1Z`to9tPT8v2 zvz0@Ot$iRNA%TR(TMv<@rly=e)B|dEb~f4a>({UBmmfcV9334c-HCGtCmQy=l#~=` z=2Dzinwy)+lfi+zUlzusQ-7f$d!ykj16xm?JVEB^?6u5tV&ZO(A3yHs z=txRR;?W$G*k}nsd7RlBgaY|$+o|E8gGc%J;4fVD7{7X$nQTXcBD++wo zp7P+@wQGt7!otERz0=at;^N|jrn;BZeG8Bt!N-CD+@Eabbm21G5j{s@uBMALkD-@1BZS6A1} z%uKcCD-sK#XrQ~hn*i$S>aw%5Q`emk#GM{Gfyn2ir%#`1y3h@PJlX;(g?~KP+SIp~hz7!MKELYe z=_)@IBcoG&e-H4||I4oZsxA^maRA?H-r&Z?CWx}{AU=Z0EJiViAeemxL8HwkHj7v^ zXc0sZ1kvO>2>ao8VHj8(MSnKPk2&Eo&K&PObN=2r->a2TDwT4-f4$!$4ezhpa=+j8 zNcFdvO$-$Z1y%$sXr1`3m*@naPwdc@MyJ!sO??wlqLG%%<)S$Sv=Lxr6wTRe)&-;P z_j{djp~D^mE*{*Y(a2aXmm^Lx=oVqq#34YiANun};d(xwFPF<=v41FGSV*Urc$zy* zuDSE`iP=z+@jy_!w5T_4kx8|H;oBeKmm=a)oP-dH-McX z8&IlNs};~`%t6l2A%8x~!(MN5zfW?YV0R9~$tXT9cLlUanG_!!{3#N`IfA++VLDCb z=Qk{Et?Tv5Hp$Eq26@;91Sa8&Jl9f%>+yJOEpiIwd_E7+{BB4^GR31?UNTCjafO2B z)lNtPMZYqkIOz3y)ZJ`0lR4E+=peu0p`!mqQEibRi;A>Tnt#b;8jXhRDi9-{PX;0W zvkA}VGhbHob)x08?REdsZ@mcbUHOMyyGBpuahEpY-H?~BSbn*@ELn9<-n;9KkeEm)PI33 z_IEH&8mLyQ9)Iyywcq59p%AZLuZIl;A?5AaY<4^zWqvnhECM(Pr~r9)+jXuVHV5r? zoA#pB75L3&vsf&w^4!j^6J1{}7heu6WNjD78bM62hAVxrlCJz!qOUsG0z2cP4GHrIea5rPPEer6x>G__v+ANsSx^!Z3V= zkh^4&O~^L)$SMS~%r<}PBoN59o2Cys4}2hmO-#4OGd(a>3*+{WB&(!Sx&2m^lnP5q zg(aoJQh#Adsj#F}SW+r16_%6=OHQdmpRBr__2ndOP)@e16!K52Q2ZwFP=wgy<0HOr z;Yzq7*3>6y_|vi)=Hf&A`}?~KM5Ov0KRGLhf}loicz%A~@Au24g#&(idh%%(vkG;b zoP~qj-QA%Dd}l{qEhM;kd3o_^7v+{pd+`Aoz<=SB>~6QysH>J%#qzXTo%vj!6+p4(SuU4x@Z0)>ev0UeXv6?4grID@mZGf3bB z6#z5RAD#nT)3O<1mOxha=OXkM)T61u2*rAe{_M@o4b}Rf52b7$%IC7#Y!rgbySlo9 zQh!c(cBrFI|JVq0a({d**s28TS0|*6RpR43F6g{5CNbEV%jMPiQbV4 zAy>Kp^=rU7i1M2kC43j6h&K2sI~aCGQlca+=})Q1Q+<4Vn24%VOJIfD+uO!Z%mwHM zX@O|CMJ|T^6tWGHifqQiZMWNn$2S6G*nfdU7%pr~pH)W}Lt))+hjB`ia9J5-hl@dg z7{ck;52$f|el8T(0Fpmq1r?eBNchjsPo$`tKt3(70a>eOF;4kumKf1YXj37kW*!>x z(}0zh1m~&8LEpx~{^9QFqJ=P4h5o5u^)F9cR z=zq{7ovSbs6+*bI6Yw=A*OHUjENUJA2;0hly}rH%=DMBnbj11>yB&6DS#+H4W0v(- zn{&W(iBp(sKN+I%MXEb6L!hO>y?>@G@~qkFgnW2}LpUo>q(j&ev|~^%K)h z0Y^|_B23s1iubUZXPwexrZ14(Dgz318SpN-Lr$hbM%9yNEs4L-G94J&Sy0($+7gDs zT^gvJ6QMMVZWN|c*%MT1vJRBShcY12FvZ4?I95b=xEBzcpH?3~^-^Z1xqsy#T^iO{ zH=QF(ha+EKU&)QMdg`EY(IB8LN}3norx}yuj^wPZ8Oi8zf|6QlpcbVy5INa6I7IxN zx3{-}(imIQh~YJ=5@j$@$Rx87C0T0?4!RVMB0?b#&H`OtURs_Q^Zu@Jn)@U?GPMb* zF&NoH1MoMifb((+SR_-BJ%1c1!E1)K$Lo+thT#r1DEoWa8#ZRw{@C}o_M2n*MFdl*Ki;RM0{mBxwVF@zb{U{0JrF^m=N zy(2C&j=52MoWJ@XDSzLI<4$K>FY5G05r#YmZ9R|wFPyc_GGoW7Tx|B}dh7gHdSKpN zt0=E)D&pCyX!w6Jb}x-F9b1N^0WEsx>C+(bFezzr0rS)6U-bxjgFUOix$AH4l2Tzw rsj#F}SSlM9=c$7E*0000vR)Yjh5(b?A6;K9So#>mjFu(-m+%<1ax=jiOw)7#V4-GqjYH8(#yJw-P; zL9(>Gs;sn;lbf}-zi)AQe13+zy~THUe06quVPk8hr>~@@u5@;OxVpk4B`q*AI?d15 z!o$b9yu_WJqEuF1i;b1*?C^7Rc-h+C)YaLFi;vLK+GlBTfrE?4$<3CRn?OQJK|@Qv zz{sz$xp8xQeSe3PmYz;eRmR87#mCQ9SYU2%b-=>Py}!puN>ZGjrr+S^NlR0Kf{0R7 zT!e**g@%eEBrKSkqK%K2gN2Q>wYjRRudlGSg@%kzQCV+rcE!fb_V)I>yuxN@ZO+ft zSzBX9NKmJ#u~=DO-QMJzouzVge0X|-pP{M9%F<(HZBkQNU}0y})!UVpoS>nn%gxo2 zlbKLaSINrIqok@_US{g*>X4F}Yi)ITdVpMAW7*o^kC2w8r>$RMXLxqj+RSJRnpYlprWdXijrn%aGs#3U}9>WpQj)q zDv67eXJ~A;xWIyhjDCNGet?LXnx154ZrR)8g@=!om!Dc(WVgA&Raak8Q(IeIWv#BV zv9h*^iH)(dyCo+tKS4>%&ekX@GS}GL*V*BBd4Zaoq%ku)tF5)XzQ$8kT{bvCb$5Sh zYjZ?KPH1X!Vq|QirL8hFJlfpk%FNW<-sWXzZ-$7FD=jrlPF6)nPrt#*IXgp-k(r8& zl#-O3qNJ?J%hTK4<*cr@!^O?S#?E?tgqfS8$H~#HueZ+7*txsIYHW0=tF!L!^WER) zH<-kf0009)Nkl?woU&$z(DeS|EoAZC4A? zFvCHY^_I+&h*-R&nJ8$kYwfxYyNJkKx{PQDbcXG@FP#kH?zJHiSH{?I8bEtD3PH}8j0?DYpw-@KrfQzoD{y$tBt+O}BdiUi9~n@Tp7{{n%X zAjY}cAvU~BuYL z;UXskwAst?YsmnmxE57a+WpM?EVafB)Ku_*&SrN>mUFrBx^G!4J7PYbh{KS)8BejGNi@}zicjNs&MvQFB@B|Ii{}byVx)J5N zo|oT?b-=7gziyA|#k!+zEC<350V8#epMGH8GFuGQx9WG^0sh7Y@6WA1eoRZpknJ7D z>Zit}(C8`JOnIX{r_9kGLqZ1Y(@EA|Xw2P0y@Tutxj6^5e%1_95}%!km7|=v#$yE% z6JU1>v_n-j*eq}r;ZH39>$UL6?#My7`r@wZs#~|*eADDdAA9Q6xv#%A={R-I-FMxp zl)B-1rOrM_sYyz``<_zw-lx>H*QrY{QR<8{m74phQcpatE;wJQ2Om;u+GM5FdDl!k g#=IVzOr}H2pRrwA;|jH}NB{r;07*qoM6N<$f~cxzk^lez literal 0 HcmV?d00001 diff --git a/tests/ref/issue-4476-outline-rtl-title-ending-in-ltr-text.png b/tests/ref/issue-4476-outline-rtl-title-ending-in-ltr-text.png new file mode 100644 index 0000000000000000000000000000000000000000..c7c359a1b990069b38118603790d635046de9fee GIT binary patch literal 3341 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ⅈL;bFt8&b1d-{@o7R?=mZ~aNZtg@E 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 JR|hc-`5%sQ_ox5> diff --git a/tests/ref/issue-4859-outline-entry-show-set.png b/tests/ref/issue-4859-outline-entry-show-set.png new file mode 100644 index 0000000000000000000000000000000000000000..33ff442d95767d3c5b26e0c038b8b41f728cb06c GIT binary patch literal 749 zcmVh9?2?dRz1X=`&TEHr6qaEy(Uhlq}kkd~>dv)bF? zl$D#8n4Yt=x^#AaF*7^6y~TcigMEI2!o$aljg>1cHNC&b&(PLvZFAJs*@}ygsH(C_ zOH)@^UOGHP%+A(+e}!&ubANz@qou7~UuW9f|r^P4i^Bv0Hm|Xrhx(vC>1D8Xmx;2TmCAPqClR-67B8lpP%cYl8?y6@X#O;~=5=)5tynch(>;3)x=H}+Pxw-iG_~_{9z{1MY)6=rDvMTo0^)M zIyyQnEiGAFV?jYd;NalS&dzprcAlP|-QC}Ugp8q~p@oN!tE;PheSQ1;`>n05uCA`G zuCP#0Qha`fe}RdCfq^M0DZRbDb8~aFw6r!hHsa#qx3{-BIXUU+=~-D>jg5`!>g+#1 zLBhhqSXfw-lat%q+rq@m;o;%U&CL!D4&2<_$;r#h%gwH^xNU81d3kxv&em;jcdxOz zQdC@ohK|(K)UdL;WM*#8(Acf7x3#yws;snTXmGy3$Y*JBXlim^U}%nzn3~cpp;}yIqNJ>Se}_m&O2ELvu&}a`lbgA_!+3gvUS437mY&GU(#*`v z8X6iQBP+49yVlm$K0ZEygNtctY4P##xVX5%!NFHoSG>N)DJwIeprE3nqH1btnw+Fg zP*_S#RGy%yOG`_%w!X^B%+S!%I66X5Qd*CZnYg;b!^O?m+Tz;W!2ng-%?J_bl>gwwJ{QTwRHAC3-YwThxuP(g8md+)vXmWq4ty>Kh;y%&fI zZ2`fe;#N?ER~{|*rrSu3n- zvzj7&DBHSj_0sT%?FWUkz$tpG7XBC_EDngXIp^jHB^=!bPi+ma-_R!sSFNAB)%5Ja zhxZasE7-D`_^xpM8bhbDeJ93IqZyI$mz11@p-!4oFX1b_cR$WTFyvFG&&VZn=S-Ri z7}~;ji4KuOwa54a?$pq&JKlFtUCGvMc%tEU1o6|@u?t4(m^q`NG+7^zsCsTPnR*c% zNxMY4=-F~76tY~dvQ^i!_(WDMY*_f;-n+YVWEWck0_tBbQg@XW;1>Qb&}^FsdI8b!sjf!a^WIDF{H*kiiHOc0k;c&fnJABuT10I z_`g9E#7ZPoLZotTd5~h2*NHI=C0D%!9=%@g)h=lb4UI@~07*qo IM6N<$f|jtSP)+9{Zw7jvi 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 eO0*LF_QXH+?ZR+&DOFGa0000B|D zB#a^@3>Xa-qD(#pk+NW-7*G_2qcLa-esT(A zD|olt?e%&(osLiTRd6i0quMjht%<*_Em&=Jn z0JRXnXaERU3>osaNo6TS_@Or&An{76m zefWhX5C~8xl%KO-tyZa2DpI@IY|`oUdcA%=pZR>gR4VQF`%0x!AP}Go-eGw74W^gc*99A+|^&%nj zf>D5o9v6$nAOOm6iVlb4bUJ-_bjam$glsOCBb3Qxg5M*WcemSN{1M_b8jZzb{TviL zaSX&0#ebK}MWIljNs&234MB({*c0UY`!BoZ^O8Um#PM@zkc8UJLr_`x4=CQfDPFxq zU___>1CcIax2|666bc?hq)s7qQ7rrgS|rgb!fqi81{u|d9>}ul$-3Bk$TH5(e&4*= z+3|hH9Wpz~o=hgWRrBBL$Ye5hyPb^(&p4@?NPi^6Uc&8mQ;R7JE|-gxr0m*kHm}#q zZ3u-zB(f+4)DWM~mrA859S(=X>2!v};aDs-7z`qj2#H)OmD1@nLNppBbID?h#S)Ll z3AD%K;YWgFp-}i2`)Go~mMfRbsj6z+hY!7pa_xtJCLD=Mf+2bP^48qQS;dKM3M1P~vpkoIakzxI-_d0sL9&L?4AV515W;oK5 z;Nl2rq=SKARKlL=j?xS_M0Y!X;d2JO%7D z5S%e7aTvG9LB!w^*zBx!A{3P_nVv!J&>58I2vfV@Wt`>|tE$)Q0t9N#Jwr)fX#~=0wOFJ8;fRa| z5SjsiV2P5YLe@J!1A(ss1Ov=4o(KXsQ!tSLVQL(}4V=Lx97BndfZ#A7IL{JThydZp zShOzOw;EfUYhR!5@&%gjcFx|lsedpE?5xY6miU@UZ5(lYY z;Kw3Z!m?MF7-K-%k8;` z_n!Qk+rCeqL$r?;XoWx@QqZ;9XZ~rtyZd!-kG~dw#LE{jfsB2H0{wDh`+v;Y3*LvF zlc!Fjft3FB*+nk^u~ko12>`rEE4^sZ<(`20k~+ zn@b3-L?VI2Di({_tcZBN<$sqHmr#!w-bgHz6(cw(G?KO;PYlluGK||{x1;Xt($>}% z`pxq^tXrNfrVr?ZOQ`2$GKspQ!(1+hCZ-=-iYE`}9*M}@6GKwnZr3%8^0tPX&1Nc< z>TQ_EpN4s*G|WwV8%9P38+M4Wo^9|-%24}gfmR5#Kr2F;vrkvo*MDAY+`e;fIld|t z9yDja|7d&fKZZ4D*VYs9Cu?TWF0VXC(F?Bcjd=fIdX{5j&QXKdYX~!jZY{}?bLz&cMkYRG!-xc_>NR)0^o!Fpa--+H`9U%f+Q&T?4LCypPzd1I+o-NB{hJQ6uV(tKs! z>HLctSxkl__alSG#s9XRXxHeIp`Ko8$klUBhJ5&XGt2*7k7T#{cDrp3J>Al?tLL?l zF^ioVU%mCyTkp)-X5(AzSXAb$_R#{Z5a`1T`d!vby?XODoqzrL>o=pM5-h%8ju|ZW z6$+HGn7ptGXTv@t>GSt{^P#HdWv~ub4wXn(%XLfXSbZl&Fad8owgFTR>hcBk5 zr`h}s^Hahw!trcG))$dTWM5?iciHZo9sAVOl*sm_6!slmtyWP%rBVqebYWq^<;}Rn zkmZ99>h-$wK!3R<&L&E%P$+nwht_hQDb8jllQAck)ev275e!*uSr$S5x<$<1Wf6YB zy^COymdj<_)xL{h%l0l}mTNwr?_H$R>DVF+D00000NkvXXu0mjfZ@mP7 diff --git a/tests/ref/issue-785-cite-locate.png b/tests/ref/issue-785-cite-locate.png index 5240aa772cce985eaa73e85b8f9c9c30c856792e..d387ed0d58686504f8956e8f8df20793558fee8a 100644 GIT binary patch literal 9441 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 F@*hG5mlps4 diff --git a/tests/ref/outline-bookmark.png b/tests/ref/outline-bookmark.png index 66e5329d88516a4cb6c8c2229682b8119df0bfcf..83c74444ae86a35f8d23115e43d9e784bb73b456 100644 GIT binary patch delta 441 zcmV;q0Y?6Y2-*XX7gQSv0{{R3fZDqh0002zP)t-s|NsBp-{1ymfbf!NbeByTjk#-`{7+NB{r;u1Q2eRCwC$ z)HMOx>6h(?W+l!bE#X>9^F?9T# zFObUb0}&~gfGE(!*XVYIOzVJG9In)X1JLT@V>mcLDz`@*t|oc7-2CWXY)8oC8i~WHG~H?|YN6bGHl<5#L*;Qe#}guy$+Ba! j67%KQ?COsyit?v7W=as7=W>hw00000NkvXXu0mjfbC%;1 delta 1021 zcmV+9=kYHDh0Z?CYl$H~!hbbQUv*KKciWM*!%w7jUQvVMSw zn3|$@d4V=KKsPrx0s;aO5)$t2?tFZFGBPscP=W?EcisjIVgcz}zIm4t?lfP#v7d3m0mo|u@JWMpJ# zXJ^RB$i&3Ny1Kgb^z`uX@M&pjXK8VRg^jhhzueyDPf=NEYjbLBbgi$qtgg1k$k4sN z$15#0qNJ?m=YQ?<^Y+5S$8K+PZg6;%mY$E1ndFMz_6`mX6ciM2aB!WSoyy9}(9qDNq@;Lwcsx8j zhK7bOFE1P%92y)X*xKTooSgtk`lD@va z#>U2(nVD>CY!43)UteFEnwq7hrTY5%&(F`Yvaa&x8-r*)8Z5kljZu)%5h2kiX#`O$e18K4K^vLI7m!2;W(Ce92SO&@*#`pq z_X3NxVSnF86h%=c8o++?Q6QxkE)@qfs6_8}X_gF)==3R(Dv>(z{3C^*43cnxjGb}2 zdt(a>8Uonr+jX)v+wv;G8vrN^z{rGDB4ww=+2o$Pt%00^x3szD`&2iMf!p8M+a_BV z{eOX!NS)K=&(d)VCO_%rxLf{3cFsy8uF}oudEni9@^=B4iE}iHq9}?Im&O2IH3(13 za$S_Lhkb=56ZVb32R+qouJ=mCx=czx)&*~TRSy_fp#~Mr(NQbUH9Z-&aczDcCNN-4 z(cyn;Iq-R_{}mQpZ<>zEce9VMjb{*xgmy{XlMWuP+zK1)F2O1uuGuF^c29cqj6nE(OR+qPgQs?2H9J<00000NkvXXu0mjfeBuqD diff --git a/tests/ref/outline-entry-complex.png b/tests/ref/outline-entry-complex.png index d0491179b803f8ada1894fea31a233c02ae19af4..d2ad49e79963ab19427e29312089345e4727bbcc 100644 GIT binary patch literal 8461 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 Yc)SGlL+9VOZw>$%Nd<`-h(X~006Aa`Hvj+t literal 14460 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 WT8wU--@m^K!DJ*9#p^|lL;gRfvkSEV diff --git a/tests/ref/outline-entry-inner.png b/tests/ref/outline-entry-inner.png new file mode 100644 index 0000000000000000000000000000000000000000..5376c9961453ad7c1f3acf1fb40e93a606fae0a8 GIT binary patch literal 462 zcmV;<0WtoGP)vq&_AXr!W1 zt5&!$0+d=mA#Afy!76i$X#A!_>QY)O6~GW<`%YaJ`|#}K%9qIwvONVGxRT+L2L zqRHNxfxwOV9KsE2!#x%NT~*a=mgsn*VVu)Kngn3bm`zm6BsU1sq(xLaM(%M*GX-*v zFnxwbb2X1d6EL_5*e)&~C0?lXsYG0*XL1HFjpm8FY)~B@YG%kDuIM#(X~rZT=+yXr zu2#5G4-9QX+y?fmhc~*H)(;?Vde5{x5;82qGW@5*U*6A7eiyuS@c;k-07*qoM6N<$ EfkPy|dRtBHO-RJ4Ol$onC8g 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 Kt{P|=_WuAvVO=`_ literal 10099 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 diff --git a/tests/ref/outline-first-line-indent.png b/tests/ref/outline-first-line-indent.png index e40b440949a8bc1ab590393a19c186bc0d793152..e3341295cdf508f9425b4553211321fcd4aa2125 100644 GIT binary patch literal 5539 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 literal 10837 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 diff --git a/tests/ref/outline-heading-start-of-page.png b/tests/ref/outline-heading-start-of-page.png new file mode 100644 index 0000000000000000000000000000000000000000..e6dbbb5f1ddaf02145241e91eb2e01dab11af21c GIT binary patch literal 6935 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 P00000NkvXXu0mjf-RwE) literal 0 HcmV?d00001 diff --git a/tests/ref/outline-indent-auto-mixed-prefix.png b/tests/ref/outline-indent-auto-mixed-prefix.png new file mode 100644 index 0000000000000000000000000000000000000000..097e0bf88f1858e0d927b48233d7f39ede2ce5a8 GIT binary patch literal 5712 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 literal 0 HcmV?d00001 diff --git a/tests/ref/outline-indent-auto-no-prefix.png b/tests/ref/outline-indent-auto-no-prefix.png new file mode 100644 index 0000000000000000000000000000000000000000..e746b35b62c7603710b7ee3025693e3c7eef0bd9 GIT binary patch literal 3101 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 literal 0 HcmV?d00001 diff --git a/tests/ref/outline-indent-auto.png b/tests/ref/outline-indent-auto.png new file mode 100644 index 0000000000000000000000000000000000000000..53517abd8352ac231a80fb3885def697d86ae548 GIT binary patch literal 5176 zcmV-86vyj{P)c_OWIg%tJQ9{X=^u^s#Ubs7PN{2A|iqUB8n_!5d{HJWM4&gWM5?m z+4p@%L|eDC{ZW(lBqzC<5P@f=nL+!#`G%bN&b@c$y~E7A_cQmt7ygm*jF%VW6o`dV z#6l@zp;#zIER-S^N)ZdiLMhL&g+U<^uf4JCVp#0x_-!p=w%hVrZYhL>{!w1hP=BKX zLN5!^{?*r)YJAD2mY#hUwg@@<`bT_X`rFG^rDqoW2Nu4yWQE38_3{qr8<=>1)n`K^ z)8c{tVQq6XBdgGG77h;I+_7^{N?Pvv@3+OorHBE~o`s>8V!|U6i%V;wW3QTQHxmOE zi-q_~eDS5%&`V=;_w~vfbG_Ke*bD|T>fw7UK56e9R1Y(=iw1_KsPQqS=;<5F%`c~} zt#7NTYo*RBxZd46sw%6GI66^RTwLd=@gLLHF+h#W#_;GZ>eTc+iq7ug!s06GimJvN zOnapEWj2NXpRH!swU;ODmiBgyfRaio~Rp2M_;#V#LHI z+8%aj@92TP(bx*@>E#Q}@bL5*8J&c<|KKls2PY;wyZX+a3!=`xmYcNvZ=W}^kO)5 z^40XhqB3e9-?IaQqtr+29VzFouZa4Le_&7VAT|5M zX+#e=9GMr&)Lx2MC`BxkA{L5;Ql4Q8HBLekuVjAo$r?9zKV8^{nV*)nn7aMC*Lv$V z)APaMF0NjfP|Bnp!MQjB!VnfB-g)mM&a%}sS$o^d5eZh-_7M0dIDW!Y%p>MrvUDYQ zh2bn*vGP+zRX`j}cUcgHXbCVmSlH1uWWN6pV2b$1IB?Jb0LTayGS+P{0W;HX;dkq{ z`1l2F+`I!{r(&LBq{g&x^Ol_;pHKBEgaG8kFU+8q;-3*L#P5^9yEyxm)lK{q0*k{` zEk9o5~eM76MnfbYZ3;6|Q0fC|Ow;ddsush({RhV< zW*~a|Mh@FKGMSl`fALZjwbyU{6_xeWd-hsQ-TWP*vunWK;kY`w%i*!q?jF9?HI3A} zf3>(Za}T1uqwkobE0b4}GoqpssZXBr!l|G(+qI9Pxuxs4%W3L_#MHR>tJE$h+#8!Z zAQ*W6I49^9Z(inwGPRc?7D^EdrHF-Mp%mj515GN{Z`k7Pb53P2zQ?$q<9m%gpeBaw zd(97UJ|HnPJlWSj3SpqB{nB?nz^s;<(_vjPe_#S@Yv-({!$%xW2%6z)?zD`2qhW5q zAwY_&sX6vXT^DS-`m=94CD!GN*8SV@+)tOVT%`Yuln%w z1=}uve>J{8#WN#Yxa{2z@db#F9adZ8A$C@P2s2Nf3%om5TR;DhAGZEX4dTp&+YBOO zh62;T!RopTfrqMsBHC<7R*q1;;i;$UjiK8cR(8+R8x9i(tF8!7>`g&)uz1jU)f@S~ z3jBJSoN~=@nEUH*HvHy&wz8@LWEO09)8_4dXU-=kr6FHXSboCQqqwAUo*qDZ9i2{s zjE7y0Av;z?8xR>{V)8afI+MA1B_5uB)NZG}LBpv{w*5><-O}29z}k+<@Q64BHIjG= z0@YAi!E|&&jc(C7HC_%cN{WrQ!DMty(xtFyY7lmU>FHZ{w`~21Nw9d=lb+N#Az9f4 z)IaVp8ymkxfDZD`WNchA$Ue30;bUat3UhBY*@>iJZkgIk5eub=g;K;qu~5qY1#|ym zx)-wum5Gc>;24^N=C=0U^o-oO*3Mv+3P$Z%9pmF0fML1-ZpP%)o#Bxw!(nbLJ?3I8 zhVIHUPMSSS`gm*vr;M_Q^qe*9REKDD+oCg#>ZIH|zc8l;;; zYG$y76QZQFiaSQJ21j?M!EKeZLhbj&223aCQ`im4Zjp>nNYSl>JXW$m%oAYrUwyrv zJ43ZZYTC6WZ!f3T9+p-~h zfxp2QB5}(Nh+|G}tk0X{;9d;e+l?C-&((wLDet0^Y6xK7u<-b~s-Y`%NX@_Ot9MF4(Nk>V`%RXJp=|_hWMAgdwYp0 zioyW?&y?0n7l@*;F>AaOT_C7T3(M>wN+e26Lb1z~l#@PK7ExqTL_JiG{dfN0gTq1Q zVIBk-IIth~%$$Aw)>?a5YwhohUcY_m%9t>SOZ0)z5S;H~0_8;VV?Ff;)AMBL@qAE&A^h?4ubD^q-mJbSD?WzqRwu+Ucj`%4q{QcU3hf0D-8wdX+l9SU-xU{GnUtiM=V zRVg5ZfuKs`<;v6N%Xv6RXMaI>b@UbuuALZ?Uy3l8QX=%#%CBHH&+?$Vy7n21?k+4Y zaTj;*JxFwb2gTRTw@~5wCp2!1aH{px1_}sKEofz##7kR4aE*30g!IPVsYDM{j`t3h zNRQ(>Z@{Y(tJU#a_Dd^sl6hg z&l*jmQ?FOh$QB`(#?=K{y3?VY^^629e_o#*Dl!-m3K!K2;Y=JN~b8>1np__a^ zcJoe5aSZI`;Tu^IoScPsC#N0QQ}^e>OAc2vCn%i+p%VgN_Juu>mT!>{XBLq1`3obf zpE_EYYg%^Dza9Z(2a>m+uucfu98@jY=OAQ{!eZ{ULq|l7l#}(dVkR?>7LOe5!%gD^ z8ai{4A&uIlfLU{GjgAdR_=VcpVq!6JZGr+32!|Y0L}S7bpQ2A~v2Kwz^zE#@IY(mX zC4m6Bxt;1i=PdM%GeY!+7Q(VVa2}AFGo;3%%G(BE6|~!_QbAZjSV34pSd|LGs#FkG z5LOUwws&tKT2)a1$Dc!b$xQ9$?IrUuh@zLm$3hHCf=GJoF?txf5Q!mSMK76@Bq83? zfr5GnGH<0xqow8jk~)))*PQ!|2}(a$u=p6qnUDE~&lzTKHpBYn?6c24d!2pG-v7P! z+LhcDaSbK_hSl@Z;6PDftuY|G;c4)30Hr<`HT->M?z8p}8;>e9ls4oKrkc=6lS8yBey)U1T^ES4&Enz|Z`NmGAHvEgGbQ-L8_W3}ov!7lCgz5aNk?HI*b_iOuK5I)4D?cE_(&j4+9LN; zA@qgLKyDU(Aah8{s;@TKn?VAUocgH^!bX=6G7dbjq|ssuJm#Xg1qwsP(-1kq8=4g) z7O^9Uk3aFWIRrZ3C?|X`^F#Igf|ud9L9ja_DEX#GzfCoIT}s63NgtS^0XPVRdMJ*`_oVH_G6G9j_Z@kTWj!unPA#YA^;QOXb_bD}3OrU#B5DNEd)o3(Cn4YrJdrst;GcD+O zK2@4~uHw_sJxP^c1do(^@f9Cm=1*x*l$J|3Zrr$e^X8DIM}2*LDPOyGt@_L5RfLeQ zU%#Gm9<4?$7Hq``v4o<+5{e2-C@L%}yfv)f(D>={&o^%RX3g5K3HD(ha9{iHzW>3| z<)3{aMw${wFxI3(qnU}59x^mx1vF{$wA=X<#XF|Yd=yoZj7d)+~9LUi%=GWKC$fNT6@fGJh6hhs*s($2L}@=3K&6;7xiw1kg>U#Qv0Jzg}H!%Fr*4& zqKnaOQNW0(a0IqvHn(}#go%(YE!~@Ei2E6X=?G3r7r^nCgGwJH;N(>ETXUReE!B0$CO6e1Y z%cnBuDl<`LB@fxXBx=uF$SP8$D$_;F(7w=_5{e2-C@L(WsBk>1uu2a5)0Q3U)^FO> z`0bCIw-G8y_u(Ta20ypCrFHGPjd;4~+%wJR3fJxz>tX(61orUsM~saKQy-Yc=r#{o z%#M-|e!6kef)`(52*eo4$gd3Q!`{wl7$ms^UV-@_$O(-!${TWNym5E#OIGwJLd`EM zTm-P)VHIjvupHzuqzZuyr~;uV${T`_*1r|F8kSdQVA{8Ec2U^2@dCvU5!#GM;wU;CpyOPv>pWd@h}F z<4NspKb^ffd_4LAz&Cd`1d-1#YcoP-Y@V2#x0=`uH~0GBMo4aueJv^kTmP#jo<7}t z=+KeFhmW2*b%t={$g$4O?lWgvE?l^D@ZjO&$4_3p+J5$I>wxEWbaWj!a7Z$V{mfW- zN=wVxwziItPn`HW)5tl5o}NB$fRL|Txq9y0`H-8N|B?S7Cw6!DDs#w}E?qf){$j`q z?-nW(_mjK2dZYugy-K?J!vK0Jcv7|z1lD&4hMA{(xf z!-<7)XBa`{KZoH*JKfaQ$H%8Zq2cuy^9sy7E}W~ToqxFMNySh`H5qboA*&osdnT;0 zj>m=fZGwm-7^*X0ldY@76GKiH?+M)FkSUaUst}QQZr(z4W^AjF4-iJ_`I8-A933)R z>K=|L0*<5#vHv(EAI*^;ThND_5k6`W6KmwvT96mWhO1eL1GunuwCr6W>kQb&ybAf; zWgtpOBT}#2YG@y0PR5<`Pfh%gvGZ5sX!u+2ywA%A^=KS}xGq!U5|d?U$s7}G6=BN(-6h#- zQm*L9@K3!PA3xtbs|gsY`_N9gf2Jixw95=!R!}>@?I>_he*~IN2RH1pLuPD{Dwj<8 z4$RcFT=$^5iLp;^^YVOIEL5W9NZ+^X9vp zqXr==K8oSoJ$rtaQW*k&Z{EDcU--U~?1S$igV8xwabl*)aw6vPPbPls*oh?X?k?p0 z`~M0epNAAi8Jt^&_WeUsQ&U4jL-?Ipx^!uwGh;HWT)A@9s#T4RjkH))SVB=@2}OlP mg(VafmQYk!LQ&zk4*vtyJal;x*#R2>0000@FlWRl4wlT4bK%#7_!r&U|6wbrV2sdcaWZms*iEA9ejg0jumbu zggpm3cJ2xGC>t_t?B*>A?}+GaJCa9^o)oib`@jBOZ%o?R3JKldECE^4!@ME`d0QCRq@frEx^h>iu% zofmjE`y9a7umAbYcj|N>-)VP#&F5`&%w`I2ij4136qc<-n2E5s|_% z8{>8*Bnbxvho+@x2~YK#apmd_;n8Ep3;c59&J=Gy;moY;g@HlBNy#beBBO;Pqhb=1 z_6t)WBlE1Vw~s%EJ5+e}+D%R*%&BRBaKi3nu0=RvP1OFB!+^pJ96XddVx$)}aHV!0 zZ5!tXQ@FMB3TV@U>I@=M+P9i7ci|VrZeA_X&d>B&rLT;d!*dpXt4zIJ3-61<}Sz>!j#KCki(K*kRv5|xp47+VU~3~;DWST~F^rV>5!P$m5Kmaq~& zHI;CbsRU5C5@Wsk4B-ist3=v5e6)Q>;^HNt!plNeZI0U^?Cmo>_1G!l ze*K4Dxq1t5?fRWQeFtmj$+XjxCi@9*-L`v4P?#{Mh}*JLm{!p|hf1zqyG=W_lTWz> z;rOiyv`rYWC4QH%t`Q(hNuv9m1L`3u+77`Hks≪BIk|3#CngLkaB*0~+Kpu=QfbrX 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 literal 0 HcmV?d00001 diff --git a/tests/ref/outline-spacing.png b/tests/ref/outline-spacing.png new file mode 100644 index 0000000000000000000000000000000000000000..897a5f74609d16efe885a14d491024be77afc562 GIT binary patch literal 2553 zcmVg((OKI>WU`qpnf>v$!#l=N`fB)d%;F_A6#Kc4w7ni1{rgu+yb8~Zc zcJ}V!ySuv|6ZH7_xR#byc6PR6nV+AB`}^h_92_(>G#nThc;9dzA0KaT?+*z2>FLSF z#s)OEx3{YHy1F{m$L;Oy`}=!U%j4tY$;k=g?(XjJ@KCXrmzQg3XbcSv5!Z?l&;Mm4 zhA8pNZxEU(G&MB?0s?SWjQjihr>CcC4|-{7iM9Fq`hLx!tEI!30Qj)&Deqdl=b#*oS#2c!rs<2N?Ot`zd1DY(9l9Gbu;^HDSG&CzK%gxO#EiDav zGcz-ej*bjzZEcN=j6~Sk*&QDrK@sJ3Aw4 zYiqIh_xGdI)6>zFm6hm{k`i=JPmeepVw1$!v9U28+uPgE&(9kh8`T^1$jAuD92^{8 z?X9S&V5yy*og&HT=;)Z5nm#{2i!)9>6>gw3Ffb6hsHjK*%^v9K={Y$$<>uxlCntx5 zgb>cy^YioZnVg&yCk9<#UoZU8K|w)E!Z9~D*Vfi9C@5eL)EhKsmLveRjg5^jdkH$a z8X6kJBg@v+)rI&QpbHBNfi*QXgJl~A0+6ourTI|kB?XTTSrGn z2P>i0UtV4c%gV}1Mn=ZV%gg%uIswJXMSLkqhU$d&@bD1+R#sL7y9m0nvNF|FU}0gw z-t_hLv7_XTg@py|nVFgR3=a>Zo12@_9362lWID3EvLADEa~vQ)KR@#LN4Q6~wY71; zO-xLvaxpP6)Gp-`0wZ#9R8$m*!^6W54h{%3QMEV7@-Ov++v$}9z-x3~A>{AI|= zrMSJ?wYRrNuh1fyvJ(U#IfSr9(=du&wCaV7ld-e2qa;~|Fpx+5>Eb4b<{P_mpTjOR zhiq$Wi!S-U4%sAV30i`dO@fx7Ws{&KXbD<230i`d?OQ-^{j<;Kx4sd+-~Md;_3tl1 zzi$4$hyJNP^S>|u@#h-i^MCD~`A<|=6vzLPrfKb#3YIh$5vZx6O$wGOn}}GJqJ&-c z9mF6E+YAiru*t9vh=72=u!ur!EhDn8A_I+sinu`=)8G0{UNV`C&c+OompL~lFXz3y z%gcP;&3*TL@3|L!KtFmci%-1z>1QSypI0mpy107Q*0&fHReqjZH-VSJd-_TCsz`DhE=N49#o^*d?63v2^gT!()(Epu{e4vyTOufK|mPli2v{t~ARqGsHDy}1p(G1$=XpML(q z35h9BpKZ`MngSLAO@%-cXetDn9ioz!*4zI(j@sM!58SI($^*j4J9gRHnhj1Hg<|v?hZ@J zD(a$QE<-+5RSP!&^z`hq&&A+d-GeM`(S8Bp2*Gy=G=wB2(40&@5Ce2ob(0#(OPM5XP3hUk%=k>~YWKpH1keT#-OzxemQ&rNY8(3(F8R^OkHBgWDC$d8yb zK)X&&5sV-pKdk>ovqB51q-Pp zsnMFg>fJSAV-Byl;#z|$`3gy2pX}R@xrXT26y!%e9G}NUBQd10adS(U+;F`>x84-v z58M?=A-oJ8AFI-q}w} zl(z#qA}Xn;cSuXn=sl3^OrUiJjV>4+0;XTluC)OTA2$xNm)Z z1CFBA*47J!HC0$c(bPOXK50}#I*DYI`R#AsY*N5Nks*PmLZAsW6+K0zowK)Zx1dA8 zHaGvl|4%S>QAwLU9HA&-Ng)$GYH1Twj~txbkph{OQ|RRKE3;IOjRw(;Sw*?yps_sx zGM$lr$Ha%)o1m;FFgS{NReb~Z*hsmi?#7|RM|Ww_JrkNk9aYRlM;ix6=QAF70ct?I zx%(inM3hfjhYpMUu^p=X6bY7i0m%DDc&Y}ptD85P0|Ivft<}S@+XnWHfYzb7pdO+J zb~nILW7h$LghHS-ceTidhWvy^jZ;h%F#0uQrl64Mgrqb$ygb4C6*IF7JiYxH%E&Ti zDQKj4WBSPeJ2`5!j?SLUEFP>%SclW%lJfNzuY1G;{QP2Ubjao9OIMy?J4mHkE32}s z>|E3;C=_Jpaeu*0x z9J}=Smo05wkU3SO^+|VEPd}Jf0uA%ukCWOK{U&>$NiwnTN@eAB;Sn@2SFZZCwfCGV z%5d)=e{!*o&3}6hpg&BI4vy-`0MLBtBqYn*HFtOvy-qczIRJEOT2=-lFFA!Vrk*+R ztbh7B>LKT^*8tij_V4VbF*2ZZ0B9ioMOtrVht@l@zgVE&2fC!Rik6THA%KpHPeIVf z1^rQi%(m!drUF1$b!xxOQ*;kbi4{{Llx`pBsF*}XW`90}aCyie=wpF~_uly^iEYuZ zZuhgr;|kRb)RTdcnc*>=OgUXxRQ}`jNch#~@>L$cy}W`A28u>{1``U1Z7!S39~qq_ zzPh%Nn7w|KnuZ+{|8z*x_^6e5dEfBk77_8Hu3n*7PQ0L1EbAR2zKPd1s8kaVi@;Jx zTu3!G1%I0%9%jK@;-zvWyxEBF6v@QheZ)5lguVSE#5XjxD2KIsL0|I=`IGhVRY8{s z^&u=xnRs@=Y-v*(u2*W48z&7WOO0eUtXf;xp))O5lIW?CQ8%Boi^6V1GII;y%-T9` zS~{cP?mg4O5`<*jN=c{G6U0Zy(B|eBz`zL+k$PkiCM`$AC<@xL>&pDI4LeK~r zg@2$CG=fGUXatQy&K0Y48f`S4kCnq~QJCn(TpbwU1&HCMg znYW@;pXH1jSGFLtwY_tZK zWu_K4A#)*JbHpqzmkVU+bUFz=Jv||`SS$$oQ2o)p3p%plC1~BVEy#TEn`SS1s4Xc1 zqe8cK9MD5ULm3$vG#ZV^<3TA$&@Vw>%AKI`3}l3I=JtYC8#m4;Q*{bUTC2$+R)5v3 zS~(gt`~>B@s;WvRlbt<#*2l+ZeSIB4zW^Ojt*49|WQet^dqH2T&;wt1Z5B&*&kW&Q!lI%gdwcuv@bK;JZEtUH7Z(?J%uhS$2IVqT=b)NdI2QISLPlfS_->(g7BYb~ zv+!1g(y?vbed@22&G=R7`6DZEj#MfQ2nYxY3W6h>%}z~C4Gau~FeD^|{3Spj5QK(? z`uqDs(J&Yc*ma-~G=fGUXatR*Q3x7AqYyNLKKc3wLi!nVVa-O!00000NkvXXu0mjf DgvX)g delta 1463 zcmV;o1xWgc3&{(RB!7@eL_t(|+U?t2Op{j_2XF@q;lj(g#h92dbz8D5yKu%V(~Frb zBUy;aGUJ6a8eo#mp-d1cIDvpbEngMIj4`qa#R9dZ&U85ZK(Lh377LX^X-m;UTj&>1 zzU-I#o7dC^g_&t)g3ptalXIT)yf1lwd2@Q2lr;}2{+C!o1b+lg&=dqs&;(6E&;(8K zDxl?Z`JFp=JRXlkBAJ?+BGdl@&6OB7u@qIUMx)6pmW^)9S0&XB3>&SOGR-t<&0ysn z{fX75(Qp6s^J_P{kPL6D*v?{g;sLMUly!BhF?bmah5mNiAyzh$q9tPpi7wQEm z$FeZqv-iM__J8iz3L4M;;YZs9Ldi>je*c6*Gi+fRpj#F9k*seYIV&;b3UnAh4P8)J z#^zM!<#Y7L@m2pu|L|klCDC6m0Xin5r~HbZY1ldd4e`$kdoSKH#g?jTuZ=8$uKk^# zb)o=MK(n&*3Ho`VKRBU8&$Qj#en9g(OkY>_%QR+bzkgY0v@C&6OFzjeJ%=g&JTe6R zT+sO3Tc0KmL4Q%A7D`9^b>rAi`i8~_^%j+Oth%QD`@^YNjoZCf(%N3%AjANhMiHBf z4J34{?(S}{*E={kXt&!ZCntx7h8{e4fD;RrIyySgV~h;)SVav6sK-@H3UoT%#KZ&& zaH}N+J%2qti;IiH!^1Y4&EarpwOXIgCzHuS1qy{?VPQe9*ITVtr_(twFyQz5pDr*M z3@C89TzBu@ML}0rSExX#RL;-OhePi_kW|OJ^rFzUoz^7Y$OWm*<@Vedupho?%KP)a z-RWtP+m1Avs&83bE>BKwL26p&&Gy?zj;3CRG7@4M~CamIlPzg;Ahl8bzj12UprKKPi2m}D_?d|3B z`M4pQ%?=fmmzM)bC=^0ptyVWQGyto(xR@yj27?t96&8y{Boe`{udk2CguMar%#D=W=rGo}cSXTGCThNp&r z)#jitEcDHgpeYENpeYENpb46Spb46Spb46wDF~XNDF}L1L;HNbnVFf;)ZuUt^s>=z zoIlg)J|}gf7im1m+;{u9o$j-@-Icf96@MMBVDK4N84QM9yLLrKM`veeV_H>JwPC}C zh=>TM(@D_J4$ornn?J_iNYi~%G3uD}BjXP|Jl{2iOyqH$dVF!Y3wb;qWOH(InCaH7 zTQS88PSDE+!CT-yG4*&n1ifthB6|d#dVl!| zv}M|l%zMQn;q=&B^4lE!mc{3R)@rqEHajaTOCphAD<|kD(A&@4%aYicmMoeGhc-IA z>+=kPeox_bXHF^wlR1p+kp|7mLLN{V!VwP91NZG`y2*z?p<;x=HT} z(6h6%7;N0Qk;#{pm0^m*2|+)GKDPWG{dTV5&2*i8*3V4my+QOMktqDsv17-M(5Yj~ zmMu|HQTRa+#vBd@d7S?U`XROguzp!>4rTt<%^?$=IgG;}ra!kjB97}mE`J@(x$5|~ z!OH8M2?_4ow-4iBFvy&vRVo#xH8nMnk&!7WDS<#BHa0dUCI+wh>kfT+U>3V`Vv`Mh zb@vo9BTnyk%{F8bnr!$~#MTiAK6>l-To^xa(b_sR$NYjVK0ZD%F%i8`C@d%_NJvP) zG$|>G`ImsUwzlNt^;cBgyQf1+x>1pmj-k7ePU)78p&JGekWK;Vkw&DuyQD_x2I=mudwk#Tz3Z;~ z7u@s9JZsiIXYI3}_{51&RhGqiLG}U;4i4+RoRm87>jeh~pMZt{L~jIEec|B9sNPG7 zYkJKeW}&)iX-yBvTDe(Hk`C`+a=m?9Y+{}tPJp_L#wdl>7NIFF5dnHbVDk+bLEMMi z7LD@FwGpQW(qOGrv;fTgOcsv1@T?j!K& z)xlEIQAB0BHI^RmSknuREi6Jp6bm-bPmh+&dbPz?CJ~B)Mdo&Uw)y;Y-SLpr?tg!@)WXXyE-NF`y#s7j`BE)M#GlIl zLXE;xPHs^2`BvqGQpE2jL6&MLjf-Bn&|)|x`cHm7jSw91C!Do(!zP!_onLwUE*rBo zRw_%)?m6CDq#~$a9#W1+zr53M*&Z|ep~KN4gd_UEt{r~vtq-g(H*7hxF>H22SA_L^ z#`)a+mBU=!|Ds6ru|zpbfTYFq*dwpq@AmBWe0u0*0X;zRjPg5yk8E5zP3l}u5wtY&xYQ{x;p*ojhK}T!|W3AJfiUEizGbmczyzR zJQ6Kzpf`J;Z^8A6L7wkd$U)X7SKB#|<^1>f=b}OAWOa5k*e{dll)7amid1;F^;R`mjTOd~(!@$hls zYl`QW6<9mdW%{mkh*uLTqMM>YqsXfhPJ+^r1iOhF zFnG-Qt)I$5{OkkxEkBU__b#l+c^!JMj)H|ypNo3H8{ z;Bm+rf4v&>*;*MN&!ik*$#@4tXW|9f5dBdldiP;IS~4fw=jfKWO$>*EqRwK$XlzIX zddsEXetC7!6vc_*GYC`r6c+8q5cOP?S(C%2XDj{32lMk&S$u4urRo5S;vlfRv<428 zYIkt60}|IRzM1deFg!ZkD5)|PzKbK{LZ11RYvCKz&H-z?$KIVRNX@%Fevr;G%-v8J z+nV|ztAAieo)Kq#N&96XB zH86dpVyr9QXRFrX;^F!|( zA-bJPc5|Sxf4@*bv-ZJ7lh7d+6=$$)r~CU1mhMEQV0n|ZH+&eu^6vY*o7;CWf?v-@ zAuu_eU8aU>o9x7 zoy%g+$M;A0Zz7g_!}MQ6?#B@QsAUungix6KAx1w|cLlQjn&T;PUh!qp2HS56G@4rw zfucY}n(6Eu&1MDA^g1$4uM$o$zfq}&*V&K&rl@f{+nG?icg9ic@W6i-aA z-Zm9kyZ{)CftmajpSY~XXap5h26Tl?=PFG*C2`XQqI}%C6dzM;y!P;>+eyRifUC*ZsY)=G__PbgS4tIV2M@Il5?IsCU6S)O++KJ0F>wqA zQWuACn845iVoCVFnQv#WqEscY7+xj&qs9utDzr*lymoDC?n80jUcZeO>)`d_gb!+B;?U~W6$15M~v`|dO%6f3{-->H*p)c6HAqJwts|2 z=9~^HE^XB8;hZnh4hn{-!UozxP<_6}IaP&bdDo^p^mG{eBBM+q;yp5+wa}X{LxMEr zU*5qoc#bVGyRE$@Z-^DNei+rf5f?ls#|A04Y9EU)A{yRIsy%siRX-p{;q%q`(uwku zutU*loCku@dHquKIFZS!ikA0xZ+;gj9H94}5JqsjZjViAoR0=Rt$lt4Ou4ty)e`Vx0AZq(2V`GGB)&=@7B#a$m30vKD{LSc={{ z3!y384Y{sN%j1%Dfkw>MVH`$^J4M=2c|qr@Q@F)xw{+q) z31*||+$5xt7X<)IQ&i+eCbkYrK@wOEmbV%UuoS0VnJL_GXh%)r1&^PMtkWx37}Skj z*8-gpm&0x$HMx_2In>%l8!X>iO;f8}m&!OMRd@c$!Fr7)$ne3i41f}9|Ap`}u8tViMMqHID z3LFHLhe#$@AdnA+bMT(KvbdVmZ-=-@B$6UPHCFAO^>fh!8RoT-e)+oLsF6&F2cFW477GW#ACka01Fi z?_VdCPeF?oKfk=$@-D;Hhdivm+7(cOCl4Bf19|6rpKYY^g0tr?4hxyyDVaBb zR~+eKgOkn4cahVp50L@YZY@MRm}2;6sHH`0{e(^-M^&@omdn?Rt~fDY{AWJwO_j>7 zUx+@e;ea*?frS(Dk3pzZosC308yg?{nV0tbGa_M}S@oB+3MsuoVg}HOi3M<%@S_4P|m$djM) z$zHf*#yt^>UL);*?{Qm$+wO0KEOD^1-Z*%^7M+|@*yjuOO5hfiwS%Bd@zcZkxcO^O z>^SO09tYE#i`@x;W^S4F_V%teA`7&MFExOTYfhU=wJWx;n{1~T=fAsd^bs4^THzHT zqGCIB|4e2g9d0dPV548ag<-h)Oi1)sfFoqg$tWm(&`17&cZgtXA1AaP`O0BCm(vOqP-MX_353bXDXU%!*pE+S^`Ce=M)J2s)B4)dTV!r_Qq zKSO9Li~ff)J#KyE&-N8YZSr3jaLLK-Vw{45gIl|AnFlJ#hW~U9CcIr=Uq5a=9|IUT znp;0KiiqWBwwS^z2IF=i885FJKP|f5E;<`tKXU&%20561+=%D~la8R@~f` z!t&Z2d0HLk1U*H)htI;eFf{-9s-c4;(qFvh43C&twi$i}@o#0kH_msc9Q;$)O-V+! zmv&R-wySOo19Z>sQj2G~K~r~k_pBEaY_|lEd4Dy6Q}-J6b;^cpH98(1Uiqc~kfIP_ z$3?y%Wfftci%x~cjV2z4`O1LsuAeD&5}Qp3Fd;nyj0-?bRcd*$Bf>Cs#FALec_qIB zt7;8fJRpzz#zSvcO{AodB$t^;qx0of6Ky4Nw0`3Qstn69XiN-q4fm~#$;l6%BUz<% z&`{^=WVE`Qr5SZ&}daVx_>8dC-gzDe=hC862F-g14UYx3* zp1rkBcgDN1O20m+8L#G+8+<@ccY~Nc)K5x$ksN$LNFT(l!X{?%c{m+lGj3!lsH-XUWU z5wM8{Tk^;?!|NZDF8$dwhG}lU_7B9w8tr&QyBng<0evzMnEG%|Y@OKkbe7r?zab|T zfoWK68ZyELMSqik8@ck@H1#* zKo_^LWB`hikh3E&HahwvaVYyOC1{~?c8WzY098pHRUa#K=omWp*#J<)3moA^*}}d& z@N{a!KCtj!!IWwStxh7R?;dDr*?IrVeE1(1;(r3D2ACU=-4^TpF$jmoYC<7fBW~S< z)*Vr6icQ8rS1s0oOfUpWG3YzptE~+1i&}_uB06_A!@Uwd-haQt-

dMPzvt`W>FK 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

=bDhhvkJjjiic|Uacbz10ty+0J? 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 literal 9302 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 (0pt, 1em, 2.5em, 3em).at(n)) + += A +== B +=== C +==== Title breaks +#set heading(numbering: none) +== E += F + +--- outline-indent-bad-type --- +// Error: 2-35 expected relative length, found dictionary +#outline(indent: n => (a: "dict")) + += Heading + +--- outline-entry --- +#set page(width: 150pt) +#set heading(numbering: "1.") + +#show outline.entry.where(level: 1): set block(above: 12pt) +#show outline.entry.where(level: 1): strong + +#outline(indent: auto) + +#show heading: none += Introduction += Background +== History +== State of the Art += Analysis +== Setup + +--- outline-entry-complex --- +#set page(width: 150pt, numbering: "I", margin: (bottom: 20pt)) +#set heading(numbering: "1.") + +#set outline.entry(fill: repeat[--]) +#show outline.entry.where(level: 1): it => link( + it.element.location(), + it.indented(it.prefix(), { + emph(it.body()) + [ ] + text(luma(100), box(width: 1fr, repeat[--·--])) + [ ] + it.page() + }) +) + +#counter(page).update(3) +#outline() + +#show heading: none + += Top heading +== Not top heading +=== Lower heading +=== Lower too +== Also not top + +#pagebreak() +#set page(numbering: "1") + += Another top heading +== Middle heading +=== Lower heading + +--- outline-entry-inner --- +#set heading(numbering: "1.") +#show outline.entry: it => block(it.inner()) +#show heading: none + +#set outline.entry(fill: repeat[ -- ]) +#outline() + += A += B + +--- outline-heading-start-of-page --- +#set page(width: 140pt, height: 200pt, margin: (bottom: 20pt), numbering: "1") #set heading(numbering: "(1/a)") #show heading.where(level: 1): set text(12pt) #show heading.where(level: 2): set text(10pt) -#outline(fill: none) +#set outline.entry(fill: none) +#outline() = A = B @@ -23,66 +208,28 @@ A == F ==== G +--- outline-bookmark --- +// Ensure that `bookmarked` option doesn't affect the outline +#set heading(numbering: "(I)", bookmarked: false) +#set outline.entry(fill: none) +#show heading: none +#outline() + += A + --- outline-styled-text --- #outline(title: none) = #text(blue)[He]llo ---- outline-bookmark --- -#outline(title: none, fill: none) - -// Ensure 'bookmarked' option doesn't affect the outline -#set heading(numbering: "(I)", bookmarked: false) -= A - ---- outline-indent-numbering --- -// With heading numbering -#set page(width: 200pt) -#set heading(numbering: "1.a.") -#show heading: none -#set outline(fill: none) - -#context test(outline.indent, none) -#outline(indent: none) -#outline(indent: auto) -#outline(indent: 2em) -#outline(indent: n => ([-], [], [==], [====]).at(n)) - -= A -== B -== C -=== D -==== E - ---- outline-indent-no-numbering --- -// Without heading numbering -#set page(width: 200pt) -#show heading: none -#set outline(fill: none) - -#outline(indent: none) -#outline(indent: auto) -#outline(indent: n => 2em * n) - -= About -== History - ---- outline-indent-bad-type --- -// Error: 2-35 expected relative length or content, found dictionary -#outline(indent: n => (a: "dict")) - -= Heading - --- outline-first-line-indent --- #set par(first-line-indent: 1.5em) #set heading(numbering: "1.1.a.") -#show outline.entry.where(level: 1): it => { - v(0.5em, weak: true) - strong(it) -} +#show outline.entry.where(level: 1): strong #outline() +#show heading: none = Introduction = Background == History @@ -90,85 +237,54 @@ A = Analysis == Setup ---- outline-entry --- -#set page(width: 150pt) -#set heading(numbering: "1.") - -#show outline.entry.where( - level: 1 -): it => { - v(12pt, weak: true) - strong(it) -} - -#outline(indent: auto) -#v(1.2em, weak: true) - -#set text(8pt) -#show heading: set block(spacing: 0.65em) - -= Introduction -= Background -== History -== State of the Art -= Analysis -== Setup - ---- outline-entry-complex --- -#set page(width: 150pt, numbering: "I", margin: (bottom: 20pt)) -#set heading(numbering: "1.") -#show outline.entry.where(level: 1): it => [ - #let loc = it.element.location() - #let num = numbering(loc.page-numbering(), ..counter(page).at(loc)) - #emph(link(loc, it.body)) - #text(luma(100), box(width: 1fr, repeat[#it.fill.body;·])) - #link(loc, num) -] - -#counter(page).update(3) -#outline(indent: auto, fill: repeat[--]) -#v(1.2em, weak: true) - -#set text(8pt) -#show heading: set block(spacing: 0.65em) - -= Top heading -== Not top heading -=== Lower heading -=== Lower too -== Also not top - -#pagebreak() -#set page(numbering: "1") - -= Another top heading -== Middle heading -=== Lower heading - --- outline-bad-element --- // Error: 2-27 cannot outline metadata #outline(target: metadata) #metadata("hello") + +--- issue-2048-outline-multiline --- +// Without the word joiner between the dots and the page number, +// the page number would be alone in its line. +#set page(width: 125pt) +#set heading(numbering: "1.a.") +#show heading: none + +#outline() + += A +== This just fits here + --- issue-2530-outline-entry-panic-text --- // Outline entry (pre-emptive) -// Error: 2-48 cannot outline text -#outline.entry(1, [Hello], [World!], none, [1]) +// Error: 2-27 cannot outline text +#outline.entry(1, [Hello]) --- issue-2530-outline-entry-panic-heading --- // Outline entry (pre-emptive, improved error) -// Error: 2-55 heading must have a location -// Hint: 2-55 try using a query or a show rule to customize the outline.entry instead -#outline.entry(1, heading[Hello], [World!], none, [1]) +// Error: 2-34 heading must have a location +// Hint: 2-34 try using a show rule to customize the outline.entry instead +#outline.entry(1, heading[Hello]) ---- issue-4476-rtl-title-ending-in-ltr-text --- +--- issue-4476-outline-rtl-title-ending-in-ltr-text --- #set text(lang: "he") #outline() +#show heading: none = הוקוס Pocus = זוהי כותרת שתורגמה על ידי מחשב ---- issue-5176-cjk-title --- +--- issue-4859-outline-entry-show-set --- +#set heading(numbering: "1.a.") +#show outline.entry.where(level: 1): set outline.entry(fill: none) +#show heading: none + +#outline() + += A +== B + +--- issue-5176-outline-cjk-title --- #set text(font: "Noto Serif CJK SC") #show heading: none From dda486a412b31acbf767087c748a62ccc6b510b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20F=C3=A4rber?= <01mf02@gmail.com> Date: Thu, 23 Jan 2025 13:08:48 +0100 Subject: [PATCH 3/9] HTML tables (#5666) --- crates/typst-html/src/encode.rs | 5 +- .../typst-library/src/layout/grid/resolve.rs | 2 +- crates/typst-library/src/model/table.rs | 66 +++++++++++++++++-- tests/ref/html/basic-table.html | 35 ++++++++++ tests/suite/layout/grid/html.typ | 32 +++++++++ 5 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 tests/ref/html/basic-table.html create mode 100644 tests/suite/layout/grid/html.typ diff --git a/crates/typst-html/src/encode.rs b/crates/typst-html/src/encode.rs index 62146f867..71422a0fc 100644 --- a/crates/typst-html/src/encode.rs +++ b/crates/typst-html/src/encode.rs @@ -120,7 +120,10 @@ fn write_element(w: &mut Writer, element: &HtmlElement) -> SourceResult<()> { /// Whether the element should be pretty-printed. fn is_pretty(element: &HtmlElement) -> bool { - tag::is_block_by_default(element.tag) || matches!(element.tag, tag::meta) + matches!( + element.tag, + tag::meta | tag::table | tag::thead | tag::tbody | tag::tfoot | tag::tr + ) || tag::is_block_by_default(element.tag) } /// Escape a character. diff --git a/crates/typst-library/src/layout/grid/resolve.rs b/crates/typst-library/src/layout/grid/resolve.rs index 504159e83..f6df57a37 100644 --- a/crates/typst-library/src/layout/grid/resolve.rs +++ b/crates/typst-library/src/layout/grid/resolve.rs @@ -602,7 +602,7 @@ pub enum Entry<'a> { impl<'a> Entry<'a> { /// Obtains the cell inside this entry, if this is not a merged cell. - fn as_cell(&self) -> Option<&Cell<'a>> { + pub fn as_cell(&self) -> Option<&Cell<'a>> { match self { Self::Cell(cell) => Some(cell), Self::Merged { .. } => None, diff --git a/crates/typst-library/src/model/table.rs b/crates/typst-library/src/model/table.rs index fa44cb58a..ba7924422 100644 --- a/crates/typst-library/src/model/table.rs +++ b/crates/typst-library/src/model/table.rs @@ -7,7 +7,11 @@ use crate::diag::{bail, HintedStrResult, HintedString, SourceResult}; use crate::engine::Engine; use crate::foundations::{ cast, elem, scope, Content, NativeElement, Packed, Show, Smart, StyleChain, + TargetElem, }; +use crate::html::{tag, HtmlAttr, HtmlAttrs, HtmlElem, HtmlTag}; +use crate::introspection::Locator; +use crate::layout::grid::resolve::{table_to_cellgrid, Cell, CellGrid, Entry}; use crate::layout::{ show_grid_cell, Abs, Alignment, BlockElem, Celled, GridCell, GridFooter, GridHLine, GridHeader, GridVLine, Length, OuterHAlignment, OuterVAlignment, Rel, Sides, @@ -258,11 +262,65 @@ impl TableElem { type TableFooter; } +fn show_cell_html(tag: HtmlTag, cell: &Cell, styles: StyleChain) -> Content { + let cell = cell.body.clone(); + let Some(cell) = cell.to_packed::() else { return cell }; + let mut attrs = HtmlAttrs::default(); + let span = |n: NonZeroUsize| (n != NonZeroUsize::MIN).then(|| n.to_string()); + if let Some(colspan) = span(cell.colspan(styles)) { + attrs.push(HtmlAttr::constant("colspan"), colspan); + } + if let Some(rowspan) = span(cell.rowspan(styles)) { + attrs.push(HtmlAttr::constant("rowspan"), rowspan); + } + HtmlElem::new(tag) + .with_body(Some(cell.body.clone())) + .with_attrs(attrs) + .pack() + .spanned(cell.span()) +} + +fn show_cellgrid_html(grid: CellGrid, styles: StyleChain) -> Content { + let elem = |tag, body| HtmlElem::new(tag).with_body(Some(body)).pack(); + let mut rows: Vec<_> = grid.entries.chunks(grid.cols.len()).collect(); + + let tr = |tag, row: &[Entry]| { + let row = row + .iter() + .flat_map(|entry| entry.as_cell()) + .map(|cell| show_cell_html(tag, cell, styles)); + elem(tag::tr, Content::sequence(row)) + }; + + let footer = grid.footer.map(|ft| { + let rows = rows.drain(ft.unwrap().start..); + elem(tag::tfoot, Content::sequence(rows.map(|row| tr(tag::td, row)))) + }); + let header = grid.header.map(|hd| { + let rows = rows.drain(..hd.unwrap().end); + elem(tag::thead, Content::sequence(rows.map(|row| tr(tag::th, row)))) + }); + + let mut body = Content::sequence(rows.into_iter().map(|row| tr(tag::td, row))); + if header.is_some() || footer.is_some() { + body = elem(tag::tbody, body); + } + + let content = header.into_iter().chain(core::iter::once(body)).chain(footer); + elem(tag::table, Content::sequence(content)) +} + impl Show for Packed { - fn show(&self, engine: &mut Engine, _: StyleChain) -> SourceResult { - Ok(BlockElem::multi_layouter(self.clone(), engine.routines.layout_table) - .pack() - .spanned(self.span())) + fn show(&self, engine: &mut Engine, styles: StyleChain) -> SourceResult { + Ok(if TargetElem::target_in(styles).is_html() { + // TODO: This is a hack, it is not clear whether the locator is actually used by HTML. + // How can we find out whether locator is actually used? + let locator = Locator::root(); + show_cellgrid_html(table_to_cellgrid(self, engine, locator, styles)?, styles) + } else { + BlockElem::multi_layouter(self.clone(), engine.routines.layout_table).pack() + } + .spanned(self.span())) } } diff --git a/tests/ref/html/basic-table.html b/tests/ref/html/basic-table.html new file mode 100644 index 000000000..6ba1864ef --- /dev/null +++ b/tests/ref/html/basic-table.html @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Thefirstand
thesecondrow
FooBazBar
12
34
Thelastrow
+ + diff --git a/tests/suite/layout/grid/html.typ b/tests/suite/layout/grid/html.typ new file mode 100644 index 000000000..2a7dfc2ce --- /dev/null +++ b/tests/suite/layout/grid/html.typ @@ -0,0 +1,32 @@ +--- basic-table html --- +#table( + columns: 3, + rows: 3, + + table.header( + [The], + [first], + [and], + [the], + [second], + [row], + table.hline(stroke: red) + ), + + table.cell(x: 1, rowspan: 2)[Baz], + [Foo], + [Bar], + + [1], + // Baz spans into the next cell + [2], + + table.cell(colspan: 2)[3], + [4], + + table.footer( + [The], + [last], + [row], + ), +) From e61cd6fb9e9a90de8d78f05a43246f08feddcf8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20F=C3=A4rber?= <01mf02@gmail.com> Date: Thu, 23 Jan 2025 13:18:46 +0100 Subject: [PATCH 4/9] Support `start` attribute for `enum` in HTML export (#5676) --- crates/typst-library/src/model/enum.rs | 24 ++++++++++++------------ tests/ref/html/enum-start.html | 12 ++++++++++++ tests/suite/model/enum.typ | 7 +++++++ 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 tests/ref/html/enum-start.html diff --git a/crates/typst-library/src/model/enum.rs b/crates/typst-library/src/model/enum.rs index eb3c2ea45..2d774cbbb 100644 --- a/crates/typst-library/src/model/enum.rs +++ b/crates/typst-library/src/model/enum.rs @@ -229,19 +229,19 @@ impl Show for Packed { if TargetElem::target_in(styles).is_html() { let mut elem = HtmlElem::new(tag::ol); if self.reversed(styles) { - elem = - elem.with_attr(const { HtmlAttr::constant("reversed") }, "reversed"); + elem = elem.with_attr(HtmlAttr::constant("reversed"), "reversed"); } - return Ok(elem - .with_body(Some(Content::sequence(self.children.iter().map(|item| { - let mut li = HtmlElem::new(tag::li); - if let Some(nr) = item.number(styles) { - li = li.with_attr(attr::value, eco_format!("{nr}")); - } - li.with_body(Some(item.body.clone())).pack().spanned(item.span()) - })))) - .pack() - .spanned(self.span())); + if let Some(n) = self.start(styles).custom() { + elem = elem.with_attr(HtmlAttr::constant("start"), eco_format!("{n}")); + } + let body = Content::sequence(self.children.iter().map(|item| { + let mut li = HtmlElem::new(tag::li); + if let Some(nr) = item.number(styles) { + li = li.with_attr(attr::value, eco_format!("{nr}")); + } + li.with_body(Some(item.body.clone())).pack().spanned(item.span()) + })); + return Ok(elem.with_body(Some(body)).pack().spanned(self.span())); } let mut realized = diff --git a/tests/ref/html/enum-start.html b/tests/ref/html/enum-start.html new file mode 100644 index 000000000..8a4ff37f9 --- /dev/null +++ b/tests/ref/html/enum-start.html @@ -0,0 +1,12 @@ + + + + + + + +

    +
  1. Skipping
  2. Ahead
  3. +
+ + diff --git a/tests/suite/model/enum.typ b/tests/suite/model/enum.typ index 258c6f6bc..e957ae9e8 100644 --- a/tests/suite/model/enum.typ +++ b/tests/suite/model/enum.typ @@ -101,6 +101,13 @@ a + 0. [Red], [Green], [Blue], [Red], ) +--- enum-start html --- +#enum( + start: 3, + [Skipping], + [Ahead], +) + --- enum-numbering-closure-nested --- // Test numbering with closure and nested lists. #set enum(numbering: n => super[#n]) From b3fb6c2326ac6d585cc17d1f643bc06e076be042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20F=C3=A4rber?= <01mf02@gmail.com> Date: Thu, 23 Jan 2025 13:21:34 +0100 Subject: [PATCH 5/9] Support quotes in HTML output (#5673) --- crates/typst-library/src/model/quote.rs | 81 +++++++++++++--------- tests/ref/html/quote-attribution-link.html | 15 ++++ tests/ref/html/quote-nesting-html.html | 12 ++++ tests/ref/html/quote-plato.html | 21 ++++++ tests/suite/model/quote.typ | 23 ++++++ 5 files changed, 120 insertions(+), 32 deletions(-) create mode 100644 tests/ref/html/quote-attribution-link.html create mode 100644 tests/ref/html/quote-nesting-html.html create mode 100644 tests/ref/html/quote-plato.html diff --git a/crates/typst-library/src/model/quote.rs b/crates/typst-library/src/model/quote.rs index 2eaa32d4c..774384acb 100644 --- a/crates/typst-library/src/model/quote.rs +++ b/crates/typst-library/src/model/quote.rs @@ -2,13 +2,14 @@ use crate::diag::SourceResult; use crate::engine::Engine; use crate::foundations::{ cast, elem, Content, Depth, Label, NativeElement, Packed, Show, ShowSet, Smart, - StyleChain, Styles, + StyleChain, Styles, TargetElem, }; +use crate::html::{tag, HtmlAttr, HtmlElem}; use crate::introspection::Locatable; use crate::layout::{ Alignment, BlockBody, BlockElem, Em, HElem, PadElem, Spacing, VElem, }; -use crate::model::{CitationForm, CiteElem}; +use crate::model::{CitationForm, CiteElem, Destination, LinkElem, LinkTarget}; use crate::text::{SmartQuoteElem, SmartQuotes, SpaceElem, TextElem}; /// Displays a quote alongside an optional attribution. @@ -158,6 +159,7 @@ impl Show for Packed { fn show(&self, _: &mut Engine, styles: StyleChain) -> SourceResult { let mut realized = self.body.clone(); let block = self.block(styles); + let html = TargetElem::target_in(styles).is_html(); if self.quotes(styles) == Smart::Custom(true) || !block { let quotes = SmartQuotes::get( @@ -171,50 +173,65 @@ impl Show for Packed { let Depth(depth) = QuoteElem::depth_in(styles); let double = depth % 2 == 0; - // Add zero-width weak spacing to make the quotes "sticky". - let hole = HElem::hole().pack(); + if !html { + // Add zero-width weak spacing to make the quotes "sticky". + let hole = HElem::hole().pack(); + realized = Content::sequence([hole.clone(), realized, hole]); + } realized = Content::sequence([ TextElem::packed(quotes.open(double)), - hole.clone(), realized, - hole, TextElem::packed(quotes.close(double)), ]) .styled(QuoteElem::set_depth(Depth(1))); } + let attribution = self.attribution(styles); + if block { - realized = BlockElem::new() - .with_body(Some(BlockBody::Content(realized))) - .pack() - .spanned(self.span()); - - if let Some(attribution) = self.attribution(styles).as_ref() { - let mut seq = vec![TextElem::packed('—'), SpaceElem::shared().clone()]; - - match attribution { - Attribution::Content(content) => { - seq.push(content.clone()); - } - Attribution::Label(label) => { - seq.push( - CiteElem::new(*label) - .with_form(Some(CitationForm::Prose)) - .pack() - .spanned(self.span()), - ); + realized = if html { + let mut elem = HtmlElem::new(tag::blockquote).with_body(Some(realized)); + if let Some(Attribution::Content(attribution)) = attribution { + if let Some(link) = attribution.to_packed::() { + if let LinkTarget::Dest(Destination::Url(url)) = &link.dest { + elem = elem.with_attr( + HtmlAttr::constant("cite"), + url.clone().into_inner(), + ); + } } } + elem.pack() + } else { + BlockElem::new().with_body(Some(BlockBody::Content(realized))).pack() + } + .spanned(self.span()); - // Use v(0.9em, weak: true) bring the attribution closer to the - // quote. - let gap = Spacing::Rel(Em::new(0.9).into()); - let v = VElem::new(gap).with_weak(true).pack(); - realized += v + Content::sequence(seq).aligned(Alignment::END); + if let Some(attribution) = attribution.as_ref() { + let attribution = match attribution { + Attribution::Content(content) => content.clone(), + Attribution::Label(label) => CiteElem::new(*label) + .with_form(Some(CitationForm::Prose)) + .pack() + .spanned(self.span()), + }; + let attribution = + [TextElem::packed('—'), SpaceElem::shared().clone(), attribution]; + + if !html { + // Use v(0.9em, weak: true) to bring the attribution closer + // to the quote. + let gap = Spacing::Rel(Em::new(0.9).into()); + let v = VElem::new(gap).with_weak(true).pack(); + realized += v; + } + realized += Content::sequence(attribution).aligned(Alignment::END); } - realized = PadElem::new(realized).pack(); - } else if let Some(Attribution::Label(label)) = self.attribution(styles) { + if !html { + realized = PadElem::new(realized).pack(); + } + } else if let Some(Attribution::Label(label)) = attribution { realized += SpaceElem::shared().clone() + CiteElem::new(*label).pack().spanned(self.span()); } diff --git a/tests/ref/html/quote-attribution-link.html b/tests/ref/html/quote-attribution-link.html new file mode 100644 index 000000000..4da8b47f5 --- /dev/null +++ b/tests/ref/html/quote-attribution-link.html @@ -0,0 +1,15 @@ + + + + + + + +
+ Compose papers faster +
+

+ — typst.com +

+ + diff --git a/tests/ref/html/quote-nesting-html.html b/tests/ref/html/quote-nesting-html.html new file mode 100644 index 000000000..c652bd97b --- /dev/null +++ b/tests/ref/html/quote-nesting-html.html @@ -0,0 +1,12 @@ + + + + + + + +

+ When you said that “he surely meant that ‘she intended to say “I'm sorry”’”, I was quite confused. +

+ + diff --git a/tests/ref/html/quote-plato.html b/tests/ref/html/quote-plato.html new file mode 100644 index 000000000..fc052d10c --- /dev/null +++ b/tests/ref/html/quote-plato.html @@ -0,0 +1,21 @@ + + + + + + + +
+ … ἔοικα γοῦν τούτου γε σμικρῷ τινι αὐτῷ τούτῳ σοφώτερος εἶναι, ὅτι ἃ μὴ οἶδα οὐδὲ οἴομαι εἰδέναι. +
+

+ — Plato +

+
+ … I seem, then, in just this little thing to be wiser than this man at any rate, that what I do not know I do not think I know either. +
+

+ — from the Henry Cary literal translation of 1897 +

+ + diff --git a/tests/suite/model/quote.typ b/tests/suite/model/quote.typ index 2c93f92cd..d0dcc55dd 100644 --- a/tests/suite/model/quote.typ +++ b/tests/suite/model/quote.typ @@ -84,3 +84,26 @@ And I quote: #quote(attribution: [René Descartes])[cogito, ergo sum]. // With custom quotes. #set smartquote(quotes: (single: ("<", ">"), double: ("(", ")"))) #quote[A #quote[nested] quote] + +--- quote-plato html --- +#set quote(block: true) + +#quote(attribution: [Plato])[ + ... ἔοικα γοῦν τούτου γε σμικρῷ τινι αὐτῷ τούτῳ σοφώτερος εἶναι, ὅτι + ἃ μὴ οἶδα οὐδὲ οἴομαι εἰδέναι. +] +#quote(attribution: [from the Henry Cary literal translation of 1897])[ + ... I seem, then, in just this little thing to be wiser than this man at + any rate, that what I do not know I do not think I know either. +] + +--- quote-nesting-html html --- +When you said that #quote[he surely meant that #quote[she intended to say #quote[I'm sorry]]], I was quite confused. + +--- quote-attribution-link html --- +#quote( + block: true, + attribution: link("https://typst.app/home")[typst.com] +)[ + Compose papers faster +] From f7bd03dd76533cda2d2626d6470d3bb55e03b012 Mon Sep 17 00:00:00 2001 From: Ian Wrzesinski <133046678+wrzian@users.noreply.github.com> Date: Thu, 23 Jan 2025 07:27:38 -0500 Subject: [PATCH 6/9] Fix delimiter unparen syntax (#5739) --- crates/typst-syntax/src/parser.rs | 4 ++-- tests/ref/math-lr-unparen.png | Bin 0 -> 493 bytes tests/suite/math/delimited.typ | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 tests/ref/math-lr-unparen.png diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs index a65e5ff6b..f9fb8b616 100644 --- a/crates/typst-syntax/src/parser.rs +++ b/crates/typst-syntax/src/parser.rs @@ -442,10 +442,10 @@ fn math_unparen(p: &mut Parser, m: Marker) { if first.text() == "(" && last.text() == ")" { first.convert_to_kind(SyntaxKind::LeftParen); last.convert_to_kind(SyntaxKind::RightParen); + // Only convert if we did have regular parens. + node.convert_to_kind(SyntaxKind::Math); } } - - node.convert_to_kind(SyntaxKind::Math); } /// The unicode math class of a string. Only returns `Some` if `text` has diff --git a/tests/ref/math-lr-unparen.png b/tests/ref/math-lr-unparen.png new file mode 100644 index 0000000000000000000000000000000000000000..d418b14eaa978f7975cc8185ce6e25b52c7a5056 GIT binary patch literal 493 zcmV+IEiC>vD{QupfuT z9}}B_3aZl+)==5U9`ix0&-3GO`8c%!#QM3`o5~iyRK5vj@A!tp;%~Z#!0a=RsT{{U zjeg>fkFQODRL{R~S^T^n z(x3QBU5nqBL)c}1a9I4S2vS2ezon|h|01^>Ja}OJWP>bRL7lby;K75NX4q3XAAeW` z1^01S{A&qR!Ij}uN!)xzz~a|8XkziNg9Lp1Zy#-Zd@}nVev404zoCi6pGqDR@Nvdt z>RKGM{TPUPI~N?s`?g1;D~R3>4&*=6z!o3d9z-RJw=LR?#9O)OAi9Esi&i4>HZR&X j+G!iLc+}!ii)je}qm_{qY}NN400000NkvXXu0mjf^L^=Q literal 0 HcmV?d00001 diff --git a/tests/suite/math/delimited.typ b/tests/suite/math/delimited.typ index 226740501..ca82427dd 100644 --- a/tests/suite/math/delimited.typ +++ b/tests/suite/math/delimited.typ @@ -125,3 +125,11 @@ $ lr(size: #3em, |)_a^b lr(size: #3em, zws|)_a^b --- issue-4188-lr-corner-brackets --- // Test positioning of U+231C to U+231F $⌜a⌟⌞b⌝$ = $⌜$$a$$⌟$$⌞$$b$$⌝$ + +--- math-lr-unparen --- +// Test that unparen with brackets stays as an LrElem. +#let item = $limits(sum)_i$ +$ + 1 / ([item]) quad + 1 / [item] +$ From 58dbbd48fe415c5a345fb1665aab478a03b5df82 Mon Sep 17 00:00:00 2001 From: SekoiaTree <51149447+SekoiaTree@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:35:29 +0100 Subject: [PATCH 7/9] Add lcm as an operator in math mode (#5718) Co-authored-by: Laurenz --- crates/typst-library/src/math/op.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/typst-library/src/math/op.rs b/crates/typst-library/src/math/op.rs index ef24705a7..5b3f58beb 100644 --- a/crates/typst-library/src/math/op.rs +++ b/crates/typst-library/src/math/op.rs @@ -17,9 +17,9 @@ use crate::text::TextElem; /// # Predefined Operators { #predefined } /// Typst predefines the operators `arccos`, `arcsin`, `arctan`, `arg`, `cos`, /// `cosh`, `cot`, `coth`, `csc`, `csch`, `ctg`, `deg`, `det`, `dim`, `exp`, -/// `gcd`, `hom`, `id`, `im`, `inf`, `ker`, `lg`, `lim`, `liminf`, `limsup`, -/// `ln`, `log`, `max`, `min`, `mod`, `Pr`, `sec`, `sech`, `sin`, `sinc`, -/// `sinh`, `sup`, `tan`, `tanh`, `tg` and `tr`. +/// `gcd`, `lcm`, `hom`, `id`, `im`, `inf`, `ker`, `lg`, `lim`, `liminf`, +/// `limsup`, `ln`, `log`, `max`, `min`, `mod`, `Pr`, `sec`, `sech`, `sin`, +/// `sinc`, `sinh`, `sup`, `tan`, `tanh`, `tg` and `tr`. #[elem(title = "Text Operator", Mathy)] pub struct OpElem { /// The operator's text. @@ -75,6 +75,7 @@ ops! { dim, exp, gcd (limits), + lcm (limits), hom, id, im, From ce299d5832095013bbcf2baef38552df6d2fc21b Mon Sep 17 00:00:00 2001 From: wznmickey Date: Thu, 23 Jan 2025 07:52:20 -0500 Subject: [PATCH 8/9] Support syntactically directly nested list, enum, and term list (#5728) Co-authored-by: Laurenz --- crates/typst-syntax/src/parser.rs | 6 +++--- tests/ref/issue-5719-enum-nested.png | Bin 0 -> 800 bytes tests/ref/issue-5719-heading-nested.png | Bin 0 -> 217 bytes tests/ref/issue-5719-list-nested.png | Bin 0 -> 506 bytes tests/ref/issue-5719-terms-nested.png | Bin 0 -> 921 bytes tests/suite/model/enum.typ | 10 ++++++++++ tests/suite/model/heading.typ | 4 ++++ tests/suite/model/list.typ | 8 ++++++++ tests/suite/model/terms.typ | 6 ++++++ 9 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 tests/ref/issue-5719-enum-nested.png create mode 100644 tests/ref/issue-5719-heading-nested.png create mode 100644 tests/ref/issue-5719-list-nested.png create mode 100644 tests/ref/issue-5719-terms-nested.png diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs index f9fb8b616..5b9e66e28 100644 --- a/crates/typst-syntax/src/parser.rs +++ b/crates/typst-syntax/src/parser.rs @@ -160,7 +160,7 @@ fn list_item(p: &mut Parser) { p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| { let m = p.marker(); p.assert(SyntaxKind::ListMarker); - markup(p, false, false, syntax_set!(RightBracket, End)); + markup(p, true, false, syntax_set!(RightBracket, End)); p.wrap(m, SyntaxKind::ListItem); }); } @@ -170,7 +170,7 @@ fn enum_item(p: &mut Parser) { p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| { let m = p.marker(); p.assert(SyntaxKind::EnumMarker); - markup(p, false, false, syntax_set!(RightBracket, End)); + markup(p, true, false, syntax_set!(RightBracket, End)); p.wrap(m, SyntaxKind::EnumItem); }); } @@ -184,7 +184,7 @@ fn term_item(p: &mut Parser) { markup(p, false, false, syntax_set!(Colon, RightBracket, End)); }); p.expect(SyntaxKind::Colon); - markup(p, false, false, syntax_set!(RightBracket, End)); + markup(p, true, false, syntax_set!(RightBracket, End)); p.wrap(m, SyntaxKind::TermItem); }); } diff --git a/tests/ref/issue-5719-enum-nested.png b/tests/ref/issue-5719-enum-nested.png new file mode 100644 index 0000000000000000000000000000000000000000..7670454498688ea2701f53fc5a56f137f42db0f9 GIT binary patch literal 800 zcmV+*1K<3KP)pUv$QdP>})$aKd}za*#x~%JkPm#o~!rw>c#e)^W}s=rW3|s1~Zt! zM*@EdX+FkJ3-;^75j-E#duYKxOi1g;(`121wfzxpIbf}AGQWiuyb}S8a{tq=17WwBu+;dykUx%`im@Ko7mG-=o4OC({rkH$hN zVb=;yZ;`>BND71Mje-#=VW7Q1OfCdYsJ~^D6do{PPgo5^x+H`bwP@L#=7nJ;7MKvS zHx2w*w}kNL+e#Hm=Y^pn&5B%4pgct?lWC4E5C${&(D1UwC$`m4`Cx<++}|{sO8VPF zVCe}Zcxr9y6zSvz08UCUU~DH9?xT6fU2S5N zWG+yiyrd>m3C|V?gBg5S*uO-ID=(;hHc1Pfs5L(&-FXL&ceLPPhd+vRzXmfD@A#uZ zgyU-N(u2ng2>HeH)Zkw_Sg<3sMFW^=!DUIxn@HdS$!TI6bm?q?Fqpvygf~ePsx_I} znd!eN!Hwl&Mkrb_bKyH3_(xua*jE%ofNhQnyshuv4KFxB1+MBgA>)2TwhoH4F1&{UW)IrAHqpg^vSY79LE%SoE&g{RdwY6+tmza@Dahh zJn*32oLeXZJd*;TSO!?vBGVmT9Rzwy$LPaaJ%Hoe^x>s51K5uA(TCxD`{wm5+guE0 eFoPK!dj0`Pr%E}6wyz8T0000EZxfpUZ5a)k*$4xaxv z>s)8{(w=u8|Nno^ZG3ai;`K-E>uP>~1**-r-}g^yt%{qj+}4UKj~vqt8UFlC6*5~Z QR|s;mr>mdKI;Vst06Z99ivR!s literal 0 HcmV?d00001 diff --git a/tests/ref/issue-5719-list-nested.png b/tests/ref/issue-5719-list-nested.png new file mode 100644 index 0000000000000000000000000000000000000000..9c9a7cc62f9fabfc6e15ce6b01c1c108c0bd069a GIT binary patch literal 506 zcmV0005ONkl9oL%^2oD;09igAHG z#u*DD{MxvYO4BxVHzIt>s>KkN2}0#N9t_qeajKjEOI!FmzLA+Ax;){b0wI{-?7Z#y)1gCfcOl$3*sBvmntIDD?q%G&NZ6$rru{~rDts;O=6Ul!0|2opF07*qoM6N<$f|hsQS^xk5 literal 0 HcmV?d00001 diff --git a/tests/ref/issue-5719-terms-nested.png b/tests/ref/issue-5719-terms-nested.png new file mode 100644 index 0000000000000000000000000000000000000000..8428ae4eee55e9d02e2d5cbf4db5837a565307a6 GIT binary patch literal 921 zcmV;K17`e*P)N5jb^JU=$x0tnPP79 zek*fMx14xE#k`doSfDepyybGJ+0>mUr$@{fe(4;7c+aQzJ^w%aIETaYa@N2_11gBU81EW6}yM&SDk|<0iK41n#HFS z?q%oWJzZ5?--TrSiQoR^-WfLF^y6)uY8@)kQR`FsiSia=*pf(P5~7)1*!5gPgQ*S~ z0XF7O5;Z+UHvmxF`UYD+_TcAe5QJNb3-www1m<6b@I|5X_6L^~R!Rn^ZI5q9 zvj$gz5{>_8w$^%qOu1;7C72$WR7i;5Y{bE22i0NmE&F^Io+VHqje|R|3(JnwajL6` z%0^h9@dfGHiNOW9QM9j>UD)M9XXjiUv3N+JnjX}>0Gq(pn>|>D20*-7o}t$egD|&F zK7>^7Q4;{fqp8*nNvy&BqF^b^Ci-eYD#!)3Kvp40D-3uyIJF36mk-P2;b*Q4|=^<`ZQJYS1U>LrseHvr=w8_ z-0`+iubW>`Hd)^Y%?G00@{H&m+}%%qQsb227{iCeeWyq;-m^=D2q!s|I*LmiW99R= vz!c=<9}_!8*XknUd+-3kForSwzr()(Ihd{iz4HV~00000NkvXXu0mjf1~sp1 literal 0 HcmV?d00001 diff --git a/tests/suite/model/enum.typ b/tests/suite/model/enum.typ index e957ae9e8..288392d45 100644 --- a/tests/suite/model/enum.typ +++ b/tests/suite/model/enum.typ @@ -199,3 +199,13 @@ a + 0. + f #align(right)[+ align] + h + +--- issue-5719-enum-nested --- +// Enums can be immediately nested. +1. A +2. 1. B + 2. C ++ + D + + E ++ = F + G diff --git a/tests/suite/model/heading.typ b/tests/suite/model/heading.typ index 45e5b50ae..4e529fdf6 100644 --- a/tests/suite/model/heading.typ +++ b/tests/suite/model/heading.typ @@ -148,3 +148,7 @@ Cannot be used as @intro // Hint: 1-16 HTML only supports

to

, not // Hint: 1-16 you may want to restructure your document so that it doesn't contain deep headings ======= Level 7 + +--- issue-5719-heading-nested --- +// Headings may not be nested like this. += = A diff --git a/tests/suite/model/list.typ b/tests/suite/model/list.typ index b3d9a830b..96ddf3c18 100644 --- a/tests/suite/model/list.typ +++ b/tests/suite/model/list.typ @@ -276,3 +276,11 @@ World - h #align(right)[- i] - j + +--- issue-5719-list-nested --- +// Lists can be immediately nested. +- A +- - B + - C +- = D + E diff --git a/tests/suite/model/terms.typ b/tests/suite/model/terms.typ index 61fe20b0d..23ac6e513 100644 --- a/tests/suite/model/terms.typ +++ b/tests/suite/model/terms.typ @@ -90,3 +90,9 @@ Not in list / h: h #align(right)[/ i: i] / j: j + +--- issue-5719-terms-nested --- +// Term lists can be immediately nested. +/ Term A: 1 +/ Term B: / Term C: 2 + / Term D: 3 From b7546bace7fb8640d1e7121b8bd7baf3cdb576e1 Mon Sep 17 00:00:00 2001 From: T0mstone <39707032+T0mstone@users.noreply.github.com> Date: Thu, 23 Jan 2025 14:05:12 +0100 Subject: [PATCH 9/9] Ignore shebang at start of file (#5702) --- crates/typst-syntax/src/highlight.rs | 1 + crates/typst-syntax/src/kind.rs | 9 ++++++++- crates/typst-syntax/src/lexer.rs | 6 ++++++ crates/typst-syntax/src/parser.rs | 2 ++ tests/suite/syntax/shebang.typ | 7 +++++++ 5 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/suite/syntax/shebang.typ diff --git a/crates/typst-syntax/src/highlight.rs b/crates/typst-syntax/src/highlight.rs index de8ed65c9..c59a03384 100644 --- a/crates/typst-syntax/src/highlight.rs +++ b/crates/typst-syntax/src/highlight.rs @@ -287,6 +287,7 @@ pub fn highlight(node: &LinkedNode) -> Option { SyntaxKind::Destructuring => None, SyntaxKind::DestructAssignment => None, + SyntaxKind::Shebang => Some(Tag::Comment), SyntaxKind::LineComment => Some(Tag::Comment), SyntaxKind::BlockComment => Some(Tag::Comment), SyntaxKind::Error => Some(Tag::Error), diff --git a/crates/typst-syntax/src/kind.rs b/crates/typst-syntax/src/kind.rs index 0a7c160b4..b4a97a3e0 100644 --- a/crates/typst-syntax/src/kind.rs +++ b/crates/typst-syntax/src/kind.rs @@ -9,6 +9,8 @@ pub enum SyntaxKind { /// An invalid sequence of characters. Error, + /// A shebang: `#! ...` + Shebang, /// A line comment: `// ...`. LineComment, /// A block comment: `/* ... */`. @@ -357,7 +359,11 @@ impl SyntaxKind { pub fn is_trivia(self) -> bool { matches!( self, - Self::LineComment | Self::BlockComment | Self::Space | Self::Parbreak + Self::Shebang + | Self::LineComment + | Self::BlockComment + | Self::Space + | Self::Parbreak ) } @@ -371,6 +377,7 @@ impl SyntaxKind { match self { Self::End => "end of tokens", Self::Error => "syntax error", + Self::Shebang => "shebang", Self::LineComment => "line comment", Self::BlockComment => "block comment", Self::Markup => "markup", diff --git a/crates/typst-syntax/src/lexer.rs b/crates/typst-syntax/src/lexer.rs index 6b5d28162..17401044f 100644 --- a/crates/typst-syntax/src/lexer.rs +++ b/crates/typst-syntax/src/lexer.rs @@ -103,6 +103,7 @@ impl Lexer<'_> { self.newline = false; let kind = match self.s.eat() { Some(c) if is_space(c, self.mode) => self.whitespace(start, c), + Some('#') if start == 0 && self.s.eat_if('!') => self.shebang(), Some('/') if self.s.eat_if('/') => self.line_comment(), Some('/') if self.s.eat_if('*') => self.block_comment(), Some('*') if self.s.eat_if('/') => { @@ -151,6 +152,11 @@ impl Lexer<'_> { } } + fn shebang(&mut self) -> SyntaxKind { + self.s.eat_until(is_newline); + SyntaxKind::Shebang + } + fn line_comment(&mut self) -> SyntaxKind { self.s.eat_until(is_newline); SyntaxKind::LineComment diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs index 5b9e66e28..5de71cafc 100644 --- a/crates/typst-syntax/src/parser.rs +++ b/crates/typst-syntax/src/parser.rs @@ -93,6 +93,8 @@ fn markup_expr(p: &mut Parser, at_start: bool, nesting: &mut usize) { p.hint("try using a backslash escape: \\]"); } + SyntaxKind::Shebang => p.eat(), + SyntaxKind::Text | SyntaxKind::Linebreak | SyntaxKind::Escape diff --git a/tests/suite/syntax/shebang.typ b/tests/suite/syntax/shebang.typ new file mode 100644 index 000000000..c2eb2e43c --- /dev/null +++ b/tests/suite/syntax/shebang.typ @@ -0,0 +1,7 @@ +// Test shebang support. + +--- shebang --- +#!typst compile + +// Error: 2-3 the character `!` is not valid in code +#!not-a-shebang