Skip to content

Commit

Permalink
Typst writer: make smart extension work.
Browse files Browse the repository at this point in the history
If `smart` is not enabled, a command in the default template will
disable smartquote substitutions.

When `smart` is enabled, render curly apostrophes as straight
and escape straight apostrophes.

When `smart` is disabled, render curly apostrophes as curly
and don't escape straight apostrophes.

And similarly for quotes, em and en dashes.

This should give more idiomatic typst output, with fewer unnecessary
escapes.

Closes #10271.
  • Loading branch information
jgm committed Oct 9, 2024
1 parent 0b51580 commit bdb1172
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 36 deletions.
5 changes: 5 additions & 0 deletions data/templates/default.typst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ $else$
$template.typst()$
$endif$

$if(smart)$
$else$
#set smartquote(enabled: false)

$endif$
$for(header-includes)$
$header-includes$

Expand Down
5 changes: 3 additions & 2 deletions src/Text/Pandoc/Extensions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,8 @@ getDefaultExtensions "jats_articleauthoring" = getDefaultExtensions "jats"
getDefaultExtensions "opml" = pandocExtensions -- affects notes
getDefaultExtensions "markua" = extensionsFromList
[]
getDefaultExtensions "typst" = extensionsFromList [Ext_citations]
getDefaultExtensions "typst" = extensionsFromList [Ext_citations,
Ext_smart]
getDefaultExtensions "dokuwiki" = extensionsFromList [Ext_smart]
getDefaultExtensions _ = extensionsFromList
[Ext_auto_identifiers]
Expand Down Expand Up @@ -656,6 +657,6 @@ getAllExtensions f = universalExtensions <> getAll f
getAll "mediawiki" = autoIdExtensions <>
extensionsFromList
[ Ext_smart ]
getAll "typst" = extensionsFromList [Ext_citations]
getAll "typst" = extensionsFromList [Ext_citations, Ext_smart]
getAll "djot" = extensionsFromList [Ext_sourcepos]
getAll _ = mempty
32 changes: 23 additions & 9 deletions src/Text/Pandoc/Writers/Typst.hs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pandocToTypst options (Pandoc meta blocks) = do
Right l ->
resetField "lang" (langLanguage l) .
maybe id (resetField "region") (langRegion l))
$ defField "smart" (isEnabled Ext_smart options)
$ defField "toc-depth" (tshow $ writerTOCDepth options)
$ defField "figure-caption-position"
(toPosition $ writerFigureCaptionPosition options)
Expand Down Expand Up @@ -351,8 +352,9 @@ inlineToTypst :: PandocMonad m => Inline -> TW m (Doc Text)
inlineToTypst inline =
case inline of
Str txt -> do
opts <- gets stOptions
context <- gets stEscapeContext
return $ escapeTypst context txt
return $ escapeTypst (isEnabled Ext_smart opts) context txt
Space -> return space
SoftBreak -> do
wrapText <- gets $ writerWrapText . stOptions
Expand Down Expand Up @@ -396,11 +398,17 @@ inlineToTypst inline =
contents <- inlinesToTypst inlines
return $ toTypstTextElement typstTextAttrs contents <> lab
Quoted quoteType inlines -> do
let q = case quoteType of
DoubleQuote -> literal "\""
SingleQuote -> literal "'"
opts <- gets stOptions
let smart = isEnabled Ext_smart opts
contents <- inlinesToTypst inlines
return $ q <> contents <> q
return $
case quoteType of
DoubleQuote
| smart -> "\"" <> contents <> "\""
| otherwise -> "" <> contents <> ""
SingleQuote
| smart -> "'" <> contents <> "'"
| otherwise -> "" <> contents <> ""
Cite citations inlines -> do
opts <- gets stOptions
if isEnabled Ext_citations opts
Expand Down Expand Up @@ -455,8 +463,8 @@ textstyle s inlines =
, needsEscapeAtLineStart c -> ("\\" <>)
_ -> id

