typst / typst

A new markup-based typesetting system that is powerful and easy to learn.
https://typst.app
Apache License 2.0
32.28k stars 864 forks source link

Multi-column Float Elements (Figures, Tables, Code Blocks, etc.) #553

Open giannissc opened 1 year ago

giannissc commented 1 year ago

Supersedes: #137.

I want to be able to break the column rules for figures and tables to the full size of the page and I want to be able to float these elements. I believe these two must be tackled together as you can see in the motivating examples

giannissc commented 1 year ago

Currently elements cannot break away from their local scope. If columns is activated globally in the document, subsequent elements cannot break from their column parent to use the full width of the page.

A separate issue is that if an element (e.g. image) doesn't fit into the remaining space it will move to the next page/column leaving a blank space behind it.

These two issues, while separate, must be tackled together as there are complex interactions between them.

To solve the first issue I propose that we introduce a scope argument to all the layout methods. Scope can either be global (relative to page) or local (relative to parent [existing behavior]).

To solve the second issue I propose a new layout element #wrap or #float (no strong preference but for the rest of this post I will be using #wrap). #wrap is the counterpart to #place. Unlike place however, it can participate in the flow.

The function signatures would be:

alignment:

giannissc commented 1 year ago

Algorithm for #wrap elements:

  1. Calculate #wrap element's dimensions and check if the element can fit to existing page/column (other #wrap elements might already populate the page)
  2. If it can, place #wrap element at correct position in current page/column based on its alignment policy. Relayout all other content (except other #wrap elements) in current page/column.
  3. If not, place #wrap element at correct position in the next page/column based on its alignment policy. Keep adding content to current page until it is filled.
giannissc commented 1 year ago

In case 2 or more #wrap elements are placed in the same position in a page/column fallback arguments can be used to decide its position:

giannissc commented 1 year ago

Does this seem reasonable? @laurmaedje, @reknih

Also is this the best place to discuss or do you prefer discord?

I am also willing to contribute code to get this out sooner! 🙂

giannissc commented 1 year ago

Motivating Examples

No wrap (existing behavior)

Not allowing text to wrap around other elements can result in the following issue: Screenshot 2023-04-05 at 08-05-05 Test Paper (copy) – Typst

No wrap,break column rules (global scope)

Simple allowing content to break the column rules and layout based on page will also have the same issue: Screenshot 2023-04-05 at 08-20-18 Test Paper – Typst

Wrap (local scope) - #wrap(scope: local, alignment: []) - Default

Screenshot 2023-04-05 at 08-08-54 Test Paper (copy) – Typst

Wrap (global scope) - #wrap(scope: global, alignment: [])

Screenshot 2023-04-05 at 08-22-12 Test Paper – Typst

Wrap (global scope) + Alignment(Centered) - #wrap(scope: global, alignment: [center+horizon])

Screenshot 2023-04-05 at 08-34-00 Test Paper – Typst

Wrap (global scope) + Conflict (Repeated) - #wrap(scope: global, alignment: [top, top])

Screenshot 2023-04-05 at 08-35-25 Test Paper – Typst

Wrap (global scope) + Conflict (Alternate) - #wrap(scope: global, alignment: [top, bottom])

Screenshot 2023-04-05 at 08-37-54 Test Paper – Typst

Andonome commented 1 year ago

This is great. In fact, it'd be ideal.

giannissc commented 1 year ago

Do you think the primary and secondary alignments are both necessary? @Andonome

eltos commented 1 year ago

This is the most important missing feature to make typst as powerful as LaTeX.

Andonome commented 1 year ago

Do you think the primary and secondary alignments are both necessary? @Andonome

I wouldn't say 'necessary', but I've found a great deal of flexibility in having both 'top' and 'bottom' options.

This page looks fine, as-is, but the two elements float apart when more text is added, which matches the general format of pictures-at-bottom, and tables-on-top.

image

I've not found tables in the centre work very often.

Of course if anyone wants to get really fancy, automatic wrapping around a PNGs filled parts would be punk-as-all-heck.

Andonome commented 1 year ago

This is the most important missing feature to make typst as powerful as LaTeX.

LaTeX doesn't have this ability. There is no reliable text wrapping in a multicols environment. It's a big factor which stops it having reliable output - every compile, every page needs to be checked, images moved, et c.


Edit: I see I've received some silent naysayers downvoting this comment.

If anyone wants to put their code where their mouth is, check out my main project, and get any 3 images (of your choosing) to float, using any macro you please.

giannissc commented 1 year ago

@Andonome I think is wrap is to be implemented it should be implemented with all these usecases in mind. Another usecase that comes to mind is that you have a central circular figure and that text should wrap around it as well. You examples are genuinely useful. Thanks!

giannissc commented 1 year ago

