Page function docs and more

This commit is contained in:
Martin Haug 2022-12-21 12:01:28 +01:00
parent 633d0b62c3
commit 959df6da3b
12 changed files with 330 additions and 94 deletions

View File

@ -43,7 +43,7 @@ pub fn lorem(args: &mut Args) -> SourceResult<Value> {
/// ## Example
/// ```
/// #numbering("1.1)", 1, 2, 3) \
/// #numbering("1.b.i", 1, 2) \
/// #numbering("1.a.i", 1, 2) \
/// #numbering("I 1", 12, 2)
/// ```
///

View File

@ -32,6 +32,7 @@ use crate::prelude::*;
///
/// ### Example
/// ```
/// #set page(height: 6cm)
/// #set text(lang: "ar")
///
/// مثال

View File

@ -4,7 +4,7 @@ use crate::text::TextNode;
/// # Columns
/// Separate a region into multiple equally sized columns.
///
/// The column function allows to separate the interior of any container into
/// The `column` function allows to separate the interior of any container into
/// multiple columns. It will not equalize the height of the columns, instead,
/// the columns will take up the height of their container or the remaining
/// height on the page. The columns function can break across pages if
@ -12,8 +12,7 @@ use crate::text::TextNode;
///
/// ## Example
/// ```
/// = [An extraordinarily
/// long heading]
/// = Towards Advanced Deep Learning
///
/// #box(height: 68pt,
/// columns(2, gutter: 11pt)[
@ -176,7 +175,7 @@ impl Layout for ColumnsNode {
///
/// ## Parameters
/// - weak: bool (named)
/// If true, the column break is skipped if the current column is already
/// If `{true}`, the column break is skipped if the current column is already
/// empty.
///
/// ## Category

View File

@ -5,10 +5,14 @@ use crate::prelude::*;
/// # Box
/// An inline-level container that sizes content.
///
/// Normally, all elements except inline math, text, and boxes are block-level
/// and cannot occur inside of a paragraph. The box element allows you to create
/// inline-level containers. Boxes take the size of their contents by default
/// but can also be sized explicitly.
/// All elements except inline math, text, and boxes are block-level and cannot
/// occur inside of a paragraph. The box element is an inline-level container.
/// Boxes take the size of their contents by default but can also be sized
/// explicitly.
///
/// _Note:_ While the behavior above will be the default in the future, the
/// transformation functions [`scale`](@scale), [`rotate`](@rotate), and
/// [`move`](@move) will currently yield inline nodes within paragraphs.
///
/// ## Example
/// ```
@ -102,7 +106,7 @@ impl Inline for BoxNode {}
/// A block-level container that places content into a separate flow.
///
/// This can be used to force elements that would otherwise be inline to become
/// block-level. This is especially useful when writing `{show}` rules.
/// block-level. This is especially useful when writing show rules.
///
/// ## Example
/// ```

View File

@ -12,81 +12,76 @@ use super::Spacing;
///
/// The sizing of the grid is determined by the track sizes specified in the
/// arguments. Because each of the sizing parameters accepts the same values, we
/// will explain them here:
/// will explain them here. Each sizing argument accepts an array of track
/// sizes. A track size is either:
///
/// Each sizing argument accepts an array of track sizes. A track size is either
/// - a fixed length (e.g. `10pt`). The track will be exactly this size.
/// - a fixed length (e.g. `{10pt}`). The track will be exactly this size.
/// - `{auto}`. The track will be sized to fit its contents. It will be at most
/// as large as the remaining space. If there is more than one `auto` track
/// that, together, claim more than the available space, they will be resized
/// to fit the available space.
/// - a `fractional` length (e.g. `{1fr}`). Once all other tracks have been
/// sized, the remaining space will be divided among the fractional tracks
/// according to their fraction. For example, if there are two fractional
/// tracks, each with a fraction of `1`, they will each take up half of the
/// remaining space.
/// as large as the remaining space. If there is more than one `{auto}` track
/// which, together, claim more than the available space, the tracks will be
/// resized to fit the available space.
/// - a fractional length (e.g. `{1fr}`). Once all other tracks have been sized,
/// the remaining space will be divided among the fractional tracks according
/// to their fraction. For example, if there are two fractional tracks, each
/// with a fraction of `{1fr}`, they will each take up half of the remaining
/// space.
///
/// To specify a single track, the array can be omitted in favor of a single
/// value. To specify multiple `{auto}` tracks, enter the number of tracks
/// instead of a value. For example, `columns: {3}` is equivalent to
/// `columns: {(auto, auto, auto)}`.
/// instead of a value. For example, `columns:` `{3}` is equivalent to
/// `columns:` `{(auto, auto, auto)}`.
///
/// ## Example
/// ```
/// #set text(hyphenate: true)
/// #set text(10pt, weight: "bold")
/// #let cell = rect.with(
/// inset: 6pt,
/// fill: rgb("e4e5ea"),
/// width: 100%,
/// radius: 6pt
/// )
///
/// #grid(
/// columns: (60pt, 1fr, 60pt),
/// rows: (60pt, auto),
/// gutter: 3pt,
/// cell(height: 100%)[*Easy to learn*],
/// cell(height: 100%)[Great output],
/// cell(height: 100%)[*Intuitive*],
/// cell[*Our best Typst yet*],
/// cell[
/// Responsive design in print
/// for everyone
/// ],
/// cell[*One more thing...*],
/// )
/// inset: 8pt,
/// fill: rgb("e4e5ea"),
/// width: 100%,
/// radius: 6pt
/// )
/// #grid(
/// columns: (60pt, 1fr, 60pt),
/// rows: (60pt, auto),
/// gutter: 3pt,
/// cell(height: 100%)[Easy to learn],
/// cell(height: 100%)[Great output],
/// cell(height: 100%)[Intuitive],
/// cell[Our best Typst yet],
/// cell[
/// Responsive design in print
/// for everyone
/// ],
/// cell[One more thing...],
/// )
/// ```
///
/// ## Parameters
/// - cells: Content (positional, variadic)
/// The contents of the table cells.
/// - cells: Content (positional, variadic) The contents of the table cells.
///
/// The cells are populated in row-major order.
///
/// - rows: TrackSizings (named)
/// Defines the row sizes.
/// - rows: TrackSizings (named) Defines the row sizes.
///
/// If there are more cells than fit the defined rows, the last row is
/// repeated until there are no more cells.
///
/// - columns: TrackSizings (named)
/// Defines the column sizes.
/// - columns: TrackSizings (named) Defines the column sizes.
///
/// Either specify a track size array or provide an
/// integer to create a grid with that many `{auto}`-sized columns. Note that
/// opposed to rows and gutters, providing a single track size will only ever
/// create a single column.
/// Either specify a track size array or provide an integer to create a grid
/// with that many `{auto}`-sized columns. Note that opposed to rows and
/// gutters, providing a single track size will only ever create a single
/// column.
///
/// - gutter: TrackSizings (named)
/// Defines the gaps between rows & columns.
/// - gutter: TrackSizings (named) Defines the gaps between rows & columns.
///
/// If there are more gutters than defined sizes, the last gutter is repeated.
///
/// - column-gutter: TrackSizings (named)
/// Defines the gaps between columns. Takes precedence over `gutter`.
/// - column-gutter: TrackSizings (named) Defines the gaps between columns.
/// Takes precedence over `gutter`.
///
/// - row-gutter: TrackSizings (named)
/// Defines the gaps between rows. Takes precedence over `gutter`.
/// - row-gutter: TrackSizings (named) Defines the gaps between rows. Takes
/// precedence over `gutter`.
///
/// ## Category
/// layout

View File

@ -4,9 +4,9 @@ use crate::prelude::*;
/// Hide content without affecting layout.
///
/// The `hide` function allows you to hide content while the layout still 'sees'
/// it. This is useful to create layout items that are exactly as large as some
/// content. It may also be useful to redact content because its arguments are
/// not included in the output.
/// it. This is useful to create to create whitespace that is exactly as large
/// as some content. It may also be useful to redact content because its
/// arguments are not included in the output.
///
/// ## Example
/// ```

View File

@ -11,7 +11,7 @@ use crate::prelude::*;
/// ```
/// #set align(center)
///
/// #pad(16pt, image("typing.jpg"))
/// #pad(x: 16pt, image("typing.jpg"))
/// _Typing speeds can be
/// measured in words per minute._
/// ```

View File

@ -7,12 +7,31 @@ use crate::text::TextNode;
/// # Page
/// Layouts its child onto one or multiple pages.
///
/// Although this function is primarily used in set rules to affect page
/// properties, it can also be used to explicitly render its argument onto
/// a set of pages of its own.
///
/// Pages can be set to use `{auto}` as their width or height. In this case,
/// the pages will grow to fit their content on the respective axis.
///
/// ## Parameters
/// - body: Content (positional, required)
/// The contents of the page(s).
///
/// Multiple pages will be created if the content does not fit on a single
/// page. A new page with the page properties prior to the function invocation
/// will be created after the body has been typeset.
///
/// - paper: Paper (positional, settable)
/// The paper size.
/// A standard paper size to set width and height. When this is not specified,
/// Typst defaults to `{"a4"}` paper.
///
/// ## Example
/// ```
/// #set page("us-letter", margin: auto)
///
/// There you go, US friends!
/// ```
///
/// ## Category
/// layout
@ -24,33 +43,207 @@ pub struct PageNode(pub Content);
#[node]
impl PageNode {
/// The unflipped width of the page.
///
/// # Example
/// ```
/// #set page(
/// width: 3cm,
/// margin: (x: 0cm),
/// )
///
/// #for i in range(3) {
/// box(square(width: 1cm))
/// }
/// ```
#[property(resolve)]
pub const WIDTH: Smart<Length> = Smart::Custom(Paper::A4.width().into());
/// The unflipped height of the page.
///
/// If this is set to `{auto}`, page breaks can only be triggered manually
/// by inserting a [page break](@pagebreak). Most examples throughout this
/// documentation use `{auto}` for the height of the page to dynamically
/// grow and shrink to fit their content.
#[property(resolve)]
pub const HEIGHT: Smart<Length> = Smart::Custom(Paper::A4.height().into());
/// Whether the page is flipped into landscape orientation.
///
/// # Example
/// ```
/// #set page(
/// "us-business-card",
/// flipped: true,
/// fill: rgb("f2e5dd"),
/// )
///
/// #set align(bottom + end)
/// #text(14pt)[*Sam H. Richards*] \
/// _Procurement Manager_
///
/// #set text(10pt)
/// 17 Main Street \
/// New York, NY 10001 \
/// +1 555 555 5555
/// ```
pub const FLIPPED: bool = false;
/// The page's margins.
///
/// - A single length: The same margin on all sides.
/// - `{auto}`: The margin is set to the default value for the page's size.
/// - `{none}`: The page will be stripped of its margins.
/// - A dictionary: With a dictionary, the margins can be set individually.
/// The dictionary can contain the following keys in order of precedence:
/// - `top`: The top margin.
/// - `right`: The right margin.
/// - `bottom`: The bottom margin.
/// - `left`: The left margin.
/// - `x`: The horizontal margins.
/// - `y`: The vertical margins.
/// - `rest`: The margins on all sides except the sides for which the
/// dictionary explicitly sets a size.
///
/// # Example
/// ```
/// #set page(
/// width: 3cm,
/// height: 4cm,
/// margin: (x: 8pt, y: 4pt),
/// )
///
/// #rect(
/// width: 100%,
/// height: 100%,
/// fill: aqua,
/// )
/// ```
#[property(fold)]
pub const MARGIN: Sides<Option<Smart<Rel<Length>>>> = Sides::splat(Smart::Auto);
/// How many columns the page has.
///
/// # Example
/// ```
/// #set page(columns: 2, height: 4.8cm)
/// Climate change is one of the
/// most pressing issues of our
/// time, with the potential to
/// devastate communities,
/// ecosystems, and economies
/// around the world. It's clear
/// that we need to take urgent
/// action to reduce our carbon
/// emissions and mitigate the
/// impacts of a rapidly changing
/// climate.
/// ```
pub const COLUMNS: NonZeroUsize = NonZeroUsize::new(1).unwrap();
/// The page's background color.
///
/// This instructs the printer to color the complete page with the given
/// color. If you are considering larger production runs, it may be more
/// environmentally friendly and cost-effective to source pre-dyed pages and
/// not set this property.
///
/// # Example
/// ```
/// #set page(fill: rgb("444352"))
/// #set text(fill: rgb("fdfdfd"))
/// *Dark mode enabled.*
/// ```
pub const FILL: Option<Paint> = None;
/// The page's header.
///
/// The header is placed at in the top margin of each page.
///
/// - Content: The content will be placed in the header.
/// - A function: The function will be called with the page number (starting
/// at one) as its only argument. The content it returns will be placed in
/// the header.
/// - `{none}`: The header will be empty.
///
/// # Example
/// ```
/// #set par(justify: true)
/// #set page(
/// margin: (x: 24pt, y: 32pt),
/// header: align(horizon + right, text(8pt)[_Exercise Sheet 3_]),
/// )
///
/// #lorem(18)
/// ```
#[property(referenced)]
pub const HEADER: Marginal = Marginal::None;
/// The page's footer.
///
/// The footer is placed at in the bottom margin of each page.
///
/// - Content: The content will be placed in the footer.
/// - A function: The function will be called with the page number (starting
/// at one) as its only argument. The content it returns will be placed in
/// the footer.
/// - `{none}`: The footer will be empty.
///
/// # Example
/// ```
/// #set par(justify: true)
/// #set page(
/// margin: (x: 24pt, y: 32pt),
/// footer: i => align(horizon + right,
/// text(8pt, numbering("I", i))
/// )
/// )
///
/// #lorem(18)
/// ```
#[property(referenced)]
pub const FOOTER: Marginal = Marginal::None;
/// Content in the page's background.
///
/// This content will be placed behind the page's body. It can be
/// used to place a background image or a watermark.
///
/// # Example
/// ```
/// #set page(
/// background: align(
/// center + horizon,
/// rotate(24deg,
/// text(18pt, fill: rgb("FFCBC4"))[*CONFIDENTIAL*]
/// )
/// ),
/// )
///
/// = Typst's secret plans
///
/// In the year 2023, we plan to take over the world
/// (of typesetting).
/// ```
#[property(referenced)]
pub const BACKGROUND: Marginal = Marginal::None;
/// Content in the page's foreground.
///
/// This content will overlay the page's body.
///
/// # Example
/// ```
/// #set page(
/// foreground: align(
/// center + horizon,
/// text(24pt)[🥸]
/// ),
/// )
///
/// Reviewer 2 has marked our paper
/// "Weak Reject" because they did
/// not understand our approach...
/// ```
#[property(referenced)]
pub const FOREGROUND: Marginal = Marginal::None;
@ -180,7 +373,7 @@ impl Debug for PageNode {
///
/// ## Parameters
/// - weak: bool (named)
/// If true, the page break is skipped if the current page is already empty.
/// If `{true}`, the page break is skipped if the current page is already empty.
///
/// ## Category
/// layout

View File

@ -152,8 +152,8 @@ castable! {
/// A paragraph break.
///
/// This starts a new paragraph. Especially useful when used within code like
/// [for loops](/docs/reference/concepts#for-loop). Paragraph breaks in an empty
/// paragraph are ignored.
/// [for loops](/docs/reference/concepts#for-loop). Multiple consecutive
/// paragraph breaks collapse into a single one.
///
/// ## Example
/// ```
@ -790,7 +790,12 @@ fn linebreak_optimized<'a>(vt: &Vt, p: &'a Preparation<'a>, width: Abs) -> Vec<L
// has minimum cost. All breakpoints before this one become
// inactive since no line can span above the mandatory break.
active = k;
MIN_COST + if attempt.justify { ratio.powi(3).abs() } else { 0.0 }
MIN_COST
+ if attempt.justify {
ratio.powi(3).abs()
} else {
0.0
}
} else {
// Normal line with cost of |ratio^3|.
ratio.powi(3).abs()

View File

@ -3,6 +3,22 @@ use crate::prelude::*;
/// # Repeat
/// Repeats content to fill a line.
///
/// This can be useful when implementing a custom index, reference, or outline.
///
/// Space may be inserted between the instances of the body parameter, so be
/// sure to include negative space if you need the instances to overlap.
///
/// ## Example
/// ```
/// Sign on the dotted line: #repeat[.]
///
/// #set text(10pt)
/// #v(8pt, weak: true)
/// #align(right)[
/// Berlin, the 22nd of December, 2022
/// ]
/// ```
///
/// ## Parameters
/// - body: Content (positional, required)
/// The content to repeat.

View File

@ -5,9 +5,9 @@ use crate::prelude::*;
/// # Spacing (H)
/// Insert horizontal spacing into a paragraph.
///
/// The spacing can be a length or a `fractional`. In the latter case, the
/// The spacing can be a length or a fractional. In the latter case, the
/// remaining space on the line is distributed among all fractional spacings
/// according to their relative size.
/// according to their relative fractions.
///
/// ## Example
/// ```
@ -35,7 +35,7 @@ use crate::prelude::*;
/// manifest in most cases. However,
/// when #h(8pt, weak: true)
/// supported
/// #h(8pt, weak: true) on all
/// #h(8pt, weak: true) on both
/// sides, they do show up.
/// ```
///
@ -100,9 +100,9 @@ impl Behave for HNode {
/// # Spacing (V)
/// Insert vertical spacing.
///
/// The spacing can be a length or a `fractional`. In the latter case, the
/// The spacing can be a length or a fractional. In the latter case, the
/// remaining space on the page is distributed among all fractional spacings
/// according to their relative size.
/// according to their relative fractions.
///
/// ## Example
/// ```
@ -115,9 +115,7 @@ impl Behave for HNode {
/// #v(5mm)
///
/// - Informed consent
///
/// - Participant confidentiality
///
/// - The use of
/// vulnerable populations.
/// ```
@ -127,23 +125,20 @@ impl Behave for HNode {
/// How much spacing to insert.
///
/// - weak: bool (named)
/// If true, the spacing collapses at the start or end of a flow.
/// Moreover, from multiple adjacent weak spacings all but the largest one
/// collapse.
/// If true, the spacing collapses at the start or end of a flow. Moreover,
/// from multiple adjacent weak spacings all but the largest one collapse.
/// Weak spacings will always collapse adjacent paragraph spacing, even if the
/// paragraph spacing is larger.
///
/// ### Example
/// ```
/// Only paragraph spacing
///
/// Override paragraph spacing
/// with weak space
/// #v(7mm, weak: true)
///
/// Add to paragraph spacing
/// #v(7mm, weak: false)
///
/// A secret, fourth thing
/// ```
/// The following theorem is
/// foundational to the field:
/// #v(4pt, weak: true)
/// $ x^2 + y^2 = r^2 $
/// #v(4pt, weak: true)
/// The proof is simple:
/// ```
/// ## Category
/// layout
#[func]

View File

@ -5,7 +5,7 @@ use crate::prelude::*;
/// # Move
/// Move content without affecting layout.
///
/// The `move` function allows you to hide content while the layout still 'sees'
/// The `move` function allows you to move content while the layout still 'sees'
/// it at the original positions. Containers will still be sized as if the content
/// was not moved.
///
@ -100,9 +100,8 @@ impl Inline for MoveNode {}
/// ```
/// {
/// range(16)
/// .map(i =>
/// rotate(360deg / 15 * i)[X]
/// ).join(h(1fr))
/// .map(i => rotate(24deg * i)[X])
/// .join(h(1fr))
/// }
/// ```
///
@ -113,6 +112,11 @@ impl Inline for MoveNode {}
/// - angle: Angle (named)
/// The amount of rotation.
///
/// ### Example
/// ```
/// #rotate(angle: -1.571rad)[To space!]
/// ```
///
/// ## Category
/// layout
#[func]
@ -128,6 +132,22 @@ pub struct RotateNode {
#[node]
impl RotateNode {
/// The origin of the rotation.
///
/// By default, the origin is the center of the rotated element. If,
/// however, you wanted the bottom left corner of the rotated element to
/// stay aligned with the baseline, you would set the origin to `bottom +
/// left`.
///
/// # Example
/// ```
/// #set text(spacing: 8pt)
/// #let square = square.with(width: 8pt)
///
/// #square()
/// #rotate(angle: 30deg, origin: center, square())
/// #rotate(angle: 30deg, origin: top + left, square())
/// #rotate(angle: 30deg, origin: bottom + right, square())
/// ```
#[property(resolve)]
pub const ORIGIN: Axes<Option<GenAlign>> = Axes::default();
@ -211,6 +231,14 @@ pub struct ScaleNode {
#[node]
impl ScaleNode {
/// The origin of the transformation.
///
/// By default, the origin is the center of the scaled element.
///
/// # Example
/// ```
/// A#scale(75%)[A]A \
/// B#scale(75%, origin: bottom + left)[B]B
/// ```
#[property(resolve)]
pub const ORIGIN: Axes<Option<GenAlign>> = Axes::default();