jgm / pandoc

Universal markup converter
https://pandoc.org
Other
33.73k stars 3.33k forks source link

Unexcepted escape seq in typst template. #9823

Closed black-desk closed 2 months ago

black-desk commented 2 months ago

Explain the problem.

I have a 1.md like this:

---
author:
  - name: XXX
    email: XXX@xxx.com
---

XXX

Then I run:

pandoc ./1.md --standalone -o 1.typ

I got 1.typ as:

// Some definitions presupposed by pandoc's typst output.
#let horizontalrule = [
  #line(start: (25%,0%), end: (75%,0%))
]

#let endnote(num, contents) = [
  #stack(dir: ltr, spacing: 3pt, super[#num], contents)
]
#show terms: it => {
  it.children
    .map(child => [
      #strong[#child.term]
      #block(inset: (left: 1.5em, top: -0.4em))[#child.description]
      ])
    .join()
}

#set table(
  inset: 6pt,
  stroke: none
)

#let conf(
  title: none,
  authors: (),
  keywords: (),
  date: none,
  abstract: none,
  cols: 1,
  margin: (x: 1.25in, y: 1.25in),
  paper: "us-letter",
  lang: "en",
  region: "US",
  font: (),
  fontsize: 11pt,
  sectionnumbering: none,
  doc,
) = {
  set document(
    title: title,
    author: authors.map(author => author.name),
    keywords: keywords,
  )
  set page(
    paper: paper,
    margin: margin,
    numbering: "1",
  )
  set par(justify: true)
  set text(lang: lang,
           region: region,
           font: font,
           size: fontsize)
  set heading(numbering: sectionnumbering)

  if title != none {
    align(center)[#block(inset: 2em)[
      #text(weight: "bold", size: 1.5em)[#title]
    ]]
  }

  if authors != none and authors != [] {
    let count = authors.len()
    let ncols = calc.min(count, 3)
    grid(
      columns: (1fr,) * ncols,
      row-gutter: 1.5em,
      ..authors.map(author =>
          align(center)[
            #author.name \
            #author.affiliation \
            #author.email
          ]
      )
    )
  }

  if date != none {
    align(center)[#block(inset: 1em)[
      #date
    ]]
  }

  if abstract != none {
    block(inset: 2em)[
    #text(weight: "semibold")[Abstract] #h(1em) #abstract
    ]
  }

  if cols == 1 {
    doc
  } else {
    columns(cols, doc)
  }
}
#show: doc => conf(
  authors: (
    ( name: "XXX",
      affiliation: "",
      email: "XXX\@xxx.com" ),
    ),
  cols: 1,
  doc,
)

XXX

The problem is that email: "XXX\@xxx.com", which make the pdf output of 1.typ looks like this:

图片

Note:

https://github.com/jgm/pandoc/blob/c19b44b071810fbad3a9b16e7a3638b231465bbc/src/Text/Pandoc/Writers/Typst.hs#L467

I think we maybe need a new context type like this:

https://github.com/jgm/pandoc/blob/c19b44b071810fbad3a9b16e7a3638b231465bbc/src/Text/Pandoc/Writers/Typst.hs#L476

Pandoc version?

❯ pandoc --version
pandoc 3.2
Features: +server +lua
Scripting engine: Lua 5.4
User data directory: /home/black_desk/.local/share/pandoc
Copyright (C) 2006-2024 John MacFarlane. Web: https://pandoc.org
This is free software; see the source for copying conditions. There is no
warranty, not even for merchantability or fitness for a particular purpose.
black-desk commented 2 months ago

Note: https://typst.app/docs/reference/foundations/str#escapes

iandol commented 2 months ago

I also have this problem with my email addresses, not sure what is correct in terms of escaping from the yaml to the email field, but I think before the @ was just passed through without problems (at least I previously used Typst and didn't see this but now I do)...

black-desk commented 2 months ago

I also have this problem with my email addresses, not sure what is correct in terms of escaping from the yaml to the email field, but I think before the @ was just passed through without problems (at least I previously used Typst and didn't see this but now I do)...

Might related to this commit:

https://github.com/jgm/pandoc/commit/ea9317c73d508d0ce7993db66edb239a3e968cdb

iandol commented 2 months ago

I'm not sure that commit is responsible, if I edit my custom template to use the [$author.email$] or "$author.email$" syntax both get the @ escaped. My internet is very flakey for searching commits, but there were a few recent changes to escape more typst content.

jgm commented 2 months ago

The field is parsed as Markdown, so it turns into Str "XXX@xxx.com". This in turn is rendered into typst with an escaped @ (because if we don't escape literal @s we can get accidental citations and references).

Some possible solutions:

    email: <XXX@xxx.com>

(will format as a linked email address)

    email: `XXX@xxx.com`

(will format as verbatim text)

    email: `XXX@xxx.com`{=typst}

(will just be a plain string without escapes).

jgm commented 2 months ago

In any case: not a bug.

iandol commented 2 months ago

Thanks @jgm.

If I use the link syntax, the link text is still escaped:

email: "#link("mailto:XXX@xxx.com")[XXX\@xxx.com];" ),

...and currently the backticked verbatim / raw inline is causing yaml parse errors:

https://pandoc.org/try/?params=%7B%22text%22%3A%22---%5Cntitle%3A+XXX%5Cnauthor%3A+%5Cn++-+name%3A+XXX%5Cn++++email%3A+%60XXX%40xxx.com%60%5Cn---%5Cn%5CnXXX%5Cn%22%2C%22to%22%3A%22typst%22%2C%22from%22%3A%22markdown%22%2C%22standalone%22%3Atrue%2C%22embed-resources%22%3Afalse%2C%22table-of-contents%22%3Afalse%2C%22number-sections%22%3Afalse%2C%22citeproc%22%3Afalse%2C%22html-math-method%22%3A%22plain%22%2C%22wrap%22%3A%22auto%22%2C%22highlight-style%22%3Anull%2C%22files%22%3A%7B%7D%2C%22template%22%3Anull%7D

iandol commented 2 months ago

OK, ` is reserved[1] (didn't it used to work before?), but YAML block literal syntax doesn't cause any YAML errors:

author:
  - name: XXX
    email: |
      `XXX@xxx.com`

... although the typst output gets some extra newlines these don't affect the PDF I think:

authors: (
    ( name: "XXX",
      affiliation: "",
      email: "`XXX@xxx.com`

" ),

[1] https://yaml.org/spec/1.2.2/#rule-c-reserved

jgm commented 2 months ago

Yeah, the link idea was not good. And the other idea requires using block syntax or maybe single quotes.

jgm commented 2 months ago

Perhaps we can adjust the escaping so that word-internal @ isn't escaped. I think that would be safe.

jgm commented 2 months ago

No such luck.

my@aoeu.com

in typst.app raises an error because the label aoeu.com isn't found.

jgm commented 2 months ago

Maybe the solution is to use [..] instead ".." in the template.

iandol commented 2 months ago

This works (at least for Typst CLI), using the current pandoc default template:

---
title: XXX
author:
  - name: XXX
    email: |
      `XXX@xxx.com`{=typst}
---

XXX
image