@@ -161,9 +161,22 @@ codeBlock = codeBlockBc <|> codeBlockPre
161161
162162codeBlockBc :: Parser [Char] ParserState Blocks
163163codeBlockBc = try $ do
164− string "bc. "
165− contents <- manyTill anyLine blanklines
166− return $ B.codeBlock (unlines contents)
164+ string "bc."
165+ extended <- option False (True <$ char '.')
166+ char ' '
167+ let starts = ["p", "table", "bq", "bc", "h1", "h2", "h3",
168+ "h4", "h5", "h6", "pre", "###", "notextile"]
169+ let ender = choice $ map explicitBlockStart starts
170+ contents <- if extended
171+ then do
172+ f <- anyLine
173+ rest <- many (notFollowedBy ender *> anyLine)
174+ return (f:rest)
175+ else manyTill anyLine blanklines
176+ return $ B.codeBlock (trimTrailingNewlines (unlines contents))
177+
178+trimTrailingNewlines :: String -> String
179+trimTrailingNewlines = reverse . dropWhile (=='\n') . reverse
167180
168181-- | Code Blocks in Textile are between <pre> and </pre>
169182codeBlockPre :: Parser [Char] ParserState Blocks
@@ -408,14 +421,21 @@ ignorableRow = try $ do
408421 _ <- anyLine
409422 return ()
410423
424+explicitBlockStart :: String -> Parser [Char] ParserState ()
425+explicitBlockStart name = try $ do
426+ string name
427+ attributes
428+ char '.'
429+ optional whitespace
430+ optional endline
431+
411432-- | Blocks like 'p' and 'table' do not need explicit block tag.
412433-- However, they can be used to set HTML/CSS attributes when needed.
413434maybeExplicitBlock :: String -- ^ block tag name
414435 -> Parser [Char] ParserState Blocks -- ^ implicit block
415436 -> Parser [Char] ParserState Blocks
416437maybeExplicitBlock name blk = try $ do
417− optional $ try $ string name >> attributes >> char '.' >>
418− optional whitespace >> optional endline
438+ optional $ explicitBlockStart name
419439 blk
420440
421441