From 8d4f01d2847e116c2156f02a869b526859364953 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 12 Nov 2024 12:54:25 +0000 Subject: [PATCH] Add support for page references through new `ref.form` property (#4729) --- crates/typst-layout/src/flow/collect.rs | 2 +- crates/typst-layout/src/flow/compose.rs | 2 +- crates/typst-layout/src/flow/distribute.rs | 2 +- crates/typst-layout/src/inline/shaping.rs | 2 +- crates/typst-layout/src/pages/finalize.rs | 3 +- crates/typst-layout/src/pages/run.rs | 8 +- .../src/introspection/introspector.rs | 12 ++ crates/typst-library/src/layout/page.rs | 20 +++ crates/typst-library/src/model/reference.rs | 166 +++++++++++++----- crates/typst-library/translations/ar.txt | 3 +- crates/typst-library/translations/ca.txt | 1 + crates/typst-library/translations/cs.txt | 3 +- crates/typst-library/translations/da.txt | 3 +- crates/typst-library/translations/de.txt | 3 +- crates/typst-library/translations/en.txt | 3 +- crates/typst-library/translations/es.txt | 3 +- crates/typst-library/translations/et.txt | 3 +- crates/typst-library/translations/fi.txt | 3 +- crates/typst-library/translations/fr.txt | 3 +- crates/typst-library/translations/gl.txt | 1 + crates/typst-library/translations/he.txt | 1 + crates/typst-library/translations/hu.txt | 3 +- crates/typst-library/translations/is.txt | 1 + crates/typst-library/translations/it.txt | 3 +- crates/typst-library/translations/ja.txt | 3 +- crates/typst-library/translations/la.txt | 1 + crates/typst-library/translations/nb.txt | 3 +- crates/typst-library/translations/nl.txt | 3 +- crates/typst-library/translations/nn.txt | 3 +- crates/typst-library/translations/pl.txt | 3 +- crates/typst-library/translations/pt-PT.txt | 3 +- crates/typst-library/translations/pt.txt | 3 +- crates/typst-library/translations/ro.txt | 3 +- crates/typst-library/translations/ru.txt | 3 +- crates/typst-library/translations/sl.txt | 3 +- crates/typst-library/translations/sq.txt | 3 +- crates/typst-library/translations/sr.txt | 3 +- crates/typst-library/translations/sv.txt | 3 +- crates/typst-library/translations/tl.txt | 3 +- crates/typst-library/translations/tr.txt | 3 +- crates/typst-library/translations/uk.txt | 3 +- crates/typst-library/translations/vi.txt | 3 +- crates/typst-library/translations/zh-TW.txt | 3 +- crates/typst-library/translations/zh.txt | 3 +- docs/guides/page-setup.md | 2 +- tests/ref/ref-form-page-unambiguous.png | Bin 0 -> 2859 bytes tests/ref/ref-form-page.png | Bin 0 -> 3592 bytes tests/suite/layout/page.typ | 7 + tests/suite/model/ref.typ | 26 +++ 49 files changed, 270 insertions(+), 77 deletions(-) create mode 100644 tests/ref/ref-form-page-unambiguous.png create mode 100644 tests/ref/ref-form-page.png diff --git a/crates/typst-layout/src/flow/collect.rs b/crates/typst-layout/src/flow/collect.rs index d39743491..49461e809 100644 --- a/crates/typst-layout/src/flow/collect.rs +++ b/crates/typst-layout/src/flow/collect.rs @@ -494,7 +494,7 @@ impl MultiSpill<'_, '_> { engine: &mut Engine, regions: Regions, ) -> SourceResult<(Frame, Option)> { - // The first region becomes unchangable and committed to our backlog. + // The first region becomes unchangeable and committed to our backlog. self.backlog.push(regions.size.y); // The remaining regions are ephemeral and may be replaced. diff --git a/crates/typst-layout/src/flow/compose.rs b/crates/typst-layout/src/flow/compose.rs index d49c3fc32..343b47833 100644 --- a/crates/typst-layout/src/flow/compose.rs +++ b/crates/typst-layout/src/flow/compose.rs @@ -723,7 +723,7 @@ fn layout_line_numbers( continue; } - // Layout the number and record its width in search of the maximium. + // Layout the number and record its width in search of the maximum. let frame = layout_line_number(engine, config, &mut locator, &marker.numbering)?; // Note that this line.y is larger than the previous due to sorting. diff --git a/crates/typst-layout/src/flow/distribute.rs b/crates/typst-layout/src/flow/distribute.rs index 1852f7ca9..5b293d352 100644 --- a/crates/typst-layout/src/flow/distribute.rs +++ b/crates/typst-layout/src/flow/distribute.rs @@ -35,7 +35,7 @@ pub fn distribute(composer: &mut Composer, regions: Regions) -> FlowResult { /// The composer that is used to handle insertions. composer: &'z mut Composer<'a, 'b, 'x, 'y>, - /// Regions which are continously shrunk as new items are added. + /// Regions which are continuously shrunk as new items are added. regions: Regions<'z>, /// Already laid out items, not yet aligned. items: Vec>, diff --git a/crates/typst-layout/src/inline/shaping.rs b/crates/typst-layout/src/inline/shaping.rs index bd803b521..c2b892d82 100644 --- a/crates/typst-layout/src/inline/shaping.rs +++ b/crates/typst-layout/src/inline/shaping.rs @@ -774,7 +774,7 @@ fn shape_segment<'a>( buffer.guess_segment_properties(); // By default, Harfbuzz will create zero-width space glyphs for default - // ignorables. This is probably useful for GUI apps that want noticable + // ignorables. This is probably useful for GUI apps that want noticeable // effects on the cursor for those, but for us it's not useful and hurts // text extraction. buffer.set_flags(BufferFlags::REMOVE_DEFAULT_IGNORABLES); diff --git a/crates/typst-layout/src/pages/finalize.rs b/crates/typst-layout/src/pages/finalize.rs index 8df6cb166..b16d95699 100644 --- a/crates/typst-layout/src/pages/finalize.rs +++ b/crates/typst-layout/src/pages/finalize.rs @@ -23,6 +23,7 @@ pub fn finalize( foreground, fill, numbering, + supplement, }: LayoutedPage, ) -> SourceResult { // If two sided, left becomes inside and right becomes outside. @@ -69,5 +70,5 @@ pub fn finalize( let number = counter.logical(); counter.step(); - Ok(Page { frame, fill, numbering, number }) + Ok(Page { frame, fill, numbering, supplement, number }) } diff --git a/crates/typst-layout/src/pages/run.rs b/crates/typst-layout/src/pages/run.rs index 15735faac..79ff5ab05 100644 --- a/crates/typst-layout/src/pages/run.rs +++ b/crates/typst-layout/src/pages/run.rs @@ -14,7 +14,7 @@ use typst_library::layout::{ }; use typst_library::model::Numbering; use typst_library::routines::{Pair, Routines}; -use typst_library::text::TextElem; +use typst_library::text::{LocalName, TextElem}; use typst_library::visualize::Paint; use typst_library::World; use typst_utils::Numeric; @@ -36,6 +36,7 @@ pub struct LayoutedPage { pub foreground: Option, pub fill: Smart>, pub numbering: Option, + pub supplement: Content, } /// Layout a single page suitable for parity adjustment. @@ -128,6 +129,10 @@ fn layout_page_run_impl( let header_ascent = PageElem::header_ascent_in(styles).relative_to(margin.top); let footer_descent = PageElem::footer_descent_in(styles).relative_to(margin.bottom); let numbering = PageElem::numbering_in(styles); + let supplement = match PageElem::supplement_in(styles) { + Smart::Auto => TextElem::packed(PageElem::local_name_in(styles)), + Smart::Custom(content) => content.unwrap_or_default(), + }; let number_align = PageElem::number_align_in(styles); let binding = PageElem::binding_in(styles).unwrap_or_else(|| match TextElem::dir_in(styles) { @@ -204,6 +209,7 @@ fn layout_page_run_impl( inner, fill: fill.clone(), numbering: numbering.clone(), + supplement: supplement.clone(), header: layout_marginal(header, header_size, Alignment::BOTTOM)?, footer: layout_marginal(footer, footer_size, Alignment::TOP)?, background: layout_marginal(background, full_size, mid)?, diff --git a/crates/typst-library/src/introspection/introspector.rs b/crates/typst-library/src/introspection/introspector.rs index f4eaea304..388d1f00f 100644 --- a/crates/typst-library/src/introspection/introspector.rs +++ b/crates/typst-library/src/introspection/introspector.rs @@ -21,6 +21,8 @@ pub struct Introspector { pages: usize, /// The page numberings, indexed by page number minus 1. page_numberings: Vec>, + /// The page supplements, indexed by page number minus 1. + page_supplements: Vec, /// All introspectable elements. elems: Vec, @@ -266,6 +268,12 @@ impl Introspector { .and_then(|slot| slot.as_ref()) } + /// Gets the page supplement for the given location, if any. + pub fn page_supplement(&self, location: Location) -> Content { + let page = self.page(location); + self.page_supplements.get(page.get() - 1).cloned().unwrap_or_default() + } + /// Try to find a location for an element with the given `key` hash /// that is closest after the `anchor`. /// @@ -339,6 +347,7 @@ impl Clone for QueryCache { #[derive(Default)] struct IntrospectorBuilder { page_numberings: Vec>, + page_supplements: Vec, seen: HashSet, insertions: MultiMap>, keys: MultiMap, @@ -355,11 +364,13 @@ impl IntrospectorBuilder { /// Build the introspector. fn build(mut self, pages: &[Page]) -> Introspector { self.page_numberings.reserve(pages.len()); + self.page_supplements.reserve(pages.len()); // Discover all elements. let mut root = Vec::new(); for (i, page) in pages.iter().enumerate() { self.page_numberings.push(page.numbering.clone()); + self.page_supplements.push(page.supplement.clone()); self.discover( &mut root, &page.frame, @@ -379,6 +390,7 @@ impl IntrospectorBuilder { Introspector { pages: pages.len(), page_numberings: self.page_numberings, + page_supplements: self.page_supplements, elems, keys: self.keys, locations: self.locations, diff --git a/crates/typst-library/src/layout/page.rs b/crates/typst-library/src/layout/page.rs index de278cb68..09aafa7f3 100644 --- a/crates/typst-library/src/layout/page.rs +++ b/crates/typst-library/src/layout/page.rs @@ -17,6 +17,7 @@ use crate::layout::{ Sides, SpecificAlignment, }; use crate::model::Numbering; +use crate::text::LocalName; use crate::visualize::{Color, Paint}; /// Layouts its child onto one or multiple pages. @@ -222,6 +223,19 @@ pub struct PageElem { #[ghost] pub numbering: Option, + /// A supplement for the pages. + /// + /// For page references, this is added before the page number. + /// + /// ```example + /// #set page(numbering: "1.", supplement: [p.]) + /// + /// = Introduction + /// We are on #ref(, form: "page")! + /// ``` + #[ghost] + pub supplement: Smart>, + /// The alignment of the page numbering. /// /// If the vertical component is `top`, the numbering is placed into the @@ -376,6 +390,10 @@ impl Construct for PageElem { } } +impl LocalName for PageElem { + const KEY: &'static str = "page"; +} + /// A manual page break. /// /// Must not be used inside any containers. @@ -449,6 +467,8 @@ pub struct Page { pub fill: Smart>, /// The page's numbering. pub numbering: Option, + /// The page's supplement. + pub supplement: Content, /// The logical page number (controlled by `counter(page)` and may thus not /// match the physical number). pub number: usize, diff --git a/crates/typst-library/src/model/reference.rs b/crates/typst-library/src/model/reference.rs index bc1919d67..96aa2117d 100644 --- a/crates/typst-library/src/model/reference.rs +++ b/crates/typst-library/src/model/reference.rs @@ -4,10 +4,10 @@ use ecow::eco_format; use crate::diag::{bail, At, Hint, SourceResult}; use crate::engine::Engine; use crate::foundations::{ - cast, elem, Content, Context, Func, IntoValue, Label, NativeElement, Packed, Show, - Smart, StyleChain, Synthesize, + cast, elem, Cast, Content, Context, Func, IntoValue, Label, NativeElement, Packed, + Show, Smart, StyleChain, Synthesize, }; -use crate::introspection::{Counter, Locatable}; +use crate::introspection::{Counter, CounterKey, Locatable}; use crate::math::EquationElem; use crate::model::{ BibliographyElem, CiteElem, Destination, Figurable, FootnoteElem, Numbering, @@ -16,22 +16,35 @@ use crate::text::TextElem; /// A reference to a label or bibliography. /// -/// Produces a textual reference to a label. For example, a reference to a -/// heading will yield an appropriate string such as "Section 1" for a reference -/// to the first heading. The references are also links to the respective -/// element. Reference syntax can also be used to [cite] from a bibliography. +/// Takes a label and cross-references it. There are two kind of references, +/// determined by its [`form`]($ref.form): `{"normal"}` and `{"page"}`. /// -/// Referenceable elements include [headings]($heading), [figures]($figure), -/// [equations]($math.equation), and [footnotes]($footnote). To create a custom -/// referenceable element like a theorem, you can create a figure of a custom -/// [`kind`]($figure.kind) and write a show rule for it. In the future, there -/// might be a more direct way to define a custom referenceable element. +/// The default, a `{"normal"}` reference, produces a textual reference to a +/// label. For example, a reference to a heading will yield an appropriate +/// string such as "Section 1" for a reference to the first heading. The +/// references are also links to the respective element. Reference syntax can +/// also be used to [cite] from a bibliography. +/// +/// As the default form requires a supplement and numbering, the label must be +/// attached to a _referenceable element_. Referenceable elements include +/// [headings]($heading), [figures]($figure), [equations]($math.equation), and +/// [footnotes]($footnote). To create a custom referenceable element like a +/// theorem, you can create a figure of a custom [`kind`]($figure.kind) and +/// write a show rule for it. In the future, there might be a more direct way +/// to define a custom referenceable element. /// /// If you just want to link to a labelled element and not get an automatic /// textual reference, consider using the [`link`] function instead. /// +/// A `{"page"}` reference produces a page reference to a label, displaying the +/// page number at its location. You can use the +/// [page's supplement]($page.supplement) to modify the text before the page +/// number. Unlike a `{"normal"}` reference, the label can be attached to any +/// element. +/// /// # Example /// ```example +/// #set page(numbering: "1") /// #set heading(numbering: "1.") /// #set math.equation(numbering: "(1)") /// @@ -40,7 +53,9 @@ use crate::text::TextElem; /// typesetting software have /// rekindled hope in previously /// frustrated researchers. @distress -/// As shown in @results, we ... +/// As shown in @results (see +/// #ref(, form: "page")), +/// we ... /// /// = Results /// We discuss our approach in @@ -55,9 +70,9 @@ use crate::text::TextElem; /// ``` /// /// # Syntax -/// This function also has dedicated syntax: A reference to a label can be -/// created by typing an `@` followed by the name of the label (e.g. -/// `[= Introduction ]` can be referenced by typing `[@intro]`). +/// This function also has dedicated syntax: A `{"normal"}` reference to a +/// label can be created by typing an `@` followed by the name of the label +/// (e.g. `[= Introduction ]` can be referenced by typing `[@intro]`). /// /// To customize the supplement, add content in square brackets after the /// reference: `[@intro[Chapter]]`. @@ -95,22 +110,30 @@ use crate::text::TextElem; pub struct RefElem { /// The target label that should be referenced. /// - /// Can be a label that is defined in the document or an entry from the + /// Can be a label that is defined in the document or, if the + /// [`form`]($ref.form) is set to `["normal"]`, an entry from the /// [`bibliography`]. #[required] pub target: Label, /// A supplement for the reference. /// - /// For references to headings or figures, this is added before the - /// referenced number. For citations, this can be used to add a page number. + /// If the [`form`]($ref.form) is set to `{"normal"}`: + /// - For references to headings or figures, this is added before the + /// referenced number. + /// - For citations, this can be used to add a page number. + /// + /// If the [`form`]($ref.form) is set to `{"page"}`, then this is added + /// before the page number of the label referenced. /// /// If a function is specified, it is passed the referenced element and /// should return content. /// /// ```example /// #set heading(numbering: "1.") - /// #set ref(supplement: it => { + /// #show ref.where( + /// form: "normal" + /// ): set ref(supplement: it => { /// if it.func() == heading { /// "Chapter" /// } else { @@ -127,6 +150,17 @@ pub struct RefElem { #[borrowed] pub supplement: Smart>, + /// The kind of reference to produce. + /// + /// ```example + /// #set page(numbering: "1") + /// + /// Here we are on + /// #ref(, form: "page"). + /// ``` + #[default(RefForm::Normal)] + pub form: RefForm, + /// A synthesized citation. #[synthesized] pub citation: Option>, @@ -167,6 +201,34 @@ impl Show for Packed { let elem = engine.introspector.query_label(target); let span = self.span(); + let form = self.form(styles); + if form == RefForm::Page { + let elem = elem.at(span)?; + let elem = elem.clone(); + + let loc = elem.location().unwrap(); + let numbering = engine + .introspector + .page_numbering(loc) + .ok_or_else(|| eco_format!("cannot reference without page numbering")) + .hint(eco_format!( + "you can enable page numbering with `#set page(numbering: \"1\")`" + )) + .at(span)?; + let supplement = engine.introspector.page_supplement(loc); + + return show_reference( + self, + engine, + styles, + Counter::new(CounterKey::Page), + numbering.clone(), + supplement, + elem, + ); + } + // RefForm::Normal + if BibliographyElem::has(engine, target) { if elem.is_ok() { bail!(span, "label occurs in the document and its bibliography"); @@ -212,31 +274,45 @@ impl Show for Packed { )) .at(span)?; - let loc = elem.location().unwrap(); - let numbers = refable.counter().display_at_loc( + show_reference( + self, engine, - loc, styles, - &numbering.clone().trimmed(), - )?; - - let supplement = match self.supplement(styles).as_ref() { - Smart::Auto => refable.supplement(), - Smart::Custom(None) => Content::empty(), - Smart::Custom(Some(supplement)) => { - supplement.resolve(engine, styles, [elem])? - } - }; - - let mut content = numbers; - if !supplement.is_empty() { - content = supplement + TextElem::packed("\u{a0}") + content; - } - - Ok(content.linked(Destination::Location(loc))) + refable.counter(), + numbering.clone(), + refable.supplement(), + elem, + ) } } +/// Show a reference. +fn show_reference( + reference: &Packed, + engine: &mut Engine, + styles: StyleChain, + counter: Counter, + numbering: Numbering, + supplement: Content, + elem: Content, +) -> SourceResult { + let loc = elem.location().unwrap(); + let numbers = counter.display_at_loc(engine, loc, styles, &numbering.trimmed())?; + + let supplement = match reference.supplement(styles).as_ref() { + Smart::Auto => supplement, + Smart::Custom(None) => Content::empty(), + Smart::Custom(Some(supplement)) => supplement.resolve(engine, styles, [elem])?, + }; + + let mut content = numbers; + if !supplement.is_empty() { + content = supplement + TextElem::packed("\u{a0}") + content; + } + + Ok(content.linked(Destination::Location(loc))) +} + /// Turn a reference into a citation. fn to_citation( reference: &Packed, @@ -293,6 +369,16 @@ cast! { v: Func => Self::Func(v), } +/// The form of the reference. +#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash, Cast)] +pub enum RefForm { + /// Produces a textual reference to a label. + #[default] + Normal, + /// Produces a page reference to a label. + Page, +} + /// Marks an element as being able to be referenced. This is used to implement /// the `@ref` element. pub trait Refable { diff --git a/crates/typst-library/translations/ar.txt b/crates/typst-library/translations/ar.txt index 5c17d379d..6b94dc44c 100644 --- a/crates/typst-library/translations/ar.txt +++ b/crates/typst-library/translations/ar.txt @@ -4,4 +4,5 @@ equation = معادلة bibliography = المراجع heading = الفصل outline = المحتويات -raw = قائمة \ No newline at end of file +raw = قائمة +page = صفحة \ No newline at end of file diff --git a/crates/typst-library/translations/ca.txt b/crates/typst-library/translations/ca.txt index b16d2f9f2..d81645eca 100644 --- a/crates/typst-library/translations/ca.txt +++ b/crates/typst-library/translations/ca.txt @@ -5,3 +5,4 @@ bibliography = Bibliografia heading = Secció outline = Índex raw = Llistat +page = pàgina \ No newline at end of file diff --git a/crates/typst-library/translations/cs.txt b/crates/typst-library/translations/cs.txt index 136705862..d4688ffee 100644 --- a/crates/typst-library/translations/cs.txt +++ b/crates/typst-library/translations/cs.txt @@ -4,4 +4,5 @@ equation = Rovnice bibliography = Bibliografie heading = Kapitola outline = Obsah -raw = Seznam \ No newline at end of file +raw = Seznam +page = strana \ No newline at end of file diff --git a/crates/typst-library/translations/da.txt b/crates/typst-library/translations/da.txt index 9664c3b0b..78d7e601e 100644 --- a/crates/typst-library/translations/da.txt +++ b/crates/typst-library/translations/da.txt @@ -4,4 +4,5 @@ equation = Ligning bibliography = Bibliografi heading = Afsnit outline = Indhold -raw = Liste \ No newline at end of file +raw = Liste +page = side \ No newline at end of file diff --git a/crates/typst-library/translations/de.txt b/crates/typst-library/translations/de.txt index 8ba72adb4..dad785bcd 100644 --- a/crates/typst-library/translations/de.txt +++ b/crates/typst-library/translations/de.txt @@ -4,4 +4,5 @@ equation = Gleichung bibliography = Bibliographie heading = Abschnitt outline = Inhaltsverzeichnis -raw = Listing \ No newline at end of file +raw = Listing +page = Seite \ No newline at end of file diff --git a/crates/typst-library/translations/en.txt b/crates/typst-library/translations/en.txt index 02e7accd1..a4f82c89c 100644 --- a/crates/typst-library/translations/en.txt +++ b/crates/typst-library/translations/en.txt @@ -4,4 +4,5 @@ equation = Equation bibliography = Bibliography heading = Section outline = Contents -raw = Listing \ No newline at end of file +raw = Listing +page = page \ No newline at end of file diff --git a/crates/typst-library/translations/es.txt b/crates/typst-library/translations/es.txt index b0e56642b..6580fb0a6 100644 --- a/crates/typst-library/translations/es.txt +++ b/crates/typst-library/translations/es.txt @@ -4,4 +4,5 @@ equation = Ecuación bibliography = Bibliografía heading = Sección outline = Índice -raw = Listado \ No newline at end of file +raw = Listado +page = página \ No newline at end of file diff --git a/crates/typst-library/translations/et.txt b/crates/typst-library/translations/et.txt index 01f23b4b1..02134eff1 100644 --- a/crates/typst-library/translations/et.txt +++ b/crates/typst-library/translations/et.txt @@ -4,4 +4,5 @@ equation = Valem bibliography = Viited heading = Peatükk outline = Sisukord -raw = List \ No newline at end of file +raw = List +page = lk. \ No newline at end of file diff --git a/crates/typst-library/translations/fi.txt b/crates/typst-library/translations/fi.txt index da516d243..91c943654 100644 --- a/crates/typst-library/translations/fi.txt +++ b/crates/typst-library/translations/fi.txt @@ -4,4 +4,5 @@ equation = Yhtälö bibliography = Viitteet heading = Osio outline = Sisällys -raw = Esimerkki \ No newline at end of file +raw = Esimerkki +page = sivu \ No newline at end of file diff --git a/crates/typst-library/translations/fr.txt b/crates/typst-library/translations/fr.txt index 6c5b60f67..a5b399154 100644 --- a/crates/typst-library/translations/fr.txt +++ b/crates/typst-library/translations/fr.txt @@ -4,4 +4,5 @@ equation = Équation bibliography = Bibliographie heading = Chapitre outline = Table des matières -raw = Liste \ No newline at end of file +raw = Liste +page = page \ No newline at end of file diff --git a/crates/typst-library/translations/gl.txt b/crates/typst-library/translations/gl.txt index 7c26953de..d11269223 100644 --- a/crates/typst-library/translations/gl.txt +++ b/crates/typst-library/translations/gl.txt @@ -5,3 +5,4 @@ bibliography = Bibliografía heading = Sección outline = Índice raw = Listado +page = páxina \ No newline at end of file diff --git a/crates/typst-library/translations/he.txt b/crates/typst-library/translations/he.txt index 7c3705a44..c3ca77120 100644 --- a/crates/typst-library/translations/he.txt +++ b/crates/typst-library/translations/he.txt @@ -5,3 +5,4 @@ bibliography = רשימת מקורות heading = חלק outline = תוכן עניינים raw = קטע מקור +page = עמוד \ No newline at end of file diff --git a/crates/typst-library/translations/hu.txt b/crates/typst-library/translations/hu.txt index f1b616b73..d800688e5 100644 --- a/crates/typst-library/translations/hu.txt +++ b/crates/typst-library/translations/hu.txt @@ -4,4 +4,5 @@ equation = Egyenlet bibliography = Irodalomjegyzék heading = Fejezet outline = Tartalomjegyzék -# raw = \ No newline at end of file +# raw = +page = oldal \ No newline at end of file diff --git a/crates/typst-library/translations/is.txt b/crates/typst-library/translations/is.txt index dcfabacd9..151303eb9 100644 --- a/crates/typst-library/translations/is.txt +++ b/crates/typst-library/translations/is.txt @@ -5,3 +5,4 @@ bibliography = Heimildaskrá heading = Kafli outline = Efnisyfirlit raw = Sýnishorn +page = blaðsíða \ No newline at end of file diff --git a/crates/typst-library/translations/it.txt b/crates/typst-library/translations/it.txt index 4c1cd90c2..f1ee1d339 100644 --- a/crates/typst-library/translations/it.txt +++ b/crates/typst-library/translations/it.txt @@ -4,4 +4,5 @@ equation = Equazione bibliography = Bibliografia heading = Sezione outline = Indice -raw = Codice \ No newline at end of file +raw = Codice +page = pag. \ No newline at end of file diff --git a/crates/typst-library/translations/ja.txt b/crates/typst-library/translations/ja.txt index 6c1f6f9c0..ea3404053 100644 --- a/crates/typst-library/translations/ja.txt +++ b/crates/typst-library/translations/ja.txt @@ -4,4 +4,5 @@ equation = 式 bibliography = 参考文献 heading = 節 outline = 目次 -raw = リスト \ No newline at end of file +raw = リスト +page = ページ \ No newline at end of file diff --git a/crates/typst-library/translations/la.txt b/crates/typst-library/translations/la.txt index 3ec63fffc..eb48d0e91 100644 --- a/crates/typst-library/translations/la.txt +++ b/crates/typst-library/translations/la.txt @@ -5,3 +5,4 @@ bibliography = Conspectus librorum heading = Caput outline = Index capitum raw = Exemplum +page = charta \ No newline at end of file diff --git a/crates/typst-library/translations/nb.txt b/crates/typst-library/translations/nb.txt index f51bcd75a..b6ad00c9b 100644 --- a/crates/typst-library/translations/nb.txt +++ b/crates/typst-library/translations/nb.txt @@ -4,4 +4,5 @@ equation = Ligning bibliography = Bibliografi heading = Kapittel outline = Innhold -raw = Utskrift \ No newline at end of file +raw = Utskrift +page = side \ No newline at end of file diff --git a/crates/typst-library/translations/nl.txt b/crates/typst-library/translations/nl.txt index ecd464b3b..788981faa 100644 --- a/crates/typst-library/translations/nl.txt +++ b/crates/typst-library/translations/nl.txt @@ -4,4 +4,5 @@ equation = Vergelijking bibliography = Bibliografie heading = Hoofdstuk outline = Inhoudsopgave -raw = Listing \ No newline at end of file +raw = Listing +page = pagina \ No newline at end of file diff --git a/crates/typst-library/translations/nn.txt b/crates/typst-library/translations/nn.txt index b067bc56e..565d9a807 100644 --- a/crates/typst-library/translations/nn.txt +++ b/crates/typst-library/translations/nn.txt @@ -4,4 +4,5 @@ equation = Likning bibliography = Bibliografi heading = Kapittel outline = Innhald -raw = Utskrift \ No newline at end of file +raw = Utskrift +page = side \ No newline at end of file diff --git a/crates/typst-library/translations/pl.txt b/crates/typst-library/translations/pl.txt index c49342571..c1b630bbb 100644 --- a/crates/typst-library/translations/pl.txt +++ b/crates/typst-library/translations/pl.txt @@ -4,4 +4,5 @@ equation = Równanie bibliography = Bibliografia heading = Sekcja outline = Spis treści -raw = Program \ No newline at end of file +raw = Program +page = strona \ No newline at end of file diff --git a/crates/typst-library/translations/pt-PT.txt b/crates/typst-library/translations/pt-PT.txt index 6fbb586af..37a64aff2 100644 --- a/crates/typst-library/translations/pt-PT.txt +++ b/crates/typst-library/translations/pt-PT.txt @@ -4,4 +4,5 @@ # bibliography = heading = Secção outline = Índice -# raw = \ No newline at end of file +# raw = +page = página \ No newline at end of file diff --git a/crates/typst-library/translations/pt.txt b/crates/typst-library/translations/pt.txt index a8372e6d0..646d907a7 100644 --- a/crates/typst-library/translations/pt.txt +++ b/crates/typst-library/translations/pt.txt @@ -4,4 +4,5 @@ equation = Equação bibliography = Bibliografia heading = Seção outline = Sumário -raw = Listagem \ No newline at end of file +raw = Listagem +page = página \ No newline at end of file diff --git a/crates/typst-library/translations/ro.txt b/crates/typst-library/translations/ro.txt index 44d6bc8b6..db7466c6a 100644 --- a/crates/typst-library/translations/ro.txt +++ b/crates/typst-library/translations/ro.txt @@ -5,4 +5,5 @@ bibliography = Bibliografie heading = Secțiunea outline = Cuprins # may be wrong -raw = Listă \ No newline at end of file +raw = Listă +page = pagina \ No newline at end of file diff --git a/crates/typst-library/translations/ru.txt b/crates/typst-library/translations/ru.txt index fccf7bc9a..0e774e7bc 100644 --- a/crates/typst-library/translations/ru.txt +++ b/crates/typst-library/translations/ru.txt @@ -4,4 +4,5 @@ equation = Уравнение bibliography = Библиография heading = Раздел outline = Содержание -raw = Листинг \ No newline at end of file +raw = Листинг +page = с. \ No newline at end of file diff --git a/crates/typst-library/translations/sl.txt b/crates/typst-library/translations/sl.txt index 1375c4dda..1b0adf664 100644 --- a/crates/typst-library/translations/sl.txt +++ b/crates/typst-library/translations/sl.txt @@ -4,4 +4,5 @@ equation = Enačba bibliography = Literatura heading = Poglavje outline = Kazalo -raw = Program \ No newline at end of file +raw = Program +page = stran \ No newline at end of file diff --git a/crates/typst-library/translations/sq.txt b/crates/typst-library/translations/sq.txt index 3b4295458..396ce69a0 100644 --- a/crates/typst-library/translations/sq.txt +++ b/crates/typst-library/translations/sq.txt @@ -4,4 +4,5 @@ equation = Ekuacion bibliography = Bibliografi heading = Kapitull outline = Përmbajtja -raw = List \ No newline at end of file +raw = List +page = faqe \ No newline at end of file diff --git a/crates/typst-library/translations/sr.txt b/crates/typst-library/translations/sr.txt index 3a2f92b9b..bd13807b0 100644 --- a/crates/typst-library/translations/sr.txt +++ b/crates/typst-library/translations/sr.txt @@ -4,4 +4,5 @@ equation = Једначина bibliography = Литература heading = Поглавље outline = Садржај -raw = Програм \ No newline at end of file +raw = Програм +page = страна \ No newline at end of file diff --git a/crates/typst-library/translations/sv.txt b/crates/typst-library/translations/sv.txt index 61a394038..079f58463 100644 --- a/crates/typst-library/translations/sv.txt +++ b/crates/typst-library/translations/sv.txt @@ -4,4 +4,5 @@ equation = Ekvation bibliography = Bibliografi heading = Kapitel outline = Innehåll -raw = Listing \ No newline at end of file +raw = Listing +page = sida \ No newline at end of file diff --git a/crates/typst-library/translations/tl.txt b/crates/typst-library/translations/tl.txt index a7b6b5712..1fd15a020 100644 --- a/crates/typst-library/translations/tl.txt +++ b/crates/typst-library/translations/tl.txt @@ -4,4 +4,5 @@ equation = Ekwasyon bibliography = Bibliograpiya heading = Seksyon outline = Talaan ng mga Nilalaman -raw = Listahan \ No newline at end of file +raw = Listahan +# page = \ No newline at end of file diff --git a/crates/typst-library/translations/tr.txt b/crates/typst-library/translations/tr.txt index a7068a4f1..2419a0d4f 100644 --- a/crates/typst-library/translations/tr.txt +++ b/crates/typst-library/translations/tr.txt @@ -4,4 +4,5 @@ equation = Denklem bibliography = Kaynakça heading = Bölüm outline = İçindekiler -raw = Liste \ No newline at end of file +raw = Liste +page = sayfa \ No newline at end of file diff --git a/crates/typst-library/translations/uk.txt b/crates/typst-library/translations/uk.txt index 30b409a6d..bced3a520 100644 --- a/crates/typst-library/translations/uk.txt +++ b/crates/typst-library/translations/uk.txt @@ -4,4 +4,5 @@ equation = Рівняння bibliography = Бібліографія heading = Розділ outline = Зміст -raw = Лістинг \ No newline at end of file +raw = Лістинг +page = c. \ No newline at end of file diff --git a/crates/typst-library/translations/vi.txt b/crates/typst-library/translations/vi.txt index a65ac09ab..41748abee 100644 --- a/crates/typst-library/translations/vi.txt +++ b/crates/typst-library/translations/vi.txt @@ -5,4 +5,5 @@ bibliography = Tài liệu tham khảo heading = Phần outline = Mục lục # may be wrong -raw = Chương trình \ No newline at end of file +raw = Chương trình +page = trang \ No newline at end of file diff --git a/crates/typst-library/translations/zh-TW.txt b/crates/typst-library/translations/zh-TW.txt index af6d59506..457a7fba9 100644 --- a/crates/typst-library/translations/zh-TW.txt +++ b/crates/typst-library/translations/zh-TW.txt @@ -4,4 +4,5 @@ equation = 式 bibliography = 書目 heading = 小節 outline = 目錄 -raw = 程式 \ No newline at end of file +raw = 程式 +# page = \ No newline at end of file diff --git a/crates/typst-library/translations/zh.txt b/crates/typst-library/translations/zh.txt index d4b86544d..948edd53d 100644 --- a/crates/typst-library/translations/zh.txt +++ b/crates/typst-library/translations/zh.txt @@ -4,4 +4,5 @@ equation = 式 bibliography = 参考文献 heading = 小节 outline = 目录 -raw = 代码 \ No newline at end of file +raw = 代码 +# page = \ No newline at end of file diff --git a/docs/guides/page-setup.md b/docs/guides/page-setup.md index d4a1e62c8..c93a778e2 100644 --- a/docs/guides/page-setup.md +++ b/docs/guides/page-setup.md @@ -433,7 +433,7 @@ frequently used for [figures]($figure.placement). ### Use columns anywhere in your document { #columns-anywhere } To create columns within a nested layout, e.g. within a rectangle, you can use the [`columns` function]($columns) directly. However, it really should only be -used within nested layouts. At the page-level, the page set rule is preferrable +used within nested layouts. At the page-level, the page set rule is preferable because it has better interactions with things like page-level floats, footnotes, and line numbers. diff --git a/tests/ref/ref-form-page-unambiguous.png b/tests/ref/ref-form-page-unambiguous.png new file mode 100644 index 0000000000000000000000000000000000000000..e7baa2f2ca7c99f8b6edfbe87486662b1942eda0 GIT binary patch literal 2859 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 JPDHLkV1fk7YZ3qe literal 0 HcmV?d00001 diff --git a/tests/ref/ref-form-page.png b/tests/ref/ref-form-page.png new file mode 100644 index 0000000000000000000000000000000000000000..52fde86d742c523fcf60dc5b6f6932236dac92b6 GIT binary patch literal 3592 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 + +// Error: 1:21-1:47 cannot reference without page numbering +// Hint: 1:21-1:47 you can enable page numbering with `#set page(numbering: "1")` +Can not be used as #ref(, form: "page") + --- page-suppress-headers-and-footers --- #set page(header: none, footer: none, numbering: "1") Look, ma, no page numbers! diff --git a/tests/suite/model/ref.typ b/tests/suite/model/ref.typ index cc6d6bf11..2f8e2fa25 100644 --- a/tests/suite/model/ref.typ +++ b/tests/suite/model/ref.typ @@ -55,6 +55,32 @@ $ A = 1 $ @arrgh #bibliography("/assets/bib/works.bib") +--- ref-form-page --- +#set page(numbering: "1") + +Text is on #ref(, form: "page"). +See #ref(, form: "page"). + +#set page(supplement: [p.]) + +== Setup +Text seen on #ref(, form: "page"). +Text seen on #ref(, form: "page", supplement: "Page"). + +--- ref-form-page-unambiguous --- +// Test that page reference is not ambiguous. +#set page(numbering: "1") + += Introduction + +#ref(, form: "page") +#bibliography("/assets/bib/works.bib") + +--- ref-form-page-bibliography --- +// Error: 2-28 label `` does not exist in the document +#ref(, form: "page") +#bibliography("/assets/bib/works.bib") + --- issue-4536-non-whitespace-before-ref --- // Test reference with non-whitespace before it. #figure[] <1>