aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn MacFarlane <[email protected]>2023-03-26 13:37:08 -0700
committerJohn MacFarlane <[email protected]>2023-03-26 19:02:05 -0700
commitcd6b3bde622c93eea763e981692b4bc53dd5e5df (patch)
tree78659dda4e5c40ef4ab62e8ad3949165da442c9d /src
parent657ebffd8f4efe334e27e7398700c5b92e453363 (diff)
Typst writer improvements.
+ Fix non-decimal enumerated lists. + Fix endnotes ending with code blocks. + Improve default template to use a typst template. + Factor out definitions and typst template into partials. + Properly escape backslash and quote inside double quotes. + Update tests.
Diffstat (limited to 'src')
-rw-r--r--src/Text/Pandoc/Writers/Typst.hs54
1 files changed, 40 insertions, 14 deletions
diff --git a/src/Text/Pandoc/Writers/Typst.hs b/src/Text/Pandoc/Writers/Typst.hs
index bcecda035..12364ce37 100644
--- a/src/Text/Pandoc/Writers/Typst.hs
+++ b/src/Text/Pandoc/Writers/Typst.hs
@@ -28,14 +28,14 @@ import Data.Text (Text)
import Data.List (intercalate, intersperse)
import qualified Data.Text as T
import Control.Monad.State ( StateT, evalStateT, gets, modify )
-import Text.Pandoc.Writers.Shared ( metaToContext, defField, toLegacyTable )
+import Text.Pandoc.Writers.Shared ( metaToContext, defField, setField,
+ toLegacyTable, lookupMetaString )
import Text.Pandoc.Shared (isTightList, orderedListMarkers)
import Text.Pandoc.Writers.Math (convertMath)
import qualified Text.TeXMath as TM
import Text.DocLayout
import Text.DocTemplates (renderTemplate)
import Text.Pandoc.Extensions (Extension(..))
-import Control.Monad (zipWithM)
-- | Convert Pandoc to Typst.
writeTypst :: PandocMonad m => WriterOptions -> Pandoc -> m Text
@@ -66,11 +66,14 @@ pandocToTypst options (Pandoc meta blocks) = do
let notes = vsep $ zipWith
(\(num :: Int) cont ->
"#endnote" <> parens (brackets (text (show num))
- <> ", " <> brackets (chomp cont)))
+ <> ", " <> brackets (chomp cont <> cr)))
[1..] noteContents
let context = defField "body" main
$ defField "notes" notes
$ defField "toc" (writerTableOfContents options)
+ $ (case lookupMetaString "lang" meta of
+ "" -> id
+ lang -> setField "lang" $ T.takeWhile (/='-') lang)
$ (if writerNumberSections options
then defField "numbering" ("1.1.1.1.1" :: Text)
else id)
@@ -116,12 +119,27 @@ blockToTypst block =
HorizontalRule ->
return $ blankline <> "#horizontalrule" <> blankline
OrderedList attribs items -> do
- items' <- zipWithM (\marker item ->
- chomp <$> listItemToTypst 3 (literal marker) item)
- (orderedListMarkers attribs) items
- return $ (if isTightList items
+ let addBlock = case attribs of
+ (1, DefaultStyle, DefaultDelim) -> id
+ (1, Decimal, Period) -> id
+ (start, sty, delim) -> \x ->
+ "#block[" $$
+ ("#set enum" <>
+ parens (
+ "numbering: " <>
+ doubleQuoted
+ (head (orderedListMarkers
+ (1, sty, delim))) <>
+ ", start: " <>
+ text (show start) )) $$
+ x $$
+ "]"
+ items' <- mapM (fmap chomp . listItemToTypst 2 ("+ ")) items
+ return $ addBlock
+ (if isTightList items
then vcat items'
- else vsep items') $$ blankline
+ else vsep items')
+ $$ blankline
BulletList items -> do
items' <- mapM (fmap chomp . listItemToTypst 2 "- ") items
return $ (if isTightList items
@@ -208,9 +226,9 @@ inlineToTypst inline =
DisplayMath -> return $ "$ " <> literal r <> " $"
Code (_,cls,_) code -> return $
case cls of
- (lang:_) -> "#raw(lang=" <> doubleQuotes (literal lang) <>
- ", " <> doubleQuotes (literal code) <> ")"
- _ | T.any (=='`') code -> "#raw(" <> doubleQuotes (literal code) <> ")"
+ (lang:_) -> "#raw(lang=" <> doubleQuoted lang <>
+ ", " <> doubleQuoted code <> ")"
+ _ | T.any (=='`') code -> "#raw(" <> doubleQuoted code <> ")"
| otherwise -> "`" <> literal code <> "`"
RawInline fmt str ->
case fmt of
@@ -238,11 +256,11 @@ inlineToTypst inline =
then return $ -- Note: this loses locators, prefix, suffix
"#cite" <> parens
(mconcat $ intersperse ", " $
- map (doubleQuotes . literal . citationId) citations)
+ map (doubleQuoted . citationId) citations)
else inlinesToTypst inlines
Link _attrs inlines (src,_tit) -> do
contents <- inlinesToTypst inlines
- return $ "#link" <> parens (doubleQuotes (literal src)) <>
+ return $ "#link" <> parens (doubleQuoted src) <>
if render Nothing contents == src
then mempty
else nowrap $ brackets contents
@@ -250,7 +268,7 @@ inlineToTypst inline =
let width' = maybe mempty ((", width: " <>) . literal) $ lookup "width" kvs
let height' = maybe mempty ((", height: " <>) . literal) $
lookup "height" kvs
- return $ "#image(" <> doubleQuotes (literal src) <> width' <> height' <> ")"
+ return $ "#image(" <> doubleQuoted src <> width' <> height' <> ")"
Note blocks -> do -- currently typst has no footnotes!
-- TODO create endnotes with manual typesetting
contents <- blocksToTypst blocks
@@ -291,3 +309,11 @@ toLabel ident =
if T.null ident
then mempty
else "#label" <> parens (doubleQuotes (literal ident))
+
+doubleQuoted :: Text -> Doc Text
+doubleQuoted = doubleQuotes . literal . escape
+ where
+ escape = T.concatMap escapeChar
+ escapeChar '\\' = "\\\\"
+ escapeChar '"' = "\\\""
+ escapeChar c = T.singleton c