@@ -4,12 +4,15 @@
44module Hakyll.Core.Provider.Metadata
55 ( loadMetadata
66 , parsePage
7+
8+ , MetadataException (..)
79 ) where
810
911
1012--------------------------------------------------------------------------------
1113import Control.Applicative
1214import Control.Arrow (second)
15+import Control.Exception (Exception, throwIO)
1316import Control.Monad (guard)
1417import qualified Data.ByteString.Char8 as BC
1518import qualified Data.HashMap.Strict as HMS
@@ -52,7 +55,9 @@ loadMetadata p identifier = do
5255loadMetadataHeader :: FilePath -> IO (Metadata, String)
5356loadMetadataHeader fp = do
5457 fileContent <- readFile fp
55− either fail return (parsePage fileContent)
58+ case parsePage fileContent of
59+ Right x -> return x
60+ Left err -> throwIO $ MetadataException fp err
5661
5762
5863--------------------------------------------------------------------------------
@@ -82,11 +87,15 @@ probablyHasMetadataHeader fp = do
8287splitMetadata :: String -> (Maybe String, String)
8388splitMetadata str0 = fromMaybe (Nothing, str0) $ do
8489 guard $ leading >= 3
85− let !(!meta, !content0) = breakWhen isTrailing (drop leading str0)
90+ let !str1 = drop leading str0
91+ guard $ all isNewline (take 1 str1)
92+ let !(!meta, !content0) = breakWhen isTrailing str1
8693 guard $ not $ null content0
8794 let !content1 = drop (leading + 1) content0
8895 !content2 = dropWhile isNewline $ dropWhile isInlineSpace content1
89− return (Just meta, content2)
96+ -- Adding this newline fixes the line numbers reported by the YAML parser.
97+ -- It's a bit ugly but it works.
98+ return (Just ('\n' : meta), content2)
9099 where
91100 -- Parse the leading "---"
92101 !leading = length $ takeWhile (== '-') str0
@@ -103,12 +112,12 @@ splitMetadata str0 = fromMaybe (Nothing, str0) $ do
103112
104113
105114--------------------------------------------------------------------------------
106−parseMetadata :: String -> Either String Metadata
107−parseMetadata = Yaml.decodeEither . T.encodeUtf8 . T.pack
115+parseMetadata :: String -> Either Yaml.ParseException Metadata
116+parseMetadata = Yaml.decodeEither' . T.encodeUtf8 . T.pack
108117
109118
110119--------------------------------------------------------------------------------
111−parsePage :: String -> Either String (Metadata, String)
120+parsePage :: String -> Either Yaml.ParseException (Metadata, String)
112121parsePage fileContent = case mbMetaBlock of
113122 Nothing -> return (mempty, content)
114123 Just metaBlock -> case parseMetadata metaBlock of
@@ -116,3 +125,19 @@ parsePage fileContent = case mbMetaBlock of
116125 Right meta -> return (meta, content)
117126 where
118127 !(!mbMetaBlock, !content) = splitMetadata fileContent
128+
129+
130+--------------------------------------------------------------------------------
131+-- | Thrown in the IO monad if things go wrong. Provides a nice-ish error
132+-- message.
133+data MetadataException = MetadataException FilePath Yaml.ParseException
134+
135+
136+--------------------------------------------------------------------------------
137+instance Exception MetadataException
138+
139+
140+--------------------------------------------------------------------------------
141+instance Show MetadataException where
142+ show (MetadataException fp err) =
143+ fp ++ ": " ++ Yaml.prettyPrintParseException err