In you table and figure example would you want to force text to move to the next page or would it be ok for it to render in-between the two elements?

Andonome commented 1 year ago

@Andonome I think is wrap is to be implemented it should be implemented with all these usecases in mind. Another usecase that comes to mind is that you have a central circular figure and that text should wrap around it as well. You examples are genuinely useful. Thanks!

Would a showcase be useful? I've had a bunch of ugly results with difficult elements.

In you table and figure example would you want to force text to move to the next page or would it be ok for it to render in-between the two elements?

It depends on the results. Either could be fine, but what's sorely lacking is the ability to return to the last page for a do-over. LaTeX can't correct previous pages, so you can get these ugly dangling single-lines of text.

I've given headers a bunch of \needspace{ commands to stop them going at the end of a page, but that's left this dangling, when the next couple of \paragraph statements (with Journeys) could have fit between these two images fine.

Of course here it's blocked by the General Tempo Chart, so that should have been moved to after the next paragraph.

image

In a lot of cases, it's far more important to say 'place this element somewhere before the next subsection' than making a statement about the position.

Here's another table that could have been better placed by floating anywhere else after the \subsection{Encounters}.

image

I don't know if there's a non-intensive way to have typst go through a bunch of options involving multiple pages, but maybe there could be a second processing option where the user understands it'll take extra time to process, but the results will make sense. Atm a full LaTeX process can take 20 minutes - that's quite doable for big pushes, but less okay when the results need fiddled with before publishing a new version.

giannissc commented 1 year ago

I have update the proposal based on your previous comments and from conversations in Discord. Here is the updated proposal if you want to have a look @Andonome :

Multi-column Float Proposal.pdf

I haven't thought thoroughly about your latest comment just yet but do you think that the proposal here covers those usecases

giannissc commented 1 year ago

Ok I just had another look and your usecase in incredibly useful! I might need to tweak the scope argument with other options such as paragraph, section, etc. for more fine-grained control!

giannissc commented 1 year ago

It depends on the results. Either could be fine, but what's sorely lacking is the ability to return to the last page for a do-over. LaTeX can't correct previous pages, so you can get these ugly dangling single-lines of text.

I am not sure I fully understand this point. Is this something that the algorithm is lacking or is it something that the existing Latex API cannot express. If it is the latter I will make a note on the algorithm implementation portion of the proposal otherwise I will make a note on the motivation and API section as an additional user intent

giannissc commented 1 year ago

Proposal v3: Multi-column Float Proposal-3.pdf

giannissc commented 1 year ago

Proposal v4: Multi-column Float Proposal-4.pdf

Andonome commented 1 year ago

Proposal v4: Multi-column Float Proposal-4.pdf

This all looks fantastic.

In 1.6:

Giving an option to disable horizontal wrapping would alleviate the issue.

It might be better to disable this by default. Nobody wants to see 2-words crawling down the side of a table. The table should be centred automatically.

In fact in general, the default being 'typst chooses' is always good. Take for example the first example table. It's clearly best presented image-wide, but that won't always be obvious until the page has processed. If the floating default behaviour was for typst to choose how it floats (and only request the user states if it should be in the same section or page as something else) then it'd really help in producing unattended document production.

0x7CFE commented 1 year ago

I can suggest reading the Lillypond essay about problems of automated music engraving. I believe, a lot of ideas are common to any complex layout system and potentially can be applied to typst as well.

tldr: Music notation is much more complicated than one can imagine. Naive approach to notation layout based on the hierarchy of containers (page→staff→lines→notes etc) simply does not work. Once in a while you will face some quirky notation like multi-staff slurs or beams, and things will get complicated. In the end, this will result in a lot of ad-hoc code, or the result will not be visually pleasing. Lillypond uses completely different approach to layout.

granthamtaylor commented 1 year ago

I just wanted to add my +1 here.

I'm trying to write up a whitepaper in IEEE format and floating tables / figures are not possible AFAIK.

KronosTheLate commented 1 year ago

It would be lovely to see this feature implemented.

coljac commented 1 year ago

+1. As far as I can tell, this is the only missing feature stopping me completing a nearly perfect template for my usual research journal (and then hassling the editors about it). Having figures and tables spanning two columns is a must.

Andonome commented 1 year ago

Just thought I'd add some god-tier image floating challenges.

Image taking up 2 out of 3 columns, at top

The ideal command here would be something like #image[ columns = 2, image.png].

Image overlapped by text

I don't how much of a 'badness' rating typst has under the hood, but perhaps an image could be covered when needed, as above.

text-wrap

Clearly only available for .png or something with transparency, but automatic text-wrapping would be the bees' knees.

jaanli commented 1 year ago

+1 need this as well @onefact!

rtbs-dev commented 11 months ago

