]> gitweb @ CieloNegro.org - Rakka.git/commitdiff
wrote more...
authorpho <pho@cielonegro.org>
Thu, 11 Oct 2007 14:04:58 +0000 (23:04 +0900)
committerpho <pho@cielonegro.org>
Thu, 11 Oct 2007 14:04:58 +0000 (23:04 +0900)
darcs-hash:20071011140458-62b54-bc2c7d82b98de0be509c94a04e7f974717602696.gz

16 files changed:
Makefile
Rakka.buildinfo.in
Rakka.cabal
Rakka/Page.hs
Rakka/Resource/Object.hs
Rakka/Resource/Render.hs
Rakka/Wiki.hs
Rakka/Wiki/Engine.hs
Rakka/Wiki/Formatter.hs
Rakka/Wiki/Parser.hs
Setup.hs
configure.ac
defaultPages/Help/Syntax
defaultPages/MainPage
test/RakkaUnitTest.hs [new file with mode: 0644]
test/WikiParserTest.hs [new file with mode: 0644]

index 41fe0529b92f99840db482cc72ad072f02127119..8ae8c88066633203c0606cb344ea359762e2a5a7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ run: build
        $(EXECUTABLE)
 
 .setup-config: $(CABAL_FILE) configure Setup Rakka.buildinfo.in
-       ./Setup configure
+       BUILD_TEST_SUITE=yes ./Setup configure
 
 configure: configure.ac
        autoconf
@@ -25,6 +25,9 @@ clean:
 install: build
        ./Setup install
 
+test: build
+       ./Setup test
+
 sdist: Setup
        ./Setup sdist
 
index f0b4306f50f3e0cf9ef5bca6fe4f9cb28d6aeab9..2949f948e6cc72bc2978ff5e81f3bab7939ba07c 100644 (file)
@@ -3,3 +3,8 @@ Executable:
     rakka
 GHC-Options:
     -DLOCALSTATEDIR="@RAKKA_LOCALSTATEDIR@"
+
+Executable:
+    RakkaUnitTest
+Buildable:
+    @BUILD_TEST_SUITE@
index 31c443aa47ff9624b91fe718e45f19b5782bc28f..ac736efb0e838a844013d1f5c85366c73aaa3856 100644 (file)
@@ -25,7 +25,8 @@ Extensions:
 GHC-Options:
     -fwarn-unused-imports
 Build-Depends:
-    Crypto, HsSVN, Lucu, base, encoding, filepath, hxt, mtl, network, parsec, unix
+    Crypto, HUnit, HsSVN, Lucu, base, encoding, filepath, hxt, mtl,
+    network, parsec, unix
 Exposed-Modules:
     Rakka.Page
     Rakka.Storage
@@ -42,6 +43,7 @@ Data-Files:
     defaultPages/Main_Page
     schemas/rakka-page-1.0.rng
 
+
 Executable:
     rakka
 Main-Is:
@@ -49,4 +51,12 @@ Main-Is:
 Extensions:
     Arrows
 GHC-Options:
-    -fwarn-unused-imports
\ No newline at end of file
+    -fwarn-unused-imports
+
+
+Executable:
+    RakkaUnitTest
+Main-Is:
+    test/RakkaUnitTest.hs
+Hs-Source-Dirs:
+    test
index c22e5206583c819facd8baab5ec437a4038d60a7..fdc622090771c780656cd80adac2548eaf9efc4d 100644 (file)
@@ -4,6 +4,7 @@ module Rakka.Page
     , encodePageName
     , decodePageName
     , mkPageURI
+    , mkPageFragmentURI
     , mkObjectURI
     )
     where
@@ -67,6 +68,14 @@ mkPageURI baseURI name
       }
 
 
