elm-build-lib (empty) → 0.0.1
raw patch · 4 files changed
+207/−0 lines, 4 filesdep +basedep +directorydep +processsetup-changed
Dependencies added: base, directory, process, temporary, text
Files
- LICENSE +27/−0
- Setup.hs +2/−0
- elm-build-lib.cabal +37/−0
- src/Language/Elm/Build.hs +141/−0
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2014, JoeyEremondi+All rights reserved.++Redistribution and use in source and binary forms, with or without modification,+are permitted provided that the following conditions are met:++* Redistributions of source code must retain the above copyright notice, this+ list of conditions and the following disclaimer.++* Redistributions in binary form must reproduce the above copyright notice, this+ list of conditions and the following disclaimer in the documentation and/or+ other materials provided with the distribution.++* Neither the name of the {organization} nor the names of its+ contributors may be used to endorse or promote products derived from+ this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ elm-build-lib.cabal view
@@ -0,0 +1,37 @@+Name: elm-build-lib+Version: 0.0.1+Synopsis: Elm compiler wrapper+Description: Wrappers around the Elm binary to compile elm source strings into Javascript within Haskell+Homepage: http://github.com/JoeyEremondi/elm-build-lib++License: BSD3+License-file: LICENSE++name: elm-build-lib+version: 0.0.1+cabal-version: >=1.6+build-type: Simple+author: Joey Eremondi+Maintainer: joey@eremondi.com+Copyright: Copyright: (c) 2014 Joey Eremondi++Category: Compiler, Language+++source-repository head+ type: git+ location: git://github.com/JoeyEremondi/elm-build-lib++++library+ exposed-modules: Language.Elm.Build+ hs-source-dirs: src+ build-depends: base >=4.2 && <5+ --, Elm+ , directory+ , process+ , temporary+ , text+ ghc-options: -Wall+
+ src/Language/Elm/Build.hs view
@@ -0,0 +1,141 @@+{-# LANGUAGE OverloadedStrings #-}++{-|+A Haskell library wrapper around the Elm executable, to build files from within Haskell.++For more information on Elm, see http://elm-lang.org.++There are two main steps to using this library: converting Elm source to a Module structure,+then compiling various modules.++To compile a string to a module, simply do++ > let auxModule = moduleFromString (pack "Aux") (pack $ "module Aux where\n" ++ "x = 3")+ +or++ > let mainModule = moduleFromString (pack "Main") (pack $ "import Aux\n" ++ "main = plainText (show Aux.x)")++Note that the first argument must match the name given in the @module X where@+declaration in your elm file.+Both arguments must be Text, not String.+You can use `moduleFromFile` similarly.++Once you have some modules, you can compile them into JavaScript or HTML:++ > Right js <- buildModulesWithOptions defaultOptions mainModule [auxModule]++The first argument is always the module containing the @main@ definition for Elm.+The list is the list of all files which are dependencies of the main module.+Files are written to a temp directory, then compiled using the @--make@ option.++A current limitation is that only single-directory structures are supported.++-}+++module Language.Elm.Build (+ Module,+ Javascript,+ BuildOptions(..),+ ModuleName,+ ModuleSource,+ defaultOptions,+ moduleFromString,+ moduleFromFile,+ buildModules,+ buildModulesWithOptions+ + ) where++import System.Process (readProcessWithExitCode)+import System.Directory (doesFileExist)+import System.Exit (ExitCode(..))+import Data.Maybe (catMaybes, fromMaybe)+import System.IO.Temp (withTempDirectory)+import Data.Text+import qualified Data.Text.IO as TextIO++++++-- | Synonym for module names (i.e. Data.Text, Main, etc.)+type ModuleName = Text++-- | Type for module source code+type ModuleSource = Text++-- | Wrapper for modules, which have a name and source code+newtype InternalModule = Module (ModuleName, ModuleSource)++-- | Opaque type representing an Elm module loaded from a string or file+type Module = InternalModule++-- | Type representing Javascript output (as a string)+type Javascript = Text++-- | Abstraction for the options given to the elm executable+-- Note that not all Elm options may be avaliable+data BuildOptions = BuildOptions {+ elmBinPath :: Maybe String,+ elmRuntimePath :: Maybe String,+ makeHtml :: Bool+ }++-- |Default options are: `elm` as binary, no runtime given, and generate JS only+defaultOptions :: BuildOptions+defaultOptions = BuildOptions {+ elmBinPath = Nothing,+ elmRuntimePath = Nothing,+ makeHtml = False+}++-- | Generate a module with the given Module name (e.g. 'MyLib.Foo')+-- and the given source code+moduleFromString :: ModuleName -> ModuleSource -> Module+moduleFromString name source = Module (name, source)++-- | Read a module from a file, with the given module name and file path+moduleFromFile :: ModuleName -> FilePath -> IO Module+moduleFromFile name path = do+ src <- TextIO.readFile path+ return $ moduleFromString name src++-- | Build a group of elm modules with the `elm` from the system `$PATH`+-- generating JavaScript using the default runtime location+buildModules :: Module -> [Module] -> IO (Either String Javascript)+buildModules = buildModulesWithOptions defaultOptions+ +-- | Given an elm "main" module, and a list of other modules,+-- compile them using the `--make` option and the given options+buildModulesWithOptions :: BuildOptions -> Module -> [Module] -> IO (Either String Javascript)+buildModulesWithOptions options mainModule@(Module (mainName, _)) otherModules = withTempDirectory "" ".elm_temp" (\dir -> do+ mapM_ (writeElmSource dir) otherModules+ writeElmSource dir mainModule++ let binPath = fromMaybe "elm" $ elmBinPath options+ let runtimeOption = maybe Nothing (\path -> Just $ "--runtime=" ++ path) $ elmRuntimePath options+ let genJSOption = if (makeHtml options) then Nothing else (Just "--only-js")+ let resultExt = if (makeHtml options) then ".html" else ".js"+ + let cmdlineOptions = ["--make", "--build-dir=" ++ dir ++ "/build", "--cache-dir=" ++ dir ++"/cache", "--src-dir=" ++ dir] ++ catMaybes [runtimeOption, genJSOption] ++ [ unpack mainName ++ ".elm"]+ + (exitCode, stdout, stderr) <- readProcessWithExitCode binPath cmdlineOptions []+ + case exitCode of+ ExitFailure i -> return $ Left $ "Elm failed with exit code " ++ (show i) ++ " and errors:" ++ stdout ++ stderr+ _ -> do+ let outputPath = dir ++ "/build/" ++ unpack mainName ++ resultExt+ exists <- doesFileExist outputPath+ case exists of+ False -> return $ Left "Could not find output file from Elm"+ _ -> do+ retJS <- TextIO.readFile outputPath+ return $ Right retJS+ + )+ where+ writeElmSource dir (Module (moduleName, source)) = do+ let path = dir ++ "/" ++ unpack moduleName ++ ".elm"+ TextIO.writeFile path source