escapeTypst :: EscapeContext -> Text -> Doc Text
escapeTypst context t =
escapeTypst :: Bool -> EscapeContext -> Text -> Doc Text
escapeTypst smart context t =
(case T.uncons t of
Just (c, _)
| needsEscapeAtLineStart c
Expand All @@ -469,9 +477,17 @@ escapeTypst context t =
where
escapeChar c
| c == '\160' = "~"
| c == '\8217', smart = "'" -- apostrophe
| c == '\8212', smart = "---" -- em dash
| c == '\8211', smart = "--" -- en dash
| needsEscape c = "\\" <> T.singleton c
| otherwise = T.singleton c
needsEscape '\160' = True
needsEscape '\8217' = smart
needsEscape '\8212' = smart
needsEscape '\8211' = smart
needsEscape '\'' = smart
needsEscape '"' = smart
needsEscape '[' = True
needsEscape ']' = True
needsEscape '#' = True
Expand All @@ -480,8 +496,6 @@ escapeTypst context t =
needsEscape '@' = True
needsEscape '$' = True
needsEscape '\\' = True
needsEscape '\'' = True
needsEscape '"' = True
needsEscape '`' = True
needsEscape '_' = True
needsEscape '*' = True
Expand Down
29 changes: 29 additions & 0 deletions test/command/10271.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
```
% pandoc -f markdown+smart -t typst+smart
"don't do it---"
^D
"don't do it---"
```
```
% pandoc -f markdown+smart -t typst-smart
"don't do it---"
^D
“don’t do it—”
```
```
% pandoc -f markdown-smart -t typst+smart
"don't do it---"
^D
\"don\'t do it---\"
```
```
% pandoc -f markdown-smart -t typst-smart
"don't do it---"
^D
"don't do it---"
```

4 changes: 2 additions & 2 deletions test/command/8966.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
^D
#strong[Samsonov T.E.] Shape-Adaptive Geometric Simplification of
Heterogeneous Line Datasets / T. E. Samsonov, O. P. Yakimova \/\/
International Journal of Geographical Information Science. 2017.
Vol. 31. № 8. pp.~1485-1520.
International Journal of Geographical Information Science. --- 2017. ---
Vol. 31. --- № 8. --- pp.~1485-1520.
```
8 changes: 4 additions & 4 deletions test/tables.typst
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ Multiline table with caption:
aligned],),
table.hline(),
[First], [row], [12.0], [Example of a row that spans multiple lines.],
[Second], [row], [5.0], [Heres another one. Note the blank line between
[Second], [row], [5.0], [Here's another one. Note the blank line between
rows.],
)]
, caption: [Heres the caption. It may span multiple lines.]
, caption: [Here's the caption. It may span multiple lines.]
, kind: table
)

Expand All @@ -72,7 +72,7 @@ Multiline table without caption:
aligned],),
table.hline(),
[First], [row], [12.0], [Example of a row that spans multiple lines.],
[Second], [row], [5.0], [Heres another one. Note the blank line between
[Second], [row], [5.0], [Here's another one. Note the blank line between
rows.],
)]
, kind: table
Expand All @@ -98,7 +98,7 @@ Multiline table without column headers:
columns: (15%, 13.75%, 16.25%, 35%),
align: (center,left,right,auto,),
[First], [row], [12.0], [Example of a row that spans multiple lines.],
[Second], [row], [5.0], [Heres another one. Note the blank line between
[Second], [row], [5.0], [Here's another one. Note the blank line between
rows.],
)]
, kind: table
Expand Down
38 changes: 19 additions & 19 deletions test/writer.typst
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@
)


This is a set of tests for pandoc. Most of them are adapted from John Grubers
This is a set of tests for pandoc. Most of them are adapted from John Gruber's
markdown test suite.

#horizontalrule
Expand Down Expand Up @@ -164,13 +164,13 @@ with no blank line

= Paragraphs
<paragraphs>
Heres a regular paragraph.
Here's a regular paragraph.

In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.
Because a hard-wrapped line in the middle of a paragraph looked like a list
item.

Heres one with a bullet. \* criminey.
Here's one with a bullet. \* criminey.

There should be a hard line break \
here.
Expand Down Expand Up @@ -320,7 +320,7 @@ Multiple paragraphs:

+ Item 1, graf one.

Item 1. graf two. The quick brown fox jumped over the lazy dogs back.
Item 1. graf two. The quick brown fox jumped over the lazy dog's back.

+ Item 2.

Expand All @@ -332,7 +332,7 @@ Multiple paragraphs:
- Tab
- Tab

Heres another:
Here's another:

+ First
+ Second:
Expand Down Expand Up @@ -549,7 +549,7 @@ Interpreted markdown in a table:

This is #emph[emphasized]
And this is #strong[strong]
Heres a simple block:
Here's a simple block:

#block[
foo
Expand Down Expand Up @@ -596,7 +596,7 @@ Code:
<hr />
```

Hrs:
Hr's:

#horizontalrule

Expand Down Expand Up @@ -637,14 +637,14 @@ a^b c^d, a\~b c\~d.

'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'

'He said, "I want to go."' Were you alive in the 70s?
'He said, "I want to go."' Were you alive in the 70's?

Here is some quoted '`code`' and a
"#link("http://example.com/?foo=1&bar=2")[quoted link];".

Some dashes: onetwo threefour five.
Some dashes: one---two --- three---four --- five.

Dashes between numbers: 57, 25566, 19871999.
Dashes between numbers: 5--7, 255--66, 1987--1999.

Ellipses…and…and….

Expand All @@ -658,19 +658,19 @@ Ellipses…and…and….
- $alpha and omega$
- $223$
- $p$-Tree
- Heres some display math:
- Here's some display math:
$ frac(d, d x) f (x) = lim_(h arrow.r 0) frac(f (x + h) - f (x), h) $
- Heres one that has a line break in it: $alpha + omega times x^2$.
- Here's one that has a line break in it: $alpha + omega times x^2$.

These shouldnt be math:
These shouldn't be math:

- To get the famous equation, write `$e = mc^2$`.
- \$22,000 is a #emph[lot] of money. So is \$34,000. (It worked if "lot" is
emphasized.)
- Shoes (\$20) and socks (\$5).
- Escaped `$`: \$73 #emph[this should be emphasized] 23\$.