+mkPageFragmentURI :: URI -> PageName -> String -> URI
+mkPageFragmentURI baseURI name fragment
+    = baseURI {
+        uriPath     = foldl combine "/" [uriPath baseURI, encodePageName name]
+      , uriFragment = ('#':fragment)
+      }
+
+
 mkObjectURI :: URI -> PageName -> URI
 mkObjectURI baseURI name
     = baseURI {
index 73f299bb955e39d628c7877c25175f0629d381c1..307792d472452b643ccd2c24efa9ba589b8b33fb 100644 (file)
@@ -9,7 +9,6 @@ import           Rakka.Environment
 import           Rakka.Page
 import           Rakka.Storage
 import           Rakka.SystemConfig
-import           System.FilePath
 import           System.Time
 
 
index 668d814b4394c0c35a11902d0a48b3b4213dbb07..e9929903e75fce46e92bd45fc717bbb0632c6666 100644 (file)
@@ -4,7 +4,6 @@ module Rakka.Resource.Render
     where
 
 import           Control.Arrow
-import           Control.Arrow.ArrowIf
 import           Control.Arrow.ArrowIO
 import           Control.Arrow.ArrowList
 import           Data.Char
@@ -72,11 +71,8 @@ handleRedirect env
 
 
 {-
-  [pageIsBinary が False の場合]
-
   <page site="CieloNegro"
-        baseURI="http://example.org/"
-        styleSheet="StyleSheet/Default"
+        styleSheet="http://example.org/object/StyleSheet/Default"
         name="Foo/Bar"
         type="text/x-rakka"
         isTheme="no"        -- text/css の場合のみ存在
@@ -97,11 +93,6 @@ handleRedirect env
       blah blah...
     </content>
   </page>
-
-  
-  [pageIsBinary が True の場合: content 要素の代はりに object 要素]
-  
-  <object data="/object/Foo/Bar" /> -- data 屬性に URI
 -}
 handleGetEntity :: (ArrowXml a, ArrowChoice a, ArrowIO a) => Environment -> a Page (Resource ())
 handleGetEntity env
@@ -115,8 +106,7 @@ handleGetEntity env
                 tree <- ( eelem "/"
                           += ( eelem "page"
                                += sattr "site"       siteName
-                               += sattr "baseURI"    (uriToString id baseURI "")
-                               += sattr "styleSheet" cssName
+                               += sattr "styleSheet" (uriToString id (mkObjectURI baseURI cssName) "")
                                += sattr "name"       (pageName page)
                                += sattr "type"       (show $ pageType page)
                                += ( case pageType page of
@@ -149,13 +139,8 @@ handleGetEntity env
                                               += sattr "page" page
                                                   | (lang, page) <- xs ]
                                   )
-                                                  
-                               += ( case pageIsBinary page of
-                                      False -> eelem "content"
-                                               += (constA page >>> formatPage)
-
-                                      True  -> eelem "object"
-                                               += sattr "data" (uriToString id (mkObjectURI baseURI $ pageName page) "")
+                               += ( eelem "content"
+                                    += (constA page >>> formatPage env )
                                   )
                                >>>
                                uniqueNamespacesFromDeclAndQNames
@@ -182,24 +167,11 @@ entityToXHTML
                      += txt " - "
                      += getXPathTreesInDoc "/page/@name/text()"
                    )
-                += ( eelem "base"
-                     += attr "href"
-                            ( getXPathTreesInDoc "/page/@baseURI/text()" )
-                   )
                 += ( eelem "link"
                      += sattr "rel"  "stylesheet"
                      += sattr "type" "text/css"
                      += attr "href"
-                            ( txt "./object/"
-                              <+>
-                              getXPathTreesInDoc "/page/@styleSheet/text()"
-                              >>>
-                              getText
-                              >>>
-                              arr encodePageName
-                              >>>
-                              mkText
-                            )
+                            ( getXPathTreesInDoc "/page/@styleSheet/text()" )
                    )
               )
            += ( eelem "body"
@@ -214,12 +186,6 @@ entityToXHTML
                      += ( eelem "div"
                           += sattr "class" "body"
                           += getXPathTreesInDoc "/page/content/*"
-                          += ( getXPathTreesInDoc "/page/object"
-                               `guards`
-                               eelem "object"
-                               += attr "data"
-                                      ( getXPathTreesInDoc "/page/object/@data/text()" )
-                             )
                         )
                    )
                 += ( eelem "div"
index f08aa96b5a8d363434d28738131b8006c36c644d..c5c2c68ec1b12b19e62bb73b85b81a5f96bc3ca2 100644 (file)
@@ -6,6 +6,9 @@ module Rakka.Wiki
     )
     where
 
+import           Rakka.Page
+
+
 type WikiPage = [WikiElement]
 
 
@@ -16,9 +19,9 @@ data WikiElement
 
 
 data BlockElement
-    = Header {
-        hdLevel :: !Int
-      , hdText  :: !String
+    = Heading {
+        headingLevel :: !Int
+      , headingText  :: !String
       }
     | EmptyLine
     deriving (Eq, Show)
@@ -26,4 +29,9 @@ data BlockElement
 
 data InlineElement
     = Text !String
+    | PageLink {
+        linkPage     :: !(Maybe PageName)
+      , linkFragment :: !(Maybe String)
+      , linkText     :: !(Maybe String)
+      }
     deriving (Eq, Show)
index 56a7adb97459857af218590f925968dc39be2a46..5aa5db4ac90e5d81a13ac28eedd086e90a585766 100644 (file)
@@ -4,11 +4,14 @@ module Rakka.Wiki.Engine
     where
 
 import           Control.Arrow
+import           Control.Arrow.ArrowIO
 import           Control.Arrow.ArrowTree
 import           Data.Encoding
 import           Data.Encoding.UTF8
 import           Network.HTTP.Lucu
+import           Rakka.Environment
 import           Rakka.Page
+import           Rakka.SystemConfig
 import           Rakka.Wiki.Parser
 import           Rakka.Wiki.Formatter
 import           Text.ParserCombinators.Parsec
@@ -16,24 +19,30 @@ import           Text.XML.HXT.Arrow.XmlArrow
 import           Text.XML.HXT.DOM.TypeDefs
 
 
-formatPage :: (ArrowXml a, ArrowChoice a) =>
-              a Page XmlTree
-formatPage
+formatPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
+              Environment
+           -> a Page XmlTree
+formatPage env
     = proc page
     -> do tree <- case pageType page of
                     MIMEType "text" "x-rakka" _
-                        -> formatWikiPage -< page
+                        -> formatWikiPage env -< page
           attachXHtmlNs -< tree
 
 
-formatWikiPage :: (ArrowXml a, ArrowChoice a) =>
-                  a Page XmlTree
-formatWikiPage
+formatWikiPage :: (ArrowXml a, ArrowChoice a, ArrowIO a) =>
+                  Environment
+               -> a Page XmlTree
+formatWikiPage env
     = proc page
     -> do let source = decodeLazy UTF8 (pageContent page)
           case parse wikiPage "" source of
-            Left  err   -> formatParseError   -< err
-            Right elems -> formatWikiElements -< elems
+            Left  err
+                -> formatParseError -< err
+
+            Right elems
+                -> do BaseURI baseURI <- getSysConfA (envSysConf env) (BaseURI undefined) -< ()
+                      formatWikiElements -< (baseURI, elems)
 
 
 formatParseError :: ArrowXml a => a ParseError XmlTree
index 1054d174582a535acafb2a4a88c1d448f790ae30..f5239381f1d718b38cc2c146ac226836ac4345c9 100644 (file)
@@ -6,6 +6,9 @@ module Rakka.Wiki.Formatter
 import           Control.Arrow
 import           Control.Arrow.ArrowList
 import           Data.List
+import           Data.Maybe
+import           Network.URI
+import           Rakka.Page
 import           Rakka.Wiki
 import           Text.XML.HXT.Arrow.XmlArrow
 import           Text.XML.HXT.DOM.TypeDefs
@@ -28,43 +31,63 @@ packParagraph elems = map pack grp
                                       Inline i -> i | x <- xs ]
                                                        
 
-formatWikiElements :: (ArrowXml a, ArrowChoice a) => a [WikiElement] XmlTree
+formatWikiElements :: (ArrowXml a, ArrowChoice a) => a (URI, [WikiElement]) XmlTree
 formatWikiElements
-    = proc elems
+    = proc (baseURI, elems)
     -> do chunk <- arrL id -< packParagraph elems
           case chunk of
             Left  x  -> formatBlock     -< x
-            Right xs -> formatParagraph -< xs
+            Right xs -> formatParagraph -< (baseURI, xs)
 
 
 formatBlock :: (ArrowXml a, ArrowChoice a) => a BlockElement XmlTree
 formatBlock 
     = proc b
-    -> do case b of
-            Header level text
-                -> formatHeader -< (level, text)
-            EmptyLine
-                -> none -< ()
+    -> case b of
+         Heading level text
+             -> formatHeading -< (level, text)
+         EmptyLine
+             -> none -< ()
 
 
-formatHeader :: ArrowXml a => a (Int, String) XmlTree
-formatHeader 
+formatHeading :: ArrowXml a => a (Int, String) XmlTree
+formatHeading 
     = proc (level, text)
     -> selem ("h" ++ show level) [txt text] -<< ()
 
 
-formatParagraph :: (ArrowXml a, ArrowChoice a) => a [InlineElement] XmlTree
+formatParagraph :: (ArrowXml a, ArrowChoice a) => a (URI, [InlineElement]) XmlTree
 formatParagraph 
-    = proc xs
-    -> do elem <- arrL id -< xs
-          tree <- ( eelem "p"
-                    += formatInline ) -< elem
-          returnA -< tree
+    = eelem "p"
+      += ( (arr fst &&& arrL snd)
+           >>>
+           formatInline
+         )
 
 
-formatInline :: (ArrowXml a, ArrowChoice a) => a InlineElement XmlTree
+formatInline :: (ArrowXml a, ArrowChoice a) => a (URI, InlineElement) XmlTree
 formatInline 
-    = proc i
-    -> do case i of
-            Text text
-                -> mkText -< text
+    = proc (baseURI, i)
+    -> case i of
+         Text text
+             -> mkText -< text
+
+         link@(PageLink _ _ _)
+             -> formatPageLink -< (baseURI, link)
+
+
+formatPageLink :: (ArrowXml a) => a (URI, InlineElement) XmlTree
+formatPageLink 
+    = proc (baseURI, PageLink page fragment text)
+    -> let uri    = case (page, fragment) of
+                      (Just  x, Just  y) -> mkPageFragmentURI baseURI x y
+                      (Just  x, Nothing) -> mkPageURI baseURI x
+                      (Nothing, Just  y) -> nullURI { uriFragment = ('#':y) }
+           href   = uriToString id uri ""
+           dLabel = fromMaybe "" page ++ fromMaybe "" (fmap ('#':) fragment)
+           label  = fromMaybe dLabel text
+       in
+         ( eelem "a"
+           += attr "href" (arr fst >>> mkText)
+           += (arr snd >>> mkText)
+         ) -< (href, label)
index b5ec74d509f9ec8e2f840bbf8f9851499e0a1406..968e6451673a72ad680a5b9c4c391d68b3cdfc81 100644 (file)
@@ -3,69 +3,124 @@ module Rakka.Wiki.Parser
     )
     where
 
