git.iko.soy/typeable/pandoc
on master help sign in
Fix regression: markdown references should be case-insensitive.

This broke when we added the Key type. We had assumed that the custom case-insensitive Ord instance would ensure case-insensitive matching, but that is not how Data.Map works. * Added a test case for case-insensitivity in markdown-reader-more * Removed old refsMatch from Text.Pandoc.Parsing module; * hid the 'Key' constructor; * dropped the custom Ord and Eq instances, deriving instead; * added fromKey and toKey to convert between Keys and Inline lists; * toKey ensures that keys are case-insensitive, since this is the only way the API provides to construct a Key. Resolves Issue #272.

commit5a4609584c84114e8d148f558bed86353c7f0146 authorJohn MacFarlane <jgm@berkeley.edu> dateSun 5 Dec 2010, 19:27 (16 years ago) parent37dc5d8
5 files changed+42−48
src/Text/Pandoc/Parsing.hs+17−38 src/Text/Pandoc/Readers/Markdown.hs+2−2 src/Text/Pandoc/Readers/RST.hs+8−7 tests/markdown-reader-more.native+5−1 tests/markdown-reader-more.txt+10
src/Text/Pandoc/Parsing.hs+17−38
@@ -64,9 +64,10 @@ module Text.Pandoc.Parsing ( (>>~),
6464 QuoteContext (..),
6565 NoteTable,
6666 KeyTable,
67− Key (..),
68− lookupKeySrc,
69− refsMatch )
67+ Key,
68+ toKey,
69+ fromKey,
70+ lookupKeySrc )
7071where
7172
7273import Text.Pandoc.Definition
@@ -651,13 +652,21 @@ data QuoteContext
651652
652653type NoteTable = [(String, String)]
653654
654−newtype Key = Key [Inline] deriving (Show, Read)
655+newtype Key = Key [Inline] deriving (Show, Read, Eq, Ord)
655656
656−instance Eq Key where
657− Key a == Key b = refsMatch a b
657+toKey :: [Inline] -> Key
658+toKey = Key . processWith lowercase
659+ where lowercase :: Inline -> Inline
660+ lowercase (Str xs) = Str (map toLower xs)
661+ lowercase (Math t xs) = Math t (map toLower xs)
662+ lowercase (Code xs) = Code (map toLower xs)
663+ lowercase (TeX xs) = TeX (map toLower xs)
664+ lowercase (HtmlInline xs) = HtmlInline (map toLower xs)
665+ lowercase LineBreak = Space
666+ lowercase x = x
658667
659−instance Ord Key where
660− compare (Key a) (Key b) = if a == b then EQ else compare a b
668+fromKey :: Key -> [Inline]
669+fromKey (Key xs) = xs
661670
662671type KeyTable = M.Map Key Target
663672
@@ -669,33 +678,3 @@ lookupKeySrc table key = case M.lookup key table of
669678 Nothing -> Nothing
670679 Just src -> Just src
671680
672−-- | Returns @True@ if keys match (case insensitive).
673−refsMatch :: [Inline] -> [Inline] -> Bool
674−refsMatch ((Str x):restx) ((Str y):resty) =
675− ((map toLower x) == (map toLower y)) && refsMatch restx resty
676−refsMatch ((Emph x):restx) ((Emph y):resty) =
677− refsMatch x y && refsMatch restx resty
678−refsMatch ((Strong x):restx) ((Strong y):resty) =
679− refsMatch x y && refsMatch restx resty
680−refsMatch ((Strikeout x):restx) ((Strikeout y):resty) =
681− refsMatch x y && refsMatch restx resty
682−refsMatch ((Superscript x):restx) ((Superscript y):resty) =
683− refsMatch x y && refsMatch restx resty
684−refsMatch ((Subscript x):restx) ((Subscript y):resty) =
685− refsMatch x y && refsMatch restx resty
686−refsMatch ((SmallCaps x):restx) ((SmallCaps y):resty) =
687− refsMatch x y && refsMatch restx resty
688−refsMatch ((Quoted t x):restx) ((Quoted u y):resty) =
689− t == u && refsMatch x y && refsMatch restx resty
690−refsMatch ((Code x):restx) ((Code y):resty) =
691− ((map toLower x) == (map toLower y)) && refsMatch restx resty
692−refsMatch ((Math t x):restx) ((Math u y):resty) =
693− ((map toLower x) == (map toLower y)) && t == u && refsMatch restx resty
694−refsMatch ((TeX x):restx) ((TeX y):resty) =
695− ((map toLower x) == (map toLower y)) && refsMatch restx resty
696−refsMatch ((HtmlInline x):restx) ((HtmlInline y):resty) =
697− ((map toLower x) == (map toLower y)) && refsMatch restx resty
698−refsMatch (x:restx) (y:resty) = (x == y) && refsMatch restx resty
699−refsMatch [] x = null x
700−refsMatch x [] = null x
701−
src/Text/Pandoc/Readers/Markdown.hs+2−2
@@ -220,7 +220,7 @@ referenceKey = try $ do
220220 let target = (escapeURI $ removeTrailingSpace src, tit)
221221 st <- getState
222222 let oldkeys = stateKeys st
223− updateState $ \s -> s { stateKeys = M.insert (Key lab) target oldkeys }
223+ updateState $ \s -> s { stateKeys = M.insert (toKey lab) target oldkeys }
224224 -- return blanks so line count isn't affected
225225 return $ replicate (sourceLine endPos - sourceLine startPos) '\n'
226226
@@ -1237,7 +1237,7 @@ referenceLink lab = do
12371237 optional (newline >> skipSpaces) >> reference))
12381238 let ref' = if null ref then lab else ref
12391239 state <- getState
1240− case lookupKeySrc (stateKeys state) (Key ref') of
1240+ case lookupKeySrc (stateKeys state) (toKey ref') of
12411241 Nothing -> fail "no corresponding key"
12421242 Just target -> return target
12431243
src/Text/Pandoc/Readers/RST.hs+8−7
@@ -565,14 +565,14 @@ imageKey = try $ do
565565 skipSpaces
566566 string "image::"
567567 src <- targetURI
568− return (Key (normalizeSpaces ref), (src, ""))
568+ return (toKey (normalizeSpaces ref), (src, ""))
569569
570570anonymousKey :: GenParser Char st (Key, Target)
571571anonymousKey = try $ do
572572 oneOfStrings [".. __:", "__"]
573573 src <- targetURI
574574 pos <- getPosition
575− return (Key [Str $ "_" ++ printf "%09d" (sourceLine pos)], (src, ""))
575+ return (toKey [Str $ "_" ++ printf "%09d" (sourceLine pos)], (src, ""))
576576
577577regularKey :: GenParser Char ParserState (Key, Target)
578578regularKey = try $ do
@@ -580,7 +580,7 @@ regularKey = try $ do
580580 ref <- referenceName
581581 char ':'
582582 src <- targetURI
583− return (Key (normalizeSpaces ref), (src, ""))
583+ return (toKey (normalizeSpaces ref), (src, ""))
584584
585585--
586586-- tables
@@ -779,9 +779,10 @@ referenceLink = try $ do
779779 label' <- (quotedReferenceName <|> simpleReferenceName) >>~ char '_'
780780 state <- getState
781781 let keyTable = stateKeys state
782− let isAnonKey (Key [Str ('_':_)]) = True
783− isAnonKey _ = False
784− key <- option (Key label') $
782+ let isAnonKey x = case fromKey x of
783+ [Str ('_':_)] -> True
784+ _ -> False
785+ key <- option (toKey label') $
785786 do char '_'
786787 let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
787788 if null anonKeys
@@ -814,7 +815,7 @@ image = try $ do
814815 ref <- manyTill inline (char '|')
815816 state <- getState
816817 let keyTable = stateKeys state
817− (src,tit) <- case lookupKeySrc keyTable (Key ref) of
818+ (src,tit) <- case lookupKeySrc keyTable (toKey ref) of
818819 Nothing -> fail "no corresponding key"
819820 Just target -> return target
820821 return $ Image (normalizeSpaces ref) (src, tit)
tests/markdown-reader-more.native+5−1
@@ -41,4 +41,8 @@ Pandoc (Meta {docTitle = [Str "Title",Space,Str "spanning",Space,Str "multiple",
4141 [ [ Plain [Str "Third",Space,Str "example",Str "."] ]
4242 ]
4343, Header 2 [Str "Macros"]
44−, Para [Math InlineMath "\\langle x,y \\rangle"] ]
44+, Para [Math InlineMath "\\langle x,y \\rangle"]
45+, Header 2 [Str "Case",Str "-",Str "insensitive",Space,Str "references"]
46+, Para [Link [Str "Fum"] ("/fum","")]
47+, Para [Link [Str "FUM"] ("/fum","")]
48+, Para [Link [Str "bat"] ("/bat","")] ]
tests/markdown-reader-more.txt+10
@@ -106,3 +106,13 @@ Explanation of examples (@foo) and (@bar).
106106
107107$\tuple{x,y}$
108108
109+## Case-insensitive references
110+
111+[Fum]
112+
113+[FUM]
114+
115+[bat]
116+
117+[fum]: /fum
118+[BAT]: /bat