mirror of
https://github.com/jgm/pandoc.git
synced 2026-08-26 10:16:32 +00:00
Changed Meta author and date types to Inline lists instead of Strings.
Meta [Inline] [[Inline]] [Inline] rather than Meta [Inline] [String] String. This is a breaking change for libraries that use pandoc and manipulate the metadata. Changed .native files in test suite for new Meta format. git-svn-id: https://pandoc.googlecode.com/svn/trunk@1699 788f1e2b-df1e-0410-8736-df70ead52e1b
This commit is contained in:
@@ -37,9 +37,9 @@ data Pandoc = Pandoc Meta [Block] deriving (Eq, Read, Show, Typeable, Data)
|
||||
|
||||
-- | Bibliographic information for the document: title (list of 'Inline'),
|
||||
-- authors (list of strings), date (string).
|
||||
data Meta = Meta [Inline] -- title
|
||||
[String] -- authors
|
||||
String -- date
|
||||
data Meta = Meta [Inline] -- title
|
||||
[[Inline]] -- authors
|
||||
[Inline] -- date
|
||||
deriving (Eq, Show, Read, Typeable, Data)
|
||||
|
||||
-- | Alignment of a table column.
|
||||
|
||||
@@ -382,7 +382,7 @@ parseTitle = try $ do
|
||||
return contents
|
||||
|
||||
-- parse header and return meta-information (for now, just title)
|
||||
parseHead :: GenParser Char ParserState ([Inline], [a], [Char])
|
||||
parseHead :: GenParser Char ParserState Meta
|
||||
parseHead = try $ do
|
||||
htmlTag "head"
|
||||
spaces
|
||||
@@ -390,7 +390,7 @@ parseHead = try $ do
|
||||
contents <- option [] parseTitle
|
||||
skipMany nonTitleNonHead
|
||||
htmlEndTag "head"
|
||||
return (contents, [], "")
|
||||
return $ Meta contents [] []
|
||||
|
||||
skipHtmlTag :: String -> GenParser Char ParserState ()
|
||||
skipHtmlTag tag = optional (htmlTag tag)
|
||||
@@ -409,7 +409,7 @@ parseHtml = do
|
||||
sepEndBy (choice [xmlDec, definition, htmlComment]) spaces
|
||||
skipHtmlTag "html"
|
||||
spaces
|
||||
(title, authors, date) <- option ([], [], "") parseHead
|
||||
meta <- option (Meta [] [] []) parseHead
|
||||
spaces
|
||||
skipHtmlTag "body"
|
||||
spaces
|
||||
@@ -420,7 +420,7 @@ parseHtml = do
|
||||
spaces
|
||||
optional (htmlEndTag "html" >> many anyChar) -- ignore anything after </html>
|
||||
eof
|
||||
return $ Pandoc (Meta title authors date) blocks
|
||||
return $ Pandoc meta blocks
|
||||
|
||||
--
|
||||
-- parsing blocks
|
||||
|
||||
@@ -317,19 +317,19 @@ title = try $ do
|
||||
authors :: GenParser Char ParserState Block
|
||||
authors = try $ do
|
||||
string "\\author{"
|
||||
authors' <- manyTill anyChar (char '}')
|
||||
authors' <- sepBy (many1 (notFollowedBy (oneOf "};,") >> inline)) (oneOf ",;")
|
||||
char '}'
|
||||
spaces
|
||||
let authors'' = map removeLeadingTrailingSpace $ lines $
|
||||
substitute "\\\\" "\n" authors'
|
||||
let authors'' = map normalizeSpaces authors'
|
||||
updateState (\s -> s { stateAuthors = authors'' })
|
||||
return Null
|
||||
|
||||
date :: GenParser Char ParserState Block
|
||||
date = try $ do
|
||||
string "\\date{"
|
||||
date' <- manyTill anyChar (char '}')
|
||||
date' <- manyTill inline (char '}')
|
||||
spaces
|
||||
updateState (\state -> state { stateDate = date' })
|
||||
updateState (\state -> state { stateDate = normalizeSpaces date' })
|
||||
return Null
|
||||
|
||||
--
|
||||
|
||||
@@ -132,28 +132,27 @@ inlinesInBalancedBrackets parser = try $ do
|
||||
titleLine :: GenParser Char ParserState [Inline]
|
||||
titleLine = try $ char '%' >> skipSpaces >> manyTill inline newline
|
||||
|
||||
authorsLine :: GenParser Char st [String]
|
||||
authorsLine :: GenParser Char ParserState [[Inline]]
|
||||
authorsLine = try $ do
|
||||
char '%'
|
||||
skipSpaces
|
||||
authors <- sepEndBy (many1 (noneOf ",;\n")) (oneOf ",;")
|
||||
authors <- sepEndBy (many1 (notFollowedBy (oneOf ",;\n") >> inline)) (oneOf ",;")
|
||||
newline
|
||||
return $ map (decodeCharacterReferences . removeLeadingTrailingSpace) authors
|
||||
return $ map normalizeSpaces authors
|
||||
|
||||
dateLine :: GenParser Char st String
|
||||
dateLine :: GenParser Char ParserState [Inline]
|
||||
dateLine = try $ do
|
||||
char '%'
|
||||
skipSpaces
|
||||
date <- many (noneOf "\n")
|
||||
newline
|
||||
return $ decodeCharacterReferences $ removeTrailingSpace date
|
||||
date <- manyTill inline newline
|
||||
return $ normalizeSpaces date
|
||||
|
||||
titleBlock :: GenParser Char ParserState ([Inline], [String], [Char])
|
||||
titleBlock :: GenParser Char ParserState ([Inline], [[Inline]], [Inline])
|
||||
titleBlock = try $ do
|
||||
failIfStrict
|
||||
title <- option [] titleLine
|
||||
author <- option [] authorsLine
|
||||
date <- option "" dateLine
|
||||
date <- option [] dateLine
|
||||
optional blanklines
|
||||
return (title, author, date)
|
||||
|
||||
@@ -175,7 +174,7 @@ parseMarkdown = do
|
||||
let reversedNotes = stateNotes st'
|
||||
updateState $ \s -> s { stateNotes = reverse reversedNotes }
|
||||
-- now parse it for real...
|
||||
(title, author, date) <- option ([],[],"") titleBlock
|
||||
(title, author, date) <- option ([],[],[]) titleBlock
|
||||
blocks <- parseBlocks
|
||||
return $ Pandoc (Meta title author date) $ filter (/= Null) blocks
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ module Text.Pandoc.Readers.RST (
|
||||
import Text.Pandoc.Definition
|
||||
import Text.Pandoc.Shared
|
||||
import Text.ParserCombinators.Parsec
|
||||
import Control.Monad ( when )
|
||||
import Control.Monad ( when, unless )
|
||||
import Data.List ( findIndex, delete, intercalate )
|
||||
|
||||
-- | Parse reStructuredText string and return Pandoc document.
|
||||
@@ -157,11 +157,13 @@ fieldList = try $ do
|
||||
let authors = case lookup "Authors" items of
|
||||
Just auth -> [auth]
|
||||
Nothing -> map snd (filter (\(x,_) -> x == "Author") items)
|
||||
if null authors
|
||||
then return ()
|
||||
else updateState $ \st -> st {stateAuthors = authors}
|
||||
unless (null authors) $ do
|
||||
authors' <- mapM (parseFromString (many inline)) authors
|
||||
updateState $ \st -> st {stateAuthors = map normalizeSpaces authors'}
|
||||
case (lookup "Date" items) of
|
||||
Just dat -> updateState $ \st -> st {stateDate = dat}
|
||||
Just dat -> do
|
||||
dat' <- parseFromString (many inline) dat
|
||||
updateState $ \st -> st{ stateDate = normalizeSpaces dat' }
|
||||
Nothing -> return ()
|
||||
case (lookup "Title" items) of
|
||||
Just tit -> parseFromString (many inline) tit >>=
|
||||
|
||||
@@ -667,8 +667,8 @@ data ParserState = ParserState
|
||||
stateTabStop :: Int, -- ^ Tab stop
|
||||
stateStandalone :: Bool, -- ^ Parse bibliographic info?
|
||||
stateTitle :: [Inline], -- ^ Title of document
|
||||
stateAuthors :: [String], -- ^ Authors of document
|
||||
stateDate :: String, -- ^ Date of document
|
||||
stateAuthors :: [[Inline]], -- ^ Authors of document
|
||||
stateDate :: [Inline], -- ^ Date of document
|
||||
stateStrict :: Bool, -- ^ Use strict markdown syntax?
|
||||
stateSmart :: Bool, -- ^ Use smart typography?
|
||||
stateLiterateHaskell :: Bool, -- ^ Treat input as literate haskell
|
||||
|
||||
@@ -53,15 +53,15 @@ writeLaTeX options document =
|
||||
pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState String
|
||||
pandocToLaTeX options (Pandoc (Meta title authors date) blocks) = do
|
||||
main <- liftM render $ blockListToLaTeX blocks
|
||||
titletext <- if null title
|
||||
then return ""
|
||||
else liftM render $ inlineListToLaTeX title
|
||||
titletext <- liftM render $ inlineListToLaTeX title
|
||||
authorsText <- mapM (liftM render . inlineListToLaTeX) authors
|
||||
dateText <- liftM render $ inlineListToLaTeX date
|
||||
let context = writerVariables options ++
|
||||
[ ("toc", if writerTableOfContents options then "yes" else "")
|
||||
, ("body", main)
|
||||
, ("title", titletext)
|
||||
, ("authors", intercalate "\\\\" $ map stringToLaTeX authors)
|
||||
, ("date", stringToLaTeX date) ]
|
||||
, ("authors", intercalate "\\\\" authorsText)
|
||||
, ("date", dateText) ]
|
||||
return $ renderTemplate context $ writerTemplate options
|
||||
|
||||
-- escape things as needed for LaTeX
|
||||
|
||||
@@ -68,6 +68,8 @@ metaToMan :: WriterOptions -- ^ Options, including Man header
|
||||
-> State WriterState (Doc, Doc)
|
||||
metaToMan options (Meta title authors date) = do
|
||||
titleText <- inlineListToMan options title
|
||||
authorsText <- mapM (inlineListToMan options) authors
|
||||
dateText <- inlineListToMan options date
|
||||
let (cmdName, rest) = break (== ' ') $ render titleText
|
||||
let (title', section) = case reverse cmdName of
|
||||
(')':d:'(':xs) | d `elem` ['0'..'9'] ->
|
||||
@@ -76,11 +78,11 @@ metaToMan options (Meta title authors date) = do
|
||||
let extras = map (doubleQuotes . text . removeLeadingTrailingSpace) $
|
||||
splitBy '|' rest
|
||||
let head' = (text ".TH") <+> title' <+> section <+>
|
||||
doubleQuotes (text date) <+> hsep extras
|
||||
let foot = case length authors of
|
||||
doubleQuotes dateText <+> hsep extras
|
||||
let foot = case length authorsText of
|
||||
0 -> empty
|
||||
1 -> text ".SH AUTHOR" $$ (text $ intercalate ", " authors)
|
||||
_ -> text ".SH AUTHORS" $$ (text $ intercalate ", " authors)
|
||||
1 -> text ".SH AUTHOR" $$ (hcat $ intersperse (text ", ") authorsText)
|
||||
_ -> text ".SH AUTHORS" $$ (hcat $ intersperse (text ", ") authorsText)
|
||||
return $ if writerStandalone options
|
||||
then (head', foot)
|
||||
else (empty, empty)
|
||||
|
||||
@@ -109,8 +109,8 @@ metaToMarkdown :: WriterOptions -> Meta -> State WriterState Doc
|
||||
metaToMarkdown _ (Meta [] [] []) = return empty
|
||||
metaToMarkdown opts (Meta title authors date) = do
|
||||
title' <- titleToMarkdown opts title
|
||||
authors' <- authorsToMarkdown authors
|
||||
date' <- dateToMarkdown date
|
||||
authors' <- authorsToMarkdown opts authors
|
||||
date' <- dateToMarkdown opts date
|
||||
return $ title' $+$ authors' $+$ date' $+$ text ""
|
||||
|
||||
titleToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc
|
||||
@@ -119,14 +119,17 @@ titleToMarkdown opts lst = do
|
||||
contents <- inlineListToMarkdown opts lst
|
||||
return $ text "% " <> contents
|
||||
|
||||
authorsToMarkdown :: [String] -> State WriterState Doc
|
||||
authorsToMarkdown [] = return empty
|
||||
authorsToMarkdown lst = return $
|
||||
text "% " <> text (intercalate ", " (map escapeString lst))
|
||||
authorsToMarkdown :: WriterOptions -> [[Inline]] -> State WriterState Doc
|
||||
authorsToMarkdown opts [] = return empty
|
||||
authorsToMarkdown opts lst = do
|
||||
authors <- mapM (inlineListToMarkdown opts) lst
|
||||
return $ text "% " <> (hcat $ intersperse (text ", ") authors)
|
||||
|
||||
dateToMarkdown :: String -> State WriterState Doc
|
||||
dateToMarkdown [] = return empty
|
||||
dateToMarkdown str = return $ text "% " <> text (escapeString str)
|
||||
dateToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc
|
||||
dateToMarkdown opts [] = return empty
|
||||
dateToMarkdown opts str = do
|
||||
date <- inlineListToMarkdown opts str
|
||||
return $ text "% " <> date
|
||||
|
||||
-- | Construct table of contents from list of header blocks.
|
||||
tableOfContents :: WriterOptions -> [Block] -> Doc
|
||||
|
||||
@@ -150,15 +150,18 @@ titleToRST lst = do
|
||||
let border = text (replicate titleLength '=')
|
||||
return $ border $+$ contents $+$ border <> text "\n"
|
||||
|
||||
authorsToRST :: [String] -> State WriterState Doc
|
||||
authorsToRST :: [[Inline]] -> State WriterState Doc
|
||||
authorsToRST [] = return empty
|
||||
authorsToRST (first:rest) = do
|
||||
rest' <- authorsToRST rest
|
||||
return $ (text ":Author: " <> text first) $+$ rest'
|
||||
first' <- inlineListToRST first
|
||||
return $ (text ":Author: " <> first') $+$ rest'
|
||||
|
||||
dateToRST :: String -> State WriterState Doc
|
||||
dateToRST :: [Inline] -> State WriterState Doc
|
||||
dateToRST [] = return empty
|
||||
dateToRST str = return $ text ":Date: " <> text (escapeString str)
|
||||
dateToRST str = do
|
||||
date <- inlineListToRST str
|
||||
return $ text ":Date: " <> date
|
||||
|
||||
-- | Convert Pandoc block element to RST.
|
||||
blockToRST :: Block -- ^ Block element
|
||||
|
||||
@@ -152,10 +152,10 @@ rtfHeader headerText (Meta title authors date) =
|
||||
authorstext = if null authors
|
||||
then ""
|
||||
else rtfPar 0 0 AlignCenter (" " ++ (intercalate "\\" $
|
||||
map stringToRTF authors))
|
||||
datetext = if date == ""
|
||||
map inlineListToRTF authors))
|
||||
datetext = if null date
|
||||
then ""
|
||||
else rtfPar 0 0 AlignCenter (" " ++ stringToRTF date) in
|
||||
else rtfPar 0 0 AlignCenter (" " ++ inlineListToRTF date) in
|
||||
let spacer = if null (titletext ++ authorstext ++ datetext)
|
||||
then ""
|
||||
else rtfPar 0 0 AlignDefault "" in
|
||||
|
||||
@@ -85,9 +85,9 @@ writeS5String options = (writeHtmlString options) . insertS5Structure
|
||||
|
||||
-- | Inserts HTML needed for an S5 presentation (e.g. around slides).
|
||||
layoutDiv :: [Inline] -- ^ Title of document (for header or footer)
|
||||
-> String -- ^ Date of document (for header or footer)
|
||||
-> [Inline] -- ^ Date of document (for header or footer)
|
||||
-> [Block] -- ^ List of block elements returned
|
||||
layoutDiv title' date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 [Str date]), (Header 2 title'), (RawHtml "</div>\n</div>\n")]
|
||||
layoutDiv title' date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 date), (Header 2 title'), (RawHtml "</div>\n</div>\n")]
|
||||
|
||||
presentationStart :: Block
|
||||
presentationStart = RawHtml "<div class=\"presentation\">\n\n"
|
||||
@@ -130,8 +130,8 @@ insertS5Structure (Pandoc (Meta title' authors date) blocks) =
|
||||
let slides = insertSlides True blocks
|
||||
firstSlide = if not (null title')
|
||||
then [slideStart, (Header 1 title'),
|
||||
(Header 3 [Str (intercalate ", " authors)]),
|
||||
(Header 4 [Str date]), slideEnd]
|
||||
(Header 3 (intercalate [Str ",", Space] authors)),
|
||||
(Header 4 date), slideEnd]
|
||||
else []
|
||||
newBlocks = (layoutDiv title' date) ++ presentationStart:firstSlide ++
|
||||
slides ++ [presentationEnd]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] [] "")
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] [] [])
|
||||
[ Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber's",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
|
||||
, HorizontalRule
|
||||
, Header 1 [Str "Headers"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] ["John MacFarlane","Anonymous"] "July 17, 2006")
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]] [Str "July",Space,Str "17,",Space,Str "2006"])
|
||||
[ Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc.",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber",Apostrophe,Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite."]
|
||||
, HorizontalRule
|
||||
, Header 1 [Str "Headers"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [] [] "")
|
||||
Pandoc (Meta [] [] [])
|
||||
[ Header 1 [Str "lhs",Space,Str "test"]
|
||||
, Para [Code "unsplit",Space,Str "is",Space,Str "an",Space,Str "arrow",Space,Str "that",Space,Str "takes",Space,Str "a",Space,Str "pair",Space,Str "of",Space,Str "values",Space,Str "and",Space,Str "combines",Space,Str "them",Space,Str "to",Space,Str "return",Space,Str "a",Space,Str "single",Space,Str "value:"]
|
||||
, CodeBlock ("",["sourceCode","literate","haskell"],[]) "unsplit :: (Arrow a) => (b -> c -> d) -> a (b, c) d\nunsplit = arr . uncurry \n -- arr (\\op (x,y) -> x `op` y) "
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [] [] "")
|
||||
Pandoc (Meta [] [] [])
|
||||
[ Header 1 [Str "Additional",Space,Str "markdown",Space,Str "reader",Space,Str "tests"]
|
||||
, Header 2 [Str "Blank",Space,Str "line",Space,Str "before",Space,Str "URL",Space,Str "in",Space,Str "link",Space,Str "reference"]
|
||||
, Para [Link [Str "foo"] ("/url",""),Space,Str "and",Space,Link [Str "bar"] ("/url","title")]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite",Str ":",Space,Str "Subtitle"] ["John MacFarlane","Anonymous"] "July 17, 2006")
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite",Str ":",Space,Str "Subtitle"] [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]] [Str "July",Space,Str "17,",Space,Str "2006"])
|
||||
[ DefinitionList
|
||||
[ ([Str "Revision"],
|
||||
[ [ Plain [Str "3"] ]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [Str "My",Space,Str "S5",Space,Str "Document"] ["Sam Smith","Jen Jones"] "July 15, 2006")
|
||||
Pandoc (Meta [Str "My",Space,Str "S5",Space,Str "Document"] [[Str "Sam",Space,Str "Smith"],[Str "Jen",Space,Str "Jones"]] [Str "July",Space,Str "15,",Space,Str "2006"])
|
||||
[ Header 1 [Str "First",Space,Str "slide"]
|
||||
, BulletList
|
||||
[ [ Plain [Str "first",Space,Str "bullet"] ]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [] [] "")
|
||||
Pandoc (Meta [] [] [])
|
||||
[ Para [Str "Simple",Space,Str "table",Space,Str "with",Space,Str "caption:"]
|
||||
, Table [Str "Demonstration",Space,Str "of",Space,Str "simple",Space,Str "table",Space,Str "syntax",Str "."] [AlignRight,AlignLeft,AlignCenter,AlignDefault] [0.0,0.0,0.0,0.0]
|
||||
[ [ Plain [Str "Right"] ]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] ["John MacFarlane","Anonymous"] "July 17, 2006")
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]] [Str "July",Space,Str "17,",Space,Str "2006"])
|
||||
[ Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber",Apostrophe,Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
|
||||
, HorizontalRule
|
||||
, Header 1 [Str "Headers"]
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] ["John MacFarlane","Anonymous"] "July 17, 2006")
|
||||
Pandoc (Meta [Str "Pandoc",Space,Str "Test",Space,Str "Suite"] [[Str "John",Space,Str "MacFarlane"],[Str "Anonymous"]] [Str "July",Space,Str "17,",Space,Str "2006"])
|
||||
[ Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "set",Space,Str "of",Space,Str "tests",Space,Str "for",Space,Str "pandoc",Str ".",Space,Str "Most",Space,Str "of",Space,Str "them",Space,Str "are",Space,Str "adapted",Space,Str "from",Space,Str "John",Space,Str "Gruber",Apostrophe,Str "s",Space,Str "markdown",Space,Str "test",Space,Str "suite",Str "."]
|
||||
, HorizontalRule
|
||||
, Header 1 [Str "Headers"]
|
||||
|
||||
Reference in New Issue
Block a user