diff --git a/yesod-core/ChangeLog.md b/yesod-core/ChangeLog.md index 4788b2ec..67f9cf9c 100644 --- a/yesod-core/ChangeLog.md +++ b/yesod-core/ChangeLog.md @@ -1,5 +1,9 @@ # ChangeLog for yesod-core +## 1.6.8 +* In the route syntax, allow trailing backslashes to indicate line + continuation. [#1558](https://github.com/yesodweb/yesod/pull/1558) + ## 1.6.7 * If no matches are found, `selectRep` chooses first representation regardless diff --git a/yesod-core/Yesod/Routes/Parse.hs b/yesod-core/Yesod/Routes/Parse.hs index e372fc0f..dcc9e501 100644 --- a/yesod-core/Yesod/Routes/Parse.hs +++ b/yesod-core/Yesod/Routes/Parse.hs @@ -65,7 +65,7 @@ parseRoutesNoCheck = QuasiQuoter -- invalid input. resourcesFromString :: String -> [ResourceTree String] resourcesFromString = - fst . parse 0 . filter (not . all (== ' ')) . lines . filter (/= '\r') + fst . parse 0 . filter (not . all (== ' ')) . foldr lineContinuations [] . lines . filter (/= '\r') where parse _ [] = ([], []) parse indent (thisLine:otherLines) @@ -285,3 +285,12 @@ dropBracket str@('{':x) = case break (== '}') x of _ -> error $ "Unclosed bracket ('{'): " ++ str dropBracket x = x +-- | If this line ends with a backslash, concatenate it together with the next line. +-- +-- @since 1.6.8 +lineContinuations :: String -> [String] -> [String] +lineContinuations this [] = [this] +lineContinuations this below@(next:rest) = case unsnoc this of + Just (this', '\\') -> (this'++next):rest + _ -> this:below + where unsnoc s = if null s then Nothing else Just (init s, last s) diff --git a/yesod-core/test/RouteSpec.hs b/yesod-core/test/RouteSpec.hs index c5c7be66..db8ac92d 100644 --- a/yesod-core/test/RouteSpec.hs +++ b/yesod-core/test/RouteSpec.hs @@ -17,7 +17,7 @@ import Test.HUnit ((@?=)) import Data.Text (Text, pack, unpack, singleton) import Yesod.Routes.Class hiding (Route) import qualified Yesod.Routes.Class as YRC -import Yesod.Routes.Parse (parseRoutesNoCheck, parseTypeTree, TypeTree (..)) +import Yesod.Routes.Parse (parseRoutesFile, parseRoutesNoCheck, parseTypeTree, TypeTree (..)) import Yesod.Routes.Overlap (findOverlapNames) import Yesod.Routes.TH hiding (Dispatch) import Language.Haskell.TH.Syntax @@ -219,11 +219,17 @@ main = hspec $ do it "routes to subparam" $ disp "PUT" ["subparam", "6", "q"] @?= (pack "subparam 6 q", Just $ SubparamR 6 $ ParamRoute 'q') - describe "parsing" $ do + describe "route parsing" $ do it "subsites work" $ do parseRoute ([pack "subsite", pack "foo"], [(pack "bar", pack "baz")]) @?= Just (SubsiteR $ MySubRoute ([pack "foo"], [(pack "bar", pack "baz")])) + describe "routing table parsing" $ do + it "recognizes trailing backslashes as line continuation directives" $ do + let routes :: [ResourceTree String] + routes = $(parseRoutesFile "test/fixtures/routes_with_line_continuations") + length routes @?= 3 + describe "overlap checking" $ do it "catches overlapping statics" $ do let routes :: [ResourceTree String] diff --git a/yesod-core/test/fixtures/routes_with_line_continuations b/yesod-core/test/fixtures/routes_with_line_continuations new file mode 100644 index 00000000..9f035ff5 --- /dev/null +++ b/yesod-core/test/fixtures/routes_with_line_continuations @@ -0,0 +1,11 @@ +-- This fixture to test line continuations is in a separate file +-- because when I put it in an in-line quasi-quotation, the compiler +-- performed the line continuations processing itself. + +/foo1 \ + Foo1 +/foo2 Foo2 +/foo3 \ + Foo3 \ + GET POST \ + !foo diff --git a/yesod-core/yesod-core.cabal b/yesod-core/yesod-core.cabal index 83eb5f7a..95cbe114 100644 --- a/yesod-core/yesod-core.cabal +++ b/yesod-core/yesod-core.cabal @@ -1,5 +1,5 @@ name: yesod-core -version: 1.6.7 +version: 1.6.8 license: MIT license-file: LICENSE author: Michael Snoyman