Also needing this for conference/journal submissions. E.g. summary tables, larger figures (a la small-multiples), etc.

danaugrs commented 10 months ago

Any updates on this? I need a way to span a table over two columns for a research paper.

laurmaedje commented 10 months ago

@danaugrs Unfortunately, there has been no progress on this lately.

denkspuren commented 9 months ago

This is my use case I would very much like to be able to reproduce in Typst: to wrap text around a textbox. In LaTeX I used packages wrapstuff and tcolorbox for this, see result:

wrapTextExample

The LaTeX code to achieve this effect looks like this; top = 5 is the number of lines of the paragraph where mybox is supposed to appear.

\begin{wrapstuff}[top=5, width=0.4\linewidth]
  \begin{mybox}[title=LektĂĽre-Empfehlung]
    Gundersen (2021, pp. 31-49) gibt in seiner (online verfügbaren) Dissertation einen informativen und zugleich prägnanten Überblick über die Anfänge und Geschichte von DBR in der Bildungsforschung. Auch in den einführenden Büchern von Bakker (2018) sowie McKenney und Reeves (2019) wird auf die Entwicklung von DBR eingegangen. Dort finden sich auch Erläuterungen zu Varianten und Hinweise auf erste Meta-Studien.
  \end{mybox}
\end{wrapstuff}
\textbf{Seit wann gibt es DBR im Bildungskontext?} Anfang der 1990er Jahre haben die Bildungsforscher Ann Brown (1992) und Allan Collins (1992) sogenannte Designexperimente kreiert. Sie waren unzufrieden mit Laborexperimenten und wollten besser verstehen, wie Lernen im Kontext funktioniert. Dazu verlegten sie ihre Forschung vom kontrollierten Labor ins reale Klassenzimmer. Klassenzimmer ist hier wörtlich zu nehmen, denn im Blick war vor allem die Schule. Das Ziel, sowohl praktische als auch theoretische Relevanz zu erreichen, ist in DBR kennzeichnend geblieben. Bereits diese frühen Designexperimente waren interventionistisch, iterativ und kollaborativ angelegt, und man arbeitete tendenziell mit kleinen Fallzahlen. Designexperimente gelten als die Anfänge von DBR.

\textbf{Wie hat sich DBR weiter entwickelt?} Ende der 1990er Jahre und um 2000 stieg das Interesse an Designexperimenten. Es entwickelten sich Varianten unter verschiedenen Bezeichnungen wie Developmental Research oder Formative Research. Einige Autoren begannen, zwischen Validierungs- und Entwicklungsstudien zu unterscheiden und als eigenständige Studientypen zu postulieren. Durchgesetzt hat sich diese Trennung allerdings nicht, was auch einem der Kernmerkmale -- der doppelten Zielsetzung für Wissenschaft und Praxis -- widerspräche. Dennoch sind die Arbeiten aus dieser Zeit einflussreich und markieren wichtige Suchbewegungen, die in DBR nach wie vor diskutiert werden: Dazu gehört etwa die Frage, wie man in DBR zu theoretischen Erkenntnissen gelangt und auf welche Weise Verallgemeinerungen möglich sind. In den 2000er Jahren sind zahlreiche methodologische Beiträge zu DBR in englischer Sprache erschienen. Das, was wir als gemeinsame Merkmale von DBR zusammengestellt haben, wurde in dieser Zeit erarbeitet. Seit 2010 werden zunehmend mehr DBR-Studien veröffentlicht; auch erste systematische Übersichtsarbeiten erscheinen. Begleitet wurden und werden diese Aktivitäten durch Kritik vor allem aus der Perspektive der empirischen (pädagogisch-psychologisch ausgerichteten) Bildungsforschung: Legt man deren Routinen und Qualitätsstandards an, erscheinen sowohl die empirischen als auch die theoretischen Prozesse und Ergebnisse von DBR oft unbefriedigend.

With mybox being defined as

