packages feed

shakespeare-js 1.1.1 → 1.1.2

raw patch · 7 files changed

+231/−43 lines, 7 filesdep −shakespeare-jsdep ~shakespearePVP ok

version bump matches the API change (PVP)

Dependencies removed: shakespeare-js

Dependency ranges changed: shakespeare

API changes (from Hackage documentation)

+ Text.TypeScript: tsc :: QuasiQuoter
+ Text.TypeScript: typeScriptFile :: FilePath -> Q Exp
+ Text.TypeScript: typeScriptFileReload :: FilePath -> Q Exp

Files

Text/Coffee.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE CPP #-}@@ -14,6 +13,34 @@ -- CoffeeScript already uses that sequence for string interpolation. Therefore, -- Shakespearean interpolation is introduced with @%{...}@. --+-- If you interpolate variables,+-- the template is first wrapped with a function containing javascript variables representing shakespeare variables,+-- then compiled with @coffee@,+-- and then the value of the variables are applied to the function.+-- This means that in production the template can be compiled+-- once at compile time and there will be no dependency in your production+-- system on @coffee@. +--+-- Your code:+--+-- >   b = 1+-- >   console.log(#{a} + b)+--+-- Function wrapper added to your coffeescript code:+--+-- > ((shakespeare_var_a) =>+-- >   b = 1+-- >   console.log(shakespeare_var_a + b)+-- > )+--+-- This is then compiled down to javascript, and the variables are applied:+--+-- > ;(function(shakespeare_var_a){+-- >   var b = 1;+-- >   console.log(shakespeare_var_a + b);+-- > })(#{a});+--+-- -- Further reading: -- -- 1. Shakespearean templates: <http://www.yesodweb.com/book/templates>@@ -39,24 +66,23 @@ import Text.Shakespeare import Text.Julius --- | The Coffeescript language compiles down to Javascript.--- We do this compilation once at compile time to avoid needing to do it during the request.--- We call this a preConversion because other shakespeare modules like Lucius use Haskell to compile during the request rather than a system call.--- During the pre-conversion we first modify all Haskell insertions--- so that they will be ignored by the Coffeescript compiler (backticks).--- So %{var} is change to `%{var}` using the preEscapeBegin and preEscapeEnd.--- preEscapeIgnore is used to not insert backtacks for variable already inside strings or backticks.--- coffeescript will happily ignore the interpolations, and backticks would not be treated as escaping in that context. coffeeSettings :: Q ShakespeareSettings coffeeSettings = do   jsettings <- javascriptSettings   return $ jsettings { varChar = '%'   , preConversion = Just PreConvert {-      preConvert = ReadProcess "coffee" ["-sp"]-    , preEscapeBegin = "`"-    , preEscapeEnd = "`"-    , preEscapeIgnoreBalanced = "'\"`"-    , preEscapeIgnoreLine = "#"+      preConvert = ReadProcess "coffee" ["-spb"]+    , preEscapeIgnoreBalanced = "'\"`"     -- don't insert backtacks for variable already inside strings or backticks.+    , preEscapeIgnoreLine = "#"            -- ignore commented lines+    , wrapInsertion = Just WrapInsertion { +        wrapInsertionIndent = Just "  "+      , wrapInsertionStartBegin = "(("+      , wrapInsertionSeparator = ", "+      , wrapInsertionStartClose = ") =>"+      , wrapInsertionEnd = ")"+      , wrapInsertionApplyBegin = "("+      , wrapInsertionApplyClose = ")\n"+      }     }   } 
Text/Julius.hs view
@@ -5,9 +5,8 @@ {-# OPTIONS_GHC -fno-warn-missing-fields #-} -- | A Shakespearean module for Javascript templates, introducing type-safe, -- compile-time variable and url interpolation.----- To use this module, @coffee@ must be installed on your system. ----- You might consider trying 'Text.Coffee', which compiles down to Javascript.+-- You might consider trying 'Text.Typescript' or 'Text.Coffee' which compile down to Javascript. -- -- Further reading: <http://www.yesodweb.com/book/templates> module Text.Julius
Text/Roy.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE CPP #-}@@ -10,15 +9,9 @@ -- -- To use this module, @roy@ must be installed on your system. ----- @#{...}@ is the Shakespearean standard for variable interpolation, but--- CoffeeScript already uses that sequence for string interpolation.--- Therefore, it seems more future-proof to use @%{...}@ for interpolation------ Integration with Roy is a bit rough right now.--- You can only perorm a shakespeare insertion inside a Roy string.--- This should work well for urls and strings.--- Otherwise you should stick your Haskell into Julius as a window variable,--- and then retrieve it in your Roy code.+-- Unfortunately variable interpolation in Roy does not currently work,+-- but it can with a small change to Roy:+-- <https://github.com/pufuwozu/roy/issues/165> -- -- Further reading: --@@ -50,13 +43,23 @@ roySettings :: Q ShakespeareSettings roySettings = do   jsettings <- javascriptSettings-  return $ jsettings { varChar = '%'+  return $ jsettings { varChar = '#'   , preConversion = Just PreConvert {       preConvert = ReadProcess "roy" ["--stdio"]-    , preEscapeBegin = "`"-    , preEscapeEnd = "`"-    , preEscapeIgnoreBalanced = "'\"`"+    , preEscapeIgnoreBalanced = "'\""     , preEscapeIgnoreLine = "//"+    , wrapInsertion = Nothing+    {-+    Just WrapInsertion { +        wrapInsertionIndent = Just "  "+      , wrapInsertionStartBegin = "(\\"+      , wrapInsertionSeparator = " "+      , wrapInsertionStartClose = " ->\n"+      , wrapInsertionEnd = ")"+      , wrapInsertionApplyBegin = " "+      , wrapInsertionApplyClose = ")\n"+      }+      -}     }   } 
+ Text/TypeScript.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -fno-warn-missing-fields #-}+-- | A Shakespearean module for TypeScript, introducing type-safe,+-- compile-time variable and url interpolation. It is exactly the same as+-- "Text.Julius", except that the template is first compiled to Javascript with+-- the system tool @tsc@.+--+-- To use this module, @tsc@ must be installed on your system.+--+-- If you interpolate variables,+-- the template is first wrapped with a function containing javascript variables representing shakespeare variables,+-- then compiled with @tsc@,+-- and then the value of the variables are applied to the function.+-- This means that in production the template can be compiled+-- once at compile time and there will be no dependency in your production+-- system on @tsc@. +--+-- Your code:+--+-- > var b = 1+-- > console.log(#{a} + b)+--+-- Final Result:+--+-- > ;(function(shakespeare_var_a){+-- >   var b = 1;+-- >   console.log(shakespeare_var_a + b);+-- > })(#{a});+--+--+-- Important Warnings! This integration is not ideal.+--+-- Due to the function wrapper, all type declarations must be in separate .d.ts files.+-- However, if you don't interpolate variables, no function wrapper will be+-- created, and you can make type declarations in the same file.+--+-- This does not work cross-platform!+--+-- Unfortunately tsc does not support stdin and stdout.+-- So a hack of writing to temporary files using the mktemp+-- command is used. This works on my version of Linux, but not for windows+-- unless perhaps you install a mktemp utility, which I have not tested.+-- Please vote up this bug: <http://typescript.codeplex.com/workitem/600>+--+-- Making this work on Windows would not be very difficult, it will just require a new+-- package with a dependency on a package like temporary.+--+-- Further reading:+--+-- 1. Shakespearean templates: <http://www.yesodweb.com/book/templates>+--+-- 2. TypeScript: <http://typescript.codeplex.com/>+module Text.TypeScript+    ( -- * Functions+      -- ** Template-Reading Functions+      -- | These QuasiQuoter and Template Haskell methods return values of+      -- type @'JavascriptUrl' url@. See the Yesod book for details.+      tsc+    , typeScriptFile+    , typeScriptFileReload++#ifdef TEST_EXPORT+    , typeScriptSettings+#endif+    ) where++import Language.Haskell.TH.Quote (QuasiQuoter (..))+import Language.Haskell.TH.Syntax+import Text.Shakespeare+import Text.Julius++-- | The TypeScript language compiles down to Javascript.+-- We do this compilation once at compile time to avoid needing to do it during the request.+-- We call this a preConversion because other shakespeare modules like Lucius use Haskell to compile during the request instead rather than a system call.+typeScriptSettings :: Q ShakespeareSettings+typeScriptSettings = do+  jsettings <- javascriptSettings+  return $ jsettings { varChar = '#'+  , preConversion = Just PreConvert {+      preConvert = ReadProcess "sh" ["-c", "TMP_IN=$(mktemp XXXXXXXXXX.ts); TMP_OUT=$(mktemp XXXXXXXXXX.js); cat /dev/stdin > ${TMP_IN} && tsc --out ${TMP_OUT} ${TMP_IN} && cat ${TMP_OUT}; rm ${TMP_IN} && rm ${TMP_OUT}"]+    , preEscapeIgnoreBalanced = "'\""+    , preEscapeIgnoreLine = "//"+    , wrapInsertion = Just WrapInsertion { +        wrapInsertionIndent = Nothing+      , wrapInsertionStartBegin = ";(function("+      , wrapInsertionSeparator = ", "+      , wrapInsertionStartClose = "){"+      , wrapInsertionEnd = "})"+      , wrapInsertionApplyBegin = "("+      , wrapInsertionApplyClose = ");\n"+      }+    }+  }++-- | Read inline, quasiquoted TypeScript+tsc :: QuasiQuoter+tsc = QuasiQuoter { quoteExp = \s -> do+    rs <- typeScriptSettings+    quoteExp (shakespeare rs) s+    }++-- | Read in a Roy template file. This function reads the file once, at+-- compile time.+typeScriptFile :: FilePath -> Q Exp+typeScriptFile fp = do+    rs <- typeScriptSettings+    shakespeareFile rs fp++-- | Read in a Roy template file. This impure function uses+-- unsafePerformIO to re-read the file on every call, allowing for rapid+-- iteration.+typeScriptFileReload :: FilePath -> Q Exp+typeScriptFileReload fp = do+    rs <- typeScriptSettings+    shakespeareFileReload rs fp
shakespeare-js.cabal view
@@ -1,5 +1,5 @@ name:            shakespeare-js-version:         1.1.1+version:         1.1.2 license:         MIT license-file:    LICENSE author:          Michael Snoyman <michael@snoyman.com>@@ -9,11 +9,13 @@     Shakespeare is a template family for type-safe, efficient templates with simple variable interpolation . Shakespeare templates can be used inline with a quasi-quoter or in an external file. Shakespeare interpolates variables according to the type being inserted.     In this case, the variable type needs a ToJavascript instance.     .-    There is also shakespeare-coffeescript for coffeescript templates. Coffescript is a language that compiles down to javascript. It expects a coffeescript compiler in your path, and variable should be a ToCoffee instance. And we even have a Roy template for the adventorous FP addicts.+    shakespeare-javascript is alson known as Julius, and passes through plain javascript     .+    There is also a shakespeare version for CoffeeScript, TypeScript, and Roy, all languages that compile down to Javascript. They all expect you to have the appropriate compiler in your path.+    .+    shakespeare originated from the hamlet template package.     Please see http://www.yesodweb.com/book/shakespearean-templates for a more thorough description and examples     .-    shakespeare-js was originally called julius, and shakespeare originated from the hamlet template package. extra-source-files:   test/juliuses/external1.coffee   test/juliuses/external1.julius@@ -38,6 +40,7 @@                      Text.Julius                      Text.Coffee                      Text.Roy+                     Text.TypeScript     ghc-options:     -Wall     if impl(ghc >= 7.4)        cpp-options: -DGHC_7_4@@ -45,6 +48,9 @@     if flag(test_coffee)         cpp-options: -DTEST_COFFEE +    if flag(test_roy)+        cpp-options: -DTEST_ROY+     if flag(test_export)         cpp-options: -DTEST_EXPORT @@ -56,15 +62,20 @@     -- cabal configure --enable-tests -ftest_coffee && cabal build && dist/build/test/test     default: False +flag test_roy+    description: render tests through coffeescript render function+    -- cabal configure --enable-tests -ftest_coffee && cabal build && dist/build/test/test+    default: False+ test-suite test-    hs-source-dirs: test+    hs-source-dirs: test ./     main-is: ../test.hs     other-modules: Quoter     type: exitcode-stdio-1.0      ghc-options:   -Wall-    build-depends: shakespeare-js-                 , shakespeare+    build-depends:+                   shakespeare                  , base                  , HUnit                  , hspec            >= 1.3@@ -72,9 +83,11 @@                  , template-haskell                  , aeson --- cabal bug---    if flag(test_coffee)---        cpp-options: -DTEST_COFFEE+    cpp-options: -DTEST_EXPORT+    if flag(test_coffee)+        cpp-options: -DTEST_COFFEE+    if flag(test_roy)+        cpp-options: -DTEST_ROY   source-repository head
test/Quoter.hs view
@@ -10,7 +10,11 @@ import Text.Coffee (coffeeSettings) import Text.Shakespeare (shakespeare) #else+#  ifdef TEST_ROY+import Text.Roy+#  else import Text.Julius+#  endif #endif  quote :: QuasiQuoter@@ -29,7 +33,13 @@ quoteFile = coffeeFile quoteFileReload = coffeeFileReload #else+#  ifdef TEST_ROY+quote = roy+quoteFile = royFile+quoteFileReload = royFileReload+#  else quote = julius quoteFile = juliusFile quoteFileReload = juliusFileReload+#  endif #endif
test/ShakespeareJsTest.hs view
@@ -29,6 +29,7 @@ 
 specs :: Spec
 specs = describe "shakespeare-js" $ do
+#if !(defined TEST_COFFEE || defined TEST_ROY)
   it "julius" $ do
     let var = "x=2"
     let urlp = (Home, [(pack "p", pack "q")])
@@ -63,6 +64,7 @@         , "url?p=q"
         , "f(2)"
         ] ++ "\n"
