@@ -33,14 +33,12 @@ the HTML using data URIs.
3333module Text.Pandoc.Offline ( offline ) where
3434import Text.HTML.TagSoup
3535import Network.URI (isAbsoluteURI, parseURI, escapeURIString)
36−import Network.Browser
3736import Network.HTTP
3837import Data.ByteString.Base64
39−import System.IO
4038import qualified Data.ByteString.Char8 as B
4139import Data.ByteString (ByteString)
42−import Data.ByteString.UTF8 (toString, fromString)
43−import System.FilePath (takeExtension, dropExtension)
40+import Data.ByteString.UTF8 (toString)
41+import System.FilePath (takeExtension, dropExtension, takeDirectory, (</>))
4442import Data.Char (toLower, isAscii, isAlphaNum)
4543import Codec.Compression.GZip as Gzip
4644import qualified Data.ByteString.Lazy as L
@@ -53,8 +51,8 @@ getItem f =
5351
5452openURL :: String -> IO ByteString
5553openURL u = getResponseBody =<< simpleHTTP (getReq u)
56− where getReq u = case parseURI u of
57− Nothing -> error $ "Could not parse URI: " ++ u
54+ where getReq v = case parseURI v of
55+ Nothing -> error $ "Could not parse URI: " ++ v
5856 Just u' -> mkRequest GET u'
5957
6058mimeTypeFor :: String -> String
@@ -189,6 +187,7 @@ mimeTypeFor s = case lookup s mimetypes of
189187 (".xul", "text/xul")
190188 ]
191189
190+isOk :: Char -> Bool
192191isOk c = isAscii c && isAlphaNum c
193192
194193convertTag :: Tag String -> IO (Tag String)
@@ -215,22 +214,46 @@ convertTag t@(TagOpen "link" as) =
215214 return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"])
216215convertTag t = return t
217216
217+cssImports :: FilePath -> ByteString -> IO ByteString
218+cssImports d orig =
219+ case B.breakSubstring "@import" orig of
220+ (x,y) | B.null y -> return orig
221+ | otherwise -> do
222+ rest <- handleImport d (B.drop 7 y) >>= cssImports d
223+ return $ x `B.append` rest
224+
225+-- @import url("blah");
226+-- @import url(blah);
227+-- @import "blah";
228+handleImport :: FilePath -> ByteString -> IO ByteString
229+handleImport d x = fmap (`B.append` rest) (getItem $ d </> url)
230+ where lparenOrQuote c = c == '(' || c == '"'
231+ rparenOrQuote c = c == ')' || c == '"'
232+ url = toString
233+ $ B.takeWhile (not . rparenOrQuote)
234+ $ B.dropWhile lparenOrQuote
235+ $ B.dropWhile (not . lparenOrQuote) x
236+ rest = B.drop 1 $ B.dropWhile (/= ';') x
237+
218238getRaw :: Tag String -> String -> IO (ByteString, String)
219239getRaw t src = do
220240 let ext = map toLower $ takeExtension src
221− let (ext',decompress) = if ext == ".gz"
222− then (takeExtension $ dropExtension src, B.concat . L.toChunks . Gzip.decompress . L.fromChunks . (:[]))
223− else (ext, id)
241+ let (ext',decomp) = if ext == ".gz"
242+ then (takeExtension $ dropExtension src, B.concat . L.toChunks . Gzip.decompress . L.fromChunks . (:[]))
243+ else (ext, id)
224244 let mime = case fromAttrib "type" t of
225245 [] -> mimeTypeFor ext'
226246 x -> x
227247 raw <- getItem src
228− return (decompress raw, mime)
248+ result <- if mime == "text/css"
249+ then cssImports (takeDirectory src) $ decomp raw
250+ else return $ decomp raw
251+ return (result, mime)
229252
230253offline :: String -> IO String
231254offline inp = do
232255 let tags = parseTags inp
233− out <- mapM convertTag tags
256+ out' <- mapM convertTag tags
234257 return $ renderTagsOptions renderOptions{ optMinimize = (\t -> t == "br"
235− || t == "img" || t == "meta" || t == "link" ) } out
258+ || t == "img" || t == "meta" || t == "link" ) } out'
236259