Integrate PlantUML diagrams into Hakyll (Old)
** Go here Integrate PlantUML diagrams into Hakyll (Updated) that uses Hakyll libraries rather than my reinvent-the-wheel-bad implementations**
0.0.1 Plant UML hex image link
Plant UML allows us to draw UML diagram using simple code.
Our goal is to allow us to write code in our pandocs markdown files in hakyll that will automatically generate the UML.
PlantUML has a server that can convert links to image urls.
http://www.plantuml.com/plantuml/svg/~h407374617274756d6c0a416c6963652d3e426f62203a204920616d207573696e67206865780a40656e64756d6c
- Converts code into ASCII decimal
- Converts ASCII decimal into hex
- Hex is part of URL of planttext which will generate our image
strToASCII :: [Char] -> [Int]
= fmap ord xs
strToASCII xs
asciiToHex :: [Int] -> [String]
= fmap (\x -> showHex x "") xs
asciiToHex xs
plantUMLhex :: [Char] -> String
= (concat. asciiToHex . strToASCII) xs
plantUMLhex xs
-- replaceLF replaces markdown doublespace newlines hex with plantUML compatible newline hex
replaceLF :: T.Text -> T.Text
= (T.replace "20200" "0a") xs
replaceLF xs
hexCode :: T.Text -> T.Text
= (replaceLF (T.pack ( plantUMLhex (T.unpack y))))
hexCode y
planthtml :: T.Text -> T.Text
= T.pack ("<figure><img src='http://www.plantuml.com/plantuml/svg/~h" <> (T.unpack $ hexCode y) <>"'></figure>") planthtml y
Above is our helper functions that will be used to generate the hex of our code.
example:
INPUT Markdown codeblock content : @startuml
strToASCII
- Convert@startuml
to [64,115,116,97,114,116,117,109,108]asciiToHex
- Convert ASCII decimal encoding with [40,73,74,61,72,74,75,6D,6C]concat
- [40,73,74,61,72,74,75,6D,6C] to “407374617274756D6C”replaceLF
- replace “20200” substrings with “0a”, in this case there are none.- intermediate hex result: “407374617274756D6C”
planthtml
- Use hex result to create a ‘http://www.plantuml.com…’ img src DOM string.
Notice in the plantuml image link above http://www.plantuml.com/plantuml/svg/~h407374617274756d6c…
the string after “~h” begins with “407374617274756D6C” which is our result.
replaceLF is neccessary because the LineFeed of our Pandocs doesn’t match PlantUML server’s LineFeed. Therefore we design a function that replaces our LineFeed hex with a suitable hex. This means in your markdown file you must add double space at the end of a line for a new line. NOTE: Updated post fixes this problem Integrate PlantUML diagrams into Hakyll (Updated)
0.0.2 Pandocs filtering
Now we need to modify site.hs so that Hakyll will transform a PlantUML code block into a html img that links to the Planttext generated image.
We can do this with Hakyll’s Pandocs Filtering.
--Pandoc filtering,
addToCodeBlock :: Pandoc -> Pandoc
= walk ftranslate
addToCodeBlock where ftranslate :: Block -> Block
CodeBlock ("",["plantuml"],[]) txt ) = RawBlock (Format "html") (planthtml txt)
ftranslate (= x ftranslate x
ftranslate (CodeBlock ("",["plantuml"],[]) txt )
pattern matches CodeBlock objects in pandoc and finds “plantuml” annotations denoted by the Attr object ("",["plantuml"],[])
The Content of our CodeBlock is pattern matched as txt
.
After pattern matching it converts it into a raw html block, and applies our “Code to Img DOM” transformation function planthtml
on the content.
INPUT Markdown codeblock :
'''plantuml
@startuml
Alice->Bob : I am using hex
@enduml
'''
Output DOM element :
0.0.3 Full Code
add under “build-depends” in your .cabal file
pandoc,
pandoc-types,
text
Add to your site.hs
import Text.Pandoc.Definition
import Text.Pandoc.Walk
import Data.Text
import Numeric (showHex)
import Data.Char (ord)
strToASCII :: [Char] -> [Int]
= fmap ord xs
strToASCII xs
asciiToHex :: [Int] -> [String]
= fmap (\x -> showHex x "") xs
asciiToHex xs
plantUMLhex :: [Char] -> String
= (concat. asciiToHex . strToASCII) xs
plantUMLhex xs
-- replaceLF replaces markdown doublespace newlines hex with plantUML compatible newline hex
replaceLF :: T.Text -> T.Text
= (T.replace "20200" "0a") xs
replaceLF xs
hexCode :: T.Text -> T.Text
= (replaceLF (T.pack ( plantUMLhex (T.unpack y))))
hexCode y
planthtml :: T.Text -> T.Text
= T.pack ("<figure><img src='http://www.plantuml.com/plantuml/svg/~h" <> (T.unpack $ hexCode y) <>"'></figure>")
planthtml y
--Pandoc filtering,
addToCodeBlock :: Pandoc -> Pandoc
= walk ftranslate
addToCodeBlock where ftranslate :: Block -> Block
CodeBlock ("",["plantuml"],[]) txt ) = RawBlock (Format "html") (planthtml txt)
ftranslate (= x ftranslate x
- If you’ve followed my mathjax hakyll tutorial, simply add the code below:
mathJaxAddedCompiler :: Compiler (Item String)
= pandocCompilerWithTransform readMathjaxOptions writeMathjaxOptions addToCodeBlock mathJaxAddedCompiler
- If you didn’t follow my mathjax hakyll tutorial, then add the code below:
simpleCompiler :: Compiler (Item String)
= pandocCompilerWithTransform defaultHakyllReaderOptions defaultHakyllWriterOptions addToCodeBlock simpleCompiler