Add support for page references through new ref.form property (#4729)

This commit is contained in:
Max 2024-11-12 12:54:25 +00:00 committed by GitHub
parent dadc2176e2
commit 8d4f01d284
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 270 additions and 77 deletions

View File

@ -494,7 +494,7 @@ impl MultiSpill<'_, '_> {
engine: &mut Engine, engine: &mut Engine,
regions: Regions, regions: Regions,
) -> SourceResult<(Frame, Option<Self>)> { ) -> SourceResult<(Frame, Option<Self>)> {
// 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); self.backlog.push(regions.size.y);
// The remaining regions are ephemeral and may be replaced. // The remaining regions are ephemeral and may be replaced.

View File

@ -723,7 +723,7 @@ fn layout_line_numbers(
continue; 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)?; let frame = layout_line_number(engine, config, &mut locator, &marker.numbering)?;
// Note that this line.y is larger than the previous due to sorting. // Note that this line.y is larger than the previous due to sorting.

View File

@ -35,7 +35,7 @@ pub fn distribute(composer: &mut Composer, regions: Regions) -> FlowResult<Frame
struct Distributor<'a, 'b, 'x, 'y, 'z> { struct Distributor<'a, 'b, 'x, 'y, 'z> {
/// The composer that is used to handle insertions. /// The composer that is used to handle insertions.
composer: &'z mut Composer<'a, 'b, 'x, 'y>, 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>, regions: Regions<'z>,
/// Already laid out items, not yet aligned. /// Already laid out items, not yet aligned.
items: Vec<Item<'a, 'b>>, items: Vec<Item<'a, 'b>>,

View File

@ -774,7 +774,7 @@ fn shape_segment<'a>(
buffer.guess_segment_properties(); buffer.guess_segment_properties();
// By default, Harfbuzz will create zero-width space glyphs for default // 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 // effects on the cursor for those, but for us it's not useful and hurts
// text extraction. // text extraction.
buffer.set_flags(BufferFlags::REMOVE_DEFAULT_IGNORABLES); buffer.set_flags(BufferFlags::REMOVE_DEFAULT_IGNORABLES);

View File

@ -23,6 +23,7 @@ pub fn finalize(
foreground, foreground,
fill, fill,
numbering, numbering,
supplement,
}: LayoutedPage, }: LayoutedPage,
) -> SourceResult<Page> { ) -> SourceResult<Page> {
// If two sided, left becomes inside and right becomes outside. // If two sided, left becomes inside and right becomes outside.
@ -69,5 +70,5 @@ pub fn finalize(
let number = counter.logical(); let number = counter.logical();
counter.step(); counter.step();
Ok(Page { frame, fill, numbering, number }) Ok(Page { frame, fill, numbering, supplement, number })
} }

View File

@ -14,7 +14,7 @@ use typst_library::layout::{
}; };
use typst_library::model::Numbering; use typst_library::model::Numbering;
use typst_library::routines::{Pair, Routines}; 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::visualize::Paint;
use typst_library::World; use typst_library::World;
use typst_utils::Numeric; use typst_utils::Numeric;
@ -36,6 +36,7 @@ pub struct LayoutedPage {
pub foreground: Option<Frame>, pub foreground: Option<Frame>,
pub fill: Smart<Option<Paint>>, pub fill: Smart<Option<Paint>>,
pub numbering: Option<Numbering>, pub numbering: Option<Numbering>,
pub supplement: Content,
} }
/// Layout a single page suitable for parity adjustment. /// 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 header_ascent = PageElem::header_ascent_in(styles).relative_to(margin.top);
let footer_descent = PageElem::footer_descent_in(styles).relative_to(margin.bottom); let footer_descent = PageElem::footer_descent_in(styles).relative_to(margin.bottom);
let numbering = PageElem::numbering_in(styles); 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 number_align = PageElem::number_align_in(styles);
let binding = let binding =
PageElem::binding_in(styles).unwrap_or_else(|| match TextElem::dir_in(styles) { PageElem::binding_in(styles).unwrap_or_else(|| match TextElem::dir_in(styles) {
@ -204,6 +209,7 @@ fn layout_page_run_impl(
inner, inner,
fill: fill.clone(), fill: fill.clone(),
numbering: numbering.clone(), numbering: numbering.clone(),
supplement: supplement.clone(),
header: layout_marginal(header, header_size, Alignment::BOTTOM)?, header: layout_marginal(header, header_size, Alignment::BOTTOM)?,
footer: layout_marginal(footer, footer_size, Alignment::TOP)?, footer: layout_marginal(footer, footer_size, Alignment::TOP)?,
background: layout_marginal(background, full_size, mid)?, background: layout_marginal(background, full_size, mid)?,

View File

@ -21,6 +21,8 @@ pub struct Introspector {
pages: usize, pages: usize,
/// The page numberings, indexed by page number minus 1. /// The page numberings, indexed by page number minus 1.
page_numberings: Vec<Option<Numbering>>, page_numberings: Vec<Option<Numbering>>,
/// The page supplements, indexed by page number minus 1.
page_supplements: Vec<Content>,
/// All introspectable elements. /// All introspectable elements.
elems: Vec<Pair>, elems: Vec<Pair>,
@ -266,6 +268,12 @@ impl Introspector {
.and_then(|slot| slot.as_ref()) .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 /// Try to find a location for an element with the given `key` hash
/// that is closest after the `anchor`. /// that is closest after the `anchor`.
/// ///
@ -339,6 +347,7 @@ impl Clone for QueryCache {
#[derive(Default)] #[derive(Default)]
struct IntrospectorBuilder { struct IntrospectorBuilder {
page_numberings: Vec<Option<Numbering>>, page_numberings: Vec<Option<Numbering>>,
page_supplements: Vec<Content>,
seen: HashSet<Location>, seen: HashSet<Location>,
insertions: MultiMap<Location, Vec<Pair>>, insertions: MultiMap<Location, Vec<Pair>>,
keys: MultiMap<u128, Location>, keys: MultiMap<u128, Location>,
@ -355,11 +364,13 @@ impl IntrospectorBuilder {
/// Build the introspector. /// Build the introspector.
fn build(mut self, pages: &[Page]) -> Introspector { fn build(mut self, pages: &[Page]) -> Introspector {
self.page_numberings.reserve(pages.len()); self.page_numberings.reserve(pages.len());
self.page_supplements.reserve(pages.len());
// Discover all elements. // Discover all elements.
let mut root = Vec::new(); let mut root = Vec::new();
for (i, page) in pages.iter().enumerate() { for (i, page) in pages.iter().enumerate() {
self.page_numberings.push(page.numbering.clone()); self.page_numberings.push(page.numbering.clone());
self.page_supplements.push(page.supplement.clone());
self.discover( self.discover(
&mut root, &mut root,
&page.frame, &page.frame,
@ -379,6 +390,7 @@ impl IntrospectorBuilder {
Introspector { Introspector {
pages: pages.len(), pages: pages.len(),
page_numberings: self.page_numberings, page_numberings: self.page_numberings,
page_supplements: self.page_supplements,
elems, elems,
keys: self.keys, keys: self.keys,
locations: self.locations, locations: self.locations,

View File

@ -17,6 +17,7 @@ use crate::layout::{
Sides, SpecificAlignment, Sides, SpecificAlignment,
}; };
use crate::model::Numbering; use crate::model::Numbering;
use crate::text::LocalName;
use crate::visualize::{Color, Paint}; use crate::visualize::{Color, Paint};
/// Layouts its child onto one or multiple pages. /// Layouts its child onto one or multiple pages.
@ -222,6 +223,19 @@ pub struct PageElem {
#[ghost] #[ghost]
pub numbering: Option<Numbering>, pub numbering: Option<Numbering>,
/// A supplement for the pages.
///
/// For page references, this is added before the page number.
///
/// ```example
/// #set page(numbering: "1.", supplement: [p.])
///
/// = Introduction <intro>
/// We are on #ref(<intro>, form: "page")!
/// ```
#[ghost]
pub supplement: Smart<Option<Content>>,
/// The alignment of the page numbering. /// The alignment of the page numbering.
/// ///
/// If the vertical component is `top`, the numbering is placed into the /// 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. /// A manual page break.
/// ///
/// Must not be used inside any containers. /// Must not be used inside any containers.
@ -449,6 +467,8 @@ pub struct Page {
pub fill: Smart<Option<Paint>>, pub fill: Smart<Option<Paint>>,
/// The page's numbering. /// The page's numbering.
pub numbering: Option<Numbering>, pub numbering: Option<Numbering>,
/// The page's supplement.
pub supplement: Content,
/// The logical page number (controlled by `counter(page)` and may thus not /// The logical page number (controlled by `counter(page)` and may thus not
/// match the physical number). /// match the physical number).
pub number: usize, pub number: usize,

View File

@ -4,10 +4,10 @@ use ecow::eco_format;
use crate::diag::{bail, At, Hint, SourceResult}; use crate::diag::{bail, At, Hint, SourceResult};
use crate::engine::Engine; use crate::engine::Engine;
use crate::foundations::{ use crate::foundations::{
cast, elem, Content, Context, Func, IntoValue, Label, NativeElement, Packed, Show, cast, elem, Cast, Content, Context, Func, IntoValue, Label, NativeElement, Packed,
Smart, StyleChain, Synthesize, Show, Smart, StyleChain, Synthesize,
}; };
use crate::introspection::{Counter, Locatable}; use crate::introspection::{Counter, CounterKey, Locatable};
use crate::math::EquationElem; use crate::math::EquationElem;
use crate::model::{ use crate::model::{
BibliographyElem, CiteElem, Destination, Figurable, FootnoteElem, Numbering, BibliographyElem, CiteElem, Destination, Figurable, FootnoteElem, Numbering,
@ -16,22 +16,35 @@ use crate::text::TextElem;
/// A reference to a label or bibliography. /// A reference to a label or bibliography.
/// ///
/// Produces a textual reference to a label. For example, a reference to a /// Takes a label and cross-references it. There are two kind of references,
/// heading will yield an appropriate string such as "Section 1" for a reference /// determined by its [`form`]($ref.form): `{"normal"}` and `{"page"}`.
/// to the first heading. The references are also links to the respective
/// element. Reference syntax can also be used to [cite] from a bibliography.
/// ///
/// Referenceable elements include [headings]($heading), [figures]($figure), /// The default, a `{"normal"}` reference, produces a textual reference to a
/// [equations]($math.equation), and [footnotes]($footnote). To create a custom /// label. For example, a reference to a heading will yield an appropriate
/// referenceable element like a theorem, you can create a figure of a custom /// string such as "Section 1" for a reference to the first heading. The
/// [`kind`]($figure.kind) and write a show rule for it. In the future, there /// references are also links to the respective element. Reference syntax can
/// might be a more direct way to define a custom referenceable element. /// 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 /// If you just want to link to a labelled element and not get an automatic
/// textual reference, consider using the [`link`] function instead. /// 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
/// ```example /// ```example
/// #set page(numbering: "1")
/// #set heading(numbering: "1.") /// #set heading(numbering: "1.")
/// #set math.equation(numbering: "(1)") /// #set math.equation(numbering: "(1)")
/// ///
@ -40,7 +53,9 @@ use crate::text::TextElem;
/// typesetting software have /// typesetting software have
/// rekindled hope in previously /// rekindled hope in previously
/// frustrated researchers. @distress /// frustrated researchers. @distress
/// As shown in @results, we ... /// As shown in @results (see
/// #ref(<results>, form: "page")),
/// we ...
/// ///
/// = Results <results> /// = Results <results>
/// We discuss our approach in /// We discuss our approach in
@ -55,9 +70,9 @@ use crate::text::TextElem;
/// ``` /// ```
/// ///
/// # Syntax /// # Syntax
/// This function also has dedicated syntax: A reference to a label can be /// This function also has dedicated syntax: A `{"normal"}` reference to a
/// created by typing an `@` followed by the name of the label (e.g. /// label can be created by typing an `@` followed by the name of the label
/// `[= Introduction <intro>]` can be referenced by typing `[@intro]`). /// (e.g. `[= Introduction <intro>]` can be referenced by typing `[@intro]`).
/// ///
/// To customize the supplement, add content in square brackets after the /// To customize the supplement, add content in square brackets after the
/// reference: `[@intro[Chapter]]`. /// reference: `[@intro[Chapter]]`.
@ -95,22 +110,30 @@ use crate::text::TextElem;
pub struct RefElem { pub struct RefElem {
/// The target label that should be referenced. /// 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`]. /// [`bibliography`].
#[required] #[required]
pub target: Label, pub target: Label,
/// A supplement for the reference. /// A supplement for the reference.
/// ///
/// For references to headings or figures, this is added before the /// If the [`form`]($ref.form) is set to `{"normal"}`:
/// referenced number. For citations, this can be used to add a page number. /// - 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 /// If a function is specified, it is passed the referenced element and
/// should return content. /// should return content.
/// ///
/// ```example /// ```example
/// #set heading(numbering: "1.") /// #set heading(numbering: "1.")
/// #set ref(supplement: it => { /// #show ref.where(
/// form: "normal"
/// ): set ref(supplement: it => {
/// if it.func() == heading { /// if it.func() == heading {
/// "Chapter" /// "Chapter"
/// } else { /// } else {
@ -127,6 +150,17 @@ pub struct RefElem {
#[borrowed] #[borrowed]
pub supplement: Smart<Option<Supplement>>, pub supplement: Smart<Option<Supplement>>,
/// The kind of reference to produce.
///
/// ```example
/// #set page(numbering: "1")
///
/// Here <here> we are on
/// #ref(<here>, form: "page").
/// ```
#[default(RefForm::Normal)]
pub form: RefForm,
/// A synthesized citation. /// A synthesized citation.
#[synthesized] #[synthesized]
pub citation: Option<Packed<CiteElem>>, pub citation: Option<Packed<CiteElem>>,
@ -167,6 +201,34 @@ impl Show for Packed<RefElem> {
let elem = engine.introspector.query_label(target); let elem = engine.introspector.query_label(target);
let span = self.span(); 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 BibliographyElem::has(engine, target) {
if elem.is_ok() { if elem.is_ok() {
bail!(span, "label occurs in the document and its bibliography"); bail!(span, "label occurs in the document and its bibliography");
@ -212,20 +274,35 @@ impl Show for Packed<RefElem> {
)) ))
.at(span)?; .at(span)?;
let loc = elem.location().unwrap(); show_reference(
let numbers = refable.counter().display_at_loc( self,
engine, engine,
loc,
styles, styles,
&numbering.clone().trimmed(), refable.counter(),
)?; numbering.clone(),
refable.supplement(),
let supplement = match self.supplement(styles).as_ref() { elem,
Smart::Auto => refable.supplement(), )
Smart::Custom(None) => Content::empty(),
Smart::Custom(Some(supplement)) => {
supplement.resolve(engine, styles, [elem])?
} }
}
/// Show a reference.
fn show_reference(
reference: &Packed<RefElem>,
engine: &mut Engine,
styles: StyleChain,
counter: Counter,
numbering: Numbering,
supplement: Content,
elem: Content,
) -> SourceResult<Content> {
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; let mut content = numbers;
@ -234,7 +311,6 @@ impl Show for Packed<RefElem> {
} }
Ok(content.linked(Destination::Location(loc))) Ok(content.linked(Destination::Location(loc)))
}
} }
/// Turn a reference into a citation. /// Turn a reference into a citation.
@ -293,6 +369,16 @@ cast! {
v: Func => Self::Func(v), 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 /// Marks an element as being able to be referenced. This is used to implement
/// the `@ref` element. /// the `@ref` element.
pub trait Refable { pub trait Refable {

View File

@ -5,3 +5,4 @@ bibliography = المراجع
heading = الفصل heading = الفصل
outline = المحتويات outline = المحتويات
raw = قائمة raw = قائمة
page = صفحة

View File

@ -5,3 +5,4 @@ bibliography = Bibliografia
heading = Secció heading = Secció
outline = Índex outline = Índex
raw = Llistat raw = Llistat
page = pàgina

View File

@ -5,3 +5,4 @@ bibliography = Bibliografie
heading = Kapitola heading = Kapitola
outline = Obsah outline = Obsah
raw = Seznam raw = Seznam
page = strana

View File

@ -5,3 +5,4 @@ bibliography = Bibliografi
heading = Afsnit heading = Afsnit
outline = Indhold outline = Indhold
raw = Liste raw = Liste
page = side

View File

@ -5,3 +5,4 @@ bibliography = Bibliographie
heading = Abschnitt heading = Abschnitt
outline = Inhaltsverzeichnis outline = Inhaltsverzeichnis
raw = Listing raw = Listing
page = Seite

View File

@ -5,3 +5,4 @@ bibliography = Bibliography
heading = Section heading = Section
outline = Contents outline = Contents
raw = Listing raw = Listing
page = page

View File

@ -5,3 +5,4 @@ bibliography = Bibliografía
heading = Sección heading = Sección
outline = Índice outline = Índice
raw = Listado raw = Listado
page = página

View File

@ -5,3 +5,4 @@ bibliography = Viited
heading = Peatükk heading = Peatükk
outline = Sisukord outline = Sisukord
raw = List raw = List
page = lk.

View File

@ -5,3 +5,4 @@ bibliography = Viitteet
heading = Osio heading = Osio
outline = Sisällys outline = Sisällys
raw = Esimerkki raw = Esimerkki
page = sivu

View File

@ -5,3 +5,4 @@ bibliography = Bibliographie
heading = Chapitre heading = Chapitre
outline = Table des matières outline = Table des matières
raw = Liste raw = Liste
page = page

View File

@ -5,3 +5,4 @@ bibliography = Bibliografía
heading = Sección heading = Sección
outline = Índice outline = Índice
raw = Listado raw = Listado
page = páxina

View File

@ -5,3 +5,4 @@ bibliography = רשימת מקורות
heading = חלק heading = חלק
outline = תוכן עניינים outline = תוכן עניינים
raw = קטע מקור raw = קטע מקור
page = עמוד

View File

@ -5,3 +5,4 @@ bibliography = Irodalomjegyzék
heading = Fejezet heading = Fejezet
outline = Tartalomjegyzék outline = Tartalomjegyzék
# raw = # raw =
page = oldal

View File

@ -5,3 +5,4 @@ bibliography = Heimildaskrá
heading = Kafli heading = Kafli
outline = Efnisyfirlit outline = Efnisyfirlit
raw = Sýnishorn raw = Sýnishorn
page = blaðsíða

View File

@ -5,3 +5,4 @@ bibliography = Bibliografia
heading = Sezione heading = Sezione
outline = Indice outline = Indice
raw = Codice raw = Codice
page = pag.

View File

@ -5,3 +5,4 @@ bibliography = 参考文献
heading = 節 heading = 節
outline = 目次 outline = 目次
raw = リスト raw = リスト
page = ページ

View File

@ -5,3 +5,4 @@ bibliography = Conspectus librorum
heading = Caput heading = Caput
outline = Index capitum outline = Index capitum
raw = Exemplum raw = Exemplum
page = charta

View File

@ -5,3 +5,4 @@ bibliography = Bibliografi
heading = Kapittel heading = Kapittel
outline = Innhold outline = Innhold
raw = Utskrift raw = Utskrift
page = side

View File

@ -5,3 +5,4 @@ bibliography = Bibliografie
heading = Hoofdstuk heading = Hoofdstuk
outline = Inhoudsopgave outline = Inhoudsopgave
raw = Listing raw = Listing
page = pagina

View File

@ -5,3 +5,4 @@ bibliography = Bibliografi
heading = Kapittel heading = Kapittel
outline = Innhald outline = Innhald
raw = Utskrift raw = Utskrift
page = side

View File

@ -5,3 +5,4 @@ bibliography = Bibliografia
heading = Sekcja heading = Sekcja
outline = Spis treści outline = Spis treści
raw = Program raw = Program
page = strona

View File

@ -5,3 +5,4 @@
heading = Secção heading = Secção
outline = Índice outline = Índice
# raw = # raw =
page = página

View File

@ -5,3 +5,4 @@ bibliography = Bibliografia
heading = Seção heading = Seção
outline = Sumário outline = Sumário
raw = Listagem raw = Listagem
page = página

View File

@ -6,3 +6,4 @@ heading = Secțiunea
outline = Cuprins outline = Cuprins
# may be wrong # may be wrong
raw = Listă raw = Listă
page = pagina

View File

@ -5,3 +5,4 @@ bibliography = Библиография
heading = Раздел heading = Раздел
outline = Содержание outline = Содержание
raw = Листинг raw = Листинг
page = с.

View File

@ -5,3 +5,4 @@ bibliography = Literatura
heading = Poglavje heading = Poglavje
outline = Kazalo outline = Kazalo
raw = Program raw = Program
page = stran

View File

@ -5,3 +5,4 @@ bibliography = Bibliografi
heading = Kapitull heading = Kapitull
outline = Përmbajtja outline = Përmbajtja
raw = List raw = List
page = faqe

View File

@ -5,3 +5,4 @@ bibliography = Литература
heading = Поглавље heading = Поглавље
outline = Садржај outline = Садржај
raw = Програм raw = Програм
page = страна

View File

@ -5,3 +5,4 @@ bibliography = Bibliografi
heading = Kapitel heading = Kapitel
outline = Innehåll outline = Innehåll
raw = Listing raw = Listing
page = sida

View File

@ -5,3 +5,4 @@ bibliography = Bibliograpiya
heading = Seksyon heading = Seksyon
outline = Talaan ng mga Nilalaman outline = Talaan ng mga Nilalaman
raw = Listahan raw = Listahan
# page =

View File

@ -5,3 +5,4 @@ bibliography = Kaynakça
heading = Bölüm heading = Bölüm
outline = İçindekiler outline = İçindekiler
raw = Liste raw = Liste
page = sayfa

View File

@ -5,3 +5,4 @@ bibliography = Бібліографія
heading = Розділ heading = Розділ
outline = Зміст outline = Зміст
raw = Лістинг raw = Лістинг
page = c.

View File

@ -6,3 +6,4 @@ heading = Phần
outline = Mục lục outline = Mục lục
# may be wrong # may be wrong
raw = Chương trình raw = Chương trình
page = trang

View File

@ -5,3 +5,4 @@ bibliography = 書目
heading = 小節 heading = 小節
outline = 目錄 outline = 目錄
raw = 程式 raw = 程式
# page =

View File

@ -5,3 +5,4 @@ bibliography = 参考文献
heading = 小节 heading = 小节
outline = 目录 outline = 目录
raw = 代码 raw = 代码
# page =

View File

@ -433,7 +433,7 @@ frequently used for [figures]($figure.placement).
### Use columns anywhere in your document { #columns-anywhere } ### Use columns anywhere in your document { #columns-anywhere }
To create columns within a nested layout, e.g. within a rectangle, you can use 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 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, because it has better interactions with things like page-level floats,
footnotes, and line numbers. footnotes, and line numbers.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
tests/ref/ref-form-page.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -230,6 +230,13 @@ Z
#counter(page).update(53) #counter(page).update(53)
#filler #filler
--- page-numbering-hint ---
= Heading <intro>
// 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(<intro>, form: "page")
--- page-suppress-headers-and-footers --- --- page-suppress-headers-and-footers ---
#set page(header: none, footer: none, numbering: "1") #set page(header: none, footer: none, numbering: "1")
Look, ma, no page numbers! Look, ma, no page numbers!

View File

@ -55,6 +55,32 @@ $ A = 1 $ <eq2>
@arrgh @arrgh
#bibliography("/assets/bib/works.bib") #bibliography("/assets/bib/works.bib")
--- ref-form-page ---
#set page(numbering: "1")
Text <text> is on #ref(<text>, form: "page").
See #ref(<setup>, form: "page").
#set page(supplement: [p.])
== Setup <setup>
Text seen on #ref(<text>, form: "page").
Text seen on #ref(<text>, form: "page", supplement: "Page").
--- ref-form-page-unambiguous ---
// Test that page reference is not ambiguous.
#set page(numbering: "1")
= Introduction <arrgh>
#ref(<arrgh>, form: "page")
#bibliography("/assets/bib/works.bib")
--- ref-form-page-bibliography ---
// Error: 2-28 label `<quark>` does not exist in the document
#ref(<quark>, form: "page")
#bibliography("/assets/bib/works.bib")
--- issue-4536-non-whitespace-before-ref --- --- issue-4536-non-whitespace-before-ref ---
// Test reference with non-whitespace before it. // Test reference with non-whitespace before it.
#figure[] <1> #figure[] <1>