|
1 | 1 | #!/usr/bin/env runhaskell
|
2 | 2 |
|
3 |
| -{-# LANGUAGE ViewPatterns #-} |
4 |
| - |
5 | 3 | {-
|
6 | 4 | The MIT License (MIT)
|
7 | 5 |
|
@@ -67,18 +65,24 @@ example, if the header is incremented by 1, the title is inserted as a level 1 h
|
67 | 65 |
|
68 | 66 | -}
|
69 | 67 |
|
| 68 | +{-# LANGUAGE BangPatterns #-} |
| 69 | +{-# LANGUAGE ViewPatterns #-} |
| 70 | + |
| 71 | + |
70 | 72 | import Control.Monad
|
71 | 73 | import Data.List
|
72 | 74 | import qualified Data.Char as C
|
73 | 75 | import qualified Data.Map as Map
|
74 | 76 | import Control.Error (readMay, fromMaybe)
|
75 | 77 | import System.Directory
|
| 78 | +import System.IO |
76 | 79 |
|
77 | 80 | import Text.Pandoc
|
78 | 81 | import Text.Pandoc.Shared (uniqueIdent, stringify)
|
79 | 82 | import Text.Pandoc.Error
|
80 | 83 | import Text.Pandoc.JSON
|
81 | 84 | import Text.Pandoc.Walk
|
| 85 | +import qualified Text.Pandoc.Builder as B |
82 | 86 |
|
83 | 87 | stripPandoc :: Int -> Either PandocError Pandoc -> [Block]
|
84 | 88 | stripPandoc _ (Left _) = [Null]
|
@@ -110,36 +114,63 @@ modifyHeaderLevelBlockWith _ _ x = x
|
110 | 114 | modifyHeaderLevelWith :: Int -> Pandoc -> Pandoc
|
111 | 115 | modifyHeaderLevelWith n = walk (modifyHeaderLevelBlockWith n mempty)
|
112 | 116 |
|
113 |
| -ioReadMarkdown :: String -> IO(Either PandocError Pandoc) |
114 |
| -ioReadMarkdown content = return $! readMarkdown def content |
| 117 | +fileContentAsString :: String -> IO String |
| 118 | +fileContentAsString file = withFile file ReadMode $ \handle -> do |
| 119 | + hSetEncoding handle utf8 |
| 120 | + hGetContents handle |
115 | 121 |
|
116 |
| -getContent :: Int -> String -> IO [Block] |
117 |
| -getContent changeInHeaderLevel file = do |
118 |
| - c <- readFile file |
119 |
| - p <- ioReadMarkdown c |
120 |
| - return $! stripPandoc changeInHeaderLevel p |
| 122 | +fileContentAsBlocks :: Int -> String -> IO [Block] |
| 123 | +fileContentAsBlocks changeInHeaderLevel file = do |
| 124 | + let contents = fileContentAsString file |
| 125 | + let p = fmap (readMarkdown def) contents |
| 126 | + stripPandoc changeInHeaderLevel <$> p |
121 | 127 |
|
122 |
| -getProcessableFileList :: String -> IO [String] |
| 128 | +getProcessableFileList :: String -> [String] |
123 | 129 | getProcessableFileList list = do
|
124 | 130 | let f = lines list
|
125 |
| - let files = filter (\x -> not $ "#" `isPrefixOf` x) f |
126 |
| - filterM doesFileExist files |
127 |
| - |
128 |
| -processFiles :: Int -> [String] -> IO [Block] |
129 |
| -processFiles changeInHeaderLevel toProcess = |
130 |
| - fmap concat (getContent changeInHeaderLevel `mapM` toProcess) |
| 131 | + filter (\x -> not $ "#" `isPrefixOf` x) f |
| 132 | + |
| 133 | +simpleInclude :: Int -> String -> [String] -> IO [Block] |
| 134 | +simpleInclude changeInHeaderLevel list classes = do |
| 135 | + let toProcess = getProcessableFileList list |
| 136 | + fmap concat (fileContentAsBlocks changeInHeaderLevel `mapM` toProcess) |
| 137 | + |
| 138 | +includeCodeBlock :: Block -> IO [Block] |
| 139 | +includeCodeBlock (CodeBlock (_, classes, _) list) = do |
| 140 | + let filePath = head $ lines list |
| 141 | + let content = fileContentAsString filePath |
| 142 | + let newclasses = filter (\x -> "include" `isPrefixOf` x || "code" `isPrefixOf` x) classes |
| 143 | + let blocks = fmap (B.codeBlockWith ("", newclasses, [])) content |
| 144 | + fmap B.toList blocks |
| 145 | + |
| 146 | +cropContent :: [String] -> (String, String) -> [String] |
| 147 | +cropContent lines (skip, count) = |
| 148 | + if not $ null skip then |
| 149 | + if not $ null count then |
| 150 | + take (read count) (drop (read skip) lines) |
| 151 | + else |
| 152 | + drop (read skip) lines |
| 153 | + else |
| 154 | + lines |
| 155 | + |
| 156 | +includeCropped :: Block -> IO [Block] |
| 157 | +includeCropped (CodeBlock (_, classes, _) list) = do |
| 158 | + let [filePath, skip, count] = lines list |
| 159 | + let content = fileContentAsString filePath |
| 160 | + let croppedContent = unlines <$> ((cropContent . lines <$> content) <*> pure (skip, count)) |
| 161 | + fmap (stripPandoc 0 . readMarkdown def) croppedContent |
131 | 162 |
|
132 | 163 | doInclude :: Block -> IO [Block]
|
133 |
| -doInclude (CodeBlock (_, classes, options) list) |
| 164 | +doInclude cb@(CodeBlock (_, classes, options) list) |
134 | 165 | | "include" `elem` classes = do
|
135 |
| - let toProcess = getProcessableFileList list |
136 |
| - changeInHeaderLevel = fromMaybe 0 $ readMay =<< "header-change" `lookup` options |
137 |
| - processFiles changeInHeaderLevel =<< toProcess |
138 |
| - | "include-indented" `elem` classes = |
| 166 | + let changeInHeaderLevel = fromMaybe 0 $ readMay =<< "header-change" `lookup` options |
| 167 | + simpleInclude changeInHeaderLevel list classes |
| 168 | + | "include-indented" `elem` classes = do |
| 169 | + let newClasses = ("include" :) . delete "include-indented" $ classes |
| 170 | + let newOptions = ("header-change","1") : options |
139 | 171 | doInclude $ CodeBlock ("", newClasses, newOptions) list
|
140 |
| - where |
141 |
| - newClasses = ("include" :) . delete "include-indented" $ classes |
142 |
| - newOptions = ("header-change","1") : options |
| 172 | + | "code" `elem` classes = includeCodeBlock cb |
| 173 | + | "cropped" `elem` classes = includeCropped cb |
143 | 174 | doInclude x = return [x]
|
144 | 175 |
|
145 | 176 | main :: IO ()
|
|
0 commit comments