SJW/src/SJW/Module/File.hs

83 lines
2.8 KiB
Haskell

--- SJW -- Clean Javascript modules for front-end development
--- Copyright © 2022 Tissevert <tissevert+devel@marvid.fr>
---
--- This file is part of SJW.
---
--- SJW is free software: you can redistribute it and/or modify it under the
--- terms of the GNU General Public License as published by the Free Software
--- Foundation, either version 3 of the License, or (at your option) any later
--- version.
---
--- SJW is distributed in the hope that it will be useful, but WITHOUT ANY
--- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
--- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
--- details.
---
--- You should have received a copy of the GNU General Public License along
--- with this program. If not, see <http://www.gnu.org/licenses/>.
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
module SJW.Module.File (
File(..)
, header
, footer
, parser
, variables
) where
import SJW.Source (Path)
import Control.Applicative ((<|>))
import Data.Attoparsec.Text (
Parser, inClass, isEndOfLine, sepBy, string, takeTill, takeWhile
)
import Data.List (intercalate)
import qualified Data.Map as Map (toList)
import Data.Text (Text)
import qualified Data.Text as Text (pack)
import SJW.Module.Imports (Reference(..), Tree(..))
import qualified SJW.Module.Imports as Imports (parser)
import Prelude hiding (takeWhile)
import Text.Printf (printf)
data File = File {
isMain :: Bool
, imports :: Tree
, payload :: [Text]
} deriving Show
parser :: Bool -> Parser File
parser isMain = File isMain
<$> Imports.parser
<*> (blank *> line `sepBy` eol)
where
eol = string "\r\n" <|> string "\r" <|> string "\n"
blank = takeWhile (inClass " \t\r\n")
line = takeTill isEndOfLine
header :: Bool -> Path -> [String] -> Text
header isMain path names = Text.pack (outside isMain ++ arguments)
where
outside True = ""
outside False = printf "modules['%s'] = " (show path)
arguments = printf "(function(%s) {" (intercalate ", " $ names ++ ["modules"])
footer :: [String] -> [Text]
footer values = [Text.pack $ printf "})(%s);" (intercalate ", " values)]
variables :: Tree -> [(String, String)]
variables = fmap (fmap computeValue) . Map.toList . children
where
computeValue :: Tree -> String
computeValue subTree =
let subModules = intercalate ", " $ f <$> Map.toList (children subTree) in
case target subTree of
Nothing -> printf "Object.create(null, {%s})" subModules
Just (ModulePath {modulePath}) ->
printf "Object.create(modules['%s'], {%s})"
(show modulePath)
subModules
Just (Object {modulePath, field}) ->
printf "modules['%s'].%s" (show modulePath) field
f (name, subTree) = printf "%s: {value: %s}" name $ computeValue subTree