Heres a LaTeX table:
Here's a LaTeX table:

#horizontalrule

Expand Down Expand Up @@ -776,14 +776,14 @@ Foo #link("/url/")[biz];.

== With ampersands
<with-ampersands>
Heres a
Here's a
#link("http://example.com/?foo=1&bar=2")[link with an ampersand in the URL];.

Heres a link with an amersand in the link text: #link("http://att.com/")[AT&T];.
Here's a link with an amersand in the link text: #link("http://att.com/")[AT&T];.

Heres an #link("/script?foo=1&bar=2")[inline link];.
Here's an #link("/script?foo=1&bar=2")[inline link];.

Heres an #link("/script?foo=1&bar=2")[inline link in pointy braces];.
Here's an #link("/script?foo=1&bar=2")[inline link in pointy braces];.

== Autolinks
<autolinks>
Expand Down Expand Up @@ -825,7 +825,7 @@ Here is a movie #box(image("movie.jpg")) icon.
<footnotes>
Here is a footnote reference,#footnote[Here is the footnote. It can go anywhere
after the footnote reference. It need not be placed at the end of the document.]
and another.#footnote[Heres the long note. This one contains multiple blocks.
and another.#footnote[Here's the long note. This one contains multiple blocks.

Subsequent blocks are indented to show that they belong to the footnote (as with
list items).
Expand Down

0 comments on commit bdb1172

Please sign in to comment.