git.iko.soy/typeable/pandoc
on master help sign in
Merge pull request #485 from paul-r-ml/master

Textile reader update

commit4b77def06173cd9a134c83aba5a0b1758b3b91fc authorJohn MacFarlane <jgm@berkeley.edu> dateFri 27 Apr 2012, 15:00 (14 years ago) parent77125ea7b11154
5 files changed+162−116
INSTALL+22 src/Text/Pandoc/Parsing.hs+5 src/Text/Pandoc/Readers/Textile.hs+114−111 tests/textile-reader.native+7−3 tests/textile-reader.textile+14−2
INSTALL+22
@@ -130,3 +130,25 @@ This is essentially what the binary installer does.
130130[blaze-html]: http://hackage.haskell.org/package/blaze-html
131131[Cabal User's Guide]: http://www.haskell.org/cabal/release/latest/doc/users-guide/builders.html#setup-configure-paths
132132
133+
134+Running tests
135+-------------
136+
137+Pandoc comes with an automated test suite integrated to cabal. Data
138+files are located under the 'tests' directory. If you implement a new
139+feature, please update them to improve covering, and make sure by any
140+necessary mean that the new reference native file is 100% correct.
141+
142+Also, tests require templates that leave in a separate git repository,
143+tied into the main one as a git submodule. To populate 'template'
144+directory, you must therefore run first :
145+
146+ git submodule update --init templates
147+
148+You are now ready to build tests :
149+
150+ cabal-dev install -ftests
151+
152+And finally run them !
153+
154+ cabal-dev test
src/Text/Pandoc/Parsing.hs+5
@@ -52,6 +52,7 @@ module Text.Pandoc.Parsing ( (>>~),
5252 failUnlessLHS,
5353 escaped,
5454 characterReference,
55+ updateLastStrPos,
5556 anyOrderedListMarker,
5657 orderedListMarker,
5758 charRef,
@@ -786,6 +787,10 @@ charOrRef cs =
786787 guard (c `elem` cs)
787788 return c)
788789
790+updateLastStrPos :: GenParser Char ParserState ()
791+updateLastStrPos = getPosition >>= \p ->
792+ updateState $ \s -> s{ stateLastStrPos = Just p }
793+
789794singleQuoteStart :: GenParser Char ParserState ()
790795singleQuoteStart = do
791796 failIfInQuoteContext InSingleQuote
src/Text/Pandoc/Readers/Textile.hs+114−111
@@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1818
1919{- |
2020 Module : Text.Pandoc.Readers.Textile
21− Copyright : Copyright (C) 2010-2011 Paul Rivier and John MacFarlane
21+ Copyright : Copyright (C) 2010-2012 Paul Rivier and John MacFarlane
2222 License : GNU GPL, version 2 or above
2323
2424 Maintainer : Paul Rivier <paul*rivier#demotera*com>
@@ -59,10 +59,12 @@ import Text.Pandoc.Definition
5959import Text.Pandoc.Shared
6060import Text.Pandoc.Parsing
6161import Text.Pandoc.Readers.HTML ( htmlTag, isInlineTag, isBlockTag )
62+import Text.Pandoc.Readers.LaTeX ( rawLaTeXInline, rawLaTeXBlock )
6263import Text.ParserCombinators.Parsec
6364import Text.HTML.TagSoup.Match
64−import Data.Char ( digitToInt, isLetter )
65+import Data.Char ( digitToInt, isUpper )
6566import Control.Monad ( guard, liftM )
67+import Control.Applicative ((<$>), (*>), (<*))
6668
6769-- | Parse a Textile text and return a Pandoc document.
6870readTextile :: ParserState -- ^ Parser state, including options for parser
@@ -72,14 +74,6 @@ readTextile state s =
7274 (readWith parseTextile) state{ stateOldDashes = True } (s ++ "\n\n")
7375
7476
75−--
76−-- Constants and data structure definitions
77−--
78−
79−-- | Special chars border strings parsing
80−specialChars :: [Char]
81−specialChars = "\\[]<>*#_@~-+^&,.;:!?|\"'%()="
82−
8377-- | Generate a Pandoc ADT from a textile document
8478parseTextile :: GenParser Char ParserState Pandoc
8579parseTextile = do
@@ -128,6 +122,7 @@ blockParsers = [ codeBlock
128122 , hrule
129123 , anyList
130124 , rawHtmlBlock
125+ , rawLaTeXBlock'
131126 , maybeExplicitBlock "table" table
132127 , maybeExplicitBlock "p" para
133128 , nullBlock ]
@@ -164,21 +159,16 @@ codeBlockPre = try $ do
164159header :: GenParser Char ParserState Block
165160header = try $ do
166161 char 'h'
167− level <- oneOf "123456" >>= return . digitToInt
168− optional attributes
169− char '.'
170− whitespace
171− name <- manyTill inline blockBreak
172− return $ Header level (normalizeSpaces name)
162+ level <- digitToInt <$> oneOf "123456"
163+ optional attributes >> char '.' >> whitespace
164+ name <- normalizeSpaces <$> manyTill inline blockBreak
165+ return $ Header level name
173166
174167-- | Blockquote of the form "bq. content"
175168blockQuote :: GenParser Char ParserState Block
176169blockQuote = try $ do
177− string "bq"
178− optional attributes
179− char '.'
180− whitespace
181− para >>= return . BlockQuote . (:[])
170+ string "bq" >> optional attributes >> char '.' >> whitespace
171+ BlockQuote . singleton <$> para
182172
183173-- Horizontal rule
184174
@@ -198,10 +188,7 @@ hrule = try $ do
198188-- strict in the nesting, sublist must start at exactly "parent depth
199189-- plus one"
200190anyList :: GenParser Char ParserState Block
201−anyList = try $ do
202− l <- anyListAtDepth 1
203− blanklines
204− return l
191+anyList = try $ ( (anyListAtDepth 1) <* blanklines )
205192
206193-- | This allow one type of list to be nested into an other type,
207194-- provided correct nesting
@@ -212,20 +199,12 @@ anyListAtDepth depth = choice [ bulletListAtDepth depth,
212199
213200-- | Bullet List of given depth, depth being the number of leading '*'
214201bulletListAtDepth :: Int -> GenParser Char ParserState Block
215−bulletListAtDepth depth = try $ do
216− items <- many1 (bulletListItemAtDepth depth)
217− return (BulletList items)
202+bulletListAtDepth depth = try $ BulletList <$> many1 (bulletListItemAtDepth depth)
218203
219204-- | Bullet List Item of given depth, depth being the number of
220205-- leading '*'
221206bulletListItemAtDepth :: Int -> GenParser Char ParserState [Block]
222−bulletListItemAtDepth depth = try $ do
223− count depth (char '*')
224− optional attributes
225− whitespace
226− p <- inlines >>= return . Plain
227− sublist <- option [] (anyListAtDepth (depth + 1) >>= return . (:[]))
228− return (p:sublist)
207+bulletListItemAtDepth = genericListItemAtDepth '*'
229208
230209-- | Ordered List of given depth, depth being the number of
231210-- leading '#'
@@ -237,19 +216,19 @@ orderedListAtDepth depth = try $ do
237216-- | Ordered List Item of given depth, depth being the number of
238217-- leading '#'
239218orderedListItemAtDepth :: Int -> GenParser Char ParserState [Block]
240−orderedListItemAtDepth depth = try $ do
241− count depth (char '#')
242− optional attributes
243− whitespace
244− p <- inlines >>= return . Plain
245− sublist <- option [] (anyListAtDepth (depth + 1) >>= return . (:[]))
246− return (p:sublist)
219+orderedListItemAtDepth = genericListItemAtDepth '#'
220+
221+-- | Common implementation of list items
222+genericListItemAtDepth :: Char -> Int -> GenParser Char ParserState [Block]
223+genericListItemAtDepth c depth = try $ do
224+ count depth (char c) >> optional attributes >> whitespace
225+ p <- inlines
226+ sublist <- option [] (singleton <$> anyListAtDepth (depth + 1))
227+ return ((Plain p):sublist)
247228
248229-- | A definition list is a set of consecutive definition items
249230definitionList :: GenParser Char ParserState Block
250−definitionList = try $ do
251− items <- many1 definitionListItem
252− return $ DefinitionList items
231+definitionList = try $ DefinitionList <$> many1 definitionListItem
253232
254233-- | A definition list item in textile begins with '- ', followed by
255234-- the term defined, then spaces and ":=". The definition follows, on
@@ -277,6 +256,8 @@ blockBreak :: GenParser Char ParserState ()
277256blockBreak = try (newline >> blanklines >> return ()) <|>
278257 (lookAhead rawHtmlBlock >> return ())
279258
259+-- raw content
260+
280261-- | A raw Html Block, optionally followed by blanklines
281262rawHtmlBlock :: GenParser Char ParserState Block
282263rawHtmlBlock = try $ do
@@ -284,11 +265,16 @@ rawHtmlBlock = try $ do
284265 optional blanklines
285266 return $ RawBlock "html" b
286267
268+-- | Raw block of LaTeX content
269+rawLaTeXBlock' :: GenParser Char ParserState Block
270+rawLaTeXBlock' = do
271+ failIfStrict
272+ RawBlock "latex" <$> (rawLaTeXBlock <* spaces)
273+
274+
287275-- | In textile, paragraphs are separated by blank lines.
288276para :: GenParser Char ParserState Block
289−para = try $ do
290− content <- manyTill inline blockBreak
291− return $ Para $ normalizeSpaces content
277+para = try $ Para . normalizeSpaces <$> manyTill inline blockBreak
292278
293279
294280-- Tables
@@ -302,11 +288,7 @@ tableCell = do
302288
303289-- | A table row is made of many table cells
304290tableRow :: GenParser Char ParserState [TableCell]
305−tableRow = try $ do
306− char '|'
307− cells <- endBy1 tableCell (char '|')
308− newline
309− return cells
291+tableRow = try $ ( char '|' *> (endBy1 tableCell (char '|')) <* newline)
310292
311293-- | Many table rows
312294tableRows :: GenParser Char ParserState [[TableCell]]
@@ -314,13 +296,8 @@ tableRows = many1 tableRow
314296
315297-- | Table headers are made of cells separated by a tag "|_."
316298tableHeaders :: GenParser Char ParserState [TableCell]
317−tableHeaders = try $ do
318− let separator = (try $ string "|_.")
319− separator
320− headers <- sepBy1 tableCell separator
321− char '|'
322− newline
323− return headers
299+tableHeaders = let separator = (try $ string "|_.") in
300+ try $ ( separator *> (sepBy1 tableCell separator) <* char '|' <* newline )
324301
325302-- | A table with an optional header. Current implementation can
326303-- handle tables with and without header, but will parse cells
@@ -373,15 +350,10 @@ inlineParsers = [ autoLink
373350 , escapedInline
374351 , htmlSpan
375352 , rawHtmlInline
353+ , rawLaTeXInline'
376354 , note
377− , simpleInline (string "??") (Cite [])
378− , simpleInline (string "**") Strong
379− , simpleInline (string "__") Emph
380− , simpleInline (char '*') Strong
381− , simpleInline (char '_') Emph
382− , simpleInline (char '-') Strikeout
383− , simpleInline (char '^') Superscript
384− , simpleInline (char '~') Subscript
355+ , try $ (char '[' *> inlineMarkup <* char ']')
356+ , inlineMarkup
385357 , link
386358 , image
387359 , mark
@@ -389,6 +361,18 @@ inlineParsers = [ autoLink
389361 , symbol
390362 ]
391363
364+-- | Inline markups
365+inlineMarkup :: GenParser Char ParserState Inline
366+inlineMarkup = choice [ simpleInline (string "??") (Cite [])
367+ , simpleInline (string "**") Strong
368+ , simpleInline (string "__") Emph
369+ , simpleInline (char '*') Strong
370+ , simpleInline (char '_') Emph
371+ , simpleInline (char '-') Strikeout
372+ , simpleInline (char '^') Superscript
373+ , simpleInline (char '~') Subscript
374+ ]
375+
392376-- | Trademark, registered, copyright
393377mark :: GenParser Char st Inline
394378mark = try $ char '(' >> (try tm <|> try reg <|> copy)
@@ -414,41 +398,53 @@ copy = do
414398
415399note :: GenParser Char ParserState Inline
416400note = try $ do
417− char '['
418− ref <- many1 digit
419− char ']'
420− state <- getState
421− let notes = stateNotes state
401+ ref <- (char '[' *> many1 digit <* char ']')
402+ notes <- stateNotes <$> getState
422403 case lookup ref notes of
423404 Nothing -> fail "note not found"
424405 Just raw -> liftM Note $ parseFromString parseBlocks raw
425406
407+-- | Special chars
408+markupChars :: [Char]
409+markupChars = "\\[]*#_@~-+^|%="
410+
411+-- | Break strings on following chars. Space tab and newline break for
412+-- inlines breaking. Open paren breaks for mark. Quote, dash and dot
413+-- break for smart punctuation. Punctuation breaks for regular
414+-- punctuation. Double quote breaks for named links. > and < break
415+-- for inline html.
416+stringBreakers :: [Char]
417+stringBreakers = " \t\n('-.,:!?;\"<>"
418+
419+wordBoundaries :: [Char]
420+wordBoundaries = markupChars ++ stringBreakers
421+
422+-- | Parse a hyphened sequence of words
423+hyphenedWords :: GenParser Char ParserState String
424+hyphenedWords = try $ do
425+ hd <- noneOf wordBoundaries
426+ tl <- many ( (noneOf wordBoundaries) <|>
427+ try (oneOf markupChars <* lookAhead (noneOf wordBoundaries) ) )
428+ let wd = hd:tl
429+ option wd $ try $
430+ (\r -> concat [wd, "-", r]) <$> (char '-' *> hyphenedWords)
431+
426432-- | Any string
427433str :: GenParser Char ParserState Inline
428434str = do
429− xs <- many1 (noneOf (specialChars ++ "\t\n "))
430− optional $ try $ do
431− lookAhead (char '(')
432− notFollowedBy' mark
433− getInput >>= setInput . (' ':) -- add space before acronym explanation
434− -- parse a following hyphen if followed by a letter
435− -- (this prevents unwanted interpretation as starting a strikeout section)
436− result <- option xs $ try $ do
437− char '-'
438− next <- lookAhead letter
439− guard $ isLetter (last xs) || isLetter next
440− return $ xs ++ "-"
441− pos <- getPosition
442− updateState $ \s -> s{ stateLastStrPos = Just pos }
443− return $ Str result
435+ baseStr <- hyphenedWords
436+ -- RedCloth compliance : if parsed word is uppercase and immediatly
437+ -- followed by parens, parens content is unconditionally word acronym
438+ fullStr <- option baseStr $ try $ do
439+ guard $ all isUpper baseStr
440+ acro <- enclosed (char '(') (char ')') anyChar
441+ return $ concat [baseStr, " (", acro, ")"]
442+ updateLastStrPos
443+ return $ Str fullStr
444444
445445-- | Textile allows HTML span infos, we discard them
446446htmlSpan :: GenParser Char ParserState Inline
447−htmlSpan = try $ do
448− char '%'
449− _ <- attributes
450− content <- manyTill anyChar (char '%')
451− return $ Str content
447+htmlSpan = try $ Str <$> ( char '%' *> attributes *> manyTill anyChar (char '%') )
452448
453449-- | Some number of space chars
454450whitespace :: GenParser Char ParserState Inline
@@ -461,8 +457,13 @@ endline = try $ do
461457 return LineBreak
462458
463459rawHtmlInline :: GenParser Char ParserState Inline
464−rawHtmlInline = liftM (RawInline "html" . snd)
465− $ htmlTag isInlineTag
460+rawHtmlInline = RawInline "html" . snd <$> htmlTag isInlineTag
461+
462+-- | Raw LaTeX Inline
463+rawLaTeXInline' :: GenParser Char ParserState Inline
464+rawLaTeXInline' = try $ do
465+ failIfStrict
466+ rawLaTeXInline
466467
467468-- | Textile standard link syntax is "label":target
468469link :: GenParser Char ParserState Inline
@@ -490,38 +491,36 @@ image = try $ do
490491escapedInline :: GenParser Char ParserState Inline
491492escapedInline = escapedEqs <|> escapedTag
492493
493−-- | literal text escaped between == ... ==
494494escapedEqs :: GenParser Char ParserState Inline
495−escapedEqs = try $ do
496− string "=="
497− contents <- manyTill anyChar (try $ string "==")
498− return $ Str contents
495+escapedEqs = Str <$> (try $ surrounded (string "==") anyChar)
496+
497+-- -- | literal text escaped between == ... ==
498+-- escapedEqs :: GenParser Char ParserState Inline
499+-- escapedEqs = try $ do
500+-- string "=="
501+-- contents <- manyTill anyChar (try $ string "==")
502+-- return $ Str contents
499503
500504-- | literal text escaped btw <notextile> tags
501505escapedTag :: GenParser Char ParserState Inline
502−escapedTag = try $ do
503− string "<notextile>"
504− contents <- manyTill anyChar (try $ string "</notextile>")
505− return $ Str contents
506+escapedTag = try $ Str <$>
507+ enclosed (string "<notextile>") (string "</notextile>") anyChar
506508
507−-- | Any special symbol defined in specialChars
509+-- | Any special symbol defined in wordBoundaries
508510symbol :: GenParser Char ParserState Inline
509−symbol = do
510− result <- oneOf specialChars
511− return $ Str [result]
511+symbol = Str . singleton <$> oneOf wordBoundaries
512512
513513-- | Inline code
514514code :: GenParser Char ParserState Inline
515515code = code1 <|> code2
516516
517517code1 :: GenParser Char ParserState Inline
518−code1 = surrounded (char '@') anyChar >>= return . Code nullAttr
518+code1 = Code nullAttr <$> surrounded (char '@') anyChar
519519
520520code2 :: GenParser Char ParserState Inline
521521code2 = do
522522 htmlTag (tagOpen (=="tt") null)
523− result' <- manyTill anyChar (try $ htmlTag $ tagClose (=="tt"))
524− return $ Code nullAttr result'
523+ Code nullAttr <$> manyTill anyChar (try $ htmlTag $ tagClose (=="tt"))
525524
526525-- | Html / CSS attributes
527526attributes :: GenParser Char ParserState String
@@ -542,3 +541,7 @@ simpleInline :: GenParser Char ParserState t -- ^ surrounding parser
542541simpleInline border construct = surrounded border (inlineWithAttribute) >>=
543542 return . construct . normalizeSpaces
544543 where inlineWithAttribute = (try $ optional attributes) >> inline
544+
545+-- | Create a singleton list
546+singleton :: a -> [a]
547+singleton x = [x]
tests/textile-reader.native+7−3
@@ -67,9 +67,9 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
6767 ,([Str "beer"],
6868 [[Plain [Str "fresh",Space,Str "and",Space,Str "bitter"]]])]
6969,Header 1 [Str "Inline",Space,Str "Markup"]
70−,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "A",Space,Link [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
70+,Para [Str "This",Space,Str "is",Space,Emph [Str "emphasized"],Str ",",Space,Str "and",Space,Str "so",Space,Emph [Str "is",Space,Str "this"],Str ".",LineBreak,Str "This",Space,Str "is",Space,Strong [Str "strong"],Str ",",Space,Str "and",Space,Str "so",Space,Strong [Str "is",Space,Str "this"],Str ".",LineBreak,Str "Hyphenated-words-are-ok",Str ",",Space,Str "as",Space,Str "well",Space,Str "as",Space,Str "strange_underscore_notation",Str ".",LineBreak,Str "A",Space,Link [Strong [Str "strong",Space,Str "link"]] ("http://www.foobar.com",""),Str "."]
7171,Para [Emph [Strong [Str "This",Space,Str "is",Space,Str "strong",Space,Str "and",Space,Str "em",Str "."]],LineBreak,Str "So",Space,Str "is",Space,Strong [Emph [Str "this"]],Space,Str "word",Space,Str "and",Space,Emph [Strong [Str "that",Space,Str "one"]],Str ".",LineBreak,Strikeout [Str "This",Space,Str "is",Space,Str "strikeout",Space,Str "and",Space,Strong [Str "strong"]]]
72−,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts",Str ":",Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O",Str "."]
72+,Para [Str "Superscripts",Str ":",Space,Str "a",Superscript [Str "bc"],Str "d",Space,Str "a",Superscript [Strong [Str "hello"]],Space,Str "a",Superscript [Str "hello",Space,Str "there"],Str ".",LineBreak,Str "Subscripts",Str ":",Space,Subscript [Str "here"],Space,Str "H",Subscript [Str "2"],Str "O",Str ",",Space,Str "H",Subscript [Str "23"],Str "O",Str ",",Space,Str "H",Subscript [Str "many",Space,Str "of",Space,Str "them"],Str "O",Str "."]
7373,Para [Str "Dashes",Space,Str ":",Space,Str "How",Space,Str "cool",Space,Str "\8212",Space,Str "automatic",Space,Str "dashes",Str "."]
7474,Para [Str "Elipses",Space,Str ":",Space,Str "He",Space,Str "thought",Space,Str "and",Space,Str "thought",Space,Str "\8230",Space,Str "and",Space,Str "then",Space,Str "thought",Space,Str "some",Space,Str "more",Str "."]
7575,Para [Str "Quotes",Space,Str "and",Space,Str "apostrophes",Space,Str ":",Space,Quoted DoubleQuote [Str "I",Str "\8217",Str "d",Space,Str "like",Space,Str "to",Space,Str "thank",Space,Str "you"],Space,Str "for",Space,Str "example",Str "."]
@@ -139,8 +139,12 @@ Pandoc (Meta {docTitle = [], docAuthors = [], docDate = []})
139139 [[Plain [Str "this",Space,Str "<",Str "div",Str ">",Space,Str "won",Str "\8217",Str "t",Space,Str "produce",Space,Str "raw",Space,Str "html",Space,Str "blocks",Space,Str "<",Str "/div",Str ">"]]
140140 ,[Plain [Str "but",Space,Str "this",Space,RawInline "html" "<strong>",Space,Str "will",Space,Str "produce",Space,Str "inline",Space,Str "html",Space,RawInline "html" "</strong>"]]]
141141,Para [Str "Can",Space,Str "you",Space,Str "prove",Space,Str "that",Space,Str "2",Space,Str "<",Space,Str "3",Space,Str "?"]
142+,Header 1 [Str "Raw",Space,Str "LaTeX"]
143+,Para [Str "This",Space,Str "Textile",Space,Str "reader",Space,Str "also",Space,Str "accepts",Space,Str "raw",Space,Str "LaTeX",Space,Str "for",Space,Str "blocks",Space,Str ":"]
144+,RawBlock "latex" "\\begin{itemize}\n \\item one\n \\item two\n\\end{itemize}"
145+,Para [Str "and",Space,Str "for",Space,RawInline "latex" "\\emph{inlines}",Str "."]
142146,Header 1 [Str "Acronyms",Space,Str "and",Space,Str "marks"]
143−,Para [Str "PBS",Space,Str "(",Str "Public",Space,Str "Broadcasting",Space,Str "System",Str ")"]
147+,Para [Str "PBS (Public Broadcasting System)"]
144148,Para [Str "Hi",Str "\8482"]
145149,Para [Str "Hi",Space,Str "\8482"]
146150,Para [Str "\174",Space,Str "Hi",Str "\174"]
tests/textile-reader.textile+14−2
@@ -115,14 +115,15 @@ h1. Inline Markup
115115
116116This is _emphasized_, and so __is this__.
117117This is *strong*, and so **is this**.
118+Hyphenated-words-are-ok, as well as strange_underscore_notation.
118119A "*strong link*":http://www.foobar.com.
119120
120121_*This is strong and em.*_
121122So is *_this_* word and __**that one**__.
122123-This is strikeout and *strong*-
123124
124−Superscripts: a^bc^d a^*hello*^ a^hello there^.
125−Subscripts: H~2~O, H~23~O, H~many of them~O.
125+Superscripts: a[^bc^]d a^*hello*^ a[^hello there^].
126+Subscripts: ~here~ H[~2~]O, H[~23~]O, H[~many of them~]O.
126127
127128Dashes : How cool -- automatic dashes.
128129
@@ -198,6 +199,17 @@ Html blocks can be <div>inlined</div> as well.
198199
199200Can you prove that 2 < 3 ?
200201
202+h1. Raw LaTeX
203+
204+This Textile reader also accepts raw LaTeX for blocks :
205+
206+\begin{itemize}
207+ \item one
208+ \item two
209+\end{itemize}
210+
211+and for \emph{inlines}.
212+
201213h1. Acronyms and marks
202214
203215PBS(Public Broadcasting System)