mirror of
https://github.com/jgm/pandoc.git
synced 2026-09-01 15:38:09 +08:00
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:
committed by
John MacFarlane
parent
c71d476fa6
commit
ca6d4bfa49
@@ -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
|
||||
]
|
||||
|
||||
@@ -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 ]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]]
|
||||
```
|
||||
Reference in New Issue
Block a user