module Tintin.ConfigurationLoading ( ConfigurationLoading , loadInfo ) where require Tintin.Errors require Tintin.Capabilities.Logging require Tintin.Capabilities.Filesystem require Tintin.Domain.HtmlFile require Tintin.Domain.Project require Data.Text import Tintin.Core import qualified Universum.Unsafe as Unsafe import Text.Read (read) data ConfigurationLoading loadInfo :: ( Has Logging.Capability eff , Has Filesystem.Capability eff ) => [HtmlFile] -> Effectful eff Project.Info loadInfo htmlFiles = do let pages = htmlFiles & map (\HtmlFile.HtmlFile {..} -> Project.Page title content filename) Filesystem.Path currentDir <- Filesystem.currentDirectory files <- Filesystem.list (Filesystem.Path currentDir) let packageYamlFile = find isPackageYaml files let cabalFile = find isCabalFile files case packageYamlFile <|> cabalFile of Nothing -> do Errors.showAndDie ["No package.yaml or *.cabal file found."] error "" Just p -> do let tintinPath = Filesystem.Path $ currentDir <> "/.tintin.yml" Logging.debug "Reading project info" projectInfoFile <- Filesystem.readFile p tintinExists <- Filesystem.doesExist tintinPath unless tintinExists $ Filesystem.writeFile tintinPath "color: blue\n" tintinFile <- Filesystem.readFile tintinPath let projectName = projectInfoFile & getFieldValue "name" projectSynopsis = projectInfoFile & getFieldValue "synopsis" projectGithub = (projectInfoFile & getFieldValue "github") <|> (projectInfoFile & getFieldValue "location") projectAuthor = projectGithub & fmap getAuthor tintinColor = tintinFile & getFieldValue "color" tintinLogo = tintinFile & getFieldValue "logo" when (isNothing projectName) (Errors.showAndDie ["Project must have a name. Please set it in package.yaml or *.cabal."]) when (isNothing projectSynopsis) (Errors.showAndDie ["Project must have a synopsis. Please set it in package.yaml or *.cabal."]) when (isNothing tintinColor) (Errors.showAndDie [errorMessages]) return Project.Info { name = Unsafe.fromJust projectName , synopsis = Unsafe.fromJust projectSynopsis , githubLink = parseGithubUrl <$> projectGithub , githubAuthor = projectAuthor , color = makeColor $ Unsafe.fromJust tintinColor , logoUrl = tintinLogo , pages = pages } where errorMessages = unlines ["Tintin usually generates a .tintin.yml file with a color configuration. Maybe you don't have enough permissions?" , "" , "" , "Try creating .tintin.yml and adding color:blue to it." ] isPackageYaml (Filesystem.Path p) = p == "package.yaml" isCabalFile (Filesystem.Path p) = ".cabal" `Text.isInfixOf` p makeColor :: Text -> Project.Color makeColor txt = let capitalLetter = txt & Text.head & Text.singleton & Text.toUpper restOfText = txt & Text.tail in (capitalLetter <> restOfText) & toString & read getFieldValue field txt = txt & lines & filter (\t -> field `Text.isPrefixOf` Text.strip t) & safeHead & fmap Text.strip & flatMap (Text.stripPrefix $ field <> ":") & fmap Text.strip getAuthor txt = let unquoted = stripQuotes txt in parseGithubUrl unquoted & (\t -> if "http" `Text.isPrefixOf` t then Text.splitOn "/" t & filter (not . Text.isInfixOf "git") & filter (not . Text.null) & Unsafe.tail & Unsafe.head else t ) & Text.takeWhile (/= '/') parseGithubUrl txt = let unquoted = stripGit $ stripQuotes txt in unquoted & Text.stripPrefix "github.com/" & fromMaybe unquoted stripQuotes txt = txt & Text.stripPrefix "\"" & flatMap (Text.stripSuffix "\"") & fromMaybe txt stripGit txt = txt & Text.stripPrefix "git://" & flatMap (Text.stripSuffix ".git") & fromMaybe txt