From 959df6da3b6e3c5876e9d5627cb2970e32a0a37f Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Wed, 21 Dec 2022 12:01:28 +0100 Subject: [PATCH] Page function docs and more --- library/src/compute/utility.rs | 2 +- library/src/layout/align.rs | 1 + library/src/layout/columns.rs | 7 +- library/src/layout/container.rs | 14 ++- library/src/layout/grid.rs | 95 ++++++++------- library/src/layout/hide.rs | 6 +- library/src/layout/pad.rs | 2 +- library/src/layout/page.rs | 197 +++++++++++++++++++++++++++++++- library/src/layout/par.rs | 11 +- library/src/layout/repeat.rs | 16 +++ library/src/layout/spacing.rs | 37 +++--- library/src/layout/transform.rs | 36 +++++- 12 files changed, 330 insertions(+), 94 deletions(-) diff --git a/library/src/compute/utility.rs b/library/src/compute/utility.rs index f8a6d4dc3..be260a5fc 100644 --- a/library/src/compute/utility.rs +++ b/library/src/compute/utility.rs @@ -43,7 +43,7 @@ pub fn lorem(args: &mut Args) -> SourceResult { /// ## Example /// ``` /// #numbering("1.1)", 1, 2, 3) \ -/// #numbering("1.b.i", 1, 2) \ +/// #numbering("1.a.i", 1, 2) \ /// #numbering("I – 1", 12, 2) /// ``` /// diff --git a/library/src/layout/align.rs b/library/src/layout/align.rs index 952612aff..344789804 100644 --- a/library/src/layout/align.rs +++ b/library/src/layout/align.rs @@ -32,6 +32,7 @@ use crate::prelude::*; /// /// ### Example /// ``` +/// #set page(height: 6cm) /// #set text(lang: "ar") /// /// مثال diff --git a/library/src/layout/columns.rs b/library/src/layout/columns.rs index a5f67b940..6d90ecb27 100644 --- a/library/src/layout/columns.rs +++ b/library/src/layout/columns.rs @@ -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 diff --git a/library/src/layout/container.rs b/library/src/layout/container.rs index 112c6f030..5bff050bd 100644 --- a/library/src/layout/container.rs +++ b/library/src/layout/container.rs @@ -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 /// ``` diff --git a/library/src/layout/grid.rs b/library/src/layout/grid.rs index eafe644fd..00233cd15 100644 --- a/library/src/layout/grid.rs +++ b/library/src/layout/grid.rs @@ -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 diff --git a/library/src/layout/hide.rs b/library/src/layout/hide.rs index 6d168d35b..a63a4974a 100644 --- a/library/src/layout/hide.rs +++ b/library/src/layout/hide.rs @@ -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 /// ``` diff --git a/library/src/layout/pad.rs b/library/src/layout/pad.rs index bbd55225f..5c10050c2 100644 --- a/library/src/layout/pad.rs +++ b/library/src/layout/pad.rs @@ -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._ /// ``` diff --git a/library/src/layout/page.rs b/library/src/layout/page.rs index 8e1461266..43a7768e8 100644 --- a/library/src/layout/page.rs +++ b/library/src/layout/page.rs @@ -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 = 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 = 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>>> = 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 = 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 diff --git a/library/src/layout/par.rs b/library/src/layout/par.rs index 412a279e8..c05ed2e8e 100644 --- a/library/src/layout/par.rs +++ b/library/src/layout/par.rs @@ -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 -/// 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> = 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> = Axes::default();