packages feed

shakespeare 2.0.6 → 2.0.7

raw patch · 6 files changed

+93/−9 lines, 6 filesdep +scientificdep +unordered-containersdep +vectordep ~aesonPVP ok

version bump matches the API change (PVP)

Dependencies added: scientific, unordered-containers, vector

Dependency ranges changed: aeson

API changes (from Hackage documentation)

Files

ChangeLog.md view
@@ -1,3 +1,7 @@+### 2.0.7++* Include aeson's JSON encoding and escape `<`, `>` and `&` to avoid XSS attacks+ ### 2.0.6  * Provide the `Text.Hamlet.Runtime` module
Text/CssCommon.hs view
@@ -11,7 +11,6 @@ import Language.Haskell.TH import Data.Word (Word8) import Data.Bits-import Data.Text.Lazy.Builder (fromLazyText) import qualified Data.Text.Lazy as TL  renderCssUrl :: (url -> [(TS.Text, TS.Text)] -> TS.Text) -> CssUrl url -> TL.Text
Text/Julius.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-missing-fields #-} -- | A Shakespearean module for Javascript templates, introducing type-safe, -- compile-time variable and url interpolation.--@@ -50,7 +52,14 @@ import qualified Data.Text.Lazy as TL import Text.Shakespeare import Data.Aeson (Value)-import Data.Aeson.Encode (fromValue)+import Data.Aeson.Types (Value(..))+import Numeric (showHex)+import qualified Data.HashMap.Strict as H+import qualified Data.Vector as V+import Data.Text.Lazy.Builder (singleton, fromString)+import qualified Data.Text as T+import Data.Scientific (FPFormat(..), Scientific, base10Exponent)+import Data.Text.Lazy.Builder.Scientific (formatScientificBuilder)  renderJavascript :: Javascript -> TL.Text renderJavascript (Javascript b) = toLazyText b@@ -80,7 +89,69 @@     toJavascript :: a -> Javascript  instance ToJavascript Bool where toJavascript = Javascript . fromText . TS.toLower . TS.pack . show-instance ToJavascript Value where toJavascript = Javascript . fromValue+instance ToJavascript Value where toJavascript = Javascript . encodeToTextBuilder++-- | Encode a JSON 'Value' to a "Data.Text" 'Builder', which can be+-- embedded efficiently in a text-based protocol.+--+-- If you are going to immediately encode straight to a+-- 'L.ByteString', it is more efficient to use 'encodeToBuilder'+-- instead.+encodeToTextBuilder :: Value -> Builder+encodeToTextBuilder =+    go+  where+    go Null       = {-# SCC "go/Null" #-} "null"+    go (Bool b)   = {-# SCC "go/Bool" #-} if b then "true" else "false"+    go (Number s) = {-# SCC "go/Number" #-} fromScientific s+    go (String s) = {-# SCC "go/String" #-} string s+    go (Array v)+        | V.null v = {-# SCC "go/Array" #-} "[]"+        | otherwise = {-# SCC "go/Array" #-}+                      singleton '[' <>+                      go (V.unsafeHead v) <>+                      V.foldr f (singleton ']') (V.unsafeTail v)+      where f a z = singleton ',' <> go a <> z+    go (Object m) = {-# SCC "go/Object" #-}+        case H.toList m of+          (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs+          _      -> "{}"+      where f a z     = singleton ',' <> one a <> z+            one (k,v) = string k <> singleton ':' <> go v++string :: T.Text -> Builder+string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'+  where+    quote q = case T.uncons t of+                Nothing      -> fromText h+                Just (!c,t') -> fromText h <> escape c <> quote t'+        where (h,t) = {-# SCC "break" #-} T.break isEscape q+    isEscape c = c == '\"' ||+                 c == '\\' ||+                 c == '<'  ||+                 c == '>'  ||+                 c == '&'  ||+                 c < '\x20'+    escape '\"' = "\\\""+    escape '\\' = "\\\\"+    escape '\n' = "\\n"+    escape '\r' = "\\r"+    escape '\t' = "\\t"+    escape '<' = "\\u003c"+    escape '>' = "\\u003e"+    escape '&' = "\\u0026"++    escape c+        | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h+        | otherwise  = singleton c+        where h = showHex (fromEnum c) ""++fromScientific :: Scientific -> Builder+fromScientific s = formatScientificBuilder format prec s+  where+    (format, prec)+      | base10Exponent s < 0 = (Generic, Nothing)+      | otherwise            = (Fixed,   Just 0)  newtype RawJavascript = RawJavascript Builder instance ToJavascript RawJavascript where
Text/MkSizeType.hs view
@@ -2,6 +2,8 @@ module Text.MkSizeType (mkSizeType) where  import Language.Haskell.TH.Syntax+import Data.Text.Lazy.Builder (fromLazyText)+import qualified Data.Text.Lazy as TL  mkSizeType :: String -> String -> Q [Dec] mkSizeType name' unit = return [ dataDec name@@ -39,11 +41,10 @@ toCssInstanceDec name = InstanceD [] (instanceType "ToCss" name) [toCssDec]   where toCssDec = FunD (mkName "toCss") [Clause [] showBody []]         showBody = NormalB $ (AppE dot from) `AppE` ((AppE dot pack) `AppE` show')-        -- FIXME this whole section makes me a little nervous-        from = VarE (mkName "fromLazyText")-        pack = VarE (mkName "TL.pack")-        dot = VarE (mkName ".")-        show' = VarE (mkName "show")+        from = VarE 'fromLazyText+        pack = VarE 'TL.pack+        dot = VarE 'Prelude.fmap+        show' = VarE 'Prelude.show  instanceType :: String -> Name -> Type instanceType className name = AppT (ConT $ mkName className) (ConT name)
shakespeare.cabal view
@@ -1,5 +1,5 @@ name:            shakespeare-version:         2.0.6+version:         2.0.7 license:         MIT license-file:    LICENSE author:          Michael Snoyman <michael@snoyman.com>@@ -49,6 +49,9 @@                    , blaze-html                    , exceptions                    , transformers+                   , vector+                   , unordered-containers+                   , scientific      exposed-modules: Text.Shakespeare.I18N                      Text.Shakespeare.Text
test/Text/Shakespeare/JsSpec.hs view
@@ -130,6 +130,12 @@ 
   it "JSON data" $ jelper "\"Hello \\\"World!\\\"\"" [julius|#{toJSON "Hello \"World!\""}|]
 
+  it "< escaping" $ jelper "\"\\u003c\"" [julius|#{toJSON "<"}|]
+
+  it "> escaping" $ jelper "\"\\u003e\"" [julius|#{toJSON ">"}|]
+
+  it "& escaping" $ jelper "\"\\u0026\"" [julius|#{toJSON "&"}|]
+
   it "boolean interpolation" $ jelper
     "true false true false true false"
     [julius|#{True} #{False} #{toJSON True} #{toJSON False} #{rawJS True} #{rawJS False}|]