Fix indirect hyperlink targets. Closes #512.
This commit is contained in:
parent
ebe4072bd9
commit
575014975e
2 changed files with 74 additions and 23 deletions
|
@ -1232,43 +1232,53 @@ explicitLink = try $ do
|
||||||
then B.str src
|
then B.str src
|
||||||
else label'
|
else label'
|
||||||
-- `link <google_>` is a reference link to _google!
|
-- `link <google_>` is a reference link to _google!
|
||||||
(src',tit,attr) <- case reverse src of
|
((src',tit),attr) <- case reverse src of
|
||||||
'_':xs -> do
|
'_':xs -> lookupKey [] (toKey (reverse xs))
|
||||||
keyTable <- stateKeys <$> getState
|
_ -> return ((src, ""), nullAttr)
|
||||||
let key = toKey $ reverse xs
|
|
||||||
case M.lookup key keyTable of
|
|
||||||
Nothing -> do
|
|
||||||
pos <- getPosition
|
|
||||||
report $ ReferenceNotFound (show key) pos
|
|
||||||
return ("","",nullAttr)
|
|
||||||
Just ((s,t),a) -> return (s,t,a)
|
|
||||||
_ -> return (src, "", nullAttr)
|
|
||||||
return $ B.linkWith attr (escapeURI src') tit label''
|
return $ B.linkWith attr (escapeURI src') tit label''
|
||||||
|
|
||||||
referenceLink :: PandocMonad m => RSTParser m Inlines
|
referenceLink :: PandocMonad m => RSTParser m Inlines
|
||||||
referenceLink = try $ do
|
referenceLink = try $ do
|
||||||
(label',ref) <- withRaw (quotedReferenceName <|> simpleReferenceName) <*
|
(label',ref) <- withRaw (quotedReferenceName <|> simpleReferenceName) <*
|
||||||
char '_'
|
char '_'
|
||||||
state <- getState
|
|
||||||
let keyTable = stateKeys state
|
|
||||||
let isAnonKey (Key ('_':_)) = True
|
let isAnonKey (Key ('_':_)) = True
|
||||||
isAnonKey _ = False
|
isAnonKey _ = False
|
||||||
|
state <- getState
|
||||||
|
let keyTable = stateKeys state
|
||||||
key <- option (toKey $ stripTicks ref) $
|
key <- option (toKey $ stripTicks ref) $
|
||||||
do char '_'
|
do char '_'
|
||||||
let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
|
let anonKeys = sort $ filter isAnonKey $ M.keys keyTable
|
||||||
if null anonKeys
|
case anonKeys of
|
||||||
then mzero
|
[] -> mzero
|
||||||
else return (head anonKeys)
|
(k:_) -> return k
|
||||||
((src,tit), attr) <- case M.lookup key keyTable of
|
((src,tit), attr) <- lookupKey [] key
|
||||||
Nothing -> do
|
|
||||||
pos <- getPosition
|
|
||||||
report $ ReferenceNotFound (show key) pos
|
|
||||||
return (("",""),nullAttr)
|
|
||||||
Just val -> return val
|
|
||||||
-- if anonymous link, remove key so it won't be used again
|
-- if anonymous link, remove key so it won't be used again
|
||||||
when (isAnonKey key) $ updateState $ \s -> s{ stateKeys = M.delete key keyTable }
|
when (isAnonKey key) $ updateState $ \s -> s{ stateKeys = M.delete key keyTable }
|
||||||
return $ B.linkWith attr src tit label'
|
return $ B.linkWith attr src tit label'
|
||||||
|
|
||||||
|
-- We keep a list of oldkeys so we can detect lookup loops.
|
||||||
|
lookupKey :: PandocMonad m
|
||||||
|
=> [Key] -> Key -> RSTParser m ((String, String), Attr)
|
||||||
|
lookupKey oldkeys key = do
|
||||||
|
pos <- getPosition
|
||||||
|
state <- getState
|
||||||
|
let keyTable = stateKeys state
|
||||||
|
case M.lookup key keyTable of
|
||||||
|
Nothing -> do
|
||||||
|
let Key key' = key
|
||||||
|
report $ ReferenceNotFound key' pos
|
||||||
|
return (("",""),nullAttr)
|
||||||
|
-- check for keys of the form link_, which need to be resolved:
|
||||||
|
Just ((u@(_:_),""),_) | last u == '_' -> do
|
||||||
|
let rawkey = init u
|
||||||
|
let newkey = toKey rawkey
|
||||||
|
if newkey `elem` oldkeys
|
||||||
|
then do
|
||||||
|
report $ CircularReference rawkey pos
|
||||||
|
return (("",""),nullAttr)
|
||||||
|
else lookupKey (key:oldkeys) newkey
|
||||||
|
Just val -> return val
|
||||||
|
|
||||||
autoURI :: Monad m => RSTParser m Inlines
|
autoURI :: Monad m => RSTParser m Inlines
|
||||||
autoURI = do
|
autoURI = do
|
||||||
(orig, src) <- uri
|
(orig, src) <- uri
|
||||||
|
@ -1305,7 +1315,7 @@ note = try $ do
|
||||||
case lookup ref notes of
|
case lookup ref notes of
|
||||||
Nothing -> do
|
Nothing -> do
|
||||||
pos <- getPosition
|
pos <- getPosition
|
||||||
report $ ReferenceNotFound (show ref) pos
|
report $ ReferenceNotFound ref pos
|
||||||
return mempty
|
return mempty
|
||||||
Just raw -> do
|
Just raw -> do
|
||||||
-- We temporarily empty the note list while parsing the note,
|
-- We temporarily empty the note list while parsing the note,
|
||||||
|
|
41
test/command/512.md
Normal file
41
test/command/512.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
```
|
||||||
|
% pandoc -f rst
|
||||||
|
`click here`__ or `click here`__
|
||||||
|
|
||||||
|
.. _link1: http://www.example.com/
|
||||||
|
.. _link2: http://johnmacfarlane.net/pandoc/
|
||||||
|
|
||||||
|
__ link1_
|
||||||
|
__ link2_
|
||||||
|
^D
|
||||||
|
<p><a href="http://www.example.com/">click here</a> or <a href="http://johnmacfarlane.net/pandoc/">click here</a></p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple indirection:
|
||||||
|
|
||||||
|
```
|
||||||
|
% pandoc -f rst
|
||||||
|
`click here`__
|
||||||
|
|
||||||
|
.. _link1: link2_
|
||||||
|
.. _link2: http://johnmacfarlane.net/pandoc/
|
||||||
|
|
||||||
|
__ link1_
|
||||||
|
^D
|
||||||
|
<p><a href="http://johnmacfarlane.net/pandoc/">click here</a></p>
|
||||||
|
```
|
||||||
|
|
||||||
|
Loop detection:
|
||||||
|
|
||||||
|
```
|
||||||
|
% pandoc -f rst
|
||||||
|
`click here`__
|
||||||
|
|
||||||
|
.. _link1: link2_
|
||||||
|
.. _link2: link1_
|
||||||
|
|
||||||
|
__ link1_
|
||||||
|
^D
|
||||||
|
<p><a href="">click here</a></p>
|
||||||
|
```
|
||||||
|
|
Loading…
Add table
Reference in a new issue