module Development.Duplo.Markups where
import Control.Applicative ((<$>))
import Control.Exception (throw)
import Control.Lens hiding (Action)
import Control.Monad.Trans.Class (lift)
import Data.Maybe (fromMaybe)
import Development.Duplo.Component (parseComponentId)
import Development.Duplo.FileList (collapseFileList, makeFile)
import Development.Duplo.Files (File(..), filePath, fileDir, fileName, componentId, fileContent, isRoot, ComponentId)
import Development.Duplo.Utilities (logStatus, headerPrintSetter, expandPaths, compile, createIntermediaryDirectories, CompiledContent, expandDeps, replace)
import Development.Shake
import Development.Shake.FilePath ((</>))
import System.Directory (findFile)
import System.FilePath.Posix (makeRelative, splitDirectories, joinPath)
import qualified Development.Duplo.FileList as FileList (filePath)
import qualified Development.Duplo.Types.Builder as BD
import qualified Development.Duplo.Types.Config as TC
build :: TC.BuildConfig
-> FilePath
-> CompiledContent ()
build config out = do
liftIO $ logStatus headerPrintSetter "Building markups"
lift alwaysRerun
let cwd = config ^. TC.cwd
let env = config ^. TC.env
let buildMode = config ^. TC.buildMode
let utilPath = config ^. TC.utilPath
let devPath = config ^. TC.devPath
let appPath = config ^. TC.appPath
let testPath = config ^. TC.testPath
let duploPath = config ^. TC.duploPath
let assetsPath = config ^. TC.assetsPath
let targetPath = config ^. TC.targetPath
let defaultsPath = config ^. TC.defaultsPath
let refTagsPath = defaultsPath </> "head.html"
let devAssetsPath = devPath </> "assets"
let devCodePath = devPath </> "modules/index"
let depIds = config ^. TC.dependencies
let inTest = TC.isInTest config
lift $ createIntermediaryDirectories devCodePath
let depExpander id = [ "components" </> id </> "app/modules/index" ]
let expanded = expandDeps depIds depExpander
let allPaths = "app/modules/index" : expanded
let absPaths = case buildMode of
"developmoent" -> [ devCodePath ]
"test" -> [ targetPath </> "vendor/mocha" ]
_ -> []
++ map (cwd </>) allPaths
paths <- lift $ expandPaths cwd ".jade" absPaths []
let compiler = utilPath </> "markups-compile.sh"
let preCompile files = return $ fmap (rewriteIncludes cwd files) files
compiled <- compile config compiler [] paths preCompile return
let possibleSources = [ devPath, appPath, defaultsPath ]
Just indexFile <- liftIO $ findFile possibleSources "index.jade"
compiledIndex <- compile config compiler [] [indexFile] preCompile return
let indexWithMarkup = replace "<body>" ("<body>" ++ compiled) compiledIndex
refTagsInTest <- lift $ readFile' $ duploPath </> "etc/test/head.html"
let indexWithTestRefs =
if inTest
then replace "</head>" (refTagsInTest ++ "</head>") indexWithMarkup
else indexWithMarkup
refTags <- lift $ readFile' refTagsPath
let indexWithRefs = replace "</head>" (refTags ++ "</head>") indexWithTestRefs
let minifier = utilPath </> "markups-minify.sh"
let postMinify _ = return indexWithRefs
minified <- compile config minifier [] paths return postMinify
lift $ writeFileChanged out minified
rewriteIncludes :: FilePath
-> [File]
-> File
-> File
rewriteIncludes cwd files file =
file & fileContent .~ rewritten
where
path = file ^. filePath
dir = file ^. fileDir
name = file ^. fileName
id = file ^. componentId
content = file ^. fileContent
isRoot' = file ^. isRoot
defaultId = if isRoot' then "" else id
content' = Prelude.lines content
rewritten' = fmap (rewriteInclude defaultId) content'
rewritten = Prelude.unlines rewritten'
rewriteInclude :: ComponentId -> String -> String
rewriteInclude defaultId line =
let
padLength = length $ takeWhile (' ' ==) line
padding = replicate padLength ' '
tokens = words line
tokenPaths = fmap splitDirectories tokens
in
case tokenPaths of
(("include":_) : fullPath@(prefix:relPath) : _) ->
padding ++ "include " ++ resolvedPath
where
(compName, relPathBase) = case parseComponentId prefix of
Right (user, repo) -> (prefix, "")
Left _ -> (defaultId, prefix)
resolvedPath = if not (null compName)
then "components" </> compName </> "app/modules" </>
relPathBase </> joinPath relPath
else "app/modules" </> joinPath fullPath
_ -> line