+import           Data.Char
 import           Rakka.Wiki
 import           Text.ParserCombinators.Parsec
 
 
 wikiPage :: Parser WikiPage
-wikiPage = do xs <- many wikiElement
+wikiPage = do xs <- many (try wikiElement)
+              skipMany comment
               eof
               return xs
 
 
 wikiElement :: Parser WikiElement
-wikiElement = ( try (blockElement >>= return . Block)
+wikiElement = skipMany comment >>
+              ( try (blockElement >>= return . Block)
                 <|>
                 try (inlineElement >>= return . Inline)
               )
 
 
 blockElement :: Parser BlockElement
-blockElement = ( try header
+blockElement = ( try heading
                  <|>
                  try emptyLine
                )
 
 
-header :: Parser BlockElement
-header = foldr (<|>) pzero (map (try . header') [1..5])
+heading :: Parser BlockElement
+heading = foldr (<|>) pzero (map (try . heading') [1..5])
+          <?>
+          "heading"
     where
-      header' :: Int -> Parser BlockElement
-      header' n = do count n (char '=')
-                     notFollowedBy (char '=')
-                     ws
-                     x  <- notFollowedBy (char '=') >> anyChar
-                     xs <- manyTill anyChar (try $ ws >> (count n (char '=')))
-                     ws
-                     eol
-                     return (Header n (x:xs))
+      heading' :: Int -> Parser BlockElement
+      heading' n = do count n (char '=')
+                      notFollowedBy (char '=')
+                      ws
+                      x  <- notFollowedBy (char '=') >> anyChar
+                      xs <- manyTill anyChar (try $ ws >> (count n (char '=')))
+                      ws
+                      eol
+                      return (Heading n (x:xs))
 
 
 emptyLine :: Parser BlockElement
-emptyLine = newline >> return EmptyLine
+emptyLine = count 2 newline >> many newline >> return EmptyLine
+            <?>
+            "empty line"
 
 
 inlineElement :: Parser InlineElement
-inlineElement = text
+inlineElement = ( try text
+                  <|>
+                  try pageLink
+                )
 
 
 text :: Parser InlineElement
-text = do xs <- many1 (noneOf symbols)
-          nl <- option "" (count 1 newline)
-          return $ Text (xs ++ nl)
-
+text = text' >>= return . Text
+    where
+      text' :: Parser String
+      text' = do x <- noneOf inlineSymbols
+                 case x of
+                   -- 單獨の \n は受け入れる。
+                   '\n' -> return [x]
+                   -- それ以外では \n を受け入れない。
+                   _    -> many (noneOf ('\n':inlineSymbols)) >>= return . (x:)
+
+
+pageLink :: Parser InlineElement
+pageLink = do string "[["
+              page     <- option Nothing $
+                          do x  <- satisfy (\ c -> not (elem c "#|]" || isLower c))
+                             xs <- many (noneOf "#|]")
+                             return $ Just (x:xs)
+              fragment <- option Nothing
+                          (char '#' >> many1 (noneOf "|]") >>= return . Just)
+              text     <- option Nothing
+                          (char '|' >> many1 (noneOf "]") >>= return . Just)
+
+              case (page, fragment) of
+                (Nothing, Nothing) -> pzero
+                (_, _)             -> return ()
+
+              string "]]"
+              return $ PageLink page fragment text
+           <?>
+           "page link"
+
+
+comment :: Parser ()
+comment = (try (string "<!--") >> skipTillEnd 1)
+          <?>
+          "comment"
+    where
+      skipTillEnd :: Int -> Parser ()
+      skipTillEnd level = ( (try (string "<!--") >> skipTillEnd (level + 1))
+                            <|>
+                            (try (string "-->") >> case level of
+                                                     1 -> return ()
+                                                     n -> skipTillEnd (n - 1))
+                            <|>
+                            (anyChar >> skipTillEnd level)
+                          )
 
-symbols :: [Char]
-symbols = "\n"
 
+inlineSymbols :: [Char]
+inlineSymbols = "<["
 
 -- white space
-ws :: Parser String
-ws = many (oneOf " \t")
+ws :: Parser ()
+ws = skipMany ( (oneOf " \t" >> return ())
+                <|>
+                comment
+              )
 
 -- end of line
 eol :: Parser ()
-eol = ( (newline >> return ())
+eol = ( (many1 newline >> return ())
         <|>
         eof
       )
index 39a754708bd585009364b5cd135a4fff647bc5ab..857ea9c577e7570ced3032799252fcf2e3d13ebd 100755 (executable)
--- a/Setup.hs
+++ b/Setup.hs
@@ -1,4 +1,10 @@
 #!/usr/bin/env runghc
 
 import Distribution.Simple
-main = defaultMainWithHooks defaultUserHooks
+import System.Cmd
+import System.Exit
+
+main = defaultMainWithHooks (defaultUserHooks { runTests = runTestUnit })
+    where
+      runTestUnit _ _ _ _
+          = system "./dist/build/RakkaUnitTest/RakkaUnitTest"
index 1a6e943a92e7158d8fde0917f1c3fa2849d7581c..05516ed863daf23a7aa20b9654d59125da239c52 100644 (file)
@@ -2,6 +2,7 @@ AC_INIT([Rakka], [], [phonohawk at ps dot sakura dot ne dot jp])
 
 AC_CONFIG_SRCDIR([Rakka.cabal])
 
+
 # $localstatedir has a reference to ${prefix} but the ${prefix} is
 # "NONE" at this time. AC_OUTPUT changes the value of ${prefix} from
 # "NONE" to $ac_default_prefix but it's too late!
@@ -12,6 +13,25 @@ fi
 RAKKA_LOCALSTATEDIR=`eval echo "$localstatedir"`/rakka
 AC_SUBST([RAKKA_LOCALSTATEDIR])
 
+
+# Since the Cabal executes ./configure with no arguments, the only way
+# we can receive options from user is to see environment variables.
+AC_ARG_VAR([BUILD_TEST_SUITE], [build and install the test suite. (yes / no) (default: no)])
+if test "$BUILD_TEST_SUITE" = ""; then
+  BUILD_TEST_SUITE=False
+else
+  if test "$BUILD_TEST_SUITE" = "yes"; then
+    BUILD_TEST_SUITE=True
+  else
+     if test "$BUILD_TEST_SUITE" = "no"; then
+       BUILD_TEST_SUITE=False
+     else
+       AC_MSG_ERROR([BUILD_TEST_SUITE must be either yes or no.])
+     fi
+  fi
+fi
+
+
 AC_CONFIG_FILES([
         Rakka.buildinfo
 ])
index 39c38f42a49d4ddeb16f1d90190b9af917018663..ece7fb961bcde1d6c329f3ac3ce7bcc8b6651d81 100644 (file)
@@ -4,11 +4,13 @@
       isBoring="yes">
   <textData>= Syntax Help =
 
-== Header ==
+== Heading ==
 
-=== Header 3 ===
+=== Heading 3 ===
 
-==== Header 4 ====
+==== Heading 4 ====
+
+===== Heading 5 =====
 
 == Verbatim ==
  This
@@ -47,9 +49,9 @@ blah blah blah blah...
 == Link ==
 * [[Page]]
 * [[Page|Link to "Page"]]
-* [[Page#Header]]
-* [[#Header]]
-* [[Page#Header|Link to "Page#Header"]]
+* [[Page#Heading]]
+* [[#Heading]]
+* [[Page#Heading|Link to "Page#Heading"]]
 * [[#example]]
 * http://www.google.com/
 * [http://www.google.com Google]
index 632b1bd0cc8267eacc31871bd29357fabb47007a..4ab9d1e1d0cd6538c76e36ca385e743a183a9e95 100644 (file)
@@ -3,5 +3,27 @@
       type="text/x-rakka"
       isBoring="yes">
   <textData>= Main Page =
-This is the main page. Hello, world!</textData>
+This is the main page. 
+Hello, world!
+
+Another paragraph...
+
+= Syntax Help =
+
+== Heading ==
+
+=== Heading 3 ===
+
+==== Heading 4 ====
+
+===== Heading 5 =====
+
+== Link ==
+[[Page]]
+[[Page|Link to "Page"]]
+[[Page#Heading]]
+[[#Heading]]
+[[Page#Heading|Link to "Page#Heading"]]
+[[#example]]
+</textData>
 </page>
diff --git a/test/RakkaUnitTest.hs b/test/RakkaUnitTest.hs
new file mode 100644 (file)
index 0000000..3099a96
--- /dev/null
@@ -0,0 +1,7 @@
+import           Test.HUnit
+import qualified WikiParserTest
+
+main = runTestTT (test testData)
+
+testData :: [Test]
+testData = WikiParserTest.testData
\ No newline at end of file
diff --git a/test/WikiParserTest.hs b/test/WikiParserTest.hs
new file mode 100644 (file)
index 0000000..b4e95b1
--- /dev/null
@@ -0,0 +1,132 @@
+module WikiParserTest
+    ( testData
+    )
+    where
+
+import           Rakka.Wiki
+import           Rakka.Wiki.Parser
+import           Test.HUnit
+import           Text.ParserCombinators.Parsec
+
+
+parseWiki :: String -> Either String WikiPage
+parseWiki src = case parse wikiPage "" src of
+                  Left  err  -> Left (show err)
+                  Right page -> Right page
+
+
+testData :: [Test]
+testData = [ (parseWiki ""
+              ~?=
+              (Right []))
+
+           , (parseWiki "=heading="
+              ~?=
+              (Right [Block (Heading 1 "heading")]))
+
+           , (parseWiki "==      heading  ==  \n"
+              ~?=
+              (Right [Block (Heading 2 "heading")]))
+
+           , (parseWiki "===== hello world =====\n"
+              ~?=
+              (Right [Block (Heading 5 "hello world")]))
+
+           , (parseWiki "a =not a heading="
+              ~?=
+              (Right [Inline (Text "a =not a heading=")]))
+
+           , (parseWiki "=h=\n\n=h="
+              ~?=
+              (Right [ Block (Heading 1 "h")
+                     , Block (Heading 1 "h")
+                     ]))
+
+           , (parseWiki "foo\nbar\n\nbaz\n"
+              ~?=
+              (Right [ Inline (Text "foo")
+                     , Inline (Text "\n")
+                     , Inline (Text "bar")
+                     , Block EmptyLine
+                     , Inline (Text "baz")
+                     , Inline (Text "\n")
+                     ]))
+
+           , (parseWiki "foo\n\n\nbar"
+              ~?=
+              (Right [ Inline (Text "foo")
+                     , Block EmptyLine
+                     , Inline (Text "bar")
+                     ]))
+
+           , (parseWiki "foo\n=h="
+              ~?=
+              (Right [ Inline (Text "foo")
+                     , Inline (Text "\n")
+                     , Block (Heading 1 "h")
+                     ]))
+
+           , (parseWiki "<!-- comment -->"
+              ~?=
+              (Right []))
+
+           , (parseWiki "<!-- comment -->foo"
+              ~?=
+              (Right [Inline (Text "foo")]))
+
+           , (parseWiki "foo<!-- comment -->"
+              ~?=
+              (Right [Inline (Text "foo")]))
+
+           , (parseWiki "foo<!-- comment -->bar"
+              ~?=
+              (Right [ Inline (Text "foo")
+                     , Inline (Text "bar")
+                     ]))
+
+           , (parseWiki "<!-- comment -->=h="
+              ~?=
+              (Right [Block (Heading 1 "h")]))
+
+           , (parseWiki "=h= <!---->"
+              ~?=
+              (Right [Block (Heading 1 "h")]))
+
+           , (parseWiki "<!-- <!-- nested --> comment -->"
+              ~?=
+              (Right []))
+
+           , (parseWiki "[[Page]]"
+              ~?= 
+              (Right [Inline (PageLink (Just "Page") Nothing Nothing)]))
+
+           , (parseWiki "[[Page|Link to \"Page\"]]"
+              ~?=
+              (Right [Inline (PageLink (Just "Page") Nothing (Just "Link to \"Page\""))]))
+
+           , (parseWiki "[[Page#foo]]"
+              ~?= 
+              (Right [Inline (PageLink (Just "Page") (Just "foo") Nothing)]))
+
+           , (parseWiki "[[#foo]]"
+              ~?= 
+              (Right [Inline (PageLink Nothing (Just "foo") Nothing)]))
+
+           , (parseWiki "[[Page#foo|Link to \"Page#foo\"]]"
+              ~?=
+              (Right [Inline (PageLink (Just "Page") (Just "foo") (Just "Link to \"Page#foo\""))]))
+
+           , (parseWiki "foo [[Bar]] baz"
+              ~?=
+              (Right [ Inline (Text "foo ")
+                     , Inline (PageLink (Just "Bar") Nothing Nothing)
+                     , Inline (Text " baz")
+                     ]))
+
+           , (parseWiki "[[Foo]]\n[[Bar]]"
+              ~?= 
+              (Right [ Inline (PageLink (Just "Foo") Nothing Nothing)
+                     , Inline (Text "\n")
+                     , Inline (PageLink (Just "Bar") Nothing Nothing)
+                     ]))
+           ]