From a3b2321f7781c98c2863a54a339af73a6d6d0050 Mon Sep 17 00:00:00 2001 From: alexwl Date: Wed, 7 Nov 2018 18:31:43 +0300 Subject: Embed static assets in haskell-code-server executable. When there is no --js-path option, haskell-code-server serves embedded static assets. --- README.md | 4 ++-- app/Server.hs | 25 +++++++++++++++++++++++-- haskell-code-explorer.cabal | 1 + 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 249d3b0..67ccb72 100644 --- a/README.md +++ b/README.md @@ -119,13 +119,13 @@ haskell-code-server -h Load the indexed package and start the server: ```bash -haskell-code-server --package PATH --port 8080 --js-path haskell-code-explorer/javascript/release +haskell-code-server --package PATH --port 8080 ``` Load multiple indexed packages and start the server: ```bash -haskell-code-server --package PATH1 --package PATH2 --package PATH3 --port 8080 --js-path haskell-code-explorer/javascript/release +haskell-code-server --package PATH1 --package PATH2 --package PATH3 --port 8080 ``` Open [http://localhost:8080](http://localhost:8080) in a browser to explore source code of the package. diff --git a/app/Server.hs b/app/Server.hs index 0ced97f..abe4958 100644 --- a/app/Server.hs +++ b/app/Server.hs @@ -1,4 +1,5 @@ {-# LANGUAGE CPP #-} +{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -29,7 +30,6 @@ import Control.Monad.Except (ExceptT(..)) import Control.Monad.Reader (MonadIO, MonadReader, ReaderT(..), asks, liftIO) import qualified Data.Aeson as A import qualified Data.ByteString as BS -import qualified Data.Vector as V import qualified Data.ByteString.Lazy as BSL import Data.Default (def) import Data.Either (lefts, rights) @@ -39,6 +39,7 @@ import qualified Data.IntervalMap.Strict as IVM import qualified Data.List as L import qualified Data.Map.Strict as M import Data.Maybe (fromMaybe, mapMaybe) +import qualified Data.Vector as V #if MIN_VERSION_GLASGOW_HASKELL(8,4,3,0) import qualified GHC.Compact as C import Data.Functor.Identity(Identity(..)) @@ -149,6 +150,7 @@ import System.Log.FastLogger ) import Text.Blaze.Html.Renderer.Text (renderHtml) import qualified Text.Blaze.Html5 as Html hiding (html, source) +import Data.FileEmbed (embedDir, embedFile) -------------------------------------------------------------------------------- -- Server config @@ -948,7 +950,19 @@ staticMiddleware _ _ mbJsDistPath _app req callback = if exists then callback $ sendFile path else callback $ sendFile (jsDistPath "index.html") - Nothing -> callback fileNotFound + Nothing -> do + let path = T.unpack $ T.intercalate "/" $ pathInfo req + if path == "" + then callback $ sendEmbeddedFile "index.html" indexHtml + else case HM.lookup path staticAssets of + Just bs -> callback $ sendEmbeddedFile path bs + Nothing -> callback $ sendEmbeddedFile "index.html" indexHtml + +staticAssets :: HM.HashMap FilePath BS.ByteString +staticAssets = HM.fromList $(embedDir "javascript/release") + +indexHtml :: BS.ByteString +indexHtml = $(embedFile "javascript/release/index.html") sendFile :: FilePath -> Response sendFile path = @@ -958,6 +972,13 @@ sendFile path = path Nothing +sendEmbeddedFile :: FilePath -> BS.ByteString -> Response +sendEmbeddedFile path bs = + responseLBS + status200 + [(hContentType, defaultMimeLookup $ T.pack $ takeFileName path)] + (BSL.fromStrict bs) + fileNotFound :: Response fileNotFound = responseLBS status404 [("Content-Type", "text/plain")] "Not found" diff --git a/haskell-code-explorer.cabal b/haskell-code-explorer.cabal index d62a598..9ecfcd6 100644 --- a/haskell-code-explorer.cabal +++ b/haskell-code-explorer.cabal @@ -109,6 +109,7 @@ executable haskell-code-server , optparse-applicative , data-default , pagination + , file-embed if impl(ghc >= 8.4.3) build-depends: ghc-compact -- cgit v1.2.3