Skip to content
Snippets Groups Projects
Unverified Commit 70d37dcb authored by stuebinm's avatar stuebinm
Browse files

support for properties that aren't strings

apparently i couldn't read or something?
parent ccb57f9a
No related branches found
No related tags found
No related merge requests found
...@@ -5,15 +5,16 @@ ...@@ -5,15 +5,16 @@
module Properties (checkProperty) where module Properties (checkProperty) where
import Control.Monad (unless) import Control.Monad (unless, when)
import Data.Text (Text, isPrefixOf) import Data.Text (Text, isPrefixOf)
import Tiled2 (Layer (layerProperties), Property, propertyName, import Tiled2 (Layer (layerProperties), Property(..), PropertyValue(..))
propertyValue)
import Util (prettyprint) import Util (prettyprint)
import LintWriter (LintWriter, complain, dependsOn, forbid, info, import LintWriter (LintWriter, complain, dependsOn, forbid, info,
suggest, warn) suggest, warn)
import Types import Types
-- | the point of this module -- | the point of this module
-- --
-- given a property, check if it is valid. It gets a reference -- given a property, check if it is valid. It gets a reference
...@@ -27,60 +28,75 @@ import Types ...@@ -27,60 +28,75 @@ import Types
-- that should make this readable even to non-Haskellers -- that should make this readable even to non-Haskellers
-- TODO: also pass the value of this property directly -- TODO: also pass the value of this property directly
checkProperty :: Layer -> Property -> LintWriter () checkProperty :: Layer -> Property -> LintWriter ()
checkProperty layer prop = case propName of checkProperty layer (Property name value) = case name of
"jitsiRoom" -> do "jitsiRoom" -> strProp $ do
info $ "found jitsi room: " <> prettyprint (propertyValue prop) info $ "found jitsi room: " <> prettyprint value
suggestPropertyValue "jitsiTrigger" "onaction" suggestPropertyValue "jitsiTrigger" "onaction"
"jitsiTrigger" -> "jitsiTrigger" -> strProp $ do
unless (hasProperty "jitsiTriggerMessage" layer)
$ suggest "set \"jitsiTriggerMessage\" to a custom message to overwrite the default \"press SPACE to enter in jitsi meet room\""
requireProperty "jitsiRoom" requireProperty "jitsiRoom"
"jitsiTriggerMessage" -> strProp
$ requireProperty "jitsiTrigger"
"jitsiUrl" -> isForbidden "jitsiUrl" -> isForbidden
"jitsiConfig" -> isForbidden "jitsiConfig" -> isForbidden
"jitsiClientConfig" -> isForbidden "jitsiClientConfig" -> isForbidden
"jitsiRoomAdminTag" -> isForbidden "jitsiRoomAdminTag" -> isForbidden
"playAudio" -> "playAudio" -> linkProp $ \link -> dependsOn $ if "https://" `isPrefixOf` link
forbidHTTPAndThen $ dependsOn $ if "https://" `isPrefixOf` propValue then Link link
then Link propValue else Local link
else Local propValue
"audioLoop" -> "audioLoop" ->
requireProperty "playAudio" boolProp $ requireProperty "playAudio"
"audioVolume" -> "audioVolume" ->
requireProperty "playAudio" boolProp $ requireProperty "playAudio"
"openWebsite" -> do "openWebsite" -> do
suggestPropertyValue "openWebsiteTrigger" "onaction" suggestPropertyValue "openWebsiteTrigger" "onaction"
if "http://" `isPrefixOf` propValue linkProp $ \link -> dependsOn $ if "https://" `isPrefixOf` link
then complain "cannot load content over http into map, please use https or include your assets locally" then Link link
else dependsOn $ else Local link
if "https://" `isPrefixOf` propValue "openWebsiteTrigger" -> strProp $ do
then Link propValue unless (hasProperty "openWebsiteTriggerMessage" layer)
else Local propValue $ suggest "set \"openWebsiteTriggerMessage\" to a custom message to overwrite the generic \"press SPACE to open Website\""
"openWebsiteTrigger" ->
requireProperty "openWebsite" requireProperty "openWebsite"
"openWebsiteTriggerMessage" ->
strProp $ requireProperty "openWebsiteTrigger"
"openWebsitePolicy" -> "openWebsitePolicy" ->
requireProperty "openWebsite" strProp $ requireProperty "openWebsite"
"exitUrl" -> "openTab" ->
forbidHTTPAndThen $ dependsOn $ if "https://" `isPrefixOf` propValue strProp $ requireProperty "openWebsite"
then MapLink propValue "url" -> isForbidden
else LocalMap propValue "allowApi" -> isForbidden
"startLayer" -> pure () "exitUrl" -> linkProp $ \link -> dependsOn $ if "https://" `isPrefixOf` link
then MapLink link
else LocalMap link
"startLayer" ->
isForbidden
"silent" -> boolProp $ pure ()
-- could also make this a "hard error" (i.e. Left), but then it -- could also make this a "hard error" (i.e. Left), but then it
-- stops checking other properties as checkLayer short-circuits. -- stops checking other properties as checkLayer short-circuits.
_ -> warn $ "unknown property type " <> prettyprint propName _ -> warn $ "unknown property type " <> prettyprint name
where where
propName = propertyName prop strProp :: LintWriter () -> LintWriter ()
propValue = propertyValue prop strProp andthen = case value of
StrProp _ -> andthen
_ -> complain $ "type mismatch in property " <> name <> "; should be of type string"
linkProp f = case value of
StrProp str -> if "http://" `isPrefixOf` str
then complain "cannot access content via http; either use https or include it locally instead."
else f str
_ -> complain $ "type mismatch in property " <> name <> "; should be of typ string"
boolProp f = case value of
BoolProp _ -> f
_ -> complain $ "type mismatch in property " <> name <> "; should be of type bool"
-- | require some property in this layer -- | require some property in this layer
requireProperty name = unless (hasProperty name layer) requireProperty name = unless (hasProperty name layer)
$ complain $ "property "<>prettyprint name<>" requires property "<>prettyprint propName $ complain $ "property "<>prettyprint name<>" requires property "<>prettyprint name
-- | This property is forbidden and should not be used -- | This property is forbidden and should not be used
isForbidden = forbid $ "property " <> prettyprint propName <> " should not be used" isForbidden = forbid $ "property " <> prettyprint name <> " should not be used"
-- TODO: check if the property has the correct value -- TODO: check if the property has the correct value
suggestPropertyValue :: Text -> Text -> LintWriter () suggestPropertyValue :: Text -> Text -> LintWriter ()
suggestPropertyValue name value = unless (hasProperty name layer) suggestPropertyValue name value = unless (hasProperty name layer)
$ suggest $ "set property " <> prettyprint name <> " to " <> prettyprint value $ suggest $ "set property " <> prettyprint name <> " to " <> prettyprint value
forbidHTTPAndThen :: LintWriter () -> LintWriter ()
forbidHTTPAndThen andthen = if "http://" `isPrefixOf` propValue
then complain "cannot access content via http; either use https or include it locally instead."
else andthen
...@@ -88,5 +104,5 @@ checkProperty layer prop = case propName of ...@@ -88,5 +104,5 @@ checkProperty layer prop = case propName of
-- | does this layer have the given property? -- | does this layer have the given property?
hasProperty :: Text -> Layer -> Bool hasProperty :: Text -> Layer -> Bool
hasProperty name = any hasProperty name = any
(\prop -> propertyName prop == name) (\(Property name' _) -> name' == name)
. layerProperties . layerProperties
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
...@@ -24,6 +25,7 @@ import Data.Text (Text) ...@@ -24,6 +25,7 @@ import Data.Text (Text)
import Data.Vector (Vector) import Data.Vector (Vector)
import GHC.Exts (fromList, toList) import GHC.Exts (fromList, toList)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Data.Functor ((<&>))
-- | A globally indexed identifier. -- | A globally indexed identifier.
...@@ -67,27 +69,41 @@ parseDefault :: FromJSON a => A.Object -> Text -> a -> Parser a ...@@ -67,27 +69,41 @@ parseDefault :: FromJSON a => A.Object -> Text -> a -> Parser a
parseDefault o s d = fromMaybe d <$> o .:? s parseDefault o s d = fromMaybe d <$> o .:? s
-- | workadventure custom property {-- | workadventure custom property
data Property = Property { propertyName :: Text data Property = Property { propertyName :: Text
--, propertyType :: Text (unnecessary since always string) --, propertyType :: Text (unnecessary since always string)
, propertyValue :: Text , propertyValue :: Text
} deriving (Eq, Generic, Show) } deriving (Eq, Generic, Show)
-}
data PropertyValue = StrProp Text | BoolProp Bool
deriving (Eq, Generic, Show)
data Property = Property Text PropertyValue
deriving (Eq, Generic, Show)
instance FromJSON Property where instance FromJSON Property where
parseJSON (A.Object o) = do parseJSON (A.Object o) = do
propertyType <- o .: "type" name <- o .: "name"
if propertyType /= A.String "string" o .: "type" >>= \case
then typeMismatch "type" "string" A.String "string" -> do
else do val <- o .: "value"
propertyName <- o .: "name" pure $ Property name (StrProp val)
propertyValue <- o .: "value" A.String "bool" -> do
pure $ Property { propertyName, propertyValue } val <- o .: "value"
pure $ Property name (BoolProp val)
ty -> fail $ "properties can only have type string or bool, but encountered " <> show ty
parseJSON invalid = typeMismatch "Property" invalid parseJSON invalid = typeMismatch "Property" invalid
instance ToJSON Property where instance ToJSON Property where
toJSON prop = object [ "type" .= A.String "string" toJSON (Property name val) = case val of
, "name" .= propertyName prop StrProp str -> object [ "type" .= A.String "string"
, "value" .= propertyName prop , "name" .= name
, "value" .= str
]
BoolProp bool -> object [ "type" .= A.String "bool"
, "name" .= name
, "value" .= bool
] ]
data Object = Object { objectId :: Int data Object = Object { objectId :: Int
...@@ -196,7 +212,7 @@ instance FromJSON Layer where ...@@ -196,7 +212,7 @@ instance FromJSON Layer where
<*> o .: "y" <*> o .: "y"
<*> (o .: "data" <|> pure Nothing) <*> (o .: "data" <|> pure Nothing)
<*> o .:? "objects" <*> o .:? "objects"
<*> (o .: "properties" <|> pure mempty) <*> (o .:? "properties" <&> fromMaybe [])
<*> o .: "opacity" <*> o .: "opacity"
<*> (o .: "draworder" <|> pure "topdown") <*> (o .: "draworder" <|> pure "topdown")
parseJSON invalid = typeMismatch "Layer" invalid parseJSON invalid = typeMismatch "Layer" invalid
......
...@@ -16,6 +16,7 @@ import GHC.Generics (Generic) ...@@ -16,6 +16,7 @@ import GHC.Generics (Generic)
import qualified Data.Aeson as A import qualified Data.Aeson as A
import Util (PrettyPrint (..), showText) import Util (PrettyPrint (..), showText)
import Tiled2 (Property(Property), PropertyValue (BoolProp, StrProp))
-- | Levels of errors and warnings, collectively called -- | Levels of errors and warnings, collectively called
......
...@@ -9,6 +9,7 @@ module Util where ...@@ -9,6 +9,7 @@ module Util where
import Data.Aeson as Aeson import Data.Aeson as Aeson
import Data.Text (Text) import Data.Text (Text)
import qualified Data.Text as T import qualified Data.Text as T
import Tiled2 (PropertyValue(..))
-- | haskell's many string types are FUN … -- | haskell's many string types are FUN …
showText :: Show a => a -> Text showText :: Show a => a -> Text
...@@ -29,6 +30,11 @@ instance PrettyPrint Aeson.Value where ...@@ -29,6 +30,11 @@ instance PrettyPrint Aeson.Value where
Aeson.String s -> prettyprint s Aeson.String s -> prettyprint s
v -> (T.pack . show) v v -> (T.pack . show) v
instance PrettyPrint PropertyValue where
prettyprint = \case
StrProp str -> str
BoolProp bool -> if bool then "true" else "false"
-- | here since Unit is sometimes used as dummy type -- | here since Unit is sometimes used as dummy type
instance PrettyPrint () where instance PrettyPrint () where
prettyprint _ = error "shouldn't pretty-print Unit" prettyprint _ = error "shouldn't pretty-print Unit"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment