diff --git a/yesod-core/Yesod/Routes/Parse.hs b/yesod-core/Yesod/Routes/Parse.hs index e372fc0f..5b325590 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,10 @@ 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. +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