mirror of
https://github.com/jgm/pandoc.git
synced 2026-09-21 05:43:39 +08:00
Add a writer for Markua 0.10 (#7729)
Markua is a markdown variant used by Leanpub. More information about Markua can be found at https://leanpub.com/markua/read. Adds a new exported function `writeMarkua` from T.P.Writers.Markdown. [API change] Closes #1871. Co-authored by Tim Wisotzki and Samuel Lemmenmeier.
This commit is contained in:
@@ -316,6 +316,7 @@ header when requesting a document from a URL:
|
||||
- `markdown_mmd` ([MultiMarkdown])
|
||||
- `markdown_phpextra` ([PHP Markdown Extra])
|
||||
- `markdown_strict` (original unextended [Markdown])
|
||||
- `markua` ([Markua])
|
||||
- `mediawiki` ([MediaWiki markup])
|
||||
- `ms` ([roff ms])
|
||||
- `muse` ([Muse]),
|
||||
@@ -502,6 +503,7 @@ header when requesting a document from a URL:
|
||||
[CSL JSON]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html
|
||||
[BibTeX]: https://ctan.org/pkg/bibtex
|
||||
[BibLaTeX]: https://ctan.org/pkg/biblatex
|
||||
[Markua]: https://leanpub.com/markua/read
|
||||
|
||||
## Reader options {.options}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
$if(titleblock)$
|
||||
$titleblock$
|
||||
|
||||
$endif$
|
||||
$for(header-includes)$
|
||||
$header-includes$
|
||||
|
||||
$endfor$
|
||||
$for(include-before)$
|
||||
$include-before$
|
||||
|
||||
$endfor$
|
||||
$if(toc)$
|
||||
$table-of-contents$
|
||||
|
||||
$endif$
|
||||
$body$
|
||||
$for(include-after)$
|
||||
|
||||
$include-after$
|
||||
$endfor$
|
||||
@@ -90,6 +90,7 @@ data-files:
|
||||
data/templates/default.epub3
|
||||
data/templates/article.jats_publishing
|
||||
data/templates/affiliations.jats
|
||||
data/templates/default.markua
|
||||
-- translations
|
||||
data/translations/*.yaml
|
||||
-- source files for reference.docx
|
||||
@@ -825,6 +826,7 @@ test-suite test-pandoc
|
||||
Tests.Writers.Docx
|
||||
Tests.Writers.RST
|
||||
Tests.Writers.TEI
|
||||
Tests.Writers.Markua
|
||||
Tests.Writers.Muse
|
||||
Tests.Writers.FB2
|
||||
Tests.Writers.Powerpoint
|
||||
|
||||
@@ -54,6 +54,7 @@ formatFromFilePath x =
|
||||
".lhs" -> Just "markdown+lhs"
|
||||
".ltx" -> Just "latex"
|
||||
".markdown" -> Just "markdown"
|
||||
".markua" -> Just "markua"
|
||||
".mkdn" -> Just "markdown"
|
||||
".mkd" -> Just "markdown"
|
||||
".mdwn" -> Just "markdown"
|
||||
|
||||
@@ -432,6 +432,8 @@ getDefaultExtensions "jats_archiving" = getDefaultExtensions "jats"
|
||||
getDefaultExtensions "jats_publishing" = getDefaultExtensions "jats"
|
||||
getDefaultExtensions "jats_articleauthoring" = getDefaultExtensions "jats"
|
||||
getDefaultExtensions "opml" = pandocExtensions -- affects notes
|
||||
getDefaultExtensions "markua" = extensionsFromList
|
||||
[]
|
||||
getDefaultExtensions _ = extensionsFromList
|
||||
[Ext_auto_identifiers]
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ module Text.Pandoc.Shared (
|
||||
ordNub,
|
||||
findM,
|
||||
-- * Text processing
|
||||
inquotes,
|
||||
tshow,
|
||||
elemText,
|
||||
notElemText,
|
||||
@@ -186,6 +187,10 @@ findM p = foldr go (pure Nothing)
|
||||
-- Text processing
|
||||
--
|
||||
|
||||
-- | Wrap double quotes around a Text
|
||||
inquotes :: T.Text -> T.Text
|
||||
inquotes txt = T.cons '\"' (T.snoc txt '\"')
|
||||
|
||||
tshow :: Show a => a -> T.Text
|
||||
tshow = T.pack . show
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ module Text.Pandoc.Writers
|
||||
, writeLaTeX
|
||||
, writeMan
|
||||
, writeMarkdown
|
||||
, writeMarkua
|
||||
, writeMediaWiki
|
||||
, writeMs
|
||||
, writeMuse
|
||||
@@ -190,6 +191,7 @@ writers = [
|
||||
,("csljson" , TextWriter writeCslJson)
|
||||
,("bibtex" , TextWriter writeBibTeX)
|
||||
,("biblatex" , TextWriter writeBibLaTeX)
|
||||
,("markua" , TextWriter writeMarkua)
|
||||
]
|
||||
|
||||
-- | Retrieve writer, extensions based on formatSpec (format+extensions).
|
||||
|
||||
@@ -18,6 +18,7 @@ Markdown: <https://daringfireball.net/projects/markdown/>
|
||||
module Text.Pandoc.Writers.Markdown (
|
||||
writeMarkdown,
|
||||
writeCommonMark,
|
||||
writeMarkua,
|
||||
writePlain) where
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.State.Strict
|
||||
@@ -42,7 +43,10 @@ import Text.Pandoc.Templates (renderTemplate)
|
||||
import Text.DocTemplates (Val(..), Context(..), FromContext(..))
|
||||
import Text.Pandoc.Walk
|
||||
import Text.Pandoc.Writers.HTML (writeHtml5String)
|
||||
import Text.Pandoc.Writers.Markdown.Inline (inlineListToMarkdown, linkAttributes, attrsToMarkdown)
|
||||
import Text.Pandoc.Writers.Markdown.Inline (inlineListToMarkdown,
|
||||
linkAttributes,
|
||||
attrsToMarkdown,
|
||||
attrsToMarkua)
|
||||
import Text.Pandoc.Writers.Markdown.Types (MarkdownVariant(..),
|
||||
WriterState(..),
|
||||
WriterEnv(..),
|
||||
@@ -77,6 +81,26 @@ writeCommonMark opts document =
|
||||
enableExtension Ext_intraword_underscores $
|
||||
writerExtensions opts }
|
||||
|
||||
-- | Convert Pandoc to Markua.
|
||||
writeMarkua :: PandocMonad m => WriterOptions -> Pandoc -> m Text
|
||||
writeMarkua opts document =
|
||||
evalMD (pandocToMarkdown opts' document) def{ envVariant = Markua } def
|
||||
where
|
||||
opts' = opts{ writerExtensions =
|
||||
enableExtension Ext_hard_line_breaks $
|
||||
enableExtension Ext_pipe_tables $
|
||||
-- required for fancy list enumerators
|
||||
enableExtension Ext_fancy_lists $
|
||||
enableExtension Ext_startnum $
|
||||
enableExtension Ext_strikeout $
|
||||
enableExtension Ext_subscript $
|
||||
enableExtension Ext_superscript $
|
||||
enableExtension Ext_definition_lists $
|
||||
enableExtension Ext_smart $
|
||||
enableExtension Ext_footnotes
|
||||
mempty }
|
||||
|
||||
|
||||
pandocTitleBlock :: Doc Text -> [Doc Text] -> Doc Text -> Doc Text
|
||||
pandocTitleBlock tit auths dat =
|
||||
hang 2 (text "% ") tit <> cr <>
|
||||
@@ -327,8 +351,15 @@ blockToMarkdown' opts (Div attrs ils) = do
|
||||
contents <- blockListToMarkdown opts ils
|
||||
variant <- asks envVariant
|
||||
return $
|
||||
case () of
|
||||
_ | isEnabled Ext_fenced_divs opts &&
|
||||
case () of
|
||||
_ | variant == Markua ->
|
||||
case () of
|
||||
() | "blurb" `elem` classes' -> prefixed "B> " contents <> blankline
|
||||
| "aside" `elem` classes' -> prefixed "A> " contents <> blankline
|
||||
-- | necessary to enable option to create a bibliography
|
||||
| (take 3 (T.unpack id')) == "ref" -> contents <> blankline
|
||||
| otherwise -> contents <> blankline
|
||||
| isEnabled Ext_fenced_divs opts &&
|
||||
attrs /= nullAttr ->
|
||||
let attrsToMd = if variant == Commonmark
|
||||
then attrsToMarkdown
|
||||
@@ -408,6 +439,7 @@ blockToMarkdown' opts b@(RawBlock f str) = do
|
||||
| f `elem` ["markdown", "markdown_github", "markdown_phpextra",
|
||||
"markdown_mmd", "markdown_strict"]
|
||||
-> return $ literal str <> literal "\n"
|
||||
Markua -> renderEmpty
|
||||
_ | isEnabled Ext_raw_attribute opts -> rawAttribBlock
|
||||
| f `elem` ["html", "html5", "html4"]
|
||||
, isEnabled Ext_markdown_attribute opts
|
||||
@@ -419,17 +451,19 @@ blockToMarkdown' opts b@(RawBlock f str) = do
|
||||
, isEnabled Ext_raw_tex opts
|
||||
-> return $ literal str <> literal "\n"
|
||||
_ -> renderEmpty
|
||||
blockToMarkdown' opts HorizontalRule =
|
||||
return $ blankline <> literal (T.replicate (writerColumns opts) "-") <> blankline
|
||||
blockToMarkdown' opts HorizontalRule = do
|
||||
variant <- asks envVariant
|
||||
let indicator = case variant of
|
||||
Markua -> "* * *"
|
||||
_ -> T.replicate (writerColumns opts) "-"
|
||||
return $ blankline <> literal indicator <> blankline
|
||||
blockToMarkdown' opts (Header level attr inlines) = do
|
||||
|
||||
-- first, if we're putting references at the end of a section, we
|
||||
-- put them here.
|
||||
blkLevel <- asks envBlockLevel
|
||||
refs <- if writerReferenceLocation opts == EndOfSection && blkLevel == 1
|
||||
then notesAndRefs opts
|
||||
else return empty
|
||||
|
||||
variant <- asks envVariant
|
||||
-- we calculate the id that would be used by auto_identifiers
|
||||
-- so we know whether to print an explicit identifier
|
||||
@@ -442,7 +476,8 @@ blockToMarkdown' opts (Header level attr inlines) = do
|
||||
&& id' == autoId -> empty
|
||||
(id',_,_) | isEnabled Ext_mmd_header_identifiers opts ->
|
||||
space <> brackets (literal id')
|
||||
_ | isEnabled Ext_header_attributes opts ||
|
||||
_ | variant == Markua -> attrsToMarkua attr
|
||||
| isEnabled Ext_header_attributes opts ||
|
||||
isEnabled Ext_attributes opts ->
|
||||
space <> attrsToMarkdown attr
|
||||
| otherwise -> empty
|
||||
@@ -476,6 +511,8 @@ blockToMarkdown' opts (Header level attr inlines) = do
|
||||
-- ghc interprets '#' characters in column 1 as linenum specifiers.
|
||||
_ | variant == PlainText || isEnabled Ext_literate_haskell opts ->
|
||||
contents <> blankline
|
||||
_ | variant == Markua -> attr' <> cr <> literal (T.replicate level "#")
|
||||
<> space <> contents <> blankline
|
||||
_ -> literal (T.replicate level "#") <> space <> contents <> attr' <> blankline
|
||||
|
||||
return $ refs <> hdr
|
||||
@@ -492,9 +529,11 @@ blockToMarkdown' opts (CodeBlock attribs str) = do
|
||||
backticks <> attrs <> cr <> literal str <> cr <> backticks <> blankline
|
||||
| isEnabled Ext_fenced_code_blocks opts ->
|
||||
tildes <> attrs <> cr <> literal str <> cr <> tildes <> blankline
|
||||
_ -> nest (writerTabStop opts) (literal str) <> blankline
|
||||
_ | variant == Markua -> blankline <> attrsToMarkua attribs <> cr <> backticks <> cr <>
|
||||
literal str <> cr <> backticks <> cr <> blankline
|
||||
| otherwise -> nest (writerTabStop opts) (literal str) <> blankline
|
||||
where
|
||||
endlineLen c = maybe 3 ((+1) . maximum) $ nonEmpty $
|
||||
endlineLen c = maybe 3 ((+1) . maximum) $ nonEmpty
|
||||
[T.length ln
|
||||
| ln <- map trim (T.lines str)
|
||||
, T.pack [c,c,c] `T.isPrefixOf` ln
|
||||
@@ -581,24 +620,29 @@ blockToMarkdown' opts t@(Table _ blkCapt specs thead tbody tfoot) = do
|
||||
return $ nst (tbl $$ caption'') $$ blankline
|
||||
blockToMarkdown' opts (BulletList items) = do
|
||||
contents <- inList $ mapM (bulletListItemToMarkdown opts) items
|
||||
return $ (if isTightList items then vcat else vsep) contents <> blankline
|
||||
return $ (if isTightList items then vcat else vsep)
|
||||
contents <> blankline
|
||||
blockToMarkdown' opts (OrderedList (start,sty,delim) items) = do
|
||||
variant <- asks envVariant
|
||||
let start' = if variant == Commonmark || isEnabled Ext_startnum opts
|
||||
then start
|
||||
else 1
|
||||
let sty' = if isEnabled Ext_fancy_lists opts then sty else DefaultStyle
|
||||
let delim' = if isEnabled Ext_fancy_lists opts
|
||||
then delim
|
||||
else if variant == Commonmark &&
|
||||
(delim == OneParen || delim == TwoParens)
|
||||
then OneParen -- commonmark only supports one paren
|
||||
else DefaultDelim
|
||||
let delim' | isEnabled Ext_fancy_lists opts =
|
||||
case variant of
|
||||
-- Markua supports 'fancy' enumerators, but no TwoParens
|
||||
Markua -> if delim == TwoParens then OneParen else delim
|
||||
_ -> delim
|
||||
| variant == Commonmark && --commonmark only supports one paren
|
||||
(delim == OneParen || delim == TwoParens) = OneParen
|
||||
| otherwise = DefaultDelim
|
||||
let attribs = (start', sty', delim')
|
||||
let markers = orderedListMarkers attribs
|
||||
let markers' = map (\m -> if T.length m < 3
|
||||
then m <> T.replicate (3 - T.length m) " "
|
||||
else m) markers
|
||||
let markers' = case variant of
|
||||
Markua -> markers
|
||||
_ -> map (\m -> if T.length m < 3
|
||||
then m <> T.replicate (3 - T.length m) " "
|
||||
else m) markers
|
||||
contents <- inList $
|
||||
zipWithM (orderedListItemToMarkdown opts) markers' items
|
||||
return $ (if isTightList items then vcat else vsep) contents <> blankline
|
||||
@@ -712,10 +756,13 @@ itemEndsWithTightList bs =
|
||||
-- | Convert bullet list item (list of blocks) to markdown.
|
||||
bulletListItemToMarkdown :: PandocMonad m => WriterOptions -> [Block] -> MD m (Doc Text)
|
||||
bulletListItemToMarkdown opts bs = do
|
||||
variant <- asks envVariant
|
||||
let exts = writerExtensions opts
|
||||
contents <- blockListToMarkdown opts $ taskListItemToAscii exts bs
|
||||
let sps = T.replicate (writerTabStop opts - 2) " "
|
||||
let start = literal $ "- " <> sps
|
||||
let start = case variant of
|
||||
Markua -> literal "* "
|
||||
_ -> literal $ "- " <> sps
|
||||
-- remove trailing blank line if item ends with a tight list
|
||||
let contents' = if itemEndsWithTightList bs
|
||||
then chomp contents <> cr
|
||||
@@ -725,19 +772,22 @@ bulletListItemToMarkdown opts bs = do
|
||||
-- | Convert ordered list item (a list of blocks) to markdown.
|
||||
orderedListItemToMarkdown :: PandocMonad m
|
||||
=> WriterOptions -- ^ options
|
||||
-> Text -- ^ list item marker
|
||||
-> Text -- ^ list item marker
|
||||
-> [Block] -- ^ list item (list of blocks)
|
||||
-> MD m (Doc Text)
|
||||
orderedListItemToMarkdown opts marker bs = do
|
||||
let exts = writerExtensions opts
|
||||
contents <- blockListToMarkdown opts $ taskListItemToAscii exts bs
|
||||
variant <- asks envVariant
|
||||
let sps = case writerTabStop opts - T.length marker of
|
||||
n | n > 0 -> literal $ T.replicate n " "
|
||||
_ -> literal " "
|
||||
let ind = if isEnabled Ext_four_space_rule opts
|
||||
then writerTabStop opts
|
||||
else max (writerTabStop opts) (T.length marker + 1)
|
||||
let start = literal marker <> sps
|
||||
let start = case variant of
|
||||
Markua -> literal marker <> " "
|
||||
_ -> literal marker <> sps
|
||||
-- remove trailing blank line if item ends with a tight list
|
||||
let contents' = if itemEndsWithTightList bs
|
||||
then chomp contents <> cr
|
||||
@@ -756,7 +806,10 @@ definitionListItemToMarkdown opts (label, defs) = do
|
||||
then do
|
||||
let tabStop = writerTabStop opts
|
||||
variant <- asks envVariant
|
||||
let leader = if variant == PlainText then " " else ": "
|
||||
let leader = case variant of
|
||||
PlainText -> " "
|
||||
Markua -> ":"
|
||||
_ -> ": "
|
||||
let sps = case writerTabStop opts - 3 of
|
||||
n | n > 0 -> literal $ T.replicate n " "
|
||||
_ -> literal " "
|
||||
@@ -827,6 +880,7 @@ blockListToMarkdown opts blocks = do
|
||||
isListBlock _ = False
|
||||
commentSep
|
||||
| variant == PlainText = Null
|
||||
| variant == Markua = Null
|
||||
| isEnabled Ext_raw_html opts = RawBlock "html" "<!-- -->\n"
|
||||
| otherwise = RawBlock "markdown" " \n"
|
||||
mconcat <$> mapM (blockToMarkdown opts) (fixBlocks blocks)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
module Text.Pandoc.Writers.Markdown.Inline (
|
||||
inlineListToMarkdown,
|
||||
linkAttributes,
|
||||
attrsToMarkdown
|
||||
attrsToMarkdown,
|
||||
attrsToMarkua
|
||||
) where
|
||||
import Control.Monad.Reader
|
||||
import Control.Monad.State.Strict
|
||||
@@ -95,6 +96,11 @@ escapeText opts = T.pack . go' . T.unpack
|
||||
, isAlphaNum x -> c : '_' : x : go xs
|
||||
_ -> c : go cs
|
||||
|
||||
-- Escape the escape character, as well as formatting pairs
|
||||
escapeMarkuaString :: Text -> Text
|
||||
escapeMarkuaString s = foldr (uncurry T.replace) s [("--","~-~-"),
|
||||
("**","~*~*"),("//","~/~/"),("^^","~^~^"),(",,","~,~,")]
|
||||
|
||||
attrsToMarkdown :: Attr -> Doc Text
|
||||
attrsToMarkdown attribs = braces $ hsep [attribId, attribClasses, attribKeys]
|
||||
where attribId = case attribs of
|
||||
@@ -116,9 +122,56 @@ attrsToMarkdown attribs = braces $ hsep [attribId, attribClasses, attribKeys]
|
||||
escAttrChar '\\' = literal "\\\\"
|
||||
escAttrChar c = literal $ T.singleton c
|
||||
|
||||
attrsToMarkua:: Attr -> Doc Text
|
||||
attrsToMarkua attributes
|
||||
| null list = empty
|
||||
| otherwise = braces $ intercalateDocText list
|
||||
where attrId = case attributes of
|
||||
("",_,_) -> []
|
||||
(i,_,_) -> [literal $ "id: " <> i]
|
||||
-- all non explicit (key,value) attributes besides id are getting
|
||||
-- a default class key to be Markua conform
|
||||
attrClasses = case attributes of
|
||||
(_,[],_) -> []
|
||||
(_,classes,_) -> map (escAttr . ("class: " <>))
|
||||
classes
|
||||
attrKeyValues = case attributes of
|
||||
(_,_,[]) -> []
|
||||
(_,_,keyvalues) -> map ((\(k,v) -> escAttr k
|
||||
<> ": " <> escAttr v) .
|
||||
preprocessKeyValues) keyvalues
|
||||
escAttr = mconcat . map escAttrChar . T.unpack
|
||||
escAttrChar '"' = literal "\""
|
||||
escAttrChar c = literal $ T.singleton c
|
||||
|
||||
list = concat [attrId, attrClasses, attrKeyValues]
|
||||
|
||||
-- if attribute key is alt, caption, title then content
|
||||
-- gets wrapped inside quotes
|
||||
-- attribute gets removed
|
||||
preprocessKeyValues :: (Text, Text) -> (Text, Text)
|
||||
preprocessKeyValues (key,value)
|
||||
| key == "alt" ||
|
||||
key == "caption" ||
|
||||
key == "title" = (key, inquotes value)
|
||||
| otherwise = (key,value)
|
||||
intercalateDocText :: [Doc Text] -> Doc Text
|
||||
intercalateDocText [] = empty
|
||||
intercalateDocText [x] = x
|
||||
intercalateDocText (x:xs) = x <> ", " <> (intercalateDocText xs)
|
||||
|
||||
-- | Add a (key, value) pair to Pandoc attr type
|
||||
addKeyValueToAttr :: Attr -> (Text,Text) -> Attr
|
||||
addKeyValueToAttr (ident,classes,kvs) (key,value)
|
||||
| not (T.null key) && not (T.null value) = (ident,
|
||||
classes,
|
||||
(key,value): kvs)
|
||||
| otherwise = (ident,classes,kvs)
|
||||
|
||||
linkAttributes :: WriterOptions -> Attr -> Doc Text
|
||||
linkAttributes opts attr =
|
||||
if (isEnabled Ext_link_attributes opts || isEnabled Ext_attributes opts) && attr /= nullAttr
|
||||
if (isEnabled Ext_link_attributes opts ||
|
||||
isEnabled Ext_attributes opts) && attr /= nullAttr
|
||||
then attrsToMarkdown attr
|
||||
else empty
|
||||
|
||||
@@ -283,6 +336,7 @@ inlineToMarkdown opts (Span attrs ils) = do
|
||||
_ -> id
|
||||
$ case variant of
|
||||
PlainText -> contents
|
||||
Markua -> "`" <> contents <> "`" <> attrsToMarkua attrs
|
||||
_ | attrs == nullAttr -> contents
|
||||
| isEnabled Ext_bracketed_spans opts ->
|
||||
let attrs' = if attrs /= nullAttr
|
||||
@@ -396,60 +450,75 @@ inlineToMarkdown opts (Quoted DoubleQuote lst) = do
|
||||
then "“" <> contents <> "”"
|
||||
else "“" <> contents <> "”"
|
||||
inlineToMarkdown opts (Code attr str) = do
|
||||
variant <- asks envVariant
|
||||
let tickGroups = filter (T.any (== '`')) $ T.group str
|
||||
let longest = maybe 0 maximum $ nonEmpty $ map T.length tickGroups
|
||||
let marker = T.replicate (longest + 1) "`"
|
||||
let spacer = if longest == 0 then "" else " "
|
||||
let attrsEnabled = isEnabled Ext_inline_code_attributes opts ||
|
||||
isEnabled Ext_attributes opts
|
||||
let attrs = if attrsEnabled && attr /= nullAttr
|
||||
then attrsToMarkdown attr
|
||||
else empty
|
||||
variant <- asks envVariant
|
||||
let attrs = case variant of
|
||||
Markua -> attrsToMarkua attr
|
||||
_ -> if attrsEnabled && attr /= nullAttr
|
||||
then attrsToMarkdown attr
|
||||
else empty
|
||||
case variant of
|
||||
PlainText -> return $ literal str
|
||||
_ -> return $ literal
|
||||
(marker <> spacer <> str <> spacer <> marker) <> attrs
|
||||
inlineToMarkdown opts (Str str) = do
|
||||
variant <- asks envVariant
|
||||
let str' = (if writerPreferAscii opts
|
||||
then toHtml5Entities
|
||||
else id) .
|
||||
(if isEnabled Ext_smart opts
|
||||
then unsmartify opts
|
||||
else id) .
|
||||
(if variant == PlainText
|
||||
then id
|
||||
else escapeText opts) $ str
|
||||
let str' = case variant of
|
||||
Markua -> escapeMarkuaString str
|
||||
_ -> (if writerPreferAscii opts
|
||||
then toHtml5Entities
|
||||
else id) .
|
||||
(if isEnabled Ext_smart opts
|
||||
then unsmartify opts
|
||||
else id) .
|
||||
(if variant == PlainText
|
||||
then id
|
||||
else escapeText opts) $ str
|
||||
return $ literal str'
|
||||
inlineToMarkdown opts (Math InlineMath str) =
|
||||
case writerHTMLMathMethod opts of
|
||||
WebTeX url -> inlineToMarkdown opts
|
||||
(Image nullAttr [Str str] (url <> urlEncode str, str))
|
||||
_ | isEnabled Ext_tex_math_dollars opts ->
|
||||
return $ "$" <> literal str <> "$"
|
||||
| isEnabled Ext_tex_math_single_backslash opts ->
|
||||
return $ "\\(" <> literal str <> "\\)"
|
||||
| isEnabled Ext_tex_math_double_backslash opts ->
|
||||
return $ "\\\\(" <> literal str <> "\\\\)"
|
||||
| otherwise -> do
|
||||
variant <- asks envVariant
|
||||
texMathToInlines InlineMath str >>=
|
||||
inlineListToMarkdown opts .
|
||||
(if variant == PlainText then makeMathPlainer else id)
|
||||
inlineToMarkdown opts (Math DisplayMath str) =
|
||||
case writerHTMLMathMethod opts of
|
||||
WebTeX url -> (\x -> blankline <> x <> blankline) `fmap`
|
||||
inlineToMarkdown opts (Image nullAttr [Str str]
|
||||
(url <> urlEncode str, str))
|
||||
_ | isEnabled Ext_tex_math_dollars opts ->
|
||||
return $ "$$" <> literal str <> "$$"
|
||||
| isEnabled Ext_tex_math_single_backslash opts ->
|
||||
return $ "\\[" <> literal str <> "\\]"
|
||||
| isEnabled Ext_tex_math_double_backslash opts ->
|
||||
return $ "\\\\[" <> literal str <> "\\\\]"
|
||||
| otherwise -> (\x -> cr <> x <> cr) `fmap`
|
||||
(texMathToInlines DisplayMath str >>= inlineListToMarkdown opts)
|
||||
inlineToMarkdown opts (Math InlineMath str) = do
|
||||
variant <- asks envVariant
|
||||
case () of
|
||||
_ | variant == Markua -> return $ "`" <> literal str <> "`" <> "$"
|
||||
| otherwise -> case writerHTMLMathMethod opts of
|
||||
WebTeX url -> inlineToMarkdown opts
|
||||
(Image nullAttr [Str str] (url <> urlEncode str, str))
|
||||
_ | isEnabled Ext_tex_math_dollars opts ->
|
||||
return $ "$" <> literal str <> "$"
|
||||
| isEnabled Ext_tex_math_single_backslash opts ->
|
||||
return $ "\\(" <> literal str <> "\\)"
|
||||
| isEnabled Ext_tex_math_double_backslash opts ->
|
||||
return $ "\\\\(" <> literal str <> "\\\\)"
|
||||
| otherwise ->
|
||||
texMathToInlines InlineMath str >>=
|
||||
inlineListToMarkdown opts .
|
||||
(if variant == PlainText then makeMathPlainer else id)
|
||||
|
||||
inlineToMarkdown opts (Math DisplayMath str) = do
|
||||
variant <- asks envVariant
|
||||
case () of
|
||||
_ | variant == Markua -> do
|
||||
let attributes = attrsToMarkua (addKeyValueToAttr ("",[],[])
|
||||
("format", "latex"))
|
||||
return $ blankline <> attributes <> cr <> literal "```" <> cr
|
||||
<> literal str <> cr <> literal "```" <> blankline
|
||||
| otherwise -> case writerHTMLMathMethod opts of
|
||||
WebTeX url -> (\x -> blankline <> x <> blankline) `fmap`
|
||||
inlineToMarkdown opts (Image nullAttr [Str str]
|
||||
(url <> urlEncode str, str))
|
||||
_ | isEnabled Ext_tex_math_dollars opts ->
|
||||
return $ "$$" <> literal str <> "$$"
|
||||
| isEnabled Ext_tex_math_single_backslash opts ->
|
||||
return $ "\\[" <> literal str <> "\\]"
|
||||
| isEnabled Ext_tex_math_double_backslash opts ->
|
||||
return $ "\\\\[" <> literal str <> "\\\\]"
|
||||
| otherwise -> (\x -> cr <> x <> cr) `fmap`
|
||||
(texMathToInlines DisplayMath str >>= inlineListToMarkdown opts)
|
||||
|
||||
inlineToMarkdown opts il@(RawInline f str) = do
|
||||
let tickGroups = filter (T.any (== '`')) $ T.group str
|
||||
let numticks = 1 + maybe 0 maximum (nonEmpty (map T.length tickGroups))
|
||||
@@ -469,6 +538,7 @@ inlineToMarkdown opts il@(RawInline f str) = do
|
||||
| f `elem` ["markdown", "markdown_github", "markdown_phpextra",
|
||||
"markdown_mmd", "markdown_strict"]
|
||||
-> return $ literal str
|
||||
Markua -> renderEmpty
|
||||
_ | isEnabled Ext_raw_attribute opts -> rawAttribInline
|
||||
| f `elem` ["html", "html5", "html4"]
|
||||
, isEnabled Ext_raw_html opts
|
||||
@@ -563,6 +633,11 @@ inlineToMarkdown opts lnk@(Link attr@(ident,classes,kvs) txt (src, tit)) = do
|
||||
PlainText
|
||||
| useAuto -> return $ literal srcSuffix
|
||||
| otherwise -> return linktext
|
||||
Markua
|
||||
| T.null tit -> return $ result <> attrsToMarkua attr
|
||||
| otherwise -> return $ result <> attrsToMarkua attributes
|
||||
where result = "[" <> linktext <> "](" <> (literal src) <> ")"
|
||||
attributes = addKeyValueToAttr attr ("title", tit)
|
||||
_ | useAuto -> return $ "<" <> literal srcSuffix <> ">"
|
||||
| useRefLinks ->
|
||||
let first = "[" <> linktext <> "]"
|
||||
@@ -594,9 +669,16 @@ inlineToMarkdown opts img@(Image attr alternate (source, tit))
|
||||
then [Str ""]
|
||||
else alternate
|
||||
linkPart <- inlineToMarkdown opts (Link attr txt (source, tit))
|
||||
alt <- inlineListToMarkdown opts alternate
|
||||
let attributes | variant == Markua = attrsToMarkua $
|
||||
addKeyValueToAttr (addKeyValueToAttr attr ("title", tit))
|
||||
("alt", render (Just (writerColumns opts)) alt)
|
||||
| otherwise = empty
|
||||
return $ case variant of
|
||||
PlainText -> "[" <> linkPart <> "]"
|
||||
_ -> "!" <> linkPart
|
||||
PlainText -> "[" <> linkPart <> "]"
|
||||
Markua -> cr <> attributes <> cr <> literal "" <> cr
|
||||
_ -> "!" <> linkPart
|
||||
inlineToMarkdown opts (Note contents) = do
|
||||
modify (\st -> st{ stNotes = contents : stNotes st })
|
||||
st <- get
|
||||
|
||||
@@ -45,7 +45,8 @@ data WriterEnv = WriterEnv { envInList :: Bool
|
||||
}
|
||||
|
||||
data MarkdownVariant =
|
||||
PlainText
|
||||
Markua
|
||||
| PlainText
|
||||
| Commonmark
|
||||
| Markdown
|
||||
deriving (Show, Eq)
|
||||
|
||||
@@ -228,6 +228,7 @@ tests pandocPath =
|
||||
, test' "reader" ["-f", "ipynb", "-t", "html"]
|
||||
"ipynb/rank.ipynb" "ipynb/rank.out.html"
|
||||
]
|
||||
, testGroup "markua" [ testGroup "writer" $ writerTests' "markua"]
|
||||
]
|
||||
where
|
||||
test' = test pandocPath
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
{-# LANGUAGE OverloadedStrings #-}
|
||||
module Tests.Writers.Markua (tests) where
|
||||
|
||||
import Test.Tasty
|
||||
import Tests.Helpers
|
||||
import Text.Pandoc
|
||||
import Text.Pandoc.Arbitrary ()
|
||||
import Text.Pandoc.Builder
|
||||
|
||||
{-
|
||||
"my test" =: X =?> Y
|
||||
|
||||
is shorthand for
|
||||
|
||||
test html "my test" $ X =?> Y
|
||||
|
||||
which is in turn shorthand for
|
||||
|
||||
test html "my test" (X,Y)
|
||||
-}
|
||||
|
||||
infix 4 =:
|
||||
(=:) :: (ToString a, ToPandoc a)
|
||||
=> String -> (a, String) -> TestTree
|
||||
(=:) = test (purely (writeMarkua def) . toPandoc)
|
||||
|
||||
tests :: [TestTree]
|
||||
tests = [ testGroup "simple blurb/aside"
|
||||
["blurb" =: divWith ("",["blurb"],[]) (bulletList [para "blurb content"])
|
||||
=?> "B> * blurb content"
|
||||
,"aside" =: divWith ("",["aside"],[]) (bulletList [para "aside list"])
|
||||
=?> "A> * aside list"
|
||||
]
|
||||
,testGroup "multiclass blurb/aside"
|
||||
["blurb" =: divWith ("",["blurb", "otherclass"],[]) (bulletList [para "blurb content"])
|
||||
=?> "B> * blurb content"
|
||||
,"aside" =: divWith ("",["otherclass", "aside"],[]) (bulletList [para "aside list"])
|
||||
=?> "A> * aside list"
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,58 @@
|
||||
Simple table with caption:
|
||||
|
||||
| Right | Left | Center | Default |
|
||||
|------:|:-----|:------:|---------|
|
||||
| 12 | 12 | 12 | 12 |
|
||||
| 123 | 123 | 123 | 123 |
|
||||
| 1 | 1 | 1 | 1 |
|
||||
|
||||
Demonstration of simple table syntax.
|
||||
|
||||
Simple table without caption:
|
||||
|
||||
| Right | Left | Center | Default |
|
||||
|------:|:-----|:------:|---------|
|
||||
| 12 | 12 | 12 | 12 |
|
||||
| 123 | 123 | 123 | 123 |
|
||||
| 1 | 1 | 1 | 1 |
|
||||
|
||||
Simple table indented two spaces:
|
||||
|
||||
| Right | Left | Center | Default |
|
||||
|------:|:-----|:------:|---------|
|
||||
| 12 | 12 | 12 | 12 |
|
||||
| 123 | 123 | 123 | 123 |
|
||||
| 1 | 1 | 1 | 1 |
|
||||
|
||||
Demonstration of simple table syntax.
|
||||
|
||||
Multiline table with caption:
|
||||
|
||||
| Centered Header | Left Aligned | Right Aligned | Default aligned |
|
||||
|:---------------:|:-------------|--------------:|:------------------------------------------------------|
|
||||
| First | row | 12.0 | Example of a row that spans multiple lines. |
|
||||
| Second | row | 5.0 | Here’s another one. Note the blank line between rows. |
|
||||
|
||||
Here’s the caption. It may span multiple lines.
|
||||
|
||||
Multiline table without caption:
|
||||
|
||||
| Centered Header | Left Aligned | Right Aligned | Default aligned |
|
||||
|:---------------:|:-------------|--------------:|:------------------------------------------------------|
|
||||
| First | row | 12.0 | Example of a row that spans multiple lines. |
|
||||
| Second | row | 5.0 | Here’s another one. Note the blank line between rows. |
|
||||
|
||||
Table without column headers:
|
||||
|
||||
| | | | |
|
||||
|----:|:----|:---:|----:|
|
||||
| 12 | 12 | 12 | 12 |
|
||||
| 123 | 123 | 123 | 123 |
|
||||
| 1 | 1 | 1 | 1 |
|
||||
|
||||
Multiline table without column headers:
|
||||
|
||||
| | | | |
|
||||
|:------:|:----|-----:|-------------------------------------------------------|
|
||||
| First | row | 12.0 | Example of a row that spans multiple lines. |
|
||||
| Second | row | 5.0 | Here’s another one. Note the blank line between rows. |
|
||||
@@ -50,6 +50,7 @@ import qualified Tests.Writers.Powerpoint
|
||||
import qualified Tests.Writers.RST
|
||||
import qualified Tests.Writers.AnnotatedTable
|
||||
import qualified Tests.Writers.TEI
|
||||
import qualified Tests.Writers.Markua
|
||||
import Text.Pandoc.Shared (inDirectory)
|
||||
|
||||
tests :: FilePath -> TestTree
|
||||
@@ -72,6 +73,7 @@ tests pandocPath = testGroup "pandoc tests"
|
||||
, testGroup "Docx" Tests.Writers.Docx.tests
|
||||
, testGroup "RST" Tests.Writers.RST.tests
|
||||
, testGroup "TEI" Tests.Writers.TEI.tests
|
||||
, testGroup "markua" Tests.Writers.Markua.tests
|
||||
, testGroup "Muse" Tests.Writers.Muse.tests
|
||||
, testGroup "FB2" Tests.Writers.FB2.tests
|
||||
, testGroup "PowerPoint" Tests.Writers.Powerpoint.tests
|
||||
|
||||
@@ -0,0 +1,700 @@
|
||||
This is a set of tests for pandoc. Most of them are adapted from John Gruber’s
|
||||
markdown test suite.
|
||||
|
||||
* * *
|
||||
|
||||
{id: headers}
|
||||
# Headers
|
||||
|
||||
{id: level-2-with-an-embedded-link}
|
||||
## Level 2 with an [embedded link](/url)
|
||||
|
||||
{id: level-3-with-emphasis}
|
||||
### Level 3 with *emphasis*
|
||||
|
||||
{id: level-4}
|
||||
#### Level 4
|
||||
|
||||
{id: level-5}
|
||||
##### Level 5
|
||||
|
||||
{id: level-1}
|
||||
# Level 1
|
||||
|
||||
{id: level-2-with-emphasis}
|
||||
## Level 2 with *emphasis*
|
||||
|
||||
{id: level-3}
|
||||
### Level 3
|
||||
|
||||
with no blank line
|
||||
|
||||
{id: level-2}
|
||||
## Level 2
|
||||
|
||||
with no blank line
|
||||
|
||||
* * *
|
||||
|
||||
{id: paragraphs}
|
||||
# Paragraphs
|
||||
|
||||
Here’s a regular paragraph.
|
||||
|
||||
In Markdown 1.0.0 and earlier. Version 8. This line turns into a list item.
|
||||
Because a hard-wrapped line in the middle of a paragraph looked like a list
|
||||
item.
|
||||
|
||||
Here’s one with a bullet. * criminey.
|
||||
|
||||
There should be a hard line break
|
||||
here.
|
||||
|
||||
* * *
|
||||
|
||||
{id: block-quotes}
|
||||
# Block Quotes
|
||||
|
||||
E-mail style:
|
||||
|
||||
> This is a block quote. It is pretty short.
|
||||
|
||||
> Code in a block quote:
|
||||
>
|
||||
> ```
|
||||
> sub status {
|
||||
> print "working";
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> A list:
|
||||
>
|
||||
> 1. item one
|
||||
> 2. item two
|
||||
>
|
||||
> Nested block quotes:
|
||||
>
|
||||
> > nested
|
||||
>
|
||||
> > nested
|
||||
|
||||
This should not be a block quote: 2 > 1.
|
||||
|
||||
And a following paragraph.
|
||||
|
||||
* * *
|
||||
|
||||
{id: code-blocks}
|
||||
# Code Blocks
|
||||
|
||||
Code:
|
||||
|
||||
```
|
||||
---- (should be four hyphens)
|
||||
|
||||
sub status {
|
||||
print "working";
|
||||
}
|
||||
|
||||
this code block is indented by one tab
|
||||
```
|
||||
|
||||
And:
|
||||
|
||||
```
|
||||
this code block is indented by two tabs
|
||||
|
||||
These should not be escaped: \$ \\ \> \[ \{
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
{id: lists}
|
||||
# Lists
|
||||
|
||||
{id: unordered}
|
||||
## Unordered
|
||||
|
||||
Asterisks tight:
|
||||
|
||||
* asterisk 1
|
||||
* asterisk 2
|
||||
* asterisk 3
|
||||
|
||||
Asterisks loose:
|
||||
|
||||
* asterisk 1
|
||||
|
||||
* asterisk 2
|
||||
|
||||
* asterisk 3
|
||||
|
||||
Pluses tight:
|
||||
|
||||
* Plus 1
|
||||
* Plus 2
|
||||
* Plus 3
|
||||
|
||||
Pluses loose:
|
||||
|
||||
* Plus 1
|
||||
|
||||
* Plus 2
|
||||
|
||||
* Plus 3
|
||||
|
||||
Minuses tight:
|
||||
|
||||
* Minus 1
|
||||
* Minus 2
|
||||
* Minus 3
|
||||
|
||||
Minuses loose:
|
||||
|
||||
* Minus 1
|
||||
|
||||
* Minus 2
|
||||
|
||||
* Minus 3
|
||||
|
||||
{id: ordered}
|
||||
## Ordered
|
||||
|
||||
Tight:
|
||||
|
||||
1. First
|
||||
2. Second
|
||||
3. Third
|
||||
|
||||
and:
|
||||
|
||||
1. One
|
||||
2. Two
|
||||
3. Three
|
||||
|
||||
Loose using tabs:
|
||||
|
||||
1. First
|
||||
|
||||
2. Second
|
||||
|
||||
3. Third
|
||||
|
||||
and using spaces:
|
||||
|
||||
1. One
|
||||
|
||||
2. Two
|
||||
|
||||
3. Three
|
||||
|
||||
Multiple paragraphs:
|
||||
|
||||
1. Item 1, graf one.
|
||||
|
||||
Item 1. graf two. The quick brown fox jumped over the lazy dog’s back.
|
||||
|
||||
2. Item 2.
|
||||
|
||||
3. Item 3.
|
||||
|
||||
{id: nested}
|
||||
## Nested
|
||||
|
||||
* Tab
|
||||
* Tab
|
||||
* Tab
|
||||
|
||||
Here’s another:
|
||||
|
||||
1. First
|
||||
2. Second:
|
||||
* Fee
|
||||
* Fie
|
||||
* Foe
|
||||
3. Third
|
||||
|
||||
Same thing but with paragraphs:
|
||||
|
||||
1. First
|
||||
|
||||
2. Second:
|
||||
|
||||
* Fee
|
||||
* Fie
|
||||
* Foe
|
||||
|
||||
3. Third
|
||||
|
||||
{id: tabs-and-spaces}
|
||||
## Tabs and spaces
|
||||
|
||||
* this is a list item indented with tabs
|
||||
|
||||
* this is a list item indented with spaces
|
||||
|
||||
* this is an example list item indented with tabs
|
||||
|
||||
* this is an example list item indented with spaces
|
||||
|
||||
{id: fancy-list-markers}
|
||||
## Fancy list markers
|
||||
|
||||
2) begins with 2
|
||||
|
||||
3) and now 3
|
||||
|
||||
with a continuation
|
||||
|
||||
iv. sublist with roman numerals, starting with 4
|
||||
v. more items
|
||||
A) a subsublist
|
||||
B) a subsublist
|
||||
|
||||
Nesting:
|
||||
|
||||
A. Upper Alpha
|
||||
I. Upper Roman.
|
||||
6) Decimal start with 6
|
||||
c) Lower alpha with paren
|
||||
|
||||
Autonumbering:
|
||||
|
||||
1. Autonumber.
|
||||
2. More.
|
||||
1. Nested.
|
||||
|
||||
Should not be a list item:
|
||||
|
||||
M.A. 2007
|
||||
|
||||
B. Williams
|
||||
|
||||
* * *
|
||||
|
||||
{id: definition-lists}
|
||||
# Definition Lists
|
||||
|
||||
Tight using spaces:
|
||||
|
||||
apple
|
||||
: red fruit
|
||||
|
||||
orange
|
||||
: orange fruit
|
||||
|
||||
banana
|
||||
: yellow fruit
|
||||
|
||||
Tight using tabs:
|
||||
|
||||
apple
|
||||
: red fruit
|
||||
|
||||
orange
|
||||
: orange fruit
|
||||
|
||||
banana
|
||||
: yellow fruit
|
||||
|
||||
Loose:
|
||||
|
||||
apple
|
||||
|
||||
: red fruit
|
||||
|
||||
orange
|
||||
|
||||
: orange fruit
|
||||
|
||||
banana
|
||||
|
||||
: yellow fruit
|
||||
|
||||
Multiple blocks with italics:
|
||||
|
||||
*apple*
|
||||
|
||||
: red fruit
|
||||
|
||||
contains seeds, crisp, pleasant to taste
|
||||
|
||||
*orange*
|
||||
|
||||
: orange fruit
|
||||
|
||||
```
|
||||
{ orange code block }
|
||||
```
|
||||
|
||||
> orange block quote
|
||||
|
||||
Multiple definitions, tight:
|
||||
|
||||
apple
|
||||
: red fruit
|
||||
: computer
|
||||
|
||||
orange
|
||||
: orange fruit
|
||||
: bank
|
||||
|
||||
Multiple definitions, loose:
|
||||
|
||||
apple
|
||||
|
||||
: red fruit
|
||||
|
||||
: computer
|
||||
|
||||
orange
|
||||
|
||||
: orange fruit
|
||||
|
||||
: bank
|
||||
|
||||
Blank line after term, indented marker, alternate markers:
|
||||
|
||||
apple
|
||||
|
||||
: red fruit
|
||||
|
||||
: computer
|
||||
|
||||
orange
|
||||
|
||||
: orange fruit
|
||||
|
||||
1. sublist
|
||||
2. sublist
|
||||
|
||||
{id: html-blocks}
|
||||
# HTML Blocks
|
||||
|
||||
Simple block on one line:
|
||||
|
||||
foo
|
||||
|
||||
And nested without indentation:
|
||||
|
||||
foo
|
||||
|
||||
bar
|
||||
|
||||
Interpreted markdown in a table:
|
||||
|
||||
This is *emphasized*
|
||||
And this is **strong**
|
||||
Here’s a simple block:
|
||||
|
||||
foo
|
||||
|
||||
This should be a code block, though:
|
||||
|
||||
```
|
||||
<div>
|
||||
foo
|
||||
</div>
|
||||
```
|
||||
|
||||
As should this:
|
||||
|
||||
```
|
||||
<div>foo</div>
|
||||
```
|
||||
|
||||
Now, nested:
|
||||
|
||||
foo
|
||||
|
||||
This should just be an HTML comment:
|
||||
|
||||
Multiline:
|
||||
|
||||
Code block:
|
||||
|
||||
```
|
||||
<!-- Comment -->
|
||||
```
|
||||
|
||||
Just plain comment, with trailing spaces on the line:
|
||||
|
||||
Code:
|
||||
|
||||
```
|
||||
<hr />
|
||||
```
|
||||
|
||||
Hr’s:
|
||||
|
||||
* * *
|
||||
|
||||
{id: inline-markup}
|
||||
# Inline Markup
|
||||
|
||||
This is *emphasized*, and so *is this*.
|
||||
|
||||
This is **strong**, and so **is this**.
|
||||
|
||||
An *[emphasized link](/url)*.
|
||||
|
||||
***This is strong and em.***
|
||||
|
||||
So is ***this*** word.
|
||||
|
||||
***This is strong and em.***
|
||||
|
||||
So is ***this*** word.
|
||||
|
||||
This is code: `>`, `$`, `\`, `\$`, `<html>`.
|
||||
|
||||
~~This is *strikeout*.~~
|
||||
|
||||
Superscripts: a^bc^d a^*hello*^ a^hello there^.
|
||||
|
||||
Subscripts: H~2~O, H~23~O, H~many of them~O.
|
||||
|
||||
These should not be superscripts or subscripts, because of the unescaped spaces:
|
||||
a^b c^d, a~b c~d.
|
||||
|
||||
* * *
|
||||
|
||||
{id: smart-quotes-ellipses-dashes}
|
||||
# Smart quotes, ellipses, dashes
|
||||
|
||||
"Hello," said the spider. "'Shelob' is my name."
|
||||
|
||||
'A', 'B', and 'C' are letters.
|
||||
|
||||
'Oak,' 'elm,' and 'beech' are names of trees. So is 'pine.'
|
||||
|
||||
'He said, "I want to go."' Were you alive in the 70’s?
|
||||
|
||||
Here is some quoted '`code`' and a "[quoted
|
||||
link](http://example.com/?foo=1&bar=2)".
|
||||
|
||||
Some dashes: one—two — three—four — five.
|
||||
|
||||
Dashes between numbers: 5–7, 255–66, 1987–1999.
|
||||
|
||||
Ellipses…and…and….
|
||||
|
||||
* * *
|
||||
|
||||
{id: latex}
|
||||
# LaTeX
|
||||
|
||||
*
|
||||
* `2+2=4`$
|
||||
* `x \in y`$
|
||||
* `\alpha \wedge \omega`$
|
||||
* `223`$
|
||||
* `p`$-Tree
|
||||
* Here’s some display math:
|
||||
|
||||
{format: latex}
|
||||
```
|
||||
\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}
|
||||
```
|
||||
* Here’s one that has a line break in it: `\alpha + \omega \times x^2`$.
|
||||
|
||||
These shouldn’t be math:
|
||||
|
||||
* To get the famous equation, write `$e = mc^2$`.
|
||||
* $22,000 is a *lot* of money. So is $34,000. (It worked if "lot" is
|
||||
emphasized.)
|
||||
* Shoes ($20) and socks ($5).
|
||||
* Escaped `$`: $73 *this should be emphasized* 23$.
|
||||
|
||||
Here’s a LaTeX table:
|
||||
|
||||
* * *
|
||||
|
||||
{id: special-characters}
|
||||
# Special Characters
|
||||
|
||||
Here is some unicode:
|
||||
|
||||
* I hat: Î
|
||||
* o umlaut: ö
|
||||
* section: §
|
||||
* set membership: ∈
|
||||
* copyright: ©
|
||||
|
||||
AT&T has an ampersand in their name.
|
||||
|
||||
AT&T is another way to write it.
|
||||
|
||||
This & that.
|
||||
|
||||
4 < 5.
|
||||
|
||||
6 > 5.
|
||||
|
||||
Backslash: \
|
||||
|
||||
Backtick: `
|
||||
|
||||
Asterisk: *
|
||||
|
||||
Underscore: _
|
||||
|
||||
Left brace: {
|
||||
|
||||
Right brace: }
|
||||
|
||||
Left bracket: [
|
||||
|
||||
Right bracket: ]
|
||||
|
||||
Left paren: (
|
||||
|
||||
Right paren: )
|
||||
|
||||
Greater-than: >
|
||||
|
||||
Hash: #
|
||||
|
||||
Period: .
|
||||
|
||||
Bang: !
|
||||
|
||||
Plus: +
|
||||
|
||||
Minus: -
|
||||
|
||||
* * *
|
||||
|
||||
{id: links}
|
||||
# Links
|
||||
|
||||
{id: explicit}
|
||||
## Explicit
|
||||
|
||||
Just a [URL](/url/).
|
||||
|
||||
[URL and title](/url/){title: "title"}.
|
||||
|
||||
[URL and title](/url/){title: "title preceded by two spaces"}.
|
||||
|
||||
[URL and title](/url/){title: "title preceded by a tab"}.
|
||||
|
||||
[URL and title](/url/){title: "title with "quotes" in it"}
|
||||
|
||||
[URL and title](/url/){title: "title with single quotes"}
|
||||
|
||||
[with_underscore](/url/with_underscore)
|
||||
|
||||
[Email link](mailto:nobody@nowhere.net)
|
||||
|
||||
[Empty]().
|
||||
|
||||
{id: reference}
|
||||
## Reference
|
||||
|
||||
Foo [bar](/url/).
|
||||
|
||||
With [embedded [brackets]](/url/).
|
||||
|
||||
[b](/url/) by itself should be a link.
|
||||
|
||||
Indented [once](/url).
|
||||
|
||||
Indented [twice](/url).
|
||||
|
||||
Indented [thrice](/url).
|
||||
|
||||
This should [not][] be a link.
|
||||
|
||||
```
|
||||
[not]: /url
|
||||
```
|
||||
|
||||
Foo [bar](/url/){title: "Title with "quotes" inside"}.
|
||||
|
||||
Foo [biz](/url/){title: "Title with "quote" inside"}.
|
||||
|
||||
{id: with-ampersands}
|
||||
## With ampersands
|
||||
|
||||
Here’s a [link with an ampersand in the URL](http://example.com/?foo=1&bar=2).
|
||||
|
||||
Here’s a link with an amersand in the link text:
|
||||
[AT&T](http://att.com/){title: "AT&T"}.
|
||||
|
||||
Here’s an [inline link](/script?foo=1&bar=2).
|
||||
|
||||
Here’s an [inline link in pointy braces](/script?foo=1&bar=2).
|
||||
|
||||
{id: autolinks}
|
||||
## Autolinks
|
||||
|
||||
With an ampersand:
|
||||
[http:~/~/example.com/?foo=1&bar=2](http://example.com/?foo=1&bar=2){class: uri}
|
||||
|
||||
* In a list?
|
||||
* [http:~/~/example.com/](http://example.com/){class: uri}
|
||||
* It should.
|
||||
|
||||
An e-mail address: [nobody@nowhere.net](mailto:nobody@nowhere.net){class: email}
|
||||
|
||||
> Blockquoted: [http:~/~/example.com/](http://example.com/){class: uri}
|
||||
|
||||
Auto-links should not occur here: `<http://example.com/>`
|
||||
|
||||
```
|
||||
or here: <http://example.com/>
|
||||
```
|
||||
|
||||
* * *
|
||||
|
||||
{id: images}
|
||||
# Images
|
||||
|
||||
From "Voyage dans la Lune" by Georges Melies (1902):
|
||||
|
||||
{alt: "lalune", title: "Voyage dans la Lune"}
|
||||

|
||||
|
||||
Here is a movie
|
||||
{alt: "movie"}
|
||||

|
||||
icon.
|
||||
|
||||
* * *
|
||||
|
||||
{id: footnotes}
|
||||
# Footnotes
|
||||
|
||||
Here is a footnote reference,[^1] and another.[^2] This should *not* be a
|
||||
footnote reference, because it contains a space.[^my note] Here is an inline
|
||||
note.[^3]
|
||||
|
||||
> Notes can go in quotes.[^4]
|
||||
|
||||
1. And in list items.[^5]
|
||||
|
||||
This paragraph should not be part of the note, as it is not indented.
|
||||
|
||||
[^1]: Here is the footnote. It can go anywhere after the footnote reference. It
|
||||
need not be placed at the end of the document.
|
||||
|
||||
[^2]: Here’s the long note. This one contains multiple blocks.
|
||||
|
||||
Subsequent blocks are indented to show that they belong to the footnote (as
|
||||
with list items).
|
||||
|
||||
```
|
||||
{ <code> }
|
||||
```
|
||||
|
||||
If you want, you can indent every line, but you can also be lazy and just
|
||||
indent the first line of each block.
|
||||
|
||||
[^3]: This is *easier* to type. Inline notes may contain
|
||||
[links](http://google.com) and `]` verbatim characters, as well as
|
||||
[bracketed text].
|
||||
|
||||
[^4]: In quote.
|
||||
|
||||
[^5]: In list.
|
||||
Reference in New Issue
Block a user