I’m looking to make a function that draws a line, beginning from the last word in a paragraph until the end of the page (minus margin ofcourse). I tried looping over the width of the paragraph while subtracting the page width but that’s not ideal because if I’m not wrong Typst puts all the words next to eachother while measuring width. Another idea is placing an invisible marker at the end of the paragraph and measuring from there but I don’t know how to implement that.
Does anyone have an idea or a reference to the right docs? Thanks!
For a line to margin, you can make a box that occupies the remaining space using box(width: 1fr, ...). Here are several ways to get a line using this box:
#set page(margin: 3cm)
#lorem(100)
#box(width: 1fr, line(length: 100%))
#lorem(100)
#box(width: 1fr, stroke: (top: 1pt))
// Quality of result will depend on PDF reader and font
#lorem(100)
#box(width: 1fr, repeat[─])
Adjacent, to this, do you maybe know how to apply this to headings? When i try to set a show rule for headings it just draws the line underneath the heading title.
By default, a heading is in a block element, and if you add a box after a block it will come below. You can solve this by wrapping the heading in a box:
#show heading: it => box(it) + box(width: 1fr, line(length: 100%))
I tried that but it seems that the heading then gets handled like a table or grid with two columns, so the line doesn’t span after the last word (given that the heading is more than 1 line long) but in the next “column”. I don’t now how to achieve the line like in regular text (like you provided).
The problem is that this doesn’t return a heading, so it could prevent some rules on headings (higher up in the document) from being applied. So make sure to put this rule at the top. Or make it return a new heading, but then you’d need a trick to avoid recursion and spurious counter increments.
Thanks, adding to that I put the counter and remaining “heading” in a grid to keep the text after the numbering when the heading goes onto the next line.
However the text’s spacing is a little bit weird and I don’t see why that is, it now spans the text over the entire page sometimes with huge gaps. Do you maybe now the reason? I added a picture to clarify.
This seems to be due to text justification. If you use it.body Typst interprets it as a paragraph (see documentation) and it is affected by the paragraph’s text justification rule. To fix your issue, you have to disable justification inside the heading show rule and optionally enable hyphenation.
Oh, yeah, other show rules won’t work when you have a destructive show rule/re-implementation of an element. But, generally speaking, you won’t have 2 show rules for the same thing in the first place. Only if you add state or metadata, that is.
Destructuring show rule go first, the rest goes after.
You might have rules with different selectors that match the same element, or beside your custom rules you might also use a template that applies some show-it rules…
If a template function exists, then all rules would be in there, as is best practice. Sometimes it’s better to merge 2 show rules, if they exist, removing the potential loss of styling.
If a template function exists, then all rules would be in there, as is best practice.
I disagree, it’s quite common to apply a template from a package and also add some personal show rules (without making a new “merged” template). There’s nothing wrong with that…
And there’s yet another case when you need multiple show-it rules and must be careful: when you have a rule at the global scope, and one inside of another show rule. For example
#show outline: it => {
show heading: x => ...
it
}