packages feed

markdown-kate (empty) → 0.1.2.1

raw patch · 71 files changed

+3881/−0 lines, 71 filesdep +attoparsecdep +attoparsec-conduitdep +basesetup-changed

Dependencies added: attoparsec, attoparsec-conduit, base, blaze-html, conduit, containers, data-default, highlighting-kate, hspec, markdown, system-fileio, system-filepath, text, transformers, xss-sanitize

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Michael Snoyman++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 Michael Snoyman 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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ Text/Markdown.hs view
@@ -0,0 +1,158 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RankNTypes #-}+module Text.Markdown+    ( -- * Functions+      markdown+      -- * Settings+    , MarkdownSettings+    , msXssProtect+    , msStandaloneHtml+    , msFencedHandlers+      -- * Newtype+    , Markdown (..)+      -- * Fenced handlers+    , FencedHandler (..)+    , codeFencedHandler+    , htmlFencedHandler+      -- * Convenience re-exports+    , def+    ) where++import Text.Markdown.Inline+import Text.Markdown.Block+import Text.Markdown.Types+import Text.Highlighting.Kate+import Prelude hiding                              (sequence, takeWhile)+import Data.Default                                (Default (..))+import Data.Text                                   (Text, unpack)+import qualified Data.Text.Lazy as TL+import Text.Blaze.Html                             (ToMarkup (..), Html)+import Text.Blaze.Html.Renderer.Text               (renderHtml)+import Data.Conduit+import qualified Data.Conduit.List as CL+import Data.Monoid                                 (Monoid (mappend, mempty, mconcat))+import Data.Functor.Identity                       (runIdentity)+import qualified Text.Blaze.Html5 as H+import qualified Text.Blaze.Html5.Attributes as HA+import Text.HTML.SanitizeXSS                       (sanitizeBalance)+import qualified Data.Map as Map+import Data.String                                 (IsString)++-- | A newtype wrapper providing a @ToHtml@ instance.+newtype Markdown = Markdown TL.Text+  deriving(Monoid, IsString)++instance ToMarkup Markdown where+    toMarkup (Markdown t) = markdown def t++-- | Convert the given textual markdown content to HTML.+--+-- >>> :set -XOverloadedStrings+-- >>> import Text.Blaze.Html.Renderer.Text+-- >>> renderHtml $ markdown def "# Hello World!"+-- "<h1>Hello World!</h1>"+--+-- >>> renderHtml $ markdown def { msXssProtect = False } "<script>alert('evil')</script>"+-- "<script>alert('evil')</script>"+markdown :: MarkdownSettings -> TL.Text -> Html+markdown ms tl =+       sanitize+     $ runIdentity+     $ CL.sourceList blocksH+    $= toHtmlB ms+    $$ CL.fold mappend mempty+  where+    sanitize+        | msXssProtect ms = preEscapedToMarkup . sanitizeBalance . TL.toStrict . renderHtml+        | otherwise = id+    fixBlock :: Block Text -> Block Html+    fixBlock = fmap $ toHtmlI ms . toInline refs++    blocksH :: [Block Html]+    blocksH = map fixBlock blocks++    blocks :: [Block Text]+    blocks = runIdentity+           $ CL.sourceList (TL.toChunks tl)+          $$ toBlocks ms+          =$ CL.consume++    refs =+        Map.unions $ map toRef blocks+      where+        toRef (BlockReference x y) = Map.singleton x y+        toRef _ = Map.empty++data MState = NoState | InList ListType++toHtmlB :: Monad m => MarkdownSettings -> Conduit (Block Html) m Html+toHtmlB ms =+    loop NoState+  where+    loop state = await >>= maybe+        (closeState state)+        (\x -> do+            state' <- getState state x+            yield $ go x+            loop state')++    closeState NoState = return ()+    closeState (InList Unordered) = yield $ escape "</ul>"+    closeState (InList Ordered) = yield $ escape "</ol>"++    getState NoState (BlockList ltype _) = do+        yield $ escape $+            case ltype of+                Unordered -> "<ul>"+                Ordered -> "<ol>"+        return $ InList ltype+    getState NoState _ = return NoState+    getState state@(InList lt1) b@(BlockList lt2 _)+        | lt1 == lt2 = return state+        | otherwise = closeState state >> getState NoState b+    getState state@(InList _) _ = closeState state >> return NoState++    go (BlockPara h) = H.p h+    go (BlockPlainText h) = h+    go (BlockList _ (Left h)) = H.li h+    go (BlockList _ (Right bs)) = H.li $ blocksToHtml bs+    go (BlockHtml t) = escape t+    go (BlockCode Nothing t) = H.pre $ H.code $ toMarkup t+    go (BlockCode (Just lang) t) = H.figure $ toHighlighted (unpack lang) (unpack t)+    go (BlockQuote bs) = H.blockquote $ blocksToHtml bs+    go BlockRule = H.hr+    go (BlockHeading level h) =+        wrap level h+      where+       wrap 1 = H.h1+       wrap 2 = H.h2+       wrap 3 = H.h3+       wrap 4 = H.h4+       wrap 5 = H.h5+       wrap _ = H.h6+    go BlockReference{} = return ()++    toHighlighted l t' = toMarkup $ formatHtmlBlock (defaultFormatOpts { numberLines = True }) $ highlightAs l t'+    blocksToHtml bs = runIdentity $ mapM_ yield bs $$ toHtmlB ms =$ CL.fold mappend mempty++escape :: Text -> Html+escape = preEscapedToMarkup++toHtmlI :: MarkdownSettings -> [Inline] -> Html+toHtmlI ms is0+    | msXssProtect ms = escape $ sanitizeBalance $ TL.toStrict $ renderHtml final+    | otherwise = final+  where+    final = gos is0+    gos = mconcat . map go++    go (InlineText t) = toMarkup t+    go (InlineItalic is) = H.i $ gos is+    go (InlineBold is) = H.b $ gos is+    go (InlineCode t) = H.code $ toMarkup t+    go (InlineLink url Nothing content) = H.a H.! HA.href (H.toValue url) $ gos content+    go (InlineLink url (Just title) content) = H.a H.! HA.href (H.toValue url) H.! HA.title (H.toValue title) $ gos content+    go (InlineImage url Nothing content) = H.img H.! HA.src (H.toValue url) H.! HA.alt (H.toValue content)+    go (InlineImage url (Just title) content) = H.img H.! HA.src (H.toValue url) H.! HA.alt (H.toValue content) H.! HA.title (H.toValue title)+    go (InlineHtml t) = escape t
+ Text/Markdown/Block.hs view
@@ -0,0 +1,324 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE CPP #-}+{-# OPTIONS_HADDOCK hide #-}+module Text.Markdown.Block+    ( Block (..)+    , ListType (..)+    , toBlocks+    ) where++import Prelude+#if MIN_VERSION_conduit(1, 0, 0)+import Data.Conduit+#else+import Data.Conduit hiding ((=$=))+import Data.Conduit.Internal (pipeL)+#endif+import qualified Data.Conduit.Text as CT+import qualified Data.Conduit.List as CL+import Data.Text (Text)+import qualified Data.Text as T+import Data.Functor.Identity (runIdentity)+import Data.Char (isDigit)+import Text.Markdown.Types+import qualified Data.Set as Set+import qualified Data.Map as Map++#if !MIN_VERSION_conduit(1, 0, 0)+(=$=) :: Monad m => Pipe a a b x m y -> Pipe b b c y m z -> Pipe a a c x m z+(=$=) = pipeL+#endif++toBlocks :: Monad m => MarkdownSettings -> Conduit Text m (Block Text)+toBlocks ms =+    mapOutput fixWS CT.lines =$= toBlocksLines ms+  where+    fixWS = T.pack . go 0 . T.unpack++    go _ [] = []+    go i ('\r':cs) = go i cs+    go i ('\t':cs) =+        (replicate j ' ') ++ go (i + j) cs+      where+        j = 4 - (i `mod` 4)+    go i (c:cs) = c : go (i + 1) cs++toBlocksLines :: Monad m => MarkdownSettings -> Conduit Text m (Block Text)+toBlocksLines ms = awaitForever (start ms) =$= tightenLists++tightenLists :: Monad m => Conduit (Either Blank (Block Text)) m (Block Text)+tightenLists =+    go Nothing+  where+    go mTightList =+        await >>= maybe (return ()) go'+      where+        go' (Left Blank) = go mTightList+        go' (Right (BlockList ltNew contents)) =+            case mTightList of+                Just (ltOld, isTight) | ltOld == ltNew -> do+                    yield $ BlockList ltNew $ (if isTight then tighten else untighten) contents+                    go mTightList+                _ -> do+                    isTight <- checkTight ltNew False+                    yield $ BlockList ltNew $ (if isTight then tighten else untighten) contents+                    go $ Just (ltNew, isTight)+        go' (Right b) = yield b >> go Nothing++    tighten (Right [BlockPara t]) = Left t+    tighten (Right []) = Left T.empty+    tighten x = x++    untighten (Left t) = Right [BlockPara t]+    untighten x = x++    checkTight lt sawBlank = do+        await >>= maybe (return $ not sawBlank) go'+      where+        go' (Left Blank) = checkTight lt True+        go' b@(Right (BlockList ltNext _)) | ltNext == lt = do+            leftover b+            return $ not sawBlank+        go' b = leftover b >> return False++data Blank = Blank++data LineType = LineList ListType Text+              | LineCode Text+              | LineFenced Text FencedHandler -- ^ terminator, language+              | LineBlockQuote Text+              | LineHeading Int Text+              | LineBlank+              | LineText Text+              | LineRule+              | LineHtml Text+              | LineReference Text Text -- ^ name, destination++lineType :: MarkdownSettings -> Text -> LineType+lineType ms t+    | T.null $ T.strip t = LineBlank+    | Just (term, fh) <- getFenced (Map.toList $ msFencedHandlers ms) t = LineFenced term fh+    | Just t' <- T.stripPrefix "> " t = LineBlockQuote t'+    | Just (level, t') <- stripHeading t = LineHeading level t'+    | Just t' <- T.stripPrefix "    " t = LineCode t'+    | isRule t = LineRule+    | isHtmlStart t = LineHtml t+    | Just (ltype, t') <- listStart t = LineList ltype t'+    | Just (name, dest) <- getReference t = LineReference name dest+    | otherwise = LineText t+  where+    getFenced [] _ = Nothing+    getFenced ((x, fh):xs) t'+        | Just rest <- T.stripPrefix x t' = Just (x, fh $ T.strip rest)+        | otherwise = getFenced xs t'++    isRule :: Text -> Bool+    isRule =+        go . T.strip+      where+        go "* * *" = True+        go "***" = True+        go "*****" = True+        go "- - -" = True+        go "---" = True+        go "___" = True+        go "_ _ _" = True+        go t' = T.length (T.takeWhile (== '-') t') >= 5++    stripHeading :: Text -> Maybe (Int, Text)+    stripHeading t'+        | T.null x = Nothing+        | otherwise = Just (T.length x, T.strip $ T.dropWhileEnd (== '#') y)+      where+        (x, y) = T.span (== '#') t'++    getReference :: Text -> Maybe (Text, Text)+    getReference a = do+        b <- T.stripPrefix "[" $ T.dropWhile (== ' ') a+        let (name, c) = T.break (== ']') b+        d <- T.stripPrefix "]:" c+        Just (name, T.strip d)++start :: Monad m => MarkdownSettings -> Text -> Conduit Text m (Either Blank (Block Text))+start ms t =+    go $ lineType ms t+  where+    go LineBlank = yield $ Left Blank+    go (LineFenced term fh) = do+        (finished, ls) <- takeTillConsume (== term)+        case finished of+            Just _ -> do+                let block =+                        case fh of+                            FHRaw fh' -> fh' $ T.intercalate "\n" ls+                            FHParsed fh' -> fh' $ runIdentity $ mapM_ yield ls $$ toBlocksLines ms =$ CL.consume+                mapM_ (yield . Right) block+            Nothing -> mapM_ leftover (reverse $ T.cons ' ' t : ls)+    go (LineBlockQuote t') = do+        ls <- takeQuotes =$= CL.consume+        let blocks = runIdentity $ mapM_ yield (t' : ls) $$ toBlocksLines ms =$ CL.consume+        yield $ Right $ BlockQuote blocks+    go (LineHeading level t') = yield $ Right $ BlockHeading level t'+    go (LineCode t') = do+        ls <- getIndented 4 =$= CL.consume+        yield $ Right $ BlockCode Nothing $ T.intercalate "\n" $ t' : ls+    go LineRule = yield $ Right BlockRule+    go (LineHtml t') = do+        if t' `Set.member` msStandaloneHtml ms+            then yield $ Right $ BlockHtml t'+            else do+                ls <- takeTill (T.null . T.strip) =$= CL.consume+                yield $ Right $ BlockHtml $ T.intercalate "\n" $ t' : ls+    go (LineList ltype t') = do+        t2 <- CL.peek+        case fmap (lineType ms) t2 of+            -- If the next line is a non-indented text line, then we have a+            -- lazy list.+            Just (LineText t2') | T.null (T.takeWhile (== ' ') t2') -> do+                CL.drop 1+                -- Get all of the non-indented lines.+                let loop front = do+                        x <- await+                        case x of+                            Nothing -> return $ front []+                            Just y ->+                                case lineType ms y of+                                    LineText z -> loop (front . (z:))+                                    _ -> leftover y >> return (front [])+                ls <- loop (\rest -> T.dropWhile (== ' ') t' : t2' : rest)+                yield $ Right $ BlockList ltype $ Right [BlockPara $ T.intercalate "\n" ls]+            -- If the next line is an indented list, then we have a sublist. I+            -- disagree with this interpretation of Markdown, but it's the way+            -- that Github implements things, so we will too.+            _ | Just t2' <- t2+              , Just t2'' <- T.stripPrefix "    " t2'+              , LineList _ltype' _t2''' <- lineType ms t2'' -> do+                ls <- getIndented 4 =$= CL.consume+                let blocks = runIdentity $ mapM_ yield ls $$ toBlocksLines ms =$ CL.consume+                let addPlainText+                        | T.null $ T.strip t' = id+                        | otherwise = (BlockPlainText (T.strip t'):)+                yield $ Right $ BlockList ltype $ Right $ addPlainText blocks+            _ -> do+                let t'' = T.dropWhile (== ' ') t'+                let leader = T.length t - T.length t''+                ls <- getIndented leader =$= CL.consume+                let blocks = runIdentity $ mapM_ yield (t'' : ls) $$ toBlocksLines ms =$ CL.consume+                yield $ Right $ BlockList ltype $ Right blocks+    go (LineReference x y) = yield $ Right $ BlockReference x y+    go (LineText t') = do+        -- Check for underline headings+        let getUnderline :: Text -> Maybe Int+            getUnderline s+                | T.length s < 2 = Nothing+                | T.all (== '=') s = Just 1+                | T.all (== '-') s = Just 2+                | otherwise = Nothing+        t2 <- CL.peek+        case t2 >>= getUnderline of+            Just level -> do+                CL.drop 1+                yield $ Right $ BlockHeading level t'+            Nothing -> do+                let listStartIndent x =+                        case listStart x of+                            Just (_, y) -> T.take 2 y == "  "+                            Nothing -> False+                    isNonPara LineBlank = True+                    isNonPara LineFenced{} = True+                    isNonPara _ = False+                (mfinal, ls) <- takeTillConsume (\x -> isNonPara (lineType ms x) || listStartIndent x)+                maybe (return ()) leftover mfinal+                yield $ Right $ BlockPara $ T.intercalate "\n" $ t' : ls++isHtmlStart :: T.Text -> Bool+isHtmlStart t =+    case T.stripPrefix "<" t of+        Nothing -> False+        Just t' ->+            let (name, rest) = T.break (\c -> c `elem` " >") t'+             in T.all isValidTagName name &&+                not (T.null name) &&+                (not ("/" `T.isPrefixOf` rest) || ("/>" `T.isPrefixOf` rest))+  where+    isValidTagName :: Char -> Bool+    isValidTagName c =+        ('A' <= c && c <= 'Z') ||+        ('a' <= c && c <= 'z') ||+        ('0' <= c && c <= '9') ||+        (c == '-') ||+        (c == '_') ||+        (c == '/') ||+        (c == '!')++takeTill :: Monad m => (i -> Bool) -> Conduit i m i+takeTill f =+    loop+  where+    loop = await >>= maybe (return ()) (\x -> if f x then return () else yield x >> loop)++--takeTillConsume :: Monad m => (i -> Bool) -> Consumer i m (Maybe i, [i])+takeTillConsume f =+    loop id+  where+    loop front = await >>= maybe+        (return (Nothing, front []))+        (\x ->+            if f x+                then return (Just x, front [])+                else loop (front . (x:))+        )++listStart :: Text -> Maybe (ListType, Text)+listStart t0+    | Just t' <- T.stripPrefix "* " t = Just (Unordered, t')+    | Just t' <- T.stripPrefix "+ " t = Just (Unordered, t')+    | Just t' <- T.stripPrefix "- " t = Just (Unordered, t')+    | Just t' <- stripNumber t, Just t'' <- stripSeparator t' = Just (Ordered, t'')+    | otherwise = Nothing+  where+    t = T.stripStart t0++stripNumber :: Text -> Maybe Text+stripNumber x+    | T.null y = Nothing+    | otherwise = Just z+  where+    (y, z) = T.span isDigit x++stripSeparator :: Text -> Maybe Text+stripSeparator x =+    case T.uncons x of+        Nothing -> Nothing+        Just ('.', y) -> Just y+        Just (')', y) -> Just y+        _ -> Nothing++getIndented :: Monad m => Int -> Conduit Text m Text+getIndented leader =+    go []+  where+    go blanks = await >>= maybe (mapM_ leftover blanks) (go' blanks)++    go' blanks t+        | T.null $ T.strip t = go (T.drop leader t : blanks)+        | T.length x == leader && T.null (T.strip x) = do+            mapM_ yield $ reverse blanks+            yield y+            go []+        | otherwise = mapM_ leftover (t:blanks)+      where+        (x, y) = T.splitAt leader t++takeQuotes :: Monad m => Conduit Text m Text+takeQuotes =+    await >>= maybe (return ()) go+  where+    go "" = return ()+    go ">" = yield "" >> takeQuotes+    go t+        | Just t' <- T.stripPrefix "> " t = yield t' >> takeQuotes+        | otherwise = yield t >> takeQuotes
+ Text/Markdown/Inline.hs view
@@ -0,0 +1,232 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_HADDOCK hide #-}+module Text.Markdown.Inline+    ( Inline (..)+    , inlineParser+    , toInline+    ) where++import Prelude hiding (takeWhile)+import Data.Text (Text)+import qualified Data.Text as T+import Data.Attoparsec.Text+import Control.Applicative+import Data.Monoid (Monoid, mappend)+import qualified Data.Map as Map++type RefMap = Map.Map Text Text++toInline :: RefMap -> Text -> [Inline]+toInline refmap t =+    case parseOnly (inlineParser refmap) t of+        Left s -> [InlineText $ T.pack s]+        Right is -> is++(<>) :: Monoid m => m -> m -> m+(<>) = mappend++data Inline = InlineText Text+            | InlineItalic [Inline]+            | InlineBold [Inline]+            | InlineCode Text+            | InlineHtml Text+            | InlineLink Text (Maybe Text) [Inline] -- ^ URL, title, content+            | InlineImage Text (Maybe Text) Text -- ^ URL, title, content+    deriving (Show, Eq)++inlineParser :: RefMap -> Parser [Inline]+inlineParser = fmap combine . many . inlineAny++combine :: [Inline] -> [Inline]+combine [] = []+combine (InlineText x:InlineText y:rest) = combine (InlineText (x <> y):rest)+combine (InlineText x:rest) = InlineText x : combine rest+combine (InlineItalic x:InlineItalic y:rest) = combine (InlineItalic (x <> y):rest)+combine (InlineItalic x:rest) = InlineItalic (combine x) : combine rest+combine (InlineBold x:InlineBold y:rest) = combine (InlineBold (x <> y):rest)+combine (InlineBold x:rest) = InlineBold (combine x) : combine rest+combine (InlineCode x:InlineCode y:rest) = combine (InlineCode (x <> y):rest)+combine (InlineCode x:rest) = InlineCode x : combine rest+combine (InlineLink u t c:rest) = InlineLink u t (combine c) : combine rest+combine (InlineImage u t c:rest) = InlineImage u t c : combine rest+combine (InlineHtml t:rest) = InlineHtml t : combine rest++specials :: [Char]+specials = "*_`\\[]!<&"++inlineAny :: RefMap -> Parser Inline+inlineAny refs =+    inline refs <|> special+  where+    special = InlineText . T.singleton <$> satisfy (`elem` specials)++inline :: RefMap -> Parser Inline+inline refs =+    text+    <|> escape+    <|> paired "**" InlineBold <|> paired "__" InlineBold+    <|> paired "*" InlineItalic <|> paired "_" InlineItalic+    <|> doubleCode <|> code+    <|> link+    <|> image+    <|> autoLink+    <|> html+    <|> entity+  where+    inlinesTill :: Text -> Parser [Inline]+    inlinesTill end =+        go id+      where+        go front =+            (string end *> pure (front []))+            <|> (do+                x <- inlineAny refs+                go $ front . (x:))++    text = InlineText <$> takeWhile1 (`notElem` specials)++    paired t wrap = wrap <$> do+        _ <- string t+        is <- inlinesTill t+        if null is then fail "wrapped around something missing" else return is++    doubleCode = InlineCode . T.pack <$> (string "`` " *> manyTill anyChar (string " ``"))+    code = InlineCode <$> (char '`' *> takeWhile1 (/= '`') <* char '`')++    escape = InlineText . T.singleton <$> (char '\\' *> satisfy (`elem` "\\`*_{}[]()#+-.!>"))++    takeBalancedBrackets =+        T.pack <$> go (0 :: Int)+      where+        go i = do+            c <- anyChar+            case c of+                '[' -> (c:) <$> go (i + 1)+                ']'+                    | i == 0 -> return []+                    | otherwise -> (c:) <$> go (i - 1)+                _ -> (c:) <$> go i++    parseUrl = fixUrl . T.pack <$> parseUrl' (0 :: Int)++    parseUrl' level+        | level > 0 = do+            c <- anyChar+            let level'+                    | c == ')' = level - 1+                    | otherwise = level+            c' <-+                if c == '\\'+                    then anyChar+                    else return c+            cs <- parseUrl' level'+            return $ c' : cs+        | otherwise = (do+            c <- hrefChar+            if c == '('+                then (c:) <$> parseUrl' 1+                else (c:) <$> parseUrl' 0) <|> return []++    parseUrlTitle defRef = parseUrlTitleInline <|> parseUrlTitleRef defRef++    parseUrlTitleInside endTitle = do+        url <- parseUrl+        mtitle <- (Just <$> title) <|> (skipSpace >> endTitle >> pure Nothing)+        return (url, mtitle)+      where+        title = do+            _ <- space+            skipSpace+            _ <- char '"'+            t <- T.stripEnd . T.pack <$> go+            return $+                if not (T.null t) && T.last t == '"'+                    then T.init t+                    else t+          where+            go =  (char '\\' *> anyChar >>= \c -> (c:) <$> go)+              <|> (endTitle *> return [])+              <|> (anyChar >>= \c -> (c:) <$> go)++    parseUrlTitleInline = char '(' *> parseUrlTitleInside (char ')')++    parseUrlTitleRef defRef = do+        ref' <- (skipSpace *> char '[' *> takeWhile (/= ']') <* char ']') <|> return ""+        let ref = if T.null ref' then defRef else ref'+        case Map.lookup (T.unwords $ T.words ref) refs of+            Nothing -> fail "ref not found"+            Just t -> either fail return $ parseOnly (parseUrlTitleInside endOfInput) t++    link = do+        _ <- char '['+        rawContent <- takeBalancedBrackets+        content <- either fail return $ parseOnly (inlineParser refs) rawContent+        (url, mtitle) <- parseUrlTitle rawContent+        return $ InlineLink url mtitle content++    image = do+        _ <- string "!["+        content <- takeBalancedBrackets+        (url, mtitle) <- parseUrlTitle content+        return $ InlineImage url mtitle content++    fixUrl t+        | T.length t > 2 && T.head t == '<' && T.last t == '>' = T.init $ T.tail t+        | otherwise = t++    autoLink = do+        _ <- char '<'+        a <- string "http:" <|> string "https:"+        b <- takeWhile1 (/= '>')+        _ <- char '>'+        let url = a `T.append` b+        return $ InlineLink url Nothing [InlineText url]++    html = do+        c <- char '<'+        t <- takeWhile1 (\x -> ('A' <= x && x <= 'Z') || ('a' <= x && x <= 'z') || x == '/')+        if T.null t+            then fail "invalid tag"+            else do+                t2 <- takeWhile (/= '>')+                c2 <- char '>'+                return $ InlineHtml $ T.concat+                    [ T.singleton c+                    , t+                    , t2+                    , T.singleton c2+                    ]++    entity =+            rawent "&lt;"+        <|> rawent "&gt;"+        <|> rawent "&amp;"+        <|> rawent "&quot;"+        <|> rawent "&apos;"+        <|> decEnt+        <|> hexEnt++    rawent t = InlineHtml <$> string t++    decEnt = do+        s <- string "&#"+        t <- takeWhile1 $ \x -> ('0' <= x && x <= '9')+        c <- char ';'+        return $ InlineHtml $ T.concat+            [ s+            , t+            , T.singleton c+            ]++    hexEnt = do+        s <- string "&#x" <|> string "&#X"+        t <- takeWhile1 $ \x -> ('0' <= x && x <= '9') || ('A' <= x && x <= 'F') || ('a' <= x && x <= 'f')+        c <- char ';'+        return $ InlineHtml $ T.concat+            [ s+            , t+            , T.singleton c+            ]++hrefChar :: Parser Char+hrefChar = (char '\\' *> anyChar) <|> satisfy (notInClass " )")
+ Text/Markdown/Types.hs view
@@ -0,0 +1,119 @@+{-# LANGUAGE OverloadedStrings #-}+module Text.Markdown.Types where++import Data.Text (Text)+import qualified Data.Text as T+import Data.Default (Default (def))+import Data.Set (Set, empty)+import Data.Map (Map, singleton)+import Data.Monoid (mappend)++-- | A settings type providing various configuration options.+--+-- See <http://www.yesodweb.com/book/settings-types> for more information on+-- settings types. In general, you can use @def@.+data MarkdownSettings = MarkdownSettings+    { msXssProtect :: Bool+      -- ^ Whether to automatically apply XSS protection to embedded HTML. Default: @True@.+    , msStandaloneHtml :: Set Text+      -- ^ HTML snippets which stand on their own. We do not require a blank line following these pieces of HTML.+      --+      -- Default: empty set.+      --+      -- Since: 0.1.2+    , msFencedHandlers :: Map Text (Text -> FencedHandler)+      -- ^ Handlers for the special \"fenced\" format. This is most commonly+      -- used for fenced code, e.g.:+      --+      -- > ```haskell+      -- > main = putStrLn "Hello"+      -- > ```+      --+      -- This is an extension of Markdown, but a fairly commonly used one.+      --+      -- This setting allows you to create new kinds of fencing. Fencing goes+      -- into two categories: parsed and raw. Code fencing would be in the raw+      -- category, where the contents are not treated as Markdown. Parsed will+      -- treat the contents as Markdown and allow you to perform some kind of+      -- modifcation to it.+      --+      -- For example, to create a new @\@\@\@@ fencing which wraps up the+      -- contents in an @article@ tag, you could use:+      --+      -- > def { msFencedHandlers = htmlFencedHandler "@@@" (const "<article>") (const "</article")+      -- >              `Map.union` msFencedHandlers def+      -- >     }+      --+      -- Default: code fencing for @```@ and @~~~@.+      --+      -- Since: 0.1.2+    }++-- | See 'msFencedHandlers.+--+-- Since 0.1.2+data FencedHandler = FHRaw (Text -> [Block Text])+                     -- ^ Wrap up the given raw content.+                   | FHParsed ([Block Text] -> [Block Text])+                     -- ^ Wrap up the given parsed content.++instance Default MarkdownSettings where+    def = MarkdownSettings+        { msXssProtect = True+        , msStandaloneHtml = empty+        , msFencedHandlers = codeFencedHandler "```" `mappend` codeFencedHandler "~~~"+        }++-- | Helper for creating a 'FHRaw'.+--+-- Since 0.1.2+codeFencedHandler :: Text -- ^ Delimiter+                  -> Map Text (Text -> FencedHandler)+codeFencedHandler key = singleton key $ \lang -> FHRaw $+    return . BlockCode (if T.null lang then Nothing else Just lang)++-- | Helper for creating a 'FHParsed'.+--+-- Note that the start and end parameters take a @Text@ parameter; this is the+-- text following the delimiter. For example, with the markdown:+--+-- > @@@ foo+--+-- @foo@ would be passed to start and end.+--+-- Since 0.1.2+htmlFencedHandler :: Text -- ^ Delimiter+                  -> (Text -> Text) -- ^ start HTML+                  -> (Text -> Text) -- ^ end HTML+                  -> Map Text (Text -> FencedHandler)+htmlFencedHandler key start end = singleton key $ \lang -> FHParsed $ \blocks ->+      BlockHtml (start lang)+    : blocks+   ++ [BlockHtml $ end lang]++data ListType = Ordered | Unordered+  deriving (Show, Eq)++data Block inline+    = BlockPara inline+    | BlockList ListType (Either inline [Block inline])+    | BlockCode (Maybe Text) Text+    | BlockQuote [Block inline]+    | BlockHtml Text+    | BlockRule+    | BlockHeading Int inline+    | BlockReference Text Text+    | BlockPlainText inline+  deriving (Show, Eq)++instance Functor Block where+    fmap f (BlockPara i) = BlockPara (f i)+    fmap f (BlockList lt (Left i)) = BlockList lt $ Left $ f i+    fmap f (BlockList lt (Right bs)) = BlockList lt $ Right $ map (fmap f) bs+    fmap _ (BlockCode a b) = BlockCode a b+    fmap f (BlockQuote bs) = BlockQuote $ map (fmap f) bs+    fmap _ (BlockHtml t) = BlockHtml t+    fmap _ BlockRule = BlockRule+    fmap f (BlockHeading level i) = BlockHeading level (f i)+    fmap _ (BlockReference x y) = BlockReference x y+    fmap f (BlockPlainText x) = BlockPlainText (f x)
+ markdown-kate.cabal view
@@ -0,0 +1,57 @@+Name:                markdown-kate+Version:             0.1.2.1+Synopsis:            Convert Markdown to HTML, with XSS protection+Description:         This library leverages existing high-performance libraries (attoparsec, blaze-html, text, and conduit), and should integrate well with existing codebases.+Homepage:            https://github.com/joelteon/markdown-kate+License:             BSD3+License-file:        LICENSE+Author:              Michael Snoyman+Maintainer:          joel@outright.com+Category:            Web+Build-type:          Simple+Extra-source-files:  test/examples/*.html+                   , test/examples/*.md+                   , test/Tests/*.html+                   , test/Tests/*.text+Cabal-version:       >=1.8++Library+  Exposed-modules:     Text.Markdown+                       Text.Markdown.Block+                       Text.Markdown.Inline+  other-modules:       Text.Markdown.Types+  Build-depends:       base                   >= 4       && < 5+                     , blaze-html             >= 0.4+                     , attoparsec             >= 0.10+                     , attoparsec-conduit     >= 0.5+                     , transformers           >= 0.2.2+                     , conduit                >= 0.5.2.1+                     , text+                     , data-default           >= 0.3+                     , xss-sanitize           >= 0.3.3+                     , containers+                     , highlighting-kate+  ghc-options:       -Wall++test-suite test+    hs-source-dirs: test+    main-is: main.hs+    other-modules: Block+                   Inline+    type: exitcode-stdio-1.0++    ghc-options:   -Wall+    build-depends: markdown+                 , base             >= 4       && < 5+                 , hspec            >= 1.3+                 , blaze-html+                 , text+                 , system-fileio+                 , system-filepath+                 , transformers+                 , conduit+                 , containers++source-repository head+  type:     git+  location: git://github.com/joelteon/markdown-kate.git
+ test/Block.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE OverloadedStrings #-}+module Block+    ( blockSpecs+    ) where+import Test.Hspec+import Data.Text (Text)+import Data.Conduit+import qualified Data.Conduit.List as CL+import Text.Markdown (def)+import Text.Markdown.Block+import Data.Functor.Identity (runIdentity)++check :: Text -> [Block Text] -> Expectation+check md blocks = runIdentity (yield md $$ toBlocks def =$ CL.consume) `shouldBe` blocks++blockSpecs :: Spec+blockSpecs = do+    describe "tilde code" $ do+        it "simple" $ check+            "~~~haskell\nfoo\n\nbar\n~~~"+            [BlockCode (Just "haskell") "foo\n\nbar"]+        it "no lang" $ check+            "~~~\nfoo\n\nbar\n~~~"+            [BlockCode Nothing "foo\n\nbar"]+        it "no close" $ check+            "~~~\nfoo\n\nbar\n"+            [BlockPara " ~~~\nfoo", BlockPara "bar"]+    describe "list" $ do+        it "simple" $ check+            "* foo\n\n*    bar\n\n"+            [ BlockList Unordered (Right [BlockPara "foo"])+            , BlockList Unordered (Right [BlockPara "bar"])+            ]+        it "nested" $ check+            "* foo\n* \n    1. bar\n    2. baz"+            [ BlockList Unordered (Left "foo")+            , BlockList Unordered (Right+                [ BlockList Ordered $ Left "bar"+                , BlockList Ordered $ Left "baz"+                ])+            ]+        it "with blank" $ check+            "*   foo\n\n    bar\n\n* baz"+            [ BlockList Unordered $ Right+                [ BlockPara "foo"+                , BlockPara "bar"+                ]+            , BlockList Unordered $ Right+                [ BlockPara "baz"+                ]+            ]+    describe "blockquote" $ do+        it "simple" $ check+            "> foo\n>\n> * bar"+            [ BlockQuote+                [ BlockPara "foo"+                , BlockList Unordered $ Left "bar"+                ]+            ]+        it "blank" $ check+            "> foo\n\n> * bar"+            [ BlockQuote [BlockPara "foo"]+            , BlockQuote [BlockList Unordered $ Left "bar"]+            ]+    describe "indented code" $ do+        it "simple" $ check+            "    foo\n    bar\n"+            [ BlockCode Nothing "foo\nbar"+            ]+        it "blank" $ check+            "    foo\n\n    bar\n"+            [ BlockCode Nothing "foo\n\nbar"+            ]+        it "extra space" $ check+            "    foo\n\n     bar\n"+            [ BlockCode Nothing "foo\n\n bar"+            ]+    describe "html" $ do+        it "simple" $ check+            "<p>Hello world!</p>"+            [ BlockHtml "<p>Hello world!</p>"+            ]+        it "multiline" $ check+            "<p>Hello world!\n</p>"+            [ BlockHtml "<p>Hello world!\n</p>"+            ]
+ test/Inline.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE OverloadedStrings #-}+module Inline+    ( inlineSpecs+    ) where++import Test.Hspec+import Text.Markdown.Inline+import Data.Text (Text)+import Data.Monoid (mempty)++check :: Text -> [Inline] -> Expectation+check md ins = toInline mempty md `shouldBe` ins++inlineSpecs :: Spec+inlineSpecs = do+    describe "raw text" $ do+        it "simple"+            $ check "raw text" [InlineText "raw text"]+        it "multiline"+            $ check "raw\ntext" [InlineText "raw\ntext"]+    describe "italic" $ do+        it "asterisk"+            $ check "raw *text*" [InlineText "raw ", InlineItalic [InlineText "text"]]+        it "underline"+            $ check "raw _text_" [InlineText "raw ", InlineItalic [InlineText "text"]]+        it "multiline"+            $ check "*raw\ntext*" [InlineItalic [InlineText "raw\ntext"]]+        it "mismatched"+            $ check "*foo* *bar" [InlineItalic [InlineText "foo"], InlineText " *bar"]+    describe "bold" $ do+        it "asterisk"+            $ check "raw **text**" [InlineText "raw ", InlineBold [InlineText "text"]]+        it "underline"+            $ check "raw __text__" [InlineText "raw ", InlineBold [InlineText "text"]]+        it "multiline"+            $ check "**raw\ntext**" [InlineBold [InlineText "raw\ntext"]]+        it "mismatched"+            $ check "**foo** *bar" [InlineBold [InlineText "foo"], InlineText " *bar"]+    describe "nested" $ do+        it "bold inside italic"+            $ check "*i __ib__ i*" [InlineItalic [InlineText "i ", InlineBold [InlineText "ib"], InlineText " i"]]+        it "bold inside italic swap"+            $ check "_i **ib** i_" [InlineItalic [InlineText "i ", InlineBold [InlineText "ib"], InlineText " i"]]+        it "italic inside bold"+            $ check "**b _ib_ b**" [InlineBold [InlineText "b ", InlineItalic [InlineText "ib"], InlineText " b"]]+        it "italic inside bold swap"+            $ check "__b *ib* b__" [InlineBold [InlineText "b ", InlineItalic [InlineText "ib"], InlineText " b"]]+    describe "code" $ do+        it "takes all characters"+            $ check "`foo*__*bar` baz`"+                [ InlineCode "foo*__*bar"+                , InlineText " baz`"+                ]+    describe "escaping" $ do+        it "asterisk"+            $ check "\\*foo*\\\\" [InlineText "*foo*\\"]+    describe "links" $ do+        it "simple" $ check "[bar](foo)" [InlineLink "foo" Nothing [InlineText "bar"]]+        it "title" $ check+            "[bar](foo \"baz\")"+            [InlineLink "foo" (Just "baz") [InlineText "bar"]]+            {-+        it "escaped href" $ check+            "<p><a href=\"foo)\" title=\"baz\">bar</a></p>"+            "[bar](foo\\) \"baz\")"+        it "escaped title" $ check+            "<p><a href=\"foo)\" title=\"baz&quot;\">bar</a></p>"+            "[bar](foo\\) \"baz\\\"\")"+        it "inside a paragraph" $ check+            "<p>Hello <a href=\"foo\">bar</a> World</p>"+            "Hello [bar](foo) World"+        it "not a link" $ check+            "<p>Not a [ link</p>"+            "Not a [ link"+            -}
+ test/Tests/Amps and angle encoding.html view
@@ -0,0 +1,17 @@+<p>AT&amp;T has an ampersand in their name.</p>++<p>AT&amp;T is another way to write it.</p>++<p>This &amp; that.</p>++<p>4 &lt; 5.</p>++<p>6 &gt; 5.</p>++<p>Here&#39;s a <a href="http://example.com/?foo=1&amp;bar=2">link</a> with an ampersand in the URL.</p>++<p>Here&#39;s a link with an amersand in the link text: <a href="http://att.com/" title="AT&amp;T">AT&amp;T</a>.</p>++<p>Here&#39;s an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>++<p>Here&#39;s an inline <a href="/script?foo=1&amp;bar=2">link</a>.</p>
+ test/Tests/Amps and angle encoding.text view
@@ -0,0 +1,21 @@+AT&T has an ampersand in their name.++AT&amp;T is another way to write it.++This & that.++4 < 5.++6 > 5.++Here's a [link] [1] with an ampersand in the URL.++Here's a link with an amersand in the link text: [AT&T] [2].++Here's an inline [link](/script?foo=1&bar=2).++Here's an inline [link](</script?foo=1&bar=2>).+++[1]: http://example.com/?foo=1&bar=2+[2]: http://att.com/  "AT&T"
+ test/Tests/Auto links.html view
@@ -0,0 +1,18 @@+<p>Link: <a href="http://example.com/">http://example.com/</a>.</p>++<p>With an ampersand: <a href="http://example.com/?foo=1&amp;bar=2">http://example.com/?foo=1&amp;bar=2</a></p>++<ul>+<li>In a list?</li>+<li><a href="http://example.com/">http://example.com/</a></li>+<li>It should.</li>+</ul>++<blockquote>+<p>Blockquoted: <a href="http://example.com/">http://example.com/</a></p>+</blockquote>++<p>Auto-links should not occur here: <code>&lt;http://example.com/&gt;</code></p>++<pre><code>or here: &lt;http://example.com/&gt;+</code></pre>
+ test/Tests/Auto links.text view
@@ -0,0 +1,13 @@+Link: <http://example.com/>.++With an ampersand: <http://example.com/?foo=1&bar=2>++* In a list?+* <http://example.com/>+* It should.++> Blockquoted: <http://example.com/>++Auto-links should not occur here: `<http://example.com/>`++	or here: <http://example.com/>
+ test/Tests/Backslash escapes.html view
@@ -0,0 +1,118 @@+<p>These should all get escaped:</p>++<p>Backslash: \</p>++<p>Backtick: `</p>++<p>Asterisk: *</p>++<p>Underscore: _</p>++<p>Left brace: {</p>++<p>Right brace: }</p>++<p>Left bracket: [</p>++<p>Right bracket: ]</p>++<p>Left paren: (</p>++<p>Right paren: )</p>++<p>Greater-than: &gt;</p>++<p>Hash: #</p>++<p>Period: .</p>++<p>Bang: !</p>++<p>Plus: +</p>++<p>Minus: -</p>++<p>These should not, because they occur within a code block:</p>++<pre><code>Backslash: \\++Backtick: \`++Asterisk: \*++Underscore: \_++Left brace: \{++Right brace: \}++Left bracket: \[++Right bracket: \]++Left paren: \(++Right paren: \)++Greater-than: \&gt;++Hash: \#++Period: \.++Bang: \!++Plus: \+++Minus: \-+</code></pre>++<p>Nor should these, which occur in code spans:</p>++<p>Backslash: <code>\\</code></p>++<p>Backtick: <code>\`</code></p>++<p>Asterisk: <code>\*</code></p>++<p>Underscore: <code>\_</code></p>++<p>Left brace: <code>\{</code></p>++<p>Right brace: <code>\}</code></p>++<p>Left bracket: <code>\[</code></p>++<p>Right bracket: <code>\]</code></p>++<p>Left paren: <code>\(</code></p>++<p>Right paren: <code>\)</code></p>++<p>Greater-than: <code>\&gt;</code></p>++<p>Hash: <code>\#</code></p>++<p>Period: <code>\.</code></p>++<p>Bang: <code>\!</code></p>++<p>Plus: <code>\+</code></p>++<p>Minus: <code>\-</code></p>+++<p>These should get escaped, even though they&#39;re matching pairs for+other Markdown constructs:</p>++<p>*asterisks*</p>++<p>_underscores_</p>++<p>`backticks`</p>++<p>This is a code span with a literal backslash-backtick sequence: <code>\`</code></p>++<p>This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.</p>++<p>This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.</p>
+ test/Tests/Backslash escapes.text view
@@ -0,0 +1,120 @@+These should all get escaped:++Backslash: \\++Backtick: \`++Asterisk: \*++Underscore: \_++Left brace: \{++Right brace: \}++Left bracket: \[++Right bracket: \]++Left paren: \(++Right paren: \)++Greater-than: \>++Hash: \#++Period: \.++Bang: \!++Plus: \+++Minus: \-++++These should not, because they occur within a code block:++	Backslash: \\++	Backtick: \`++	Asterisk: \*++	Underscore: \_++	Left brace: \{++	Right brace: \}++	Left bracket: \[++	Right bracket: \]++	Left paren: \(++	Right paren: \)++	Greater-than: \>++	Hash: \#++	Period: \.++	Bang: \!++	Plus: \+++	Minus: \-+++Nor should these, which occur in code spans:++Backslash: `\\`++Backtick: `` \` ``++Asterisk: `\*`++Underscore: `\_`++Left brace: `\{`++Right brace: `\}`++Left bracket: `\[`++Right bracket: `\]`++Left paren: `\(`++Right paren: `\)`++Greater-than: `\>`++Hash: `\#`++Period: `\.`++Bang: `\!`++Plus: `\+`++Minus: `\-`+++These should get escaped, even though they're matching pairs for+other Markdown constructs:++\*asterisks\*++\_underscores\_++\`backticks\`++This is a code span with a literal backslash-backtick sequence: `` \` ``++This is a tag with unescaped backticks <span attr='`ticks`'>bar</span>.++This is a tag with backslashes <span attr='\\backslashes\\'>bar</span>.
+ test/Tests/Blockquotes with code blocks.html view
@@ -0,0 +1,15 @@+<blockquote>+<p>Example:</p>++<pre><code>sub status {+    print &quot;working&quot;;+}+</code></pre>++<p>Or:</p>++<pre><code>sub status {+    return &quot;working&quot;;+}+</code></pre>+</blockquote>
+ test/Tests/Blockquotes with code blocks.text view
@@ -0,0 +1,11 @@+> Example:+> +>     sub status {+>         print "working";+>     }+> +> Or:+> +>     sub status {+>         return "working";+>     }
+ test/Tests/Code Blocks.html view
@@ -0,0 +1,18 @@+<pre><code>code block on the first line+</code></pre>++<p>Regular text.</p>++<pre><code>code block indented by spaces+</code></pre>++<p>Regular text.</p>++<pre><code>the lines in this block  +all contain trailing spaces  +</code></pre>++<p>Regular Text.</p>++<pre><code>code block on the last line+</code></pre>
+ test/Tests/Code Blocks.text view
@@ -0,0 +1,14 @@+	code block on the first line+	+Regular text.++    code block indented by spaces++Regular text.++	the lines in this block  +	all contain trailing spaces  ++Regular Text.++	code block on the last line
+ test/Tests/Code Spans.html view
@@ -0,0 +1,5 @@+<p><code>&lt;test a=&quot;</code> content of attribute <code>&quot;&gt;</code></p>++<p>Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span></p>++<p>Here&#39;s how you put <code>`backticks`</code> in a code span.</p>
+ test/Tests/Code Spans.text view
@@ -0,0 +1,5 @@+`<test a="` content of attribute `">`++Fix for backticks within HTML tag: <span attr='`ticks`'>like this</span>++Here's how you put `` `backticks` `` in a code span.
+ test/Tests/Hard-wrapped paragraphs with list-like lines.html view
@@ -0,0 +1,8 @@+<p>In Markdown 1.0.0 and earlier. Version+8. This line turns into a list item.+Because a hard-wrapped line in the+middle of a paragraph looked like a+list item.</p>++<p>Here&#39;s one with a bullet.+* criminey.</p>
+ test/Tests/Hard-wrapped paragraphs with list-like lines.text view
@@ -0,0 +1,8 @@+In Markdown 1.0.0 and earlier. Version+8. This line turns into a list item.+Because a hard-wrapped line in the+middle of a paragraph looked like a+list item.++Here's one with a bullet.+* criminey.
+ test/Tests/Horizontal rules.html view
@@ -0,0 +1,71 @@+<p>Dashes:</p>++<hr>++<hr>++<hr>++<hr>++<pre><code>---+</code></pre>++<hr>++<hr>++<hr>++<hr>++<pre><code>- - -+</code></pre>++<p>Asterisks:</p>++<hr>++<hr>++<hr>++<hr>++<pre><code>***+</code></pre>++<hr>++<hr>++<hr>++<hr>++<pre><code>* * *+</code></pre>++<p>Underscores:</p>++<hr>++<hr>++<hr>++<hr>++<pre><code>___+</code></pre>++<hr>++<hr>++<hr>++<hr>++<pre><code>_ _ _+</code></pre>
+ test/Tests/Horizontal rules.text view
@@ -0,0 +1,67 @@+Dashes:++---++ ---+ +  ---++   ---++	---++- - -++ - - -+ +  - - -++   - - -++	- - -+++Asterisks:++***++ ***+ +  ***++   ***++	***++* * *++ * * *+ +  * * *++   * * *++	* * *+++Underscores:++___++ ___+ +  ___++   ___++    ___++_ _ _++ _ _ _+ +  _ _ _++   _ _ _++    _ _ _
+ test/Tests/Images.html view
@@ -0,0 +1,21 @@+<p><img src="/path/to/img.jpg" alt="Alt text"></p>++<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title"></p>++<p>Inline within a paragraph: <a href="/url/">alt text</a>.</p>++<p><img src="/url/" alt="alt text" title="title preceded by two spaces"></p>++<p><img src="/url/" alt="alt text" title="title has spaces afterward"></p>++<p><img src="/url/" alt="alt text"></p>++<p><img src="/url/" alt="alt text" title="with a title">.</p>++<p><img src="" alt="Empty"></p>++<p><img src="http://example.com/(parens).jpg" alt="this is a stupid URL"></p>++<p><img src="/url/" alt="alt text"></p>++<p><img src="/url/" alt="alt text" title="Title here"></p>
+ test/Tests/Images.text view
@@ -0,0 +1,26 @@+![Alt text](/path/to/img.jpg)++![Alt text](/path/to/img.jpg "Optional title")++Inline within a paragraph: [alt text](/url/).++![alt text](/url/  "title preceded by two spaces")++![alt text](/url/  "title has spaces afterward"  )++![alt text](</url/>)++![alt text](</url/> "with a title").++![Empty]()++![this is a stupid URL](http://example.com/(parens).jpg)+++![alt text][foo]++  [foo]: /url/++![alt text][bar]++  [bar]: /url/ "Title here"
+ test/Tests/Inline HTML (Advanced).html view
@@ -0,0 +1,30 @@+<p>Simple block on one line:</p>++<div>foo</div>++<p>And nested without indentation:</p>++<div>+<div>+<div>+foo+</div>+<div style=">"/>+</div>+<div>bar</div>+</div>++<p>And with attributes:</p>++<div>+    <div id="foo">+    </div>+</div>++<p>This was broken in 1.0.2b7:</p>++<div class="inlinepage">+<div class="toggleableend">+foo+</div>+</div>
+ test/Tests/Inline HTML (Advanced).text view
@@ -0,0 +1,30 @@+Simple block on one line:++<div>foo</div>++And nested without indentation:++<div>+<div>+<div>+foo+</div>+<div style=">"/>+</div>+<div>bar</div>+</div>++And with attributes:++<div>+	<div id="foo">+	</div>+</div>++This was broken in 1.0.2b7:++<div class="inlinepage">+<div class="toggleableend">+foo+</div>+</div>
+ test/Tests/Inline HTML (Simple).html view
@@ -0,0 +1,72 @@+<p>Here&#39;s a simple block:</p>++<div>+    foo+</div>++<p>This should be a code block, though:</p>++<pre><code>&lt;div&gt;+    foo+&lt;/div&gt;+</code></pre>++<p>As should this:</p>++<pre><code>&lt;div&gt;foo&lt;/div&gt;+</code></pre>++<p>Now, nested:</p>++<div>+    <div>+        <div>+            foo+        </div>+    </div>+</div>++<p>This should just be an HTML comment:</p>++<!-- Comment -->++<p>Multiline:</p>++<!--+Blah+Blah+-->++<p>Code block:</p>++<pre><code>&lt;!-- Comment --&gt;+</code></pre>++<p>Just plain comment, with trailing spaces on the line:</p>++<!-- foo -->   ++<p>Code:</p>++<pre><code>&lt;hr /&gt;+</code></pre>++<p>Hr&#39;s:</p>++<hr>++<hr/>++<hr />++<hr>   ++<hr/>  ++<hr /> ++<hr class="foo" id="bar" />++<hr class="foo" id="bar"/>++<hr class="foo" id="bar" >
+ test/Tests/Inline HTML (Simple).text view
@@ -0,0 +1,69 @@+Here's a simple block:++<div>+	foo+</div>++This should be a code block, though:++	<div>+		foo+	</div>++As should this:++	<div>foo</div>++Now, nested:++<div>+	<div>+		<div>+			foo+		</div>+	</div>+</div>++This should just be an HTML comment:++<!-- Comment -->++Multiline:++<!--+Blah+Blah+-->++Code block:++	<!-- Comment -->++Just plain comment, with trailing spaces on the line:++<!-- foo -->   ++Code:++	<hr />+	+Hr's:++<hr>++<hr/>++<hr />++<hr>   ++<hr/>  ++<hr /> ++<hr class="foo" id="bar" />++<hr class="foo" id="bar"/>++<hr class="foo" id="bar" >+
+ test/Tests/Inline HTML comments.html view
@@ -0,0 +1,13 @@+<p>Paragraph one.</p>++<!-- This is a simple comment -->++<!--+    This is another comment.+-->++<p>Paragraph two.</p>++<!-- one comment block -- -- with two comments -->++<p>The end.</p>
+ test/Tests/Inline HTML comments.text view
@@ -0,0 +1,13 @@+Paragraph one.++<!-- This is a simple comment -->++<!--+	This is another comment.+-->++Paragraph two.++<!-- one comment block -- -- with two comments -->++The end.
+ test/Tests/Links, inline style.html view
@@ -0,0 +1,23 @@+<p>Just a <a href="/url/">URL</a>.</p>++<p><a href="/url/" title="title">URL and title</a>.</p>++<p><a href="/url/" title="title preceded by two spaces">URL and title</a>.</p>++<p><a href="/url/" title="title preceded by a tab">URL and title</a>.</p>++<p><a href="/url/" title="title has spaces afterward">URL and title</a>.</p>++<p><a href="/url/">URL wrapped in angle brackets</a>.</p>++<p><a href="/url/" title="Here&#39;s the title">URL w/ angle brackets + title</a>.</p>++<p><a href="">Empty</a>.</p>++<p><a href="http://en.wikipedia.org/wiki/WIMP_(computing)">With parens in the URL</a></p>++<p>(With outer parens and <a href="/foo(bar)">parens in url</a>)</p>++<p><a href="/foo(bar)" title="and a title">With parens in the URL</a></p>++<p>(With outer parens and <a href="/foo(bar)" title="and a title">parens in url</a>)</p>
+ test/Tests/Links, inline style.text view
@@ -0,0 +1,24 @@+Just a [URL](/url/).++[URL and title](/url/ "title").++[URL and title](/url/  "title preceded by two spaces").++[URL and title](/url/	"title preceded by a tab").++[URL and title](/url/ "title has spaces afterward"  ).++[URL wrapped in angle brackets](</url/>).++[URL w/ angle brackets + title](</url/> "Here's the title").++[Empty]().++[With parens in the URL](http://en.wikipedia.org/wiki/WIMP_(computing))++(With outer parens and [parens in url](/foo(bar)))+++[With parens in the URL](/foo(bar) "and a title")++(With outer parens and [parens in url](/foo(bar) "and a title"))
+ test/Tests/Links, reference style.html view
@@ -0,0 +1,52 @@+<p>Foo <a href="/url/" title="Title">bar</a>.</p>++<p>Foo <a href="/url/" title="Title">bar</a>.</p>++<p>Foo <a href="/url/" title="Title">bar</a>.</p>++<p>With <a href="/url/">embedded [brackets]</a>.</p>++<p>Indented <a href="/url">once</a>.</p>++<p>Indented <a href="/url">twice</a>.</p>++<p>Indented <a href="/url">thrice</a>.</p>++<p>Indented [four][] times.</p>++<pre><code>[four]: /url+</code></pre>++<hr>++<p><a href="foo">this</a> should work</p>++<p>So should <a href="foo">this</a>.</p>++<p>And <a href="foo">this</a>.</p>++<p>And <a href="foo">this</a>.</p>++<p>And <a href="foo">this</a>.</p>++<p>But not [that] [].</p>++<p>Nor [that][].</p>++<p>Nor [that].</p>++<p>[Something in brackets like <a href="foo">this</a> should work]</p>++<p>[Same with <a href="foo">this</a>.]</p>++<p>In this case, <a href="/somethingelse/">this</a> points to something else.</p>++<p>Backslashing should suppress [this] and [this].</p>++<hr>++<p>Here&#39;s one where the <a href="/url/">link+breaks</a> across lines.</p>++<p>Here&#39;s another where the <a href="/url/">link +breaks</a> across lines, but with a line-ending space.</p>
+ test/Tests/Links, reference style.text view
@@ -0,0 +1,71 @@+Foo [bar] [1].++Foo [bar][1].++Foo [bar]+[1].++[1]: /url/  "Title"+++With [embedded [brackets]] [b].+++Indented [once][].++Indented [twice][].++Indented [thrice][].++Indented [four][] times.++ [once]: /url++  [twice]: /url++   [thrice]: /url++    [four]: /url+++[b]: /url/++* * *++[this] [this] should work++So should [this][this].++And [this] [].++And [this][].++And [this].++But not [that] [].++Nor [that][].++Nor [that].++[Something in brackets like [this][] should work]++[Same with [this].]++In this case, [this](/somethingelse/) points to something else.++Backslashing should suppress \[this] and [this\].++[this]: foo+++* * *++Here's one where the [link+breaks] across lines.++Here's another where the [link +breaks] across lines, but with a line-ending space.+++[link breaks]: /url/
+ test/Tests/Links, shortcut references.html view
@@ -0,0 +1,9 @@+<p>This is the <a href="/simple">simple case</a>.</p>++<p>This one has a <a href="/foo">line+break</a>.</p>++<p>This one has a <a href="/foo">line +break</a> with a line-ending space.</p>++<p><a href="/that">this</a> and the <a href="/other">other</a></p>
+ test/Tests/Links, shortcut references.text view
@@ -0,0 +1,20 @@+This is the [simple case].++[simple case]: /simple++++This one has a [line+break].++This one has a [line +break] with a line-ending space.++[line break]: /foo+++[this] [that] and the [other]++[this]: /this+[that]: /that+[other]: /other
+ test/Tests/Literal quotes in titles.html view
@@ -0,0 +1,3 @@+<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>++<p>Foo <a href="/url/" title="Title with &quot;quotes&quot; inside">bar</a>.</p>
+ test/Tests/Literal quotes in titles.text view
@@ -0,0 +1,7 @@+Foo [bar][].++Foo [bar](/url/ "Title with "quotes" inside").+++  [bar]: /url/ "Title with "quotes" inside"+
+ test/Tests/Markdown Documentation - Basics.html view
@@ -0,0 +1,314 @@+<h1>Markdown: Basics</h1>++<ul id="ProjectSubmenu">+    <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>+    <li><a class="selected" title="Markdown Basics">Basics</a></li>+    <li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>+    <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>+    <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>+</ul>++<h2>Getting the Gist of Markdown's Formatting Syntax</h2>++<p>This page offers a brief overview of what it's like to use Markdown.+The <a href="/projects/markdown/syntax" title="Markdown Syntax">syntax page</a> provides complete, detailed documentation for+every feature, but Markdown should be very easy to pick up simply by+looking at a few examples of it in action. The examples on this page+are written in a before/after style, showing example syntax and the+HTML output produced by Markdown.</p>++<p>It's also helpful to simply try Markdown out; the <a href="/projects/markdown/dingus" title="Markdown Dingus">Dingus</a> is a+web application that allows you type your own Markdown-formatted text+and translate it to XHTML.</p>++<p><strong>Note:</strong> This document is itself written using Markdown; you+can <a href="/projects/markdown/basics.text">see the source for it by adding '.text' to the URL</a>.</p>++<h2>Paragraphs, Headers, Blockquotes</h2>++<p>A paragraph is simply one or more consecutive lines of text, separated+by one or more blank lines. (A blank line is any line that looks like a+blank line -- a line containing nothing spaces or tabs is considered+blank.) Normal paragraphs should not be intended with spaces or tabs.</p>++<p>Markdown offers two styles of headers: <em>Setext</em> and <em>atx</em>.+Setext-style headers for <code>&lt;h1&gt;</code> and <code>&lt;h2&gt;</code> are created by+"underlining" with equal signs (<code>=</code>) and hyphens (<code>-</code>), respectively.+To create an atx-style header, you put 1-6 hash marks (<code>#</code>) at the+beginning of the line -- the number of hashes equals the resulting+HTML header level.</p>++<p>Blockquotes are indicated using email-style '<code>&gt;</code>' angle brackets.</p>++<p>Markdown:</p>++<pre><code>A First Level Header+====================++A Second Level Header+---------------------++Now is the time for all good men to come to+the aid of their country. This is just a+regular paragraph.++The quick brown fox jumped over the lazy+dog's back.++### Header 3++&gt; This is a blockquote.+&gt; +&gt; This is the second paragraph in the blockquote.+&gt;+&gt; ## This is an H2 in a blockquote+</code></pre>++<p>Output:</p>++<pre><code>&lt;h1&gt;A First Level Header&lt;/h1&gt;++&lt;h2&gt;A Second Level Header&lt;/h2&gt;++&lt;p&gt;Now is the time for all good men to come to+the aid of their country. This is just a+regular paragraph.&lt;/p&gt;++&lt;p&gt;The quick brown fox jumped over the lazy+dog's back.&lt;/p&gt;++&lt;h3&gt;Header 3&lt;/h3&gt;++&lt;blockquote&gt;+    &lt;p&gt;This is a blockquote.&lt;/p&gt;++    &lt;p&gt;This is the second paragraph in the blockquote.&lt;/p&gt;++    &lt;h2&gt;This is an H2 in a blockquote&lt;/h2&gt;+&lt;/blockquote&gt;+</code></pre>++<h3>Phrase Emphasis</h3>++<p>Markdown uses asterisks and underscores to indicate spans of emphasis.</p>++<p>Markdown:</p>++<pre><code>Some of these words *are emphasized*.+Some of these words _are emphasized also_.++Use two asterisks for **strong emphasis**.+Or, if you prefer, __use two underscores instead__.+</code></pre>++<p>Output:</p>++<pre><code>&lt;p&gt;Some of these words &lt;em&gt;are emphasized&lt;/em&gt;.+Some of these words &lt;em&gt;are emphasized also&lt;/em&gt;.&lt;/p&gt;++&lt;p&gt;Use two asterisks for &lt;strong&gt;strong emphasis&lt;/strong&gt;.+Or, if you prefer, &lt;strong&gt;use two underscores instead&lt;/strong&gt;.&lt;/p&gt;+</code></pre>++<h2>Lists</h2>++<p>Unordered (bulleted) lists use asterisks, pluses, and hyphens (<code>*</code>,+<code>+</code>, and <code>-</code>) as list markers. These three markers are+interchangable; this:</p>++<pre><code>*   Candy.+*   Gum.+*   Booze.+</code></pre>++<p>this:</p>++<pre><code>+   Candy.++   Gum.++   Booze.+</code></pre>++<p>and this:</p>++<pre><code>-   Candy.+-   Gum.+-   Booze.+</code></pre>++<p>all produce the same output:</p>++<pre><code>&lt;ul&gt;+&lt;li&gt;Candy.&lt;/li&gt;+&lt;li&gt;Gum.&lt;/li&gt;+&lt;li&gt;Booze.&lt;/li&gt;+&lt;/ul&gt;+</code></pre>++<p>Ordered (numbered) lists use regular numbers, followed by periods, as+list markers:</p>++<pre><code>1.  Red+2.  Green+3.  Blue+</code></pre>++<p>Output:</p>++<pre><code>&lt;ol&gt;+&lt;li&gt;Red&lt;/li&gt;+&lt;li&gt;Green&lt;/li&gt;+&lt;li&gt;Blue&lt;/li&gt;+&lt;/ol&gt;+</code></pre>++<p>If you put blank lines between items, you'll get <code>&lt;p&gt;</code> tags for the+list item text. You can create multi-paragraph list items by indenting+the paragraphs by 4 spaces or 1 tab:</p>++<pre><code>*   A list item.++    With multiple paragraphs.++*   Another item in the list.+</code></pre>++<p>Output:</p>++<pre><code>&lt;ul&gt;+&lt;li&gt;&lt;p&gt;A list item.&lt;/p&gt;+&lt;p&gt;With multiple paragraphs.&lt;/p&gt;&lt;/li&gt;+&lt;li&gt;&lt;p&gt;Another item in the list.&lt;/p&gt;&lt;/li&gt;+&lt;/ul&gt;+</code></pre>++<h3>Links</h3>++<p>Markdown supports two styles for creating links: <em>inline</em> and+<em>reference</em>. With both styles, you use square brackets to delimit the+text you want to turn into a link.</p>++<p>Inline-style links use parentheses immediately after the link text.+For example:</p>++<pre><code>This is an [example link](http://example.com/).+</code></pre>++<p>Output:</p>++<pre><code>&lt;p&gt;This is an &lt;a href="http://example.com/"&gt;+example link&lt;/a&gt;.&lt;/p&gt;+</code></pre>++<p>Optionally, you may include a title attribute in the parentheses:</p>++<pre><code>This is an [example link](http://example.com/ "With a Title").+</code></pre>++<p>Output:</p>++<pre><code>&lt;p&gt;This is an &lt;a href="http://example.com/" title="With a Title"&gt;+example link&lt;/a&gt;.&lt;/p&gt;+</code></pre>++<p>Reference-style links allow you to refer to your links by names, which+you define elsewhere in your document:</p>++<pre><code>I get 10 times more traffic from [Google][1] than from+[Yahoo][2] or [MSN][3].++[1]: http://google.com/        "Google"+[2]: http://search.yahoo.com/  "Yahoo Search"+[3]: http://search.msn.com/    "MSN Search"+</code></pre>++<p>Output:</p>++<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"+title="Google"&gt;Google&lt;/a&gt; than from &lt;a href="http://search.yahoo.com/"+title="Yahoo Search"&gt;Yahoo&lt;/a&gt; or &lt;a href="http://search.msn.com/"+title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;+</code></pre>++<p>The title attribute is optional. Link names may contain letters,+numbers and spaces, but are <em>not</em> case sensitive:</p>++<pre><code>I start my morning with a cup of coffee and+[The New York Times][NY Times].++[ny times]: http://www.nytimes.com/+</code></pre>++<p>Output:</p>++<pre><code>&lt;p&gt;I start my morning with a cup of coffee and+&lt;a href="http://www.nytimes.com/"&gt;The New York Times&lt;/a&gt;.&lt;/p&gt;+</code></pre>++<h3>Images</h3>++<p>Image syntax is very much like link syntax.</p>++<p>Inline (titles are optional):</p>++<pre><code>![alt text](/path/to/img.jpg "Title")+</code></pre>++<p>Reference-style:</p>++<pre><code>![alt text][id]++[id]: /path/to/img.jpg "Title"+</code></pre>++<p>Both of the above examples produce the same output:</p>++<pre><code>&lt;img src="/path/to/img.jpg" alt="alt text" title="Title" /&gt;+</code></pre>++<h3>Code</h3>++<p>In a regular paragraph, you can create code span by wrapping text in+backtick quotes. Any ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> or+<code>&gt;</code>) will automatically be translated into HTML entities. This makes+it easy to use Markdown to write about HTML example code:</p>++<pre><code>I strongly recommend against using any `&lt;blink&gt;` tags.++I wish SmartyPants used named entities like `&amp;mdash;`+instead of decimal-encoded entites like `&amp;#8212;`.+</code></pre>++<p>Output:</p>++<pre><code>&lt;p&gt;I strongly recommend against using any+&lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;++&lt;p&gt;I wish SmartyPants used named entities like+&lt;code&gt;&amp;amp;mdash;&lt;/code&gt; instead of decimal-encoded+entites like &lt;code&gt;&amp;amp;#8212;&lt;/code&gt;.&lt;/p&gt;+</code></pre>++<p>To specify an entire block of pre-formatted code, indent every line of+the block by 4 spaces or 1 tab. Just like with code spans, <code>&amp;</code>, <code>&lt;</code>,+and <code>&gt;</code> characters will be escaped automatically.</p>++<p>Markdown:</p>++<pre><code>If you want your page to validate under XHTML 1.0 Strict,+you've got to put paragraph tags in your blockquotes:++    &lt;blockquote&gt;+        &lt;p&gt;For example.&lt;/p&gt;+    &lt;/blockquote&gt;+</code></pre>++<p>Output:</p>++<pre><code>&lt;p&gt;If you want your page to validate under XHTML 1.0 Strict,+you've got to put paragraph tags in your blockquotes:&lt;/p&gt;++&lt;pre&gt;&lt;code&gt;&amp;lt;blockquote&amp;gt;+    &amp;lt;p&amp;gt;For example.&amp;lt;/p&amp;gt;+&amp;lt;/blockquote&amp;gt;+&lt;/code&gt;&lt;/pre&gt;+</code></pre>
+ test/Tests/Markdown Documentation - Syntax.html view
@@ -0,0 +1,942 @@+<h1>Markdown: Syntax</h1>++<ul id="ProjectSubmenu">+    <li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>+    <li><a href="/projects/markdown/basics" title="Markdown Basics">Basics</a></li>+    <li><a class="selected" title="Markdown Syntax Documentation">Syntax</a></li>+    <li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>+    <li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>+</ul>++<ul>+<li><a href="#overview">Overview</a>+<ul>+<li><a href="#philosophy">Philosophy</a></li>+<li><a href="#html">Inline HTML</a></li>+<li><a href="#autoescape">Automatic Escaping for Special Characters</a></li>+</ul></li>+<li><a href="#block">Block Elements</a>+<ul>+<li><a href="#p">Paragraphs and Line Breaks</a></li>+<li><a href="#header">Headers</a></li>+<li><a href="#blockquote">Blockquotes</a></li>+<li><a href="#list">Lists</a></li>+<li><a href="#precode">Code Blocks</a></li>+<li><a href="#hr">Horizontal Rules</a></li>+</ul></li>+<li><a href="#span">Span Elements</a>+<ul>+<li><a href="#link">Links</a></li>+<li><a href="#em">Emphasis</a></li>+<li><a href="#code">Code</a></li>+<li><a href="#img">Images</a></li>+</ul></li>+<li><a href="#misc">Miscellaneous</a>+<ul>+<li><a href="#backslash">Backslash Escapes</a></li>+<li><a href="#autolink">Automatic Links</a></li>+</ul></li>+</ul>++<p><strong>Note:</strong> This document is itself written using Markdown; you+can <a href="/projects/markdown/syntax.text">see the source for it by adding '.text' to the URL</a>.</p>++<hr />++<h2 id="overview">Overview</h2>++<h3 id="philosophy">Philosophy</h3>++<p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>++<p>Readability, however, is emphasized above all else. A Markdown-formatted+document should be publishable as-is, as plain text, without looking+like it's been marked up with tags or formatting instructions. While+Markdown's syntax has been influenced by several existing text-to-HTML+filters -- including <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a>, <a href="http://www.aaronsw.com/2002/atx/">atx</a>, <a href="http://textism.com/tools/textile/">Textile</a>, <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>,+<a href="http://www.triptico.com/software/grutatxt.html">Grutatext</a>, and <a href="http://ettext.taint.org/doc/">EtText</a> -- the single biggest source of+inspiration for Markdown's syntax is the format of plain text email.</p>++<p>To this end, Markdown's syntax is comprised entirely of punctuation+characters, which punctuation characters have been carefully chosen so+as to look like what they mean. E.g., asterisks around a word actually+look like *emphasis*. Markdown lists look like, well, lists. Even+blockquotes look like quoted passages of text, assuming you've ever+used email.</p>++<h3 id="html">Inline HTML</h3>++<p>Markdown's syntax is intended for one purpose: to be used as a+format for <em>writing</em> for the web.</p>++<p>Markdown is not a replacement for HTML, or even close to it. Its+syntax is very small, corresponding only to a very small subset of+HTML tags. The idea is <em>not</em> to create a syntax that makes it easier+to insert HTML tags. In my opinion, HTML tags are already easy to+insert. The idea for Markdown is to make it easy to read, write, and+edit prose. HTML is a <em>publishing</em> format; Markdown is a <em>writing</em>+format. Thus, Markdown's formatting syntax only addresses issues that+can be conveyed in plain text.</p>++<p>For any markup that is not covered by Markdown's syntax, you simply+use HTML itself. There's no need to preface it or delimit it to+indicate that you're switching from Markdown to HTML; you just use+the tags.</p>++<p>The only restrictions are that block-level HTML elements -- e.g. <code>&lt;div&gt;</code>,+<code>&lt;table&gt;</code>, <code>&lt;pre&gt;</code>, <code>&lt;p&gt;</code>, etc. -- must be separated from surrounding+content by blank lines, and the start and end tags of the block should+not be indented with tabs or spaces. Markdown is smart enough not+to add extra (unwanted) <code>&lt;p&gt;</code> tags around HTML block-level tags.</p>++<p>For example, to add an HTML table to a Markdown article:</p>++<pre><code>This is a regular paragraph.++&lt;table&gt;+    &lt;tr&gt;+        &lt;td&gt;Foo&lt;/td&gt;+    &lt;/tr&gt;+&lt;/table&gt;++This is another regular paragraph.+</code></pre>++<p>Note that Markdown formatting syntax is not processed within block-level+HTML tags. E.g., you can't use Markdown-style <code>*emphasis*</code> inside an+HTML block.</p>++<p>Span-level HTML tags -- e.g. <code>&lt;span&gt;</code>, <code>&lt;cite&gt;</code>, or <code>&lt;del&gt;</code> -- can be+used anywhere in a Markdown paragraph, list item, or header. If you+want, you can even use HTML tags instead of Markdown formatting; e.g. if+you'd prefer to use HTML <code>&lt;a&gt;</code> or <code>&lt;img&gt;</code> tags instead of Markdown's+link or image syntax, go right ahead.</p>++<p>Unlike block-level HTML tags, Markdown syntax <em>is</em> processed within+span-level tags.</p>++<h3 id="autoescape">Automatic Escaping for Special Characters</h3>++<p>In HTML, there are two characters that demand special treatment: <code>&lt;</code>+and <code>&amp;</code>. Left angle brackets are used to start tags; ampersands are+used to denote HTML entities. If you want to use them as literal+characters, you must escape them as entities, e.g. <code>&amp;lt;</code>, and+<code>&amp;amp;</code>.</p>++<p>Ampersands in particular are bedeviling for web writers. If you want to+write about 'AT&amp;T', you need to write '<code>AT&amp;amp;T</code>'. You even need to+escape ampersands within URLs. Thus, if you want to link to:</p>++<pre><code>http://images.google.com/images?num=30&amp;q=larry+bird+</code></pre>++<p>you need to encode the URL as:</p>++<pre><code>http://images.google.com/images?num=30&amp;amp;q=larry+bird+</code></pre>++<p>in your anchor tag <code>href</code> attribute. Needless to say, this is easy to+forget, and is probably the single most common source of HTML validation+errors in otherwise well-marked-up web sites.</p>++<p>Markdown allows you to use these characters naturally, taking care of+all the necessary escaping for you. If you use an ampersand as part of+an HTML entity, it remains unchanged; otherwise it will be translated+into <code>&amp;amp;</code>.</p>++<p>So, if you want to include a copyright symbol in your article, you can write:</p>++<pre><code>&amp;copy;+</code></pre>++<p>and Markdown will leave it alone. But if you write:</p>++<pre><code>AT&amp;T+</code></pre>++<p>Markdown will translate it to:</p>++<pre><code>AT&amp;amp;T+</code></pre>++<p>Similarly, because Markdown supports <a href="#html">inline HTML</a>, if you use+angle brackets as delimiters for HTML tags, Markdown will treat them as+such. But if you write:</p>++<pre><code>4 &lt; 5+</code></pre>++<p>Markdown will translate it to:</p>++<pre><code>4 &amp;lt; 5+</code></pre>++<p>However, inside Markdown code spans and blocks, angle brackets and+ampersands are <em>always</em> encoded automatically. This makes it easy to use+Markdown to write about HTML code. (As opposed to raw HTML, which is a+terrible format for writing about HTML syntax, because every single <code>&lt;</code>+and <code>&amp;</code> in your example code needs to be escaped.)</p>++<hr />++<h2 id="block">Block Elements</h2>++<h3 id="p">Paragraphs and Line Breaks</h3>++<p>A paragraph is simply one or more consecutive lines of text, separated+by one or more blank lines. (A blank line is any line that looks like a+blank line -- a line containing nothing but spaces or tabs is considered+blank.) Normal paragraphs should not be intended with spaces or tabs.</p>++<p>The implication of the "one or more consecutive lines of text" rule is+that Markdown supports "hard-wrapped" text paragraphs. This differs+significantly from most other text-to-HTML formatters (including Movable+Type's "Convert Line Breaks" option) which translate every line break+character in a paragraph into a <code>&lt;br /&gt;</code> tag.</p>++<p>When you <em>do</em> want to insert a <code>&lt;br /&gt;</code> break tag using Markdown, you+end a line with two or more spaces, then type return.</p>++<p>Yes, this takes a tad more effort to create a <code>&lt;br /&gt;</code>, but a simplistic+"every line break is a <code>&lt;br /&gt;</code>" rule wouldn't work for Markdown.+Markdown's email-style <a href="#blockquote">blockquoting</a> and multi-paragraph <a href="#list">list items</a>+work best -- and look better -- when you format them with hard breaks.</p>++<h3 id="header">Headers</h3>++<p>Markdown supports two styles of headers, <a href="http://docutils.sourceforge.net/mirror/setext.html">Setext</a> and <a href="http://www.aaronsw.com/2002/atx/">atx</a>.</p>++<p>Setext-style headers are "underlined" using equal signs (for first-level+headers) and dashes (for second-level headers). For example:</p>++<pre><code>This is an H1+=============++This is an H2+-------------+</code></pre>++<p>Any number of underlining <code>=</code>'s or <code>-</code>'s will work.</p>++<p>Atx-style headers use 1-6 hash characters at the start of the line,+corresponding to header levels 1-6. For example:</p>++<pre><code># This is an H1++## This is an H2++###### This is an H6+</code></pre>++<p>Optionally, you may "close" atx-style headers. This is purely+cosmetic -- you can use this if you think it looks better. The+closing hashes don't even need to match the number of hashes+used to open the header. (The number of opening hashes+determines the header level.) :</p>++<pre><code># This is an H1 #++## This is an H2 ##++### This is an H3 ######+</code></pre>++<h3 id="blockquote">Blockquotes</h3>++<p>Markdown uses email-style <code>&gt;</code> characters for blockquoting. If you're+familiar with quoting passages of text in an email message, then you+know how to create a blockquote in Markdown. It looks best if you hard+wrap the text and put a <code>&gt;</code> before every line:</p>++<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,+&gt; consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.+&gt; Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.+&gt; +&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse+&gt; id sem consectetuer libero luctus adipiscing.+</code></pre>++<p>Markdown allows you to be lazy and only put the <code>&gt;</code> before the first+line of a hard-wrapped paragraph:</p>++<pre><code>&gt; This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,+consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.+Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.++&gt; Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse+id sem consectetuer libero luctus adipiscing.+</code></pre>++<p>Blockquotes can be nested (i.e. a blockquote-in-a-blockquote) by+adding additional levels of <code>&gt;</code>:</p>++<pre><code>&gt; This is the first level of quoting.+&gt;+&gt; &gt; This is nested blockquote.+&gt;+&gt; Back to the first level.+</code></pre>++<p>Blockquotes can contain other Markdown elements, including headers, lists,+and code blocks:</p>++<pre><code>&gt; ## This is a header.+&gt; +&gt; 1.   This is the first list item.+&gt; 2.   This is the second list item.+&gt; +&gt; Here's some example code:+&gt; +&gt;     return shell_exec("echo $input | $markdown_script");+</code></pre>++<p>Any decent text editor should make email-style quoting easy. For+example, with BBEdit, you can make a selection and choose Increase+Quote Level from the Text menu.</p>++<h3 id="list">Lists</h3>++<p>Markdown supports ordered (numbered) and unordered (bulleted) lists.</p>++<p>Unordered lists use asterisks, pluses, and hyphens -- interchangably+-- as list markers:</p>++<pre><code>*   Red+*   Green+*   Blue+</code></pre>++<p>is equivalent to:</p>++<pre><code>+   Red++   Green++   Blue+</code></pre>++<p>and:</p>++<pre><code>-   Red+-   Green+-   Blue+</code></pre>++<p>Ordered lists use numbers followed by periods:</p>++<pre><code>1.  Bird+2.  McHale+3.  Parish+</code></pre>++<p>It's important to note that the actual numbers you use to mark the+list have no effect on the HTML output Markdown produces. The HTML+Markdown produces from the above list is:</p>++<pre><code>&lt;ol&gt;+&lt;li&gt;Bird&lt;/li&gt;+&lt;li&gt;McHale&lt;/li&gt;+&lt;li&gt;Parish&lt;/li&gt;+&lt;/ol&gt;+</code></pre>++<p>If you instead wrote the list in Markdown like this:</p>++<pre><code>1.  Bird+1.  McHale+1.  Parish+</code></pre>++<p>or even:</p>++<pre><code>3. Bird+1. McHale+8. Parish+</code></pre>++<p>you'd get the exact same HTML output. The point is, if you want to,+you can use ordinal numbers in your ordered Markdown lists, so that+the numbers in your source match the numbers in your published HTML.+But if you want to be lazy, you don't have to.</p>++<p>If you do use lazy list numbering, however, you should still start the+list with the number 1. At some point in the future, Markdown may support+starting ordered lists at an arbitrary number.</p>++<p>List markers typically start at the left margin, but may be indented by+up to three spaces. List markers must be followed by one or more spaces+or a tab.</p>++<p>To make lists look nice, you can wrap items with hanging indents:</p>++<pre><code>*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.+    Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,+    viverra nec, fringilla in, laoreet vitae, risus.+*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.+    Suspendisse id sem consectetuer libero luctus adipiscing.+</code></pre>++<p>But if you want to be lazy, you don't have to:</p>++<pre><code>*   Lorem ipsum dolor sit amet, consectetuer adipiscing elit.+Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,+viverra nec, fringilla in, laoreet vitae, risus.+*   Donec sit amet nisl. Aliquam semper ipsum sit amet velit.+Suspendisse id sem consectetuer libero luctus adipiscing.+</code></pre>++<p>If list items are separated by blank lines, Markdown will wrap the+items in <code>&lt;p&gt;</code> tags in the HTML output. For example, this input:</p>++<pre><code>*   Bird+*   Magic+</code></pre>++<p>will turn into:</p>++<pre><code>&lt;ul&gt;+&lt;li&gt;Bird&lt;/li&gt;+&lt;li&gt;Magic&lt;/li&gt;+&lt;/ul&gt;+</code></pre>++<p>But this:</p>++<pre><code>*   Bird++*   Magic+</code></pre>++<p>will turn into:</p>++<pre><code>&lt;ul&gt;+&lt;li&gt;&lt;p&gt;Bird&lt;/p&gt;&lt;/li&gt;+&lt;li&gt;&lt;p&gt;Magic&lt;/p&gt;&lt;/li&gt;+&lt;/ul&gt;+</code></pre>++<p>List items may consist of multiple paragraphs. Each subsequent+paragraph in a list item must be intended by either 4 spaces+or one tab:</p>++<pre><code>1.  This is a list item with two paragraphs. Lorem ipsum dolor+    sit amet, consectetuer adipiscing elit. Aliquam hendrerit+    mi posuere lectus.++    Vestibulum enim wisi, viverra nec, fringilla in, laoreet+    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum+    sit amet velit.++2.  Suspendisse id sem consectetuer libero luctus adipiscing.+</code></pre>++<p>It looks nice if you indent every line of the subsequent+paragraphs, but here again, Markdown will allow you to be+lazy:</p>++<pre><code>*   This is a list item with two paragraphs.++    This is the second paragraph in the list item. You're+only required to indent the first line. Lorem ipsum dolor+sit amet, consectetuer adipiscing elit.++*   Another item in the same list.+</code></pre>++<p>To put a blockquote within a list item, the blockquote's <code>&gt;</code>+delimiters need to be indented:</p>++<pre><code>*   A list item with a blockquote:++    &gt; This is a blockquote+    &gt; inside a list item.+</code></pre>++<p>To put a code block within a list item, the code block needs+to be indented <em>twice</em> -- 8 spaces or two tabs:</p>++<pre><code>*   A list item with a code block:++        &lt;code goes here&gt;+</code></pre>++<p>It's worth noting that it's possible to trigger an ordered list by+accident, by writing something like this:</p>++<pre><code>1986. What a great season.+</code></pre>++<p>In other words, a <em>number-period-space</em> sequence at the beginning of a+line. To avoid this, you can backslash-escape the period:</p>++<pre><code>1986\. What a great season.+</code></pre>++<h3 id="precode">Code Blocks</h3>++<p>Pre-formatted code blocks are used for writing about programming or+markup source code. Rather than forming normal paragraphs, the lines+of a code block are interpreted literally. Markdown wraps a code block+in both <code>&lt;pre&gt;</code> and <code>&lt;code&gt;</code> tags.</p>++<p>To produce a code block in Markdown, simply indent every line of the+block by at least 4 spaces or 1 tab. For example, given this input:</p>++<pre><code>This is a normal paragraph:++    This is a code block.+</code></pre>++<p>Markdown will generate:</p>++<pre><code>&lt;p&gt;This is a normal paragraph:&lt;/p&gt;++&lt;pre&gt;&lt;code&gt;This is a code block.+&lt;/code&gt;&lt;/pre&gt;+</code></pre>++<p>One level of indentation -- 4 spaces or 1 tab -- is removed from each+line of the code block. For example, this:</p>++<pre><code>Here is an example of AppleScript:++    tell application "Foo"+        beep+    end tell+</code></pre>++<p>will turn into:</p>++<pre><code>&lt;p&gt;Here is an example of AppleScript:&lt;/p&gt;++&lt;pre&gt;&lt;code&gt;tell application "Foo"+    beep+end tell+&lt;/code&gt;&lt;/pre&gt;+</code></pre>++<p>A code block continues until it reaches a line that is not indented+(or the end of the article).</p>++<p>Within a code block, ampersands (<code>&amp;</code>) and angle brackets (<code>&lt;</code> and <code>&gt;</code>)+are automatically converted into HTML entities. This makes it very+easy to include example HTML source code using Markdown -- just paste+it and indent it, and Markdown will handle the hassle of encoding the+ampersands and angle brackets. For example, this:</p>++<pre><code>    &lt;div class="footer"&gt;+        &amp;copy; 2004 Foo Corporation+    &lt;/div&gt;+</code></pre>++<p>will turn into:</p>++<pre><code>&lt;pre&gt;&lt;code&gt;&amp;lt;div class="footer"&amp;gt;+    &amp;amp;copy; 2004 Foo Corporation+&amp;lt;/div&amp;gt;+&lt;/code&gt;&lt;/pre&gt;+</code></pre>++<p>Regular Markdown syntax is not processed within code blocks. E.g.,+asterisks are just literal asterisks within a code block. This means+it's also easy to use Markdown to write about Markdown's own syntax.</p>++<h3 id="hr">Horizontal Rules</h3>++<p>You can produce a horizontal rule tag (<code>&lt;hr /&gt;</code>) by placing three or+more hyphens, asterisks, or underscores on a line by themselves. If you+wish, you may use spaces between the hyphens or asterisks. Each of the+following lines will produce a horizontal rule:</p>++<pre><code>* * *++***++*****++- - -++---------------------------------------++_ _ _+</code></pre>++<hr />++<h2 id="span">Span Elements</h2>++<h3 id="link">Links</h3>++<p>Markdown supports two style of links: <em>inline</em> and <em>reference</em>.</p>++<p>In both styles, the link text is delimited by [square brackets].</p>++<p>To create an inline link, use a set of regular parentheses immediately+after the link text's closing square bracket. Inside the parentheses,+put the URL where you want the link to point, along with an <em>optional</em>+title for the link, surrounded in quotes. For example:</p>++<pre><code>This is [an example](http://example.com/ "Title") inline link.++[This link](http://example.net/) has no title attribute.+</code></pre>++<p>Will produce:</p>++<pre><code>&lt;p&gt;This is &lt;a href="http://example.com/" title="Title"&gt;+an example&lt;/a&gt; inline link.&lt;/p&gt;++&lt;p&gt;&lt;a href="http://example.net/"&gt;This link&lt;/a&gt; has no+title attribute.&lt;/p&gt;+</code></pre>++<p>If you're referring to a local resource on the same server, you can+use relative paths:</p>++<pre><code>See my [About](/about/) page for details.+</code></pre>++<p>Reference-style links use a second set of square brackets, inside+which you place a label of your choosing to identify the link:</p>++<pre><code>This is [an example][id] reference-style link.+</code></pre>++<p>You can optionally use a space to separate the sets of brackets:</p>++<pre><code>This is [an example] [id] reference-style link.+</code></pre>++<p>Then, anywhere in the document, you define your link label like this,+on a line by itself:</p>++<pre><code>[id]: http://example.com/  "Optional Title Here"+</code></pre>++<p>That is:</p>++<ul>+<li>Square brackets containing the link identifier (optionally+indented from the left margin using up to three spaces);</li>+<li>followed by a colon;</li>+<li>followed by one or more spaces (or tabs);</li>+<li>followed by the URL for the link;</li>+<li>optionally followed by a title attribute for the link, enclosed+in double or single quotes.</li>+</ul>++<p>The link URL may, optionally, be surrounded by angle brackets:</p>++<pre><code>[id]: &lt;http://example.com/&gt;  "Optional Title Here"+</code></pre>++<p>You can put the title attribute on the next line and use extra spaces+or tabs for padding, which tends to look better with longer URLs:</p>++<pre><code>[id]: http://example.com/longish/path/to/resource/here+    "Optional Title Here"+</code></pre>++<p>Link definitions are only used for creating links during Markdown+processing, and are stripped from your document in the HTML output.</p>++<p>Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are <em>not</em> case sensitive. E.g. these two links:</p>++<pre><code>[link text][a]+[link text][A]+</code></pre>++<p>are equivalent.</p>++<p>The <em>implicit link name</em> shortcut allows you to omit the name of the+link, in which case the link text itself is used as the name.+Just use an empty set of square brackets -- e.g., to link the word+"Google" to the google.com web site, you could simply write:</p>++<pre><code>[Google][]+</code></pre>++<p>And then define the link:</p>++<pre><code>[Google]: http://google.com/+</code></pre>++<p>Because link names may contain spaces, this shortcut even works for+multiple words in the link text:</p>++<pre><code>Visit [Daring Fireball][] for more information.+</code></pre>++<p>And then define the link:</p>++<pre><code>[Daring Fireball]: http://daringfireball.net/+</code></pre>++<p>Link definitions can be placed anywhere in your Markdown document. I+tend to put them immediately after each paragraph in which they're+used, but if you want, you can put them all at the end of your+document, sort of like footnotes.</p>++<p>Here's an example of reference links in action:</p>++<pre><code>I get 10 times more traffic from [Google] [1] than from+[Yahoo] [2] or [MSN] [3].++  [1]: http://google.com/        "Google"+  [2]: http://search.yahoo.com/  "Yahoo Search"+  [3]: http://search.msn.com/    "MSN Search"+</code></pre>++<p>Using the implicit link name shortcut, you could instead write:</p>++<pre><code>I get 10 times more traffic from [Google][] than from+[Yahoo][] or [MSN][].++  [google]: http://google.com/        "Google"+  [yahoo]:  http://search.yahoo.com/  "Yahoo Search"+  [msn]:    http://search.msn.com/    "MSN Search"+</code></pre>++<p>Both of the above examples will produce the following HTML output:</p>++<pre><code>&lt;p&gt;I get 10 times more traffic from &lt;a href="http://google.com/"+title="Google"&gt;Google&lt;/a&gt; than from+&lt;a href="http://search.yahoo.com/" title="Yahoo Search"&gt;Yahoo&lt;/a&gt;+or &lt;a href="http://search.msn.com/" title="MSN Search"&gt;MSN&lt;/a&gt;.&lt;/p&gt;+</code></pre>++<p>For comparison, here is the same paragraph written using+Markdown's inline link style:</p>++<pre><code>I get 10 times more traffic from [Google](http://google.com/ "Google")+than from [Yahoo](http://search.yahoo.com/ "Yahoo Search") or+[MSN](http://search.msn.com/ "MSN Search").+</code></pre>++<p>The point of reference-style links is not that they're easier to+write. The point is that with reference-style links, your document+source is vastly more readable. Compare the above examples: using+reference-style links, the paragraph itself is only 81 characters+long; with inline-style links, it's 176 characters; and as raw HTML,+it's 234 characters. In the raw HTML, there's more markup than there+is text.</p>++<p>With Markdown's reference-style links, a source document much more+closely resembles the final output, as rendered in a browser. By+allowing you to move the markup-related metadata out of the paragraph,+you can add links without interrupting the narrative flow of your+prose.</p>++<h3 id="em">Emphasis</h3>++<p>Markdown treats asterisks (<code>*</code>) and underscores (<code>_</code>) as indicators of+emphasis. Text wrapped with one <code>*</code> or <code>_</code> will be wrapped with an+HTML <code>&lt;em&gt;</code> tag; double <code>*</code>'s or <code>_</code>'s will be wrapped with an HTML+<code>&lt;strong&gt;</code> tag. E.g., this input:</p>++<pre><code>*single asterisks*++_single underscores_++**double asterisks**++__double underscores__+</code></pre>++<p>will produce:</p>++<pre><code>&lt;em&gt;single asterisks&lt;/em&gt;++&lt;em&gt;single underscores&lt;/em&gt;++&lt;strong&gt;double asterisks&lt;/strong&gt;++&lt;strong&gt;double underscores&lt;/strong&gt;+</code></pre>++<p>You can use whichever style you prefer; the lone restriction is that+the same character must be used to open and close an emphasis span.</p>++<p>Emphasis can be used in the middle of a word:</p>++<pre><code>un*fucking*believable+</code></pre>++<p>But if you surround an <code>*</code> or <code>_</code> with spaces, it'll be treated as a+literal asterisk or underscore.</p>++<p>To produce a literal asterisk or underscore at a position where it+would otherwise be used as an emphasis delimiter, you can backslash+escape it:</p>++<pre><code>\*this text is surrounded by literal asterisks\*+</code></pre>++<h3 id="code">Code</h3>++<p>To indicate a span of code, wrap it with backtick quotes (<code>`</code>).+Unlike a pre-formatted code block, a code span indicates code within a+normal paragraph. For example:</p>++<pre><code>Use the `printf()` function.+</code></pre>++<p>will produce:</p>++<pre><code>&lt;p&gt;Use the &lt;code&gt;printf()&lt;/code&gt; function.&lt;/p&gt;+</code></pre>++<p>To include a literal backtick character within a code span, you can use+multiple backticks as the opening and closing delimiters:</p>++<pre><code>``There is a literal backtick (`) here.``+</code></pre>++<p>which will produce this:</p>++<pre><code>&lt;p&gt;&lt;code&gt;There is a literal backtick (`) here.&lt;/code&gt;&lt;/p&gt;+</code></pre>++<p>The backtick delimiters surrounding a code span may include spaces --+one after the opening, one before the closing. This allows you to place+literal backtick characters at the beginning or end of a code span:</p>++<pre><code>A single backtick in a code span: `` ` ``++A backtick-delimited string in a code span: `` `foo` ``+</code></pre>++<p>will produce:</p>++<pre><code>&lt;p&gt;A single backtick in a code span: &lt;code&gt;`&lt;/code&gt;&lt;/p&gt;++&lt;p&gt;A backtick-delimited string in a code span: &lt;code&gt;`foo`&lt;/code&gt;&lt;/p&gt;+</code></pre>++<p>With a code span, ampersands and angle brackets are encoded as HTML+entities automatically, which makes it easy to include example HTML+tags. Markdown will turn this:</p>++<pre><code>Please don't use any `&lt;blink&gt;` tags.+</code></pre>++<p>into:</p>++<pre><code>&lt;p&gt;Please don't use any &lt;code&gt;&amp;lt;blink&amp;gt;&lt;/code&gt; tags.&lt;/p&gt;+</code></pre>++<p>You can write this:</p>++<pre><code>`&amp;#8212;` is the decimal-encoded equivalent of `&amp;mdash;`.+</code></pre>++<p>to produce:</p>++<pre><code>&lt;p&gt;&lt;code&gt;&amp;amp;#8212;&lt;/code&gt; is the decimal-encoded+equivalent of &lt;code&gt;&amp;amp;mdash;&lt;/code&gt;.&lt;/p&gt;+</code></pre>++<h3 id="img">Images</h3>++<p>Admittedly, it's fairly difficult to devise a "natural" syntax for+placing images into a plain text document format.</p>++<p>Markdown uses an image syntax that is intended to resemble the syntax+for links, allowing for two styles: <em>inline</em> and <em>reference</em>.</p>++<p>Inline image syntax looks like this:</p>++<pre><code>![Alt text](/path/to/img.jpg)++![Alt text](/path/to/img.jpg "Optional title")+</code></pre>++<p>That is:</p>++<ul>+<li>An exclamation mark: <code>!</code>;</li>+<li>followed by a set of square brackets, containing the <code>alt</code>+attribute text for the image;</li>+<li>followed by a set of parentheses, containing the URL or path to+the image, and an optional <code>title</code> attribute enclosed in double+or single quotes.</li>+</ul>++<p>Reference-style image syntax looks like this:</p>++<pre><code>![Alt text][id]+</code></pre>++<p>Where "id" is the name of a defined image reference. Image references+are defined using syntax identical to link references:</p>++<pre><code>[id]: url/to/image  "Optional title attribute"+</code></pre>++<p>As of this writing, Markdown has no syntax for specifying the+dimensions of an image; if this is important to you, you can simply+use regular HTML <code>&lt;img&gt;</code> tags.</p>++<hr />++<h2 id="misc">Miscellaneous</h2>++<h3 id="autolink">Automatic Links</h3>++<p>Markdown supports a shortcut style for creating "automatic" links for URLs and email addresses: simply surround the URL or email address with angle brackets. What this means is that if you want to show the actual text of a URL or email address, and also have it be a clickable link, you can do this:</p>++<pre><code>&lt;http://example.com/&gt;+</code></pre>++<p>Markdown will turn this into:</p>++<pre><code>&lt;a href="http://example.com/"&gt;http://example.com/&lt;/a&gt;+</code></pre>++<p>Automatic links for email addresses work similarly, except that+Markdown will also perform a bit of randomized decimal and hex+entity-encoding to help obscure your address from address-harvesting+spambots. For example, Markdown will turn this:</p>++<pre><code>&lt;address@example.com&gt;+</code></pre>++<p>into something like this:</p>++<pre><code>&lt;a href="&amp;#x6D;&amp;#x61;i&amp;#x6C;&amp;#x74;&amp;#x6F;:&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;+&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;+&amp;#109;"&gt;&amp;#x61;&amp;#x64;&amp;#x64;&amp;#x72;&amp;#x65;&amp;#115;&amp;#115;&amp;#64;&amp;#101;&amp;#120;&amp;#x61;+&amp;#109;&amp;#x70;&amp;#x6C;e&amp;#x2E;&amp;#99;&amp;#111;&amp;#109;&lt;/a&gt;+</code></pre>++<p>which will render in a browser as a clickable link to "address@example.com".</p>++<p>(This sort of entity-encoding trick will indeed fool many, if not+most, address-harvesting bots, but it definitely won't fool all of+them. It's better than nothing, but an address published in this way+will probably eventually start receiving spam.)</p>++<h3 id="backslash">Backslash Escapes</h3>++<p>Markdown allows you to use backslash escapes to generate literal+characters which would otherwise have special meaning in Markdown's+formatting syntax. For example, if you wanted to surround a word with+literal asterisks (instead of an HTML <code>&lt;em&gt;</code> tag), you can backslashes+before the asterisks, like this:</p>++<pre><code>\*literal asterisks\*+</code></pre>++<p>Markdown provides backslash escapes for the following characters:</p>++<pre><code>\   backslash+`   backtick+*   asterisk+_   underscore+{}  curly braces+[]  square brackets+()  parentheses+#   hash mark++   plus sign+-   minus sign (hyphen)+.   dot+!   exclamation mark+</code></pre>
+ test/Tests/Nested blockquotes.html view
@@ -0,0 +1,9 @@+<blockquote>+<p>foo</p>++<blockquote>+<p>bar</p>+</blockquote>++<p>foo</p>+</blockquote>
+ test/Tests/Nested blockquotes.text view
@@ -0,0 +1,5 @@+> foo+>+> > bar+>+> foo
+ test/Tests/Ordered and unordered lists.html view
@@ -0,0 +1,148 @@+<h2>Unordered</h2>++<p>Asterisks tight:</p>++<ul>+<li>asterisk 1</li>+<li>asterisk 2</li>+<li>asterisk 3</li>+</ul>++<p>Asterisks loose:</p>++<ul>+<li><p>asterisk 1</p></li>+<li><p>asterisk 2</p></li>+<li><p>asterisk 3</p></li>+</ul>++<hr>++<p>Pluses tight:</p>++<ul>+<li>Plus 1</li>+<li>Plus 2</li>+<li>Plus 3</li>+</ul>++<p>Pluses loose:</p>++<ul>+<li><p>Plus 1</p></li>+<li><p>Plus 2</p></li>+<li><p>Plus 3</p></li>+</ul>++<hr>++<p>Minuses tight:</p>++<ul>+<li>Minus 1</li>+<li>Minus 2</li>+<li>Minus 3</li>+</ul>++<p>Minuses loose:</p>++<ul>+<li><p>Minus 1</p></li>+<li><p>Minus 2</p></li>+<li><p>Minus 3</p></li>+</ul>++<h2>Ordered</h2>++<p>Tight:</p>++<ol>+<li>First</li>+<li>Second</li>+<li>Third</li>+</ol>++<p>and:</p>++<ol>+<li>One</li>+<li>Two</li>+<li>Three</li>+</ol>++<p>Loose using tabs:</p>++<ol>+<li><p>First</p></li>+<li><p>Second</p></li>+<li><p>Third</p></li>+</ol>++<p>and using spaces:</p>++<ol>+<li><p>One</p></li>+<li><p>Two</p></li>+<li><p>Three</p></li>+</ol>++<p>Multiple paragraphs:</p>++<ol>+<li><p>Item 1, graf one.</p>++<p>Item 2. graf two. The quick brown fox jumped over the lazy dog&#39;s+back.</p></li>+<li><p>Item 2.</p></li>+<li><p>Item 3.</p></li>+</ol>++<h2>Nested</h2>++<ul>+<li><p>Tab</p>+<ul>+<li><p>Tab</p>+<ul>+<li>Tab</li>+</ul></li>+</ul></li>+</ul>++<p>Here&#39;s another:</p>++<ol>+<li>First</li>+<li>Second:+<ul>+<li>Fee</li>+<li>Fie</li>+<li>Foe</li>+</ul></li>+<li>Third</li>+</ol>++<p>Same thing but with paragraphs:</p>++<ol>+<li><p>First</p></li>+<li><p>Second:</p>++<ul>+<li>Fee</li>+<li>Fie</li>+<li>Foe</li>+</ul></li>+<li><p>Third</p></li>+</ol>+++<p>This was an error in Markdown 1.0.1:</p>++<ul>+<li><p>this</p>++<ul><li>sub</li></ul>++<p>that</p></li>+</ul>
+ test/Tests/Strong and em together.html view
@@ -0,0 +1,7 @@+<p><b><i>This is strong and em.</i></b></p>++<p>So is <b><i>this</i></b> word.</p>++<p><b><i>This is strong and em.</i></b></p>++<p>So is <b><i>this</i></b> word.</p>
+ test/Tests/Strong and em together.text view
@@ -0,0 +1,7 @@+***This is strong and em.***++So is ***this*** word.++___This is strong and em.___++So is ___this___ word.
+ test/Tests/Tabs.html view
@@ -0,0 +1,25 @@+<ul>+<li><p>this is a list item+indented with tabs</p></li>+<li><p>this is a list item+indented with spaces</p></li>+</ul>++<p>Code:</p>++<pre><code>this code block is indented by one tab+</code></pre>++<p>And:</p>++<pre><code>    this code block is indented by two tabs+</code></pre>++<p>And:</p>++<pre><code>+   this is an example list item+    indented with tabs+++   this is an example list item+    indented with spaces+</code></pre>
+ test/Tests/Tabs.text view
@@ -0,0 +1,21 @@++	this is a list item+	indented with tabs+++   this is a list item+    indented with spaces++Code:++	this code block is indented by one tab++And:++		this code block is indented by two tabs++And:++	+	this is an example list item+		indented with tabs+	+	+   this is an example list item+	    indented with spaces
+ test/Tests/Tidyness.html view
@@ -0,0 +1,8 @@+<blockquote>+<p>A list within a blockquote:</p>+<ul>+<li>asterisk 1</li>+<li>asterisk 2</li>+<li>asterisk 3</li>+</ul>+</blockquote>
+ test/Tests/Tidyness.text view
@@ -0,0 +1,5 @@+> A list within a blockquote:+> +> *	asterisk 1+> *	asterisk 2+> *	asterisk 3
+ test/examples/closing-tags.html view
@@ -0,0 +1,1 @@+<ul><li><p>foo</p></li></ul>
+ test/examples/closing-tags.md view
@@ -0,0 +1,1 @@+* <p>foo</p>
+ test/examples/entities.html view
@@ -0,0 +1,1 @@+<p>1 &lt; 2 &amp; 2 &gt; 1, also 1 &lt; 2 &amp; 2 &gt; 1   ý &amp;#xP;</p>
+ test/examples/entities.md view
@@ -0,0 +1,1 @@+1 < 2 & 2 > 1, also 1 &lt; 2 &amp; 2 &gt; 1 &#160; &#xfd; &#xP;
+ test/examples/fence-whitespace.html view
@@ -0,0 +1,1 @@+<p>foo</p><pre><code>bar</code></pre>
+ test/examples/fence-whitespace.md view
@@ -0,0 +1,4 @@+foo+```+bar+```
+ test/examples/lazy.html view
@@ -0,0 +1,3 @@+<blockquote><p>this is+lazy</p></blockquote><ol><li>This is+a list</li><li>Another item</li></ol>
+ test/examples/lazy.md view
@@ -0,0 +1,6 @@+> this is+lazy++1.  This is+a list+2.  Another item
+ test/examples/list-blocks.html view
@@ -0,0 +1,1 @@+<ul><li><p>This is a paragraph.</p><p>Another paragraph.</p></li><li><p>Non-paragraph.</p></li><li><p>Item.</p><ul><li>Sublist item.</li><li><ol><li>Item 1</li><li>Item 2</li></ol></li></ul></li></ul>
+ test/examples/list-blocks.md view
@@ -0,0 +1,12 @@+*   This is a paragraph.++    Another paragraph.++* Non-paragraph.++*   Item.++    * Sublist item.+    * +        1. Item 1+        2. Item 2
+ test/examples/lists-code.html view
@@ -0,0 +1,2 @@+<ol><li>hello+world</li><li><p>hello</p><pre><code class="haskell">data Foo</code></pre></li></ol>
+ test/examples/lists-code.md view
@@ -0,0 +1,7 @@+1. hello+   world+2.    hello++      ```haskell+      data Foo+      ```
+ test/examples/multiline-paragraphs.html view
@@ -0,0 +1,5 @@+<p>This is a multiline+paragraph.</p><ul><li><p>Multiline paragraph+in a list.</p></li><li><p>The purpose of classy prelude is <i>not</i> to encourage writing polymorphic+code based on the typeclasses provided. Though it's certainly possible to+write code such as:</p></li></ul>
+ test/examples/multiline-paragraphs.md view
@@ -0,0 +1,9 @@+This is a multiline+paragraph.++*    Multiline paragraph+     in a list.++*   The purpose of classy prelude is *not* to encourage writing polymorphic+    code based on the typeclasses provided. Though it's certainly possible to+    write code such as:
+ test/examples/sublists.html view
@@ -0,0 +1,1 @@+<ol><li>No encounters</li><li>Encounters<ol><li>First kind</li><li>Second kind</li></ol></li></ol>
+ test/examples/sublists.md view
@@ -0,0 +1,4 @@+1.  No encounters+2.  Encounters+    1. First kind+    2. Second kind
+ test/examples/tilde-code.html view
@@ -0,0 +1,4 @@+<pre><code class="haskell">foo+bar++baz</code></pre>
+ test/examples/tilde-code.md view
@@ -0,0 +1,6 @@+~~~haskell+foo+bar++baz+~~~
+ test/main.hs view
@@ -0,0 +1,226 @@+{-# LANGUAGE OverloadedStrings #-}+import Test.Hspec+import Text.Markdown+import Data.Text.Lazy (Text, unpack, snoc, fromStrict)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import Text.Blaze.Html.Renderer.Text (renderHtml)+import Control.Monad (forM_)+import qualified Data.Set as Set+import qualified Data.Map as Map++import qualified Filesystem.Path.CurrentOS as F+import qualified Filesystem as F++import Block+import Inline++check :: Text -> Text -> Expectation+check html md = renderHtml (markdown def md) `shouldBe` html++checkSet :: MarkdownSettings -> Text -> Text -> Expectation+checkSet set html md = renderHtml (markdown set md) `shouldBe` html++check' :: Text -> Text -> Expectation+check' html md = renderHtml (markdown def { msXssProtect = False } md) `shouldBe` html++checkNoNL :: Text -> Text -> Expectation+checkNoNL html md =+    f (renderHtml $ markdown def { msXssProtect = False } md) `shouldBe` f html+  where+    f = TL.filter (/= '\n')++-- FIXME add quickcheck: all input is valid++main :: IO ()+main = do+  examples <- getExamples+  gruber <- getGruber+  hspec $ do+    describe "block" blockSpecs+    describe "inline" inlineSpecs+    describe "paragraphs" $ do+        it "simple"+            $ check "<p>Hello World!</p>" "Hello World!"+        it "multiline"+            $ check "<p>Hello\nWorld!</p>" "Hello\nWorld!"+        it "multiple"+            $ check "<p>Hello</p><p>World!</p>" "Hello\n\nWorld!"+    describe "italics" $ do+        it "simple"+            $ check "<p><i>foo</i></p>" "*foo*"+        it "hanging"+            $ check "<p><i>foo</i> *</p>" "*foo* *"+        it "two"+            $ check "<p><i>foo</i> <i>bar</i></p>" "*foo* *bar*"+    describe "italics under" $ do+        it "simple"+            $ check "<p><i>foo</i></p>" "_foo_"+        it "hanging"+            $ check "<p><i>foo</i> _</p>" "_foo_ _"+        it "two"+            $ check "<p><i>foo</i> <i>bar</i></p>" "_foo_ _bar_"+    describe "bold" $ do+        it "simple"+            $ check "<p><b>foo</b></p>" "**foo**"+        it "hanging"+            $ check "<p><b>foo</b> **</p>" "**foo** **"+        it "two"+            $ check "<p><b>foo</b> <b>bar</b></p>" "**foo** **bar**"+    describe "bold under" $ do+        it "simple"+            $ check "<p><b>foo</b></p>" "__foo__"+        it "hanging"+            $ check "<p><b>foo</b> __</p>" "__foo__ __"+        it "two"+            $ check "<p><b>foo</b> <b>bar</b></p>" "__foo__ __bar__"+    describe "html" $ do+        it "simple"+            $ check "<div>Hello</div>" "<div>Hello</div>"+        it "dangerous"+            $ check "<div>Hello</div>" "<div onclick='alert(foo)'>Hello</div>"+        it "dangerous and allowed"+            $ check' "<div onclick='alert(foo)'>Hello</div>" "<div onclick='alert(foo)'>Hello</div>"++        let ml = "<div>foo\nbar\nbaz</div>"+        it "multiline" $ check ml ml++        let close = "<div>foo\nbar\nbaz"+        it "autoclose" $ check ml close++        let close2 = "<div>foo\nbar\nbaz\n\nparagraph"+        it "autoclose 2"+            $ check "<div>foo\nbar\nbaz<p>paragraph</p></div>" close2+    describe "inline code" $ do+        it "simple"+            $ check "<p>foo <code>bar</code> baz</p>" "foo `bar` baz"+    describe "code block" $ do+        it "simple"+            $ check+                "<pre><code>foo\n bar\nbaz</code></pre>"+                "    foo\n     bar\n    baz"+    describe "escaping" $ do+        it "everything"+            $ check+                "<p>*foo_bar<i>baz</i>\\`bin</p>"+                "\\*foo\\_bar_baz_\\\\\\`bin"+    describe "bullets" $ do+        it "simple"+            $ check+                "<ul><li>foo</li><li>bar</li><li>baz</li></ul>"+                "* foo\n* bar\n* baz\n"+    describe "numbers" $ do+        it "simple"+            $ check+                "<ol><li>foo</li><li>bar</li><li>baz</li></ol>"+                "5. foo\n2. bar\n1. baz\n"+    describe "headings" $ do+        it "hashes"+            $ check+                "<h1>foo</h1><h2>bar</h2><h3>baz</h3>"+                "# foo\n\n##     bar\n\n###baz"+        it "trailing hashes"+            $ check+                "<h1>foo</h1>"+                "# foo    ####"+        it "underline"+            $ check+                "<h1>foo</h1><h2>bar</h2>"+                "foo\n=============\n\nbar\n----------------\n"+    describe "blockquotes" $ do+        it "simple"+            $ check+                "<blockquote><p>foo</p><pre><code>bar</code></pre></blockquote>"+                "> foo\n>\n>     bar"+    describe "links" $ do+        it "simple" $ check "<p><a href=\"foo\">bar</a></p>" "[bar](foo)"+        it "title" $ check+            "<p><a href=\"foo\" title=\"baz\">bar</a></p>"+            "[bar](foo \"baz\")"+        it "escaped href" $ check+            "<p><a href=\"foo)\" title=\"baz\">bar</a></p>"+            "[bar](foo\\) \"baz\")"+        it "escaped title" $ check+            "<p><a href=\"foo)\" title=\"baz&quot;\">bar</a></p>"+            "[bar](foo\\) \"baz\\\"\")"+        it "inside a paragraph" $ check+            "<p>Hello <a href=\"foo\">bar</a> World</p>"+            "Hello [bar](foo) World"+        it "not a link" $ check+            "<p>Not a [ link</p>"+            "Not a [ link"++    {-+    describe "github links" $ do+        it "simple" $ check "<p><a href=\"foo\">bar</a></p>" "[[bar|foo]]"+        it "no link text" $ check "<p><a href=\"foo\">foo</a></p>" "[[foo]]"+        it "escaping" $ check "<p><a href=\"foo-baz-bin\">bar</a></p>" "[[bar|foo/baz bin]]"+        it "inside a list" $ check "<ul><li><a href=\"foo\">foo</a></li></ul>" "* [[foo]]"+    -}++    describe "images" $ do+        it "simple" $ check +            "<p><img src=\"http://link.to/image.jpg\" alt=\"foo\"></p>"+            "![foo](http://link.to/image.jpg)"+        it "title" $ check+            "<p><img src=\"http://link.to/image.jpg\" alt=\"foo\" title=\"bar\"></p>"+            "![foo](http://link.to/image.jpg \"bar\")"+        it "inside a paragraph" $ check+            "<p>Hello <img src=\"http://link.to/image.jpg\" alt=\"foo\"> World</p>"+            "Hello ![foo](http://link.to/image.jpg) World"+        it "not an image" $ check+            "<p>Not an ![ image</p>"+            "Not an ![ image"++    describe "rules" $ do+        let options = concatMap (\t -> [t, snoc t '\n'])+                [ "* * *"+                , "***"+                , "*****"+                , "- - -"+                , "---------------------------------------"+                , "----------------------------------"+                ]+        forM_ options $ \o -> it (unpack o) $ check "<hr>" o++    describe "html" $ do+        it "inline" $ check "<p>foo<br>bar</p>" "foo<br>bar"+        it "inline xss" $ check "<p>foo<br>bar</p>" "foo<br onclick='evil'>bar"+        it "block" $ check "<div>hello world</div>" "<div>hello world</div>"+        it "block xss" $ check "alert('evil')" "<script>alert('evil')</script>"+        it "should be escaped" $ check "<p>1 &lt; 2</p>" "1 < 2"+        it "standalone" $ checkSet+            def { msStandaloneHtml = Set.fromList ["<hidden>", "</hidden>"], msXssProtect = False }+            "<hidden><pre><code class=\"haskell\">foo\nbar</code></pre></hidden>"+            "<hidden>\n```haskell\nfoo\nbar\n```\n</hidden>\n"+    describe "fencing" $ do+        it "custom fencing" $ checkSet+            def+                { msFencedHandlers = Map.union+                    (htmlFencedHandler "@@@" (\clazz -> T.concat ["<article class=\"", clazz, "\">"]) (const "</article>"))+                    (msFencedHandlers def)+                }+            "<article class=\"someclass\"><p>foo</p><blockquote><p>bar</p></blockquote></article>"+            "@@@ someclass\nfoo\n\n> bar\n@@@"+    describe "examples" $ sequence_ examples+    describe "John Gruber's test suite" $ sequence_ gruber++getExamples :: IO [Spec]+getExamples = do+    files <- F.listDirectory "test/examples"+    mapM go $ filter (flip F.hasExtension "md") files+  where+    go fp = do+        input <- F.readTextFile fp+        output <- F.readTextFile $ F.replaceExtension fp "html"+        return $ it (F.encodeString $ F.basename fp) $ check (fromStrict $ T.strip output) (fromStrict input)++getGruber :: IO [Spec]+getGruber = do+    files <- F.listDirectory "test/Tests"+    mapM go $ filter (flip F.hasExtension "text") files+  where+    go fp = do+        input <- F.readTextFile fp+        output <- F.readTextFile $ F.replaceExtension fp "html"+        return $ it (F.encodeString $ F.basename fp) $ checkNoNL (fromStrict $ T.strip output) (fromStrict input)