` tags, but as described
+ // above, raw HTML blocks starting with `` *can* contain blank
+ // lines.
+ //
+ // ## Link reference definitions
+ //
+ // A [link reference definition](@)
+ // consists of a [link label], indented up to three spaces, followed
+ // by a colon (`:`), optional [whitespace] (including up to one
+ // [line ending]), a [link destination],
+ // optional [whitespace] (including up to one
+ // [line ending]), and an optional [link
+ // title], which if it is present must be separated
+ // from the [link destination] by [whitespace].
+ // No further [non-whitespace characters] may occur on the line.
+ //
+ // A [link reference definition]
+ // does not correspond to a structural element of a document. Instead, it
+ // defines a label which can be used in [reference links]
+ // and reference-style [images] elsewhere in the document. [Link
+ // reference definitions] can come either before or after the links that use
+ // them.
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example159()
+ {
+ // Example 159
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url "title"
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 159\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /url \"title\"\n\n[foo]", "foo
", "");
+ }
+
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example160()
+ {
+ // Example 160
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]:
+ // /url
+ // 'the title'
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 160\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec(" [foo]: \n /url \n 'the title' \n\n[foo]", "foo
", "");
+ }
+
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example161()
+ {
+ // Example 161
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [Foo*bar\]]:my_(url) 'title (with parens)'
+ //
+ // [Foo*bar\]]
+ //
+ // Should be rendered as:
+ // Foo*bar]
+
+ Console.WriteLine("Example 161\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[Foo*bar\\]]:my_(url) 'title (with parens)'\n\n[Foo*bar\\]]", "Foo*bar]
", "");
+ }
+
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example162()
+ {
+ // Example 162
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [Foo bar]:
+ //
+ // 'title'
+ //
+ // [Foo bar]
+ //
+ // Should be rendered as:
+ // Foo bar
+
+ Console.WriteLine("Example 162\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[Foo bar]:\n\n'title'\n\n[Foo bar]", "Foo bar
", "");
+ }
+
+ // The title may extend over multiple lines:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example163()
+ {
+ // Example 163
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url '
+ // title
+ // line1
+ // line2
+ // '
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 163\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /url '\ntitle\nline1\nline2\n'\n\n[foo]", "foo
", "");
+ }
+
+ // However, it may not contain a [blank line]:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example164()
+ {
+ // Example 164
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url 'title
+ //
+ // with blank line'
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // [foo]: /url 'title
+ // with blank line'
+ // [foo]
+
+ Console.WriteLine("Example 164\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /url 'title\n\nwith blank line'\n\n[foo]", "[foo]: /url 'title
\nwith blank line'
\n[foo]
", "");
+ }
+
+ // The title may be omitted:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example165()
+ {
+ // Example 165
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]:
+ // /url
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 165\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]:\n/url\n\n[foo]", "foo
", "");
+ }
+
+ // The link destination may not be omitted:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example166()
+ {
+ // Example 166
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]:
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // [foo]:
+ // [foo]
+
+ Console.WriteLine("Example 166\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]:\n\n[foo]", "[foo]:
\n[foo]
", "");
+ }
+
+ // Both title and destination can contain backslash escapes
+ // and literal backslashes:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example167()
+ {
+ // Example 167
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url\bar\*baz "foo\"bar\baz"
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 167\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /url\\bar\\*baz \"foo\\\"bar\\baz\"\n\n[foo]", "foo
", "");
+ }
+
+ // A link can come before its corresponding definition:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example168()
+ {
+ // Example 168
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]
+ //
+ // [foo]: url
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 168\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]\n\n[foo]: url", "foo
", "");
+ }
+
+ // If there are several matching definitions, the first one takes
+ // precedence:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example169()
+ {
+ // Example 169
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]
+ //
+ // [foo]: first
+ // [foo]: second
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 169\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]\n\n[foo]: first\n[foo]: second", "foo
", "");
+ }
+
+ // As noted in the section on [Links], matching of labels is
+ // case-insensitive (see [matches]).
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example170()
+ {
+ // Example 170
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [FOO]: /url
+ //
+ // [Foo]
+ //
+ // Should be rendered as:
+ // Foo
+
+ Console.WriteLine("Example 170\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[FOO]: /url\n\n[Foo]", "Foo
", "");
+ }
+
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example171()
+ {
+ // Example 171
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [ΑΓΩ]: /φου
+ //
+ // [αγω]
+ //
+ // Should be rendered as:
+ // αγω
+
+ Console.WriteLine("Example 171\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[ΑΓΩ]: /φου\n\n[αγω]", "αγω
", "");
+ }
+
+ // Here is a link reference definition with no corresponding link.
+ // It contributes nothing to the document.
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example172()
+ {
+ // Example 172
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url
+ //
+ // Should be rendered as:
+ //
+ Console.WriteLine("Example 172\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /url", "", "");
+ }
+
+ // Here is another one:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example173()
+ {
+ // Example 173
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [
+ // foo
+ // ]: /url
+ // bar
+ //
+ // Should be rendered as:
+ // bar
+
+ Console.WriteLine("Example 173\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[\nfoo\n]: /url\nbar", "bar
", "");
+ }
+
+ // This is not a link reference definition, because there are
+ // [non-whitespace characters] after the title:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example174()
+ {
+ // Example 174
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url "title" ok
+ //
+ // Should be rendered as:
+ // [foo]: /url "title" ok
+
+ Console.WriteLine("Example 174\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /url \"title\" ok", "[foo]: /url "title" ok
", "");
+ }
+
+ // This is a link reference definition, but it has no title:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example175()
+ {
+ // Example 175
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url
+ // "title" ok
+ //
+ // Should be rendered as:
+ // "title" ok
+
+ Console.WriteLine("Example 175\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /url\n\"title\" ok", ""title" ok
", "");
+ }
+
+ // This is not a link reference definition, because it is indented
+ // four spaces:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example176()
+ {
+ // Example 176
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /url "title"
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // [foo]: /url "title"
+ //
+ // [foo]
+
+ Console.WriteLine("Example 176\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec(" [foo]: /url \"title\"\n\n[foo]", "[foo]: /url "title"\n
\n[foo]
", "");
+ }
+
+ // This is not a link reference definition, because it occurs inside
+ // a code block:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example177()
+ {
+ // Example 177
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // ```
+ // [foo]: /url
+ // ```
+ //
+ // [foo]
+ //
+ // Should be rendered as:
+ // [foo]: /url
+ //
+ // [foo]
+
+ Console.WriteLine("Example 177\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("```\n[foo]: /url\n```\n\n[foo]", "[foo]: /url\n
\n[foo]
", "");
+ }
+
+ // A [link reference definition] cannot interrupt a paragraph.
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example178()
+ {
+ // Example 178
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // Foo
+ // [bar]: /baz
+ //
+ // [bar]
+ //
+ // Should be rendered as:
+ // Foo
+ // [bar]: /baz
+ // [bar]
+
+ Console.WriteLine("Example 178\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("Foo\n[bar]: /baz\n\n[bar]", "Foo\n[bar]: /baz
\n[bar]
", "");
+ }
+
+ // However, it can directly follow other block elements, such as headings
+ // and thematic breaks, and it need not be followed by a blank line.
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example179()
+ {
+ // Example 179
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // # [Foo]
+ // [foo]: /url
+ // > bar
+ //
+ // Should be rendered as:
+ //
+ //
+ // bar
+ //
+
+ Console.WriteLine("Example 179\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("# [Foo]\n[foo]: /url\n> bar", "\n\nbar
\n
", "");
+ }
+
+ // Several [link reference definitions]
+ // can occur one after another, without intervening blank lines.
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example180()
+ {
+ // Example 180
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]: /foo-url "foo"
+ // [bar]: /bar-url
+ // "bar"
+ // [baz]: /baz-url
+ //
+ // [foo],
+ // [bar],
+ // [baz]
+ //
+ // Should be rendered as:
+ // foo,
+ // bar,
+ // baz
+
+ Console.WriteLine("Example 180\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]: /foo-url \"foo\"\n[bar]: /bar-url\n \"bar\"\n[baz]: /baz-url\n\n[foo],\n[bar],\n[baz]", "foo,\nbar,\nbaz
", "");
+ }
+
+ // [Link reference definitions] can occur
+ // inside block containers, like lists and block quotations. They
+ // affect the entire document, not just the container in which they
+ // are defined:
+ [Test]
+ public void LeafBlocksLinkReferenceDefinitions_Example181()
+ {
+ // Example 181
+ // Section: Leaf blocks / Link reference definitions
+ //
+ // The following Markdown:
+ // [foo]
+ //
+ // > [foo]: /url
+ //
+ // Should be rendered as:
+ // foo
+ //
+ //
+
+ Console.WriteLine("Example 181\nSection Leaf blocks / Link reference definitions\n");
+ TestParser.TestSpec("[foo]\n\n> [foo]: /url", "foo
\n\n
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestLeafBlocksParagraphs
+ {
+ // ## Paragraphs
+ //
+ // A sequence of non-blank lines that cannot be interpreted as other
+ // kinds of blocks forms a [paragraph](@).
+ // The contents of the paragraph are the result of parsing the
+ // paragraph's raw content as inlines. The paragraph's raw content
+ // is formed by concatenating the lines and removing initial and final
+ // [whitespace].
+ //
+ // A simple example with two paragraphs:
+ [Test]
+ public void LeafBlocksParagraphs_Example182()
+ {
+ // Example 182
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ //
+ // bbb
+ //
+ // Should be rendered as:
+ // aaa
+ // bbb
+
+ Console.WriteLine("Example 182\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec("aaa\n\nbbb", "aaa
\nbbb
", "");
+ }
+
+ // Paragraphs can contain multiple lines, but no blank lines:
+ [Test]
+ public void LeafBlocksParagraphs_Example183()
+ {
+ // Example 183
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ // bbb
+ //
+ // ccc
+ // ddd
+ //
+ // Should be rendered as:
+ // aaa
+ // bbb
+ // ccc
+ // ddd
+
+ Console.WriteLine("Example 183\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec("aaa\nbbb\n\nccc\nddd", "aaa\nbbb
\nccc\nddd
", "");
+ }
+
+ // Multiple blank lines between paragraph have no effect:
+ [Test]
+ public void LeafBlocksParagraphs_Example184()
+ {
+ // Example 184
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ //
+ //
+ // bbb
+ //
+ // Should be rendered as:
+ // aaa
+ // bbb
+
+ Console.WriteLine("Example 184\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec("aaa\n\n\nbbb", "aaa
\nbbb
", "");
+ }
+
+ // Leading spaces are skipped:
+ [Test]
+ public void LeafBlocksParagraphs_Example185()
+ {
+ // Example 185
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ // bbb
+ //
+ // Should be rendered as:
+ // aaa
+ // bbb
+
+ Console.WriteLine("Example 185\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec(" aaa\n bbb", "aaa\nbbb
", "");
+ }
+
+ // Lines after the first may be indented any amount, since indented
+ // code blocks cannot interrupt paragraphs.
+ [Test]
+ public void LeafBlocksParagraphs_Example186()
+ {
+ // Example 186
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ // bbb
+ // ccc
+ //
+ // Should be rendered as:
+ // aaa
+ // bbb
+ // ccc
+
+ Console.WriteLine("Example 186\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec("aaa\n bbb\n ccc", "aaa\nbbb\nccc
", "");
+ }
+
+ // However, the first line may be indented at most three spaces,
+ // or an indented code block will be triggered:
+ [Test]
+ public void LeafBlocksParagraphs_Example187()
+ {
+ // Example 187
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ // bbb
+ //
+ // Should be rendered as:
+ // aaa
+ // bbb
+
+ Console.WriteLine("Example 187\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec(" aaa\nbbb", "aaa\nbbb
", "");
+ }
+
+ [Test]
+ public void LeafBlocksParagraphs_Example188()
+ {
+ // Example 188
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ // bbb
+ //
+ // Should be rendered as:
+ // aaa
+ //
+ // bbb
+
+ Console.WriteLine("Example 188\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec(" aaa\nbbb", "aaa\n
\nbbb
", "");
+ }
+
+ // Final spaces are stripped before inline parsing, so a paragraph
+ // that ends with two or more spaces will not end with a [hard line
+ // break]:
+ [Test]
+ public void LeafBlocksParagraphs_Example189()
+ {
+ // Example 189
+ // Section: Leaf blocks / Paragraphs
+ //
+ // The following Markdown:
+ // aaa
+ // bbb
+ //
+ // Should be rendered as:
+ // aaa
+ // bbb
+
+ Console.WriteLine("Example 189\nSection Leaf blocks / Paragraphs\n");
+ TestParser.TestSpec("aaa \nbbb ", "aaa
\nbbb
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestLeafBlocksBlankLines
+ {
+ // ## Blank lines
+ //
+ // [Blank lines] between block-level elements are ignored,
+ // except for the role they play in determining whether a [list]
+ // is [tight] or [loose].
+ //
+ // Blank lines at the beginning and end of the document are also ignored.
+ [Test]
+ public void LeafBlocksBlankLines_Example190()
+ {
+ // Example 190
+ // Section: Leaf blocks / Blank lines
+ //
+ // The following Markdown:
+ //
+ //
+ // aaa
+ //
+ //
+ // # aaa
+ //
+ //
+ //
+ // Should be rendered as:
+ // aaa
+ // aaa
+
+ Console.WriteLine("Example 190\nSection Leaf blocks / Blank lines\n");
+ TestParser.TestSpec(" \n\naaa\n \n\n# aaa\n\n ", "aaa
\naaa
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestContainerBlocksBlockQuotes
+ {
+ // # Container blocks
+ //
+ // A [container block] is a block that has other
+ // blocks as its contents. There are two basic kinds of container blocks:
+ // [block quotes] and [list items].
+ // [Lists] are meta-containers for [list items].
+ //
+ // We define the syntax for container blocks recursively. The general
+ // form of the definition is:
+ //
+ // > If X is a sequence of blocks, then the result of
+ // > transforming X in such-and-such a way is a container of type Y
+ // > with these blocks as its content.
+ //
+ // So, we explain what counts as a block quote or list item by explaining
+ // how these can be *generated* from their contents. This should suffice
+ // to define the syntax, although it does not give a recipe for *parsing*
+ // these constructions. (A recipe is provided below in the section entitled
+ // [A parsing strategy](#appendix-a-parsing-strategy).)
+ //
+ // ## Block quotes
+ //
+ // A [block quote marker](@)
+ // consists of 0-3 spaces of initial indent, plus (a) the character `>` together
+ // with a following space, or (b) a single character `>` not followed by a space.
+ //
+ // The following rules define [block quotes]:
+ //
+ // 1. **Basic case.** If a string of lines *Ls* constitute a sequence
+ // of blocks *Bs*, then the result of prepending a [block quote
+ // marker] to the beginning of each line in *Ls*
+ // is a [block quote](#block-quotes) containing *Bs*.
+ //
+ // 2. **Laziness.** If a string of lines *Ls* constitute a [block
+ // quote](#block-quotes) with contents *Bs*, then the result of deleting
+ // the initial [block quote marker] from one or
+ // more lines in which the next [non-whitespace character] after the [block
+ // quote marker] is [paragraph continuation
+ // text] is a block quote with *Bs* as its content.
+ // [Paragraph continuation text](@) is text
+ // that will be parsed as part of the content of a paragraph, but does
+ // not occur at the beginning of the paragraph.
+ //
+ // 3. **Consecutiveness.** A document cannot contain two [block
+ // quotes] in a row unless there is a [blank line] between them.
+ //
+ // Nothing else counts as a [block quote](#block-quotes).
+ //
+ // Here is a simple example:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example191()
+ {
+ // Example 191
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > # Foo
+ // > bar
+ // > baz
+ //
+ // Should be rendered as:
+ //
+ // Foo
+ // bar
+ // baz
+ //
+
+ Console.WriteLine("Example 191\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> # Foo\n> bar\n> baz", "\nFoo
\nbar\nbaz
\n
", "");
+ }
+
+ // The spaces after the `>` characters can be omitted:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example192()
+ {
+ // Example 192
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // ># Foo
+ // >bar
+ // > baz
+ //
+ // Should be rendered as:
+ //
+ // Foo
+ // bar
+ // baz
+ //
+
+ Console.WriteLine("Example 192\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("># Foo\n>bar\n> baz", "\nFoo
\nbar\nbaz
\n
", "");
+ }
+
+ // The `>` characters can be indented 1-3 spaces:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example193()
+ {
+ // Example 193
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > # Foo
+ // > bar
+ // > baz
+ //
+ // Should be rendered as:
+ //
+ // Foo
+ // bar
+ // baz
+ //
+
+ Console.WriteLine("Example 193\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec(" > # Foo\n > bar\n > baz", "\nFoo
\nbar\nbaz
\n
", "");
+ }
+
+ // Four spaces gives us a code block:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example194()
+ {
+ // Example 194
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > # Foo
+ // > bar
+ // > baz
+ //
+ // Should be rendered as:
+ // > # Foo
+ // > bar
+ // > baz
+ //
+
+ Console.WriteLine("Example 194\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec(" > # Foo\n > bar\n > baz", "> # Foo\n> bar\n> baz\n
", "");
+ }
+
+ // The Laziness clause allows us to omit the `>` before
+ // [paragraph continuation text]:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example195()
+ {
+ // Example 195
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > # Foo
+ // > bar
+ // baz
+ //
+ // Should be rendered as:
+ //
+ // Foo
+ // bar
+ // baz
+ //
+
+ Console.WriteLine("Example 195\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> # Foo\n> bar\nbaz", "\nFoo
\nbar\nbaz
\n
", "");
+ }
+
+ // A block quote can contain some lazy and some non-lazy
+ // continuation lines:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example196()
+ {
+ // Example 196
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > bar
+ // baz
+ // > foo
+ //
+ // Should be rendered as:
+ //
+ // bar
+ // baz
+ // foo
+ //
+
+ Console.WriteLine("Example 196\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> bar\nbaz\n> foo", "\nbar\nbaz\nfoo
\n
", "");
+ }
+
+ // Laziness only applies to lines that would have been continuations of
+ // paragraphs had they been prepended with [block quote markers].
+ // For example, the `> ` cannot be omitted in the second line of
+ //
+ // ``` markdown
+ // > foo
+ // > ---
+ // ```
+ //
+ // without changing the meaning:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example197()
+ {
+ // Example 197
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > foo
+ // ---
+ //
+ // Should be rendered as:
+ //
+ // foo
+ //
+ //
+
+ Console.WriteLine("Example 197\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> foo\n---", "\nfoo
\n
\n
", "");
+ }
+
+ // Similarly, if we omit the `> ` in the second line of
+ //
+ // ``` markdown
+ // > - foo
+ // > - bar
+ // ```
+ //
+ // then the block quote ends after the first line:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example198()
+ {
+ // Example 198
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > - foo
+ // - bar
+ //
+ // Should be rendered as:
+ //
+ //
+ //
+ //
+
+ Console.WriteLine("Example 198\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> - foo\n- bar", "\n\n
\n", "");
+ }
+
+ // For the same reason, we can't omit the `> ` in front of
+ // subsequent lines of an indented or fenced code block:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example199()
+ {
+ // Example 199
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > foo
+ // bar
+ //
+ // Should be rendered as:
+ //
+ // foo
+ //
+ //
+ // bar
+ //
+
+ Console.WriteLine("Example 199\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> foo\n bar", "\nfoo\n
\n
\nbar\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example200()
+ {
+ // Example 200
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > ```
+ // foo
+ // ```
+ //
+ // Should be rendered as:
+ //
+ //
+ //
+ // foo
+ //
+
+ Console.WriteLine("Example 200\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> ```\nfoo\n```", "\n
\n
\nfoo
\n
", "");
+ }
+
+ // Note that in the following case, we have a [lazy
+ // continuation line]:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example201()
+ {
+ // Example 201
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > foo
+ // - bar
+ //
+ // Should be rendered as:
+ //
+ // foo
+ // - bar
+ //
+
+ Console.WriteLine("Example 201\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> foo\n - bar", "\nfoo\n- bar
\n
", "");
+ }
+
+ // To see why, note that in
+ //
+ // ```markdown
+ // > foo
+ // > - bar
+ // ```
+ //
+ // the `- bar` is indented too far to start a list, and can't
+ // be an indented code block because indented code blocks cannot
+ // interrupt paragraphs, so it is [paragraph continuation text].
+ //
+ // A block quote can be empty:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example202()
+ {
+ // Example 202
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // >
+ //
+ // Should be rendered as:
+ //
+ //
+
+ Console.WriteLine("Example 202\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec(">", "\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example203()
+ {
+ // Example 203
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // >
+ // >
+ // >
+ //
+ // Should be rendered as:
+ //
+ //
+
+ Console.WriteLine("Example 203\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec(">\n> \n> ", "\n
", "");
+ }
+
+ // A block quote can have initial or final blank lines:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example204()
+ {
+ // Example 204
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // >
+ // > foo
+ // >
+ //
+ // Should be rendered as:
+ //
+ // foo
+ //
+
+ Console.WriteLine("Example 204\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec(">\n> foo\n> ", "\nfoo
\n
", "");
+ }
+
+ // A blank line always separates block quotes:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example205()
+ {
+ // Example 205
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > foo
+ //
+ // > bar
+ //
+ // Should be rendered as:
+ //
+ // foo
+ //
+ //
+ // bar
+ //
+
+ Console.WriteLine("Example 205\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> foo\n\n> bar", "\nfoo
\n
\n\nbar
\n
", "");
+ }
+
+ // (Most current Markdown implementations, including John Gruber's
+ // original `Markdown.pl`, will parse this example as a single block quote
+ // with two paragraphs. But it seems better to allow the author to decide
+ // whether two block quotes or one are wanted.)
+ //
+ // Consecutiveness means that if we put these block quotes together,
+ // we get a single block quote:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example206()
+ {
+ // Example 206
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > foo
+ // > bar
+ //
+ // Should be rendered as:
+ //
+ // foo
+ // bar
+ //
+
+ Console.WriteLine("Example 206\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> foo\n> bar", "\nfoo\nbar
\n
", "");
+ }
+
+ // To get a block quote with two paragraphs, use:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example207()
+ {
+ // Example 207
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > foo
+ // >
+ // > bar
+ //
+ // Should be rendered as:
+ //
+ // foo
+ // bar
+ //
+
+ Console.WriteLine("Example 207\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> foo\n>\n> bar", "\nfoo
\nbar
\n
", "");
+ }
+
+ // Block quotes can interrupt paragraphs:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example208()
+ {
+ // Example 208
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // foo
+ // > bar
+ //
+ // Should be rendered as:
+ // foo
+ //
+ // bar
+ //
+
+ Console.WriteLine("Example 208\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("foo\n> bar", "foo
\n\nbar
\n
", "");
+ }
+
+ // In general, blank lines are not needed before or after block
+ // quotes:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example209()
+ {
+ // Example 209
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > aaa
+ // ***
+ // > bbb
+ //
+ // Should be rendered as:
+ //
+ // aaa
+ //
+ //
+ //
+ // bbb
+ //
+
+ Console.WriteLine("Example 209\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> aaa\n***\n> bbb", "\naaa
\n
\n
\n\nbbb
\n
", "");
+ }
+
+ // However, because of laziness, a blank line is needed between
+ // a block quote and a following paragraph:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example210()
+ {
+ // Example 210
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > bar
+ // baz
+ //
+ // Should be rendered as:
+ //
+ // bar
+ // baz
+ //
+
+ Console.WriteLine("Example 210\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> bar\nbaz", "\nbar\nbaz
\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example211()
+ {
+ // Example 211
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > bar
+ //
+ // baz
+ //
+ // Should be rendered as:
+ //
+ // bar
+ //
+ // baz
+
+ Console.WriteLine("Example 211\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> bar\n\nbaz", "\nbar
\n
\nbaz
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example212()
+ {
+ // Example 212
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > bar
+ // >
+ // baz
+ //
+ // Should be rendered as:
+ //
+ // bar
+ //
+ // baz
+
+ Console.WriteLine("Example 212\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> bar\n>\nbaz", "\nbar
\n
\nbaz
", "");
+ }
+
+ // It is a consequence of the Laziness rule that any number
+ // of initial `>`s may be omitted on a continuation line of a
+ // nested block quote:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example213()
+ {
+ // Example 213
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > > > foo
+ // bar
+ //
+ // Should be rendered as:
+ //
+ //
+ //
+ // foo
+ // bar
+ //
+ //
+ //
+
+ Console.WriteLine("Example 213\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> > > foo\nbar", "\n\n\nfoo\nbar
\n
\n
\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example214()
+ {
+ // Example 214
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // >>> foo
+ // > bar
+ // >>baz
+ //
+ // Should be rendered as:
+ //
+ //
+ //
+ // foo
+ // bar
+ // baz
+ //
+ //
+ //
+
+ Console.WriteLine("Example 214\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec(">>> foo\n> bar\n>>baz", "\n\n\nfoo\nbar\nbaz
\n
\n
\n
", "");
+ }
+
+ // When including an indented code block in a block quote,
+ // remember that the [block quote marker] includes
+ // both the `>` and a following space. So *five spaces* are needed after
+ // the `>`:
+ [Test]
+ public void ContainerBlocksBlockQuotes_Example215()
+ {
+ // Example 215
+ // Section: Container blocks / Block quotes
+ //
+ // The following Markdown:
+ // > code
+ //
+ // > not code
+ //
+ // Should be rendered as:
+ //
+ // code
+ //
+ //
+ //
+ // not code
+ //
+
+ Console.WriteLine("Example 215\nSection Container blocks / Block quotes\n");
+ TestParser.TestSpec("> code\n\n> not code", "\ncode\n
\n
\n\nnot code
\n
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestContainerBlocksListItems
+ {
+ // ## List items
+ //
+ // A [list marker](@) is a
+ // [bullet list marker] or an [ordered list marker].
+ //
+ // A [bullet list marker](@)
+ // is a `-`, `+`, or `*` character.
+ //
+ // An [ordered list marker](@)
+ // is a sequence of 1--9 arabic digits (`0-9`), followed by either a
+ // `.` character or a `)` character. (The reason for the length
+ // limit is that with 10 digits we start seeing integer overflows
+ // in some browsers.)
+ //
+ // The following rules define [list items]:
+ //
+ // 1. **Basic case.** If a sequence of lines *Ls* constitute a sequence of
+ // blocks *Bs* starting with a [non-whitespace character] and not separated
+ // from each other by more than one blank line, and *M* is a list
+ // marker of width *W* followed by 1 ≤ *N* ≤ 4 spaces, then the result
+ // of prepending *M* and the following spaces to the first line of
+ // *Ls*, and indenting subsequent lines of *Ls* by *W + N* spaces, is a
+ // list item with *Bs* as its contents. The type of the list item
+ // (bullet or ordered) is determined by the type of its list marker.
+ // If the list item is ordered, then it is also assigned a start
+ // number, based on the ordered list marker.
+ //
+ // Exceptions:
+ //
+ // 1. When the first list item in a [list] interrupts
+ // a paragraph---that is, when it starts on a line that would
+ // otherwise count as [paragraph continuation text]---then (a)
+ // the lines *Ls* must not begin with a blank line, and (b) if
+ // the list item is ordered, the start number must be 1.
+ // 2. If any line is a [thematic break][thematic breaks] then
+ // that line is not a list item.
+ //
+ // For example, let *Ls* be the lines
+ [Test]
+ public void ContainerBlocksListItems_Example216()
+ {
+ // Example 216
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+ // Should be rendered as:
+ // A paragraph
+ // with two lines.
+ // indented code
+ //
+ //
+ // A block quote.
+ //
+
+ Console.WriteLine("Example 216\nSection Container blocks / List items\n");
+ TestParser.TestSpec("A paragraph\nwith two lines.\n\n indented code\n\n> A block quote.", "A paragraph\nwith two lines.
\nindented code\n
\n\nA block quote.
\n
", "");
+ }
+
+ // And let *M* be the marker `1.`, and *N* = 2. Then rule #1 says
+ // that the following is an ordered list item with start number 1,
+ // and the same contents as *Ls*:
+ [Test]
+ public void ContainerBlocksListItems_Example217()
+ {
+ // Example 217
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
A paragraph
+ // with two lines.
+ // indented code
+ //
+ //
+ // A block quote.
+ //
+ //
+ //
+
+ Console.WriteLine("Example 217\nSection Container blocks / List items\n");
+ TestParser.TestSpec("1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.", "\n- \n
A paragraph\nwith two lines.
\nindented code\n
\n\nA block quote.
\n
\n \n
", "");
+ }
+
+ // The most important thing to notice is that the position of
+ // the text after the list marker determines how much indentation
+ // is needed in subsequent blocks in the list item. If the list
+ // marker takes up two spaces, and there are three spaces between
+ // the list marker and the next [non-whitespace character], then blocks
+ // must be indented five spaces in order to fall under the list
+ // item.
+ //
+ // Here are some examples showing how far content must be indented to be
+ // put under the list item:
+ [Test]
+ public void ContainerBlocksListItems_Example218()
+ {
+ // Example 218
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - one
+ //
+ // two
+ //
+ // Should be rendered as:
+ //
+ // two
+
+ Console.WriteLine("Example 218\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- one\n\n two", "\ntwo
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example219()
+ {
+ // Example 219
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - one
+ //
+ // two
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
one
+ // two
+ //
+ //
+
+ Console.WriteLine("Example 219\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- one\n\n two", "", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example220()
+ {
+ // Example 220
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - one
+ //
+ // two
+ //
+ // Should be rendered as:
+ //
+ // two
+ //
+
+ Console.WriteLine("Example 220\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" - one\n\n two", "\n two\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example221()
+ {
+ // Example 221
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - one
+ //
+ // two
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
one
+ // two
+ //
+ //
+
+ Console.WriteLine("Example 221\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" - one\n\n two", "", "");
+ }
+
+ // It is tempting to think of this in terms of columns: the continuation
+ // blocks must be indented at least to the column of the first
+ // [non-whitespace character] after the list marker. However, that is not quite right.
+ // The spaces after the list marker determine how much relative indentation
+ // is needed. Which column this indentation reaches will depend on
+ // how the list item is embedded in other constructions, as shown by
+ // this example:
+ [Test]
+ public void ContainerBlocksListItems_Example222()
+ {
+ // Example 222
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // > > 1. one
+ // >>
+ // >> two
+ //
+ // Should be rendered as:
+ //
+ //
+ //
+ // -
+ //
one
+ // two
+ //
+ //
+ //
+ //
+
+ Console.WriteLine("Example 222\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" > > 1. one\n>>\n>> two", "\n\n\n- \n
one
\ntwo
\n \n
\n
\n
", "");
+ }
+
+ // Here `two` occurs in the same column as the list marker `1.`,
+ // but is actually contained in the list item, because there is
+ // sufficient indentation after the last containing blockquote marker.
+ //
+ // The converse is also possible. In the following example, the word `two`
+ // occurs far to the right of the initial text of the list item, `one`, but
+ // it is not considered part of the list item, because it is not indented
+ // far enough past the blockquote marker:
+ [Test]
+ public void ContainerBlocksListItems_Example223()
+ {
+ // Example 223
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // >>- one
+ // >>
+ // > > two
+ //
+ // Should be rendered as:
+ //
+ //
+ //
+ // two
+ //
+ //
+
+ Console.WriteLine("Example 223\nSection Container blocks / List items\n");
+ TestParser.TestSpec(">>- one\n>>\n > > two", "\n\n\ntwo
\n
\n
", "");
+ }
+
+ // Note that at least one space is needed between the list marker and
+ // any following content, so these are not list items:
+ [Test]
+ public void ContainerBlocksListItems_Example224()
+ {
+ // Example 224
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // -one
+ //
+ // 2.two
+ //
+ // Should be rendered as:
+ // -one
+ // 2.two
+
+ Console.WriteLine("Example 224\nSection Container blocks / List items\n");
+ TestParser.TestSpec("-one\n\n2.two", "-one
\n2.two
", "");
+ }
+
+ // A list item may contain blocks that are separated by more than
+ // one blank line.
+ [Test]
+ public void ContainerBlocksListItems_Example225()
+ {
+ // Example 225
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ //
+ //
+ // bar
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ // bar
+ //
+ //
+
+ Console.WriteLine("Example 225\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n\n\n bar", "", "");
+ }
+
+ // A list item may contain any kind of block:
+ [Test]
+ public void ContainerBlocksListItems_Example226()
+ {
+ // Example 226
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. foo
+ //
+ // ```
+ // bar
+ // ```
+ //
+ // baz
+ //
+ // > bam
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ // bar
+ //
+ // baz
+ //
+ // bam
+ //
+ //
+ //
+
+ Console.WriteLine("Example 226\nSection Container blocks / List items\n");
+ TestParser.TestSpec("1. foo\n\n ```\n bar\n ```\n\n baz\n\n > bam", "\n- \n
foo
\nbar\n
\nbaz
\n\nbam
\n
\n \n
", "");
+ }
+
+ // A list item that contains an indented code block will preserve
+ // empty lines within the code block verbatim.
+ [Test]
+ public void ContainerBlocksListItems_Example227()
+ {
+ // Example 227
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - Foo
+ //
+ // bar
+ //
+ //
+ // baz
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 227\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- Foo\n\n bar\n\n\n baz", "\n- \n
Foo
\nbar\n\n\nbaz\n
\n \n
", "");
+ }
+
+ // Note that ordered list start numbers must be nine digits or less:
+ [Test]
+ public void ContainerBlocksListItems_Example228()
+ {
+ // Example 228
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 123456789. ok
+ //
+ // Should be rendered as:
+ //
+ // - ok
+ //
+
+ Console.WriteLine("Example 228\nSection Container blocks / List items\n");
+ TestParser.TestSpec("123456789. ok", "\n- ok
\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example229()
+ {
+ // Example 229
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1234567890. not ok
+ //
+ // Should be rendered as:
+ // 1234567890. not ok
+
+ Console.WriteLine("Example 229\nSection Container blocks / List items\n");
+ TestParser.TestSpec("1234567890. not ok", "1234567890. not ok
", "");
+ }
+
+ // A start number may begin with 0s:
+ [Test]
+ public void ContainerBlocksListItems_Example230()
+ {
+ // Example 230
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 0. ok
+ //
+ // Should be rendered as:
+ //
+ // - ok
+ //
+
+ Console.WriteLine("Example 230\nSection Container blocks / List items\n");
+ TestParser.TestSpec("0. ok", "\n- ok
\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example231()
+ {
+ // Example 231
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 003. ok
+ //
+ // Should be rendered as:
+ //
+ // - ok
+ //
+
+ Console.WriteLine("Example 231\nSection Container blocks / List items\n");
+ TestParser.TestSpec("003. ok", "\n- ok
\n
", "");
+ }
+
+ // A start number may not be negative:
+ [Test]
+ public void ContainerBlocksListItems_Example232()
+ {
+ // Example 232
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // -1. not ok
+ //
+ // Should be rendered as:
+ // -1. not ok
+
+ Console.WriteLine("Example 232\nSection Container blocks / List items\n");
+ TestParser.TestSpec("-1. not ok", "-1. not ok
", "");
+ }
+
+ // 2. **Item starting with indented code.** If a sequence of lines *Ls*
+ // constitute a sequence of blocks *Bs* starting with an indented code
+ // block and not separated from each other by more than one blank line,
+ // and *M* is a list marker of width *W* followed by
+ // one space, then the result of prepending *M* and the following
+ // space to the first line of *Ls*, and indenting subsequent lines of
+ // *Ls* by *W + 1* spaces, is a list item with *Bs* as its contents.
+ // If a line is empty, then it need not be indented. The type of the
+ // list item (bullet or ordered) is determined by the type of its list
+ // marker. If the list item is ordered, then it is also assigned a
+ // start number, based on the ordered list marker.
+ //
+ // An indented code block will have to be indented four spaces beyond
+ // the edge of the region where text will be included in the list item.
+ // In the following case that is 6 spaces:
+ [Test]
+ public void ContainerBlocksListItems_Example233()
+ {
+ // Example 233
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ //
+ // bar
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ // bar
+ //
+ //
+ //
+
+ Console.WriteLine("Example 233\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n\n bar", "", "");
+ }
+
+ // And in this case it is 11 spaces:
+ [Test]
+ public void ContainerBlocksListItems_Example234()
+ {
+ // Example 234
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 10. foo
+ //
+ // bar
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ // bar
+ //
+ //
+ //
+
+ Console.WriteLine("Example 234\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" 10. foo\n\n bar", "\n- \n
foo
\nbar\n
\n \n
", "");
+ }
+
+ // If the *first* block in the list item is an indented code block,
+ // then by rule #2, the contents must be indented *one* space after the
+ // list marker:
+ [Test]
+ public void ContainerBlocksListItems_Example235()
+ {
+ // Example 235
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // indented code
+ //
+ // paragraph
+ //
+ // more code
+ //
+ // Should be rendered as:
+ // indented code
+ //
+ // paragraph
+ // more code
+ //
+
+ Console.WriteLine("Example 235\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" indented code\n\nparagraph\n\n more code", "indented code\n
\nparagraph
\nmore code\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example236()
+ {
+ // Example 236
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. indented code
+ //
+ // paragraph
+ //
+ // more code
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
indented code
+ //
+ // paragraph
+ // more code
+ //
+ //
+ //
+
+ Console.WriteLine("Example 236\nSection Container blocks / List items\n");
+ TestParser.TestSpec("1. indented code\n\n paragraph\n\n more code", "\n- \n
indented code\n
\nparagraph
\nmore code\n
\n \n
", "");
+ }
+
+ // Note that an additional space indent is interpreted as space
+ // inside the code block:
+ [Test]
+ public void ContainerBlocksListItems_Example237()
+ {
+ // Example 237
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. indented code
+ //
+ // paragraph
+ //
+ // more code
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
indented code
+ //
+ // paragraph
+ // more code
+ //
+ //
+ //
+
+ Console.WriteLine("Example 237\nSection Container blocks / List items\n");
+ TestParser.TestSpec("1. indented code\n\n paragraph\n\n more code", "\n- \n
indented code\n
\nparagraph
\nmore code\n
\n \n
", "");
+ }
+
+ // Note that rules #1 and #2 only apply to two cases: (a) cases
+ // in which the lines to be included in a list item begin with a
+ // [non-whitespace character], and (b) cases in which
+ // they begin with an indented code
+ // block. In a case like the following, where the first block begins with
+ // a three-space indent, the rules do not allow us to form a list item by
+ // indenting the whole thing and prepending a list marker:
+ [Test]
+ public void ContainerBlocksListItems_Example238()
+ {
+ // Example 238
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // foo
+ //
+ // bar
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 238\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" foo\n\nbar", "foo
\nbar
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example239()
+ {
+ // Example 239
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ //
+ // bar
+ //
+ // Should be rendered as:
+ //
+ // bar
+
+ Console.WriteLine("Example 239\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n\n bar", "\nbar
", "");
+ }
+
+ // This is not a significant restriction, because when a block begins
+ // with 1-3 spaces indent, the indentation can always be removed without
+ // a change in interpretation, allowing rule #1 to be applied. So, in
+ // the above case:
+ [Test]
+ public void ContainerBlocksListItems_Example240()
+ {
+ // Example 240
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ //
+ // bar
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ // bar
+ //
+ //
+
+ Console.WriteLine("Example 240\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n\n bar", "", "");
+ }
+
+ // 3. **Item starting with a blank line.** If a sequence of lines *Ls*
+ // starting with a single [blank line] constitute a (possibly empty)
+ // sequence of blocks *Bs*, not separated from each other by more than
+ // one blank line, and *M* is a list marker of width *W*,
+ // then the result of prepending *M* to the first line of *Ls*, and
+ // indenting subsequent lines of *Ls* by *W + 1* spaces, is a list
+ // item with *Bs* as its contents.
+ // If a line is empty, then it need not be indented. The type of the
+ // list item (bullet or ordered) is determined by the type of its list
+ // marker. If the list item is ordered, then it is also assigned a
+ // start number, based on the ordered list marker.
+ //
+ // Here are some list items that start with a blank line but are not empty:
+ [Test]
+ public void ContainerBlocksListItems_Example241()
+ {
+ // Example 241
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // -
+ // foo
+ // -
+ // ```
+ // bar
+ // ```
+ // -
+ // baz
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ // -
+ //
bar
+ //
+ //
+ // -
+ //
baz
+ //
+ //
+ //
+
+ Console.WriteLine("Example 241\nSection Container blocks / List items\n");
+ TestParser.TestSpec("-\n foo\n-\n ```\n bar\n ```\n-\n baz", "\n- foo
\n- \n
bar\n
\n \n- \n
baz\n
\n \n
", "");
+ }
+
+ // When the list item starts with a blank line, the number of spaces
+ // following the list marker doesn't change the required indentation:
+ [Test]
+ public void ContainerBlocksListItems_Example242()
+ {
+ // Example 242
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // -
+ // foo
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 242\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- \n foo", "", "");
+ }
+
+ // A list item can begin with at most one blank line.
+ // In the following example, `foo` is not part of the list
+ // item:
+ [Test]
+ public void ContainerBlocksListItems_Example243()
+ {
+ // Example 243
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // -
+ //
+ // foo
+ //
+ // Should be rendered as:
+ //
+ // foo
+
+ Console.WriteLine("Example 243\nSection Container blocks / List items\n");
+ TestParser.TestSpec("-\n\n foo", "\nfoo
", "");
+ }
+
+ // Here is an empty bullet list item:
+ [Test]
+ public void ContainerBlocksListItems_Example244()
+ {
+ // Example 244
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ // -
+ // - bar
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ //
+ // - bar
+ //
+
+ Console.WriteLine("Example 244\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n-\n- bar", "", "");
+ }
+
+ // It does not matter whether there are spaces following the [list marker]:
+ [Test]
+ public void ContainerBlocksListItems_Example245()
+ {
+ // Example 245
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ // -
+ // - bar
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ //
+ // - bar
+ //
+
+ Console.WriteLine("Example 245\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n- \n- bar", "", "");
+ }
+
+ // Here is an empty ordered list item:
+ [Test]
+ public void ContainerBlocksListItems_Example246()
+ {
+ // Example 246
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. foo
+ // 2.
+ // 3. bar
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ //
+ // - bar
+ //
+
+ Console.WriteLine("Example 246\nSection Container blocks / List items\n");
+ TestParser.TestSpec("1. foo\n2.\n3. bar", "\n- foo
\n\n- bar
\n
", "");
+ }
+
+ // A list may start or end with an empty list item:
+ [Test]
+ public void ContainerBlocksListItems_Example247()
+ {
+ // Example 247
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // *
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 247\nSection Container blocks / List items\n");
+ TestParser.TestSpec("*", "", "");
+ }
+
+ // However, an empty list item cannot interrupt a paragraph:
+ [Test]
+ public void ContainerBlocksListItems_Example248()
+ {
+ // Example 248
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // foo
+ // *
+ //
+ // foo
+ // 1.
+ //
+ // Should be rendered as:
+ // foo
+ // *
+ // foo
+ // 1.
+
+ Console.WriteLine("Example 248\nSection Container blocks / List items\n");
+ TestParser.TestSpec("foo\n*\n\nfoo\n1.", "foo\n*
\nfoo\n1.
", "");
+ }
+
+ // 4. **Indentation.** If a sequence of lines *Ls* constitutes a list item
+ // according to rule #1, #2, or #3, then the result of indenting each line
+ // of *Ls* by 1-3 spaces (the same for each line) also constitutes a
+ // list item with the same contents and attributes. If a line is
+ // empty, then it need not be indented.
+ //
+ // Indented one space:
+ [Test]
+ public void ContainerBlocksListItems_Example249()
+ {
+ // Example 249
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
A paragraph
+ // with two lines.
+ // indented code
+ //
+ //
+ // A block quote.
+ //
+ //
+ //
+
+ Console.WriteLine("Example 249\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.", "\n- \n
A paragraph\nwith two lines.
\nindented code\n
\n\nA block quote.
\n
\n \n
", "");
+ }
+
+ // Indented two spaces:
+ [Test]
+ public void ContainerBlocksListItems_Example250()
+ {
+ // Example 250
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
A paragraph
+ // with two lines.
+ // indented code
+ //
+ //
+ // A block quote.
+ //
+ //
+ //
+
+ Console.WriteLine("Example 250\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.", "\n- \n
A paragraph\nwith two lines.
\nindented code\n
\n\nA block quote.
\n
\n \n
", "");
+ }
+
+ // Indented three spaces:
+ [Test]
+ public void ContainerBlocksListItems_Example251()
+ {
+ // Example 251
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
A paragraph
+ // with two lines.
+ // indented code
+ //
+ //
+ // A block quote.
+ //
+ //
+ //
+
+ Console.WriteLine("Example 251\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.", "\n- \n
A paragraph\nwith two lines.
\nindented code\n
\n\nA block quote.
\n
\n \n
", "");
+ }
+
+ // Four spaces indent gives a code block:
+ [Test]
+ public void ContainerBlocksListItems_Example252()
+ {
+ // Example 252
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+ // Should be rendered as:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+
+ Console.WriteLine("Example 252\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" 1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.", "1. A paragraph\n with two lines.\n\n indented code\n\n > A block quote.\n
", "");
+ }
+
+ // 5. **Laziness.** If a string of lines *Ls* constitute a [list
+ // item](#list-items) with contents *Bs*, then the result of deleting
+ // some or all of the indentation from one or more lines in which the
+ // next [non-whitespace character] after the indentation is
+ // [paragraph continuation text] is a
+ // list item with the same contents and attributes. The unindented
+ // lines are called
+ // [lazy continuation line](@)s.
+ //
+ // Here is an example with [lazy continuation lines]:
+ [Test]
+ public void ContainerBlocksListItems_Example253()
+ {
+ // Example 253
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // indented code
+ //
+ // > A block quote.
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
A paragraph
+ // with two lines.
+ // indented code
+ //
+ //
+ // A block quote.
+ //
+ //
+ //
+
+ Console.WriteLine("Example 253\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" 1. A paragraph\nwith two lines.\n\n indented code\n\n > A block quote.", "\n- \n
A paragraph\nwith two lines.
\nindented code\n
\n\nA block quote.
\n
\n \n
", "");
+ }
+
+ // Indentation can be partially deleted:
+ [Test]
+ public void ContainerBlocksListItems_Example254()
+ {
+ // Example 254
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. A paragraph
+ // with two lines.
+ //
+ // Should be rendered as:
+ //
+ // - A paragraph
+ // with two lines.
+ //
+
+ Console.WriteLine("Example 254\nSection Container blocks / List items\n");
+ TestParser.TestSpec(" 1. A paragraph\n with two lines.", "\n- A paragraph\nwith two lines.
\n
", "");
+ }
+
+ // These examples show how laziness can work in nested structures:
+ [Test]
+ public void ContainerBlocksListItems_Example255()
+ {
+ // Example 255
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // > 1. > Blockquote
+ // continued here.
+ //
+ // Should be rendered as:
+ //
+ //
+ // -
+ //
+ // Blockquote
+ // continued here.
+ //
+ //
+ //
+ //
+
+ Console.WriteLine("Example 255\nSection Container blocks / List items\n");
+ TestParser.TestSpec("> 1. > Blockquote\ncontinued here.", "\n\n- \n
\nBlockquote\ncontinued here.
\n
\n \n
\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example256()
+ {
+ // Example 256
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // > 1. > Blockquote
+ // > continued here.
+ //
+ // Should be rendered as:
+ //
+ //
+ // -
+ //
+ // Blockquote
+ // continued here.
+ //
+ //
+ //
+ //
+
+ Console.WriteLine("Example 256\nSection Container blocks / List items\n");
+ TestParser.TestSpec("> 1. > Blockquote\n> continued here.", "\n\n- \n
\nBlockquote\ncontinued here.
\n
\n \n
\n
", "");
+ }
+
+ // 6. **That's all.** Nothing that is not counted as a list item by rules
+ // #1--5 counts as a [list item](#list-items).
+ //
+ // The rules for sublists follow from the general rules above. A sublist
+ // must be indented the same number of spaces a paragraph would need to be
+ // in order to be included in the list item.
+ //
+ // So, in this case we need two spaces indent:
+ [Test]
+ public void ContainerBlocksListItems_Example257()
+ {
+ // Example 257
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ // - bar
+ // - baz
+ // - boo
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 257\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n - bar\n - baz\n - boo", "", "");
+ }
+
+ // One is not enough:
+ [Test]
+ public void ContainerBlocksListItems_Example258()
+ {
+ // Example 258
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - foo
+ // - bar
+ // - baz
+ // - boo
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ // - bar
+ // - baz
+ // - boo
+ //
+
+ Console.WriteLine("Example 258\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- foo\n - bar\n - baz\n - boo", "", "");
+ }
+
+ // Here we need four, because the list marker is wider:
+ [Test]
+ public void ContainerBlocksListItems_Example259()
+ {
+ // Example 259
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 10) foo
+ // - bar
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ //
+ //
+ //
+
+ Console.WriteLine("Example 259\nSection Container blocks / List items\n");
+ TestParser.TestSpec("10) foo\n - bar", "\n- foo\n\n
\n
", "");
+ }
+
+ // Three is not enough:
+ [Test]
+ public void ContainerBlocksListItems_Example260()
+ {
+ // Example 260
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 10) foo
+ // - bar
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ //
+ //
+
+ Console.WriteLine("Example 260\nSection Container blocks / List items\n");
+ TestParser.TestSpec("10) foo\n - bar", "\n- foo
\n
\n", "");
+ }
+
+ // A list may be the first block in a list item:
+ [Test]
+ public void ContainerBlocksListItems_Example261()
+ {
+ // Example 261
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - - foo
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 261\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- - foo", "", "");
+ }
+
+ [Test]
+ public void ContainerBlocksListItems_Example262()
+ {
+ // Example 262
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // 1. - 2. foo
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
+ // -
+ //
+ // - foo
+ //
+ //
+ //
+ //
+ //
+
+ Console.WriteLine("Example 262\nSection Container blocks / List items\n");
+ TestParser.TestSpec("1. - 2. foo", "\n- \n\n
\n
", "");
+ }
+
+ // A list item can contain a heading:
+ [Test]
+ public void ContainerBlocksListItems_Example263()
+ {
+ // Example 263
+ // Section: Container blocks / List items
+ //
+ // The following Markdown:
+ // - # Foo
+ // - Bar
+ // ---
+ // baz
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
Foo
+ //
+ // -
+ //
Bar
+ // baz
+ //
+
+ Console.WriteLine("Example 263\nSection Container blocks / List items\n");
+ TestParser.TestSpec("- # Foo\n- Bar\n ---\n baz", "", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestContainerBlocksLists
+ {
+ // ### Motivation
+ //
+ // John Gruber's Markdown spec says the following about list items:
+ //
+ // 1. "List markers typically start at the left margin, but may be indented
+ // by up to three spaces. List markers must be followed by one or more
+ // spaces or a tab."
+ //
+ // 2. "To make lists look nice, you can wrap items with hanging indents....
+ // But if you don't want to, you don't have to."
+ //
+ // 3. "List items may consist of multiple paragraphs. Each subsequent
+ // paragraph in a list item must be indented by either 4 spaces or one
+ // tab."
+ //
+ // 4. "It looks nice if you indent every line of the subsequent paragraphs,
+ // but here again, Markdown will allow you to be lazy."
+ //
+ // 5. "To put a blockquote within a list item, the blockquote's `>`
+ // delimiters need to be indented."
+ //
+ // 6. "To put a code block within a list item, the code block needs to be
+ // indented twice — 8 spaces or two tabs."
+ //
+ // These rules specify that a paragraph under a list item must be indented
+ // four spaces (presumably, from the left margin, rather than the start of
+ // the list marker, but this is not said), and that code under a list item
+ // must be indented eight spaces instead of the usual four. They also say
+ // that a block quote must be indented, but not by how much; however, the
+ // example given has four spaces indentation. Although nothing is said
+ // about other kinds of block-level content, it is certainly reasonable to
+ // infer that *all* block elements under a list item, including other
+ // lists, must be indented four spaces. This principle has been called the
+ // *four-space rule*.
+ //
+ // The four-space rule is clear and principled, and if the reference
+ // implementation `Markdown.pl` had followed it, it probably would have
+ // become the standard. However, `Markdown.pl` allowed paragraphs and
+ // sublists to start with only two spaces indentation, at least on the
+ // outer level. Worse, its behavior was inconsistent: a sublist of an
+ // outer-level list needed two spaces indentation, but a sublist of this
+ // sublist needed three spaces. It is not surprising, then, that different
+ // implementations of Markdown have developed very different rules for
+ // determining what comes under a list item. (Pandoc and python-Markdown,
+ // for example, stuck with Gruber's syntax description and the four-space
+ // rule, while discount, redcarpet, marked, PHP Markdown, and others
+ // followed `Markdown.pl`'s behavior more closely.)
+ //
+ // Unfortunately, given the divergences between implementations, there
+ // is no way to give a spec for list items that will be guaranteed not
+ // to break any existing documents. However, the spec given here should
+ // correctly handle lists formatted with either the four-space rule or
+ // the more forgiving `Markdown.pl` behavior, provided they are laid out
+ // in a way that is natural for a human to read.
+ //
+ // The strategy here is to let the width and indentation of the list marker
+ // determine the indentation necessary for blocks to fall under the list
+ // item, rather than having a fixed and arbitrary number. The writer can
+ // think of the body of the list item as a unit which gets indented to the
+ // right enough to fit the list marker (and any indentation on the list
+ // marker). (The laziness rule, #5, then allows continuation lines to be
+ // unindented if needed.)
+ //
+ // This rule is superior, we claim, to any rule requiring a fixed level of
+ // indentation from the margin. The four-space rule is clear but
+ // unnatural. It is quite unintuitive that
+ //
+ // ``` markdown
+ // - foo
+ //
+ // bar
+ //
+ // - baz
+ // ```
+ //
+ // should be parsed as two lists with an intervening paragraph,
+ //
+ // ``` html
+ //
+ // bar
+ //
+ // ```
+ //
+ // as the four-space rule demands, rather than a single list,
+ //
+ // ``` html
+ //
+ // -
+ //
foo
+ // bar
+ //
+ //
+ //
+ // ```
+ //
+ // The choice of four spaces is arbitrary. It can be learned, but it is
+ // not likely to be guessed, and it trips up beginners regularly.
+ //
+ // Would it help to adopt a two-space rule? The problem is that such
+ // a rule, together with the rule allowing 1--3 spaces indentation of the
+ // initial list marker, allows text that is indented *less than* the
+ // original list marker to be included in the list item. For example,
+ // `Markdown.pl` parses
+ //
+ // ``` markdown
+ // - one
+ //
+ // two
+ // ```
+ //
+ // as a single list item, with `two` a continuation paragraph:
+ //
+ // ``` html
+ //
+ // -
+ //
one
+ // two
+ //
+ //
+ // ```
+ //
+ // and similarly
+ //
+ // ``` markdown
+ // > - one
+ // >
+ // > two
+ // ```
+ //
+ // as
+ //
+ // ``` html
+ //
+ //
+ // -
+ //
one
+ // two
+ //
+ //
+ //
+ // ```
+ //
+ // This is extremely unintuitive.
+ //
+ // Rather than requiring a fixed indent from the margin, we could require
+ // a fixed indent (say, two spaces, or even one space) from the list marker (which
+ // may itself be indented). This proposal would remove the last anomaly
+ // discussed. Unlike the spec presented above, it would count the following
+ // as a list item with a subparagraph, even though the paragraph `bar`
+ // is not indented as far as the first paragraph `foo`:
+ //
+ // ``` markdown
+ // 10. foo
+ //
+ // bar
+ // ```
+ //
+ // Arguably this text does read like a list item with `bar` as a subparagraph,
+ // which may count in favor of the proposal. However, on this proposal indented
+ // code would have to be indented six spaces after the list marker. And this
+ // would break a lot of existing Markdown, which has the pattern:
+ //
+ // ``` markdown
+ // 1. foo
+ //
+ // indented code
+ // ```
+ //
+ // where the code is indented eight spaces. The spec above, by contrast, will
+ // parse this text as expected, since the code block's indentation is measured
+ // from the beginning of `foo`.
+ //
+ // The one case that needs special treatment is a list item that *starts*
+ // with indented code. How much indentation is required in that case, since
+ // we don't have a "first paragraph" to measure from? Rule #2 simply stipulates
+ // that in such cases, we require one space indentation from the list marker
+ // (and then the normal four spaces for the indented code). This will match the
+ // four-space rule in cases where the list marker plus its initial indentation
+ // takes four spaces (a common case), but diverge in other cases.
+ //
+ // ## Lists
+ //
+ // A [list](@) is a sequence of one or more
+ // list items [of the same type]. The list items
+ // may be separated by any number of blank lines.
+ //
+ // Two list items are [of the same type](@)
+ // if they begin with a [list marker] of the same type.
+ // Two list markers are of the
+ // same type if (a) they are bullet list markers using the same character
+ // (`-`, `+`, or `*`) or (b) they are ordered list numbers with the same
+ // delimiter (either `.` or `)`).
+ //
+ // A list is an [ordered list](@)
+ // if its constituent list items begin with
+ // [ordered list markers], and a
+ // [bullet list](@) if its constituent list
+ // items begin with [bullet list markers].
+ //
+ // The [start number](@)
+ // of an [ordered list] is determined by the list number of
+ // its initial list item. The numbers of subsequent list items are
+ // disregarded.
+ //
+ // A list is [loose](@) if any of its constituent
+ // list items are separated by blank lines, or if any of its constituent
+ // list items directly contain two block-level elements with a blank line
+ // between them. Otherwise a list is [tight](@).
+ // (The difference in HTML output is that paragraphs in a loose list are
+ // wrapped in `` tags, while paragraphs in a tight list are not.)
+ //
+ // Changing the bullet or ordered list delimiter starts a new list:
+ [Test]
+ public void ContainerBlocksLists_Example264()
+ {
+ // Example 264
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - foo
+ // - bar
+ // + baz
+ //
+ // Should be rendered as:
+ //
+ //
+
+ Console.WriteLine("Example 264\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- foo\n- bar\n+ baz", "\n", "");
+ }
+
+ [Test]
+ public void ContainerBlocksLists_Example265()
+ {
+ // Example 265
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // 1. foo
+ // 2. bar
+ // 3) baz
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ // - bar
+ //
+ //
+ // - baz
+ //
+
+ Console.WriteLine("Example 265\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("1. foo\n2. bar\n3) baz", "\n- foo
\n- bar
\n
\n\n- baz
\n
", "");
+ }
+
+ // In CommonMark, a list can interrupt a paragraph. That is,
+ // no blank line is needed to separate a paragraph from a following
+ // list:
+ [Test]
+ public void ContainerBlocksLists_Example266()
+ {
+ // Example 266
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // Foo
+ // - bar
+ // - baz
+ //
+ // Should be rendered as:
+ // Foo
+ //
+
+ Console.WriteLine("Example 266\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("Foo\n- bar\n- baz", "Foo
\n", "");
+ }
+
+ // `Markdown.pl` does not allow this, through fear of triggering a list
+ // via a numeral in a hard-wrapped line:
+ //
+ // ``` markdown
+ // The number of windows in my house is
+ // 14. The number of doors is 6.
+ // ```
+ //
+ // Oddly, though, `Markdown.pl` *does* allow a blockquote to
+ // interrupt a paragraph, even though the same considerations might
+ // apply.
+ //
+ // In CommonMark, we do allow lists to interrupt paragraphs, for
+ // two reasons. First, it is natural and not uncommon for people
+ // to start lists without blank lines:
+ //
+ // ``` markdown
+ // I need to buy
+ // - new shoes
+ // - a coat
+ // - a plane ticket
+ // ```
+ //
+ // Second, we are attracted to a
+ //
+ // > [principle of uniformity](@):
+ // > if a chunk of text has a certain
+ // > meaning, it will continue to have the same meaning when put into a
+ // > container block (such as a list item or blockquote).
+ //
+ // (Indeed, the spec for [list items] and [block quotes] presupposes
+ // this principle.) This principle implies that if
+ //
+ // ``` markdown
+ // * I need to buy
+ // - new shoes
+ // - a coat
+ // - a plane ticket
+ // ```
+ //
+ // is a list item containing a paragraph followed by a nested sublist,
+ // as all Markdown implementations agree it is (though the paragraph
+ // may be rendered without `` tags, since the list is "tight"),
+ // then
+ //
+ // ``` markdown
+ // I need to buy
+ // - new shoes
+ // - a coat
+ // - a plane ticket
+ // ```
+ //
+ // by itself should be a paragraph followed by a nested sublist.
+ //
+ // Since it is well established Markdown practice to allow lists to
+ // interrupt paragraphs inside list items, the [principle of
+ // uniformity] requires us to allow this outside list items as
+ // well. ([reStructuredText](http://docutils.sourceforge.net/rst.html)
+ // takes a different approach, requiring blank lines before lists
+ // even inside other list items.)
+ //
+ // In order to solve of unwanted lists in paragraphs with
+ // hard-wrapped numerals, we allow only lists starting with `1` to
+ // interrupt paragraphs. Thus,
+ [Test]
+ public void ContainerBlocksLists_Example267()
+ {
+ // Example 267
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // The number of windows in my house is
+ // 14. The number of doors is 6.
+ //
+ // Should be rendered as:
+ //
The number of windows in my house is
+ // 14. The number of doors is 6.
+
+ Console.WriteLine("Example 267\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("The number of windows in my house is\n14. The number of doors is 6.", "The number of windows in my house is\n14. The number of doors is 6.
", "");
+ }
+
+ // We may still get an unintended result in cases like
+ [Test]
+ public void ContainerBlocksLists_Example268()
+ {
+ // Example 268
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // The number of windows in my house is
+ // 1. The number of doors is 6.
+ //
+ // Should be rendered as:
+ // The number of windows in my house is
+ //
+ // - The number of doors is 6.
+ //
+
+ Console.WriteLine("Example 268\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("The number of windows in my house is\n1. The number of doors is 6.", "The number of windows in my house is
\n\n- The number of doors is 6.
\n
", "");
+ }
+
+ // but this rule should prevent most spurious list captures.
+ //
+ // There can be any number of blank lines between items:
+ [Test]
+ public void ContainerBlocksLists_Example269()
+ {
+ // Example 269
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - foo
+ //
+ // - bar
+ //
+ //
+ // - baz
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ //
+ // -
+ //
bar
+ //
+ // -
+ //
baz
+ //
+ //
+
+ Console.WriteLine("Example 269\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- foo\n\n- bar\n\n\n- baz", "\n- \n
foo
\n \n- \n
bar
\n \n- \n
baz
\n \n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksLists_Example270()
+ {
+ // Example 270
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - foo
+ // - bar
+ // - baz
+ //
+ //
+ // bim
+ //
+ // Should be rendered as:
+ //
+ // - foo
+ //
+ // - bar
+ //
+ // -
+ //
baz
+ // bim
+ //
+ //
+ //
+ //
+ //
+ //
+
+ Console.WriteLine("Example 270\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- foo\n - bar\n - baz\n\n\n bim", "", "");
+ }
+
+ // To separate consecutive lists of the same type, or to separate a
+ // list from an indented code block that would otherwise be parsed
+ // as a subparagraph of the final list item, you can insert a blank HTML
+ // comment:
+ [Test]
+ public void ContainerBlocksLists_Example271()
+ {
+ // Example 271
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - foo
+ // - bar
+ //
+ //
+ //
+ // - baz
+ // - bim
+ //
+ // Should be rendered as:
+ //
+ //
+ //
+
+ Console.WriteLine("Example 271\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- foo\n- bar\n\n\n\n- baz\n- bim", "\n\n", "");
+ }
+
+ [Test]
+ public void ContainerBlocksLists_Example272()
+ {
+ // Example 272
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - foo
+ //
+ // notcode
+ //
+ // - foo
+ //
+ //
+ //
+ // code
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ // notcode
+ //
+ // -
+ //
foo
+ //
+ //
+ //
+ // code
+ //
+
+ Console.WriteLine("Example 272\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- foo\n\n notcode\n\n- foo\n\n\n\n code", "\n- \n
foo
\nnotcode
\n \n- \n
foo
\n \n
\n\ncode\n
", "");
+ }
+
+ // List items need not be indented to the same level. The following
+ // list items will be treated as items at the same list level,
+ // since none is indented enough to belong to the previous list
+ // item:
+ [Test]
+ public void ContainerBlocksLists_Example273()
+ {
+ // Example 273
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - b
+ // - c
+ // - d
+ // - e
+ // - f
+ // - g
+ // - h
+ // - i
+ //
+ // Should be rendered as:
+ //
+ // - a
+ // - b
+ // - c
+ // - d
+ // - e
+ // - f
+ // - g
+ // - h
+ // - i
+ //
+
+ Console.WriteLine("Example 273\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n - b\n - c\n - d\n - e\n - f\n - g\n - h\n- i", "\n- a
\n- b
\n- c
\n- d
\n- e
\n- f
\n- g
\n- h
\n- i
\n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksLists_Example274()
+ {
+ // Example 274
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // 1. a
+ //
+ // 2. b
+ //
+ // 3. c
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
a
+ //
+ // -
+ //
b
+ //
+ // -
+ //
c
+ //
+ //
+
+ Console.WriteLine("Example 274\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("1. a\n\n 2. b\n\n 3. c", "\n- \n
a
\n \n- \n
b
\n \n- \n
c
\n \n
", "");
+ }
+
+ // This is a loose list, because there is a blank line between
+ // two of the list items:
+ [Test]
+ public void ContainerBlocksLists_Example275()
+ {
+ // Example 275
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - b
+ //
+ // - c
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
a
+ //
+ // -
+ //
b
+ //
+ // -
+ //
c
+ //
+ //
+
+ Console.WriteLine("Example 275\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n- b\n\n- c", "", "");
+ }
+
+ // So is this, with a empty second item:
+ [Test]
+ public void ContainerBlocksLists_Example276()
+ {
+ // Example 276
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // * a
+ // *
+ //
+ // * c
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
a
+ //
+ //
+ // -
+ //
c
+ //
+ //
+
+ Console.WriteLine("Example 276\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("* a\n*\n\n* c", "", "");
+ }
+
+ // These are loose lists, even though there is no space between the items,
+ // because one of the items directly contains two block-level elements
+ // with a blank line between them:
+ [Test]
+ public void ContainerBlocksLists_Example277()
+ {
+ // Example 277
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - b
+ //
+ // c
+ // - d
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
a
+ //
+ // -
+ //
b
+ // c
+ //
+ // -
+ //
d
+ //
+ //
+
+ Console.WriteLine("Example 277\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n- b\n\n c\n- d", "\n- \n
a
\n \n- \n
b
\nc
\n \n- \n
d
\n \n
", "");
+ }
+
+ [Test]
+ public void ContainerBlocksLists_Example278()
+ {
+ // Example 278
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - b
+ //
+ // [ref]: /url
+ // - d
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
a
+ //
+ // -
+ //
b
+ //
+ // -
+ //
d
+ //
+ //
+
+ Console.WriteLine("Example 278\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n- b\n\n [ref]: /url\n- d", "", "");
+ }
+
+ // This is a tight list, because the blank lines are in a code block:
+ [Test]
+ public void ContainerBlocksLists_Example279()
+ {
+ // Example 279
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - ```
+ // b
+ //
+ //
+ // ```
+ // - c
+ //
+ // Should be rendered as:
+ //
+ // - a
+ // -
+ //
b
+ //
+ //
+ //
+ //
+ // - c
+ //
+
+ Console.WriteLine("Example 279\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n- ```\n b\n\n\n ```\n- c", "", "");
+ }
+
+ // This is a tight list, because the blank line is between two
+ // paragraphs of a sublist. So the sublist is loose while
+ // the outer list is tight:
+ [Test]
+ public void ContainerBlocksLists_Example280()
+ {
+ // Example 280
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - b
+ //
+ // c
+ // - d
+ //
+ // Should be rendered as:
+ //
+ // - a
+ //
+ // -
+ //
b
+ // c
+ //
+ //
+ //
+ // - d
+ //
+
+ Console.WriteLine("Example 280\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n - b\n\n c\n- d", "", "");
+ }
+
+ // This is a tight list, because the blank line is inside the
+ // block quote:
+ [Test]
+ public void ContainerBlocksLists_Example281()
+ {
+ // Example 281
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // * a
+ // > b
+ // >
+ // * c
+ //
+ // Should be rendered as:
+ //
+ // - a
+ //
+ // b
+ //
+ //
+ // - c
+ //
+
+ Console.WriteLine("Example 281\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("* a\n > b\n >\n* c", "", "");
+ }
+
+ // This list is tight, because the consecutive block elements
+ // are not separated by blank lines:
+ [Test]
+ public void ContainerBlocksLists_Example282()
+ {
+ // Example 282
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // > b
+ // ```
+ // c
+ // ```
+ // - d
+ //
+ // Should be rendered as:
+ //
+ // - a
+ //
+ // b
+ //
+ // c
+ //
+ //
+ // - d
+ //
+
+ Console.WriteLine("Example 282\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n > b\n ```\n c\n ```\n- d", "", "");
+ }
+
+ // A single-paragraph list is tight:
+ [Test]
+ public void ContainerBlocksLists_Example283()
+ {
+ // Example 283
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 283\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a", "", "");
+ }
+
+ [Test]
+ public void ContainerBlocksLists_Example284()
+ {
+ // Example 284
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - b
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 284\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n - b", "", "");
+ }
+
+ // This list is loose, because of the blank line between the
+ // two block elements in the list item:
+ [Test]
+ public void ContainerBlocksLists_Example285()
+ {
+ // Example 285
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // 1. ```
+ // foo
+ // ```
+ //
+ // bar
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ //
+ // bar
+ //
+ //
+
+ Console.WriteLine("Example 285\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("1. ```\n foo\n ```\n\n bar", "\n- \n
foo\n
\nbar
\n \n
", "");
+ }
+
+ // Here the outer list is loose, the inner list tight:
+ [Test]
+ public void ContainerBlocksLists_Example286()
+ {
+ // Example 286
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // * foo
+ // * bar
+ //
+ // baz
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
foo
+ //
+ // baz
+ //
+ //
+
+ Console.WriteLine("Example 286\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("* foo\n * bar\n\n baz", "", "");
+ }
+
+ [Test]
+ public void ContainerBlocksLists_Example287()
+ {
+ // Example 287
+ // Section: Container blocks / Lists
+ //
+ // The following Markdown:
+ // - a
+ // - b
+ // - c
+ //
+ // - d
+ // - e
+ // - f
+ //
+ // Should be rendered as:
+ //
+ // -
+ //
a
+ //
+ //
+ // -
+ //
d
+ //
+ //
+ //
+
+ Console.WriteLine("Example 287\nSection Container blocks / Lists\n");
+ TestParser.TestSpec("- a\n - b\n - c\n\n- d\n - e\n - f", "", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlines
+ {
+ // # Inlines
+ //
+ // Inlines are parsed sequentially from the beginning of the character
+ // stream to the end (left to right, in left-to-right languages).
+ // Thus, for example, in
+ [Test]
+ public void Inlines_Example288()
+ {
+ // Example 288
+ // Section: Inlines
+ //
+ // The following Markdown:
+ // `hi`lo`
+ //
+ // Should be rendered as:
+ // hilo`
+
+ Console.WriteLine("Example 288\nSection Inlines\n");
+ TestParser.TestSpec("`hi`lo`", "hilo`
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesBackslashEscapes
+ {
+ // `hi` is parsed as code, leaving the backtick at the end as a literal
+ // backtick.
+ //
+ // ## Backslash escapes
+ //
+ // Any ASCII punctuation character may be backslash-escaped:
+ [Test]
+ public void InlinesBackslashEscapes_Example289()
+ {
+ // Example 289
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
+ //
+ // Should be rendered as:
+ // !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
+
+ Console.WriteLine("Example 289\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~", "!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~
", "");
+ }
+
+ // Backslashes before other characters are treated as literal
+ // backslashes:
+ [Test]
+ public void InlinesBackslashEscapes_Example290()
+ {
+ // Example 290
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // \→\A\a\ \3\φ\«
+ //
+ // Should be rendered as:
+ // \→\A\a\ \3\φ\«
+
+ Console.WriteLine("Example 290\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("\\\t\\A\\a\\ \\3\\φ\\«", "\\\t\\A\\a\\ \\3\\φ\\«
", "");
+ }
+
+ // Escaped characters are treated as regular characters and do
+ // not have their usual Markdown meanings:
+ [Test]
+ public void InlinesBackslashEscapes_Example291()
+ {
+ // Example 291
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // \*not emphasized*
+ // \
not a tag
+ // \[not a link](/foo)
+ // \`not code`
+ // 1\. not a list
+ // \* not a list
+ // \# not a heading
+ // \[foo]: /url "not a reference"
+ //
+ // Should be rendered as:
+ // *not emphasized*
+ // <br/> not a tag
+ // [not a link](/foo)
+ // `not code`
+ // 1. not a list
+ // * not a list
+ // # not a heading
+ // [foo]: /url "not a reference"
+
+ Console.WriteLine("Example 291\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("\\*not emphasized*\n\\
not a tag\n\\[not a link](/foo)\n\\`not code`\n1\\. not a list\n\\* not a list\n\\# not a heading\n\\[foo]: /url \"not a reference\"", "*not emphasized*\n<br/> not a tag\n[not a link](/foo)\n`not code`\n1. not a list\n* not a list\n# not a heading\n[foo]: /url "not a reference"
", "");
+ }
+
+ // If a backslash is itself escaped, the following character is not:
+ [Test]
+ public void InlinesBackslashEscapes_Example292()
+ {
+ // Example 292
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // \\*emphasis*
+ //
+ // Should be rendered as:
+ // \emphasis
+
+ Console.WriteLine("Example 292\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("\\\\*emphasis*", "\\emphasis
", "");
+ }
+
+ // A backslash at the end of the line is a [hard line break]:
+ [Test]
+ public void InlinesBackslashEscapes_Example293()
+ {
+ // Example 293
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // foo\
+ // bar
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 293\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("foo\\\nbar", "foo
\nbar
", "");
+ }
+
+ // Backslash escapes do not work in code blocks, code spans, autolinks, or
+ // raw HTML:
+ [Test]
+ public void InlinesBackslashEscapes_Example294()
+ {
+ // Example 294
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // `` \[\` ``
+ //
+ // Should be rendered as:
+ // \[\`
+
+ Console.WriteLine("Example 294\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("`` \\[\\` ``", "\\[\\`
", "");
+ }
+
+ [Test]
+ public void InlinesBackslashEscapes_Example295()
+ {
+ // Example 295
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // \[\]
+ //
+ // Should be rendered as:
+ // \[\]
+ //
+
+ Console.WriteLine("Example 295\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec(" \\[\\]", "\\[\\]\n
", "");
+ }
+
+ [Test]
+ public void InlinesBackslashEscapes_Example296()
+ {
+ // Example 296
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // ~~~
+ // \[\]
+ // ~~~
+ //
+ // Should be rendered as:
+ // \[\]
+ //
+
+ Console.WriteLine("Example 296\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("~~~\n\\[\\]\n~~~", "\\[\\]\n
", "");
+ }
+
+ [Test]
+ public void InlinesBackslashEscapes_Example297()
+ {
+ // Example 297
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // http://example.com?find=\*
+
+ Console.WriteLine("Example 297\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("", "http://example.com?find=\\*
", "");
+ }
+
+ [Test]
+ public void InlinesBackslashEscapes_Example298()
+ {
+ // Example 298
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 298\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("", "", "");
+ }
+
+ // But they work in all other contexts, including URLs and link titles,
+ // link references, and [info strings] in [fenced code blocks]:
+ [Test]
+ public void InlinesBackslashEscapes_Example299()
+ {
+ // Example 299
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // [foo](/bar\* "ti\*tle")
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 299\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("[foo](/bar\\* \"ti\\*tle\")", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesBackslashEscapes_Example300()
+ {
+ // Example 300
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // [foo]
+ //
+ // [foo]: /bar\* "ti\*tle"
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 300\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("[foo]\n\n[foo]: /bar\\* \"ti\\*tle\"", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesBackslashEscapes_Example301()
+ {
+ // Example 301
+ // Section: Inlines / Backslash escapes
+ //
+ // The following Markdown:
+ // ``` foo\+bar
+ // foo
+ // ```
+ //
+ // Should be rendered as:
+ // foo
+ //
+
+ Console.WriteLine("Example 301\nSection Inlines / Backslash escapes\n");
+ TestParser.TestSpec("``` foo\\+bar\nfoo\n```", "foo\n
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesEntityAndNumericCharacterReferences
+ {
+ // ## Entity and numeric character references
+ //
+ // All valid HTML entity references and numeric character
+ // references, except those occuring in code blocks and code spans,
+ // are recognized as such and treated as equivalent to the
+ // corresponding Unicode characters. Conforming CommonMark parsers
+ // need not store information about whether a particular character
+ // was represented in the source using a Unicode character or
+ // an entity reference.
+ //
+ // [Entity references](@) consist of `&` + any of the valid
+ // HTML5 entity names + `;`. The
+ // document
+ // is used as an authoritative source for the valid entity
+ // references and their corresponding code points.
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example302()
+ {
+ // Example 302
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // & © Æ Ď
+ // ¾ ℋ ⅆ
+ // ∲ ≧̸
+ //
+ // Should be rendered as:
+ // & © Æ Ď
+ // ¾ ℋ ⅆ
+ // ∲ ≧̸
+
+ Console.WriteLine("Example 302\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec(" & © Æ Ď\n¾ ℋ ⅆ\n∲ ≧̸", " & © Æ Ď\n¾ ℋ ⅆ\n∲ ≧̸
", "");
+ }
+
+ // [Decimal numeric character
+ // references](@)
+ // consist of `` + a string of 1--8 arabic digits + `;`. A
+ // numeric character reference is parsed as the corresponding
+ // Unicode character. Invalid Unicode code points will be replaced by
+ // the REPLACEMENT CHARACTER (`U+FFFD`). For security reasons,
+ // the code point `U+0000` will also be replaced by `U+FFFD`.
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example303()
+ {
+ // Example 303
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // # Ӓ Ϡ
+ //
+ // Should be rendered as:
+ // # Ӓ Ϡ � �
+
+ Console.WriteLine("Example 303\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("# Ӓ Ϡ ", "# Ӓ Ϡ � �
", "");
+ }
+
+ // [Hexadecimal numeric character
+ // references](@) consist of `` +
+ // either `X` or `x` + a string of 1-8 hexadecimal digits + `;`.
+ // They too are parsed as the corresponding Unicode character (this
+ // time specified with a hexadecimal numeral instead of decimal).
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example304()
+ {
+ // Example 304
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // " ആ ಫ
+ //
+ // Should be rendered as:
+ // " ആ ಫ
+
+ Console.WriteLine("Example 304\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("" ആ ಫ", "" ആ ಫ
", "");
+ }
+
+ // Here are some nonentities:
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example305()
+ {
+ // Example 305
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ //   &x;
+ // &ThisIsNotDefined; &hi?;
+ //
+ // Should be rendered as:
+ //   &x; &#; &#x;
+ // &ThisIsNotDefined; &hi?;
+
+ Console.WriteLine("Example 305\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("  &x; \n&ThisIsNotDefined; &hi?;", "  &x; &#; &#x;\n&ThisIsNotDefined; &hi?;
", "");
+ }
+
+ // Although HTML5 does accept some entity references
+ // without a trailing semicolon (such as `©`), these are not
+ // recognized here, because it makes the grammar too ambiguous:
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example306()
+ {
+ // Example 306
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // ©
+ //
+ // Should be rendered as:
+ // ©
+
+ Console.WriteLine("Example 306\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("©", "©
", "");
+ }
+
+ // Strings that are not on the list of HTML5 named entities are not
+ // recognized as entity references either:
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example307()
+ {
+ // Example 307
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // &MadeUpEntity;
+ //
+ // Should be rendered as:
+ // &MadeUpEntity;
+
+ Console.WriteLine("Example 307\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("&MadeUpEntity;", "&MadeUpEntity;
", "");
+ }
+
+ // Entity and numeric character references are recognized in any
+ // context besides code spans or code blocks, including
+ // URLs, [link titles], and [fenced code block][] [info strings]:
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example308()
+ {
+ // Example 308
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 308\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("", "", "");
+ }
+
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example309()
+ {
+ // Example 309
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // [foo](/föö "föö")
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 309\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("[foo](/föö \"föö\")", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example310()
+ {
+ // Example 310
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // [foo]
+ //
+ // [foo]: /föö "föö"
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 310\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("[foo]\n\n[foo]: /föö \"föö\"", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example311()
+ {
+ // Example 311
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // ``` föö
+ // foo
+ // ```
+ //
+ // Should be rendered as:
+ // foo
+ //
+
+ Console.WriteLine("Example 311\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("``` föö\nfoo\n```", "foo\n
", "");
+ }
+
+ // Entity and numeric character references are treated as literal
+ // text in code spans and code blocks:
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example312()
+ {
+ // Example 312
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // `föö`
+ //
+ // Should be rendered as:
+ // föö
+
+ Console.WriteLine("Example 312\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec("`föö`", "föö
", "");
+ }
+
+ [Test]
+ public void InlinesEntityAndNumericCharacterReferences_Example313()
+ {
+ // Example 313
+ // Section: Inlines / Entity and numeric character references
+ //
+ // The following Markdown:
+ // föfö
+ //
+ // Should be rendered as:
+ // föfö
+ //
+
+ Console.WriteLine("Example 313\nSection Inlines / Entity and numeric character references\n");
+ TestParser.TestSpec(" föfö", "föfö\n
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesCodeSpans
+ {
+ // ## Code spans
+ //
+ // A [backtick string](@)
+ // is a string of one or more backtick characters (`` ` ``) that is neither
+ // preceded nor followed by a backtick.
+ //
+ // A [code span](@) begins with a backtick string and ends with
+ // a backtick string of equal length. The contents of the code span are
+ // the characters between the two backtick strings, with leading and
+ // trailing spaces and [line endings] removed, and
+ // [whitespace] collapsed to single spaces.
+ //
+ // This is a simple code span:
+ [Test]
+ public void InlinesCodeSpans_Example314()
+ {
+ // Example 314
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `foo`
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 314\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`foo`", "foo
", "");
+ }
+
+ // Here two backticks are used, because the code contains a backtick.
+ // This example also illustrates stripping of leading and trailing spaces:
+ [Test]
+ public void InlinesCodeSpans_Example315()
+ {
+ // Example 315
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `` foo ` bar ``
+ //
+ // Should be rendered as:
+ // foo ` bar
+
+ Console.WriteLine("Example 315\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`` foo ` bar ``", "foo ` bar
", "");
+ }
+
+ // This example shows the motivation for stripping leading and trailing
+ // spaces:
+ [Test]
+ public void InlinesCodeSpans_Example316()
+ {
+ // Example 316
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // ` `` `
+ //
+ // Should be rendered as:
+ // ``
+
+ Console.WriteLine("Example 316\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("` `` `", "``
", "");
+ }
+
+ // [Line endings] are treated like spaces:
+ [Test]
+ public void InlinesCodeSpans_Example317()
+ {
+ // Example 317
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // ``
+ // foo
+ // ``
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 317\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("``\nfoo\n``", "foo
", "");
+ }
+
+ // Interior spaces and [line endings] are collapsed into
+ // single spaces, just as they would be by a browser:
+ [Test]
+ public void InlinesCodeSpans_Example318()
+ {
+ // Example 318
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `foo bar
+ // baz`
+ //
+ // Should be rendered as:
+ // foo bar baz
+
+ Console.WriteLine("Example 318\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`foo bar\n baz`", "foo bar baz
", "");
+ }
+
+ // Not all [Unicode whitespace] (for instance, non-breaking space) is
+ // collapsed, however:
+ [Test]
+ public void InlinesCodeSpans_Example319()
+ {
+ // Example 319
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `a b`
+ //
+ // Should be rendered as:
+ // a b
+
+ Console.WriteLine("Example 319\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`a b`", "a b
", "");
+ }
+
+ // Q: Why not just leave the spaces, since browsers will collapse them
+ // anyway? A: Because we might be targeting a non-HTML format, and we
+ // shouldn't rely on HTML-specific rendering assumptions.
+ //
+ // (Existing implementations differ in their treatment of internal
+ // spaces and [line endings]. Some, including `Markdown.pl` and
+ // `showdown`, convert an internal [line ending] into a
+ // `
` tag. But this makes things difficult for those who like to
+ // hard-wrap their paragraphs, since a line break in the midst of a code
+ // span will cause an unintended line break in the output. Others just
+ // leave internal spaces as they are, which is fine if only HTML is being
+ // targeted.)
+ [Test]
+ public void InlinesCodeSpans_Example320()
+ {
+ // Example 320
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `foo `` bar`
+ //
+ // Should be rendered as:
+ // foo `` bar
+
+ Console.WriteLine("Example 320\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`foo `` bar`", "foo `` bar
", "");
+ }
+
+ // Note that backslash escapes do not work in code spans. All backslashes
+ // are treated literally:
+ [Test]
+ public void InlinesCodeSpans_Example321()
+ {
+ // Example 321
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `foo\`bar`
+ //
+ // Should be rendered as:
+ // foo\bar`
+
+ Console.WriteLine("Example 321\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`foo\\`bar`", "foo\\bar`
", "");
+ }
+
+ // Backslash escapes are never needed, because one can always choose a
+ // string of *n* backtick characters as delimiters, where the code does
+ // not contain any strings of exactly *n* backtick characters.
+ //
+ // Code span backticks have higher precedence than any other inline
+ // constructs except HTML tags and autolinks. Thus, for example, this is
+ // not parsed as emphasized text, since the second `*` is part of a code
+ // span:
+ [Test]
+ public void InlinesCodeSpans_Example322()
+ {
+ // Example 322
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // *foo`*`
+ //
+ // Should be rendered as:
+ // *foo*
+
+ Console.WriteLine("Example 322\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("*foo`*`", "*foo*
", "");
+ }
+
+ // And this is not parsed as a link:
+ [Test]
+ public void InlinesCodeSpans_Example323()
+ {
+ // Example 323
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // [not a `link](/foo`)
+ //
+ // Should be rendered as:
+ // [not a link](/foo)
+
+ Console.WriteLine("Example 323\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("[not a `link](/foo`)", "[not a link](/foo)
", "");
+ }
+
+ // Code spans, HTML tags, and autolinks have the same precedence.
+ // Thus, this is code:
+ [Test]
+ public void InlinesCodeSpans_Example324()
+ {
+ // Example 324
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // ``
+ //
+ // Should be rendered as:
+ // <a href="">`
+
+ Console.WriteLine("Example 324\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("``", "<a href="">`
", "");
+ }
+
+ // But this is an HTML tag:
+ [Test]
+ public void InlinesCodeSpans_Example325()
+ {
+ // Example 325
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `
+ //
+ // Should be rendered as:
+ // `
+
+ Console.WriteLine("Example 325\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`", "`
", "");
+ }
+
+ // And this is code:
+ [Test]
+ public void InlinesCodeSpans_Example326()
+ {
+ // Example 326
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // ``
+ //
+ // Should be rendered as:
+ // <http://foo.bar.baz>`
+
+ Console.WriteLine("Example 326\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("``", "<http://foo.bar.baz>`
", "");
+ }
+
+ // But this is an autolink:
+ [Test]
+ public void InlinesCodeSpans_Example327()
+ {
+ // Example 327
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `
+ //
+ // Should be rendered as:
+ // http://foo.bar.`baz`
+
+ Console.WriteLine("Example 327\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`", "http://foo.bar.`baz`
", "");
+ }
+
+ // When a backtick string is not closed by a matching backtick string,
+ // we just have literal backticks:
+ [Test]
+ public void InlinesCodeSpans_Example328()
+ {
+ // Example 328
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // ```foo``
+ //
+ // Should be rendered as:
+ // ```foo``
+
+ Console.WriteLine("Example 328\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("```foo``", "```foo``
", "");
+ }
+
+ [Test]
+ public void InlinesCodeSpans_Example329()
+ {
+ // Example 329
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `foo
+ //
+ // Should be rendered as:
+ // `foo
+
+ Console.WriteLine("Example 329\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`foo", "`foo
", "");
+ }
+
+ // The following case also illustrates the need for opening and
+ // closing backtick strings to be equal in length:
+ [Test]
+ public void InlinesCodeSpans_Example330()
+ {
+ // Example 330
+ // Section: Inlines / Code spans
+ //
+ // The following Markdown:
+ // `foo``bar``
+ //
+ // Should be rendered as:
+ // `foobar
+
+ Console.WriteLine("Example 330\nSection Inlines / Code spans\n");
+ TestParser.TestSpec("`foo``bar``", "`foobar
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesEmphasisAndStrongEmphasis
+ {
+ // ## Emphasis and strong emphasis
+ //
+ // John Gruber's original [Markdown syntax
+ // description](http://daringfireball.net/projects/markdown/syntax#em) says:
+ //
+ // > Markdown treats asterisks (`*`) and underscores (`_`) as indicators of
+ // > emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML
+ // > `` tag; double `*`'s or `_`'s will be wrapped with an HTML ``
+ // > tag.
+ //
+ // This is enough for most users, but these rules leave much undecided,
+ // especially when it comes to nested emphasis. The original
+ // `Markdown.pl` test suite makes it clear that triple `***` and
+ // `___` delimiters can be used for strong emphasis, and most
+ // implementations have also allowed the following patterns:
+ //
+ // ``` markdown
+ // ***strong emph***
+ // ***strong** in emph*
+ // ***emph* in strong**
+ // **in strong *emph***
+ // *in emph **strong***
+ // ```
+ //
+ // The following patterns are less widely supported, but the intent
+ // is clear and they are useful (especially in contexts like bibliography
+ // entries):
+ //
+ // ``` markdown
+ // *emph *with emph* in it*
+ // **strong **with strong** in it**
+ // ```
+ //
+ // Many implementations have also restricted intraword emphasis to
+ // the `*` forms, to avoid unwanted emphasis in words containing
+ // internal underscores. (It is best practice to put these in code
+ // spans, but users often do not.)
+ //
+ // ``` markdown
+ // internal emphasis: foo*bar*baz
+ // no emphasis: foo_bar_baz
+ // ```
+ //
+ // The rules given below capture all of these patterns, while allowing
+ // for efficient parsing strategies that do not backtrack.
+ //
+ // First, some definitions. A [delimiter run](@) is either
+ // a sequence of one or more `*` characters that is not preceded or
+ // followed by a non-backslash-escaped `*` character, or a sequence
+ // of one or more `_` characters that is not preceded or followed by
+ // a non-backslash-escaped `_` character.
+ //
+ // A [left-flanking delimiter run](@) is
+ // a [delimiter run] that is (a) not followed by [Unicode whitespace],
+ // and (b) not followed by a [punctuation character], or
+ // preceded by [Unicode whitespace] or a [punctuation character].
+ // For purposes of this definition, the beginning and the end of
+ // the line count as Unicode whitespace.
+ //
+ // A [right-flanking delimiter run](@) is
+ // a [delimiter run] that is (a) not preceded by [Unicode whitespace],
+ // and (b) not preceded by a [punctuation character], or
+ // followed by [Unicode whitespace] or a [punctuation character].
+ // For purposes of this definition, the beginning and the end of
+ // the line count as Unicode whitespace.
+ //
+ // Here are some examples of delimiter runs.
+ //
+ // - left-flanking but not right-flanking:
+ //
+ // ```
+ // ***abc
+ // _abc
+ // **"abc"
+ // _"abc"
+ // ```
+ //
+ // - right-flanking but not left-flanking:
+ //
+ // ```
+ // abc***
+ // abc_
+ // "abc"**
+ // "abc"_
+ // ```
+ //
+ // - Both left and right-flanking:
+ //
+ // ```
+ // abc***def
+ // "abc"_"def"
+ // ```
+ //
+ // - Neither left nor right-flanking:
+ //
+ // ```
+ // abc *** def
+ // a _ b
+ // ```
+ //
+ // (The idea of distinguishing left-flanking and right-flanking
+ // delimiter runs based on the character before and the character
+ // after comes from Roopesh Chander's
+ // [vfmd](http://www.vfmd.org/vfmd-spec/specification/#procedure-for-identifying-emphasis-tags).
+ // vfmd uses the terminology "emphasis indicator string" instead of "delimiter
+ // run," and its rules for distinguishing left- and right-flanking runs
+ // are a bit more complex than the ones given here.)
+ //
+ // The following rules define emphasis and strong emphasis:
+ //
+ // 1. A single `*` character [can open emphasis](@)
+ // iff (if and only if) it is part of a [left-flanking delimiter run].
+ //
+ // 2. A single `_` character [can open emphasis] iff
+ // it is part of a [left-flanking delimiter run]
+ // and either (a) not part of a [right-flanking delimiter run]
+ // or (b) part of a [right-flanking delimiter run]
+ // preceded by punctuation.
+ //
+ // 3. A single `*` character [can close emphasis](@)
+ // iff it is part of a [right-flanking delimiter run].
+ //
+ // 4. A single `_` character [can close emphasis] iff
+ // it is part of a [right-flanking delimiter run]
+ // and either (a) not part of a [left-flanking delimiter run]
+ // or (b) part of a [left-flanking delimiter run]
+ // followed by punctuation.
+ //
+ // 5. A double `**` [can open strong emphasis](@)
+ // iff it is part of a [left-flanking delimiter run].
+ //
+ // 6. A double `__` [can open strong emphasis] iff
+ // it is part of a [left-flanking delimiter run]
+ // and either (a) not part of a [right-flanking delimiter run]
+ // or (b) part of a [right-flanking delimiter run]
+ // preceded by punctuation.
+ //
+ // 7. A double `**` [can close strong emphasis](@)
+ // iff it is part of a [right-flanking delimiter run].
+ //
+ // 8. A double `__` [can close strong emphasis] iff
+ // it is part of a [right-flanking delimiter run]
+ // and either (a) not part of a [left-flanking delimiter run]
+ // or (b) part of a [left-flanking delimiter run]
+ // followed by punctuation.
+ //
+ // 9. Emphasis begins with a delimiter that [can open emphasis] and ends
+ // with a delimiter that [can close emphasis], and that uses the same
+ // character (`_` or `*`) as the opening delimiter. The
+ // opening and closing delimiters must belong to separate
+ // [delimiter runs]. If one of the delimiters can both
+ // open and close emphasis, then the sum of the lengths of the
+ // delimiter runs containing the opening and closing delimiters
+ // must not be a multiple of 3.
+ //
+ // 10. Strong emphasis begins with a delimiter that
+ // [can open strong emphasis] and ends with a delimiter that
+ // [can close strong emphasis], and that uses the same character
+ // (`_` or `*`) as the opening delimiter. The
+ // opening and closing delimiters must belong to separate
+ // [delimiter runs]. If one of the delimiters can both open
+ // and close strong emphasis, then the sum of the lengths of
+ // the delimiter runs containing the opening and closing
+ // delimiters must not be a multiple of 3.
+ //
+ // 11. A literal `*` character cannot occur at the beginning or end of
+ // `*`-delimited emphasis or `**`-delimited strong emphasis, unless it
+ // is backslash-escaped.
+ //
+ // 12. A literal `_` character cannot occur at the beginning or end of
+ // `_`-delimited emphasis or `__`-delimited strong emphasis, unless it
+ // is backslash-escaped.
+ //
+ // Where rules 1--12 above are compatible with multiple parsings,
+ // the following principles resolve ambiguity:
+ //
+ // 13. The number of nestings should be minimized. Thus, for example,
+ // an interpretation `...` is always preferred to
+ // `...`.
+ //
+ // 14. An interpretation `...` is always
+ // preferred to `...`.
+ //
+ // 15. When two potential emphasis or strong emphasis spans overlap,
+ // so that the second begins before the first ends and ends after
+ // the first ends, the first takes precedence. Thus, for example,
+ // `*foo _bar* baz_` is parsed as `foo _bar baz_` rather
+ // than `*foo bar* baz`.
+ //
+ // 16. When there are two potential emphasis or strong emphasis spans
+ // with the same closing delimiter, the shorter one (the one that
+ // opens later) takes precedence. Thus, for example,
+ // `**foo **bar baz**` is parsed as `**foo bar baz`
+ // rather than `foo **bar baz`.
+ //
+ // 17. Inline code spans, links, images, and HTML tags group more tightly
+ // than emphasis. So, when there is a choice between an interpretation
+ // that contains one of these elements and one that does not, the
+ // former always wins. Thus, for example, `*[foo*](bar)` is
+ // parsed as `*foo*` rather than as
+ // `[foo](bar)`.
+ //
+ // These rules can be illustrated through a series of examples.
+ //
+ // Rule 1:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example331()
+ {
+ // Example 331
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo bar*
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 331\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo bar*", "foo bar
", "");
+ }
+
+ // This is not emphasis, because the opening `*` is followed by
+ // whitespace, and hence not part of a [left-flanking delimiter run]:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example332()
+ {
+ // Example 332
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // a * foo bar*
+ //
+ // Should be rendered as:
+ // a * foo bar*
+
+ Console.WriteLine("Example 332\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("a * foo bar*", "a * foo bar*
", "");
+ }
+
+ // This is not emphasis, because the opening `*` is preceded
+ // by an alphanumeric and followed by punctuation, and hence
+ // not part of a [left-flanking delimiter run]:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example333()
+ {
+ // Example 333
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // a*"foo"*
+ //
+ // Should be rendered as:
+ // a*"foo"*
+
+ Console.WriteLine("Example 333\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("a*\"foo\"*", "a*"foo"*
", "");
+ }
+
+ // Unicode nonbreaking spaces count as whitespace, too:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example334()
+ {
+ // Example 334
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // * a *
+ //
+ // Should be rendered as:
+ // * a *
+
+ Console.WriteLine("Example 334\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("* a *", "* a *
", "");
+ }
+
+ // Intraword emphasis with `*` is permitted:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example335()
+ {
+ // Example 335
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo*bar*
+ //
+ // Should be rendered as:
+ // foobar
+
+ Console.WriteLine("Example 335\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo*bar*", "foobar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example336()
+ {
+ // Example 336
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // 5*6*78
+ //
+ // Should be rendered as:
+ // 5678
+
+ Console.WriteLine("Example 336\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("5*6*78", "5678
", "");
+ }
+
+ // Rule 2:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example337()
+ {
+ // Example 337
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo bar_
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 337\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo bar_", "foo bar
", "");
+ }
+
+ // This is not emphasis, because the opening `_` is followed by
+ // whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example338()
+ {
+ // Example 338
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _ foo bar_
+ //
+ // Should be rendered as:
+ // _ foo bar_
+
+ Console.WriteLine("Example 338\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_ foo bar_", "_ foo bar_
", "");
+ }
+
+ // This is not emphasis, because the opening `_` is preceded
+ // by an alphanumeric and followed by punctuation:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example339()
+ {
+ // Example 339
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // a_"foo"_
+ //
+ // Should be rendered as:
+ // a_"foo"_
+
+ Console.WriteLine("Example 339\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("a_\"foo\"_", "a_"foo"_
", "");
+ }
+
+ // Emphasis with `_` is not allowed inside words:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example340()
+ {
+ // Example 340
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo_bar_
+ //
+ // Should be rendered as:
+ // foo_bar_
+
+ Console.WriteLine("Example 340\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo_bar_", "foo_bar_
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example341()
+ {
+ // Example 341
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // 5_6_78
+ //
+ // Should be rendered as:
+ // 5_6_78
+
+ Console.WriteLine("Example 341\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("5_6_78", "5_6_78
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example342()
+ {
+ // Example 342
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // пристаням_стремятся_
+ //
+ // Should be rendered as:
+ // пристаням_стремятся_
+
+ Console.WriteLine("Example 342\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("пристаням_стремятся_", "пристаням_стремятся_
", "");
+ }
+
+ // Here `_` does not generate emphasis, because the first delimiter run
+ // is right-flanking and the second left-flanking:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example343()
+ {
+ // Example 343
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // aa_"bb"_cc
+ //
+ // Should be rendered as:
+ // aa_"bb"_cc
+
+ Console.WriteLine("Example 343\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("aa_\"bb\"_cc", "aa_"bb"_cc
", "");
+ }
+
+ // This is emphasis, even though the opening delimiter is
+ // both left- and right-flanking, because it is preceded by
+ // punctuation:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example344()
+ {
+ // Example 344
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo-_(bar)_
+ //
+ // Should be rendered as:
+ // foo-(bar)
+
+ Console.WriteLine("Example 344\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo-_(bar)_", "foo-(bar)
", "");
+ }
+
+ // Rule 3:
+ //
+ // This is not emphasis, because the closing delimiter does
+ // not match the opening delimiter:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example345()
+ {
+ // Example 345
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo*
+ //
+ // Should be rendered as:
+ // _foo*
+
+ Console.WriteLine("Example 345\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo*", "_foo*
", "");
+ }
+
+ // This is not emphasis, because the closing `*` is preceded by
+ // whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example346()
+ {
+ // Example 346
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo bar *
+ //
+ // Should be rendered as:
+ // *foo bar *
+
+ Console.WriteLine("Example 346\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo bar *", "*foo bar *
", "");
+ }
+
+ // A newline also counts as whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example347()
+ {
+ // Example 347
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo bar
+ // *
+ //
+ // Should be rendered as:
+ // *foo bar
+ // *
+
+ Console.WriteLine("Example 347\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo bar\n*", "*foo bar\n*
", "");
+ }
+
+ // This is not emphasis, because the second `*` is
+ // preceded by punctuation and followed by an alphanumeric
+ // (hence it is not part of a [right-flanking delimiter run]:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example348()
+ {
+ // Example 348
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *(*foo)
+ //
+ // Should be rendered as:
+ // *(*foo)
+
+ Console.WriteLine("Example 348\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*(*foo)", "*(*foo)
", "");
+ }
+
+ // The point of this restriction is more easily appreciated
+ // with this example:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example349()
+ {
+ // Example 349
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *(*foo*)*
+ //
+ // Should be rendered as:
+ // (foo)
+
+ Console.WriteLine("Example 349\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*(*foo*)*", "(foo)
", "");
+ }
+
+ // Intraword emphasis with `*` is allowed:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example350()
+ {
+ // Example 350
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo*bar
+ //
+ // Should be rendered as:
+ // foobar
+
+ Console.WriteLine("Example 350\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo*bar", "foobar
", "");
+ }
+
+ // Rule 4:
+ //
+ // This is not emphasis, because the closing `_` is preceded by
+ // whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example351()
+ {
+ // Example 351
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo bar _
+ //
+ // Should be rendered as:
+ // _foo bar _
+
+ Console.WriteLine("Example 351\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo bar _", "_foo bar _
", "");
+ }
+
+ // This is not emphasis, because the second `_` is
+ // preceded by punctuation and followed by an alphanumeric:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example352()
+ {
+ // Example 352
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _(_foo)
+ //
+ // Should be rendered as:
+ // _(_foo)
+
+ Console.WriteLine("Example 352\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_(_foo)", "_(_foo)
", "");
+ }
+
+ // This is emphasis within emphasis:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example353()
+ {
+ // Example 353
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _(_foo_)_
+ //
+ // Should be rendered as:
+ // (foo)
+
+ Console.WriteLine("Example 353\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_(_foo_)_", "(foo)
", "");
+ }
+
+ // Intraword emphasis is disallowed for `_`:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example354()
+ {
+ // Example 354
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo_bar
+ //
+ // Should be rendered as:
+ // _foo_bar
+
+ Console.WriteLine("Example 354\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo_bar", "_foo_bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example355()
+ {
+ // Example 355
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _пристаням_стремятся
+ //
+ // Should be rendered as:
+ // _пристаням_стремятся
+
+ Console.WriteLine("Example 355\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_пристаням_стремятся", "_пристаням_стремятся
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example356()
+ {
+ // Example 356
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo_bar_baz_
+ //
+ // Should be rendered as:
+ // foo_bar_baz
+
+ Console.WriteLine("Example 356\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo_bar_baz_", "foo_bar_baz
", "");
+ }
+
+ // This is emphasis, even though the closing delimiter is
+ // both left- and right-flanking, because it is followed by
+ // punctuation:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example357()
+ {
+ // Example 357
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _(bar)_.
+ //
+ // Should be rendered as:
+ // (bar).
+
+ Console.WriteLine("Example 357\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_(bar)_.", "(bar).
", "");
+ }
+
+ // Rule 5:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example358()
+ {
+ // Example 358
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo bar**
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 358\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo bar**", "foo bar
", "");
+ }
+
+ // This is not strong emphasis, because the opening delimiter is
+ // followed by whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example359()
+ {
+ // Example 359
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ** foo bar**
+ //
+ // Should be rendered as:
+ // ** foo bar**
+
+ Console.WriteLine("Example 359\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("** foo bar**", "** foo bar**
", "");
+ }
+
+ // This is not strong emphasis, because the opening `**` is preceded
+ // by an alphanumeric and followed by punctuation, and hence
+ // not part of a [left-flanking delimiter run]:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example360()
+ {
+ // Example 360
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // a**"foo"**
+ //
+ // Should be rendered as:
+ // a**"foo"**
+
+ Console.WriteLine("Example 360\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("a**\"foo\"**", "a**"foo"**
", "");
+ }
+
+ // Intraword strong emphasis with `**` is permitted:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example361()
+ {
+ // Example 361
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo**bar**
+ //
+ // Should be rendered as:
+ // foobar
+
+ Console.WriteLine("Example 361\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo**bar**", "foobar
", "");
+ }
+
+ // Rule 6:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example362()
+ {
+ // Example 362
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo bar__
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 362\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo bar__", "foo bar
", "");
+ }
+
+ // This is not strong emphasis, because the opening delimiter is
+ // followed by whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example363()
+ {
+ // Example 363
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __ foo bar__
+ //
+ // Should be rendered as:
+ // __ foo bar__
+
+ Console.WriteLine("Example 363\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__ foo bar__", "__ foo bar__
", "");
+ }
+
+ // A newline counts as whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example364()
+ {
+ // Example 364
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __
+ // foo bar__
+ //
+ // Should be rendered as:
+ // __
+ // foo bar__
+
+ Console.WriteLine("Example 364\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__\nfoo bar__", "__\nfoo bar__
", "");
+ }
+
+ // This is not strong emphasis, because the opening `__` is preceded
+ // by an alphanumeric and followed by punctuation:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example365()
+ {
+ // Example 365
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // a__"foo"__
+ //
+ // Should be rendered as:
+ // a__"foo"__
+
+ Console.WriteLine("Example 365\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("a__\"foo\"__", "a__"foo"__
", "");
+ }
+
+ // Intraword strong emphasis is forbidden with `__`:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example366()
+ {
+ // Example 366
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo__bar__
+ //
+ // Should be rendered as:
+ // foo__bar__
+
+ Console.WriteLine("Example 366\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo__bar__", "foo__bar__
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example367()
+ {
+ // Example 367
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // 5__6__78
+ //
+ // Should be rendered as:
+ // 5__6__78
+
+ Console.WriteLine("Example 367\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("5__6__78", "5__6__78
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example368()
+ {
+ // Example 368
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // пристаням__стремятся__
+ //
+ // Should be rendered as:
+ // пристаням__стремятся__
+
+ Console.WriteLine("Example 368\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("пристаням__стремятся__", "пристаням__стремятся__
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example369()
+ {
+ // Example 369
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo, __bar__, baz__
+ //
+ // Should be rendered as:
+ // foo, bar, baz
+
+ Console.WriteLine("Example 369\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo, __bar__, baz__", "foo, bar, baz
", "");
+ }
+
+ // This is strong emphasis, even though the opening delimiter is
+ // both left- and right-flanking, because it is preceded by
+ // punctuation:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example370()
+ {
+ // Example 370
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo-__(bar)__
+ //
+ // Should be rendered as:
+ // foo-(bar)
+
+ Console.WriteLine("Example 370\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo-__(bar)__", "foo-(bar)
", "");
+ }
+
+ // Rule 7:
+ //
+ // This is not strong emphasis, because the closing delimiter is preceded
+ // by whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example371()
+ {
+ // Example 371
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo bar **
+ //
+ // Should be rendered as:
+ // **foo bar **
+
+ Console.WriteLine("Example 371\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo bar **", "**foo bar **
", "");
+ }
+
+ // (Nor can it be interpreted as an emphasized `*foo bar *`, because of
+ // Rule 11.)
+ //
+ // This is not strong emphasis, because the second `**` is
+ // preceded by punctuation and followed by an alphanumeric:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example372()
+ {
+ // Example 372
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **(**foo)
+ //
+ // Should be rendered as:
+ // **(**foo)
+
+ Console.WriteLine("Example 372\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**(**foo)", "**(**foo)
", "");
+ }
+
+ // The point of this restriction is more easily appreciated
+ // with these examples:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example373()
+ {
+ // Example 373
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *(**foo**)*
+ //
+ // Should be rendered as:
+ // (foo)
+
+ Console.WriteLine("Example 373\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*(**foo**)*", "(foo)
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example374()
+ {
+ // Example 374
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **Gomphocarpus (*Gomphocarpus physocarpus*, syn.
+ // *Asclepias physocarpa*)**
+ //
+ // Should be rendered as:
+ // Gomphocarpus (Gomphocarpus physocarpus, syn.
+ // Asclepias physocarpa)
+
+ Console.WriteLine("Example 374\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**Gomphocarpus (*Gomphocarpus physocarpus*, syn.\n*Asclepias physocarpa*)**", "Gomphocarpus (Gomphocarpus physocarpus, syn.\nAsclepias physocarpa)
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example375()
+ {
+ // Example 375
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo "*bar*" foo**
+ //
+ // Should be rendered as:
+ // foo "bar" foo
+
+ Console.WriteLine("Example 375\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo \"*bar*\" foo**", "foo "bar" foo
", "");
+ }
+
+ // Intraword emphasis:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example376()
+ {
+ // Example 376
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo**bar
+ //
+ // Should be rendered as:
+ // foobar
+
+ Console.WriteLine("Example 376\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo**bar", "foobar
", "");
+ }
+
+ // Rule 8:
+ //
+ // This is not strong emphasis, because the closing delimiter is
+ // preceded by whitespace:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example377()
+ {
+ // Example 377
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo bar __
+ //
+ // Should be rendered as:
+ // __foo bar __
+
+ Console.WriteLine("Example 377\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo bar __", "__foo bar __
", "");
+ }
+
+ // This is not strong emphasis, because the second `__` is
+ // preceded by punctuation and followed by an alphanumeric:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example378()
+ {
+ // Example 378
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __(__foo)
+ //
+ // Should be rendered as:
+ // __(__foo)
+
+ Console.WriteLine("Example 378\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__(__foo)", "__(__foo)
", "");
+ }
+
+ // The point of this restriction is more easily appreciated
+ // with this example:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example379()
+ {
+ // Example 379
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _(__foo__)_
+ //
+ // Should be rendered as:
+ // (foo)
+
+ Console.WriteLine("Example 379\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_(__foo__)_", "(foo)
", "");
+ }
+
+ // Intraword strong emphasis is forbidden with `__`:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example380()
+ {
+ // Example 380
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo__bar
+ //
+ // Should be rendered as:
+ // __foo__bar
+
+ Console.WriteLine("Example 380\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo__bar", "__foo__bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example381()
+ {
+ // Example 381
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __пристаням__стремятся
+ //
+ // Should be rendered as:
+ // __пристаням__стремятся
+
+ Console.WriteLine("Example 381\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__пристаням__стремятся", "__пристаням__стремятся
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example382()
+ {
+ // Example 382
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo__bar__baz__
+ //
+ // Should be rendered as:
+ // foo__bar__baz
+
+ Console.WriteLine("Example 382\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo__bar__baz__", "foo__bar__baz
", "");
+ }
+
+ // This is strong emphasis, even though the closing delimiter is
+ // both left- and right-flanking, because it is followed by
+ // punctuation:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example383()
+ {
+ // Example 383
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __(bar)__.
+ //
+ // Should be rendered as:
+ // (bar).
+
+ Console.WriteLine("Example 383\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__(bar)__.", "(bar).
", "");
+ }
+
+ // Rule 9:
+ //
+ // Any nonempty sequence of inline elements can be the contents of an
+ // emphasized span.
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example384()
+ {
+ // Example 384
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo [bar](/url)*
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 384\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo [bar](/url)*", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example385()
+ {
+ // Example 385
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo
+ // bar*
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 385\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo\nbar*", "foo\nbar
", "");
+ }
+
+ // In particular, emphasis and strong emphasis can be nested
+ // inside emphasis:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example386()
+ {
+ // Example 386
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo __bar__ baz_
+ //
+ // Should be rendered as:
+ // foo bar baz
+
+ Console.WriteLine("Example 386\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo __bar__ baz_", "foo bar baz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example387()
+ {
+ // Example 387
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo _bar_ baz_
+ //
+ // Should be rendered as:
+ // foo bar baz
+
+ Console.WriteLine("Example 387\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo _bar_ baz_", "foo bar baz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example388()
+ {
+ // Example 388
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo_ bar_
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 388\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo_ bar_", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example389()
+ {
+ // Example 389
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo *bar**
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 389\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo *bar**", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example390()
+ {
+ // Example 390
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo **bar** baz*
+ //
+ // Should be rendered as:
+ // foo bar baz
+
+ Console.WriteLine("Example 390\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo **bar** baz*", "foo bar baz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example391()
+ {
+ // Example 391
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo**bar**baz*
+ //
+ // Should be rendered as:
+ // foobarbaz
+
+ Console.WriteLine("Example 391\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo**bar**baz*", "foobarbaz
", "");
+ }
+
+ // Note that in the preceding case, the interpretation
+ //
+ // ``` markdown
+ // foobarbaz
+ // ```
+ //
+ //
+ // is precluded by the condition that a delimiter that
+ // can both open and close (like the `*` after `foo`)
+ // cannot form emphasis if the sum of the lengths of
+ // the delimiter runs containing the opening and
+ // closing delimiters is a multiple of 3.
+ //
+ // The same condition ensures that the following
+ // cases are all strong emphasis nested inside
+ // emphasis, even when the interior spaces are
+ // omitted:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example392()
+ {
+ // Example 392
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ***foo** bar*
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 392\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("***foo** bar*", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example393()
+ {
+ // Example 393
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo **bar***
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 393\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo **bar***", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example394()
+ {
+ // Example 394
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo**bar***
+ //
+ // Should be rendered as:
+ // foobar
+
+ Console.WriteLine("Example 394\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo**bar***", "foobar
", "");
+ }
+
+ // Indefinite levels of nesting are possible:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example395()
+ {
+ // Example 395
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo **bar *baz* bim** bop*
+ //
+ // Should be rendered as:
+ // foo bar baz bim bop
+
+ Console.WriteLine("Example 395\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo **bar *baz* bim** bop*", "foo bar baz bim bop
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example396()
+ {
+ // Example 396
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo [*bar*](/url)*
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 396\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo [*bar*](/url)*", "foo bar
", "");
+ }
+
+ // There can be no empty emphasis or strong emphasis:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example397()
+ {
+ // Example 397
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ** is not an empty emphasis
+ //
+ // Should be rendered as:
+ // ** is not an empty emphasis
+
+ Console.WriteLine("Example 397\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("** is not an empty emphasis", "** is not an empty emphasis
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example398()
+ {
+ // Example 398
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **** is not an empty strong emphasis
+ //
+ // Should be rendered as:
+ // **** is not an empty strong emphasis
+
+ Console.WriteLine("Example 398\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**** is not an empty strong emphasis", "**** is not an empty strong emphasis
", "");
+ }
+
+ // Rule 10:
+ //
+ // Any nonempty sequence of inline elements can be the contents of an
+ // strongly emphasized span.
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example399()
+ {
+ // Example 399
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo [bar](/url)**
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 399\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo [bar](/url)**", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example400()
+ {
+ // Example 400
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo
+ // bar**
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 400\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo\nbar**", "foo\nbar
", "");
+ }
+
+ // In particular, emphasis and strong emphasis can be nested
+ // inside strong emphasis:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example401()
+ {
+ // Example 401
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo _bar_ baz__
+ //
+ // Should be rendered as:
+ // foo bar baz
+
+ Console.WriteLine("Example 401\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo _bar_ baz__", "foo bar baz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example402()
+ {
+ // Example 402
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo __bar__ baz__
+ //
+ // Should be rendered as:
+ // foo bar baz
+
+ Console.WriteLine("Example 402\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo __bar__ baz__", "foo bar baz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example403()
+ {
+ // Example 403
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ____foo__ bar__
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 403\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("____foo__ bar__", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example404()
+ {
+ // Example 404
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo **bar****
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 404\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo **bar****", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example405()
+ {
+ // Example 405
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo *bar* baz**
+ //
+ // Should be rendered as:
+ // foo bar baz
+
+ Console.WriteLine("Example 405\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo *bar* baz**", "foo bar baz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example406()
+ {
+ // Example 406
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo*bar*baz**
+ //
+ // Should be rendered as:
+ // foobarbaz
+
+ Console.WriteLine("Example 406\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo*bar*baz**", "foobarbaz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example407()
+ {
+ // Example 407
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ***foo* bar**
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 407\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("***foo* bar**", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example408()
+ {
+ // Example 408
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo *bar***
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 408\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo *bar***", "foo bar
", "");
+ }
+
+ // Indefinite levels of nesting are possible:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example409()
+ {
+ // Example 409
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo *bar **baz**
+ // bim* bop**
+ //
+ // Should be rendered as:
+ // foo bar baz
+ // bim bop
+
+ Console.WriteLine("Example 409\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo *bar **baz**\nbim* bop**", "foo bar baz\nbim bop
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example410()
+ {
+ // Example 410
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo [*bar*](/url)**
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 410\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo [*bar*](/url)**", "foo bar
", "");
+ }
+
+ // There can be no empty emphasis or strong emphasis:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example411()
+ {
+ // Example 411
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __ is not an empty emphasis
+ //
+ // Should be rendered as:
+ // __ is not an empty emphasis
+
+ Console.WriteLine("Example 411\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__ is not an empty emphasis", "__ is not an empty emphasis
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example412()
+ {
+ // Example 412
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ____ is not an empty strong emphasis
+ //
+ // Should be rendered as:
+ // ____ is not an empty strong emphasis
+
+ Console.WriteLine("Example 412\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("____ is not an empty strong emphasis", "____ is not an empty strong emphasis
", "");
+ }
+
+ // Rule 11:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example413()
+ {
+ // Example 413
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo ***
+ //
+ // Should be rendered as:
+ // foo ***
+
+ Console.WriteLine("Example 413\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo ***", "foo ***
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example414()
+ {
+ // Example 414
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo *\**
+ //
+ // Should be rendered as:
+ // foo *
+
+ Console.WriteLine("Example 414\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo *\\**", "foo *
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example415()
+ {
+ // Example 415
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo *_*
+ //
+ // Should be rendered as:
+ // foo _
+
+ Console.WriteLine("Example 415\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo *_*", "foo _
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example416()
+ {
+ // Example 416
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo *****
+ //
+ // Should be rendered as:
+ // foo *****
+
+ Console.WriteLine("Example 416\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo *****", "foo *****
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example417()
+ {
+ // Example 417
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo **\***
+ //
+ // Should be rendered as:
+ // foo *
+
+ Console.WriteLine("Example 417\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo **\\***", "foo *
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example418()
+ {
+ // Example 418
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo **_**
+ //
+ // Should be rendered as:
+ // foo _
+
+ Console.WriteLine("Example 418\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo **_**", "foo _
", "");
+ }
+
+ // Note that when delimiters do not match evenly, Rule 11 determines
+ // that the excess literal `*` characters will appear outside of the
+ // emphasis, rather than inside it:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example419()
+ {
+ // Example 419
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo*
+ //
+ // Should be rendered as:
+ // *foo
+
+ Console.WriteLine("Example 419\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo*", "*foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example420()
+ {
+ // Example 420
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo**
+ //
+ // Should be rendered as:
+ // foo*
+
+ Console.WriteLine("Example 420\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo**", "foo*
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example421()
+ {
+ // Example 421
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ***foo**
+ //
+ // Should be rendered as:
+ // *foo
+
+ Console.WriteLine("Example 421\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("***foo**", "*foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example422()
+ {
+ // Example 422
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ****foo*
+ //
+ // Should be rendered as:
+ // ***foo
+
+ Console.WriteLine("Example 422\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("****foo*", "***foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example423()
+ {
+ // Example 423
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo***
+ //
+ // Should be rendered as:
+ // foo*
+
+ Console.WriteLine("Example 423\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo***", "foo*
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example424()
+ {
+ // Example 424
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo****
+ //
+ // Should be rendered as:
+ // foo***
+
+ Console.WriteLine("Example 424\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo****", "foo***
", "");
+ }
+
+ // Rule 12:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example425()
+ {
+ // Example 425
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo ___
+ //
+ // Should be rendered as:
+ // foo ___
+
+ Console.WriteLine("Example 425\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo ___", "foo ___
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example426()
+ {
+ // Example 426
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo _\__
+ //
+ // Should be rendered as:
+ // foo _
+
+ Console.WriteLine("Example 426\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo _\\__", "foo _
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example427()
+ {
+ // Example 427
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo _*_
+ //
+ // Should be rendered as:
+ // foo *
+
+ Console.WriteLine("Example 427\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo _*_", "foo *
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example428()
+ {
+ // Example 428
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo _____
+ //
+ // Should be rendered as:
+ // foo _____
+
+ Console.WriteLine("Example 428\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo _____", "foo _____
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example429()
+ {
+ // Example 429
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo __\___
+ //
+ // Should be rendered as:
+ // foo _
+
+ Console.WriteLine("Example 429\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo __\\___", "foo _
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example430()
+ {
+ // Example 430
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // foo __*__
+ //
+ // Should be rendered as:
+ // foo *
+
+ Console.WriteLine("Example 430\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("foo __*__", "foo *
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example431()
+ {
+ // Example 431
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo_
+ //
+ // Should be rendered as:
+ // _foo
+
+ Console.WriteLine("Example 431\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo_", "_foo
", "");
+ }
+
+ // Note that when delimiters do not match evenly, Rule 12 determines
+ // that the excess literal `_` characters will appear outside of the
+ // emphasis, rather than inside it:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example432()
+ {
+ // Example 432
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo__
+ //
+ // Should be rendered as:
+ // foo_
+
+ Console.WriteLine("Example 432\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo__", "foo_
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example433()
+ {
+ // Example 433
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ___foo__
+ //
+ // Should be rendered as:
+ // _foo
+
+ Console.WriteLine("Example 433\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("___foo__", "_foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example434()
+ {
+ // Example 434
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ____foo_
+ //
+ // Should be rendered as:
+ // ___foo
+
+ Console.WriteLine("Example 434\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("____foo_", "___foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example435()
+ {
+ // Example 435
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo___
+ //
+ // Should be rendered as:
+ // foo_
+
+ Console.WriteLine("Example 435\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo___", "foo_
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example436()
+ {
+ // Example 436
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo____
+ //
+ // Should be rendered as:
+ // foo___
+
+ Console.WriteLine("Example 436\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo____", "foo___
", "");
+ }
+
+ // Rule 13 implies that if you want emphasis nested directly inside
+ // emphasis, you must use different delimiters:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example437()
+ {
+ // Example 437
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo**
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 437\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo**", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example438()
+ {
+ // Example 438
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *_foo_*
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 438\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*_foo_*", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example439()
+ {
+ // Example 439
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __foo__
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 439\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__foo__", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example440()
+ {
+ // Example 440
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _*foo*_
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 440\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_*foo*_", "foo
", "");
+ }
+
+ // However, strong emphasis within strong emphasis is possible without
+ // switching delimiters:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example441()
+ {
+ // Example 441
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ****foo****
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 441\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("****foo****", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example442()
+ {
+ // Example 442
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ____foo____
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 442\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("____foo____", "foo
", "");
+ }
+
+ // Rule 13 can be applied to arbitrarily long sequences of
+ // delimiters:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example443()
+ {
+ // Example 443
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ******foo******
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 443\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("******foo******", "foo
", "");
+ }
+
+ // Rule 14:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example444()
+ {
+ // Example 444
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // ***foo***
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 444\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("***foo***", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example445()
+ {
+ // Example 445
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _____foo_____
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 445\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_____foo_____", "foo
", "");
+ }
+
+ // Rule 15:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example446()
+ {
+ // Example 446
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo _bar* baz_
+ //
+ // Should be rendered as:
+ // foo _bar baz_
+
+ Console.WriteLine("Example 446\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo _bar* baz_", "foo _bar baz_
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example447()
+ {
+ // Example 447
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo __bar *baz bim__ bam*
+ //
+ // Should be rendered as:
+ // foo bar *baz bim bam
+
+ Console.WriteLine("Example 447\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo __bar *baz bim__ bam*", "foo bar *baz bim bam
", "");
+ }
+
+ // Rule 16:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example448()
+ {
+ // Example 448
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **foo **bar baz**
+ //
+ // Should be rendered as:
+ // **foo bar baz
+
+ Console.WriteLine("Example 448\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**foo **bar baz**", "**foo bar baz
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example449()
+ {
+ // Example 449
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *foo *bar baz*
+ //
+ // Should be rendered as:
+ // *foo bar baz
+
+ Console.WriteLine("Example 449\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*foo *bar baz*", "*foo bar baz
", "");
+ }
+
+ // Rule 17:
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example450()
+ {
+ // Example 450
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *[bar*](/url)
+ //
+ // Should be rendered as:
+ // *bar*
+
+ Console.WriteLine("Example 450\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*[bar*](/url)", "*bar*
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example451()
+ {
+ // Example 451
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _foo [bar_](/url)
+ //
+ // Should be rendered as:
+ // _foo bar_
+
+ Console.WriteLine("Example 451\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_foo [bar_](/url)", "_foo bar_
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example452()
+ {
+ // Example 452
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *
+ //
+ // Should be rendered as:
+ // *
+
+ Console.WriteLine("Example 452\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*
", "*
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example453()
+ {
+ // Example 453
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **
+ //
+ // Should be rendered as:
+ // **
+
+ Console.WriteLine("Example 453\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**", "**
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example454()
+ {
+ // Example 454
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __
+ //
+ // Should be rendered as:
+ // __
+
+ Console.WriteLine("Example 454\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__", "__
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example455()
+ {
+ // Example 455
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // *a `*`*
+ //
+ // Should be rendered as:
+ // a *
+
+ Console.WriteLine("Example 455\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("*a `*`*", "a *
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example456()
+ {
+ // Example 456
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // _a `_`_
+ //
+ // Should be rendered as:
+ // a _
+
+ Console.WriteLine("Example 456\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("_a `_`_", "a _
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example457()
+ {
+ // Example 457
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // **a
+ //
+ // Should be rendered as:
+ // **ahttp://foo.bar/?q=**
+
+ Console.WriteLine("Example 457\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("**a", "**ahttp://foo.bar/?q=**
", "");
+ }
+
+ [Test]
+ public void InlinesEmphasisAndStrongEmphasis_Example458()
+ {
+ // Example 458
+ // Section: Inlines / Emphasis and strong emphasis
+ //
+ // The following Markdown:
+ // __a
+ //
+ // Should be rendered as:
+ // __ahttp://foo.bar/?q=__
+
+ Console.WriteLine("Example 458\nSection Inlines / Emphasis and strong emphasis\n");
+ TestParser.TestSpec("__a", "__ahttp://foo.bar/?q=__
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesLinks
+ {
+ // ## Links
+ //
+ // A link contains [link text] (the visible text), a [link destination]
+ // (the URI that is the link destination), and optionally a [link title].
+ // There are two basic kinds of links in Markdown. In [inline links] the
+ // destination and title are given immediately after the link text. In
+ // [reference links] the destination and title are defined elsewhere in
+ // the document.
+ //
+ // A [link text](@) consists of a sequence of zero or more
+ // inline elements enclosed by square brackets (`[` and `]`). The
+ // following rules apply:
+ //
+ // - Links may not contain other links, at any level of nesting. If
+ // multiple otherwise valid link definitions appear nested inside each
+ // other, the inner-most definition is used.
+ //
+ // - Brackets are allowed in the [link text] only if (a) they
+ // are backslash-escaped or (b) they appear as a matched pair of brackets,
+ // with an open bracket `[`, a sequence of zero or more inlines, and
+ // a close bracket `]`.
+ //
+ // - Backtick [code spans], [autolinks], and raw [HTML tags] bind more tightly
+ // than the brackets in link text. Thus, for example,
+ // `` [foo`]` `` could not be a link text, since the second `]`
+ // is part of a code span.
+ //
+ // - The brackets in link text bind more tightly than markers for
+ // [emphasis and strong emphasis]. Thus, for example, `*[foo*](url)` is a link.
+ //
+ // A [link destination](@) consists of either
+ //
+ // - a sequence of zero or more characters between an opening `<` and a
+ // closing `>` that contains no spaces, line breaks, or unescaped
+ // `<` or `>` characters, or
+ //
+ // - a nonempty sequence of characters that does not include
+ // ASCII space or control characters, and includes parentheses
+ // only if (a) they are backslash-escaped or (b) they are part of
+ // a balanced pair of unescaped parentheses. (Implementations
+ // may impose limits on parentheses nesting to avoid performance
+ // issues, but at least three levels of nesting should be supported.)
+ //
+ // A [link title](@) consists of either
+ //
+ // - a sequence of zero or more characters between straight double-quote
+ // characters (`"`), including a `"` character only if it is
+ // backslash-escaped, or
+ //
+ // - a sequence of zero or more characters between straight single-quote
+ // characters (`'`), including a `'` character only if it is
+ // backslash-escaped, or
+ //
+ // - a sequence of zero or more characters between matching parentheses
+ // (`(...)`), including a `)` character only if it is backslash-escaped.
+ //
+ // Although [link titles] may span multiple lines, they may not contain
+ // a [blank line].
+ //
+ // An [inline link](@) consists of a [link text] followed immediately
+ // by a left parenthesis `(`, optional [whitespace], an optional
+ // [link destination], an optional [link title] separated from the link
+ // destination by [whitespace], optional [whitespace], and a right
+ // parenthesis `)`. The link's text consists of the inlines contained
+ // in the [link text] (excluding the enclosing square brackets).
+ // The link's URI consists of the link destination, excluding enclosing
+ // `<...>` if present, with backslash-escapes in effect as described
+ // above. The link's title consists of the link title, excluding its
+ // enclosing delimiters, with backslash-escapes in effect as described
+ // above.
+ //
+ // Here is a simple inline link:
+ [Test]
+ public void InlinesLinks_Example459()
+ {
+ // Example 459
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/uri "title")
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 459\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/uri \"title\")", "link
", "");
+ }
+
+ // The title may be omitted:
+ [Test]
+ public void InlinesLinks_Example460()
+ {
+ // Example 460
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/uri)
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 460\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/uri)", "link
", "");
+ }
+
+ // Both the title and the destination may be omitted:
+ [Test]
+ public void InlinesLinks_Example461()
+ {
+ // Example 461
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link]()
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 461\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link]()", "link
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example462()
+ {
+ // Example 462
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](<>)
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 462\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](<>)", "link
", "");
+ }
+
+ // The destination cannot contain spaces or line breaks,
+ // even if enclosed in pointy brackets:
+ [Test]
+ public void InlinesLinks_Example463()
+ {
+ // Example 463
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/my uri)
+ //
+ // Should be rendered as:
+ // [link](/my uri)
+
+ Console.WriteLine("Example 463\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/my uri)", "[link](/my uri)
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example464()
+ {
+ // Example 464
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link]()
+ //
+ // Should be rendered as:
+ // [link](</my uri>)
+
+ Console.WriteLine("Example 464\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link]()", "[link](</my uri>)
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example465()
+ {
+ // Example 465
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](foo
+ // bar)
+ //
+ // Should be rendered as:
+ // [link](foo
+ // bar)
+
+ Console.WriteLine("Example 465\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](foo\nbar)", "[link](foo\nbar)
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example466()
+ {
+ // Example 466
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link]()
+ //
+ // Should be rendered as:
+ // [link]()
+
+ Console.WriteLine("Example 466\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link]()", "[link]()
", "");
+ }
+
+ // Parentheses inside the link destination may be escaped:
+ [Test]
+ public void InlinesLinks_Example467()
+ {
+ // Example 467
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](\(foo\))
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 467\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](\\(foo\\))", "link
", "");
+ }
+
+ // Any number of parentheses are allowed without escaping, as long as they are
+ // balanced:
+ [Test]
+ public void InlinesLinks_Example468()
+ {
+ // Example 468
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](foo(and(bar)))
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 468\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](foo(and(bar)))", "link
", "");
+ }
+
+ // However, if you have unbalanced parentheses, you need to escape or use the
+ // `<...>` form:
+ [Test]
+ public void InlinesLinks_Example469()
+ {
+ // Example 469
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](foo\(and\(bar\))
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 469\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](foo\\(and\\(bar\\))", "link
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example470()
+ {
+ // Example 470
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link]()
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 470\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link]()", "link
", "");
+ }
+
+ // Parentheses and other symbols can also be escaped, as usual
+ // in Markdown:
+ [Test]
+ public void InlinesLinks_Example471()
+ {
+ // Example 471
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](foo\)\:)
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 471\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](foo\\)\\:)", "link
", "");
+ }
+
+ // A link can contain fragment identifiers and queries:
+ [Test]
+ public void InlinesLinks_Example472()
+ {
+ // Example 472
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](#fragment)
+ //
+ // [link](http://example.com#fragment)
+ //
+ // [link](http://example.com?foo=3#frag)
+ //
+ // Should be rendered as:
+ // link
+ // link
+ // link
+
+ Console.WriteLine("Example 472\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](#fragment)\n\n[link](http://example.com#fragment)\n\n[link](http://example.com?foo=3#frag)", "link
\nlink
\nlink
", "");
+ }
+
+ // Note that a backslash before a non-escapable character is
+ // just a backslash:
+ [Test]
+ public void InlinesLinks_Example473()
+ {
+ // Example 473
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](foo\bar)
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 473\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](foo\\bar)", "link
", "");
+ }
+
+ // URL-escaping should be left alone inside the destination, as all
+ // URL-escaped characters are also valid URL characters. Entity and
+ // numerical character references in the destination will be parsed
+ // into the corresponding Unicode code points, as usual. These may
+ // be optionally URL-escaped when written as HTML, but this spec
+ // does not enforce any particular policy for rendering URLs in
+ // HTML or other formats. Renderers may make different decisions
+ // about how to escape or normalize URLs in the output.
+ [Test]
+ public void InlinesLinks_Example474()
+ {
+ // Example 474
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](foo%20bä)
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 474\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](foo%20bä)", "link
", "");
+ }
+
+ // Note that, because titles can often be parsed as destinations,
+ // if you try to omit the destination and keep the title, you'll
+ // get unexpected results:
+ [Test]
+ public void InlinesLinks_Example475()
+ {
+ // Example 475
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link]("title")
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 475\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](\"title\")", "link
", "");
+ }
+
+ // Titles may be in single quotes, double quotes, or parentheses:
+ [Test]
+ public void InlinesLinks_Example476()
+ {
+ // Example 476
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/url "title")
+ // [link](/url 'title')
+ // [link](/url (title))
+ //
+ // Should be rendered as:
+ // link
+ // link
+ // link
+
+ Console.WriteLine("Example 476\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/url \"title\")\n[link](/url 'title')\n[link](/url (title))", "link\nlink\nlink
", "");
+ }
+
+ // Backslash escapes and entity and numeric character references
+ // may be used in titles:
+ [Test]
+ public void InlinesLinks_Example477()
+ {
+ // Example 477
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/url "title \""")
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 477\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/url \"title \\\""\")", "link
", "");
+ }
+
+ // Titles must be separated from the link using a [whitespace].
+ // Other [Unicode whitespace] like non-breaking space doesn't work.
+ [Test]
+ public void InlinesLinks_Example478()
+ {
+ // Example 478
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/url "title")
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 478\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/url \"title\")", "link
", "");
+ }
+
+ // Nested balanced quotes are not allowed without escaping:
+ [Test]
+ public void InlinesLinks_Example479()
+ {
+ // Example 479
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/url "title "and" title")
+ //
+ // Should be rendered as:
+ // [link](/url "title "and" title")
+
+ Console.WriteLine("Example 479\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/url \"title \"and\" title\")", "[link](/url "title "and" title")
", "");
+ }
+
+ // But it is easy to work around this by using a different quote type:
+ [Test]
+ public void InlinesLinks_Example480()
+ {
+ // Example 480
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link](/url 'title "and" title')
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 480\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link](/url 'title \"and\" title')", "link
", "");
+ }
+
+ // (Note: `Markdown.pl` did allow double quotes inside a double-quoted
+ // title, and its test suite included a test demonstrating this.
+ // But it is hard to see a good rationale for the extra complexity this
+ // brings, since there are already many ways---backslash escaping,
+ // entity and numeric character references, or using a different
+ // quote type for the enclosing title---to write titles containing
+ // double quotes. `Markdown.pl`'s handling of titles has a number
+ // of other strange features. For example, it allows single-quoted
+ // titles in inline links, but not reference links. And, in
+ // reference links but not inline links, it allows a title to begin
+ // with `"` and end with `)`. `Markdown.pl` 1.0.1 even allows
+ // titles with no closing quotation mark, though 1.0.2b8 does not.
+ // It seems preferable to adopt a simple, rational rule that works
+ // the same way in inline links and link reference definitions.)
+ //
+ // [Whitespace] is allowed around the destination and title:
+ [Test]
+ public void InlinesLinks_Example481()
+ {
+ // Example 481
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link]( /uri
+ // "title" )
+ //
+ // Should be rendered as:
+ // link
+
+ Console.WriteLine("Example 481\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link]( /uri\n \"title\" )", "link
", "");
+ }
+
+ // But it is not allowed between the link text and the
+ // following parenthesis:
+ [Test]
+ public void InlinesLinks_Example482()
+ {
+ // Example 482
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link] (/uri)
+ //
+ // Should be rendered as:
+ // [link] (/uri)
+
+ Console.WriteLine("Example 482\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link] (/uri)", "[link] (/uri)
", "");
+ }
+
+ // The link text may contain balanced brackets, but not unbalanced ones,
+ // unless they are escaped:
+ [Test]
+ public void InlinesLinks_Example483()
+ {
+ // Example 483
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link [foo [bar]]](/uri)
+ //
+ // Should be rendered as:
+ // link [foo [bar]]
+
+ Console.WriteLine("Example 483\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link [foo [bar]]](/uri)", "link [foo [bar]]
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example484()
+ {
+ // Example 484
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link] bar](/uri)
+ //
+ // Should be rendered as:
+ // [link] bar](/uri)
+
+ Console.WriteLine("Example 484\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link] bar](/uri)", "[link] bar](/uri)
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example485()
+ {
+ // Example 485
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link [bar](/uri)
+ //
+ // Should be rendered as:
+ // [link bar
+
+ Console.WriteLine("Example 485\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link [bar](/uri)", "[link bar
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example486()
+ {
+ // Example 486
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link \[bar](/uri)
+ //
+ // Should be rendered as:
+ // link [bar
+
+ Console.WriteLine("Example 486\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link \\[bar](/uri)", "link [bar
", "");
+ }
+
+ // The link text may contain inline content:
+ [Test]
+ public void InlinesLinks_Example487()
+ {
+ // Example 487
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link *foo **bar** `#`*](/uri)
+ //
+ // Should be rendered as:
+ // link foo bar #
+
+ Console.WriteLine("Example 487\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link *foo **bar** `#`*](/uri)", "link foo bar #
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example488()
+ {
+ // Example 488
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [](/uri)
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 488\nSection Inlines / Links\n");
+ TestParser.TestSpec("[](/uri)", "
", "");
+ }
+
+ // However, links may not contain other links, at any level of nesting.
+ [Test]
+ public void InlinesLinks_Example489()
+ {
+ // Example 489
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo [bar](/uri)](/uri)
+ //
+ // Should be rendered as:
+ // [foo bar](/uri)
+
+ Console.WriteLine("Example 489\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo [bar](/uri)](/uri)", "[foo bar](/uri)
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example490()
+ {
+ // Example 490
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo *[bar [baz](/uri)](/uri)*](/uri)
+ //
+ // Should be rendered as:
+ // [foo [bar baz](/uri)](/uri)
+
+ Console.WriteLine("Example 490\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo *[bar [baz](/uri)](/uri)*](/uri)", "[foo [bar baz](/uri)](/uri)
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example491()
+ {
+ // Example 491
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // ](uri2)](uri3)
+ //
+ // Should be rendered as:
+ // ](uri3)
+
+ Console.WriteLine("Example 491\nSection Inlines / Links\n");
+ TestParser.TestSpec("](uri2)](uri3)", "\"](\"uri3\")
", "");
+ }
+
+ // These cases illustrate the precedence of link text grouping over
+ // emphasis grouping:
+ [Test]
+ public void InlinesLinks_Example492()
+ {
+ // Example 492
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // *[foo*](/uri)
+ //
+ // Should be rendered as:
+ // *foo*
+
+ Console.WriteLine("Example 492\nSection Inlines / Links\n");
+ TestParser.TestSpec("*[foo*](/uri)", "*foo*
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example493()
+ {
+ // Example 493
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo *bar](baz*)
+ //
+ // Should be rendered as:
+ // foo *bar
+
+ Console.WriteLine("Example 493\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo *bar](baz*)", "foo *bar
", "");
+ }
+
+ // Note that brackets that *aren't* part of links do not take
+ // precedence:
+ [Test]
+ public void InlinesLinks_Example494()
+ {
+ // Example 494
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // *foo [bar* baz]
+ //
+ // Should be rendered as:
+ // foo [bar baz]
+
+ Console.WriteLine("Example 494\nSection Inlines / Links\n");
+ TestParser.TestSpec("*foo [bar* baz]", "foo [bar baz]
", "");
+ }
+
+ // These cases illustrate the precedence of HTML tags, code spans,
+ // and autolinks over link grouping:
+ [Test]
+ public void InlinesLinks_Example495()
+ {
+ // Example 495
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo
+ //
+ // Should be rendered as:
+ // [foo
+
+ Console.WriteLine("Example 495\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo ", "[foo
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example496()
+ {
+ // Example 496
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo`](/uri)`
+ //
+ // Should be rendered as:
+ // [foo](/uri)
+
+ Console.WriteLine("Example 496\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo`](/uri)`", "[foo](/uri)
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example497()
+ {
+ // Example 497
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo
+ //
+ // Should be rendered as:
+ // [foohttp://example.com/?search=](uri)
+
+ Console.WriteLine("Example 497\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo", "[foohttp://example.com/?search=](uri)
", "");
+ }
+
+ // There are three kinds of [reference link](@)s:
+ // [full](#full-reference-link), [collapsed](#collapsed-reference-link),
+ // and [shortcut](#shortcut-reference-link).
+ //
+ // A [full reference link](@)
+ // consists of a [link text] immediately followed by a [link label]
+ // that [matches] a [link reference definition] elsewhere in the document.
+ //
+ // A [link label](@) begins with a left bracket (`[`) and ends
+ // with the first right bracket (`]`) that is not backslash-escaped.
+ // Between these brackets there must be at least one [non-whitespace character].
+ // Unescaped square bracket characters are not allowed inside the
+ // opening and closing square brackets of [link labels]. A link
+ // label can have at most 999 characters inside the square
+ // brackets.
+ //
+ // One label [matches](@)
+ // another just in case their normalized forms are equal. To normalize a
+ // label, strip off the opening and closing brackets,
+ // perform the *Unicode case fold*, strip leading and trailing
+ // [whitespace] and collapse consecutive internal
+ // [whitespace] to a single space. If there are multiple
+ // matching reference link definitions, the one that comes first in the
+ // document is used. (It is desirable in such cases to emit a warning.)
+ //
+ // The contents of the first link label are parsed as inlines, which are
+ // used as the link's text. The link's URI and title are provided by the
+ // matching [link reference definition].
+ //
+ // Here is a simple example:
+ [Test]
+ public void InlinesLinks_Example498()
+ {
+ // Example 498
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][bar]
+ //
+ // [bar]: /url "title"
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 498\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][bar]\n\n[bar]: /url \"title\"", "foo
", "");
+ }
+
+ // The rules for the [link text] are the same as with
+ // [inline links]. Thus:
+ //
+ // The link text may contain balanced brackets, but not unbalanced ones,
+ // unless they are escaped:
+ [Test]
+ public void InlinesLinks_Example499()
+ {
+ // Example 499
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link [foo [bar]]][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // link [foo [bar]]
+
+ Console.WriteLine("Example 499\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link [foo [bar]]][ref]\n\n[ref]: /uri", "link [foo [bar]]
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example500()
+ {
+ // Example 500
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link \[bar][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // link [bar
+
+ Console.WriteLine("Example 500\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link \\[bar][ref]\n\n[ref]: /uri", "link [bar
", "");
+ }
+
+ // The link text may contain inline content:
+ [Test]
+ public void InlinesLinks_Example501()
+ {
+ // Example 501
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [link *foo **bar** `#`*][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // link foo bar #
+
+ Console.WriteLine("Example 501\nSection Inlines / Links\n");
+ TestParser.TestSpec("[link *foo **bar** `#`*][ref]\n\n[ref]: /uri", "link foo bar #
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example502()
+ {
+ // Example 502
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 502\nSection Inlines / Links\n");
+ TestParser.TestSpec("[][ref]\n\n[ref]: /uri", "
", "");
+ }
+
+ // However, links may not contain other links, at any level of nesting.
+ [Test]
+ public void InlinesLinks_Example503()
+ {
+ // Example 503
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo [bar](/uri)][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // [foo bar]ref
+
+ Console.WriteLine("Example 503\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo [bar](/uri)][ref]\n\n[ref]: /uri", "[foo bar]ref
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example504()
+ {
+ // Example 504
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo *bar [baz][ref]*][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // [foo bar baz]ref
+
+ Console.WriteLine("Example 504\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo *bar [baz][ref]*][ref]\n\n[ref]: /uri", "[foo bar baz]ref
", "");
+ }
+
+ // (In the examples above, we have two [shortcut reference links]
+ // instead of one [full reference link].)
+ //
+ // The following cases illustrate the precedence of link text grouping over
+ // emphasis grouping:
+ [Test]
+ public void InlinesLinks_Example505()
+ {
+ // Example 505
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // *[foo*][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // *foo*
+
+ Console.WriteLine("Example 505\nSection Inlines / Links\n");
+ TestParser.TestSpec("*[foo*][ref]\n\n[ref]: /uri", "*foo*
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example506()
+ {
+ // Example 506
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo *bar][ref]
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // foo *bar
+
+ Console.WriteLine("Example 506\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo *bar][ref]\n\n[ref]: /uri", "foo *bar
", "");
+ }
+
+ // These cases illustrate the precedence of HTML tags, code spans,
+ // and autolinks over link grouping:
+ [Test]
+ public void InlinesLinks_Example507()
+ {
+ // Example 507
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // [foo
+
+ Console.WriteLine("Example 507\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo \n\n[ref]: /uri", "[foo
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example508()
+ {
+ // Example 508
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo`][ref]`
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // [foo][ref]
+
+ Console.WriteLine("Example 508\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo`][ref]`\n\n[ref]: /uri", "[foo][ref]
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example509()
+ {
+ // Example 509
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo
+ //
+ // [ref]: /uri
+ //
+ // Should be rendered as:
+ // [foohttp://example.com/?search=][ref]
+
+ Console.WriteLine("Example 509\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo\n\n[ref]: /uri", "[foohttp://example.com/?search=][ref]
", "");
+ }
+
+ // Matching is case-insensitive:
+ [Test]
+ public void InlinesLinks_Example510()
+ {
+ // Example 510
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][BaR]
+ //
+ // [bar]: /url "title"
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 510\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][BaR]\n\n[bar]: /url \"title\"", "foo
", "");
+ }
+
+ // Unicode case fold is used:
+ [Test]
+ public void InlinesLinks_Example511()
+ {
+ // Example 511
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [Толпой][Толпой] is a Russian word.
+ //
+ // [ТОЛПОЙ]: /url
+ //
+ // Should be rendered as:
+ // Толпой is a Russian word.
+
+ Console.WriteLine("Example 511\nSection Inlines / Links\n");
+ TestParser.TestSpec("[Толпой][Толпой] is a Russian word.\n\n[ТОЛПОЙ]: /url", "Толпой is a Russian word.
", "");
+ }
+
+ // Consecutive internal [whitespace] is treated as one space for
+ // purposes of determining matching:
+ [Test]
+ public void InlinesLinks_Example512()
+ {
+ // Example 512
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [Foo
+ // bar]: /url
+ //
+ // [Baz][Foo bar]
+ //
+ // Should be rendered as:
+ // Baz
+
+ Console.WriteLine("Example 512\nSection Inlines / Links\n");
+ TestParser.TestSpec("[Foo\n bar]: /url\n\n[Baz][Foo bar]", "Baz
", "");
+ }
+
+ // No [whitespace] is allowed between the [link text] and the
+ // [link label]:
+ [Test]
+ public void InlinesLinks_Example513()
+ {
+ // Example 513
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo] [bar]
+ //
+ // [bar]: /url "title"
+ //
+ // Should be rendered as:
+ // [foo] bar
+
+ Console.WriteLine("Example 513\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo] [bar]\n\n[bar]: /url \"title\"", "[foo] bar
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example514()
+ {
+ // Example 514
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo]
+ // [bar]
+ //
+ // [bar]: /url "title"
+ //
+ // Should be rendered as:
+ // [foo]
+ // bar
+
+ Console.WriteLine("Example 514\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo]\n[bar]\n\n[bar]: /url \"title\"", "[foo]\nbar
", "");
+ }
+
+ // This is a departure from John Gruber's original Markdown syntax
+ // description, which explicitly allows whitespace between the link
+ // text and the link label. It brings reference links in line with
+ // [inline links], which (according to both original Markdown and
+ // this spec) cannot have whitespace after the link text. More
+ // importantly, it prevents inadvertent capture of consecutive
+ // [shortcut reference links]. If whitespace is allowed between the
+ // link text and the link label, then in the following we will have
+ // a single reference link, not two shortcut reference links, as
+ // intended:
+ //
+ // ``` markdown
+ // [foo]
+ // [bar]
+ //
+ // [foo]: /url1
+ // [bar]: /url2
+ // ```
+ //
+ // (Note that [shortcut reference links] were introduced by Gruber
+ // himself in a beta version of `Markdown.pl`, but never included
+ // in the official syntax description. Without shortcut reference
+ // links, it is harmless to allow space between the link text and
+ // link label; but once shortcut references are introduced, it is
+ // too dangerous to allow this, as it frequently leads to
+ // unintended results.)
+ //
+ // When there are multiple matching [link reference definitions],
+ // the first is used:
+ [Test]
+ public void InlinesLinks_Example515()
+ {
+ // Example 515
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo]: /url1
+ //
+ // [foo]: /url2
+ //
+ // [bar][foo]
+ //
+ // Should be rendered as:
+ // bar
+
+ Console.WriteLine("Example 515\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo]: /url1\n\n[foo]: /url2\n\n[bar][foo]", "bar
", "");
+ }
+
+ // Note that matching is performed on normalized strings, not parsed
+ // inline content. So the following does not match, even though the
+ // labels define equivalent inline content:
+ [Test]
+ public void InlinesLinks_Example516()
+ {
+ // Example 516
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [bar][foo\!]
+ //
+ // [foo!]: /url
+ //
+ // Should be rendered as:
+ // [bar][foo!]
+
+ Console.WriteLine("Example 516\nSection Inlines / Links\n");
+ TestParser.TestSpec("[bar][foo\\!]\n\n[foo!]: /url", "[bar][foo!]
", "");
+ }
+
+ // [Link labels] cannot contain brackets, unless they are
+ // backslash-escaped:
+ [Test]
+ public void InlinesLinks_Example517()
+ {
+ // Example 517
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][ref[]
+ //
+ // [ref[]: /uri
+ //
+ // Should be rendered as:
+ // [foo][ref[]
+ // [ref[]: /uri
+
+ Console.WriteLine("Example 517\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][ref[]\n\n[ref[]: /uri", "[foo][ref[]
\n[ref[]: /uri
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example518()
+ {
+ // Example 518
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][ref[bar]]
+ //
+ // [ref[bar]]: /uri
+ //
+ // Should be rendered as:
+ // [foo][ref[bar]]
+ // [ref[bar]]: /uri
+
+ Console.WriteLine("Example 518\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][ref[bar]]\n\n[ref[bar]]: /uri", "[foo][ref[bar]]
\n[ref[bar]]: /uri
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example519()
+ {
+ // Example 519
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [[[foo]]]
+ //
+ // [[[foo]]]: /url
+ //
+ // Should be rendered as:
+ // [[[foo]]]
+ // [[[foo]]]: /url
+
+ Console.WriteLine("Example 519\nSection Inlines / Links\n");
+ TestParser.TestSpec("[[[foo]]]\n\n[[[foo]]]: /url", "[[[foo]]]
\n[[[foo]]]: /url
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example520()
+ {
+ // Example 520
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][ref\[]
+ //
+ // [ref\[]: /uri
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 520\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][ref\\[]\n\n[ref\\[]: /uri", "foo
", "");
+ }
+
+ // Note that in this example `]` is not backslash-escaped:
+ [Test]
+ public void InlinesLinks_Example521()
+ {
+ // Example 521
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [bar\\]: /uri
+ //
+ // [bar\\]
+ //
+ // Should be rendered as:
+ // bar\
+
+ Console.WriteLine("Example 521\nSection Inlines / Links\n");
+ TestParser.TestSpec("[bar\\\\]: /uri\n\n[bar\\\\]", "bar\\
", "");
+ }
+
+ // A [link label] must contain at least one [non-whitespace character]:
+ [Test]
+ public void InlinesLinks_Example522()
+ {
+ // Example 522
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // []
+ //
+ // []: /uri
+ //
+ // Should be rendered as:
+ // []
+ // []: /uri
+
+ Console.WriteLine("Example 522\nSection Inlines / Links\n");
+ TestParser.TestSpec("[]\n\n[]: /uri", "[]
\n[]: /uri
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example523()
+ {
+ // Example 523
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [
+ // ]
+ //
+ // [
+ // ]: /uri
+ //
+ // Should be rendered as:
+ // [
+ // ]
+ // [
+ // ]: /uri
+
+ Console.WriteLine("Example 523\nSection Inlines / Links\n");
+ TestParser.TestSpec("[\n ]\n\n[\n ]: /uri", "[\n]
\n[\n]: /uri
", "");
+ }
+
+ // A [collapsed reference link](@)
+ // consists of a [link label] that [matches] a
+ // [link reference definition] elsewhere in the
+ // document, followed by the string `[]`.
+ // The contents of the first link label are parsed as inlines,
+ // which are used as the link's text. The link's URI and title are
+ // provided by the matching reference link definition. Thus,
+ // `[foo][]` is equivalent to `[foo][foo]`.
+ [Test]
+ public void InlinesLinks_Example524()
+ {
+ // Example 524
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 524\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][]\n\n[foo]: /url \"title\"", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example525()
+ {
+ // Example 525
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [*foo* bar][]
+ //
+ // [*foo* bar]: /url "title"
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 525\nSection Inlines / Links\n");
+ TestParser.TestSpec("[*foo* bar][]\n\n[*foo* bar]: /url \"title\"", "foo bar
", "");
+ }
+
+ // The link labels are case-insensitive:
+ [Test]
+ public void InlinesLinks_Example526()
+ {
+ // Example 526
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [Foo][]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // Foo
+
+ Console.WriteLine("Example 526\nSection Inlines / Links\n");
+ TestParser.TestSpec("[Foo][]\n\n[foo]: /url \"title\"", "Foo
", "");
+ }
+
+ // As with full reference links, [whitespace] is not
+ // allowed between the two sets of brackets:
+ [Test]
+ public void InlinesLinks_Example527()
+ {
+ // Example 527
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo]
+ // []
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // foo
+ // []
+
+ Console.WriteLine("Example 527\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo] \n[]\n\n[foo]: /url \"title\"", "foo\n[]
", "");
+ }
+
+ // A [shortcut reference link](@)
+ // consists of a [link label] that [matches] a
+ // [link reference definition] elsewhere in the
+ // document and is not followed by `[]` or a link label.
+ // The contents of the first link label are parsed as inlines,
+ // which are used as the link's text. The link's URI and title
+ // are provided by the matching link reference definition.
+ // Thus, `[foo]` is equivalent to `[foo][]`.
+ [Test]
+ public void InlinesLinks_Example528()
+ {
+ // Example 528
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 528\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo]\n\n[foo]: /url \"title\"", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example529()
+ {
+ // Example 529
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [*foo* bar]
+ //
+ // [*foo* bar]: /url "title"
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 529\nSection Inlines / Links\n");
+ TestParser.TestSpec("[*foo* bar]\n\n[*foo* bar]: /url \"title\"", "foo bar
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example530()
+ {
+ // Example 530
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [[*foo* bar]]
+ //
+ // [*foo* bar]: /url "title"
+ //
+ // Should be rendered as:
+ // [foo bar]
+
+ Console.WriteLine("Example 530\nSection Inlines / Links\n");
+ TestParser.TestSpec("[[*foo* bar]]\n\n[*foo* bar]: /url \"title\"", "[foo bar]
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example531()
+ {
+ // Example 531
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [[bar [foo]
+ //
+ // [foo]: /url
+ //
+ // Should be rendered as:
+ // [[bar foo
+
+ Console.WriteLine("Example 531\nSection Inlines / Links\n");
+ TestParser.TestSpec("[[bar [foo]\n\n[foo]: /url", "[[bar foo
", "");
+ }
+
+ // The link labels are case-insensitive:
+ [Test]
+ public void InlinesLinks_Example532()
+ {
+ // Example 532
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [Foo]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // Foo
+
+ Console.WriteLine("Example 532\nSection Inlines / Links\n");
+ TestParser.TestSpec("[Foo]\n\n[foo]: /url \"title\"", "Foo
", "");
+ }
+
+ // A space after the link text should be preserved:
+ [Test]
+ public void InlinesLinks_Example533()
+ {
+ // Example 533
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo] bar
+ //
+ // [foo]: /url
+ //
+ // Should be rendered as:
+ // foo bar
+
+ Console.WriteLine("Example 533\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo] bar\n\n[foo]: /url", "foo bar
", "");
+ }
+
+ // If you just want bracketed text, you can backslash-escape the
+ // opening bracket to avoid links:
+ [Test]
+ public void InlinesLinks_Example534()
+ {
+ // Example 534
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // \[foo]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // [foo]
+
+ Console.WriteLine("Example 534\nSection Inlines / Links\n");
+ TestParser.TestSpec("\\[foo]\n\n[foo]: /url \"title\"", "[foo]
", "");
+ }
+
+ // Note that this is a link, because a link label ends with the first
+ // following closing bracket:
+ [Test]
+ public void InlinesLinks_Example535()
+ {
+ // Example 535
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo*]: /url
+ //
+ // *[foo*]
+ //
+ // Should be rendered as:
+ // *foo*
+
+ Console.WriteLine("Example 535\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo*]: /url\n\n*[foo*]", "*foo*
", "");
+ }
+
+ // Full and compact references take precedence over shortcut
+ // references:
+ [Test]
+ public void InlinesLinks_Example536()
+ {
+ // Example 536
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][bar]
+ //
+ // [foo]: /url1
+ // [bar]: /url2
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 536\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][bar]\n\n[foo]: /url1\n[bar]: /url2", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example537()
+ {
+ // Example 537
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][]
+ //
+ // [foo]: /url1
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 537\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][]\n\n[foo]: /url1", "foo
", "");
+ }
+
+ // Inline links also take precedence:
+ [Test]
+ public void InlinesLinks_Example538()
+ {
+ // Example 538
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo]()
+ //
+ // [foo]: /url1
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 538\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo]()\n\n[foo]: /url1", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesLinks_Example539()
+ {
+ // Example 539
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo](not a link)
+ //
+ // [foo]: /url1
+ //
+ // Should be rendered as:
+ // foo(not a link)
+
+ Console.WriteLine("Example 539\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo](not a link)\n\n[foo]: /url1", "foo(not a link)
", "");
+ }
+
+ // In the following case `[bar][baz]` is parsed as a reference,
+ // `[foo]` as normal text:
+ [Test]
+ public void InlinesLinks_Example540()
+ {
+ // Example 540
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][bar][baz]
+ //
+ // [baz]: /url
+ //
+ // Should be rendered as:
+ // [foo]bar
+
+ Console.WriteLine("Example 540\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][bar][baz]\n\n[baz]: /url", "[foo]bar
", "");
+ }
+
+ // Here, though, `[foo][bar]` is parsed as a reference, since
+ // `[bar]` is defined:
+ [Test]
+ public void InlinesLinks_Example541()
+ {
+ // Example 541
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][bar][baz]
+ //
+ // [baz]: /url1
+ // [bar]: /url2
+ //
+ // Should be rendered as:
+ // foobaz
+
+ Console.WriteLine("Example 541\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][bar][baz]\n\n[baz]: /url1\n[bar]: /url2", "foobaz
", "");
+ }
+
+ // Here `[foo]` is not parsed as a shortcut reference, because it
+ // is followed by a link label (even though `[bar]` is not defined):
+ [Test]
+ public void InlinesLinks_Example542()
+ {
+ // Example 542
+ // Section: Inlines / Links
+ //
+ // The following Markdown:
+ // [foo][bar][baz]
+ //
+ // [baz]: /url1
+ // [foo]: /url2
+ //
+ // Should be rendered as:
+ // [foo]bar
+
+ Console.WriteLine("Example 542\nSection Inlines / Links\n");
+ TestParser.TestSpec("[foo][bar][baz]\n\n[baz]: /url1\n[foo]: /url2", "[foo]bar
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesImages
+ {
+ // ## Images
+ //
+ // Syntax for images is like the syntax for links, with one
+ // difference. Instead of [link text], we have an
+ // [image description](@). The rules for this are the
+ // same as for [link text], except that (a) an
+ // image description starts with `![` rather than `[`, and
+ // (b) an image description may contain links.
+ // An image description has inline elements
+ // as its contents. When an image is rendered to HTML,
+ // this is standardly used as the image's `alt` attribute.
+ [Test]
+ public void InlinesImages_Example543()
+ {
+ // Example 543
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // 
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 543\nSection Inlines / Images\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example544()
+ {
+ // Example 544
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo *bar*]
+ //
+ // [foo *bar*]: train.jpg "train & tracks"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 544\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo *bar*]\n\n[foo *bar*]: train.jpg \"train & tracks\"", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example545()
+ {
+ // Example 545
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ](/url2)
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 545\nSection Inlines / Images\n");
+ TestParser.TestSpec("](/url2)", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example546()
+ {
+ // Example 546
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ](/url2)
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 546\nSection Inlines / Images\n");
+ TestParser.TestSpec("](/url2)", "
", "");
+ }
+
+ // Though this spec is concerned with parsing, not rendering, it is
+ // recommended that in rendering to HTML, only the plain string content
+ // of the [image description] be used. Note that in
+ // the above example, the alt attribute's value is `foo bar`, not `foo
+ // [bar](/url)` or `foo bar`. Only the plain string
+ // content is rendered, without formatting.
+ [Test]
+ public void InlinesImages_Example547()
+ {
+ // Example 547
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo *bar*][]
+ //
+ // [foo *bar*]: train.jpg "train & tracks"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 547\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo *bar*][]\n\n[foo *bar*]: train.jpg \"train & tracks\"", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example548()
+ {
+ // Example 548
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo *bar*][foobar]
+ //
+ // [FOOBAR]: train.jpg "train & tracks"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 548\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo *bar*][foobar]\n\n[FOOBAR]: train.jpg \"train & tracks\"", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example549()
+ {
+ // Example 549
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // 
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 549\nSection Inlines / Images\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example550()
+ {
+ // Example 550
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // My 
+ //
+ // Should be rendered as:
+ // My 
+
+ Console.WriteLine("Example 550\nSection Inlines / Images\n");
+ TestParser.TestSpec("My ", "My 
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example551()
+ {
+ // Example 551
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo]()
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 551\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo]()", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example552()
+ {
+ // Example 552
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // 
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 552\nSection Inlines / Images\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ // Reference-style:
+ [Test]
+ public void InlinesImages_Example553()
+ {
+ // Example 553
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo][bar]
+ //
+ // [bar]: /url
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 553\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo][bar]\n\n[bar]: /url", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example554()
+ {
+ // Example 554
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo][bar]
+ //
+ // [BAR]: /url
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 554\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo][bar]\n\n[BAR]: /url", "
", "");
+ }
+
+ // Collapsed:
+ [Test]
+ public void InlinesImages_Example555()
+ {
+ // Example 555
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo][]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 555\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo][]\n\n[foo]: /url \"title\"", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example556()
+ {
+ // Example 556
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![*foo* bar][]
+ //
+ // [*foo* bar]: /url "title"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 556\nSection Inlines / Images\n");
+ TestParser.TestSpec("![*foo* bar][]\n\n[*foo* bar]: /url \"title\"", "
", "");
+ }
+
+ // The labels are case-insensitive:
+ [Test]
+ public void InlinesImages_Example557()
+ {
+ // Example 557
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![Foo][]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 557\nSection Inlines / Images\n");
+ TestParser.TestSpec("![Foo][]\n\n[foo]: /url \"title\"", "
", "");
+ }
+
+ // As with reference links, [whitespace] is not allowed
+ // between the two sets of brackets:
+ [Test]
+ public void InlinesImages_Example558()
+ {
+ // Example 558
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo]
+ // []
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ //
+ // []
+
+ Console.WriteLine("Example 558\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo] \n[]\n\n[foo]: /url \"title\"", "
\n[]
", "");
+ }
+
+ // Shortcut:
+ [Test]
+ public void InlinesImages_Example559()
+ {
+ // Example 559
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![foo]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 559\nSection Inlines / Images\n");
+ TestParser.TestSpec("![foo]\n\n[foo]: /url \"title\"", "
", "");
+ }
+
+ [Test]
+ public void InlinesImages_Example560()
+ {
+ // Example 560
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![*foo* bar]
+ //
+ // [*foo* bar]: /url "title"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 560\nSection Inlines / Images\n");
+ TestParser.TestSpec("![*foo* bar]\n\n[*foo* bar]: /url \"title\"", "
", "");
+ }
+
+ // Note that link labels cannot contain unescaped brackets:
+ [Test]
+ public void InlinesImages_Example561()
+ {
+ // Example 561
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![[foo]]
+ //
+ // [[foo]]: /url "title"
+ //
+ // Should be rendered as:
+ // ![[foo]]
+ // [[foo]]: /url "title"
+
+ Console.WriteLine("Example 561\nSection Inlines / Images\n");
+ TestParser.TestSpec("![[foo]]\n\n[[foo]]: /url \"title\"", "![[foo]]
\n[[foo]]: /url "title"
", "");
+ }
+
+ // The link labels are case-insensitive:
+ [Test]
+ public void InlinesImages_Example562()
+ {
+ // Example 562
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // ![Foo]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // 
+
+ Console.WriteLine("Example 562\nSection Inlines / Images\n");
+ TestParser.TestSpec("![Foo]\n\n[foo]: /url \"title\"", "
", "");
+ }
+
+ // If you just want a literal `!` followed by bracketed text, you can
+ // backslash-escape the opening `[`:
+ [Test]
+ public void InlinesImages_Example563()
+ {
+ // Example 563
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // !\[foo]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // ![foo]
+
+ Console.WriteLine("Example 563\nSection Inlines / Images\n");
+ TestParser.TestSpec("!\\[foo]\n\n[foo]: /url \"title\"", "![foo]
", "");
+ }
+
+ // If you want a link after a literal `!`, backslash-escape the
+ // `!`:
+ [Test]
+ public void InlinesImages_Example564()
+ {
+ // Example 564
+ // Section: Inlines / Images
+ //
+ // The following Markdown:
+ // \![foo]
+ //
+ // [foo]: /url "title"
+ //
+ // Should be rendered as:
+ // !foo
+
+ Console.WriteLine("Example 564\nSection Inlines / Images\n");
+ TestParser.TestSpec("\\![foo]\n\n[foo]: /url \"title\"", "!foo
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesAutolinks
+ {
+ // ## Autolinks
+ //
+ // [Autolink](@)s are absolute URIs and email addresses inside
+ // `<` and `>`. They are parsed as links, with the URL or email address
+ // as the link label.
+ //
+ // A [URI autolink](@) consists of `<`, followed by an
+ // [absolute URI] not containing `<`, followed by `>`. It is parsed as
+ // a link to the URI, with the URI as the link's label.
+ //
+ // An [absolute URI](@),
+ // for these purposes, consists of a [scheme] followed by a colon (`:`)
+ // followed by zero or more characters other than ASCII
+ // [whitespace] and control characters, `<`, and `>`. If
+ // the URI includes these characters, they must be percent-encoded
+ // (e.g. `%20` for a space).
+ //
+ // For purposes of this spec, a [scheme](@) is any sequence
+ // of 2--32 characters beginning with an ASCII letter and followed
+ // by any combination of ASCII letters, digits, or the symbols plus
+ // ("+"), period ("."), or hyphen ("-").
+ //
+ // Here are some valid autolinks:
+ [Test]
+ public void InlinesAutolinks_Example565()
+ {
+ // Example 565
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // http://foo.bar.baz
+
+ Console.WriteLine("Example 565\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "http://foo.bar.baz
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example566()
+ {
+ // Example 566
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // http://foo.bar.baz/test?q=hello&id=22&boolean
+
+ Console.WriteLine("Example 566\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "http://foo.bar.baz/test?q=hello&id=22&boolean
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example567()
+ {
+ // Example 567
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // irc://foo.bar:2233/baz
+
+ Console.WriteLine("Example 567\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "irc://foo.bar:2233/baz
", "");
+ }
+
+ // Uppercase is also fine:
+ [Test]
+ public void InlinesAutolinks_Example568()
+ {
+ // Example 568
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // MAILTO:FOO@BAR.BAZ
+
+ Console.WriteLine("Example 568\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "MAILTO:FOO@BAR.BAZ
", "");
+ }
+
+ // Note that many strings that count as [absolute URIs] for
+ // purposes of this spec are not valid URIs, because their
+ // schemes are not registered or because of other problems
+ // with their syntax:
+ [Test]
+ public void InlinesAutolinks_Example569()
+ {
+ // Example 569
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // a+b+c:d
+
+ Console.WriteLine("Example 569\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "a+b+c:d
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example570()
+ {
+ // Example 570
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // made-up-scheme://foo,bar
+
+ Console.WriteLine("Example 570\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "made-up-scheme://foo,bar
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example571()
+ {
+ // Example 571
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // http://../
+
+ Console.WriteLine("Example 571\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "http://../
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example572()
+ {
+ // Example 572
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // localhost:5001/foo
+
+ Console.WriteLine("Example 572\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "localhost:5001/foo
", "");
+ }
+
+ // Spaces are not allowed in autolinks:
+ [Test]
+ public void InlinesAutolinks_Example573()
+ {
+ // Example 573
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // <http://foo.bar/baz bim>
+
+ Console.WriteLine("Example 573\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "<http://foo.bar/baz bim>
", "");
+ }
+
+ // Backslash-escapes do not work inside autolinks:
+ [Test]
+ public void InlinesAutolinks_Example574()
+ {
+ // Example 574
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // http://example.com/\[\
+
+ Console.WriteLine("Example 574\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "http://example.com/\\[\\
", "");
+ }
+
+ // An [email autolink](@)
+ // consists of `<`, followed by an [email address],
+ // followed by `>`. The link's label is the email address,
+ // and the URL is `mailto:` followed by the email address.
+ //
+ // An [email address](@),
+ // for these purposes, is anything that matches
+ // the [non-normative regex from the HTML5
+ // spec](https://html.spec.whatwg.org/multipage/forms.html#e-mail-state-(type=email)):
+ //
+ // /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?
+ // (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
+ //
+ // Examples of email autolinks:
+ [Test]
+ public void InlinesAutolinks_Example575()
+ {
+ // Example 575
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // foo@bar.example.com
+
+ Console.WriteLine("Example 575\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "foo@bar.example.com
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example576()
+ {
+ // Example 576
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // foo+special@Bar.baz-bar0.com
+
+ Console.WriteLine("Example 576\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "foo+special@Bar.baz-bar0.com
", "");
+ }
+
+ // Backslash-escapes do not work inside email autolinks:
+ [Test]
+ public void InlinesAutolinks_Example577()
+ {
+ // Example 577
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // <foo+@bar.example.com>
+
+ Console.WriteLine("Example 577\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "<foo+@bar.example.com>
", "");
+ }
+
+ // These are not autolinks:
+ [Test]
+ public void InlinesAutolinks_Example578()
+ {
+ // Example 578
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ // <>
+ //
+ // Should be rendered as:
+ // <>
+
+ Console.WriteLine("Example 578\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("<>", "<>
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example579()
+ {
+ // Example 579
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ // < http://foo.bar >
+ //
+ // Should be rendered as:
+ // < http://foo.bar >
+
+ Console.WriteLine("Example 579\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("< http://foo.bar >", "< http://foo.bar >
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example580()
+ {
+ // Example 580
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // <m:abc>
+
+ Console.WriteLine("Example 580\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "<m:abc>
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example581()
+ {
+ // Example 581
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // <foo.bar.baz>
+
+ Console.WriteLine("Example 581\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("", "<foo.bar.baz>
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example582()
+ {
+ // Example 582
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ // http://example.com
+ //
+ // Should be rendered as:
+ // http://example.com
+
+ Console.WriteLine("Example 582\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("http://example.com", "http://example.com
", "");
+ }
+
+ [Test]
+ public void InlinesAutolinks_Example583()
+ {
+ // Example 583
+ // Section: Inlines / Autolinks
+ //
+ // The following Markdown:
+ // foo@bar.example.com
+ //
+ // Should be rendered as:
+ // foo@bar.example.com
+
+ Console.WriteLine("Example 583\nSection Inlines / Autolinks\n");
+ TestParser.TestSpec("foo@bar.example.com", "foo@bar.example.com
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesRawHTML
+ {
+ // ## Raw HTML
+ //
+ // Text between `<` and `>` that looks like an HTML tag is parsed as a
+ // raw HTML tag and will be rendered in HTML without escaping.
+ // Tag and attribute names are not limited to current HTML tags,
+ // so custom tags (and even, say, DocBook tags) may be used.
+ //
+ // Here is the grammar for tags:
+ //
+ // A [tag name](@) consists of an ASCII letter
+ // followed by zero or more ASCII letters, digits, or
+ // hyphens (`-`).
+ //
+ // An [attribute](@) consists of [whitespace],
+ // an [attribute name], and an optional
+ // [attribute value specification].
+ //
+ // An [attribute name](@)
+ // consists of an ASCII letter, `_`, or `:`, followed by zero or more ASCII
+ // letters, digits, `_`, `.`, `:`, or `-`. (Note: This is the XML
+ // specification restricted to ASCII. HTML5 is laxer.)
+ //
+ // An [attribute value specification](@)
+ // consists of optional [whitespace],
+ // a `=` character, optional [whitespace], and an [attribute
+ // value].
+ //
+ // An [attribute value](@)
+ // consists of an [unquoted attribute value],
+ // a [single-quoted attribute value], or a [double-quoted attribute value].
+ //
+ // An [unquoted attribute value](@)
+ // is a nonempty string of characters not
+ // including spaces, `"`, `'`, `=`, `<`, `>`, or `` ` ``.
+ //
+ // A [single-quoted attribute value](@)
+ // consists of `'`, zero or more
+ // characters not including `'`, and a final `'`.
+ //
+ // A [double-quoted attribute value](@)
+ // consists of `"`, zero or more
+ // characters not including `"`, and a final `"`.
+ //
+ // An [open tag](@) consists of a `<` character, a [tag name],
+ // zero or more [attributes], optional [whitespace], an optional `/`
+ // character, and a `>` character.
+ //
+ // A [closing tag](@) consists of the string ``, a
+ // [tag name], optional [whitespace], and the character `>`.
+ //
+ // An [HTML comment](@) consists of ``,
+ // where *text* does not start with `>` or `->`, does not end with `-`,
+ // and does not contain `--`. (See the
+ // [HTML5 spec](http://www.w3.org/TR/html5/syntax.html#comments).)
+ //
+ // A [processing instruction](@)
+ // consists of the string ``, a string
+ // of characters not including the string `?>`, and the string
+ // `?>`.
+ //
+ // A [declaration](@) consists of the
+ // string ``, and the character `>`.
+ //
+ // A [CDATA section](@) consists of
+ // the string ``, and the string `]]>`.
+ //
+ // An [HTML tag](@) consists of an [open tag], a [closing tag],
+ // an [HTML comment], a [processing instruction], a [declaration],
+ // or a [CDATA section].
+ //
+ // Here are some simple open tags:
+ [Test]
+ public void InlinesRawHTML_Example584()
+ {
+ // Example 584
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 584\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ // Empty elements:
+ [Test]
+ public void InlinesRawHTML_Example585()
+ {
+ // Example 585
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 585\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ // [Whitespace] is allowed:
+ [Test]
+ public void InlinesRawHTML_Example586()
+ {
+ // Example 586
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 586\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ // With attributes:
+ [Test]
+ public void InlinesRawHTML_Example587()
+ {
+ // Example 587
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 587\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ // Custom tag names can be used:
+ [Test]
+ public void InlinesRawHTML_Example588()
+ {
+ // Example 588
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // Foo
+ //
+ // Should be rendered as:
+ // Foo
+
+ Console.WriteLine("Example 588\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("Foo ", "Foo
", "");
+ }
+
+ // Illegal tag names, not parsed as HTML:
+ [Test]
+ public void InlinesRawHTML_Example589()
+ {
+ // Example 589
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // <33> <__>
+ //
+ // Should be rendered as:
+ // <33> <__>
+
+ Console.WriteLine("Example 589\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("<33> <__>", "<33> <__>
", "");
+ }
+
+ // Illegal attribute names:
+ [Test]
+ public void InlinesRawHTML_Example590()
+ {
+ // Example 590
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // <a h*#ref="hi">
+
+ Console.WriteLine("Example 590\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "<a h*#ref="hi">
", "");
+ }
+
+ // Illegal attribute values:
+ [Test]
+ public void InlinesRawHTML_Example591()
+ {
+ // Example 591
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // ", "<a href="hi'> <a href=hi'>
", "");
+ }
+
+ // Illegal [whitespace]:
+ [Test]
+ public void InlinesRawHTML_Example592()
+ {
+ // Example 592
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // < a><
+ // foo>
+ //
+ // Should be rendered as:
+ // < a><
+ // foo><bar/ >
+
+ Console.WriteLine("Example 592\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("< a><\nfoo>", "< a><\nfoo><bar/ >
", "");
+ }
+
+ // Missing [whitespace]:
+ [Test]
+ public void InlinesRawHTML_Example593()
+ {
+ // Example 593
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // <a href='bar'title=title>
+
+ Console.WriteLine("Example 593\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "<a href='bar'title=title>
", "");
+ }
+
+ // Closing tags:
+ [Test]
+ public void InlinesRawHTML_Example594()
+ {
+ // Example 594
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 594\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "", "");
+ }
+
+ // Illegal attributes in closing tag:
+ [Test]
+ public void InlinesRawHTML_Example595()
+ {
+ // Example 595
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // </a href="foo">
+
+ Console.WriteLine("Example 595\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "</a href="foo">
", "");
+ }
+
+ // Comments:
+ [Test]
+ public void InlinesRawHTML_Example596()
+ {
+ // Example 596
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 596\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo ", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesRawHTML_Example597()
+ {
+ // Example 597
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo
+ //
+ // Should be rendered as:
+ // foo <!-- not a comment -- two hyphens -->
+
+ Console.WriteLine("Example 597\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo ", "foo <!-- not a comment -- two hyphens -->
", "");
+ }
+
+ // Not comments:
+ [Test]
+ public void InlinesRawHTML_Example598()
+ {
+ // Example 598
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo foo -->
+ //
+ // foo
+ //
+ // Should be rendered as:
+ // foo <!--> foo -->
+ // foo <!-- foo--->
+
+ Console.WriteLine("Example 598\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo foo -->\n\nfoo ", "foo <!--> foo -->
\nfoo <!-- foo--->
", "");
+ }
+
+ // Processing instructions:
+ [Test]
+ public void InlinesRawHTML_Example599()
+ {
+ // Example 599
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 599\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo ", "foo
", "");
+ }
+
+ // Declarations:
+ [Test]
+ public void InlinesRawHTML_Example600()
+ {
+ // Example 600
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 600\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo ", "foo
", "");
+ }
+
+ // CDATA sections:
+ [Test]
+ public void InlinesRawHTML_Example601()
+ {
+ // Example 601
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo &<]]>
+ //
+ // Should be rendered as:
+ // foo &<]]>
+
+ Console.WriteLine("Example 601\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo &<]]>", "foo &<]]>
", "");
+ }
+
+ // Entity and numeric character references are preserved in HTML
+ // attributes:
+ [Test]
+ public void InlinesRawHTML_Example602()
+ {
+ // Example 602
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 602\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo ", "foo
", "");
+ }
+
+ // Backslash escapes do not work in HTML attributes:
+ [Test]
+ public void InlinesRawHTML_Example603()
+ {
+ // Example 603
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ // foo
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 603\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("foo ", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesRawHTML_Example604()
+ {
+ // Example 604
+ // Section: Inlines / Raw HTML
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ // <a href=""">
+
+ Console.WriteLine("Example 604\nSection Inlines / Raw HTML\n");
+ TestParser.TestSpec("", "<a href=""">
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesHardLineBreaks
+ {
+ // ## Hard line breaks
+ //
+ // A line break (not in a code span or HTML tag) that is preceded
+ // by two or more spaces and does not occur at the end of a block
+ // is parsed as a [hard line break](@) (rendered
+ // in HTML as a `
` tag):
+ [Test]
+ public void InlinesHardLineBreaks_Example605()
+ {
+ // Example 605
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // foo
+ // baz
+ //
+ // Should be rendered as:
+ // foo
+ // baz
+
+ Console.WriteLine("Example 605\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("foo \nbaz", "foo
\nbaz
", "");
+ }
+
+ // For a more visible alternative, a backslash before the
+ // [line ending] may be used instead of two spaces:
+ [Test]
+ public void InlinesHardLineBreaks_Example606()
+ {
+ // Example 606
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // foo\
+ // baz
+ //
+ // Should be rendered as:
+ // foo
+ // baz
+
+ Console.WriteLine("Example 606\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("foo\\\nbaz", "foo
\nbaz
", "");
+ }
+
+ // More than two spaces can be used:
+ [Test]
+ public void InlinesHardLineBreaks_Example607()
+ {
+ // Example 607
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // foo
+ // baz
+ //
+ // Should be rendered as:
+ // foo
+ // baz
+
+ Console.WriteLine("Example 607\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("foo \nbaz", "foo
\nbaz
", "");
+ }
+
+ // Leading spaces at the beginning of the next line are ignored:
+ [Test]
+ public void InlinesHardLineBreaks_Example608()
+ {
+ // Example 608
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // foo
+ // bar
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 608\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("foo \n bar", "foo
\nbar
", "");
+ }
+
+ [Test]
+ public void InlinesHardLineBreaks_Example609()
+ {
+ // Example 609
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // foo\
+ // bar
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 609\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("foo\\\n bar", "foo
\nbar
", "");
+ }
+
+ // Line breaks can occur inside emphasis, links, and other constructs
+ // that allow inline content:
+ [Test]
+ public void InlinesHardLineBreaks_Example610()
+ {
+ // Example 610
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // *foo
+ // bar*
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 610\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("*foo \nbar*", "foo
\nbar
", "");
+ }
+
+ [Test]
+ public void InlinesHardLineBreaks_Example611()
+ {
+ // Example 611
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // *foo\
+ // bar*
+ //
+ // Should be rendered as:
+ // foo
+ // bar
+
+ Console.WriteLine("Example 611\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("*foo\\\nbar*", "foo
\nbar
", "");
+ }
+
+ // Line breaks do not occur inside code spans
+ [Test]
+ public void InlinesHardLineBreaks_Example612()
+ {
+ // Example 612
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // `code
+ // span`
+ //
+ // Should be rendered as:
+ // code span
+
+ Console.WriteLine("Example 612\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("`code \nspan`", "code span
", "");
+ }
+
+ [Test]
+ public void InlinesHardLineBreaks_Example613()
+ {
+ // Example 613
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // `code\
+ // span`
+ //
+ // Should be rendered as:
+ // code\ span
+
+ Console.WriteLine("Example 613\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("`code\\\nspan`", "code\\ span
", "");
+ }
+
+ // or HTML tags:
+ [Test]
+ public void InlinesHardLineBreaks_Example614()
+ {
+ // Example 614
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 614\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ [Test]
+ public void InlinesHardLineBreaks_Example615()
+ {
+ // Example 615
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ //
+ //
+ // Should be rendered as:
+ //
+
+ Console.WriteLine("Example 615\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("", "
", "");
+ }
+
+ // Hard line breaks are for separating inline content within a block.
+ // Neither syntax for hard line breaks works at the end of a paragraph or
+ // other block element:
+ [Test]
+ public void InlinesHardLineBreaks_Example616()
+ {
+ // Example 616
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // foo\
+ //
+ // Should be rendered as:
+ // foo\
+
+ Console.WriteLine("Example 616\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("foo\\", "foo\\
", "");
+ }
+
+ [Test]
+ public void InlinesHardLineBreaks_Example617()
+ {
+ // Example 617
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // foo
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 617\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("foo ", "foo
", "");
+ }
+
+ [Test]
+ public void InlinesHardLineBreaks_Example618()
+ {
+ // Example 618
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // ### foo\
+ //
+ // Should be rendered as:
+ // foo\
+
+ Console.WriteLine("Example 618\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("### foo\\", "foo\\
", "");
+ }
+
+ [Test]
+ public void InlinesHardLineBreaks_Example619()
+ {
+ // Example 619
+ // Section: Inlines / Hard line breaks
+ //
+ // The following Markdown:
+ // ### foo
+ //
+ // Should be rendered as:
+ // foo
+
+ Console.WriteLine("Example 619\nSection Inlines / Hard line breaks\n");
+ TestParser.TestSpec("### foo ", "foo
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesSoftLineBreaks
+ {
+ // ## Soft line breaks
+ //
+ // A regular line break (not in a code span or HTML tag) that is not
+ // preceded by two or more spaces or a backslash is parsed as a
+ // [softbreak](@). (A softbreak may be rendered in HTML either as a
+ // [line ending] or as a space. The result will be the same in
+ // browsers. In the examples here, a [line ending] will be used.)
+ [Test]
+ public void InlinesSoftLineBreaks_Example620()
+ {
+ // Example 620
+ // Section: Inlines / Soft line breaks
+ //
+ // The following Markdown:
+ // foo
+ // baz
+ //
+ // Should be rendered as:
+ // foo
+ // baz
+
+ Console.WriteLine("Example 620\nSection Inlines / Soft line breaks\n");
+ TestParser.TestSpec("foo\nbaz", "foo\nbaz
", "");
+ }
+
+ // Spaces at the end of the line and beginning of the next line are
+ // removed:
+ [Test]
+ public void InlinesSoftLineBreaks_Example621()
+ {
+ // Example 621
+ // Section: Inlines / Soft line breaks
+ //
+ // The following Markdown:
+ // foo
+ // baz
+ //
+ // Should be rendered as:
+ // foo
+ // baz
+
+ Console.WriteLine("Example 621\nSection Inlines / Soft line breaks\n");
+ TestParser.TestSpec("foo \n baz", "foo\nbaz
", "");
+ }
+ }
+
+ [TestFixture]
+ public class TestInlinesTextualContent
+ {
+ // A conforming parser may render a soft line break in HTML either as a
+ // line break or as a space.
+ //
+ // A renderer may also provide an option to render soft line breaks
+ // as hard line breaks.
+ //
+ // ## Textual content
+ //
+ // Any characters not given an interpretation by the above rules will
+ // be parsed as plain textual content.
+ [Test]
+ public void InlinesTextualContent_Example622()
+ {
+ // Example 622
+ // Section: Inlines / Textual content
+ //
+ // The following Markdown:
+ // hello $.;'there
+ //
+ // Should be rendered as:
+ // hello $.;'there
+
+ Console.WriteLine("Example 622\nSection Inlines / Textual content\n");
+ TestParser.TestSpec("hello $.;'there", "hello $.;'there
", "");
+ }
+
+ [Test]
+ public void InlinesTextualContent_Example623()
+ {
+ // Example 623
+ // Section: Inlines / Textual content
+ //
+ // The following Markdown:
+ // Foo χρῆν
+ //
+ // Should be rendered as:
+ // Foo χρῆν
+
+ Console.WriteLine("Example 623\nSection Inlines / Textual content\n");
+ TestParser.TestSpec("Foo χρῆν", "Foo χρῆν
", "");
+ }
+
+ // Internal spaces are preserved verbatim:
+ [Test]
+ public void InlinesTextualContent_Example624()
+ {
+ // Example 624
+ // Section: Inlines / Textual content
+ //
+ // The following Markdown:
+ // Multiple spaces
+ //
+ // Should be rendered as:
+ // Multiple spaces
+
+ Console.WriteLine("Example 624\nSection Inlines / Textual content\n");
+ TestParser.TestSpec("Multiple spaces", "Multiple spaces
", "");
+ }
+ //
+ //
+ // # Appendix: A parsing strategy
+ //
+ // In this appendix we describe some features of the parsing strategy
+ // used in the CommonMark reference implementations.
+ //
+ // ## Overview
+ //
+ // Parsing has two phases:
+ //
+ // 1. In the first phase, lines of input are consumed and the block
+ // structure of the document---its division into paragraphs, block quotes,
+ // list items, and so on---is constructed. Text is assigned to these
+ // blocks but not parsed. Link reference definitions are parsed and a
+ // map of links is constructed.
+ //
+ // 2. In the second phase, the raw text contents of paragraphs and headings
+ // are parsed into sequences of Markdown inline elements (strings,
+ // code spans, links, emphasis, and so on), using the map of link
+ // references constructed in phase 1.
+ //
+ // At each point in processing, the document is represented as a tree of
+ // **blocks**. The root of the tree is a `document` block. The `document`
+ // may have any number of other blocks as **children**. These children
+ // may, in turn, have other blocks as children. The last child of a block
+ // is normally considered **open**, meaning that subsequent lines of input
+ // can alter its contents. (Blocks that are not open are **closed**.)
+ // Here, for example, is a possible document tree, with the open blocks
+ // marked by arrows:
+ //
+ // ``` tree
+ // -> document
+ // -> block_quote
+ // paragraph
+ // "Lorem ipsum dolor\nsit amet."
+ // -> list (type=bullet tight=true bullet_char=-)
+ // list_item
+ // paragraph
+ // "Qui *quodsi iracundia*"
+ // -> list_item
+ // -> paragraph
+ // "aliquando id"
+ // ```
+ //
+ // ## Phase 1: block structure
+ //
+ // Each line that is processed has an effect on this tree. The line is
+ // analyzed and, depending on its contents, the document may be altered
+ // in one or more of the following ways:
+ //
+ // 1. One or more open blocks may be closed.
+ // 2. One or more new blocks may be created as children of the
+ // last open block.
+ // 3. Text may be added to the last (deepest) open block remaining
+ // on the tree.
+ //
+ // Once a line has been incorporated into the tree in this way,
+ // it can be discarded, so input can be read in a stream.
+ //
+ // For each line, we follow this procedure:
+ //
+ // 1. First we iterate through the open blocks, starting with the
+ // root document, and descending through last children down to the last
+ // open block. Each block imposes a condition that the line must satisfy
+ // if the block is to remain open. For example, a block quote requires a
+ // `>` character. A paragraph requires a non-blank line.
+ // In this phase we may match all or just some of the open
+ // blocks. But we cannot close unmatched blocks yet, because we may have a
+ // [lazy continuation line].
+ //
+ // 2. Next, after consuming the continuation markers for existing
+ // blocks, we look for new block starts (e.g. `>` for a block quote).
+ // If we encounter a new block start, we close any blocks unmatched
+ // in step 1 before creating the new block as a child of the last
+ // matched block.
+ //
+ // 3. Finally, we look at the remainder of the line (after block
+ // markers like `>`, list markers, and indentation have been consumed).
+ // This is text that can be incorporated into the last open
+ // block (a paragraph, code block, heading, or raw HTML).
+ //
+ // Setext headings are formed when we see a line of a paragraph
+ // that is a [setext heading underline].
+ //
+ // Reference link definitions are detected when a paragraph is closed;
+ // the accumulated text lines are parsed to see if they begin with
+ // one or more reference link definitions. Any remainder becomes a
+ // normal paragraph.
+ //
+ // We can see how this works by considering how the tree above is
+ // generated by four lines of Markdown:
+ //
+ // ``` markdown
+ // > Lorem ipsum dolor
+ // sit amet.
+ // > - Qui *quodsi iracundia*
+ // > - aliquando id
+ // ```
+ //
+ // At the outset, our document model is just
+ //
+ // ``` tree
+ // -> document
+ // ```
+ //
+ // The first line of our text,
+ //
+ // ``` markdown
+ // > Lorem ipsum dolor
+ // ```
+ //
+ // causes a `block_quote` block to be created as a child of our
+ // open `document` block, and a `paragraph` block as a child of
+ // the `block_quote`. Then the text is added to the last open
+ // block, the `paragraph`:
+ //
+ // ``` tree
+ // -> document
+ // -> block_quote
+ // -> paragraph
+ // "Lorem ipsum dolor"
+ // ```
+ //
+ // The next line,
+ //
+ // ``` markdown
+ // sit amet.
+ // ```
+ //
+ // is a "lazy continuation" of the open `paragraph`, so it gets added
+ // to the paragraph's text:
+ //
+ // ``` tree
+ // -> document
+ // -> block_quote
+ // -> paragraph
+ // "Lorem ipsum dolor\nsit amet."
+ // ```
+ //
+ // The third line,
+ //
+ // ``` markdown
+ // > - Qui *quodsi iracundia*
+ // ```
+ //
+ // causes the `paragraph` block to be closed, and a new `list` block
+ // opened as a child of the `block_quote`. A `list_item` is also
+ // added as a child of the `list`, and a `paragraph` as a child of
+ // the `list_item`. The text is then added to the new `paragraph`:
+ //
+ // ``` tree
+ // -> document
+ // -> block_quote
+ // paragraph
+ // "Lorem ipsum dolor\nsit amet."
+ // -> list (type=bullet tight=true bullet_char=-)
+ // -> list_item
+ // -> paragraph
+ // "Qui *quodsi iracundia*"
+ // ```
+ //
+ // The fourth line,
+ //
+ // ``` markdown
+ // > - aliquando id
+ // ```
+ //
+ // causes the `list_item` (and its child the `paragraph`) to be closed,
+ // and a new `list_item` opened up as child of the `list`. A `paragraph`
+ // is added as a child of the new `list_item`, to contain the text.
+ // We thus obtain the final tree:
+ //
+ // ``` tree
+ // -> document
+ // -> block_quote
+ // paragraph
+ // "Lorem ipsum dolor\nsit amet."
+ // -> list (type=bullet tight=true bullet_char=-)
+ // list_item
+ // paragraph
+ // "Qui *quodsi iracundia*"
+ // -> list_item
+ // -> paragraph
+ // "aliquando id"
+ // ```
+ //
+ // ## Phase 2: inline structure
+ //
+ // Once all of the input has been parsed, all open blocks are closed.
+ //
+ // We then "walk the tree," visiting every node, and parse raw
+ // string contents of paragraphs and headings as inlines. At this
+ // point we have seen all the link reference definitions, so we can
+ // resolve reference links as we go.
+ //
+ // ``` tree
+ // document
+ // block_quote
+ // paragraph
+ // str "Lorem ipsum dolor"
+ // softbreak
+ // str "sit amet."
+ // list (type=bullet tight=true bullet_char=-)
+ // list_item
+ // paragraph
+ // str "Qui "
+ // emph
+ // str "quodsi iracundia"
+ // list_item
+ // paragraph
+ // str "aliquando id"
+ // ```
+ //
+ // Notice how the [line ending] in the first paragraph has
+ // been parsed as a `softbreak`, and the asterisks in the first list item
+ // have become an `emph`.
+ //
+ // ### An algorithm for parsing nested emphasis and links
+ //
+ // By far the trickiest part of inline parsing is handling emphasis,
+ // strong emphasis, links, and images. This is done using the following
+ // algorithm.
+ //
+ // When we're parsing inlines and we hit either
+ //
+ // - a run of `*` or `_` characters, or
+ // - a `[` or `.
+ //
+ // The [delimiter stack] is a doubly linked list. Each
+ // element contains a pointer to a text node, plus information about
+ //
+ // - the type of delimiter (`[`, `![`, `*`, `_`)
+ // - the number of delimiters,
+ // - whether the delimiter is "active" (all are active to start), and
+ // - whether the delimiter is a potential opener, a potential closer,
+ // or both (which depends on what sort of characters precede
+ // and follow the delimiters).
+ //
+ // When we hit a `]` character, we call the *look for link or image*
+ // procedure (see below).
+ //
+ // When we hit the end of the input, we call the *process emphasis*
+ // procedure (see below), with `stack_bottom` = NULL.
+ //
+ // #### *look for link or image*
+ //
+ // Starting at the top of the delimiter stack, we look backwards
+ // through the stack for an opening `[` or `![` delimiter.
+ //
+ // - If we don't find one, we return a literal text node `]`.
+ //
+ // - If we do find one, but it's not *active*, we remove the inactive
+ // delimiter from the stack, and return a literal text node `]`.
+ //
+ // - If we find one and it's active, then we parse ahead to see if
+ // we have an inline link/image, reference link/image, compact reference
+ // link/image, or shortcut reference link/image.
+ //
+ // + If we don't, then we remove the opening delimiter from the
+ // delimiter stack and return a literal text node `]`.
+ //
+ // + If we do, then
+ //
+ // * We return a link or image node whose children are the inlines
+ // after the text node pointed to by the opening delimiter.
+ //
+ // * We run *process emphasis* on these inlines, with the `[` opener
+ // as `stack_bottom`.
+ //
+ // * We remove the opening delimiter.
+ //
+ // * If we have a link (and not an image), we also set all
+ // `[` delimiters before the opening delimiter to *inactive*. (This
+ // will prevent us from getting links within links.)
+ //
+ // #### *process emphasis*
+ //
+ // Parameter `stack_bottom` sets a lower bound to how far we
+ // descend in the [delimiter stack]. If it is NULL, we can
+ // go all the way to the bottom. Otherwise, we stop before
+ // visiting `stack_bottom`.
+ //
+ // Let `current_position` point to the element on the [delimiter stack]
+ // just above `stack_bottom` (or the first element if `stack_bottom`
+ // is NULL).
+ //
+ // We keep track of the `openers_bottom` for each delimiter
+ // type (`*`, `_`). Initialize this to `stack_bottom`.
+ //
+ // Then we repeat the following until we run out of potential
+ // closers:
+ //
+ // - Move `current_position` forward in the delimiter stack (if needed)
+ // until we find the first potential closer with delimiter `*` or `_`.
+ // (This will be the potential closer closest
+ // to the beginning of the input -- the first one in parse order.)
+ //
+ // - Now, look back in the stack (staying above `stack_bottom` and
+ // the `openers_bottom` for this delimiter type) for the
+ // first matching potential opener ("matching" means same delimiter).
+ //
+ // - If one is found:
+ //
+ // + Figure out whether we have emphasis or strong emphasis:
+ // if both closer and opener spans have length >= 2, we have
+ // strong, otherwise regular.
+ //
+ // + Insert an emph or strong emph node accordingly, after
+ // the text node corresponding to the opener.
+ //
+ // + Remove any delimiters between the opener and closer from
+ // the delimiter stack.
+ //
+ // + Remove 1 (for regular emph) or 2 (for strong emph) delimiters
+ // from the opening and closing text nodes. If they become empty
+ // as a result, remove them and remove the corresponding element
+ // of the delimiter stack. If the closing node is removed, reset
+ // `current_position` to the next element in the stack.
+ //
+ // - If none in found:
+ //
+ // + Set `openers_bottom` to the element before `current_position`.
+ // (We know that there are no openers for this kind of closer up to and
+ // including this point, so this puts a lower bound on future searches.)
+ //
+ // + If the closer at `current_position` is not a potential opener,
+ // remove it from the delimiter stack (since we know it can't
+ // be a closer either).
+ //
+ // + Advance `current_position` to the next element in the stack.
+ //
+ // After we're done, we remove all delimiters above `stack_bottom` from the
+ // delimiter stack.
+ }
+}
diff --git a/src/Markdig.Tests/Specs/CommonMark.md b/src/Markdig.Tests/Specs/CommonMark.md
new file mode 100644
index 00000000..9fd58413
--- /dev/null
+++ b/src/Markdig.Tests/Specs/CommonMark.md
@@ -0,0 +1,9414 @@
+---
+title: CommonMark Spec
+author: John MacFarlane
+version: 0.28
+date: '2017-08-01'
+license: '[CC-BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/)'
+...
+
+# Introduction
+
+## What is Markdown?
+
+Markdown is a plain text format for writing structured documents,
+based on conventions for indicating formatting in email
+and usenet posts. It was developed by John Gruber (with
+help from Aaron Swartz) and released in 2004 in the form of a
+[syntax description](http://daringfireball.net/projects/markdown/syntax)
+and a Perl script (`Markdown.pl`) for converting Markdown to
+HTML. In the next decade, dozens of implementations were
+developed in many languages. Some extended the original
+Markdown syntax with conventions for footnotes, tables, and
+other document elements. Some allowed Markdown documents to be
+rendered in formats other than HTML. Websites like Reddit,
+StackOverflow, and GitHub had millions of people using Markdown.
+And Markdown started to be used beyond the web, to author books,
+articles, slide shows, letters, and lecture notes.
+
+What distinguishes Markdown from many other lightweight markup
+syntaxes, which are often easier to write, is its readability.
+As Gruber writes:
+
+> The overriding design goal for Markdown's formatting syntax is
+> to make it as readable as possible. The idea is that a
+> Markdown-formatted document should be publishable as-is, as
+> plain text, without looking like it's been marked up with tags
+> or formatting instructions.
+> ()
+
+The point can be illustrated by comparing a sample of
+[AsciiDoc](http://www.methods.co.nz/asciidoc/) with
+an equivalent sample of Markdown. Here is a sample of
+AsciiDoc from the AsciiDoc manual:
+
+```
+1. List item one.
++
+List item one continued with a second paragraph followed by an
+Indented block.
++
+.................
+$ ls *.sh
+$ mv *.sh ~/tmp
+.................
++
+List item continued with a third paragraph.
+
+2. List item two continued with an open block.
++
+--
+This paragraph is part of the preceding list item.
+
+a. This list is nested and does not require explicit item
+continuation.
++
+This paragraph is part of the preceding list item.
+
+b. List item b.
+
+This paragraph belongs to item two of the outer list.
+--
+```
+
+And here is the equivalent in Markdown:
+```
+1. List item one.
+
+ List item one continued with a second paragraph followed by an
+ Indented block.
+
+ $ ls *.sh
+ $ mv *.sh ~/tmp
+
+ List item continued with a third paragraph.
+
+2. List item two continued with an open block.
+
+ This paragraph is part of the preceding list item.
+
+ 1. This list is nested and does not require explicit item continuation.
+
+ This paragraph is part of the preceding list item.
+
+ 2. List item b.
+
+ This paragraph belongs to item two of the outer list.
+```
+
+The AsciiDoc version is, arguably, easier to write. You don't need
+to worry about indentation. But the Markdown version is much easier
+to read. The nesting of list items is apparent to the eye in the
+source, not just in the processed document.
+
+## Why is a spec needed?
+
+John Gruber's [canonical description of Markdown's
+syntax](http://daringfireball.net/projects/markdown/syntax)
+does not specify the syntax unambiguously. Here are some examples of
+questions it does not answer:
+
+1. How much indentation is needed for a sublist? The spec says that
+ continuation paragraphs need to be indented four spaces, but is
+ not fully explicit about sublists. It is natural to think that
+ they, too, must be indented four spaces, but `Markdown.pl` does
+ not require that. This is hardly a "corner case," and divergences
+ between implementations on this issue often lead to surprises for
+ users in real documents. (See [this comment by John
+ Gruber](http://article.gmane.org/gmane.text.markdown.general/1997).)
+
+2. Is a blank line needed before a block quote or heading?
+ Most implementations do not require the blank line. However,
+ this can lead to unexpected results in hard-wrapped text, and
+ also to ambiguities in parsing (note that some implementations
+ put the heading inside the blockquote, while others do not).
+ (John Gruber has also spoken [in favor of requiring the blank
+ lines](http://article.gmane.org/gmane.text.markdown.general/2146).)
+
+3. Is a blank line needed before an indented code block?
+ (`Markdown.pl` requires it, but this is not mentioned in the
+ documentation, and some implementations do not require it.)
+
+ ``` markdown
+ paragraph
+ code?
+ ```
+
+4. What is the exact rule for determining when list items get
+ wrapped in `` tags? Can a list be partially "loose" and partially
+ "tight"? What should we do with a list like this?
+
+ ``` markdown
+ 1. one
+
+ 2. two
+ 3. three
+ ```
+
+ Or this?
+
+ ``` markdown
+ 1. one
+ - a
+
+ - b
+ 2. two
+ ```
+
+ (There are some relevant comments by John Gruber
+ [here](http://article.gmane.org/gmane.text.markdown.general/2554).)
+
+5. Can list markers be indented? Can ordered list markers be right-aligned?
+
+ ``` markdown
+ 8. item 1
+ 9. item 2
+ 10. item 2a
+ ```
+
+6. Is this one list with a thematic break in its second item,
+ or two lists separated by a thematic break?
+
+ ``` markdown
+ * a
+ * * * * *
+ * b
+ ```
+
+7. When list markers change from numbers to bullets, do we have
+ two lists or one? (The Markdown syntax description suggests two,
+ but the perl scripts and many other implementations produce one.)
+
+ ``` markdown
+ 1. fee
+ 2. fie
+ - foe
+ - fum
+ ```
+
+8. What are the precedence rules for the markers of inline structure?
+ For example, is the following a valid link, or does the code span
+ take precedence ?
+
+ ``` markdown
+ [a backtick (`)](/url) and [another backtick (`)](/url).
+ ```
+
+9. What are the precedence rules for markers of emphasis and strong
+ emphasis? For example, how should the following be parsed?
+
+ ``` markdown
+ *foo *bar* baz*
+ ```
+
+10. What are the precedence rules between block-level and inline-level
+ structure? For example, how should the following be parsed?
+
+ ``` markdown
+ - `a long code span can contain a hyphen like this
+ - and it can screw things up`
+ ```
+
+11. Can list items include section headings? (`Markdown.pl` does not
+ allow this, but does allow blockquotes to include headings.)
+
+ ``` markdown
+ - # Heading
+ ```
+
+12. Can list items be empty?
+
+ ``` markdown
+ * a
+ *
+ * b
+ ```
+
+13. Can link references be defined inside block quotes or list items?
+
+ ``` markdown
+ > Blockquote [foo].
+ >
+ > [foo]: /url
+ ```
+
+14. If there are multiple definitions for the same reference, which takes
+ precedence?
+
+ ``` markdown
+ [foo]: /url1
+ [foo]: /url2
+
+ [foo][]
+ ```
+
+In the absence of a spec, early implementers consulted `Markdown.pl`
+to resolve these ambiguities. But `Markdown.pl` was quite buggy, and
+gave manifestly bad results in many cases, so it was not a
+satisfactory replacement for a spec.
+
+Because there is no unambiguous spec, implementations have diverged
+considerably. As a result, users are often surprised to find that
+a document that renders one way on one system (say, a github wiki)
+renders differently on another (say, converting to docbook using
+pandoc). To make matters worse, because nothing in Markdown counts
+as a "syntax error," the divergence often isn't discovered right away.
+
+## About this document
+
+This document attempts to specify Markdown syntax unambiguously.
+It contains many examples with side-by-side Markdown and
+HTML. These are intended to double as conformance tests. An
+accompanying script `spec_tests.py` can be used to run the tests
+against any Markdown program:
+
+ python test/spec_tests.py --spec spec.txt --program PROGRAM
+
+Since this document describes how Markdown is to be parsed into
+an abstract syntax tree, it would have made sense to use an abstract
+representation of the syntax tree instead of HTML. But HTML is capable
+of representing the structural distinctions we need to make, and the
+choice of HTML for the tests makes it possible to run the tests against
+an implementation without writing an abstract syntax tree renderer.
+
+This document is generated from a text file, `spec.txt`, written
+in Markdown with a small extension for the side-by-side tests.
+The script `tools/makespec.py` can be used to convert `spec.txt` into
+HTML or CommonMark (which can then be converted into other formats).
+
+In the examples, the `→` character is used to represent tabs.
+
+# Preliminaries
+
+## Characters and lines
+
+Any sequence of [characters] is a valid CommonMark
+document.
+
+A [character](@) is a Unicode code point. Although some
+code points (for example, combining accents) do not correspond to
+characters in an intuitive sense, all code points count as characters
+for purposes of this spec.
+
+This spec does not specify an encoding; it thinks of lines as composed
+of [characters] rather than bytes. A conforming parser may be limited
+to a certain encoding.
+
+A [line](@) is a sequence of zero or more [characters]
+other than newline (`U+000A`) or carriage return (`U+000D`),
+followed by a [line ending] or by the end of file.
+
+A [line ending](@) is a newline (`U+000A`), a carriage return
+(`U+000D`) not followed by a newline, or a carriage return and a
+following newline.
+
+A line containing no characters, or a line containing only spaces
+(`U+0020`) or tabs (`U+0009`), is called a [blank line](@).
+
+The following definitions of character classes will be used in this spec:
+
+A [whitespace character](@) is a space
+(`U+0020`), tab (`U+0009`), newline (`U+000A`), line tabulation (`U+000B`),
+form feed (`U+000C`), or carriage return (`U+000D`).
+
+[Whitespace](@) is a sequence of one or more [whitespace
+characters].
+
+A [Unicode whitespace character](@) is
+any code point in the Unicode `Zs` general category, or a tab (`U+0009`),
+carriage return (`U+000D`), newline (`U+000A`), or form feed
+(`U+000C`).
+
+[Unicode whitespace](@) is a sequence of one
+or more [Unicode whitespace characters].
+
+A [space](@) is `U+0020`.
+
+A [non-whitespace character](@) is any character
+that is not a [whitespace character].
+
+An [ASCII punctuation character](@)
+is `!`, `"`, `#`, `$`, `%`, `&`, `'`, `(`, `)`,
+`*`, `+`, `,`, `-`, `.`, `/`, `:`, `;`, `<`, `=`, `>`, `?`, `@`,
+`[`, `\`, `]`, `^`, `_`, `` ` ``, `{`, `|`, `}`, or `~`.
+
+A [punctuation character](@) is an [ASCII
+punctuation character] or anything in
+the general Unicode categories `Pc`, `Pd`, `Pe`, `Pf`, `Pi`, `Po`, or `Ps`.
+
+## Tabs
+
+Tabs in lines are not expanded to [spaces]. However,
+in contexts where whitespace helps to define block structure,
+tabs behave as if they were replaced by spaces with a tab stop
+of 4 characters.
+
+Thus, for example, a tab can be used instead of four spaces
+in an indented code block. (Note, however, that internal
+tabs are passed through as literal tabs, not expanded to
+spaces.)
+
+```````````````````````````````` example
+→foo→baz→→bim
+.
+
foo→baz→→bim
+
+````````````````````````````````
+
+```````````````````````````````` example
+ →foo→baz→→bim
+.
+foo→baz→→bim
+
+````````````````````````````````
+
+```````````````````````````````` example
+ a→a
+ ὐ→a
+.
+a→a
+ὐ→a
+
+````````````````````````````````
+
+In the following example, a continuation paragraph of a list
+item is indented with a tab; this has exactly the same effect
+as indentation with four spaces would:
+
+```````````````````````````````` example
+ - foo
+
+→bar
+.
+
+````````````````````````````````
+
+```````````````````````````````` example
+- foo
+
+→→bar
+.
+
+````````````````````````````````
+
+Normally the `>` that begins a block quote may be followed
+optionally by a space, which is not considered part of the
+content. In the following case `>` is followed by a tab,
+which is treated as if it were expanded into three spaces.
+Since one of these spaces is considered part of the
+delimiter, `foo` is considered to be indented six spaces
+inside the block quote context, so we get an indented
+code block starting with two spaces.
+
+```````````````````````````````` example
+>→→foo
+.
+
+ foo
+
+
+````````````````````````````````
+
+```````````````````````````````` example
+-→→foo
+.
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+ foo
+→bar
+.
+foo
+bar
+
+````````````````````````````````
+
+```````````````````````````````` example
+ - foo
+ - bar
+→ - baz
+.
+
+````````````````````````````````
+
+```````````````````````````````` example
+#→Foo
+.
+Foo
+````````````````````````````````
+
+```````````````````````````````` example
+*→*→*→
+.
+
+````````````````````````````````
+
+
+## Insecure characters
+
+For security reasons, the Unicode character `U+0000` must be replaced
+with the REPLACEMENT CHARACTER (`U+FFFD`).
+
+# Blocks and inlines
+
+We can think of a document as a sequence of
+[blocks](@)---structural elements like paragraphs, block
+quotations, lists, headings, rules, and code blocks. Some blocks (like
+block quotes and list items) contain other blocks; others (like
+headings and paragraphs) contain [inline](@) content---text,
+links, emphasized text, images, code spans, and so on.
+
+## Precedence
+
+Indicators of block structure always take precedence over indicators
+of inline structure. So, for example, the following is a list with
+two items, not a list with one item containing a code span:
+
+```````````````````````````````` example
+- `one
+- two`
+.
+
+````````````````````````````````
+
+
+This means that parsing can proceed in two steps: first, the block
+structure of the document can be discerned; second, text lines inside
+paragraphs, headings, and other block constructs can be parsed for inline
+structure. The second step requires information about link reference
+definitions that will be available only at the end of the first
+step. Note that the first step requires processing lines in sequence,
+but the second can be parallelized, since the inline parsing of
+one block element does not affect the inline parsing of any other.
+
+## Container blocks and leaf blocks
+
+We can divide blocks into two types:
+[container block](@)s,
+which can contain other blocks, and [leaf block](@)s,
+which cannot.
+
+# Leaf blocks
+
+This section describes the different kinds of leaf block that make up a
+Markdown document.
+
+## Thematic breaks
+
+A line consisting of 0-3 spaces of indentation, followed by a sequence
+of three or more matching `-`, `_`, or `*` characters, each followed
+optionally by any number of spaces, forms a
+[thematic break](@).
+
+```````````````````````````````` example
+***
+---
+___
+.
+
+
+
+````````````````````````````````
+
+
+Wrong characters:
+
+```````````````````````````````` example
++++
+.
++++
+````````````````````````````````
+
+
+```````````````````````````````` example
+===
+.
+===
+````````````````````````````````
+
+
+Not enough characters:
+
+```````````````````````````````` example
+--
+**
+__
+.
+--
+**
+__
+````````````````````````````````
+
+
+One to three spaces indent are allowed:
+
+```````````````````````````````` example
+ ***
+ ***
+ ***
+.
+
+
+
+````````````````````````````````
+
+
+Four spaces is too many:
+
+```````````````````````````````` example
+ ***
+.
+***
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+Foo
+ ***
+.
+Foo
+***
+````````````````````````````````
+
+
+More than three characters may be used:
+
+```````````````````````````````` example
+_____________________________________
+.
+
+````````````````````````````````
+
+
+Spaces are allowed between the characters:
+
+```````````````````````````````` example
+ - - -
+.
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ** * ** * ** * **
+.
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+- - - -
+.
+
+````````````````````````````````
+
+
+Spaces are allowed at the end:
+
+```````````````````````````````` example
+- - - -
+.
+
+````````````````````````````````
+
+
+However, no other characters may occur in the line:
+
+```````````````````````````````` example
+_ _ _ _ a
+
+a------
+
+---a---
+.
+_ _ _ _ a
+a------
+---a---
+````````````````````````````````
+
+
+It is required that all of the [non-whitespace characters] be the same.
+So, this is not a thematic break:
+
+```````````````````````````````` example
+ *-*
+.
+-
+````````````````````````````````
+
+
+Thematic breaks do not need blank lines before or after:
+
+```````````````````````````````` example
+- foo
+***
+- bar
+.
+
+
+
+````````````````````````````````
+
+
+Thematic breaks can interrupt a paragraph:
+
+```````````````````````````````` example
+Foo
+***
+bar
+.
+Foo
+
+bar
+````````````````````````````````
+
+
+If a line of dashes that meets the above conditions for being a
+thematic break could also be interpreted as the underline of a [setext
+heading], the interpretation as a
+[setext heading] takes precedence. Thus, for example,
+this is a setext heading, not a paragraph followed by a thematic break:
+
+```````````````````````````````` example
+Foo
+---
+bar
+.
+Foo
+bar
+````````````````````````````````
+
+
+When both a thematic break and a list item are possible
+interpretations of a line, the thematic break takes precedence:
+
+```````````````````````````````` example
+* Foo
+* * *
+* Bar
+.
+
+
+
+````````````````````````````````
+
+
+If you want a thematic break in a list item, use a different bullet:
+
+```````````````````````````````` example
+- Foo
+- * * *
+.
+
+````````````````````````````````
+
+
+## ATX headings
+
+An [ATX heading](@)
+consists of a string of characters, parsed as inline content, between an
+opening sequence of 1--6 unescaped `#` characters and an optional
+closing sequence of any number of unescaped `#` characters.
+The opening sequence of `#` characters must be followed by a
+[space] or by the end of line. The optional closing sequence of `#`s must be
+preceded by a [space] and may be followed by spaces only. The opening
+`#` character may be indented 0-3 spaces. The raw contents of the
+heading are stripped of leading and trailing spaces before being parsed
+as inline content. The heading level is equal to the number of `#`
+characters in the opening sequence.
+
+Simple headings:
+
+```````````````````````````````` example
+# foo
+## foo
+### foo
+#### foo
+##### foo
+###### foo
+.
+foo
+foo
+foo
+foo
+foo
+foo
+````````````````````````````````
+
+
+More than six `#` characters is not a heading:
+
+```````````````````````````````` example
+####### foo
+.
+####### foo
+````````````````````````````````
+
+
+At least one space is required between the `#` characters and the
+heading's contents, unless the heading is empty. Note that many
+implementations currently do not require the space. However, the
+space was required by the
+[original ATX implementation](http://www.aaronsw.com/2002/atx/atx.py),
+and it helps prevent things like the following from being parsed as
+headings:
+
+```````````````````````````````` example
+#5 bolt
+
+#hashtag
+.
+#5 bolt
+#hashtag
+````````````````````````````````
+
+
+This is not a heading, because the first `#` is escaped:
+
+```````````````````````````````` example
+\## foo
+.
+## foo
+````````````````````````````````
+
+
+Contents are parsed as inlines:
+
+```````````````````````````````` example
+# foo *bar* \*baz\*
+.
+foo bar *baz*
+````````````````````````````````
+
+
+Leading and trailing blanks are ignored in parsing inline content:
+
+```````````````````````````````` example
+# foo
+.
+foo
+````````````````````````````````
+
+
+One to three spaces indentation are allowed:
+
+```````````````````````````````` example
+ ### foo
+ ## foo
+ # foo
+.
+foo
+foo
+foo
+````````````````````````````````
+
+
+Four spaces are too much:
+
+```````````````````````````````` example
+ # foo
+.
+# foo
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+foo
+ # bar
+.
+foo
+# bar
+````````````````````````````````
+
+
+A closing sequence of `#` characters is optional:
+
+```````````````````````````````` example
+## foo ##
+ ### bar ###
+.
+foo
+bar
+````````````````````````````````
+
+
+It need not be the same length as the opening sequence:
+
+```````````````````````````````` example
+# foo ##################################
+##### foo ##
+.
+foo
+foo
+````````````````````````````````
+
+
+Spaces are allowed after the closing sequence:
+
+```````````````````````````````` example
+### foo ###
+.
+foo
+````````````````````````````````
+
+
+A sequence of `#` characters with anything but [spaces] following it
+is not a closing sequence, but counts as part of the contents of the
+heading:
+
+```````````````````````````````` example
+### foo ### b
+.
+foo ### b
+````````````````````````````````
+
+
+The closing sequence must be preceded by a space:
+
+```````````````````````````````` example
+# foo#
+.
+foo#
+````````````````````````````````
+
+
+Backslash-escaped `#` characters do not count as part
+of the closing sequence:
+
+```````````````````````````````` example
+### foo \###
+## foo #\##
+# foo \#
+.
+foo ###
+foo ###
+foo #
+````````````````````````````````
+
+
+ATX headings need not be separated from surrounding content by blank
+lines, and they can interrupt paragraphs:
+
+```````````````````````````````` example
+****
+## foo
+****
+.
+
+foo
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+Foo bar
+# baz
+Bar foo
+.
+Foo bar
+baz
+Bar foo
+````````````````````````````````
+
+
+ATX headings can be empty:
+
+```````````````````````````````` example
+##
+#
+### ###
+.
+
+
+
+````````````````````````````````
+
+
+## Setext headings
+
+A [setext heading](@) consists of one or more
+lines of text, each containing at least one [non-whitespace
+character], with no more than 3 spaces indentation, followed by
+a [setext heading underline]. The lines of text must be such
+that, were they not followed by the setext heading underline,
+they would be interpreted as a paragraph: they cannot be
+interpretable as a [code fence], [ATX heading][ATX headings],
+[block quote][block quotes], [thematic break][thematic breaks],
+[list item][list items], or [HTML block][HTML blocks].
+
+A [setext heading underline](@) is a sequence of
+`=` characters or a sequence of `-` characters, with no more than 3
+spaces indentation and any number of trailing spaces. If a line
+containing a single `-` can be interpreted as an
+empty [list items], it should be interpreted this way
+and not as a [setext heading underline].
+
+The heading is a level 1 heading if `=` characters are used in
+the [setext heading underline], and a level 2 heading if `-`
+characters are used. The contents of the heading are the result
+of parsing the preceding lines of text as CommonMark inline
+content.
+
+In general, a setext heading need not be preceded or followed by a
+blank line. However, it cannot interrupt a paragraph, so when a
+setext heading comes after a paragraph, a blank line is needed between
+them.
+
+Simple examples:
+
+```````````````````````````````` example
+Foo *bar*
+=========
+
+Foo *bar*
+---------
+.
+Foo bar
+Foo bar
+````````````````````````````````
+
+
+The content of the header may span more than one line:
+
+```````````````````````````````` example
+Foo *bar
+baz*
+====
+.
+Foo bar
+baz
+````````````````````````````````
+
+
+The underlining can be any length:
+
+```````````````````````````````` example
+Foo
+-------------------------
+
+Foo
+=
+.
+Foo
+Foo
+````````````````````````````````
+
+
+The heading content can be indented up to three spaces, and need
+not line up with the underlining:
+
+```````````````````````````````` example
+ Foo
+---
+
+ Foo
+-----
+
+ Foo
+ ===
+.
+Foo
+Foo
+Foo
+````````````````````````````````
+
+
+Four spaces indent is too much:
+
+```````````````````````````````` example
+ Foo
+ ---
+
+ Foo
+---
+.
+Foo
+---
+
+Foo
+
+
+````````````````````````````````
+
+
+The setext heading underline can be indented up to three spaces, and
+may have trailing spaces:
+
+```````````````````````````````` example
+Foo
+ ----
+.
+Foo
+````````````````````````````````
+
+
+Four spaces is too much:
+
+```````````````````````````````` example
+Foo
+ ---
+.
+Foo
+---
+````````````````````````````````
+
+
+The setext heading underline cannot contain internal spaces:
+
+```````````````````````````````` example
+Foo
+= =
+
+Foo
+--- -
+.
+Foo
+= =
+Foo
+
+````````````````````````````````
+
+
+Trailing spaces in the content line do not cause a line break:
+
+```````````````````````````````` example
+Foo
+-----
+.
+Foo
+````````````````````````````````
+
+
+Nor does a backslash at the end:
+
+```````````````````````````````` example
+Foo\
+----
+.
+Foo\
+````````````````````````````````
+
+
+Since indicators of block structure take precedence over
+indicators of inline structure, the following are setext headings:
+
+```````````````````````````````` example
+`Foo
+----
+`
+
+
+.
+`Foo
+`
+<a title="a lot
+of dashes"/>
+````````````````````````````````
+
+
+The setext heading underline cannot be a [lazy continuation
+line] in a list item or block quote:
+
+```````````````````````````````` example
+> Foo
+---
+.
+
+Foo
+
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+> foo
+bar
+===
+.
+
+foo
+bar
+===
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+- Foo
+---
+.
+
+
+````````````````````````````````
+
+
+A blank line is needed between a paragraph and a following
+setext heading, since otherwise the paragraph becomes part
+of the heading's content:
+
+```````````````````````````````` example
+Foo
+Bar
+---
+.
+Foo
+Bar
+````````````````````````````````
+
+
+But in general a blank line is not required before or after
+setext headings:
+
+```````````````````````````````` example
+---
+Foo
+---
+Bar
+---
+Baz
+.
+
+Foo
+Bar
+Baz
+````````````````````````````````
+
+
+Setext headings cannot be empty:
+
+```````````````````````````````` example
+
+====
+.
+====
+````````````````````````````````
+
+
+Setext heading text lines must not be interpretable as block
+constructs other than paragraphs. So, the line of dashes
+in these examples gets interpreted as a thematic break:
+
+```````````````````````````````` example
+---
+---
+.
+
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+- foo
+-----
+.
+
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+ foo
+---
+.
+foo
+
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+> foo
+-----
+.
+
+foo
+
+
+````````````````````````````````
+
+
+If you want a heading with `> foo` as its literal text, you can
+use backslash escapes:
+
+```````````````````````````````` example
+\> foo
+------
+.
+> foo
+````````````````````````````````
+
+
+**Compatibility note:** Most existing Markdown implementations
+do not allow the text of setext headings to span multiple lines.
+But there is no consensus about how to interpret
+
+``` markdown
+Foo
+bar
+---
+baz
+```
+
+One can find four different interpretations:
+
+1. paragraph "Foo", heading "bar", paragraph "baz"
+2. paragraph "Foo bar", thematic break, paragraph "baz"
+3. paragraph "Foo bar --- baz"
+4. heading "Foo bar", paragraph "baz"
+
+We find interpretation 4 most natural, and interpretation 4
+increases the expressive power of CommonMark, by allowing
+multiline headings. Authors who want interpretation 1 can
+put a blank line after the first paragraph:
+
+```````````````````````````````` example
+Foo
+
+bar
+---
+baz
+.
+Foo
+bar
+baz
+````````````````````````````````
+
+
+Authors who want interpretation 2 can put blank lines around
+the thematic break,
+
+```````````````````````````````` example
+Foo
+bar
+
+---
+
+baz
+.
+Foo
+bar
+
+baz
+````````````````````````````````
+
+
+or use a thematic break that cannot count as a [setext heading
+underline], such as
+
+```````````````````````````````` example
+Foo
+bar
+* * *
+baz
+.
+Foo
+bar
+
+baz
+````````````````````````````````
+
+
+Authors who want interpretation 3 can use backslash escapes:
+
+```````````````````````````````` example
+Foo
+bar
+\---
+baz
+.
+Foo
+bar
+---
+baz
+````````````````````````````````
+
+
+## Indented code blocks
+
+An [indented code block](@) is composed of one or more
+[indented chunks] separated by blank lines.
+An [indented chunk](@) is a sequence of non-blank lines,
+each indented four or more spaces. The contents of the code block are
+the literal contents of the lines, including trailing
+[line endings], minus four spaces of indentation.
+An indented code block has no [info string].
+
+An indented code block cannot interrupt a paragraph, so there must be
+a blank line between a paragraph and a following indented code block.
+(A blank line is not needed, however, between a code block and a following
+paragraph.)
+
+```````````````````````````````` example
+ a simple
+ indented code block
+.
+a simple
+ indented code block
+
+````````````````````````````````
+
+
+If there is any ambiguity between an interpretation of indentation
+as a code block and as indicating that material belongs to a [list
+item][list items], the list item interpretation takes precedence:
+
+```````````````````````````````` example
+ - foo
+
+ bar
+.
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+1. foo
+
+ - bar
+.
+
+-
+
foo
+
+
+
+````````````````````````````````
+
+
+
+The contents of a code block are literal text, and do not get parsed
+as Markdown:
+
+```````````````````````````````` example
+
+ *hi*
+
+ - one
+.
+<a/>
+*hi*
+
+- one
+
+````````````````````````````````
+
+
+Here we have three chunks separated by blank lines:
+
+```````````````````````````````` example
+ chunk1
+
+ chunk2
+
+
+
+ chunk3
+.
+chunk1
+
+chunk2
+
+
+
+chunk3
+
+````````````````````````````````
+
+
+Any initial spaces beyond four will be included in the content, even
+in interior blank lines:
+
+```````````````````````````````` example
+ chunk1
+
+ chunk2
+.
+chunk1
+
+ chunk2
+
+````````````````````````````````
+
+
+An indented code block cannot interrupt a paragraph. (This
+allows hanging indents and the like.)
+
+```````````````````````````````` example
+Foo
+ bar
+
+.
+Foo
+bar
+````````````````````````````````
+
+
+However, any non-blank line with fewer than four leading spaces ends
+the code block immediately. So a paragraph may occur immediately
+after indented code:
+
+```````````````````````````````` example
+ foo
+bar
+.
+foo
+
+bar
+````````````````````````````````
+
+
+And indented code can occur immediately before and after other kinds of
+blocks:
+
+```````````````````````````````` example
+# Heading
+ foo
+Heading
+------
+ foo
+----
+.
+Heading
+foo
+
+Heading
+foo
+
+
+````````````````````````````````
+
+
+The first line can be indented more than four spaces:
+
+```````````````````````````````` example
+ foo
+ bar
+.
+ foo
+bar
+
+````````````````````````````````
+
+
+Blank lines preceding or following an indented code block
+are not included in it:
+
+```````````````````````````````` example
+
+
+ foo
+
+
+.
+foo
+
+````````````````````````````````
+
+
+Trailing spaces are included in the code block's content:
+
+```````````````````````````````` example
+ foo
+.
+foo
+
+````````````````````````````````
+
+
+
+## Fenced code blocks
+
+A [code fence](@) is a sequence
+of at least three consecutive backtick characters (`` ` ``) or
+tildes (`~`). (Tildes and backticks cannot be mixed.)
+A [fenced code block](@)
+begins with a code fence, indented no more than three spaces.
+
+The line with the opening code fence may optionally contain some text
+following the code fence; this is trimmed of leading and trailing
+spaces and called the [info string](@).
+The [info string] may not contain any backtick
+characters. (The reason for this restriction is that otherwise
+some inline code would be incorrectly interpreted as the
+beginning of a fenced code block.)
+
+The content of the code block consists of all subsequent lines, until
+a closing [code fence] of the same type as the code block
+began with (backticks or tildes), and with at least as many backticks
+or tildes as the opening code fence. If the leading code fence is
+indented N spaces, then up to N spaces of indentation are removed from
+each line of the content (if present). (If a content line is not
+indented, it is preserved unchanged. If it is indented less than N
+spaces, all of the indentation is removed.)
+
+The closing code fence may be indented up to three spaces, and may be
+followed only by spaces, which are ignored. If the end of the
+containing block (or document) is reached and no closing code fence
+has been found, the code block contains all of the lines after the
+opening code fence until the end of the containing block (or
+document). (An alternative spec would require backtracking in the
+event that a closing code fence is not found. But this makes parsing
+much less efficient, and there seems to be no real down side to the
+behavior described here.)
+
+A fenced code block may interrupt a paragraph, and does not require
+a blank line either before or after.
+
+The content of a code fence is treated as literal text, not parsed
+as inlines. The first word of the [info string] is typically used to
+specify the language of the code sample, and rendered in the `class`
+attribute of the `code` tag. However, this spec does not mandate any
+particular treatment of the [info string].
+
+Here is a simple example with backticks:
+
+```````````````````````````````` example
+```
+<
+ >
+```
+.
+<
+ >
+
+````````````````````````````````
+
+
+With tildes:
+
+```````````````````````````````` example
+~~~
+<
+ >
+~~~
+.
+<
+ >
+
+````````````````````````````````
+
+Fewer than three backticks is not enough:
+
+```````````````````````````````` example
+``
+foo
+``
+.
+foo
+````````````````````````````````
+
+The closing code fence must use the same character as the opening
+fence:
+
+```````````````````````````````` example
+```
+aaa
+~~~
+```
+.
+aaa
+~~~
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~
+aaa
+```
+~~~
+.
+aaa
+```
+
+````````````````````````````````
+
+
+The closing code fence must be at least as long as the opening fence:
+
+```````````````````````````````` example
+````
+aaa
+```
+``````
+.
+aaa
+```
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~~
+aaa
+~~~
+~~~~
+.
+aaa
+~~~
+
+````````````````````````````````
+
+
+Unclosed code blocks are closed by the end of the document
+(or the enclosing [block quote][block quotes] or [list item][list items]):
+
+```````````````````````````````` example
+```
+.
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+`````
+
+```
+aaa
+.
+
+```
+aaa
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+> ```
+> aaa
+
+bbb
+.
+
+aaa
+
+
+bbb
+````````````````````````````````
+
+
+A code block can have all empty lines as its content:
+
+```````````````````````````````` example
+```
+
+
+```
+.
+
+
+
+````````````````````````````````
+
+
+A code block can be empty:
+
+```````````````````````````````` example
+```
+```
+.
+
+````````````````````````````````
+
+
+Fences can be indented. If the opening fence is indented,
+content lines will have equivalent opening indentation removed,
+if present:
+
+```````````````````````````````` example
+ ```
+ aaa
+aaa
+```
+.
+aaa
+aaa
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ```
+aaa
+ aaa
+aaa
+ ```
+.
+aaa
+aaa
+aaa
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ```
+ aaa
+ aaa
+ aaa
+ ```
+.
+aaa
+ aaa
+aaa
+
+````````````````````````````````
+
+
+Four spaces indentation produces an indented code block:
+
+```````````````````````````````` example
+ ```
+ aaa
+ ```
+.
+```
+aaa
+```
+
+````````````````````````````````
+
+
+Closing fences may be indented by 0-3 spaces, and their indentation
+need not match that of the opening fence:
+
+```````````````````````````````` example
+```
+aaa
+ ```
+.
+aaa
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+ ```
+aaa
+ ```
+.
+aaa
+
+````````````````````````````````
+
+
+This is not a closing fence, because it is indented 4 spaces:
+
+```````````````````````````````` example
+```
+aaa
+ ```
+.
+aaa
+ ```
+
+````````````````````````````````
+
+
+
+Code fences (opening and closing) cannot contain internal spaces:
+
+```````````````````````````````` example
+``` ```
+aaa
+.
+
+aaa
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~~~~
+aaa
+~~~ ~~
+.
+aaa
+~~~ ~~
+
+````````````````````````````````
+
+
+Fenced code blocks can interrupt paragraphs, and can be followed
+directly by paragraphs, without a blank line between:
+
+```````````````````````````````` example
+foo
+```
+bar
+```
+baz
+.
+foo
+bar
+
+baz
+````````````````````````````````
+
+
+Other blocks can also occur before and after fenced code blocks
+without an intervening blank line:
+
+```````````````````````````````` example
+foo
+---
+~~~
+bar
+~~~
+# baz
+.
+foo
+bar
+
+baz
+````````````````````````````````
+
+
+An [info string] can be provided after the opening code fence.
+Opening and closing spaces will be stripped, and the first word, prefixed
+with `language-`, is used as the value for the `class` attribute of the
+`code` element within the enclosing `pre` element.
+
+```````````````````````````````` example
+```ruby
+def foo(x)
+ return 3
+end
+```
+.
+def foo(x)
+ return 3
+end
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+~~~~ ruby startline=3 $%@#$
+def foo(x)
+ return 3
+end
+~~~~~~~
+.
+def foo(x)
+ return 3
+end
+
+````````````````````````````````
+
+
+```````````````````````````````` example
+````;
+````
+.
+
+````````````````````````````````
+
+
+[Info strings] for backtick code blocks cannot contain backticks:
+
+```````````````````````````````` example
+``` aa ```
+foo
+.
+aa
+foo
+````````````````````````````````
+
+
+Closing code fences cannot have [info strings]:
+
+```````````````````````````````` example
+```
+``` aaa
+```
+.
+``` aaa
+
+````````````````````````````````
+
+
+
+## HTML blocks
+
+An [HTML block](@) is a group of lines that is treated
+as raw HTML (and will not be escaped in HTML output).
+
+There are seven kinds of [HTML block], which can be defined
+by their start and end conditions. The block begins with a line that
+meets a [start condition](@) (after up to three spaces
+optional indentation). It ends with the first subsequent line that
+meets a matching [end condition](@), or the last line of
+the document or other [container block]), if no line is encountered that meets the
+[end condition]. If the first line meets both the [start condition]
+and the [end condition], the block will contain just that line.
+
+1. **Start condition:** line begins with the string ``, ``, or `` (case-insensitive; it
+need not match the start tag).
+
+2. **Start condition:** line begins with the string ``.
+
+3. **Start condition:** line begins with the string ``.\
+**End condition:** line contains the string `?>`.
+
+4. **Start condition:** line begins with the string ``.
+
+5. **Start condition:** line begins with the string
+``.
+
+6. **Start condition:** line begins the string `<` or ``
+followed by one of the strings (case-insensitive) `address`,
+`article`, `aside`, `base`, `basefont`, `blockquote`, `body`,
+`caption`, `center`, `col`, `colgroup`, `dd`, `details`, `dialog`,
+`dir`, `div`, `dl`, `dt`, `fieldset`, `figcaption`, `figure`,
+`footer`, `form`, `frame`, `frameset`,
+`h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `head`, `header`, `hr`,
+`html`, `iframe`, `legend`, `li`, `link`, `main`, `menu`, `menuitem`,
+`meta`, `nav`, `noframes`, `ol`, `optgroup`, `option`, `p`, `param`,
+`section`, `source`, `summary`, `table`, `tbody`, `td`,
+`tfoot`, `th`, `thead`, `title`, `tr`, `track`, `ul`, followed
+by [whitespace], the end of the line, the string `>`, or
+the string `/>`.\
+**End condition:** line is followed by a [blank line].
+
+7. **Start condition:** line begins with a complete [open tag]
+or [closing tag] (with any [tag name] other than `script`,
+`style`, or `pre`) followed only by [whitespace]
+or the end of the line.\
+**End condition:** line is followed by a [blank line].
+
+HTML blocks continue until they are closed by their appropriate
+[end condition], or the last line of the document or other [container block].
+This means any HTML **within an HTML block** that might otherwise be recognised
+as a start condition will be ignored by the parser and passed through as-is,
+without changing the parser's state.
+
+For instance, `` within a HTML block started by `