Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZimWiki writer: added source code naming, removed internal formatting from note and table cells #3446

Merged
merged 1 commit into from
Feb 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 54 additions & 24 deletions src/Text/Pandoc/Writers/ZimWiki.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

{- |
Module : Text.Pandoc.Writers.ZimWiki
Copyright : Copyright (C) 2008-2015 John MacFarlane, 2016 Alex Ivkin
Copyright : Copyright (C) 2008-2015 John MacFarlane, 2017 Alex Ivkin
License : GNU GPL, version 2 or above

Maintainer : Alex Ivkin <[email protected]>
Stability : alpha
Stability : beta
Portability : portable

Conversion of 'Pandoc' documents to ZimWiki markup.
Expand All @@ -44,20 +44,22 @@ import Data.Default (Default(..))
import Network.URI ( isURI )
import Control.Monad ( zipWithM )
import Control.Monad.State ( modify, State, get, evalState )
--import Control.Monad.Reader ( ReaderT, runReaderT, ask, local )
import Text.Pandoc.Class ( PandocMonad )
import qualified Data.Map as Map

data WriterState = WriterState {
stItemNum :: Int,
stIndent :: String -- Indent after the marker at the beginning of list items
stIndent :: String, -- Indent after the marker at the beginning of list items
stInTable :: Bool, -- Inside a table
stInLink :: Bool -- Inside a link description
}

instance Default WriterState where
def = WriterState { stItemNum = 1, stIndent = "" }
def = WriterState { stItemNum = 1, stIndent = "", stInTable = False, stInLink = False }

-- | Convert Pandoc to ZimWiki.
writeZimWiki :: PandocMonad m => WriterOptions -> Pandoc -> m String
writeZimWiki opts document = return $ evalState (pandocToZimWiki opts document) (WriterState 1 "")
writeZimWiki opts document = return $ evalState (pandocToZimWiki opts document) def

-- | Return ZimWiki representation of document.
pandocToZimWiki :: WriterOptions -> Pandoc -> State WriterState String
Expand Down Expand Up @@ -129,9 +131,15 @@ blockToZimWiki opts (Header level _ inlines) = do
return $ eqs ++ " " ++ contents ++ " " ++ eqs ++ "\n"

blockToZimWiki _ (CodeBlock (_,classes,_) str) = do
-- Remap languages into the gtksourceview2 convention that ZimWiki source code plugin is using
let langal = [("javascript", "js"), ("bash", "sh"), ("winbatch", "dosbatch")]
let langmap = Map.fromList langal
return $ case classes of
[] -> "'''\n" ++ cleanupCode str ++ "\n'''\n" -- no lang block is a quote block
(x:_) -> "{{{code: lang=\"" ++ x ++ "\" linenumbers=\"True\"\n" ++ str ++ "\n}}}\n" -- for zim's code plugin, go verbatim on the lang spec
[] -> "'''\n" ++ cleanupCode str ++ "\n'''\n" -- turn no lang block into a quote block
(x:_) -> "{{{code: lang=\"" ++
(case Map.lookup x langmap of
Nothing -> x
Just y -> y) ++ "\" linenumbers=\"True\"\n" ++ str ++ "\n}}}\n" -- for zim's code plugin, go verbatim on the lang spec

blockToZimWiki opts (BlockQuote blocks) = do
contents <- blockListToZimWiki opts blocks
Expand All @@ -145,7 +153,7 @@ blockToZimWiki opts (Table capt aligns _ headers rows) = do
return $ "" ++ c ++ "\n"
headers' <- if all null headers
then zipWithM (tableItemToZimWiki opts) aligns (rows !! 0)
else zipWithM (tableItemToZimWiki opts) aligns headers
else mapM (inlineListToZimWiki opts) (map removeFormatting headers) -- emphasis, links etc. are not allowed in table headers
rows' <- mapM (zipWithM (tableItemToZimWiki opts) aligns) rows
let widths = map (maximum . map length) $ transpose (headers':rows')
let padTo (width, al) s =
Expand All @@ -167,10 +175,10 @@ blockToZimWiki opts (Table capt aligns _ headers rows) = do
then replicate (width-1) '-' ++ ":"
else ":" ++ replicate (width-2) '-' ++ ":"
let underheader = "|" ++ intercalate "|" (zipWith borderCell (zip widths aligns) headers') ++ "|"
let renderRow sep cells = sep ++ intercalate sep (zipWith padTo (zip widths aligns) cells) ++ sep
let renderRow cells = "|" ++ intercalate "|" (zipWith padTo (zip widths aligns) cells) ++ "|"
return $ captionDoc ++
(if null headers' then "" else renderRow "|" headers' ++ "\n") ++ underheader ++ "\n" ++
unlines (map (renderRow "|") rows')
(if null headers' then "" else renderRow headers' ++ "\n") ++ underheader ++ "\n" ++
unlines (map renderRow rows')

blockToZimWiki opts (BulletList items) = do
indent <- stIndent <$> get
Expand Down Expand Up @@ -255,7 +263,9 @@ tableItemToZimWiki opts align' item = do
(if align' == AlignLeft || align' == AlignCenter
then " "
else "")
contents <- blockListToZimWiki opts item -- local (\s -> s { stBackSlashLB = True }) $
modify $ \s -> s { stInTable = True }
contents <- blockListToZimWiki opts item
modify $ \s -> s { stInTable = False }
return $ mkcell contents

-- | Convert list of Pandoc block elements to ZimWiki.
Expand Down Expand Up @@ -305,7 +315,15 @@ inlineToZimWiki opts (Cite _ lst) = inlineListToZimWiki opts lst

inlineToZimWiki _ (Code _ str) = return $ "''" ++ str ++ "''"

inlineToZimWiki _ (Str str) = return $ escapeString str
inlineToZimWiki _ (Str str) = do
inTable <- stInTable <$> get
inLink <- stInLink <$> get
if inTable
then return $ substitute "|" "\\|" . escapeString $ str
else
if inLink
then return $ str
else return $ escapeString str

inlineToZimWiki _ (Math mathType str) = return $ delim ++ str ++ delim -- note: str should NOT be escaped
where delim = case mathType of
Expand All @@ -318,7 +336,11 @@ inlineToZimWiki opts (RawInline f str)
| f == Format "html" = do cont <- indentFromHTML opts str; return cont
| otherwise = return ""

inlineToZimWiki _ LineBreak = return "\n" -- was \\\\
inlineToZimWiki _ LineBreak = do
inTable <- stInTable <$> get
if inTable
then return "\\n"
else return "\n"

inlineToZimWiki opts SoftBreak =
case writerWrapText opts of
Expand All @@ -329,30 +351,38 @@ inlineToZimWiki opts SoftBreak =
inlineToZimWiki _ Space = return " "

inlineToZimWiki opts (Link _ txt (src, _)) = do
label <- inlineListToZimWiki opts txt
inTable <- stInTable <$> get
modify $ \s -> s { stInLink = True }
label <- inlineListToZimWiki opts $ removeFormatting txt -- zim does not allow formatting in link text, it takes the text verbatim, no need to escape it
modify $ \s -> s { stInLink = False }
let label'= if inTable
then "" -- no label is allowed in a table
else "|"++label
case txt of
[Str s] | "mailto:" `isPrefixOf` src -> return $ "<" ++ s ++ ">"
| escapeURI s == src -> return src
_ -> if isURI src
then return $ "[[" ++ src ++ "|" ++ label ++ "]]"
else return $ "[[" ++ src' ++ "|" ++ label ++ "]]"
then return $ "[[" ++ src ++ label' ++ "]]"
else return $ "[[" ++ src' ++ label' ++ "]]"
where src' = case src of
'/':xs -> xs -- with leading / it's a
_ -> src -- link to a help page
inlineToZimWiki opts (Image attr alt (source, tit)) = do
alt' <- inlineListToZimWiki opts alt
let txt = case (tit, alt) of
("", []) -> ""
("", _ ) -> "|" ++ alt'
(_ , _ ) -> "|" ++ tit
inTable <- stInTable <$> get
let txt = case (tit, alt, inTable) of
("",[], _) -> ""
("", _, False ) -> "|" ++ alt'
(_ , _, False ) -> "|" ++ tit
(_ , _, True ) -> ""
-- Relative links fail isURI and receive a colon
prefix = if isURI source then "" else ":"
return $ "{{" ++ prefix ++ source ++ imageDims opts attr ++ txt ++ "}}"

inlineToZimWiki opts (Note contents) = do
-- no concept of notes in zim wiki, use a text block
contents' <- blockListToZimWiki opts contents
return $ "((" ++ contents' ++ "))"
-- note - may not work for notes with multiple blocks
return $ " **{Note:** " ++ trimr contents' ++ "**}**"

imageDims :: WriterOptions -> Attr -> String
imageDims opts attr = go (toPx $ dimension Width attr) (toPx $ dimension Height attr)
Expand Down
46 changes: 23 additions & 23 deletions test/tables.zimwiki
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
Simple table with caption:

Demonstration of simple table syntax.
| Right|Left | Center |Default|
|------:|:-----|:--------:|-------|
| 12|12 | 12 |12 |
| 123|123 | 123 |123 |
| 1|1 | 1 |1 |
|Right|Left |Center |Default|
|----:|:----|:-----:|-------|
| 12|12 | 12 |12 |
| 123|123 | 123 |123 |
| 1|1 | 1 |1 |

Simple table without caption:

| Right|Left | Center |Default|
|------:|:-----|:--------:|-------|
| 12|12 | 12 |12 |
| 123|123 | 123 |123 |
| 1|1 | 1 |1 |
|Right|Left |Center |Default|
|----:|:----|:-----:|-------|
| 12|12 | 12 |12 |
| 123|123 | 123 |123 |
| 1|1 | 1 |1 |

Simple table indented two spaces:

Demonstration of simple table syntax.
| Right|Left | Center |Default|
|------:|:-----|:--------:|-------|
| 12|12 | 12 |12 |
| 123|123 | 123 |123 |
| 1|1 | 1 |1 |
|Right|Left |Center |Default|
|----:|:----|:-----:|-------|
| 12|12 | 12 |12 |
| 123|123 | 123 |123 |
| 1|1 | 1 |1 |

Multiline table with caption:

Here’s the caption. It may span multiple lines.
| Centered Header |Left Aligned | Right Aligned|Default aligned |
|:-----------------:|:-------------|--------------:|:------------------------------------------------------|
| 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 rows. |
|Centered Header|Left Aligned|Right Aligned|Default aligned |
|:-------------:|:-----------|------------:|:------------------------------------------------------|
| 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 rows. |

Multiline table without caption:

| Centered Header |Left Aligned | Right Aligned|Default aligned |
|:-----------------:|:-------------|--------------:|:------------------------------------------------------|
| 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 rows. |
|Centered Header|Left Aligned|Right Aligned|Default aligned |
|:-------------:|:-----------|------------:|:------------------------------------------------------|
| 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 rows. |

Table without column headers:

Expand Down
12 changes: 4 additions & 8 deletions test/writer.zimwiki
Original file line number Diff line number Diff line change
Expand Up @@ -606,22 +606,18 @@ Here is a movie {{:movie.jpg|movie}} icon.

====== Footnotes ======

Here is a footnote reference,((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.((Here’s the long note. This one contains multiple blocks.
Here is a footnote reference, **{Note:** 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. **{Note:** 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).

'''
{ <code> }
'''

If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.
)) This should //not// be a footnote reference, because it contains a space.[^my note] Here is an inline note.((This is //easier// to type. Inline notes may contain [[http://google.com|links]] and '']'' verbatim characters, as well as [bracketed text].
))
If you want, you can indent every line, but you can also be lazy and just indent the first line of each block.**}** This should //not// be a footnote reference, because it contains a space.[^my note] Here is an inline note. **{Note:** This is //easier// to type. Inline notes may contain [[http://google.com|links]] and '']'' verbatim characters, as well as [bracketed text].**}**

> Notes can go in quotes.((In quote.
> ))
> Notes can go in quotes. **{Note:** In quote.**}**

1. And in list items.((In list.))
1. And in list items. **{Note:** In list.**}**

This paragraph should not be part of the note, as it is not indented.