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