From daaf635806fba3ec459da3c2c97301920cea1270 Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Wed, 5 Nov 2014 22:27:25 +0100 Subject: Org reader: absolute, relative paths in links The org reader was to restrictive when parsing links, some relative links and links to files given as absolute paths were not recognized correctly. The org reader's link parsing function was amended to handle such cases properly. This fixes #1741 --- src/Text/Pandoc/Readers/Org.hs | 33 +++++++++++++++++++-------------- tests/Tests/Readers/Org.hs | 8 ++++++++ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/Text/Pandoc/Readers/Org.hs b/src/Text/Pandoc/Readers/Org.hs index 1ddfeab87..2f149765e 100644 --- a/src/Text/Pandoc/Readers/Org.hs +++ b/src/Text/Pandoc/Readers/Org.hs @@ -1139,27 +1139,32 @@ applyCustomLinkFormat link = do formatter <- M.lookup linkType <$> asksF orgStateLinkFormatters return $ maybe link ($ drop 1 rest) formatter - linkToInlinesF :: String -> Inlines -> F Inlines -linkToInlinesF s@('#':_) = pure . B.link s "" -linkToInlinesF s - | isImageFilename s = const . pure $ B.image s "" "" - | isUri s = pure . B.link s "" - | isRelativeUrl s = pure . B.link s "" -linkToInlinesF s = \title -> do - anchorB <- (s `elem`) <$> asksF orgStateAnchorIds - if anchorB - then pure $ B.link ('#':s) "" title - else pure $ B.emph title - -isRelativeUrl :: String -> Bool -isRelativeUrl s = (':' `notElem` s) && ("./" `isPrefixOf` s) +linkToInlinesF s = + case s of + ('#':_) -> pure . B.link s "" + _ | isImageFilename s -> const . pure $ B.image s "" "" + _ | isUri s -> pure . B.link s "" + _ | isRelativeFilePath s -> pure . B.link s "" + _ | isAbsoluteFilePath s -> pure . B.link ("file://" ++ s) "" + _ -> \title -> do + anchorB <- (s `elem`) <$> asksF orgStateAnchorIds + if anchorB + then pure $ B.link ('#':s) "" title + else pure $ B.emph title + +isRelativeFilePath :: String -> Bool +isRelativeFilePath s = (("./" `isPrefixOf` s) || ("../" `isPrefixOf` s)) && + (':' `notElem` s) isUri :: String -> Bool isUri s = let (scheme, path) = break (== ':') s in all (\c -> isAlphaNum c || c `elem` ".-") scheme && not (null path) +isAbsoluteFilePath :: String -> Bool +isAbsoluteFilePath = ('/' ==) . head + isImageFilename :: String -> Bool isImageFilename filename = any (\x -> ('.':x) `isSuffixOf` filename) imageExtensions && diff --git a/tests/Tests/Readers/Org.hs b/tests/Tests/Readers/Org.hs index 392388ec0..fd337f760 100644 --- a/tests/Tests/Readers/Org.hs +++ b/tests/Tests/Readers/Org.hs @@ -197,6 +197,14 @@ tests = "[[http://zeitlens.com/]]" =?> (para $ link "http://zeitlens.com/" "" "http://zeitlens.com/") + , "Absolute file link" =: + "[[/url][hi]]" =?> + (para $ link "file:///url" "" "hi") + + , "Link to file in parent directory" =: + "[[../file.txt][moin]]" =?> + (para $ link "../file.txt" "" "moin") + , "Image link" =: "[[sunset.png][dusk.svg]]" =?> (para $ link "sunset.png" "" (image "dusk.svg" "" "")) -- cgit v1.2.3 From e6cd8c907788c083adea5e00def8918b11553f2b Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Wed, 5 Nov 2014 22:49:17 +0100 Subject: Org reader: allow empty links for gitit interop While empty links are not allowed in Emacs org-mode, Pandoc org-mode should support them: gitit relies on empty links as they are used to create wiki links. Fixes jgm/gitit#471 --- src/Text/Pandoc/Readers/Org.hs | 6 +++++- tests/Tests/Readers/Org.hs | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Text/Pandoc/Readers/Org.hs b/src/Text/Pandoc/Readers/Org.hs index 2f149765e..4c34b7bd5 100644 --- a/src/Text/Pandoc/Readers/Org.hs +++ b/src/Text/Pandoc/Readers/Org.hs @@ -1099,7 +1099,7 @@ linkOrImage = explicitOrImageLink explicitOrImageLink :: OrgParser (F Inlines) explicitOrImageLink = try $ do char '[' - srcF <- applyCustomLinkFormat =<< linkTarget + srcF <- applyCustomLinkFormat =<< possiblyEmptyLinkTarget title <- enclosedRaw (char '[') (char ']') title' <- parseFromString (mconcat <$> many inline) title char ']' @@ -1132,6 +1132,9 @@ selfTarget = try $ char '[' *> linkTarget <* char ']' linkTarget :: OrgParser String linkTarget = enclosedByPair '[' ']' (noneOf "\n\r[]") +possiblyEmptyLinkTarget :: OrgParser String +possiblyEmptyLinkTarget = try linkTarget <|> ("" <$ string "[]") + applyCustomLinkFormat :: String -> OrgParser (F String) applyCustomLinkFormat link = do let (linkType, rest) = break (== ':') link @@ -1142,6 +1145,7 @@ applyCustomLinkFormat link = do linkToInlinesF :: String -> Inlines -> F Inlines linkToInlinesF s = case s of + "" -> pure . B.link "" "" ('#':_) -> pure . B.link s "" _ | isImageFilename s -> const . pure $ B.image s "" "" _ | isUri s -> pure . B.link s "" diff --git a/tests/Tests/Readers/Org.hs b/tests/Tests/Readers/Org.hs index fd337f760..e59080bae 100644 --- a/tests/Tests/Readers/Org.hs +++ b/tests/Tests/Readers/Org.hs @@ -205,6 +205,10 @@ tests = "[[../file.txt][moin]]" =?> (para $ link "../file.txt" "" "moin") + , "Empty link (for gitit interop)" =: + "[[][New Link]]" =?> + (para $ link "" "" "New Link") + , "Image link" =: "[[sunset.png][dusk.svg]]" =?> (para $ link "sunset.png" "" (image "dusk.svg" "" "")) -- cgit v1.2.3