How to create a toggle for figures to be inlined or appended?

188 Views Asked by At

I am using typst to write my Facharbeit (scientific paper in a German high school). One of the formal criteria is that all figures have to be appended at the end.

However, for reading the text digitally, this is extremely inconvenient as you have to scroll all the way down only to get the relevant context, and a teacher of mine said she wants to have a printed version of the document with the figures inline, i.e. inserted in the text content at not at the end. Manually moving them is repetitive and error-prone, especially as information is lost when moving the figures at the end.

Would it be possible to implement such a toggle, i.e. #let inline-figures = true | false, and automatically move the figures to where they belong? Ideally, I could just use the figure-command as is without needing to change anything about it, but it would also be fine if there could be a new function, "#myfigure", that did what I described for me.

Thanks in advance!

1

There are 1 best solutions below

0
On

From the documentation and issue tracker of Typst it seems that it is not possible to modify the position of rendered figures programmatically (see https://github.com/typst/typst/issues/553 for some background).

An alternative approach is to postprocess the document with a different programming language in order to move the figures in the source code which can then be recompiled.

The following Python program searches for #figure tags and extracts the following code up to the balanced closing parenthesis and possible label between < >. Then it reconstructs the code by removing all figure chunks from the main text and adding them back at the end.

import re

fin = open("inlinefigs.typ")
fulltext = fin.read()
fin.close()

# find all indices of the start of a figure with the preceding newline
figures_start = [m.start()-1 for m in re.finditer('#figure\(', fulltext)]
figures_end = []

# find the balanced closing parenthesis for each figure
for start in figures_start:
   stack = 1
   # skip \n#figure( when looking for closing parenthesis
   i = start + 9
   while stack > 0:
      if fulltext[i] == ')':
         stack -= 1
      if fulltext[i] == '(':
         stack += 1
      i += 1
   # check for possible label
   if fulltext[i+1] == '<':
      i = fulltext.find('>', i) + 1
   # store end position of current figure in second list
   figures_end.append(i)

prev_idx = 0
newtext = ""
allfigs = ""
# remove figure spans from the text
for i in range(len(figures_start)):
    allfigs += fulltext[figures_start[i]:figures_end[i]] + "\n"
    newtext += fulltext[prev_idx:figures_start[i]]
    prev_idx = figures_end[i]

# add text after last figure
newtext += fulltext[prev_idx:]

fout = open("endfigs.typ", "w")
# write text without figures
fout.write(newtext)
# write figures at the end
fout.write("= All figures\n")
fout.write(allfigs)
fout.close()

This Python code can be applied on the following Typst document:

@glacier shows a glacier. Glaciers
are complex systems.

#figure(
  image("glacier.jpg", width: 30%),
  caption: [A curious figure.],
) <glacier>

Molecular testing is also very complex, as seen in @molecular.

#figure(
  image("molecular.jpg", width: 30%),
  caption: [
    The molecular testing pipeline.
  ],
) <molecular>

Trees are simple acyclic graphs.

#figure(
  image("graph.png", width: 30%),
  caption: [
    A (binary) tree.
  ],
)

There is much more to say about these images, but that is left for future work.

The resulting document endfigs.typ, when compiled, looks like this:

enter image description here