github.com/levb/mattermost-server@v5.3.1+incompatible/utils/markdown/autolink_test.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package markdown 5 6 import ( 7 "testing" 8 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestParseURLAutolink(t *testing.T) { 13 testCases := []struct { 14 Description string 15 Input string 16 Position int 17 Expected string 18 }{ 19 { 20 Description: "no link", 21 Input: "This is an :emoji:", 22 Position: 11, 23 Expected: "", 24 }, 25 { 26 Description: "no link 2", 27 Input: "These are two things: apple and orange", 28 Position: 20, 29 Expected: "", 30 }, 31 { 32 Description: "link with http", 33 Input: "http://example.com and some text", 34 Position: 4, 35 Expected: "http://example.com", 36 }, 37 { 38 Description: "link with https", 39 Input: "https://example.com and some text", 40 Position: 5, 41 Expected: "https://example.com", 42 }, 43 { 44 Description: "link with ftp", 45 Input: "ftp://example.com and some text", 46 Position: 3, 47 Expected: "ftp://example.com", 48 }, 49 { 50 Description: "link with a path", 51 Input: "https://example.com/abcd and some text", 52 Position: 5, 53 Expected: "https://example.com/abcd", 54 }, 55 { 56 Description: "link with parameters", 57 Input: "ftp://example.com/abcd?foo=bar and some text", 58 Position: 3, 59 Expected: "ftp://example.com/abcd?foo=bar", 60 }, 61 { 62 Description: "link, not at start", 63 Input: "This is https://example.com and some text", 64 Position: 13, 65 Expected: "https://example.com", 66 }, 67 { 68 Description: "link with a path, not at start", 69 Input: "This is also http://www.example.com/abcd and some text", 70 Position: 17, 71 Expected: "http://www.example.com/abcd", 72 }, 73 { 74 Description: "link with parameters, not at start", 75 Input: "These are https://www.example.com/abcd?foo=bar and some text", 76 Position: 15, 77 Expected: "https://www.example.com/abcd?foo=bar", 78 }, 79 { 80 Description: "link with trailing characters", 81 Input: "This is ftp://www.example.com??", 82 Position: 11, 83 Expected: "ftp://www.example.com", 84 }, 85 { 86 Description: "multiple links", 87 Input: "This is https://example.com/abcd and ftp://www.example.com/1234", 88 Position: 13, 89 Expected: "https://example.com/abcd", 90 }, 91 { 92 Description: "second of multiple links", 93 Input: "This is https://example.com/abcd and ftp://www.example.com/1234", 94 Position: 40, 95 Expected: "ftp://www.example.com/1234", 96 }, 97 { 98 Description: "link with brackets", 99 Input: "Go to ftp://www.example.com/my/page_(disambiguation) and some text", 100 Position: 9, 101 Expected: "ftp://www.example.com/my/page_(disambiguation)", 102 }, 103 { 104 Description: "link in brackets", 105 Input: "(https://www.example.com/foo/bar)", 106 Position: 6, 107 Expected: "https://www.example.com/foo/bar", 108 }, 109 { 110 Description: "link in underscores", 111 Input: "_http://www.example.com_", 112 Position: 5, 113 Expected: "http://www.example.com", 114 }, 115 { 116 Description: "link in asterisks", 117 Input: "This is **ftp://example.com**", 118 Position: 13, 119 Expected: "ftp://example.com", 120 }, 121 { 122 Description: "link in strikethrough", 123 Input: "Those were ~~https://example.com~~", 124 Position: 18, 125 Expected: "https://example.com", 126 }, 127 { 128 Description: "link with angle brackets", 129 Input: "<b>We use http://example.com</b>", 130 Position: 14, 131 Expected: "http://example.com", 132 }, 133 } 134 135 for _, testCase := range testCases { 136 t.Run(testCase.Description, func(t *testing.T) { 137 rawRange, ok := parseURLAutolink(testCase.Input, testCase.Position) 138 139 if testCase.Expected == "" { 140 assert.False(t, ok) 141 assert.Equal(t, Range{0, 0}, rawRange) 142 } else { 143 assert.True(t, ok) 144 assert.Equal(t, testCase.Expected, testCase.Input[rawRange.Position:rawRange.End]) 145 } 146 }) 147 } 148 } 149 150 func TestParseWWWAutolink(t *testing.T) { 151 testCases := []struct { 152 Description string 153 Input string 154 Position int 155 Expected string 156 }{ 157 { 158 Description: "no link", 159 Input: "This is some text", 160 Position: 0, 161 Expected: "", 162 }, 163 { 164 Description: "link", 165 Input: "www.example.com and some text", 166 Position: 0, 167 Expected: "www.example.com", 168 }, 169 { 170 Description: "link with a path", 171 Input: "www.example.com/abcd and some text", 172 Position: 0, 173 Expected: "www.example.com/abcd", 174 }, 175 { 176 Description: "link with parameters", 177 Input: "www.example.com/abcd?foo=bar and some text", 178 Position: 0, 179 Expected: "www.example.com/abcd?foo=bar", 180 }, 181 { 182 Description: "link, not at start", 183 Input: "This is www.example.com and some text", 184 Position: 8, 185 Expected: "www.example.com", 186 }, 187 { 188 Description: "link with a path, not at start", 189 Input: "This is also www.example.com/abcd and some text", 190 Position: 13, 191 Expected: "www.example.com/abcd", 192 }, 193 { 194 Description: "link with parameters, not at start", 195 Input: "These are www.example.com/abcd?foo=bar and some text", 196 Position: 10, 197 Expected: "www.example.com/abcd?foo=bar", 198 }, 199 { 200 Description: "link with trailing characters", 201 Input: "This is www.example.com??", 202 Position: 8, 203 Expected: "www.example.com", 204 }, 205 { 206 Description: "link after current position", 207 Input: "This is some text and www.example.com", 208 Position: 0, 209 Expected: "", 210 }, 211 { 212 Description: "multiple links", 213 Input: "This is www.example.com/abcd and www.example.com/1234", 214 Position: 8, 215 Expected: "www.example.com/abcd", 216 }, 217 { 218 Description: "multiple links 2", 219 Input: "This is www.example.com/abcd and www.example.com/1234", 220 Position: 33, 221 Expected: "www.example.com/1234", 222 }, 223 { 224 Description: "link with brackets", 225 Input: "Go to www.example.com/my/page_(disambiguation) and some text", 226 Position: 6, 227 Expected: "www.example.com/my/page_(disambiguation)", 228 }, 229 { 230 Description: "link following other letters", 231 Input: "aaawww.example.com and some text", 232 Position: 3, 233 Expected: "", 234 }, 235 { 236 Description: "link in brackets", 237 Input: "(www.example.com)", 238 Position: 1, 239 Expected: "www.example.com", 240 }, 241 { 242 Description: "link in underscores", 243 Input: "_www.example.com_", 244 Position: 1, 245 Expected: "www.example.com", 246 }, 247 { 248 Description: "link in asterisks", 249 Input: "This is **www.example.com**", 250 Position: 10, 251 Expected: "www.example.com", 252 }, 253 { 254 Description: "link in strikethrough", 255 Input: "Those were ~~www.example.com~~", 256 Position: 13, 257 Expected: "www.example.com", 258 }, 259 { 260 Description: "using www1", 261 Input: "Our backup site is at www1.example.com/foo", 262 Position: 22, 263 Expected: "www1.example.com/foo", 264 }, 265 { 266 Description: "link with angle brackets", 267 Input: "<b>We use www2.example.com</b>", 268 Position: 10, 269 Expected: "www2.example.com", 270 }, 271 } 272 273 for _, testCase := range testCases { 274 t.Run(testCase.Description, func(t *testing.T) { 275 rawRange, ok := parseWWWAutolink(testCase.Input, testCase.Position) 276 277 if testCase.Expected == "" { 278 assert.False(t, ok) 279 assert.Equal(t, Range{0, 0}, rawRange) 280 } else { 281 assert.True(t, ok) 282 assert.Equal(t, testCase.Expected, testCase.Input[rawRange.Position:rawRange.End]) 283 } 284 }) 285 } 286 } 287 288 func TestTrimTrailingCharactersFromLink(t *testing.T) { 289 testCases := []struct { 290 Input string 291 Start int 292 End int 293 ExpectedEnd int 294 }{ 295 { 296 Input: "http://www.example.com", 297 ExpectedEnd: 22, 298 }, 299 { 300 Input: "http://www.example.com/abcd", 301 ExpectedEnd: 27, 302 }, 303 { 304 Input: "http://www.example.com/abcd/", 305 ExpectedEnd: 28, 306 }, 307 { 308 Input: "http://www.example.com/1234", 309 ExpectedEnd: 27, 310 }, 311 { 312 Input: "http://www.example.com/abcd?foo=bar", 313 ExpectedEnd: 35, 314 }, 315 { 316 Input: "http://www.example.com/abcd#heading", 317 ExpectedEnd: 35, 318 }, 319 { 320 Input: "http://www.example.com.", 321 ExpectedEnd: 22, 322 }, 323 { 324 Input: "http://www.example.com,", 325 ExpectedEnd: 22, 326 }, 327 { 328 Input: "http://www.example.com?", 329 ExpectedEnd: 22, 330 }, 331 { 332 Input: "http://www.example.com)", 333 ExpectedEnd: 22, 334 }, 335 { 336 Input: "http://www.example.com", 337 ExpectedEnd: 22, 338 }, 339 { 340 Input: "https://en.wikipedia.org/wiki/Dolphin_(disambiguation)", 341 ExpectedEnd: 54, 342 }, 343 { 344 Input: "https://en.wikipedia.org/wiki/Dolphin_(disambiguation", 345 ExpectedEnd: 53, 346 }, 347 { 348 Input: "https://en.wikipedia.org/wiki/Dolphin_(disambiguation))", 349 ExpectedEnd: 54, 350 }, 351 { 352 Input: "https://en.wikipedia.org/wiki/Dolphin_(disambiguation)_(disambiguation)", 353 ExpectedEnd: 71, 354 }, 355 { 356 Input: "https://en.wikipedia.org/wiki/Dolphin_(disambiguation_(disambiguation))", 357 ExpectedEnd: 71, 358 }, 359 { 360 Input: "http://www.example.com"", 361 ExpectedEnd: 22, 362 }, 363 { 364 Input: "this is a sentence containing http://www.example.com in it", 365 Start: 30, 366 End: 52, 367 ExpectedEnd: 52, 368 }, 369 { 370 Input: "this is a sentence containing http://www.example.com???", 371 Start: 30, 372 End: 55, 373 ExpectedEnd: 52, 374 }, 375 { 376 Input: "http://google.com/å", 377 ExpectedEnd: len("http://google.com/å"), 378 }, 379 { 380 Input: "http://google.com/å...", 381 ExpectedEnd: len("http://google.com/å"), 382 }, 383 { 384 Input: "This is http://google.com/å, a link, and http://google.com/å", 385 Start: 8, 386 End: len("This is http://google.com/å,"), 387 ExpectedEnd: len("This is http://google.com/å"), 388 }, 389 { 390 Input: "This is http://google.com/å, a link, and http://google.com/å", 391 Start: 41, 392 End: len("This is http://google.com/å, a link, and http://google.com/å"), 393 ExpectedEnd: len("This is http://google.com/å, a link, and http://google.com/å"), 394 }, 395 { 396 Input: "This is http://google.com/å, a link, and http://google.com/å.", 397 Start: 41, 398 End: len("This is http://google.com/å, a link, and http://google.com/å."), 399 ExpectedEnd: len("This is http://google.com/å, a link, and http://google.com/å"), 400 }, 401 { 402 Input: "http://🍄.ga/ http://x🍄.ga/", 403 Start: 0, 404 End: len("http://🍄.ga/"), 405 ExpectedEnd: len("http://🍄.ga/"), 406 }, 407 { 408 Input: "http://🍄.ga/ http://x🍄.ga/", 409 Start: len("http://🍄.ga/ "), 410 End: len("http://🍄.ga/ http://x🍄.ga/"), 411 ExpectedEnd: len("http://🍄.ga/ http://x🍄.ga/"), 412 }, 413 } 414 415 for _, testCase := range testCases { 416 t.Run(testCase.Input, func(t *testing.T) { 417 if testCase.End == 0 { 418 testCase.End = len(testCase.Input) - testCase.Start 419 } 420 421 assert.Equal(t, testCase.ExpectedEnd, trimTrailingCharactersFromLink(testCase.Input, testCase.Start, testCase.End)) 422 }) 423 } 424 } 425 426 func TestAutolinking(t *testing.T) { 427 // These tests are adapted from https://github.com/mattermost/commonmark.js/test/mattermost.txt. 428 // It is missing tests for: 429 // 1. Links surrounded by emphasis (emphasis not implemented on the server) 430 // 2. IPv6 addresses (not implemented on the server or by GitHub) 431 // 3. Custom URL schemes (not implemented) 432 433 for name, tc := range map[string]struct { 434 Markdown string 435 ExpectedHTML string 436 }{ 437 "valid-link-1": { 438 Markdown: `http://example.com`, 439 ExpectedHTML: `<p><a href="http://example.com">http://example.com</a></p>`, 440 }, 441 "valid-link-2": { 442 Markdown: `https://example.com`, 443 ExpectedHTML: `<p><a href="https://example.com">https://example.com</a></p>`, 444 }, 445 "valid-link-3": { 446 Markdown: `ftp://example.com`, 447 ExpectedHTML: `<p><a href="ftp://example.com">ftp://example.com</a></p>`, 448 }, 449 // "valid-link-4": { 450 // Markdown: `ts3server://example.com?port=9001`, 451 // ExpectedHTML: `<p><a href="ts3server://example.com?port=9001">ts3server://example.com?port=9001</a></p>`, 452 // }, 453 "valid-link-5": { 454 Markdown: `www.example.com`, 455 ExpectedHTML: `<p><a href="http://www.example.com">www.example.com</a></p>`, 456 }, 457 "valid-link-6": { 458 Markdown: `www.example.com/index`, 459 ExpectedHTML: `<p><a href="http://www.example.com/index">www.example.com/index</a></p>`, 460 }, 461 "valid-link-7": { 462 Markdown: `www.example.com/index.html`, 463 ExpectedHTML: `<p><a href="http://www.example.com/index.html">www.example.com/index.html</a></p>`, 464 }, 465 "valid-link-8": { 466 Markdown: `http://example.com/index/sub`, 467 ExpectedHTML: `<p><a href="http://example.com/index/sub">http://example.com/index/sub</a></p>`, 468 }, 469 "valid-link-9": { 470 Markdown: `www1.example.com`, 471 ExpectedHTML: `<p><a href="http://www1.example.com">www1.example.com</a></p>`, 472 }, 473 "valid-link-10": { 474 Markdown: `https://en.wikipedia.org/wiki/URLs#Syntax`, 475 ExpectedHTML: `<p><a href="https://en.wikipedia.org/wiki/URLs#Syntax">https://en.wikipedia.org/wiki/URLs#Syntax</a></p>`, 476 }, 477 "valid-link-11": { 478 Markdown: `https://groups.google.com/forum/#!msg`, 479 ExpectedHTML: `<p><a href="https://groups.google.com/forum/#!msg">https://groups.google.com/forum/#!msg</a></p>`, 480 }, 481 "valid-link-12": { 482 Markdown: `www.example.com/index?params=1`, 483 ExpectedHTML: `<p><a href="http://www.example.com/index?params=1">www.example.com/index?params=1</a></p>`, 484 }, 485 "valid-link-13": { 486 Markdown: `www.example.com/index?params=1&other=2`, 487 ExpectedHTML: `<p><a href="http://www.example.com/index?params=1&other=2">www.example.com/index?params=1&other=2</a></p>`, 488 }, 489 "valid-link-14": { 490 Markdown: `www.example.com/index?params=1;other=2`, 491 ExpectedHTML: `<p><a href="http://www.example.com/index?params=1;other=2">www.example.com/index?params=1;other=2</a></p>`, 492 }, 493 "valid-link-15": { 494 Markdown: `http://www.example.com/_/page`, 495 ExpectedHTML: `<p><a href="http://www.example.com/_/page">http://www.example.com/_/page</a></p>`, 496 }, 497 "valid-link-16": { 498 Markdown: `https://en.wikipedia.org/wiki/🐬`, 499 ExpectedHTML: `<p><a href="https://en.wikipedia.org/wiki/%F0%9F%90%AC">https://en.wikipedia.org/wiki/🐬</a></p>`, 500 }, 501 "valid-link-17": { 502 Markdown: `http://✪df.ws/1234`, 503 ExpectedHTML: `<p><a href="http://%E2%9C%AAdf.ws/1234">http://✪df.ws/1234</a></p>`, 504 }, 505 "valid-link-18": { 506 Markdown: `https://groups.google.com/forum/#!msg`, 507 ExpectedHTML: `<p><a href="https://groups.google.com/forum/#!msg">https://groups.google.com/forum/#!msg</a></p>`, 508 }, 509 "valid-link-19": { 510 Markdown: `https://пример.срб/пример-26/`, 511 ExpectedHTML: `<p><a href="https://%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80.%D1%81%D1%80%D0%B1/%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80-26/">https://пример.срб/пример-26/</a></p>`, 512 }, 513 "valid-link-20": { 514 Markdown: `mailto://test@example.com`, 515 ExpectedHTML: `<p><a href="mailto://test@example.com">mailto://test@example.com</a></p>`, 516 }, 517 "valid-link-21": { 518 Markdown: `tel://555-123-4567`, 519 ExpectedHTML: `<p><a href="tel://555-123-4567">tel://555-123-4567</a></p>`, 520 }, 521 522 "ip-address-1": { 523 Markdown: `http://127.0.0.1`, 524 ExpectedHTML: `<p><a href="http://127.0.0.1">http://127.0.0.1</a></p>`, 525 }, 526 "ip-address-2": { 527 Markdown: `http://192.168.1.1:4040`, 528 ExpectedHTML: `<p><a href="http://192.168.1.1:4040">http://192.168.1.1:4040</a></p>`, 529 }, 530 "ip-address-3": { 531 Markdown: `http://username:password@127.0.0.1`, 532 ExpectedHTML: `<p><a href="http://username:password@127.0.0.1">http://username:password@127.0.0.1</a></p>`, 533 }, 534 "ip-address-4": { 535 Markdown: `http://username:password@[2001:0:5ef5:79fb:303a:62d5:3312:ff42]:80`, 536 ExpectedHTML: `<p><a href="http://username:password@%5B2001:0:5ef5:79fb:303a:62d5:3312:ff42%5D:80">http://username:password@[2001:0:5ef5:79fb:303a:62d5:3312:ff42]:80</a></p>`, 537 }, 538 539 "link-with-brackets-1": { 540 Markdown: `https://en.wikipedia.org/wiki/Rendering_(computer_graphics)`, 541 ExpectedHTML: `<p><a href="https://en.wikipedia.org/wiki/Rendering_(computer_graphics)">https://en.wikipedia.org/wiki/Rendering_(computer_graphics)</a></p>`, 542 }, 543 "link-with-brackets-2": { 544 Markdown: `http://example.com/more_(than)_one_(parens)`, 545 ExpectedHTML: `<p><a href="http://example.com/more_(than)_one_(parens)">http://example.com/more_(than)_one_(parens)</a></p>`, 546 }, 547 "link-with-brackets-3": { 548 Markdown: `http://example.com/(something)?after=parens`, 549 ExpectedHTML: `<p><a href="http://example.com/(something)?after=parens">http://example.com/(something)?after=parens</a></p>`, 550 }, 551 "link-with-brackets-4": { 552 Markdown: `http://foo.com/unicode_(✪)_in_parens`, 553 ExpectedHTML: `<p><a href="http://foo.com/unicode_(%E2%9C%AA)_in_parens">http://foo.com/unicode_(✪)_in_parens</a></p>`, 554 }, 555 556 "inside-another-link-1": { 557 Markdown: `[www.example.com](https://example.com)`, 558 ExpectedHTML: `<p><a href="https://example.com">www.example.com</a></p>`, 559 }, 560 "inside-another-link-2": { 561 Markdown: `[http://www.example.com](https://example.com)`, 562 ExpectedHTML: `<p><a href="https://example.com">http://www.example.com</a></p>`, 563 }, 564 565 "link-in-sentence-1": { 566 Markdown: `(http://example.com)`, 567 ExpectedHTML: `<p>(<a href="http://example.com">http://example.com</a>)</p>`, 568 }, 569 "link-in-sentence-2": { 570 Markdown: `(see http://example.com)`, 571 ExpectedHTML: `<p>(see <a href="http://example.com">http://example.com</a>)</p>`, 572 }, 573 "link-in-sentence-3": { 574 Markdown: `(http://example.com watch this)`, 575 ExpectedHTML: `<p>(<a href="http://example.com">http://example.com</a> watch this)</p>`, 576 }, 577 "link-in-sentence-4": { 578 Markdown: `This is a sentence with a http://example.com in it.`, 579 ExpectedHTML: `<p>This is a sentence with a <a href="http://example.com">http://example.com</a> in it.</p>`, 580 }, 581 "link-in-sentence-5": { 582 Markdown: `This is a sentence with a [link](http://example.com) in it.`, 583 ExpectedHTML: `<p>This is a sentence with a <a href="http://example.com">link</a> in it.</p>`, 584 }, 585 "link-in-sentence-6": { 586 Markdown: `This is a sentence with a http://example.com/_/underscore in it.`, 587 ExpectedHTML: `<p>This is a sentence with a <a href="http://example.com/_/underscore">http://example.com/_/underscore</a> in it.</p>`, 588 }, 589 "link-in-sentence-7": { 590 Markdown: `This is a sentence with a link (http://example.com) in it.`, 591 ExpectedHTML: `<p>This is a sentence with a link (<a href="http://example.com">http://example.com</a>) in it.</p>`, 592 }, 593 "link-in-sentence-8": { 594 Markdown: `This is a sentence with a (https://en.wikipedia.org/wiki/Rendering_(computer_graphics)) in it.`, 595 ExpectedHTML: `<p>This is a sentence with a (<a href="https://en.wikipedia.org/wiki/Rendering_(computer_graphics)">https://en.wikipedia.org/wiki/Rendering_(computer_graphics)</a>) in it.</p>`, 596 }, 597 "link-in-sentence-9": { 598 Markdown: `This is a sentence with a http://192.168.1.1:4040 in it.`, 599 ExpectedHTML: `<p>This is a sentence with a <a href="http://192.168.1.1:4040">http://192.168.1.1:4040</a> in it.</p>`, 600 }, 601 "link-in-sentence-10": { 602 Markdown: `This is a link to http://example.com.`, 603 ExpectedHTML: `<p>This is a link to <a href="http://example.com">http://example.com</a>.</p>`, 604 }, 605 "link-in-sentence-11": { 606 Markdown: `This is a link to http://example.com*`, 607 ExpectedHTML: `<p>This is a link to <a href="http://example.com">http://example.com</a>*</p>`, 608 }, 609 "link-in-sentence-12": { 610 Markdown: `This is a link to http://example.com_`, 611 ExpectedHTML: `<p>This is a link to <a href="http://example.com">http://example.com</a>_</p>`, 612 }, 613 "link-in-sentence-13": { 614 Markdown: `This is a link containing http://example.com/something?with,commas,in,url, but not at the end`, 615 ExpectedHTML: `<p>This is a link containing <a href="http://example.com/something?with,commas,in,url">http://example.com/something?with,commas,in,url</a>, but not at the end</p>`, 616 }, 617 "link-in-sentence-14": { 618 Markdown: `This is a question about a link http://example.com?`, 619 ExpectedHTML: `<p>This is a question about a link <a href="http://example.com">http://example.com</a>?</p>`, 620 }, 621 622 "plt-7250-link-with-trailing-periods-1": { 623 Markdown: `http://example.com.`, 624 ExpectedHTML: `<p><a href="http://example.com">http://example.com</a>.</p>`, 625 }, 626 "plt-7250-link-with-trailing-periods-2": { 627 Markdown: `http://example.com...`, 628 ExpectedHTML: `<p><a href="http://example.com">http://example.com</a>...</p>`, 629 }, 630 "plt-7250-link-with-trailing-periods-3": { 631 Markdown: `http://example.com/foo.`, 632 ExpectedHTML: `<p><a href="http://example.com/foo">http://example.com/foo</a>.</p>`, 633 }, 634 "plt-7250-link-with-trailing-periods-4": { 635 Markdown: `http://example.com/foo...`, 636 ExpectedHTML: `<p><a href="http://example.com/foo">http://example.com/foo</a>...</p>`, 637 }, 638 "plt-7250-link-with-trailing-periods-5": { 639 Markdown: `http://example.com/foo.bar`, 640 ExpectedHTML: `<p><a href="http://example.com/foo.bar">http://example.com/foo.bar</a></p>`, 641 }, 642 "plt-7250-link-with-trailing-periods-6": { 643 Markdown: `http://example.com/foo...bar`, 644 ExpectedHTML: `<p><a href="http://example.com/foo...bar">http://example.com/foo...bar</a></p>`, 645 }, 646 647 "rn-319-www-link-as-part-of-word-1": { 648 Markdown: `testwww.example.com`, 649 ExpectedHTML: `<p>testwww.example.com</p>`, 650 }, 651 652 "mm-10180-link-containing-period-followed-by-non-letter-1": { 653 Markdown: `https://example.com/123.+Pagetitle`, 654 ExpectedHTML: `<p><a href="https://example.com/123.+Pagetitle">https://example.com/123.+Pagetitle</a></p>`, 655 }, 656 "mm-10180-link-containing-period-followed-by-non-letter-2": { 657 Markdown: `https://example.com/123.?Pagetitle`, 658 ExpectedHTML: `<p><a href="https://example.com/123.?Pagetitle">https://example.com/123.?Pagetitle</a></p>`, 659 }, 660 "mm-10180-link-containing-period-followed-by-non-letter-3": { 661 Markdown: `https://example.com/123.-Pagetitle`, 662 ExpectedHTML: `<p><a href="https://example.com/123.-Pagetitle">https://example.com/123.-Pagetitle</a></p>`, 663 }, 664 "mm-10180-link-containing-period-followed-by-non-letter-4": { 665 Markdown: `https://example.com/123._Pagetitle`, 666 ExpectedHTML: `<p><a href="https://example.com/123._Pagetitle">https://example.com/123._Pagetitle</a></p>`, 667 }, 668 "mm-10180-link-containing-period-followed-by-non-letter-5": { 669 Markdown: `https://example.com/123.+`, 670 ExpectedHTML: `<p><a href="https://example.com/123.+">https://example.com/123.+</a></p>`, 671 }, 672 "mm-10180-link-containing-period-followed-by-non-letter-6": { 673 Markdown: `https://example.com/123.?`, 674 ExpectedHTML: `<p><a href="https://example.com/123">https://example.com/123</a>.?</p>`, 675 }, 676 "mm-10180-link-containing-period-followed-by-non-letter-7": { 677 Markdown: `https://example.com/123.-`, 678 ExpectedHTML: `<p><a href="https://example.com/123.-">https://example.com/123.-</a></p>`, 679 }, 680 "mm-10180-link-containing-period-followed-by-non-letter-8": { 681 Markdown: `https://example.com/123._`, 682 ExpectedHTML: `<p><a href="https://example.com/123">https://example.com/123</a>._</p>`, 683 }, 684 } { 685 t.Run(name, func(t *testing.T) { 686 assert.Equal(t, tc.ExpectedHTML, RenderHTML(tc.Markdown)) 687 }) 688 } 689 }