Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promote margin to a type #3636

Open
ntjess opened this issue Mar 12, 2024 · 6 comments
Open

Promote margin to a type #3636

ntjess opened this issue Mar 12, 2024 · 6 comments
Labels
proposal You think that something is a good idea or should work differently. scripting About Typst's coding capabilities

Comments

@ntjess
Copy link

ntjess commented Mar 12, 2024

Description

Similar to how stroke allows converting a dictionary into stroke properties, there should be a margin type that converts a dictionary specifier into a page margin

Use Case

Page margins can be specified in numerous ways:

  • Inside/outside
  • Single argument vs several
  • x/y vs left/right etc.
  • unspecified => auto

This makes it difficult to consume through a context call due to the wide variety of potential outputs. Each of these specifiers results in a different-format output:

#let page-margin(..args) = {
  let margin = if args.pos().len() > 0 {
    args.pos().at(0)
  } else {
    args.named()
  }
  set page(margin: margin)
  context page.margin
}

#set page(height: auto)
#(
  1em,
  (outside: 1em),
  (left: 3em),
).map(page-margin).join()

Similar to how a stroke evolved from a dict into its own type, I recommend the same thing for a margin. This way, users can expect to resolve top, bottom, left, and right without calculating it manually by checking the binding and page number, referencing auto against paper defaults, etc.

Real-world example: The "drafting" package would need to take all these into account to provide robust margin notes without user specifications.

@ntjess ntjess added the feature request New feature or request label Mar 12, 2024
@laurmaedje laurmaedje added proposal You think that something is a good idea or should work differently. and removed feature request New feature or request labels Mar 12, 2024
@ntjess
Copy link
Author

ntjess commented Mar 12, 2024

Related note: Since context doesn't provide page.paper, is there an existing way to resolve an auto margin?

@laurmaedje
Copy link
Member

The auto margin can be resolved as 2.5 / 21 * calc.min(page.width, page.height). In the future, that might happen automatically.

@Leedehai
Copy link
Contributor

Leedehai commented Mar 13, 2024

This way, users can expect to resolve top, bottom, left, and right without calculating it manually by checking the binding and page number

Hi, could you pls elaborate on how making a margin type could help with this use case?

@laurmaedje laurmaedje added the scripting About Typst's coding capabilities label Mar 14, 2024
@ntjess
Copy link
Author

ntjess commented Mar 14, 2024

The easiest example is to compare to a stroke. You can pass many forms of stroke into a shape, i.e.

  • black + 5pt
  • (paint: red, dash: "dashed")
  • 1em
    Each of these is a different type, but construct a stroke with the same set of fields. So having access to a stroke type means the user is not responsible to understand how to handle all these separate formats. They just need to do
    stroke(input).thickness to get the line thickness. This is why typst authors added the type in 0.10

In the same way, a margin can be constructed from all the types and arguments listed in the feature request. So if I wanted to know the page margin, it is possible the user passed in margin: (outside: 3in). In this case, just to know the left margin, I need to

  1. Find out whether the binding is left/right/auto
  2. Find out whether the text direction is ltr/rtl/auto
  3. Find out whether the language is ltr/rtl by default (!)
  4. Find out whether the page is even or odd

If the margin type exists, I can just call context margin(input).left and it will provide me this value "out-of-the-box"

@JustForFun88
Copy link
Contributor

Can we also consider the ability to specify different margins on different pages?

It will be very useful, especially for the first page!

@PgBiel
Copy link
Contributor

PgBiel commented Mar 28, 2024

I'm not sure I see the link between resolving the page margin and making it into its own type with its own constructor. You can expose, through context, a value different from what the user specified directly - this happens today with most synthesized fields; e.g., in a show rule of table.cell, you will see the cell's final position, stroke etc. even if the user didn't specify those. The need to resolve properties for context shouldn't be our sole reason to create new types, as that would apply too broadly to other elements as well.

Indeed, what's missing here is a step in which we resolve page properties before each page is laid out (and, as a consequence, transform what users specified into what Typst effectively is aware of, i.e. into a single dictionary-like structure, through a custom type or not). I elaborate on this approach at #3671. We can see that #3811, for example, doesn't solve the resolving margin auto problem (the tests still show properties returning auto through context), only the structure problem. Resolving the margin and other page properties automatically, as I've previously suggested, would not only remove the auto problem, but also ensure the properties have a uniform structure when obtained through context, solving both problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal You think that something is a good idea or should work differently. scripting About Typst's coding capabilities
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants