@@ -1,3 +1,4 @@
1+{-# LANGUAGE ScopedTypeVariables #-}
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
@@ -35,6 +36,8 @@ import Text.Pandoc.Builder (setMeta, fromList)
35import Text.Pandoc.Shared
36import Text.Pandoc.Shared
36import Text.Pandoc.Parsing
37import Text.Pandoc.Parsing
37import Text.Pandoc.Options
38import Text.Pandoc.Options
39+import Text.Pandoc.Error
40+import qualified Text.Pandoc.UTF8 as UTF8
38import Control.Monad ( when, liftM, guard, mzero )
41import Control.Monad ( when, liftM, guard, mzero )
39import Data.List ( findIndex, intercalate,
42import Data.List ( findIndex, intercalate,
40 transpose, sort, deleteFirstsBy, isSuffixOf , nub, union)
43 transpose, sort, deleteFirstsBy, isSuffixOf , nub, union)
@@ -46,9 +49,9 @@ import qualified Text.Pandoc.Builder as B
46import Data.Sequence (viewr, ViewR(..))
49import Data.Sequence (viewr, ViewR(..))
47import Data.Char (toLower, isHexDigit, isSpace)
50import Data.Char (toLower, isHexDigit, isSpace)
48import Data.Monoid ((<>))
51import Data.Monoid ((<>))
49−import Control.Monad.Except (throwError)
52+import Control.Monad.Except (throwError, catchError)
50import Control.Monad.Trans (lift)
53import Control.Monad.Trans (lift)
51−import Text.Pandoc.Class (PandocMonad)
54+import Text.Pandoc.Class (PandocMonad, warning, readFileLazy)
52import qualified Text.Pandoc.Class as P
55import qualified Text.Pandoc.Class as P
54-- | Parse reStructuredText string and return Pandoc document.
57-- | Parse reStructuredText string and return Pandoc document.
@@ -177,6 +180,7 @@ block :: PandocMonad m => RSTParser m Blocks
177block = choice [ codeBlock
180block = choice [ codeBlock
178 , blockQuote
181 , blockQuote
179 , fieldList
182 , fieldList
180 , directive
184 , directive
181 , comment
185 , comment
@@ -397,6 +401,65 @@ blockQuote = do
397 contents <- parseFromString parseBlocks $ raw ++ "\n\n"
401 contents <- parseFromString parseBlocks $ raw ++ "\n\n"
398 return $ B.blockQuote contents
402 return $ B.blockQuote contents
406+The following options are recognized:
409+Only the content starting from this line will be included. (As usual in Python, the first line has index 0 and negative values count from the end.)
411+Only the content up to (but excluding) this line will be included.
412+start-after : text to find in the external data file
413+Only the content after the first occurrence of the specified text will be included.
414+end-before : text to find in the external data file
415+Only the content before the first occurrence of the specified text (but after any after text) will be included.
416+literal : flag (empty)
417+The entire included text is inserted into the document as a single literal block.
418+code : formal language (optional)
419+The argument and the content of the included file are passed to the code directive (useful for program listings). (New in Docutils 0.9)
420+number-lines : [start line number]
421+Precede every code line with a line number. The optional argument is the number of the first line (defaut 1). Works only with code or literal. (New in Docutils 0.9)
422+encoding : name of text encoding
423+The text encoding of the external data file. Defaults to the document's input_encoding.
425+Number of spaces for hard tab expansion. A negative value prevents expansion of hard tabs. Defaults to the tab_width configuration setting.
426+With code or literal the common options :class: and :name: are recognized as well.
428+Combining start/end-line and start-after/end-before is possible. The text markers will be searched in the specified lines (further limiting the included content).
432+include :: PandocMonad m => RSTParser m Blocks
434+ string ".. include::"
436+ f <- trim <$> anyLine
438+ guard $ not (null f)
439+ oldPos <- getPosition
440+ oldInput <- getInput
441+ containers <- stateContainers <$> getState
442+ when (f `elem` containers) $
443+ throwError $ PandocParseError $ "Include file loop at " ++ show oldPos
444+ updateState $ \s -> s{ stateContainers = f : stateContainers s }
445+ res <- lift $ readFileLazy' f
446+ contents <- case res of
449+ lift $ warning $ "Could not read include file " ++ f ++ "."
451+ setPosition $ newPos f 1 1
453+ bs <- optional blanklines >> (mconcat <$> many block)
456+ updateState $ \s -> s{ stateContainers = tail $ stateContainers s }
459+readFileLazy' :: PandocMonad m => FilePath -> m (Either PandocError String)
460+readFileLazy' f = catchError ((Right . UTF8.toStringLazy) <$> readFileLazy f) $
461+ \(e :: PandocError) -> return (Left e)
401-- list blocks
464-- list blocks