git.iko.soy/typeable/pandoc
on master help sign in
Org reader: properly handle links to `file:target`
4d85b17Albert Krewinkel
src/Text/Pandoc/Readers/Org.hs+18−6
@@ -1142,20 +1142,25 @@ applyCustomLinkFormat link = do
1142 formatter <- M.lookup linkType <$> asksF orgStateLinkFormatters
1142 formatter <- M.lookup linkType <$> asksF orgStateLinkFormatters
1143 return $ maybe link ($ drop 1 rest) formatter
1143 return $ maybe link ($ drop 1 rest) formatter
1144
1144
1145+-- TODO: might be a lot smarter/cleaner to use parsec and ADTs for this kind
1146+-- of parsing.
1145linkToInlinesF :: String -> Inlines -> F Inlines
1147linkToInlinesF :: String -> Inlines -> F Inlines
1146linkToInlinesF s =
1148linkToInlinesF s =
1147 case s of
1149 case s of
1148 "" -> pure . B.link "" ""
1150 "" -> pure . B.link "" ""
1149 ('#':_) -> pure . B.link s ""
1151 ('#':_) -> pure . B.link s ""
1150 _ | isImageFilename s -> const . pure $ B.image s "" ""
1152 _ | isImageFilename s -> const . pure $ B.image s "" ""
1153+ _ | isFileLink s -> pure . B.link (dropLinkType s) ""
1151 _ | isUri s -> pure . B.link s ""
1154 _ | isUri s -> pure . B.link s ""
1152− _ | isRelativeFilePath s -> pure . B.link s ""
1153 _ | isAbsoluteFilePath s -> pure . B.link ("file://" ++ s) ""
1155 _ | isAbsoluteFilePath s -> pure . B.link ("file://" ++ s) ""
1154− _ -> \title -> do
1156+ _ | isRelativeFilePath s -> pure . B.link s ""
1155− anchorB <- (s `elem`) <$> asksF orgStateAnchorIds
1157+ _ -> internalLink s
1156− if anchorB
1158+
1157− then pure $ B.link ('#':s) "" title
1159+isFileLink :: String -> Bool
1158− else pure $ B.emph title
1160+isFileLink s = ("file:" `isPrefixOf` s) && not ("file://" `isPrefixOf` s)
1161+
1162+dropLinkType :: String -> String
1163+dropLinkType = tail . snd . break (== ':')
1159
1164
1160isRelativeFilePath :: String -> Bool
1165isRelativeFilePath :: String -> Bool
1161isRelativeFilePath s = (("./" `isPrefixOf` s) || ("../" `isPrefixOf` s)) &&
1166isRelativeFilePath s = (("./" `isPrefixOf` s) || ("../" `isPrefixOf` s)) &&
@@ -1178,6 +1183,13 @@ isImageFilename filename =
1178 imageExtensions = [ "jpeg" , "jpg" , "png" , "gif" , "svg" ]
1183 imageExtensions = [ "jpeg" , "jpg" , "png" , "gif" , "svg" ]
1179 protocols = [ "file", "http", "https" ]
1184 protocols = [ "file", "http", "https" ]
1180
1185
1186+internalLink :: String -> Inlines -> F Inlines
1187+internalLink link title = do
1188+ anchorB <- (link `elem`) <$> asksF orgStateAnchorIds
1189+ if anchorB
1190+ then return $ B.link ('#':link) "" title
1191+ else return $ B.emph title
1192+
1181-- | Parse an anchor like @<<anchor-id>>@ and return an empty span with
1193-- | Parse an anchor like @<<anchor-id>>@ and return an empty span with
1182-- @anchor-id@ set as id. Legal anchors in org-mode are defined through
1194-- @anchor-id@ set as id. Legal anchors in org-mode are defined through
1183-- @org-target-regexp@, which is fairly liberal. Since no link is created if
1195-- @org-target-regexp@, which is fairly liberal. Since no link is created if
tests/Tests/Readers/Org.hs+8−1
@@ -4,7 +4,6 @@ module Tests.Readers.Org (tests) where
4import Text.Pandoc.Definition
4import Text.Pandoc.Definition
5import Test.Framework
5import Test.Framework
6import Tests.Helpers
6import Tests.Helpers
7−import Tests.Arbitrary()
8import Text.Pandoc.Builder
7import Text.Pandoc.Builder
9import Text.Pandoc
8import Text.Pandoc
10import Data.List (intersperse)
9import Data.List (intersperse)
@@ -227,6 +226,14 @@ tests =
227 , "for", "fnords."
226 , "for", "fnords."
228 ])
227 ])
229
228
229+ , "Absolute file link" =:
230+ "[[file:///etc/passwd][passwd]]" =?>
231+ (para $ link "file:///etc/passwd" "" "passwd")
232+
233+ , "File link" =:
234+ "[[file:target][title]]" =?>
235+ (para $ link "target" "" "title")
236+
230 , "Anchor" =:
237 , "Anchor" =:
231 "<<anchor>> Link here later." =?>
238 "<<anchor>> Link here later." =?>
232 (para $ spanWith ("anchor", [], []) mempty <>
239 (para $ spanWith ("anchor", [], []) mempty <>