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
This commit is contained in:
Albert Krewinkel
2022-12-15 21:19:48 +01:00
committed by John MacFarlane
parent c71d476fa6
commit ca6d4bfa49
7 changed files with 219 additions and 5 deletions
+8
View File
@@ -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
]
+4
View File
@@ -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 ]
+17 -2
View File
@@ -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
+11 -1
View File
@@ -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
+22 -2
View File
@@ -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"
@@ -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]]
```
@@ -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]]
```