\newtcolorbox{mybox}[1][]{
  enhanced,
  boxsep=0pt,
  boxrule=0pt,
  toprule=3pt,
  code={\vspace{-2ex}\footnotesize\singlespacing\fontfamily{cmss}\selectfont},
  #1}
let-me-cook commented 9 months ago

Is this feature being considered for version 1.0 of Typst?

laurmaedje commented 9 months ago

Is this feature being considered for version 1.0 of Typst?

Definitely. But note that 1.0 is still a ways off.

Polydynamical commented 8 months ago

We need this feature Typst Devs :cry:

ntjess commented 7 months ago

A solution in the meantime: https://github.com/ntjess/wrap-it PR is here: https://github.com/typst/packages/pull/357

It handles the common cases (think of it like a less-finicky version of wrapfig), but there are still some fundamental limitations that can't be solved in typst image

denkspuren commented 7 months ago

I'm impressed by your solution Nathan! Great work!

davidleejy commented 6 months ago

A solution in the meantime: https://github.com/ntjess/wrap-it PR is here: typst/packages#357

It handles the common cases (think of it like a less-finicky version of wrapfig), but there are still some fundamental limitations that can't be solved in typst

This looks pretty neat. Does anyone know whether it's possible to position a table spanning the width of the page in typical Typst 2-column layout with this package?

danaugrs commented 4 months ago

A solution in the meantime: https://github.com/ntjess/wrap-it PR is here: typst/packages#357 It handles the common cases (think of it like a less-finicky version of wrapfig), but there are still some fundamental limitations that can't be solved in typst

This looks pretty neat. Does anyone know whether it's possible to position a table spanning the width of the page in typical Typst 2-column layout with this package?

Doesn't seem like it's possible - at least I wasn't able to. Maybe @ntjess knows a workaround?

RaulDurand commented 4 months ago

Im not sure if it was already discussed elsewhere but I believe that the ability to place multicolumn floats should be a feature of columns (reflowing the text as needed) instead of a temporary break of the columns element.

the-busy-beaver commented 4 months ago

i encountered the same issue whilst using the charged-iee template, i wasn't able to put a figure containing a large / wide image at the top, spanning the two columns :thinking:

having this feature or a workaround would be really great :innocent:

vivek2000anand commented 3 months ago

Any idea when this feature will be added?

laurmaedje commented 3 months ago

@Vivdaddy We plan to take a closer look at this for 0.12, but I can't make any promises.

danaugrs commented 1 month ago

It seems like spanning a figure across all columns should be relatively straightforward to implement and it would fix 90% of all multi-column issues. Specially if the figure is at the top or bottom of a page. It would be as if a page with such a figure were a little shorter and the page break happened a bit before or after the actual page break in order to make space for the figure. I know that if this feature were implemented it would prevent me from temporarily switching back to LaTeX, and it seems a lot of people are also anxiously waiting for this (over 100 users if we go by GitHub reactions, but I suspect there are many more). Please let us know when you have updates! :heart:

Enivex commented 1 month ago

It seems like spanning a figure across all columns should be relatively straightforward to implement and it would fix 90% of all multi-column issues. Specially if the figure is at the top or bottom of a page. It would be as if a page with such a figure were a little shorter and the page break happened a bit before or after the actual page break in order to make space for the figure. I know that if this feature were implemented it would prevent me from temporarily switching back to LaTeX, and it seems a lot of people are also anxiously waiting for this (over 100 users if we go by GitHub reactions, but I suspect there are many more). Please let us know when you have updates! :heart:

I suspect that if it was straightforward the issue wouldn't still be open.

danaugrs commented 1 month ago

I suspect that if it was straightforward the issue wouldn't still be open.

This issue is about arbitrary multi-column float elements, which is a complex problem, specially if it involves arbitrary-shape text wrapping as in the last image in this comment. My objective was to point out that there is a subset of this problem space i.e. spanning an element across all columns of a page, specially at the top or bottom of a page (with no arbitrary-shape text wrapping), which is simpler to implement, and would solve the majority of use cases. I think any attempt at a solution should first focus on this.

Polydynamical commented 1 month ago

@laurmaedje Any progress on this feature request? :)

RaulDurand commented 1 month ago

I believe that the lack of support for multi-column figures and tables is the main limitation to using Typst for writing manuscripts for scientific journals.

kescobo commented 1 month ago

is the main limitation

It depends on the field - almost nothing I submit to (in biology) uses multi-column layouts, but I need line numbers (happily that's being worked on #352 )

DKierner commented 1 month ago

I believe that the lack of support for multi-column figures and tables is the main limitation to using Typst for writing manuscripts for scientific journals.

Definitely true for informatics and computer sciences where the IEEE format is quite common. Some stuff is just to large to fit in a single half-page column meaningfullly.

danaugrs commented 1 month ago

I think the ideal solution, from a user's perspective, would involve adding a single parameter, tentatively called colspan, to non-breakable block elements, which would specify how many columns that element should span. Specifying a colspan of more columns than exist in the current context would result in an error. I think such a parameter, coupled with the existing usage of placement: "auto" | "top" | "bottom", would provide complete freedom to place multi-column blocks anywhere as desired.

jounathaen commented 1 month ago

I'm not a mod, but I think that there are now enough "This feature is stopping me from using Typst"/"This feature is missing for XYZ support" comments in this issue. The Devs are aware of this issue, and it is as-of-now the third most upvoted issue. So instead of adding more comments of the same, I'd suggest using the emoticons to express your support for this feature. (And the selfish remark: Then people that have subscribed to this issue will not get spammed with non-progress messages)