{- oso2pdf --- Better conversion of Oxford Scholarship Online material to PDF Copyright (C) 2015 Sean Whitton This file is part of oso2pdf. oso2pdf is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. oso2pdf is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with oso2pdf. If not, see . -} import Data.List (isPrefixOf, isSuffixOf) import Data.Monoid ((<>)) import Text.Pandoc.JSON data Page = Page Int [Block] instance Monoid Page where mempty = Page 1 [] (Page n xs) `mappend` (Page _ ys) = Page n (xs ++ ys) pagesToBlocks :: [Page] -> [Block] pagesToBlocks [Page _ xs] = xs pagesToBlocks ps@( _ : (Page n _) : _) = RawBlock (Format "tex") ("\\setcounter{page}{" ++ show (n - 1) ++ "}") : (drop 1 $ foldr step [] ps) -- drop first \\pagebreak where step (Page n p) ps = RawBlock (Format "tex") "\\pagebreak" : p ++ ps -- TODO factor out joining Pages together and appending or just -- putting side by side blocksToPages :: [Block] -> [Page] blocksToPages = foldr step [] where step (Para xs) [] = paraToPages xs step x [] = [Page 1 [x]] step (Para xs) ( y@(Page n _) : ys ) = case paraToPages xs of [a, b] -> if n /= 1 then a : b : y : ys else a : (b <> y) : ys [a] -> if n /= 1 then a : y : ys else (a <> y) : ys step x (y:ys) = ((Page 1 [x]) <> y) : ys -- ASSUME: not more than one page break per paragraph! paraToPages :: [Inline] -> [Page] paraToPages para = let (first, n, second) = foldr step ([], 1, []) para in if n == 1 then [Page 1 [Para second]] else if null first then [Page 1 [Para first], Page n [Para second]] else [ Page 1 [Para first] , Page n [Para (RawInline (Format "tex") "\\noindent" : second)]] where step chunk (xs, n, ys) = if n /= 1 then (chunk : xs, n, ys) else case chunk of (Str x) -> if "(p." `isPrefixOf` x && ")" `isSuffixOf` x then let m = read . drop 3 . init $ x in (xs, m, ys) -- TODO: what about [Space, Space] left behind? else (xs, n, chunk : ys) _ -> (xs, n, chunk : ys) main = toJSONFilter process where process (Pandoc meta blocks) = Pandoc meta (pagesToBlocks . blocksToPages $ blocks)