How to wrap long "unbreakable" text in a table cell?

Hello,
I am formatting a table from the following input json:

[   
    [   
        "Date",
        "Tran Type",
        "Tran ID",
        "Withdrawals",
        "Deposits",
        "Another Head",
        "One more head",
        "Last one"
    ],
    [   
        "01/05/2024",
        "TFR",
        "S81420904S81420",
        "S81420904",
        "S81420904",
        "S81420904",
        "700.00",
        ""
    ],
    [
        "01/05/2024",
        "TFR",
        "S84554541",
        "S84554541",
        "S84554541",
        "S84554541",
        "",
        "1.01"
    ]
]

Using the following typst script:

#let txn = json("data2.json")
#table(
  columns: 8,
  ..txn.flatten()
)

And getting the following output:

As it can be seen, the Tran ID spills over in to the next cell. I understand that there is no place to break that text in the cell, but if it’s possible to just wrap along the cell boundary and put the remaining text inthe next line, it will look much better.

You can use a regex that matches the data in the “Tran ID” column, and use it to put a soft hyphen (if you want a hyphen) or a zero-width space (if you don’t want a hyphen) between each character. You also want to enable hyphenation in general (or scoped to the table), so that “Withdrawals” doesn’t overflow:

#set text(hyphenate: true)
#show regex("(S[0-9]+)+"): it => {
  it.text.codepoints().join(sym.zws) // or .join[-?]
}

#table(
  columns: 8,
  ..txn.flatten()
)

If you can’t use a regex, you could also use a show rule limited to the third column, though you then probably want to scope it to that one table:

#{
  show table.cell.where(x: 2): cell => {
    show regex("\b.+?\b"): it => it.text.codepoints().join(sym.zws)
    cell
  }

  table(
    columns: 8,
    ..txn.flatten()
  )
}
1 Like

Thanks, I went with the second suggestion and it worked perfectly. I used chatgpt to understand exactly how this snippet works and here is the answer for any one stumbling upon this later:

Overview

This snippet utilizes Typst’s capabilities to process and transform text using regular expressions. Specifically, it:

  1. Finds all words in a given text using a regular expression.
  2. Transforms each word by inserting zero-width spaces between its characters.
  3. Displays the transformed text with these modifications.

Detailed Breakdown

Let’s dissect each component of the snippet to understand how it works:

1. regex("\b.+?\b")

  • Purpose: Defines a regular expression pattern to identify parts of the text to be transformed.

  • Pattern Explanation:

    • \b: Word Boundary

      • Matches the position between a word character (typically letters, digits, or underscores) and a non-word character. It ensures that the regex matches whole words rather than substrings within words.
    • .+?: Non-Greedy Match of One or More Characters

      • .: Matches any character except newline characters.
      • +: Quantifier that matches one or more of the preceding element (. in this case).
      • ?: Makes the preceding quantifier non-greedy, meaning it matches the smallest possible string that satisfies the pattern.
  • Combined Pattern (\b.+?\b):

    • This regex matches whole words in the text by finding sequences of characters that start and end at word boundaries. The non-greedy .+? ensures that it matches the smallest possible sequence between word boundaries, effectively capturing individual words.

2. it => it.text.codepoints().join(sym.zws)

  • Purpose: Defines a transformation function (a lambda) that is applied to each regex match (it).

  • Components:

    • it: Represents the current match object found by the regex.

    • it.text: Extracts the text content of the current match (i.e., the word matched by the regex).

    • codepoints():

      • Function: Converts the string into a list of Unicode code points (essentially, individual characters).
      • Example:
        • "Hello" → ["H", "e", "l", "l", "o"]
    • join(sym.zws):

      • Function: Joins the list of characters into a single string, inserting a zero-width space (sym.zws) between each character.
      • sym.zws: Represents a zero-width space character in Typst, which is invisible but allows for potential line breaks or other text processing.
      • Example:
        • ["H", "e", "l", "l", "o"] joined with sym.zws → "H​e​l​l​o" (with zero-width spaces between letters)
  • Overall Transformation:

    • Takes each word matched by the regex and inserts zero-width spaces between its characters. This can influence how the text is rendered, allowing for flexible line breaking or other text manipulations without altering the visible content.

3. show

  • Purpose: Renders or displays the transformed text within the Typst document.

  • Functionality:

    • Applies the defined regex and transformation to the input text.
    • Outputs the result, which includes the zero-width spaces inserted between characters of each word.

Putting It All Together

Here’s a step-by-step execution of the snippet:

  1. Input Text: Suppose you have the following text in your Typst document:

    Hello World
    
  2. Regex Application:

    • The regex \b.+?\b scans the text and identifies two matches:
      • "Hello"
      • "World"
  3. Transformation Function:

    • For each matched word, the lambda function it => it.text.codepoints().join(sym.zws) is applied:

      • “Hello”:

        • codepoints(): ["H", "e", "l", "l", "o"]
        • join(sym.zws): "H​e​l​l​o" (with zero-width spaces)
      • “World”:

        • codepoints(): ["W", "o", "r", "l", "d"]
        • join(sym.zws): "W​o​r​l​d" (with zero-width spaces)
  4. Rendering with show:

    • The transformed text is displayed as:

      H​e​l​l​o W​o​r​l​d
      
      • Note: The zero-width spaces are invisible, so the text appears the same as the original. However, they enable more flexible text processing, such as allowing line breaks between characters if the layout requires it.

Practical Use Cases

  1. Flexible Line Breaking:

    • By inserting zero-width spaces between characters, you allow the text renderer to break lines between any two characters if necessary. This can be useful in narrow columns or responsive designs where words might need to wrap more flexibly.

Hey @raj2569! I’ve updated your post title to conform to our question guidelines: How to post in the Questions category

Make sure your title is a question you’d ask to a friend about Typst. :wink: