summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Krewinkel <albert@zeitkraut.de>2022-12-15 21:19:48 +0100
committerJohn MacFarlane <jgm@berkeley.edu>2023-01-15 10:46:55 -0800
commitca6d4bfa490349e7a4dfeee05119427a1c5ace6c (patch)
tree462ab8e861e5447cb72f68b4d186780514c90f2c
parentc71d476fa6126a6fe9095c67838e452956249df4 (diff)
Markdown, CommonMark: add support for wiki links. [API change]
Adds the Markdown/CommonMark extensions `wikilinks_title_after_pipe` and `wikilinks_title_before_pipe`. The former enables links of style `[[Name of page|Title]]` and the latter `[[Title|Name of page]]`. Titles are optional in both variants, so this works for both: `[[https://example.org]]`, `[[Name of page]]`. The writer is modified to render links with title `wikilink` as a wikilink if a respective extension is enabled. Pandoc will use `wikilinks_title_after_pipe` if both extensions are enabled. Closes: #2923
-rw-r--r--src/Text/Pandoc/Extensions.hs8
-rw-r--r--src/Text/Pandoc/Readers/CommonMark.hs4
-rw-r--r--src/Text/Pandoc/Readers/Markdown.hs19
-rw-r--r--src/Text/Pandoc/Writers/Markdown/Inline.hs12
-rw-r--r--test/Tests/Readers/Markdown.hs24
-rw-r--r--test/command/wikilinks_title_after_pipe.md73
-rw-r--r--test/command/wikilinks_title_before_pipe.md84
7 files changed, 219 insertions, 5 deletions
diff --git a/src/Text/Pandoc/Extensions.hs b/src/Text/Pandoc/Extensions.hs
index 525e96ac6..97ac8e77a 100644
--- a/src/Text/Pandoc/Extensions.hs
+++ b/src/Text/Pandoc/Extensions.hs
@@ -135,6 +135,10 @@ data Extension =
| Ext_tex_math_dollars -- ^ TeX math between $..$ or $$..$$
| Ext_tex_math_double_backslash -- ^ TeX math btw \\(..\\) \\[..\\]
| Ext_tex_math_single_backslash -- ^ TeX math btw \(..\) \[..\]
+ | Ext_wikilinks_title_after_pipe -- ^ Support wikilinks of style
+ -- [[target|title]]
+ | Ext_wikilinks_title_before_pipe -- ^ Support wikilinks of style
+ -- [[title|target]]
| Ext_xrefs_name -- ^ Use xrefs with names
| Ext_xrefs_number -- ^ Use xrefs with numbers
| Ext_yaml_metadata_block -- ^ YAML metadata block
@@ -505,6 +509,8 @@ getAllExtensions f = universalExtensions <> getAll f
, Ext_literate_haskell
, Ext_short_subsuperscripts
, Ext_rebase_relative_paths
+ , Ext_wikilinks_title_after_pipe
+ , Ext_wikilinks_title_before_pipe
]
getAll "markdown_strict" = allMarkdownExtensions
getAll "markdown_phpextra" = allMarkdownExtensions
@@ -557,6 +563,8 @@ getAllExtensions f = universalExtensions <> getAll f
, Ext_implicit_header_references
, Ext_attributes
, Ext_sourcepos
+ , Ext_wikilinks_title_after_pipe
+ , Ext_wikilinks_title_before_pipe
, Ext_yaml_metadata_block
, Ext_rebase_relative_paths
]
diff --git a/src/Text/Pandoc/Readers/CommonMark.hs b/src/Text/Pandoc/Readers/CommonMark.hs
index b19637a3e..6f1e270ba 100644
--- a/src/Text/Pandoc/Readers/CommonMark.hs
+++ b/src/Text/Pandoc/Readers/CommonMark.hs
@@ -157,5 +157,9 @@ specFor opts = foldr ($) defaultSyntaxSpec exts
[ (footnoteSpec <>) | isEnabled Ext_footnotes opts ] ++
[ (definitionListSpec <>) | isEnabled Ext_definition_lists opts ] ++
[ (taskListSpec <>) | isEnabled Ext_task_lists opts ] ++
+ [ (wikilinksSpec TitleAfterPipe <>)
+ | isEnabled Ext_wikilinks_title_after_pipe opts ] ++
+ [ (wikilinksSpec TitleBeforePipe <>)
+ | isEnabled Ext_wikilinks_title_before_pipe opts ] ++
[ (rebaseRelativePathsSpec <>)
| isEnabled Ext_rebase_relative_paths opts ]
diff --git a/src/Text/Pandoc/Readers/Markdown.hs b/src/Text/Pandoc/Readers/Markdown.hs
index 776eecd62..4369c0b2a 100644
--- a/src/Text/Pandoc/Readers/Markdown.hs
+++ b/src/Text/Pandoc/Readers/Markdown.hs
@@ -24,7 +24,6 @@ import Control.Monad
import Control.Monad.Except (throwError)
import Data.Bifunctor (second)
import Data.Char (isAlphaNum, isPunctuation, isSpace)
-import Text.DocLayout (realLength)
import Data.List (transpose, elemIndex, sortOn, foldl')
import qualified Data.Map as M
import Data.Maybe
@@ -35,6 +34,7 @@ import qualified Data.ByteString as BS
import System.FilePath (addExtension, takeExtension, takeDirectory)
import qualified System.FilePath.Windows as Windows
import qualified System.FilePath.Posix as Posix
+import Text.DocLayout (realLength)
import Text.HTML.TagSoup hiding (Row)
import Text.Pandoc.Builder (Blocks, Inlines)
import qualified Text.Pandoc.Builder as B
@@ -1516,7 +1516,7 @@ inline = do
'_' -> strongOrEmph
'*' -> strongOrEmph
'^' -> superscript <|> inlineNote -- in this order bc ^[link](/foo)^
- '[' -> note <|> cite <|> bracketedSpan <|> link
+ '[' -> note <|> cite <|> bracketedSpan <|> wikilink <|> link
'!' -> image
'$' -> math
'~' -> strikeout <|> subscript
@@ -1831,6 +1831,21 @@ source = do
linkTitle :: PandocMonad m => MarkdownParser m Text
linkTitle = quotedTitle '"' <|> quotedTitle '\''
+wikilink :: PandocMonad m => MarkdownParser m (F Inlines)
+wikilink =
+ (guardEnabled Ext_wikilinks_title_after_pipe *> wikilink' swap) <|>
+ (guardEnabled Ext_wikilinks_title_before_pipe *> wikilink' id)
+ where
+ swap (a, b) = (b, a)
+ wikilink' order = try $ do
+ string "[["
+ notFollowedBy' (char '[')
+ raw <- many1TillChar (noneOf "\n\r\f\t") (try $ string "]]")
+ let (title, url) = case T.break (== '|') raw of
+ (before, "") -> (before, before)
+ (before, after) -> order (before, T.drop 1 after)
+ return . pure . B.link url "wikilink" $ B.str title
+
link :: PandocMonad m => MarkdownParser m (F Inlines)
link = try $ do
st <- getState
diff --git a/src/Text/Pandoc/Writers/Markdown/Inline.hs b/src/Text/Pandoc/Writers/Markdown/Inline.hs
index 56970e706..e7be4fc21 100644
--- a/src/Text/Pandoc/Writers/Markdown/Inline.hs
+++ b/src/Text/Pandoc/Writers/Markdown/Inline.hs
@@ -651,6 +651,9 @@ inlineToMarkdown opts lnk@(Link attr@(ident,classes,kvs) txt (src, tit)) = do
case txt of
[Str s] | escapeURI s == srcSuffix -> True
_ -> False
+ let useWikilink = tit == "wikilink" &&
+ (isEnabled Ext_wikilinks_title_after_pipe opts ||
+ isEnabled Ext_wikilinks_title_before_pipe opts)
let useRefLinks = writerReferenceLinks opts && not useAuto
shortcutable <- asks envRefShortcutable
let useShortcutRefLinks = shortcutable &&
@@ -667,7 +670,14 @@ inlineToMarkdown opts lnk@(Link attr@(ident,classes,kvs) txt (src, tit)) = do
| otherwise -> return $ result <> attrsToMarkua attributes
where result = "[" <> linktext <> "](" <> (literal src) <> ")"
attributes = addKeyValueToAttr attr ("title", tit)
- _ | useAuto -> return $ "<" <> literal srcSuffix <> ">"
+ -- Use wikilinks where possible
+ _ | src == stringify txt && useWikilink ->
+ return $ "[[" <> literal (stringify txt) <> "]]"
+ | useAuto -> return $ "<" <> literal srcSuffix <> ">"
+ | useWikilink && isEnabled Ext_wikilinks_title_after_pipe opts -> return $
+ "[[" <> literal src <> "|" <> literal (stringify txt) <> "]]"
+ | useWikilink && isEnabled Ext_wikilinks_title_before_pipe opts -> return $
+ "[[" <> literal (stringify txt) <> "|" <> literal src <> "]]"
| useRefLinks ->
let first = "[" <> linktext <> "]"
second = if getKey linktext == getKey reftext
diff --git a/test/Tests/Readers/Markdown.hs b/test/Tests/Readers/Markdown.hs
index af94c7559..86c424d4b 100644
--- a/test/Tests/Readers/Markdown.hs
+++ b/test/Tests/Readers/Markdown.hs
@@ -34,8 +34,8 @@ markdownCDL = purely $ readMarkdown def { readerExtensions = enableExtension
Ext_compact_definition_lists pandocExtensions }
markdownGH :: Text -> Pandoc
-markdownGH = purely $ readMarkdown def {
- readerExtensions = githubMarkdownExtensions }
+markdownGH = purely $ readMarkdown def {readerExtensions = enableExtension
+ Ext_wikilinks_title_before_pipe githubMarkdownExtensions }
markdownMMD :: Text -> Pandoc
markdownMMD = purely $ readMarkdown def {
@@ -309,6 +309,26 @@ tests = [ testGroup "inline code"
"[https://example.org(](url)" =?>
para (link "url" "" (text "https://example.org("))
]
+ , testGroup "Github wiki links"
+ [ test markdownGH "autolink" $
+ "[[https://example.org]]" =?>
+ para (link "https://example.org" "wikilink" (str "https://example.org"))
+ , test markdownGH "link with title" $
+ "[[title|https://example.org]]" =?>
+ para (link "https://example.org" "wikilink" (str "title"))
+ , test markdownGH "bad link with title" $
+ "[[title|random string]]" =?>
+ para (link "random string" "wikilink" (str "title"))
+ , test markdownGH "autolink not being a link" $
+ "[[Name of page]]" =?>
+ para (link "Name of page" "wikilink" (str "Name of page"))
+ , test markdownGH "autolink not being a link with a square bracket" $
+ "[[Name of ]page]]" =?>
+ para (link "Name of ]page" "wikilink" (str "Name of ]page"))
+ , test markdownGH "link with inline start should be a link" $
+ "[[t`i*t_le|https://example.org]]" =?>
+ para (link "https://example.org" "wikilink" (str "t`i*t_le"))
+ ]
, testGroup "Headers"
[ "blank line before header" =:
"\n# Header\n"
diff --git a/test/command/wikilinks_title_after_pipe.md b/test/command/wikilinks_title_after_pipe.md
new file mode 100644
index 000000000..201e5ee1a
--- /dev/null
+++ b/test/command/wikilinks_title_after_pipe.md
@@ -0,0 +1,73 @@
+# CommonMark
+
+## Reader
+```
+% pandoc --from commonmark_x+wikilinks_title_after_pipe -t html --columns 90
+[[https://example.org]]
+
+[[https://example.org|title]]
+
+[[name of page]]
+
+[[name of page|title]]
+^D
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="name of page" title="wikilink">name of page</a></p>
+<p><a href="name of page" title="wikilink">title</a></p>
+```
+
+## Writer
+
+```
+% pandoc -t commonmark_x+wikilinks_title_after_pipe -f html
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="Home" title="wikilink">Home</a></p>
+<p><a href="Name of page" title="wikilink">Title</a></p>
+^D
+[[https://example.org]]
+
+[[https://example.org|title]]
+
+[[Home]]
+
+[[Name%20of%20page|Title]]
+```
+
+# Markdown
+## Reader
+
+```
+% pandoc --from markdown+wikilinks_title_after_pipe -t html --columns 90
+[[https://example.org]]
+
+[[https://example.org|title]]
+
+[[name of page]]
+
+[[name of page|title]]
+^D
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="name of page" title="wikilink">name of page</a></p>
+<p><a href="name of page" title="wikilink">title</a></p>
+```
+
+## Writer
+
+```
+% pandoc -t markdown+wikilinks_title_after_pipe -f html
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="Home" title="wikilink">Home</a></p>
+<p><a href="Name of page" title="wikilink">Title</a></p>
+^D
+[[https://example.org]]
+
+[[https://example.org|title]]
+
+[[Home]]
+
+[[Name%20of%20page|Title]]
+```
diff --git a/test/command/wikilinks_title_before_pipe.md b/test/command/wikilinks_title_before_pipe.md
new file mode 100644
index 000000000..51bb009bf
--- /dev/null
+++ b/test/command/wikilinks_title_before_pipe.md
@@ -0,0 +1,84 @@
+# CommonMark
+
+## Reader
+
+```
+% pandoc -f commonmark+wikilinks_title_before_pipe -t html --columns 90
+[[https://example.org]]
+
+[[title|https://example.org]]
+
+[[Name of page]]
+
+[[Title|Name of page]]
+^D
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="Name of page" title="wikilink">Name of page</a></p>
+<p><a href="Name of page" title="wikilink">Title</a></p>
+```
+
+## Writer
+
+```
+% pandoc -t commonmark_x+wikilinks_title_before_pipe -f html
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="Home" title="wikilink">Home</a></p>
+<p><a href="Name of page" title="wikilink">Title</a></p>
+^D
+[[https://example.org]]
+
+[[title|https://example.org]]
+
+[[Home]]
+
+[[Title|Name%20of%20page]]
+```
+
+## Regular links should still work
+
+```
+% pandoc -f commonmark+wikilinks_title_before_pipe -t html
+[Title](Name%20of%20page)
+^D
+<p><a href="Name%20of%20page">Title</a></p>
+```
+
+# Markdown
+
+## Reader
+
+```
+% pandoc -f markdown+wikilinks_title_before_pipe -t html --columns 90
+[[https://example.org]]
+
+[[title|https://example.org]]
+
+[[Name of page]]
+
+[[Title|Name of page]]
+^D
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="Name of page" title="wikilink">Name of page</a></p>
+<p><a href="Name of page" title="wikilink">Title</a></p>
+```
+
+## Writer
+
+```
+% pandoc -t markdown+wikilinks_title_before_pipe -f html
+<p><a href="https://example.org" title="wikilink">https://example.org</a></p>
+<p><a href="https://example.org" title="wikilink">title</a></p>
+<p><a href="Home" title="wikilink">Home</a></p>
+<p><a href="Name of page" title="wikilink">Title</a></p>
+^D
+[[https://example.org]]
+
+[[title|https://example.org]]
+
+[[Home]]
+
+[[Title|Name%20of%20page]]
+```