diff --git a/data/templates/default.typst b/data/templates/default.typst index 1e7b5efd422e..8efe33887a7d 100644 --- a/data/templates/default.typst +++ b/data/templates/default.typst @@ -28,6 +28,11 @@ $else$ $template.typst()$ $endif$ +$if(smart)$ +$else$ +#set smartquote(enabled: false) + +$endif$ $for(header-includes)$ $header-includes$ diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs index 868ab9609243..7f1b35c17bfc 100644 --- a/src/Text/Pandoc/Extensions.hs +++ b/src/Text/Pandoc/Extensions.hs @@ -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] @@ -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 diff --git a/src/Text/Pandoc/Writers/Typst.hs b/src/Text/Pandoc/Writers/Typst.hs index 80ae6dab3f18..42a17dcccba1 100644 --- a/src/Text/Pandoc/Writers/Typst.hs +++ b/src/Text/Pandoc/Writers/Typst.hs @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 @@ -480,8 +496,6 @@ escapeTypst context t = needsEscape '@' = True needsEscape '$' = True needsEscape '\\' = True - needsEscape '\'' = True - needsEscape '"' = True needsEscape '`' = True needsEscape '_' = True needsEscape '*' = True diff --git a/test/command/10271.md b/test/command/10271.md new file mode 100644 index 000000000000..40f5c0a3e59d --- /dev/null +++ b/test/command/10271.md @@ -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---" + +``` + diff --git a/test/command/8966.md b/test/command/8966.md index f0c9e99e100f..de70fe7207e2 100644 --- a/test/command/8966.md +++ b/test/command/8966.md @@ -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. ``` diff --git a/test/tables.typst b/test/tables.typst index 3736a7193cb1..9bdcc13b8966 100644 --- a/test/tables.typst +++ b/test/tables.typst @@ -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], [Here’s another one. Note the blank line between + [Second], [row], [5.0], [Here's another one. Note the blank line between rows.], )] - , caption: [Here’s the caption. It may span multiple lines.] + , caption: [Here's the caption. It may span multiple lines.] , kind: table ) @@ -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], [Here’s another one. Note the blank line between + [Second], [row], [5.0], [Here's another one. Note the blank line between rows.], )] , kind: table @@ -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], [Here’s another one. Note the blank line between + [Second], [row], [5.0], [Here's another one. Note the blank line between rows.], )] , kind: table diff --git a/test/writer.typst b/test/writer.typst index 7609e0db01b3..70298b2edb0a 100644 --- a/test/writer.typst +++ b/test/writer.typst @@ -133,7 +133,7 @@ ) -This is a set of tests for pandoc. Most of them are adapted from John Gruber’s +This is a set of tests for pandoc. Most of them are adapted from John Gruber's markdown test suite. #horizontalrule @@ -164,13 +164,13 @@ with no blank line = Paragraphs -Here’s 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. -Here’s one with a bullet. \* criminey. +Here's one with a bullet. \* criminey. There should be a hard line break \ here. @@ -320,7 +320,7 @@ Multiple paragraphs: + Item 1, graf one. - Item 1. graf two. The quick brown fox jumped over the lazy dog’s back. + Item 1. graf two. The quick brown fox jumped over the lazy dog's back. + Item 2. @@ -332,7 +332,7 @@ Multiple paragraphs: - Tab - Tab -Here’s another: +Here's another: + First + Second: @@ -549,7 +549,7 @@ Interpreted markdown in a table: This is #emph[emphasized] And this is #strong[strong] -Here’s a simple block: +Here's a simple block: #block[ foo @@ -596,7 +596,7 @@ Code:
``` -Hr’s: +Hr's: #horizontalrule @@ -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 70’s? +'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: one—two — three—four — five. +Some dashes: one---two --- three---four --- five. -Dashes between numbers: 5–7, 255–66, 1987–1999. +Dashes between numbers: 5--7, 255--66, 1987--1999. Ellipses…and…and…. @@ -658,11 +658,11 @@ Ellipses…and…and…. - $alpha and omega$ - $223$ - $p$-Tree -- Here’s 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) $ -- Here’s 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 shouldn’t 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 @@ -670,7 +670,7 @@ These shouldn’t be math: - Shoes (\$20) and socks (\$5). - Escaped `$`: \$73 #emph[this should be emphasized] 23\$. -Here’s a LaTeX table: +Here's a LaTeX table: #horizontalrule @@ -776,14 +776,14 @@ Foo #link("/url/")[biz];. == With ampersands -Here’s a +Here's a #link("http://example.com/?foo=1&bar=2")[link with an ampersand in the URL];. -Here’s 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];. -Here’s an #link("/script?foo=1&bar=2")[inline link];. +Here's an #link("/script?foo=1&bar=2")[inline link];. -Here’s 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 @@ -825,7 +825,7 @@ Here is a movie #box(image("movie.jpg")) icon. 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[Here’s 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).