Skip to content

Commit d2e1eb7

Browse files
committed
combine all transclusion types
1 parent df35d7a commit d2e1eb7

File tree

2 files changed

+64
-51
lines changed

2 files changed

+64
-51
lines changed

src/Text/Pandoc/Readers/Markdown.hs

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ module Text.Pandoc.Readers.Markdown (
2323
import Control.Monad
2424
import Control.Monad.Except (throwError)
2525
import Data.Bifunctor (second)
26-
import Data.Char (isAlphaNum, isPunctuation, isSpace)
26+
import Data.Char (isAlphaNum, isPunctuation, isSpace, toLower)
2727
import Data.List (transpose, elemIndex, sortOn, foldl')
2828
import qualified Data.Map as M
2929
import Data.Maybe
@@ -1537,7 +1537,7 @@ inline = do
15371537
'*' -> strongOrEmph
15381538
'^' -> inlineNote <|> superscript <|> blockId -- in this order bc ^[link](/foo)^
15391539
'[' -> note <|> cite <|> bracketedSpan <|> wikilink B.linkWith <|> link
1540-
'!' -> image
1540+
'!' -> transclusion <|> image
15411541
'$' -> math
15421542
'~' -> strikeout <|> subscript
15431543
'=' -> mark
@@ -2042,29 +2042,9 @@ rebasePath pos path = do
20422042
"." -> path
20432043
d -> T.pack d <> "/" <> path
20442044

2045-
image :: PandocMonad m => MarkdownParser m (F Inlines)
2046-
image = try $ do
2045+
transclusion :: PandocMonad m => MarkdownParser m (F Inlines)
2046+
transclusion = try $ do
20472047
char '!'
2048-
-- First try wikilink transclusion
2049-
(try wikilinkTransclusion) <|>
2050-
-- Then try regular image parsing
2051-
(do (lab,raw) <- reference
2052-
defaultExt <- getOption readerDefaultImageExtension
2053-
let constructor attr' src
2054-
| "data:" `T.isPrefixOf` src = B.imageWith attr' src -- see #9118
2055-
| otherwise =
2056-
case takeExtension (T.unpack src) of
2057-
"" -> B.imageWith attr' (T.pack $ addExtension (T.unpack src)
2058-
$ T.unpack defaultExt)
2059-
_ -> B.imageWith attr' src
2060-
regLink constructor lab <|> referenceLink constructor (lab, "!" <> raw)) <|>
2061-
-- Fallback: if it looks like ![[...]], create a span with literal text
2062-
(do try $ string "[["
2063-
content <- many1TillChar anyChar (try $ string "]]")
2064-
return $ return $ B.spanWith ("", [], []) (B.str $ "![[" <> content <> "]]"))
2065-
2066-
wikilinkTransclusion :: PandocMonad m => MarkdownParser m (F Inlines)
2067-
wikilinkTransclusion = try $ do
20682048
string "[[" *> notFollowedBy' (char '[')
20692049
raw <- many1TillChar anyChar (try $ string "]]")
20702050
titleAfter <- (True <$ guardEnabled Ext_wikilinks_title_after_pipe) <|> pure False
@@ -2075,32 +2055,65 @@ wikilinkTransclusion = try $ do
20752055
| otherwise -> (before, T.drop 1 after)
20762056
let (url, fragment) = T.break (== '#') target'
20772057
guard $ T.all (`notElem` ['\n','\r','\f','\t']) url
2078-
if T.null fragment
2079-
then do
2080-
guardEnabled Ext_wikilink_transclusions
2081-
currentDir <- takeDirectory . sourceName <$> getPosition
2082-
let filename = T.unpack url <> ".md" -- Assume .md extension for transclusion
2083-
-- Support relative paths like "Folder/File" by using currentDir as base
2084-
insertIncludedFile parseTranscludedInlines toSources [currentDir] filename Nothing Nothing
2085-
else do
2086-
let fragmentContent = T.drop 1 fragment -- Remove the '#' prefix
2087-
if T.take 1 fragmentContent == "^"
2088-
then do
2089-
-- Block ID transclusion: ![[File#^block-id]]
2090-
guardEnabled Ext_wikilink_block_transclusions
2091-
currentDir <- takeDirectory . sourceName <$> getPosition
2092-
let filename = T.unpack url <> ".md" -- Assume .md extension for block transclusion
2093-
let blockIdText = T.drop 1 fragmentContent -- Remove the '^' prefix
2094-
-- Support relative paths like "Folder/File" by using currentDir as base
2095-
insertIncludedFile (parseBlockTransclusion blockIdText) toSources [currentDir] filename Nothing Nothing
2096-
else do
2097-
-- Heading transclusion: ![[File#Heading]]
2098-
guardEnabled Ext_wikilink_heading_transclusions
2099-
currentDir <- takeDirectory . sourceName <$> getPosition
2100-
let filename = T.unpack url <> ".md" -- Assume .md extension for heading transclusion
2101-
let headingText = fragmentContent
2102-
-- Support relative paths like "Folder/File" by using currentDir as base
2103-
insertIncludedFile (parseHeadingTransclusion headingText) toSources [currentDir] filename Nothing Nothing
2058+
2059+
let urlStr = T.unpack url
2060+
let ext = map toLower $ takeExtension urlStr
2061+
let hasExtension = not (null ext)
2062+
let isMdFile = ext == ".md"
2063+
2064+
-- Check if any transclusion extensions are enabled
2065+
hasTransclusions <- (True <$ guardEnabled Ext_wikilink_transclusions) <|>
2066+
(True <$ guardEnabled Ext_wikilink_block_transclusions) <|>
2067+
(True <$ guardEnabled Ext_wikilink_heading_transclusions) <|>
2068+
return False
2069+
2070+
if hasTransclusions && (not hasExtension || isMdFile)
2071+
then -- Handle as transclusion (no extension or .md extension)
2072+
if T.null fragment
2073+
then do
2074+
guardEnabled Ext_wikilink_transclusions
2075+
currentDir <- takeDirectory . sourceName <$> getPosition
2076+
-- Only add .md extension if the file doesn't already have an extension
2077+
let filename = if null (takeExtension urlStr)
2078+
then T.unpack url <> ".md"
2079+
else T.unpack url
2080+
-- Support relative paths like "Folder/File" by using currentDir as base
2081+
insertIncludedFile parseTranscludedInlines toSources [currentDir] filename Nothing Nothing
2082+
else do
2083+
let fragmentContent = T.drop 1 fragment -- Remove the '#' prefix
2084+
if T.take 1 fragmentContent == "^"
2085+
then do
2086+
-- Block ID transclusion: ![[File#^block-id]]
2087+
guardEnabled Ext_wikilink_block_transclusions
2088+
currentDir <- takeDirectory . sourceName <$> getPosition
2089+
let filename = T.unpack url <> ".md" -- Assume .md extension for block transclusion
2090+
let blockIdText = T.drop 1 fragmentContent -- Remove the '^' prefix
2091+
-- Support relative paths like "Folder/File" by using currentDir as base
2092+
insertIncludedFile (parseBlockTransclusion blockIdText) toSources [currentDir] filename Nothing Nothing
2093+
else do
2094+
-- Heading transclusion: ![[File#Heading]]
2095+
guardEnabled Ext_wikilink_heading_transclusions
2096+
currentDir <- takeDirectory . sourceName <$> getPosition
2097+
let filename = T.unpack url <> ".md" -- Assume .md extension for heading transclusion
2098+
let headingText = fragmentContent
2099+
-- Support relative paths like "Folder/File" by using currentDir as base
2100+
insertIncludedFile (parseHeadingTransclusion headingText) toSources [currentDir] filename Nothing Nothing
2101+
else -- Handle as image/embed (has non-.md extension or transclusions disabled)
2102+
return $ return $ B.imageWith ("", ["wikilink"], []) url "" (B.text target')
2103+
2104+
image :: PandocMonad m => MarkdownParser m (F Inlines)
2105+
image = try $ do
2106+
char '!'
2107+
(lab,raw) <- reference
2108+
defaultExt <- getOption readerDefaultImageExtension
2109+
let constructor attr' src
2110+
| "data:" `T.isPrefixOf` src = B.imageWith attr' src -- see #9118
2111+
| otherwise =
2112+
case takeExtension (T.unpack src) of
2113+
"" -> B.imageWith attr' (T.pack $ addExtension (T.unpack src)
2114+
$ T.unpack defaultExt)
2115+
_ -> B.imageWith attr' src
2116+
regLink constructor lab <|> referenceLink constructor (lab, "!" <> raw)
21042117

21052118
note :: PandocMonad m => MarkdownParser m (F Inlines)
21062119
note = try $ do

test/command/8853.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
% pandoc -f markdown+wikilinks_title_after_pipe --wrap=none
33
[[hi]] and ![[hi.jpg]]
44
^D
5-
<p><a href="hi" class="wikilink">hi</a> and <img src="hi.jpg" class="wikilink" alt="hi" /></p>
5+
<p><a href="hi" class="wikilink">hi</a> and <img src="hi.jpg" class="wikilink" alt="hi.jpg" /></p>
66
```

0 commit comments

Comments
 (0)