@@ -37,7 +37,7 @@ import Network.HTTP
37import Data.ByteString.Base64
37import Data.ByteString.Base64
38import qualified Data.ByteString.Char8 as B
38import qualified Data.ByteString.Char8 as B
39import Data.ByteString (ByteString)
39import Data.ByteString (ByteString)
40−import Data.ByteString.UTF8 (toString)
40+import Data.ByteString.UTF8 (toString, fromString)
41import System.FilePath (takeExtension, dropExtension, takeDirectory, (</>))
41import System.FilePath (takeExtension, dropExtension, takeDirectory, (</>))
42import Data.Char (toLower, isAscii, isAlphaNum)
42import Data.Char (toLower, isAscii, isAlphaNum)
43import Codec.Compression.GZip as Gzip
43import Codec.Compression.GZip as Gzip
@@ -206,67 +206,60 @@ convertTag userdata t@(TagOpen "img" as) =
206 case fromAttrib "src" t of
206 case fromAttrib "src" t of
207 [] -> return t
207 [] -> return t
208 src -> do
208 src -> do
209− (raw, mime) <- getRaw userdata t src
209+ (raw, mime) <- getRaw userdata (fromAttrib "type" t) src
210 let enc = "data:" ++ mime ++ ";base64," ++ toString (encode raw)
210 let enc = "data:" ++ mime ++ ";base64," ++ toString (encode raw)
211 return $ TagOpen "img" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
211 return $ TagOpen "img" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
212convertTag userdata t@(TagOpen "video" as) =
212convertTag userdata t@(TagOpen "video" as) =
213 case fromAttrib "src" t of
213 case fromAttrib "src" t of
214 [] -> return t
214 [] -> return t
215 src -> do
215 src -> do
216− (raw, mime) <- getRaw userdata t src
216+ (raw, mime) <- getRaw userdata (fromAttrib "type" t) src
217 let enc = "data:" ++ mime ++ ";base64," ++ toString (encode raw)
217 let enc = "data:" ++ mime ++ ";base64," ++ toString (encode raw)
218 return $ TagOpen "video" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
218 return $ TagOpen "video" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
219convertTag userdata t@(TagOpen "script" as) =
219convertTag userdata t@(TagOpen "script" as) =
220 case fromAttrib "src" t of
220 case fromAttrib "src" t of
221 [] -> return t
221 [] -> return t
222 src -> do
222 src -> do
223− (raw, mime) <- getRaw userdata t src
223+ (raw, mime) <- getRaw userdata (fromAttrib "type" t) src
224 let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw)
224 let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw)
225 return $ TagOpen "script" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
225 return $ TagOpen "script" (("src",enc) : [(x,y) | (x,y) <- as, x /= "src"])
226convertTag userdata t@(TagOpen "link" as) =
226convertTag userdata t@(TagOpen "link" as) =
227 case fromAttrib "href" t of
227 case fromAttrib "href" t of
228 [] -> return t
228 [] -> return t
229 src -> do
229 src -> do
230− (raw, mime) <- getRaw userdata t src
230+ (raw, mime) <- getRaw userdata (fromAttrib "type" t) src
231 let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw)
231 let enc = "data:" ++ mime ++ "," ++ escapeURIString isOk (toString raw)
232 return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"])
232 return $ TagOpen "link" (("href",enc) : [(x,y) | (x,y) <- as, x /= "href"])
233convertTag _ t = return t
233convertTag _ t = return t
235−cssImports :: Maybe FilePath -> FilePath -> ByteString -> IO ByteString
235+cssURLs :: Maybe FilePath -> FilePath -> ByteString -> IO ByteString
236−cssImports userdata d orig =
236+cssURLs userdata d orig =
237− case B.breakSubstring "@import" orig of
237+ case B.breakSubstring "url(" orig of
238 (x,y) | B.null y -> return orig
238 (x,y) | B.null y -> return orig
239 | otherwise -> do
239 | otherwise -> do
240− rest <- handleImport userdata d (B.drop 7 y)
240+ let (u,v) = B.breakSubstring ")" $ B.drop 4 y
242+ $ case B.take 1 u of
243+ "\"" -> B.takeWhile (/='"') $ B.drop 1 u
241− >>= cssImports userdata d
245+ (raw, mime) <- getRaw userdata "" (d </> url)
246+ rest <- cssURLs userdata d v
247+ let enc = "data:" `B.append` fromString mime `B.append`
248+ ";base64," `B.append` (encode raw)
242− return $ x `B.append` rest
249+ return $ x `B.append` "url(" `B.append` enc `B.append` rest
244−-- @import url("blah");
245−-- @import url(blah);
247−handleImport :: Maybe FilePath -> FilePath -> ByteString -> IO ByteString
248−handleImport userdata d x =
249− fmap (`B.append` rest) (getItem userdata $ d </> url)
250− where lparenOrQuote c = c == '(' || c == '"'
251− rparenOrQuote c = c == ')' || c == '"'
253− $ B.takeWhile (not . rparenOrQuote)
254− $ B.dropWhile lparenOrQuote
255− $ B.dropWhile (not . lparenOrQuote) x
256− rest = B.drop 1 $ B.dropWhile (/= ';') x
258−getRaw :: Maybe FilePath -> Tag String -> String -> IO (ByteString, String)
251+getRaw :: Maybe FilePath -> String -> String -> IO (ByteString, String)
259−getRaw userdata t src = do
252+getRaw userdata mimetype src = do
260 let ext = map toLower $ takeExtension src
253 let ext = map toLower $ takeExtension src
261 let (ext',decomp) = if ext == ".gz"
254 let (ext',decomp) = if ext == ".gz"
262 then (takeExtension $ dropExtension src, B.concat . L.toChunks . Gzip.decompress . L.fromChunks . (:[]))
255 then (takeExtension $ dropExtension src, B.concat . L.toChunks . Gzip.decompress . L.fromChunks . (:[]))
263 else (ext, id)
256 else (ext, id)
264− let mime = case fromAttrib "type" t of
257+ let mime = case mimetype of
265 [] -> mimeTypeFor ext'
258 [] -> mimeTypeFor ext'
267 raw <- getItem userdata src
260 raw <- getItem userdata src
268 result <- if mime == "text/css"
261 result <- if mime == "text/css"
269− then cssImports userdata (takeDirectory src) $ decomp raw
262+ then cssURLs userdata (takeDirectory src) $ decomp raw
270 else return $ decomp raw
263 else return $ decomp raw
271 return (result, mime)
264 return (result, mime)