...

Source file src/github.com/russross/blackfriday/v2/inline_test.go

Documentation: github.com/russross/blackfriday/v2

     1  //
     2  // Blackfriday Markdown Processor
     3  // Available at http://github.com/russross/blackfriday
     4  //
     5  // Copyright © 2011 Russ Ross <russ@russross.com>.
     6  // Distributed under the Simplified BSD License.
     7  // See README.md for details.
     8  //
     9  
    10  //
    11  // Unit tests for inline parsing
    12  //
    13  
    14  package blackfriday
    15  
    16  import (
    17  	"regexp"
    18  	"testing"
    19  
    20  	"strings"
    21  )
    22  
    23  func TestEmphasis(t *testing.T) {
    24  	t.Parallel()
    25  	var tests = []string{
    26  		"nothing inline\n",
    27  		"<p>nothing inline</p>\n",
    28  
    29  		"simple *inline* test\n",
    30  		"<p>simple <em>inline</em> test</p>\n",
    31  
    32  		"*at the* beginning\n",
    33  		"<p><em>at the</em> beginning</p>\n",
    34  
    35  		"at the *end*\n",
    36  		"<p>at the <em>end</em></p>\n",
    37  
    38  		"*try two* in *one line*\n",
    39  		"<p><em>try two</em> in <em>one line</em></p>\n",
    40  
    41  		"over *two\nlines* test\n",
    42  		"<p>over <em>two\nlines</em> test</p>\n",
    43  
    44  		"odd *number of* markers* here\n",
    45  		"<p>odd <em>number of</em> markers* here</p>\n",
    46  
    47  		"odd *number\nof* markers* here\n",
    48  		"<p>odd <em>number\nof</em> markers* here</p>\n",
    49  
    50  		"simple _inline_ test\n",
    51  		"<p>simple <em>inline</em> test</p>\n",
    52  
    53  		"_at the_ beginning\n",
    54  		"<p><em>at the</em> beginning</p>\n",
    55  
    56  		"at the _end_\n",
    57  		"<p>at the <em>end</em></p>\n",
    58  
    59  		"_try two_ in _one line_\n",
    60  		"<p><em>try two</em> in <em>one line</em></p>\n",
    61  
    62  		"over _two\nlines_ test\n",
    63  		"<p>over <em>two\nlines</em> test</p>\n",
    64  
    65  		"odd _number of_ markers_ here\n",
    66  		"<p>odd <em>number of</em> markers_ here</p>\n",
    67  
    68  		"odd _number\nof_ markers_ here\n",
    69  		"<p>odd <em>number\nof</em> markers_ here</p>\n",
    70  
    71  		"mix of *markers_\n",
    72  		"<p>mix of *markers_</p>\n",
    73  
    74  		"*What is A\\* algorithm?*\n",
    75  		"<p><em>What is A* algorithm?</em></p>\n",
    76  	}
    77  	doTestsInline(t, tests)
    78  }
    79  
    80  func TestReferenceOverride(t *testing.T) {
    81  	t.Parallel()
    82  	var tests = []string{
    83  		"test [ref1][]\n",
    84  		"<p>test <a href=\"http://www.ref1.com/\" title=\"Reference 1\">ref1</a></p>\n",
    85  
    86  		"test [my ref][ref1]\n",
    87  		"<p>test <a href=\"http://www.ref1.com/\" title=\"Reference 1\">my ref</a></p>\n",
    88  
    89  		"test [ref2][]\n\n[ref2]: http://www.leftalone.com/ (Ref left alone)\n",
    90  		"<p>test <a href=\"http://www.overridden.com/\" title=\"Reference Overridden\">ref2</a></p>\n",
    91  
    92  		"test [ref3][]\n\n[ref3]: http://www.leftalone.com/ (Ref left alone)\n",
    93  		"<p>test <a href=\"http://www.leftalone.com/\" title=\"Ref left alone\">ref3</a></p>\n",
    94  
    95  		"test [ref4][]\n\n[ref4]: http://zombo.com/ (You can do anything)\n",
    96  		"<p>test [ref4][]</p>\n",
    97  
    98  		"test [!(*http.ServeMux).ServeHTTP][] complicated ref\n",
    99  		"<p>test <a href=\"http://localhost:6060/pkg/net/http/#ServeMux.ServeHTTP\" title=\"ServeHTTP docs\">!(*http.ServeMux).ServeHTTP</a> complicated ref</p>\n",
   100  
   101  		"test [ref5][]\n",
   102  		"<p>test <a href=\"http://www.ref5.com/\" title=\"Reference 5\">Moo</a></p>\n",
   103  	}
   104  	doTestsInlineParam(t, tests, TestParams{
   105  		referenceOverride: func(reference string) (rv *Reference, overridden bool) {
   106  			switch reference {
   107  			case "ref1":
   108  				// just an overridden reference exists without definition
   109  				return &Reference{
   110  					Link:  "http://www.ref1.com/",
   111  					Title: "Reference 1"}, true
   112  			case "ref2":
   113  				// overridden exists and reference defined
   114  				return &Reference{
   115  					Link:  "http://www.overridden.com/",
   116  					Title: "Reference Overridden"}, true
   117  			case "ref3":
   118  				// not overridden and reference defined
   119  				return nil, false
   120  			case "ref4":
   121  				// overridden missing and defined
   122  				return nil, true
   123  			case "!(*http.ServeMux).ServeHTTP":
   124  				return &Reference{
   125  					Link:  "http://localhost:6060/pkg/net/http/#ServeMux.ServeHTTP",
   126  					Title: "ServeHTTP docs"}, true
   127  			case "ref5":
   128  				return &Reference{
   129  					Link:  "http://www.ref5.com/",
   130  					Title: "Reference 5",
   131  					Text:  "Moo",
   132  				}, true
   133  			}
   134  			return nil, false
   135  		},
   136  	})
   137  }
   138  
   139  func TestStrong(t *testing.T) {
   140  	t.Parallel()
   141  	var tests = []string{
   142  		"nothing inline\n",
   143  		"<p>nothing inline</p>\n",
   144  
   145  		"simple **inline** test\n",
   146  		"<p>simple <strong>inline</strong> test</p>\n",
   147  
   148  		"**at the** beginning\n",
   149  		"<p><strong>at the</strong> beginning</p>\n",
   150  
   151  		"at the **end**\n",
   152  		"<p>at the <strong>end</strong></p>\n",
   153  
   154  		"**try two** in **one line**\n",
   155  		"<p><strong>try two</strong> in <strong>one line</strong></p>\n",
   156  
   157  		"over **two\nlines** test\n",
   158  		"<p>over <strong>two\nlines</strong> test</p>\n",
   159  
   160  		"odd **number of** markers** here\n",
   161  		"<p>odd <strong>number of</strong> markers** here</p>\n",
   162  
   163  		"odd **number\nof** markers** here\n",
   164  		"<p>odd <strong>number\nof</strong> markers** here</p>\n",
   165  
   166  		"simple __inline__ test\n",
   167  		"<p>simple <strong>inline</strong> test</p>\n",
   168  
   169  		"__at the__ beginning\n",
   170  		"<p><strong>at the</strong> beginning</p>\n",
   171  
   172  		"at the __end__\n",
   173  		"<p>at the <strong>end</strong></p>\n",
   174  
   175  		"__try two__ in __one line__\n",
   176  		"<p><strong>try two</strong> in <strong>one line</strong></p>\n",
   177  
   178  		"over __two\nlines__ test\n",
   179  		"<p>over <strong>two\nlines</strong> test</p>\n",
   180  
   181  		"odd __number of__ markers__ here\n",
   182  		"<p>odd <strong>number of</strong> markers__ here</p>\n",
   183  
   184  		"odd __number\nof__ markers__ here\n",
   185  		"<p>odd <strong>number\nof</strong> markers__ here</p>\n",
   186  
   187  		"mix of **markers__\n",
   188  		"<p>mix of **markers__</p>\n",
   189  
   190  		"**`/usr`** : this folder is named `usr`\n",
   191  		"<p><strong><code>/usr</code></strong> : this folder is named <code>usr</code></p>\n",
   192  
   193  		"**`/usr`** :\n\n this folder is named `usr`\n",
   194  		"<p><strong><code>/usr</code></strong> :</p>\n\n<p>this folder is named <code>usr</code></p>\n",
   195  	}
   196  	doTestsInline(t, tests)
   197  }
   198  
   199  func TestEmphasisMix(t *testing.T) {
   200  	t.Parallel()
   201  	var tests = []string{
   202  		"***triple emphasis***\n",
   203  		"<p><strong><em>triple emphasis</em></strong></p>\n",
   204  
   205  		"***triple\nemphasis***\n",
   206  		"<p><strong><em>triple\nemphasis</em></strong></p>\n",
   207  
   208  		"___triple emphasis___\n",
   209  		"<p><strong><em>triple emphasis</em></strong></p>\n",
   210  
   211  		"***triple emphasis___\n",
   212  		"<p>***triple emphasis___</p>\n",
   213  
   214  		"*__triple emphasis__*\n",
   215  		"<p><em><strong>triple emphasis</strong></em></p>\n",
   216  
   217  		"__*triple emphasis*__\n",
   218  		"<p><strong><em>triple emphasis</em></strong></p>\n",
   219  
   220  		"**improper *nesting** is* bad\n",
   221  		"<p><strong>improper *nesting</strong> is* bad</p>\n",
   222  
   223  		"*improper **nesting* is** bad\n",
   224  		"<p>*improper <strong>nesting* is</strong> bad</p>\n",
   225  	}
   226  	doTestsInline(t, tests)
   227  }
   228  
   229  func TestEmphasisLink(t *testing.T) {
   230  	t.Parallel()
   231  	var tests = []string{
   232  		"[first](before) *text[second] (inside)text* [third](after)\n",
   233  		"<p><a href=\"before\">first</a> <em>text<a href=\"inside\">second</a>text</em> <a href=\"after\">third</a></p>\n",
   234  
   235  		"*incomplete [link] definition*\n",
   236  		"<p><em>incomplete [link] definition</em></p>\n",
   237  
   238  		"*it's [emphasis*] (not link)\n",
   239  		"<p><em>it's [emphasis</em>] (not link)</p>\n",
   240  
   241  		"*it's [emphasis*] and *[asterisk]\n",
   242  		"<p><em>it's [emphasis</em>] and *[asterisk]</p>\n",
   243  	}
   244  	doTestsInline(t, tests)
   245  }
   246  
   247  func TestStrikeThrough(t *testing.T) {
   248  	t.Parallel()
   249  	var tests = []string{
   250  		"nothing inline\n",
   251  		"<p>nothing inline</p>\n",
   252  
   253  		"simple ~~inline~~ test\n",
   254  		"<p>simple <del>inline</del> test</p>\n",
   255  
   256  		"~~at the~~ beginning\n",
   257  		"<p><del>at the</del> beginning</p>\n",
   258  
   259  		"at the ~~end~~\n",
   260  		"<p>at the <del>end</del></p>\n",
   261  
   262  		"~~try two~~ in ~~one line~~\n",
   263  		"<p><del>try two</del> in <del>one line</del></p>\n",
   264  
   265  		"over ~~two\nlines~~ test\n",
   266  		"<p>over <del>two\nlines</del> test</p>\n",
   267  
   268  		"odd ~~number of~~ markers~~ here\n",
   269  		"<p>odd <del>number of</del> markers~~ here</p>\n",
   270  
   271  		"odd ~~number\nof~~ markers~~ here\n",
   272  		"<p>odd <del>number\nof</del> markers~~ here</p>\n",
   273  	}
   274  	doTestsInline(t, tests)
   275  }
   276  
   277  func TestCodeSpan(t *testing.T) {
   278  	t.Parallel()
   279  	var tests = []string{
   280  		"`source code`\n",
   281  		"<p><code>source code</code></p>\n",
   282  
   283  		"` source code with spaces `\n",
   284  		"<p><code>source code with spaces</code></p>\n",
   285  
   286  		"` source code with spaces `not here\n",
   287  		"<p><code>source code with spaces</code>not here</p>\n",
   288  
   289  		"a `single marker\n",
   290  		"<p>a `single marker</p>\n",
   291  
   292  		"a single multi-tick marker with ``` no text\n",
   293  		"<p>a single multi-tick marker with ``` no text</p>\n",
   294  
   295  		"markers with ` ` a space\n",
   296  		"<p>markers with  a space</p>\n",
   297  
   298  		"`source code` and a `stray\n",
   299  		"<p><code>source code</code> and a `stray</p>\n",
   300  
   301  		"`source *with* _awkward characters_ in it`\n",
   302  		"<p><code>source *with* _awkward characters_ in it</code></p>\n",
   303  
   304  		"`split over\ntwo lines`\n",
   305  		"<p><code>split over\ntwo lines</code></p>\n",
   306  
   307  		"```multiple ticks``` for the marker\n",
   308  		"<p><code>multiple ticks</code> for the marker</p>\n",
   309  
   310  		"```multiple ticks `with` ticks inside```\n",
   311  		"<p><code>multiple ticks `with` ticks inside</code></p>\n",
   312  	}
   313  	doTestsInline(t, tests)
   314  }
   315  
   316  func TestLineBreak(t *testing.T) {
   317  	t.Parallel()
   318  	var tests = []string{
   319  		"this line  \nhas a break\n",
   320  		"<p>this line<br />\nhas a break</p>\n",
   321  
   322  		"this line \ndoes not\n",
   323  		"<p>this line\ndoes not</p>\n",
   324  
   325  		"this line\\\ndoes not\n",
   326  		"<p>this line\\\ndoes not</p>\n",
   327  
   328  		"this line\\ \ndoes not\n",
   329  		"<p>this line\\\ndoes not</p>\n",
   330  
   331  		"this has an   \nextra space\n",
   332  		"<p>this has an<br />\nextra space</p>\n",
   333  	}
   334  	doTestsInline(t, tests)
   335  
   336  	tests = []string{
   337  		"this line  \nhas a break\n",
   338  		"<p>this line<br />\nhas a break</p>\n",
   339  
   340  		"this line \ndoes not\n",
   341  		"<p>this line\ndoes not</p>\n",
   342  
   343  		"this line\\\nhas a break\n",
   344  		"<p>this line<br />\nhas a break</p>\n",
   345  
   346  		"this line\\ \ndoes not\n",
   347  		"<p>this line\\\ndoes not</p>\n",
   348  
   349  		"this has an   \nextra space\n",
   350  		"<p>this has an<br />\nextra space</p>\n",
   351  	}
   352  	doTestsInlineParam(t, tests, TestParams{
   353  		extensions: BackslashLineBreak})
   354  }
   355  
   356  func TestInlineLink(t *testing.T) {
   357  	t.Parallel()
   358  	var tests = []string{
   359  		"[foo](/bar/)\n",
   360  		"<p><a href=\"/bar/\">foo</a></p>\n",
   361  
   362  		"[foo with a title](/bar/ \"title\")\n",
   363  		"<p><a href=\"/bar/\" title=\"title\">foo with a title</a></p>\n",
   364  
   365  		"[foo with a title](/bar/\t\"title\")\n",
   366  		"<p><a href=\"/bar/\" title=\"title\">foo with a title</a></p>\n",
   367  
   368  		"[foo with a title](/bar/ \"title\"  )\n",
   369  		"<p><a href=\"/bar/\" title=\"title\">foo with a title</a></p>\n",
   370  
   371  		"[foo with a title](/bar/ title with no quotes)\n",
   372  		"<p><a href=\"/bar/ title with no quotes\">foo with a title</a></p>\n",
   373  
   374  		"[foo]()\n",
   375  		"<p>[foo]()</p>\n",
   376  
   377  		"![foo](/bar/)\n",
   378  		"<p><img src=\"/bar/\" alt=\"foo\" /></p>\n",
   379  
   380  		"![foo with a title](/bar/ \"title\")\n",
   381  		"<p><img src=\"/bar/\" alt=\"foo with a title\" title=\"title\" /></p>\n",
   382  
   383  		"![foo with a title](/bar/\t\"title\")\n",
   384  		"<p><img src=\"/bar/\" alt=\"foo with a title\" title=\"title\" /></p>\n",
   385  
   386  		"![foo with a title](/bar/ \"title\"  )\n",
   387  		"<p><img src=\"/bar/\" alt=\"foo with a title\" title=\"title\" /></p>\n",
   388  
   389  		"![foo with a title](/bar/ title with no quotes)\n",
   390  		"<p><img src=\"/bar/ title with no quotes\" alt=\"foo with a title\" /></p>\n",
   391  
   392  		"![](img.jpg)\n",
   393  		"<p><img src=\"img.jpg\" alt=\"\" /></p>\n",
   394  
   395  		"[link](url)\n",
   396  		"<p><a href=\"url\">link</a></p>\n",
   397  
   398  		"![foo]()\n",
   399  		"<p>![foo]()</p>\n",
   400  
   401  		"[a link]\t(/with_a_tab/)\n",
   402  		"<p><a href=\"/with_a_tab/\">a link</a></p>\n",
   403  
   404  		"[a link]  (/with_spaces/)\n",
   405  		"<p><a href=\"/with_spaces/\">a link</a></p>\n",
   406  
   407  		"[text (with) [[nested] (brackets)]](/url/)\n",
   408  		"<p><a href=\"/url/\">text (with) [[nested] (brackets)]</a></p>\n",
   409  
   410  		"[text (with) [broken nested] (brackets)]](/url/)\n",
   411  		"<p>[text (with) <a href=\"brackets\">broken nested</a>]](/url/)</p>\n",
   412  
   413  		"[text\nwith a newline](/link/)\n",
   414  		"<p><a href=\"/link/\">text\nwith a newline</a></p>\n",
   415  
   416  		"[text in brackets] [followed](/by a link/)\n",
   417  		"<p>[text in brackets] <a href=\"/by a link/\">followed</a></p>\n",
   418  
   419  		"[link with\\] a closing bracket](/url/)\n",
   420  		"<p><a href=\"/url/\">link with] a closing bracket</a></p>\n",
   421  
   422  		"[link with\\[ an opening bracket](/url/)\n",
   423  		"<p><a href=\"/url/\">link with[ an opening bracket</a></p>\n",
   424  
   425  		"[link with\\) a closing paren](/url/)\n",
   426  		"<p><a href=\"/url/\">link with) a closing paren</a></p>\n",
   427  
   428  		"[link with\\( an opening paren](/url/)\n",
   429  		"<p><a href=\"/url/\">link with( an opening paren</a></p>\n",
   430  
   431  		"[link](  with whitespace)\n",
   432  		"<p><a href=\"with whitespace\">link</a></p>\n",
   433  
   434  		"[link](  with whitespace   )\n",
   435  		"<p><a href=\"with whitespace\">link</a></p>\n",
   436  
   437  		"[![image](someimage)](with image)\n",
   438  		"<p><a href=\"with image\"><img src=\"someimage\" alt=\"image\" /></a></p>\n",
   439  
   440  		"[link](url \"one quote)\n",
   441  		"<p><a href=\"url &quot;one quote\">link</a></p>\n",
   442  
   443  		"[link](url 'one quote)\n",
   444  		"<p><a href=\"url 'one quote\">link</a></p>\n",
   445  
   446  		"[link](<url>)\n",
   447  		"<p><a href=\"url\">link</a></p>\n",
   448  
   449  		"[link & ampersand](/url/)\n",
   450  		"<p><a href=\"/url/\">link &amp; ampersand</a></p>\n",
   451  
   452  		"[link &amp; ampersand](/url/)\n",
   453  		"<p><a href=\"/url/\">link &amp; ampersand</a></p>\n",
   454  
   455  		"[link](/url/&query)\n",
   456  		"<p><a href=\"/url/&amp;query\">link</a></p>\n",
   457  
   458  		"[[t]](/t)\n",
   459  		"<p><a href=\"/t\">[t]</a></p>\n",
   460  
   461  		"[link](</>)\n",
   462  		"<p><a href=\"/\">link</a></p>\n",
   463  
   464  		"[link](<./>)\n",
   465  		"<p><a href=\"./\">link</a></p>\n",
   466  
   467  		"[link](<../>)\n",
   468  		"<p><a href=\"../\">link</a></p>\n",
   469  	}
   470  	doLinkTestsInline(t, tests)
   471  
   472  }
   473  
   474  func TestRelAttrLink(t *testing.T) {
   475  	t.Parallel()
   476  	var nofollowTests = []string{
   477  		"[foo](http://bar.com/foo/)\n",
   478  		"<p><a href=\"http://bar.com/foo/\" rel=\"nofollow\">foo</a></p>\n",
   479  
   480  		"[foo](/bar/)\n",
   481  		"<p><a href=\"/bar/\">foo</a></p>\n",
   482  
   483  		"[foo](/)\n",
   484  		"<p><a href=\"/\">foo</a></p>\n",
   485  
   486  		"[foo](./)\n",
   487  		"<p><a href=\"./\">foo</a></p>\n",
   488  
   489  		"[foo](../)\n",
   490  		"<p><a href=\"../\">foo</a></p>\n",
   491  
   492  		"[foo](../bar)\n",
   493  		"<p><a href=\"../bar\">foo</a></p>\n",
   494  	}
   495  	doTestsInlineParam(t, nofollowTests, TestParams{
   496  		HTMLFlags: Safelink | NofollowLinks,
   497  	})
   498  
   499  	var noreferrerTests = []string{
   500  		"[foo](http://bar.com/foo/)\n",
   501  		"<p><a href=\"http://bar.com/foo/\" rel=\"noreferrer\">foo</a></p>\n",
   502  
   503  		"[foo](/bar/)\n",
   504  		"<p><a href=\"/bar/\">foo</a></p>\n",
   505  	}
   506  	doTestsInlineParam(t, noreferrerTests, TestParams{
   507  		HTMLFlags: Safelink | NoreferrerLinks,
   508  	})
   509  
   510  	var noopenerTests = []string{
   511  		"[foo](http://bar.com/foo/)\n",
   512  		"<p><a href=\"http://bar.com/foo/\" rel=\"noopener\">foo</a></p>\n",
   513  
   514  		"[foo](/bar/)\n",
   515  		"<p><a href=\"/bar/\">foo</a></p>\n",
   516  	}
   517  	doTestsInlineParam(t, noopenerTests, TestParams{
   518  		HTMLFlags: Safelink | NoopenerLinks,
   519  	})
   520  
   521  	var nofollownoreferrernoopenerTests = []string{
   522  		"[foo](http://bar.com/foo/)\n",
   523  		"<p><a href=\"http://bar.com/foo/\" rel=\"nofollow noreferrer noopener\">foo</a></p>\n",
   524  
   525  		"[foo](/bar/)\n",
   526  		"<p><a href=\"/bar/\">foo</a></p>\n",
   527  	}
   528  	doTestsInlineParam(t, nofollownoreferrernoopenerTests, TestParams{
   529  		HTMLFlags: Safelink | NofollowLinks | NoreferrerLinks | NoopenerLinks,
   530  	})
   531  }
   532  
   533  func TestHrefTargetBlank(t *testing.T) {
   534  	t.Parallel()
   535  	var tests = []string{
   536  		// internal link
   537  		"[foo](/bar/)\n",
   538  		"<p><a href=\"/bar/\">foo</a></p>\n",
   539  
   540  		"[foo](/)\n",
   541  		"<p><a href=\"/\">foo</a></p>\n",
   542  
   543  		"[foo](./)\n",
   544  		"<p><a href=\"./\">foo</a></p>\n",
   545  
   546  		"[foo](./bar)\n",
   547  		"<p><a href=\"./bar\">foo</a></p>\n",
   548  
   549  		"[foo](../)\n",
   550  		"<p><a href=\"../\">foo</a></p>\n",
   551  
   552  		"[foo](../bar)\n",
   553  		"<p><a href=\"../bar\">foo</a></p>\n",
   554  
   555  		"[foo](http://example.com)\n",
   556  		"<p><a href=\"http://example.com\" target=\"_blank\">foo</a></p>\n",
   557  	}
   558  	doTestsInlineParam(t, tests, TestParams{
   559  		HTMLFlags: Safelink | HrefTargetBlank,
   560  	})
   561  }
   562  
   563  func TestSafeInlineLink(t *testing.T) {
   564  	t.Parallel()
   565  	var tests = []string{
   566  		"[foo](/bar/)\n",
   567  		"<p><a href=\"/bar/\">foo</a></p>\n",
   568  
   569  		"[foo](/)\n",
   570  		"<p><a href=\"/\">foo</a></p>\n",
   571  
   572  		"[foo](./)\n",
   573  		"<p><a href=\"./\">foo</a></p>\n",
   574  
   575  		"[foo](../)\n",
   576  		"<p><a href=\"../\">foo</a></p>\n",
   577  
   578  		"[foo](http://bar/)\n",
   579  		"<p><a href=\"http://bar/\">foo</a></p>\n",
   580  
   581  		"[foo](https://bar/)\n",
   582  		"<p><a href=\"https://bar/\">foo</a></p>\n",
   583  
   584  		"[foo](ftp://bar/)\n",
   585  		"<p><a href=\"ftp://bar/\">foo</a></p>\n",
   586  
   587  		"[foo](mailto://bar/)\n",
   588  		"<p><a href=\"mailto://bar/\">foo</a></p>\n",
   589  
   590  		// Not considered safe
   591  		"[foo](baz://bar/)\n",
   592  		"<p><tt>foo</tt></p>\n",
   593  	}
   594  	doSafeTestsInline(t, tests)
   595  }
   596  
   597  func TestReferenceLink(t *testing.T) {
   598  	t.Parallel()
   599  	var tests = []string{
   600  		"[link][ref]\n",
   601  		"<p>[link][ref]</p>\n",
   602  
   603  		"[link][ref]\n   [ref]: /url/ \"title\"\n",
   604  		"<p><a href=\"/url/\" title=\"title\">link</a></p>\n",
   605  
   606  		"[link][ref]\n   [ref]: /url/\n",
   607  		"<p><a href=\"/url/\">link</a></p>\n",
   608  
   609  		"   [ref]: /url/\n",
   610  		"",
   611  
   612  		"   [ref]: /url/\n[ref2]: /url/\n [ref3]: /url/\n",
   613  		"",
   614  
   615  		"   [ref]: /url/\n[ref2]: /url/\n [ref3]: /url/\n    [4spaces]: /url/\n",
   616  		"<pre><code>[4spaces]: /url/\n</code></pre>\n",
   617  
   618  		"[hmm](ref2)\n   [ref]: /url/\n[ref2]: /url/\n [ref3]: /url/\n",
   619  		"<p><a href=\"ref2\">hmm</a></p>\n",
   620  
   621  		"[ref]\n",
   622  		"<p>[ref]</p>\n",
   623  
   624  		"[ref]\n   [ref]: /url/ \"title\"\n",
   625  		"<p><a href=\"/url/\" title=\"title\">ref</a></p>\n",
   626  
   627  		"[ref]\n   [ref]: ../url/ \"title\"\n",
   628  		"<p><a href=\"../url/\" title=\"title\">ref</a></p>\n",
   629  
   630  		"[link][ref]\n   [ref]: /url/",
   631  		"<p><a href=\"/url/\">link</a></p>\n",
   632  	}
   633  	doLinkTestsInline(t, tests)
   634  }
   635  
   636  func TestTags(t *testing.T) {
   637  	t.Parallel()
   638  	var tests = []string{
   639  		"a <span>tag</span>\n",
   640  		"<p>a <span>tag</span></p>\n",
   641  
   642  		"<span>tag</span>\n",
   643  		"<p><span>tag</span></p>\n",
   644  
   645  		"<span>mismatch</spandex>\n",
   646  		"<p><span>mismatch</spandex></p>\n",
   647  
   648  		"a <singleton /> tag\n",
   649  		"<p>a <singleton /> tag</p>\n",
   650  	}
   651  	doTestsInline(t, tests)
   652  }
   653  
   654  func TestAutoLink(t *testing.T) {
   655  	t.Parallel()
   656  	var tests = []string{
   657  		"http://foo.com/\n",
   658  		"<p><a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   659  
   660  		"1 http://foo.com/\n",
   661  		"<p>1 <a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   662  
   663  		"1http://foo.com/\n",
   664  		"<p>1<a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   665  
   666  		"1.http://foo.com/\n",
   667  		"<p>1.<a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   668  
   669  		"1. http://foo.com/\n",
   670  		"<ol>\n<li><a href=\"http://foo.com/\">http://foo.com/</a></li>\n</ol>\n",
   671  
   672  		"-http://foo.com/\n",
   673  		"<p>-<a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   674  
   675  		"- http://foo.com/\n",
   676  		"<ul>\n<li><a href=\"http://foo.com/\">http://foo.com/</a></li>\n</ul>\n",
   677  
   678  		"_http://foo.com/\n",
   679  		"<p>_<a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   680  
   681  		"令狐http://foo.com/\n",
   682  		"<p>令狐<a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   683  
   684  		"令狐 http://foo.com/\n",
   685  		"<p>令狐 <a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   686  
   687  		"ahttp://foo.com/\n",
   688  		"<p>ahttp://foo.com/</p>\n",
   689  
   690  		">http://foo.com/\n",
   691  		"<blockquote>\n<p><a href=\"http://foo.com/\">http://foo.com/</a></p>\n</blockquote>\n",
   692  
   693  		"> http://foo.com/\n",
   694  		"<blockquote>\n<p><a href=\"http://foo.com/\">http://foo.com/</a></p>\n</blockquote>\n",
   695  
   696  		"go to <http://foo.com/>\n",
   697  		"<p>go to <a href=\"http://foo.com/\">http://foo.com/</a></p>\n",
   698  
   699  		"a secure <https://link.org>\n",
   700  		"<p>a secure <a href=\"https://link.org\">https://link.org</a></p>\n",
   701  
   702  		"an email <mailto:some@one.com>\n",
   703  		"<p>an email <a href=\"mailto:some@one.com\">some@one.com</a></p>\n",
   704  
   705  		"an email <mailto://some@one.com>\n",
   706  		"<p>an email <a href=\"mailto://some@one.com\">some@one.com</a></p>\n",
   707  
   708  		"an email <some@one.com>\n",
   709  		"<p>an email <a href=\"mailto:some@one.com\">some@one.com</a></p>\n",
   710  
   711  		"an ftp <ftp://old.com>\n",
   712  		"<p>an ftp <a href=\"ftp://old.com\">ftp://old.com</a></p>\n",
   713  
   714  		"an ftp <ftp:old.com>\n",
   715  		"<p>an ftp <a href=\"ftp:old.com\">ftp:old.com</a></p>\n",
   716  
   717  		"a link with <http://new.com?query=foo&bar>\n",
   718  		"<p>a link with <a href=\"http://new.com?query=foo&amp;bar\">" +
   719  			"http://new.com?query=foo&amp;bar</a></p>\n",
   720  
   721  		"quotes mean a tag <http://new.com?query=\"foo\"&bar>\n",
   722  		"<p>quotes mean a tag <http://new.com?query=\"foo\"&bar></p>\n",
   723  
   724  		"quotes mean a tag <http://new.com?query='foo'&bar>\n",
   725  		"<p>quotes mean a tag <http://new.com?query='foo'&bar></p>\n",
   726  
   727  		"unless escaped <http://new.com?query=\\\"foo\\\"&bar>\n",
   728  		"<p>unless escaped <a href=\"http://new.com?query=&quot;foo&quot;&amp;bar\">" +
   729  			"http://new.com?query=&quot;foo&quot;&amp;bar</a></p>\n",
   730  
   731  		"even a > can be escaped <http://new.com?q=\\>&etc>\n",
   732  		"<p>even a &gt; can be escaped <a href=\"http://new.com?q=&gt;&amp;etc\">" +
   733  			"http://new.com?q=&gt;&amp;etc</a></p>\n",
   734  
   735  		"<a href=\"http://fancy.com\">http://fancy.com</a>\n",
   736  		"<p><a href=\"http://fancy.com\">http://fancy.com</a></p>\n",
   737  
   738  		"<a href=\"http://fancy.com\">This is a link</a>\n",
   739  		"<p><a href=\"http://fancy.com\">This is a link</a></p>\n",
   740  
   741  		"<a href=\"http://www.fancy.com/A_B.pdf\">http://www.fancy.com/A_B.pdf</a>\n",
   742  		"<p><a href=\"http://www.fancy.com/A_B.pdf\">http://www.fancy.com/A_B.pdf</a></p>\n",
   743  
   744  		"(<a href=\"http://www.fancy.com/A_B\">http://www.fancy.com/A_B</a> (\n",
   745  		"<p>(<a href=\"http://www.fancy.com/A_B\">http://www.fancy.com/A_B</a> (</p>\n",
   746  
   747  		"(<a href=\"http://www.fancy.com/A_B\">http://www.fancy.com/A_B</a> (part two: <a href=\"http://www.fancy.com/A_B\">http://www.fancy.com/A_B</a>)).\n",
   748  		"<p>(<a href=\"http://www.fancy.com/A_B\">http://www.fancy.com/A_B</a> (part two: <a href=\"http://www.fancy.com/A_B\">http://www.fancy.com/A_B</a>)).</p>\n",
   749  
   750  		"http://www.foo.com<br />\n",
   751  		"<p><a href=\"http://www.foo.com\">http://www.foo.com</a><br /></p>\n",
   752  
   753  		"http://foo.com/viewtopic.php?f=18&amp;t=297",
   754  		"<p><a href=\"http://foo.com/viewtopic.php?f=18&amp;t=297\">http://foo.com/viewtopic.php?f=18&amp;t=297</a></p>\n",
   755  
   756  		"http://foo.com/viewtopic.php?param=&quot;18&quot;zz",
   757  		"<p><a href=\"http://foo.com/viewtopic.php?param=&quot;18&quot;zz\">http://foo.com/viewtopic.php?param=&quot;18&quot;zz</a></p>\n",
   758  
   759  		"http://foo.com/viewtopic.php?param=&quot;18&quot;",
   760  		"<p><a href=\"http://foo.com/viewtopic.php?param=&quot;18&quot;\">http://foo.com/viewtopic.php?param=&quot;18&quot;</a></p>\n",
   761  
   762  		"<a href=\"https://fancy.com\">https://fancy.com</a>\n",
   763  		"<p><a href=\"https://fancy.com\">https://fancy.com</a></p>\n",
   764  	}
   765  	doLinkTestsInline(t, tests)
   766  }
   767  
   768  var footnoteTests = []string{
   769  	"testing footnotes.[^a]\n\n[^a]: This is the note\n",
   770  	`<p>testing footnotes.<sup class="footnote-ref" id="fnref:a"><a href="#fn:a">1</a></sup></p>
   771  
   772  <div class="footnotes">
   773  
   774  <hr />
   775  
   776  <ol>
   777  <li id="fn:a">This is the note</li>
   778  </ol>
   779  
   780  </div>
   781  `,
   782  
   783  	`testing long[^b] notes.
   784  
   785  [^b]: Paragraph 1
   786  
   787  	Paragraph 2
   788  
   789  	` + "```\n\tsome code\n\t```" + `
   790  
   791  	Paragraph 3
   792  
   793  No longer in the footnote
   794  `,
   795  	`<p>testing long<sup class="footnote-ref" id="fnref:b"><a href="#fn:b">1</a></sup> notes.</p>
   796  
   797  <p>No longer in the footnote</p>
   798  
   799  <div class="footnotes">
   800  
   801  <hr />
   802  
   803  <ol>
   804  <li id="fn:b"><p>Paragraph 1</p>
   805  
   806  <p>Paragraph 2</p>
   807  
   808  <p><code>
   809  some code
   810  </code></p>
   811  
   812  <p>Paragraph 3</p></li>
   813  </ol>
   814  
   815  </div>
   816  `,
   817  
   818  	`testing[^c] multiple[^d] notes.
   819  
   820  [^c]: this is [note] c
   821  
   822  
   823  omg
   824  
   825  [^d]: this is note d
   826  
   827  what happens here
   828  
   829  [note]: /link/c
   830  
   831  `,
   832  	`<p>testing<sup class="footnote-ref" id="fnref:c"><a href="#fn:c">1</a></sup> multiple<sup class="footnote-ref" id="fnref:d"><a href="#fn:d">2</a></sup> notes.</p>
   833  
   834  <p>omg</p>
   835  
   836  <p>what happens here</p>
   837  
   838  <div class="footnotes">
   839  
   840  <hr />
   841  
   842  <ol>
   843  <li id="fn:c">this is <a href="/link/c">note</a> c</li>
   844  
   845  <li id="fn:d">this is note d</li>
   846  </ol>
   847  
   848  </div>
   849  `,
   850  
   851  	"testing inline^[this is the note] notes.\n",
   852  	`<p>testing inline<sup class="footnote-ref" id="fnref:this-is-the-note"><a href="#fn:this-is-the-note">1</a></sup> notes.</p>
   853  
   854  <div class="footnotes">
   855  
   856  <hr />
   857  
   858  <ol>
   859  <li id="fn:this-is-the-note">this is the note</li>
   860  </ol>
   861  
   862  </div>
   863  `,
   864  
   865  	"testing multiple[^1] types^[inline note] of notes[^2]\n\n[^2]: the second deferred note\n[^1]: the first deferred note\n\n\twhich happens to be a block\n",
   866  	`<p>testing multiple<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> types<sup class="footnote-ref" id="fnref:inline-note"><a href="#fn:inline-note">2</a></sup> of notes<sup class="footnote-ref" id="fnref:2"><a href="#fn:2">3</a></sup></p>
   867  
   868  <div class="footnotes">
   869  
   870  <hr />
   871  
   872  <ol>
   873  <li id="fn:1"><p>the first deferred note</p>
   874  
   875  <p>which happens to be a block</p></li>
   876  
   877  <li id="fn:inline-note">inline note</li>
   878  
   879  <li id="fn:2">the second deferred note</li>
   880  </ol>
   881  
   882  </div>
   883  `,
   884  
   885  	`This is a footnote[^1]^[and this is an inline footnote]
   886  
   887  [^1]: the footnote text.
   888  
   889      may be multiple paragraphs.
   890  `,
   891  	`<p>This is a footnote<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup><sup class="footnote-ref" id="fnref:and-this-is-an-i"><a href="#fn:and-this-is-an-i">2</a></sup></p>
   892  
   893  <div class="footnotes">
   894  
   895  <hr />
   896  
   897  <ol>
   898  <li id="fn:1"><p>the footnote text.</p>
   899  
   900  <p>may be multiple paragraphs.</p></li>
   901  
   902  <li id="fn:and-this-is-an-i">and this is an inline footnote</li>
   903  </ol>
   904  
   905  </div>
   906  `,
   907  
   908  	"empty footnote[^]\n\n[^]: fn text",
   909  	"<p>empty footnote<sup class=\"footnote-ref\" id=\"fnref:\"><a href=\"#fn:\">1</a></sup></p>\n\n<div class=\"footnotes\">\n\n<hr />\n\n<ol>\n<li id=\"fn:\">fn text</li>\n</ol>\n\n</div>\n",
   910  
   911  	"Some text.[^note1]\n\n[^note1]: fn1",
   912  	"<p>Some text.<sup class=\"footnote-ref\" id=\"fnref:note1\"><a href=\"#fn:note1\">1</a></sup></p>\n\n<div class=\"footnotes\">\n\n<hr />\n\n<ol>\n<li id=\"fn:note1\">fn1</li>\n</ol>\n\n</div>\n",
   913  
   914  	"Some text.[^note1][^note2]\n\n[^note1]: fn1\n[^note2]: fn2\n",
   915  	"<p>Some text.<sup class=\"footnote-ref\" id=\"fnref:note1\"><a href=\"#fn:note1\">1</a></sup><sup class=\"footnote-ref\" id=\"fnref:note2\"><a href=\"#fn:note2\">2</a></sup></p>\n\n<div class=\"footnotes\">\n\n<hr />\n\n<ol>\n<li id=\"fn:note1\">fn1</li>\n\n<li id=\"fn:note2\">fn2</li>\n</ol>\n\n</div>\n",
   916  
   917  	`Bla bla [^1] [WWW][w3]
   918  
   919  [^1]: This is a footnote
   920  
   921  [w3]: http://www.w3.org/
   922  `,
   923  	`<p>Bla bla <sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup> <a href="http://www.w3.org/">WWW</a></p>
   924  
   925  <div class="footnotes">
   926  
   927  <hr />
   928  
   929  <ol>
   930  <li id="fn:1">This is a footnote</li>
   931  </ol>
   932  
   933  </div>
   934  `,
   935  
   936  	`This is exciting![^fn1]
   937  
   938  [^fn1]: Fine print
   939  `,
   940  	`<p>This is exciting!<sup class="footnote-ref" id="fnref:fn1"><a href="#fn:fn1">1</a></sup></p>
   941  
   942  <div class="footnotes">
   943  
   944  <hr />
   945  
   946  <ol>
   947  <li id="fn:fn1">Fine print</li>
   948  </ol>
   949  
   950  </div>
   951  `,
   952  
   953  	`This text does not reference a footnote.
   954  
   955  [^footnote]: But it has a footnote! And it gets omitted.
   956  `,
   957  	"<p>This text does not reference a footnote.</p>\n",
   958  }
   959  
   960  func TestFootnotes(t *testing.T) {
   961  	t.Parallel()
   962  	doTestsInlineParam(t, footnoteTests, TestParams{
   963  		extensions: Footnotes,
   964  	})
   965  }
   966  
   967  func TestFootnotesWithParameters(t *testing.T) {
   968  	t.Parallel()
   969  	tests := make([]string, len(footnoteTests))
   970  
   971  	prefix := "testPrefix"
   972  	returnText := "ret"
   973  	re := regexp.MustCompile(`(?ms)<li id="fn:(\S+?)">(.*?)</li>`)
   974  
   975  	// Transform the test expectations to match the parameters we're using.
   976  	for i, test := range footnoteTests {
   977  		if i%2 == 1 {
   978  			test = strings.Replace(test, "fn:", "fn:"+prefix, -1)
   979  			test = strings.Replace(test, "fnref:", "fnref:"+prefix, -1)
   980  			test = re.ReplaceAllString(test, `<li id="fn:$1">$2 <a class="footnote-return" href="#fnref:$1">ret</a></li>`)
   981  		}
   982  		tests[i] = test
   983  	}
   984  
   985  	params := HTMLRendererParameters{
   986  		FootnoteAnchorPrefix:       prefix,
   987  		FootnoteReturnLinkContents: returnText,
   988  	}
   989  
   990  	doTestsInlineParam(t, tests, TestParams{
   991  		extensions:             Footnotes,
   992  		HTMLFlags:              FootnoteReturnLinks,
   993  		HTMLRendererParameters: params,
   994  	})
   995  }
   996  
   997  func TestNestedFootnotes(t *testing.T) {
   998  	t.Parallel()
   999  	var tests = []string{
  1000  		`Paragraph.[^fn1]
  1001  
  1002  [^fn1]:
  1003    Asterisk[^fn2]
  1004  
  1005  [^fn2]:
  1006    Obelisk`,
  1007  		`<p>Paragraph.<sup class="footnote-ref" id="fnref:fn1"><a href="#fn:fn1">1</a></sup></p>
  1008  
  1009  <div class="footnotes">
  1010  
  1011  <hr />
  1012  
  1013  <ol>
  1014  <li id="fn:fn1">Asterisk<sup class="footnote-ref" id="fnref:fn2"><a href="#fn:fn2">2</a></sup></li>
  1015  
  1016  <li id="fn:fn2">Obelisk</li>
  1017  </ol>
  1018  
  1019  </div>
  1020  `,
  1021  	}
  1022  	doTestsInlineParam(t, tests, TestParams{extensions: Footnotes})
  1023  }
  1024  
  1025  func TestInlineComments(t *testing.T) {
  1026  	t.Parallel()
  1027  	var tests = []string{
  1028  		"Hello <!-- there ->\n",
  1029  		"<p>Hello &lt;!&mdash; there &ndash;&gt;</p>\n",
  1030  
  1031  		"Hello <!-- there -->\n",
  1032  		"<p>Hello <!-- there --></p>\n",
  1033  
  1034  		"Hello <!-- there -->",
  1035  		"<p>Hello <!-- there --></p>\n",
  1036  
  1037  		"Hello <!---->\n",
  1038  		"<p>Hello <!----></p>\n",
  1039  
  1040  		"Hello <!-- there -->\na",
  1041  		"<p>Hello <!-- there -->\na</p>\n",
  1042  
  1043  		"* list <!-- item -->\n",
  1044  		"<ul>\n<li>list <!-- item --></li>\n</ul>\n",
  1045  
  1046  		"<!-- Front --> comment\n",
  1047  		"<p><!-- Front --> comment</p>\n",
  1048  
  1049  		"blahblah\n<!--- foo -->\nrhubarb\n",
  1050  		"<p>blahblah\n<!--- foo -->\nrhubarb</p>\n",
  1051  	}
  1052  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsDashes})
  1053  }
  1054  
  1055  func TestSmartDoubleQuotes(t *testing.T) {
  1056  	t.Parallel()
  1057  	var tests = []string{
  1058  		"this should be normal \"quoted\" text.\n",
  1059  		"<p>this should be normal &ldquo;quoted&rdquo; text.</p>\n",
  1060  		"this \" single double\n",
  1061  		"<p>this &ldquo; single double</p>\n",
  1062  		"two pair of \"some\" quoted \"text\".\n",
  1063  		"<p>two pair of &ldquo;some&rdquo; quoted &ldquo;text&rdquo;.</p>\n"}
  1064  
  1065  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants})
  1066  }
  1067  
  1068  func TestSmartDoubleQuotesNBSP(t *testing.T) {
  1069  	t.Parallel()
  1070  	var tests = []string{
  1071  		"this should be normal \"quoted\" text.\n",
  1072  		"<p>this should be normal &ldquo;&nbsp;quoted&nbsp;&rdquo; text.</p>\n",
  1073  		"this \" single double\n",
  1074  		"<p>this &ldquo;&nbsp; single double</p>\n",
  1075  		"two pair of \"some\" quoted \"text\".\n",
  1076  		"<p>two pair of &ldquo;&nbsp;some&nbsp;&rdquo; quoted &ldquo;&nbsp;text&nbsp;&rdquo;.</p>\n"}
  1077  
  1078  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsQuotesNBSP})
  1079  }
  1080  
  1081  func TestSmartAngledDoubleQuotes(t *testing.T) {
  1082  	t.Parallel()
  1083  	var tests = []string{
  1084  		"this should be angled \"quoted\" text.\n",
  1085  		"<p>this should be angled &laquo;quoted&raquo; text.</p>\n",
  1086  		"this \" single double\n",
  1087  		"<p>this &laquo; single double</p>\n",
  1088  		"two pair of \"some\" quoted \"text\".\n",
  1089  		"<p>two pair of &laquo;some&raquo; quoted &laquo;text&raquo;.</p>\n"}
  1090  
  1091  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsAngledQuotes})
  1092  }
  1093  
  1094  func TestSmartAngledDoubleQuotesNBSP(t *testing.T) {
  1095  	t.Parallel()
  1096  	var tests = []string{
  1097  		"this should be angled \"quoted\" text.\n",
  1098  		"<p>this should be angled &laquo;&nbsp;quoted&nbsp;&raquo; text.</p>\n",
  1099  		"this \" single double\n",
  1100  		"<p>this &laquo;&nbsp; single double</p>\n",
  1101  		"two pair of \"some\" quoted \"text\".\n",
  1102  		"<p>two pair of &laquo;&nbsp;some&nbsp;&raquo; quoted &laquo;&nbsp;text&nbsp;&raquo;.</p>\n"}
  1103  
  1104  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsAngledQuotes | SmartypantsQuotesNBSP})
  1105  }
  1106  
  1107  func TestSmartFractions(t *testing.T) {
  1108  	t.Parallel()
  1109  	var tests = []string{
  1110  		"1/2, 1/4 and 3/4; 1/4th and 3/4ths\n",
  1111  		"<p>&frac12;, &frac14; and &frac34;; &frac14;th and &frac34;ths</p>\n",
  1112  		"1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.\n",
  1113  		"<p>1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.</p>\n"}
  1114  
  1115  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants})
  1116  
  1117  	tests = []string{
  1118  		"1/2, 2/3, 81/100 and 1000000/1048576.\n",
  1119  		"<p><sup>1</sup>&frasl;<sub>2</sub>, <sup>2</sup>&frasl;<sub>3</sub>, <sup>81</sup>&frasl;<sub>100</sub> and <sup>1000000</sup>&frasl;<sub>1048576</sub>.</p>\n",
  1120  		"1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.\n",
  1121  		"<p>1/2/2015, 1/4/2015, 3/4/2015; 2015/1/2, 2015/1/4, 2015/3/4.</p>\n"}
  1122  
  1123  	doTestsInlineParam(t, tests, TestParams{HTMLFlags: Smartypants | SmartypantsFractions})
  1124  }
  1125  
  1126  func TestDisableSmartDashes(t *testing.T) {
  1127  	t.Parallel()
  1128  	doTestsInlineParam(t, []string{
  1129  		"foo - bar\n",
  1130  		"<p>foo - bar</p>\n",
  1131  		"foo -- bar\n",
  1132  		"<p>foo -- bar</p>\n",
  1133  		"foo --- bar\n",
  1134  		"<p>foo --- bar</p>\n",
  1135  	}, TestParams{})
  1136  	doTestsInlineParam(t, []string{
  1137  		"foo - bar\n",
  1138  		"<p>foo &ndash; bar</p>\n",
  1139  		"foo -- bar\n",
  1140  		"<p>foo &mdash; bar</p>\n",
  1141  		"foo --- bar\n",
  1142  		"<p>foo &mdash;&ndash; bar</p>\n",
  1143  	}, TestParams{HTMLFlags: Smartypants | SmartypantsDashes})
  1144  	doTestsInlineParam(t, []string{
  1145  		"foo - bar\n",
  1146  		"<p>foo - bar</p>\n",
  1147  		"foo -- bar\n",
  1148  		"<p>foo &ndash; bar</p>\n",
  1149  		"foo --- bar\n",
  1150  		"<p>foo &mdash; bar</p>\n",
  1151  	}, TestParams{HTMLFlags: Smartypants | SmartypantsLatexDashes | SmartypantsDashes})
  1152  	doTestsInlineParam(t, []string{
  1153  		"foo - bar\n",
  1154  		"<p>foo - bar</p>\n",
  1155  		"foo -- bar\n",
  1156  		"<p>foo -- bar</p>\n",
  1157  		"foo --- bar\n",
  1158  		"<p>foo --- bar</p>\n",
  1159  	}, TestParams{HTMLFlags: Smartypants | SmartypantsLatexDashes})
  1160  }
  1161  
  1162  func TestSkipLinks(t *testing.T) {
  1163  	t.Parallel()
  1164  	doTestsInlineParam(t, []string{
  1165  		"[foo](gopher://foo.bar)",
  1166  		"<p><tt>foo</tt></p>\n",
  1167  
  1168  		"[foo](mailto://bar/)\n",
  1169  		"<p><tt>foo</tt></p>\n",
  1170  	}, TestParams{
  1171  		HTMLFlags: SkipLinks,
  1172  	})
  1173  }
  1174  
  1175  func TestSkipImages(t *testing.T) {
  1176  	t.Parallel()
  1177  	doTestsInlineParam(t, []string{
  1178  		"![foo](/bar/)\n",
  1179  		"<p></p>\n",
  1180  	}, TestParams{
  1181  		HTMLFlags: SkipImages,
  1182  	})
  1183  }
  1184  
  1185  func TestUseXHTML(t *testing.T) {
  1186  	t.Parallel()
  1187  	doTestsParam(t, []string{
  1188  		"---",
  1189  		"<hr>\n",
  1190  	}, TestParams{})
  1191  	doTestsParam(t, []string{
  1192  		"---",
  1193  		"<hr />\n",
  1194  	}, TestParams{HTMLFlags: UseXHTML})
  1195  }
  1196  
  1197  func TestSkipHTML(t *testing.T) {
  1198  	t.Parallel()
  1199  	doTestsParam(t, []string{
  1200  		"<div class=\"foo\"></div>\n\ntext\n\n<form>the form</form>",
  1201  		"<p>text</p>\n\n<p>the form</p>\n",
  1202  
  1203  		"text <em>inline html</em> more text",
  1204  		"<p>text inline html more text</p>\n",
  1205  	}, TestParams{HTMLFlags: SkipHTML})
  1206  }
  1207  
  1208  func BenchmarkSmartDoubleQuotes(b *testing.B) {
  1209  	params := TestParams{HTMLFlags: Smartypants}
  1210  	params.extensions |= Autolink | Strikethrough
  1211  	params.HTMLFlags |= UseXHTML
  1212  
  1213  	for i := 0; i < b.N; i++ {
  1214  		runMarkdown("this should be normal \"quoted\" text.\n", params)
  1215  	}
  1216  }
  1217  

View as plain text