@@ -35,6 +35,7 @@ import Codec.Compression.GZip as Gzip
35import Control.Applicative ((<|>))
35import Control.Applicative ((<|>))
36import Control.Monad.Except (throwError)
36import Control.Monad.Except (throwError)
37import Control.Monad.Trans (lift)
37import Control.Monad.Trans (lift)
38+import Data.Monoid ((<>))
38import Data.ByteString (ByteString)
39import Data.ByteString (ByteString)
39import Data.ByteString.Base64
40import Data.ByteString.Base64
40import qualified Data.ByteString.Char8 as B
41import qualified Data.ByteString.Char8 as B
@@ -95,9 +96,9 @@ convertTags sourceURL (t@(TagOpen "script" as):TagClose "script":ts) =
95 (("src",dataUri) : [(x,y) | (x,y) <- as, x /= "src"]) :
96 (("src",dataUri) : [(x,y) | (x,y) <- as, x /= "src"]) :
96 TagClose "script" : rest
97 TagClose "script" : rest
97 Right (mime, bs)
98 Right (mime, bs)
98− | (mime == "text/javascript" ||
99+ | ("text/javascript" `isPrefixOf` mime ||
99− mime == "application/javascript" ||
100+ "application/javascript" `isPrefixOf` mime ||
100− mime == "application/x-javascript") &&
101+ "application/x-javascript" `isPrefixOf` mime) &&
101 not ("</script" `B.isInfixOf` bs) ->
102 not ("</script" `B.isInfixOf` bs) ->
103 TagOpen "script" [("type", typeAttr)|not (null typeAttr)]
104 TagOpen "script" [("type", typeAttr)|not (null typeAttr)]
@@ -121,11 +122,12 @@ convertTags sourceURL (t@(TagOpen "link" as):ts) =
121 (("href",dataUri) : [(x,y) | (x,y) <- as, x /= "href"]) :
122 (("href",dataUri) : [(x,y) | (x,y) <- as, x /= "href"]) :
123 Right (mime, bs)
124 Right (mime, bs)
125+ | "text/css" `isPrefixOf` mime
124− | mime == "text/css" && not ("</" `B.isInfixOf` bs) -> do
126+ && not ("</" `B.isInfixOf` bs) -> do
125 rest <- convertTags sourceURL $
127 rest <- convertTags sourceURL $
126 dropWhile (==TagClose "link") ts
128 dropWhile (==TagClose "link") ts
128− TagOpen "style" [("type", "text/css")]
130+ TagOpen "style" [("type", mime)]
129 : TagText (toString bs)
131 : TagText (toString bs)
130 : TagClose "style"
132 : TagClose "style"
@@ -149,7 +151,20 @@ cssURLs sourceURL d orig = do
149parseCSSUrls :: PandocMonad m
151parseCSSUrls :: PandocMonad m
150 => Maybe String -> FilePath -> ParsecT ByteString () m ByteString
152 => Maybe String -> FilePath -> ParsecT ByteString () m ByteString
151parseCSSUrls sourceURL d = B.concat <$> P.many
153parseCSSUrls sourceURL d = B.concat <$> P.many
154+ (pCSSWhite <|> pCSSComment <|> pCSSImport sourceURL d <|>
152− (pCSSWhite <|> pCSSComment <|> pCSSUrl sourceURL d <|> pCSSOther)
155+ pCSSUrl sourceURL d <|> pCSSOther)
157+pCSSImport :: PandocMonad m => Maybe String -> FilePath
158+ -> ParsecT ByteString () m ByteString
159+pCSSImport sourceURL d = P.try $ do
162+ res <- pCSSUrl' sourceURL d
164+ P.optional $ P.char ';' >> P.spaces
166+ Left b -> return $ B.pack "@import " <> b
167+ Right (_, b) -> return b
154-- Note: some whitespace in CSS is significant, so we can't collapse it!
169-- Note: some whitespace in CSS is significant, so we can't collapse it!
155pCSSWhite :: PandocMonad m => ParsecT ByteString () m ByteString
170pCSSWhite :: PandocMonad m => ParsecT ByteString () m ByteString
@@ -170,13 +185,25 @@ pCSSOther = do
170pCSSUrl :: PandocMonad m
185pCSSUrl :: PandocMonad m
171 => Maybe String -> FilePath -> ParsecT ByteString () m ByteString
186 => Maybe String -> FilePath -> ParsecT ByteString () m ByteString
172pCSSUrl sourceURL d = P.try $ do
187pCSSUrl sourceURL d = P.try $ do
188+ res <- pCSSUrl' sourceURL d
192+ let enc = makeDataURI (mt, b)
193+ return (B.pack $ "url(" ++ enc ++ ")")
195+pCSSUrl' :: PandocMonad m
196+ => Maybe String -> FilePath
197+ -> ParsecT ByteString () m (Either ByteString (MimeType, ByteString))
198+pCSSUrl' sourceURL d = P.try $ do
173 P.string "url("
199 P.string "url("
175 quote <- P.option Nothing (Just <$> P.oneOf "\"'")
201 quote <- P.option Nothing (Just <$> P.oneOf "\"'")
176 url <- P.manyTill P.anyChar (maybe (P.lookAhead (P.char ')')) P.char quote)
202 url <- P.manyTill P.anyChar (maybe (P.lookAhead (P.char ')')) P.char quote)
178 P.char ')'
204 P.char ')'
205+ let fallback = Left $
179− let fallback = B.pack ("url(" ++ maybe "" (:[]) quote ++ trim url ++
206+ B.pack ("url(" ++ maybe "" (:[]) quote ++ trim url ++
180 maybe "" (:[]) quote ++ ")")
207 maybe "" (:[]) quote ++ ")")
181 -- pipes are used in URLs provided by Google Code fonts
208 -- pipes are used in URLs provided by Google Code fonts
182 -- but parseURI doesn't like them, so we escape them:
209 -- but parseURI doesn't like them, so we escape them:
@@ -186,13 +213,14 @@ pCSSUrl sourceURL d = P.try $ do
186 u -> do let url' = if isURI u then u else d </> u
213 u -> do let url' = if isURI u then u else d </> u
187 res <- lift $ getData sourceURL "" url'
214 res <- lift $ getData sourceURL "" url'
188 case res of
215 case res of
189− Left uri -> return (B.pack $ "url(" ++ uri ++ ")")
216+ Left uri -> return $ Left (B.pack $ "url(" ++ uri ++ ")")
190 Right (mt, raw) -> do
217 Right (mt, raw) -> do
191− -- note that the downloaded content may
218+ -- note that the downloaded CSS may
192 -- itself contain url(...).
219 -- itself contain url(...).
220+ b <- if "text/css" `isPrefixOf` mt
193− raw' <- cssURLs sourceURL d raw
221+ then cssURLs sourceURL d raw
194− let enc = makeDataURI (mt, raw')
222+ else return raw
195− return (B.pack $ "url(" ++ enc ++ ")")
223+ return $ Right (mt, b)
197getDataURI :: PandocMonad m => Maybe String -> MimeType -> String -> m String
225getDataURI :: PandocMonad m => Maybe String -> MimeType -> String -> m String
198getDataURI sourceURL mimetype src = do
226getDataURI sourceURL mimetype src = do
@@ -224,7 +252,7 @@ getData sourceURL mimetype src = do
224 uriQuery = "",
252 uriQuery = "",
225 uriFragment = "" }
253 uriFragment = "" }
226 _ -> Nothing
254 _ -> Nothing
227− result <- if mime == "text/css"
255+ result <- if "text/css" `isPrefixOf` mime
228 then cssURLs cssSourceURL (takeDirectory src) raw'
256 then cssURLs cssSourceURL (takeDirectory src) raw'
229 else return raw'
257 else return raw'
230 return $ Right (mime, result)
258 return $ Right (mime, result)