+#endif
 
 {- TODO
   it "juliusFileDebugChange" $ do
@@ -80,16 +82,20 @@     let foo = "foo"
         double = 3.14 :: Double
         int = -5 :: Int
-    in jelper "[oof, oof, 3.14, -5]"
 #ifdef TEST_COFFEE
-         [quote|[%{Data.List.reverse foo}, %{L.reverse foo}, %{show double}, %{show int}]|]
+    in jelper "var _this = this;\n\n(function(shakespeare_var_rawJSDataListreversefoo, shakespeare_var_rawJSLreversefoo, shakespeare_var_rawJSshowdouble, shakespeare_var_rawJSshowint) {\n  return [shakespeare_var_rawJSDataListreversefoo, shakespeare_var_rawJSLreversefoo, shakespeare_var_rawJSshowdouble, shakespeare_var_rawJSshowint];\n})(oof, oof, 3.14, -5)"
 #else
-         [quote|[#{rawJS $ Data.List.reverse foo}, #{rawJS $ L.reverse foo}, #{rawJS $ show double}, #{rawJS $ show int}]|]
+#  ifdef TEST_ROY
+    in jelper "(function(shakespeare_var_rawJSDataListreversefoo, shakespeare_var_rawJSLreversefoo, shakespeare_var_rawJSshowdouble, shakespeare_var_rawJSshowint) {\n  return [shakespeare_var_rawJSDataListreversefoo, shakespeare_var_rawJSLreversefoo, shakespeare_var_rawJSshowdouble, shakespeare_var_rawJSshowint];\n})(oof, oof, 3.14, -5)"
+#  else
+    in jelper "[oof, oof, 3.14, -5]"
+#  endif
 #endif
+         [quote|[#{rawJS $ Data.List.reverse foo}, #{rawJS $ L.reverse foo}, #{rawJS $ show double}, #{rawJS $ show int}]|]
 
 
 -- not valid coffeescript
-#ifndef TEST_COFFEE
+#if !(defined TEST_COFFEE || defined TEST_ROY)
   it "single dollar at and caret" $ do
     jelper "$@^" [quote|$@^|]
     jelper "#{@{^{" [quote|#\{@\{^\{|]
@@ -97,8 +103,13 @@ 
   it "dollar operator" $ do
     let val = (1 :: Int, (2 :: Int, 3 :: Int))
+#if !(defined TEST_COFFEE || defined TEST_ROY)
     jelper "2" [quote|#{ rawJS $ show $ fst $ snd val }|]
     jelper "2" [quote|#{ rawJS $ show $ fst $ snd $ val}|]
+#else
+    jelper "var _this = this;\n\n(function(shakespeare_var_rawJSshowfstsndval) {\n  return shakespeare_var_rawJSshowfstsndval;\n})(2)" [quote|#{ rawJS $ show $ fst $ snd val }|]
+    jelper "var _this = this;\n\n(function(shakespeare_var_rawJSshowfstsndval) {\n  return shakespeare_var_rawJSshowfstsndval;\n})(2)" [quote|#{ rawJS $ show $ fst $ snd val }|]
+#endif
 
   it "empty file" $ jelper "" [quote||]
 
@@ -108,8 +119,15 @@     "true false true false true false"
     [julius|#{True} #{False} #{toJSON True} #{toJSON False} #{rawJS True} #{rawJS False}|]
 
+  it "^\\ should not be escaped" $ jelper
+     "var re = /[^\\r]/;"
+     [julius|var re = /[^\r]/;|]
 
+  it "^\\{ should be escaped" $ jelper
+     "var re = /[^{]/;"
+     [julius|var re = /[^\{]/;|]
 
+
 data Url = Home | Sub SubUrl
 data SubUrl = SubUrl
 render :: Url -> [(Text, Text)] -> Text
@@ -150,8 +168,10 @@ 
 
 
+#ifndef TEST_ROY
 jmixin :: JavascriptUrl u
 jmixin = [quote|f(2)|]
+#endif
 
 jelper :: String -> JavascriptUrl Url -> Assertion
 jelper res h = do