diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,5 @@
+# Revision history for pandoc-filter-graphviz
+
+## 0.1.0.0  -- YYYY-mm-dd
+
+* First version. Released on an unsuspecting world.
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2017, Jean-Pierre PRUNARET
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Jean-Pierre PRUNARET nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/pandoc-filter-graphviz.cabal b/pandoc-filter-graphviz.cabal
new file mode 100644
--- /dev/null
+++ b/pandoc-filter-graphviz.cabal
@@ -0,0 +1,37 @@
+-- Initial pandoc-filter-graphviz.cabal generated by cabal init.  For 
+-- further documentation, see http://haskell.org/cabal/users-guide/
+
+name:                pandoc-filter-graphviz
+version:             0.1.0.0
+synopsis:            A Pandoc filter to use graphviz
+description:         Interpret '~~~ graphviz' bloc as a call to graphviz software and substritude text with produced picture.
+homepage:            https://github.com/jpierre03/pandoc-filter-graphviz
+license:             BSD3
+license-file:        LICENSE
+author:              Jean-Pierre PRUNARET
+maintainer:          jean-pierre+git@prunetwork.fr
+-- copyright:           
+category:            Text
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+executable pandoc-filter-graphviz
+  main-is:             Main.hs
+  other-modules:
+    PandocFilterGraphviz
+  -- other-extensions:    
+  build-depends:       base > 4.5 && < 5
+    , bytestring
+    , pandoc
+    , text
+    , base16-bytestring
+    , cryptonite
+    , byteable
+    , containers
+    , directory
+    , process
+    , pandoc-types
+    , filepath
+  hs-source-dirs:      src
+  default-language:    Haskell2010
diff --git a/src/Main.hs b/src/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Main.hs
@@ -0,0 +1,10 @@
+module Main where
+
+import PandocFilterGraphviz
+
+import Text.Pandoc
+import Text.Pandoc.JSON
+
+main :: IO ()
+main =
+    toJSONFilter graphviz
diff --git a/src/PandocFilterGraphviz.hs b/src/PandocFilterGraphviz.hs
new file mode 100644
--- /dev/null
+++ b/src/PandocFilterGraphviz.hs
@@ -0,0 +1,114 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module PandocFilterGraphviz where
+
+import Crypto.Hash
+import Control.Monad (unless)
+
+import Data.ByteString (ByteString)
+import Data.Byteable (toBytes)
+import qualified Data.ByteString.Char8 as C8
+import qualified Data.ByteString.Base16 as B16
+
+import qualified Data.Map.Strict as M
+import Data.Text as T
+import Data.Text.Encoding as E
+
+import System.FilePath
+import System.Directory
+import System.Exit
+import System.Process (system)
+
+import Text.Pandoc
+import Text.Pandoc.JSON
+
+data Renderer = Dot | Neato | Twopi | Circo | FDP | SFDP | Patchwork
+instance Show Renderer where
+  show Dot = "dot"
+  show Neato = "neato"
+  show Twopi = "twopi"
+  show Circo = "circo"
+  show FDP = "fdp"
+  show SFDP = "sfdp"
+  show Patchwork = "patchwork"
+
+rendererFromString :: Text -> Maybe Renderer
+rendererFromString "dot" = Just Dot
+rendererFromString "neato" = Just Neato
+rendererFromString "twopi" = Just Twopi
+rendererFromString "circo" = Just Circo
+rendererFromString "fdp" = Just FDP
+rendererFromString "sfdp" = Just SFDP
+rendererFromString "patchwork" = Just Patchwork
+rendererFromString _ = Nothing
+
+(¤) :: Text -> Text -> Text
+(¤) = T.append
+
+hexSha3_512 :: ByteString -> ByteString
+hexSha3_512 bs = C8.pack $ show (hash bs :: Digest SHA3_512)
+
+sha :: Text -> Text
+sha = E.decodeUtf8 . hexSha3_512 . B16.encode . E.encodeUtf8
+
+fileName4Code :: Text -> Text -> Maybe Text -> FilePath
+fileName4Code name source ext =
+  filename
+  where
+    dirname = name ¤ "-images"
+    shaN = sha source
+    barename = shaN ¤ (case ext of
+        Just e -> "." ¤ e
+        Nothing -> "")
+    filename = T.unpack dirname </> T.unpack barename
+
+getCaption :: M.Map Text Text -> (Text,Text)
+getCaption m = case M.lookup "caption" m of
+  Just cap -> (cap,"fig:")
+  Nothing -> ("","")
+
+getFmt :: Maybe Format -> String
+getFmt mfmt = case mfmt of
+  Just (Format "latex") -> "pdf"
+  Just _ -> "png"
+  Nothing -> "png"
+
+renderDot1 :: Maybe Format -> Maybe Renderer -> FilePath -> IO FilePath
+renderDot1 mfmt mrndr src = renderDot mfmt rndr src dst >> return dst
+  where
+    dst = (dropExtension src) <.> (getFmt mfmt)
+    rndr = case mrndr of
+      Just r -> r
+      Nothing -> Dot
+
+renderDot :: Maybe Format -> Renderer -> FilePath -> FilePath -> IO ExitCode
+renderDot mfmt rndr src dst =
+  system $
+    Prelude.unwords [ show rndr
+                    , "-T" ++ (getFmt mfmt)
+                    , "-o" ++ show dst
+                    , show src ]
+
+graphviz :: Maybe Format -> Block -> IO Block
+graphviz mfmt cblock@(CodeBlock (id, classes, attrs) content) =
+  if "graphviz" `elem` classes then do
+    ensureFile dest >> writeFile dest content
+    img <- renderDot1 mfmt mrndr dest
+    ensureFile img
+    return $ Para [Image (id,classes,attrs) [] (img, T.unpack caption)]
+  else return cblock
+  where
+    dest = fileName4Code "graphviz" (T.pack content) (Just "dot")
+    ensureFile fp =
+      let dir = takeDirectory fp in
+      createDirectoryIfMissing True dir >> doesFileExist fp >>=
+        \exist ->
+          unless exist $ writeFile fp ""
+    toTextPairs = Prelude.map (\(f,s) -> (T.pack f,T.pack s))
+    m = M.fromList $ toTextPairs $ attrs
+    mrndr = case M.lookup "renderer" m of
+      Just str -> rendererFromString str
+      _ -> Nothing
+    (caption, typedef) = getCaption m
+graphviz fmt x = return x
+
