mirror of
https://github.com/commercialhaskell/stackage-server.git
synced 2026-01-20 07:51:55 +01:00
Crazy takeUntilChunk implementation
This commit is contained in:
parent
83e67f857a
commit
66919e1e14
@ -5,9 +5,6 @@ module Handler.Haddock
|
|||||||
|
|
||||||
import Import
|
import Import
|
||||||
import Stackage.Database
|
import Stackage.Database
|
||||||
import Text.HTML.DOM (eventConduit)
|
|
||||||
import Text.XML.Stream.Render
|
|
||||||
import Data.XML.Types (Event (..), Content (..))
|
|
||||||
|
|
||||||
makeURL :: SnapName -> [Text] -> Text
|
makeURL :: SnapName -> [Text] -> Text
|
||||||
makeURL slug rest = concat
|
makeURL slug rest = concat
|
||||||
@ -31,23 +28,12 @@ getHaddockR slug rest
|
|||||||
case result of
|
case result of
|
||||||
Just route -> redirect route
|
Just route -> redirect route
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
let stylesheet = render' $ StaticR haddock_style_css
|
let extra = concat
|
||||||
render' = return . ContentText . render
|
[ "<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Open+Sans'>"
|
||||||
addExtra t@(EventEndElement "head") =
|
, "<link rel='stylesheet' href='"
|
||||||
[ EventBeginElement "link"
|
, render $ StaticR haddock_style_css
|
||||||
[ ("rel", [ContentText "stylesheet"])
|
, "'>"
|
||||||
, ("href", [ContentText "https://fonts.googleapis.com/css?family=Open+Sans"])
|
|
||||||
]
|
|
||||||
, EventEndElement "link"
|
|
||||||
, EventBeginElement "link"
|
|
||||||
[ ("rel", [ContentText "stylesheet"])
|
|
||||||
, ("href", stylesheet)
|
|
||||||
]
|
|
||||||
, EventEndElement "link"
|
|
||||||
, t
|
|
||||||
]
|
]
|
||||||
addExtra t@(EventBeginElement "body" _) = [t]
|
|
||||||
addExtra t = [t]
|
|
||||||
req <- parseRequest $ unpack $ makeURL slug rest
|
req <- parseRequest $ unpack $ makeURL slug rest
|
||||||
(_, res) <- acquireResponse req >>= allocateAcquire
|
(_, res) <- acquireResponse req >>= allocateAcquire
|
||||||
mstyle' <- lookupGetParam "style"
|
mstyle' <- lookupGetParam "style"
|
||||||
@ -59,16 +45,53 @@ getHaddockR slug rest
|
|||||||
case mstyle of
|
case mstyle of
|
||||||
Just "plain" -> respondSource "text/html; charset=utf-8"
|
Just "plain" -> respondSource "text/html; charset=utf-8"
|
||||||
$ responseBody res .| mapC (Chunk . toBuilder)
|
$ responseBody res .| mapC (Chunk . toBuilder)
|
||||||
_ -> respondSource "text/html; charset=utf-8"
|
_ -> respondSource "text/html; charset=utf-8" $ responseBody res .| (do
|
||||||
$ responseBody res
|
takeUntilChunk "</head>"
|
||||||
.| eventConduit
|
peekC >>= maybe (return ()) (const $ yield $ encodeUtf8 extra)
|
||||||
.| concatMapC addExtra
|
mapC id) .| mapC (Chunk . toBuilder)
|
||||||
.| renderBuilder def
|
|
||||||
{ rsXMLDeclaration = False
|
|
||||||
}
|
|
||||||
.| mapC Chunk
|
|
||||||
| otherwise = redirect $ makeURL slug rest
|
| otherwise = redirect $ makeURL slug rest
|
||||||
|
|
||||||
|
takeUntilChunk :: Monad m => ByteString -> ConduitM ByteString ByteString m ()
|
||||||
|
takeUntilChunk fullNeedle =
|
||||||
|
start
|
||||||
|
where
|
||||||
|
start = await >>= mapM_ start'
|
||||||
|
|
||||||
|
start' bs =
|
||||||
|
case checkNeedle fullNeedle bs of
|
||||||
|
CNNotFound -> yield bs >> start
|
||||||
|
CNFound before after -> yield before >> leftover after
|
||||||
|
CNPartial before after newNeedle -> yield before >> loop (after:) newNeedle
|
||||||
|
|
||||||
|
loop front needle =
|
||||||
|
await >>= mapM_ loop'
|
||||||
|
where
|
||||||
|
loop' bs =
|
||||||
|
if needle `isPrefixOf` bs
|
||||||
|
then leftover $ concat $ front [bs]
|
||||||
|
else
|
||||||
|
case stripPrefix bs needle of
|
||||||
|
Just needle' -> loop (front . (bs:)) needle'
|
||||||
|
Nothing -> yieldMany (front [bs]) >> start
|
||||||
|
|
||||||
|
data CheckNeedle = CNNotFound | CNFound !ByteString !ByteString | CNPartial !ByteString !ByteString !ByteString
|
||||||
|
|
||||||
|
checkNeedle :: ByteString -> ByteString -> CheckNeedle
|
||||||
|
checkNeedle needle bs0 =
|
||||||
|
loop 0
|
||||||
|
where
|
||||||
|
loop idx
|
||||||
|
| idx >= length bs0 = CNNotFound
|
||||||
|
| otherwise =
|
||||||
|
case uncurry checkIndex $ splitAt idx bs0 of
|
||||||
|
CNNotFound -> loop (idx + 1)
|
||||||
|
res -> res
|
||||||
|
|
||||||
|
checkIndex before bs
|
||||||
|
| needle `isPrefixOf` bs = CNFound before bs
|
||||||
|
| Just needle' <- stripPrefix bs needle = CNPartial before bs needle'
|
||||||
|
| otherwise = CNNotFound
|
||||||
|
|
||||||
redirectWithVersion
|
redirectWithVersion
|
||||||
:: (GetStackageDatabase m,MonadHandler m,RedirectUrl (HandlerSite m) (Route App))
|
:: (GetStackageDatabase m,MonadHandler m,RedirectUrl (HandlerSite m) (Route App))
|
||||||
=> SnapName -> [Text] -> m (Maybe (Route App))
|
=> SnapName -> [Text] -> m (Maybe (Route App))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user