module Rules.Src.JavaScript (
    rules
) where

import           Control.Monad    (forM_, when)
import           Hakyll
import           System.Directory (doesPathExist, removePathForcibly)
import           System.FilePath  ((</>))

import           Config.Program   (hakyllConfig)
import           Media            (compressJsCompiler)
import           Media.TS         (compileTypeScriptCompiler)

rules :: Rules ()
rules :: Rules ()
rules = do
    IO () -> Rules ()
forall a. IO a -> Rules a
preprocess IO ()
cleanupStaleJsOutputs
    Dependency
viteDependency <- Pattern -> Rules Dependency
forall (m :: * -> *). MonadMetadata m => Pattern -> m Dependency
makePatternDependency (Pattern -> Rules Dependency) -> Pattern -> Rules Dependency
forall a b. (a -> b) -> a -> b
$ Pattern
viteDependencyPath Pattern -> Pattern -> Pattern
.||. Pattern
viteConfigPath Pattern -> Pattern -> Pattern
.||. Pattern
tsconfigPath

    -- Vite/TypeScript設定ファイルと可視化向け型定義は公開しないが、変更時にバンドルを再生成させる
    Pattern -> Rules () -> Rules ()
match Pattern
viteConfigPath (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$ Compiler (Item String) -> Rules ()
forall a.
(Binary a, Typeable a, Writable a) =>
Compiler (Item a) -> Rules ()
compile Compiler (Item String)
getResourceBody
    Pattern -> Rules () -> Rules ()
match Pattern
tsconfigPath (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$ Compiler (Item String) -> Rules ()
forall a.
(Binary a, Typeable a, Writable a) =>
Compiler (Item a) -> Rules ()
compile Compiler (Item String)
getResourceBody
    Pattern -> Rules () -> Rules ()
match Pattern
visualizationTypesPath (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$ Compiler (Item String) -> Rules ()
forall a.
(Binary a, Typeable a, Writable a) =>
Compiler (Item a) -> Rules ()
compile Compiler (Item String)
getResourceBody

    -- Viteでバンドルするエントリーポイント
    [Dependency] -> Rules () -> Rules ()
forall a. [Dependency] -> Rules a -> Rules a
rulesExtraDependencies [Dependency
viteDependency] (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$
        Pattern -> Rules () -> Rules ()
match Pattern
visualizationEntryPath (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$ do
            Routes -> Rules ()
route Routes
tsRoute
            Compiler (Item String) -> Rules ()
forall a.
(Binary a, Typeable a, Writable a) =>
Compiler (Item a) -> Rules ()
compile Compiler (Item String)
compileTypeScriptCompiler

    -- TypeScriptファイルの処理(公開不要ファイルとViteバンドル対象を除外)
    Pattern -> Rules () -> Rules ()
match (Pattern
runtimeTsPath Pattern -> Pattern -> Pattern
.&&. Pattern -> Pattern
complement Pattern
visualizationBundledSourcePath Pattern -> Pattern -> Pattern
.&&. Pattern -> Pattern
complement Pattern
visualizationEntryPath) (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$ do
        Routes -> Rules ()
route Routes
tsRoute
        Compiler (Item String) -> Rules ()
forall a.
(Binary a, Typeable a, Writable a) =>
Compiler (Item a) -> Rules ()
compile Compiler (Item String)
compileTypeScriptCompiler

    -- JavaScriptファイルの処理(手動で作成されたもの)
    Pattern -> Rules () -> Rules ()
match Pattern
jsPath (Rules () -> Rules ()) -> Rules () -> Rules ()
forall a b. (a -> b) -> a -> b
$ do
        Routes -> Rules ()
route (Routes -> Rules ()) -> Routes -> Rules ()
forall a b. (a -> b) -> a -> b
$ String -> (String -> String) -> Routes
gsubRoute String
"contents/" ((String -> String) -> Routes) -> (String -> String) -> Routes
forall a b. (a -> b) -> a -> b
$ String -> String -> String
forall a b. a -> b -> a
const String
forall a. Monoid a => a
mempty
        Compiler (Item String) -> Rules ()
forall a.
(Binary a, Typeable a, Writable a) =>
Compiler (Item a) -> Rules ()
compile Compiler (Item String)
compressJsCompiler
  where
    tsRoute :: Routes
tsRoute = String -> (String -> String) -> Routes
gsubRoute String
"contents/ts/" (String -> String -> String
forall a b. a -> b -> a
const String
"js/") Routes -> Routes -> Routes
`composeRoutes` String -> Routes
setExtension String
"js"
    tsPath :: Pattern
tsPath = String -> Pattern
fromRegex String
"^contents/ts/.+\\.ts$"
    testTsPath :: Pattern
testTsPath = String -> Pattern
fromRegex String
"^contents/ts/(.*/)?__tests__/.*|^contents/ts/.+\\.test\\.ts$"
    declarationTsPath :: Pattern
declarationTsPath = String -> Pattern
fromRegex String
"^contents/ts/.+\\.d\\.ts$"
    declarationOnlyTsPath :: Pattern
declarationOnlyTsPath = String -> Pattern
fromRegex String
"^contents/ts/types/.+\\.ts$"
    runtimeTsPath :: Pattern
runtimeTsPath =
        Pattern
tsPath
            Pattern -> Pattern -> Pattern
.&&. Pattern -> Pattern
complement Pattern
testTsPath
            Pattern -> Pattern -> Pattern
.&&. Pattern -> Pattern
complement Pattern
declarationTsPath
            Pattern -> Pattern -> Pattern
.&&. Pattern -> Pattern
complement Pattern
declarationOnlyTsPath
    visualizationEntryPath :: Pattern
visualizationEntryPath = String -> Pattern
fromRegex String
"^contents/ts/disney-experience-visualizations\\.ts$"
    visualizationSupportPath :: Pattern
visualizationSupportPath = String -> Pattern
fromRegex String
"^contents/ts/(disney-hotel-card-navigation|disney-tab-manager)\\.ts$"
    visualizationsPath :: Pattern
visualizationsPath = String -> Pattern
fromRegex String
"^contents/ts/visualizations/.+\\.ts$"
    visualizationBundledSourcePath :: Pattern
visualizationBundledSourcePath = Pattern
visualizationsPath Pattern -> Pattern -> Pattern
.&&. Pattern -> Pattern
complement Pattern
testTsPath
    visualizationTypesPath :: Pattern
visualizationTypesPath = String -> Pattern
fromRegex String
"^contents/ts/types\\.d\\.ts$"
    viteDependencyPath :: Pattern
viteDependencyPath =
        Pattern
visualizationSupportPath
            Pattern -> Pattern -> Pattern
.||. Pattern
visualizationBundledSourcePath
            Pattern -> Pattern -> Pattern
.||. Pattern
visualizationTypesPath
    viteConfigPath :: Pattern
viteConfigPath = String -> Pattern
fromRegex String
"^vite\\.config\\.production\\.ts$"
    tsconfigPath :: Pattern
tsconfigPath = String -> Pattern
fromRegex String
"^tsconfig\\.json$"
    jsPath :: Pattern
jsPath = String -> Pattern
fromRegex String
"^contents/js/.+$"
    cleanupStaleJsOutputs :: IO ()
cleanupStaleJsOutputs = do
        let jsRoot :: String
jsRoot = Configuration -> String
destinationDirectory Configuration
hakyllConfig String -> String -> String
</> String
"js"
            staleOutputs :: [String]
staleOutputs = [
                String
jsRoot String -> String -> String
</> String
"__tests__"
              , String
jsRoot String -> String -> String
</> String
"types.d.js"
              , String
jsRoot String -> String -> String
</> String
"types" String -> String -> String
</> String
"disney-experience.js"
              ]
        [String] -> (String -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [String]
staleOutputs ((String -> IO ()) -> IO ()) -> (String -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \String
path ->
            String -> IO Bool
doesPathExist String
path IO Bool -> (Bool -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Bool -> IO () -> IO ()) -> IO () -> Bool -> IO ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (String -> IO ()
removePathForcibly String
path)