|
1 | 1 | <!doctype html> |
2 | 2 |
|
3 | 3 | <html> |
4 | | -<markdown-html version="1.16.0" author="PJ568" repo="https://github.com/PJ-568/markdown.html" |
| 4 | +<markdown-html version="1.17.0" author="PJ568" repo="https://github.com/PJ-568/markdown.html" |
5 | 5 | license="CC BY-SA 4.0 International"></markdown-html> |
6 | 6 |
|
7 | 7 | <head> |
|
283 | 283 | return mdPath; |
284 | 284 | } |
285 | 285 |
|
| 286 | + // 判断链接是否为外链 |
| 287 | + function isExternalLink(url) { |
| 288 | + if (!url || typeof url !== 'string') return false; |
| 289 | + |
| 290 | + //// 排除特殊协议 |
| 291 | + const excludedProtocols = ['#', 'javascript:', 'mailto:', 'tel:', 'data:']; |
| 292 | + if (excludedProtocols.some(proto => url.startsWith(proto))) { |
| 293 | + return false; |
| 294 | + } |
| 295 | + |
| 296 | + try { |
| 297 | + const currentUrl = new URL(window.location.href); |
| 298 | + const targetUrl = new URL(url, currentUrl.origin); |
| 299 | + |
| 300 | + //// 排除非 HTTP(S) 协议 |
| 301 | + if (!['http:', 'https:'].includes(targetUrl.protocol)) return false; |
| 302 | + |
| 303 | + //// 域名统一转小写比较 |
| 304 | + const currentHost = currentUrl.hostname.toLowerCase(); |
| 305 | + const targetHost = targetUrl.hostname.toLowerCase(); |
| 306 | + |
| 307 | + return currentHost !== targetHost; |
| 308 | + } catch (e) { |
| 309 | + return false; |
| 310 | + } |
| 311 | + } |
| 312 | + |
286 | 313 | // 判断路径是否为相对路径 |
287 | 314 | function isRelativePath(path) { |
288 | | - return !path.match(/^\//); |
| 315 | + return !path.match(/^\//); //// 不以 / 开头 |
289 | 316 | } |
290 | 317 |
|
291 | 318 | // 处理错误 |
|
454 | 481 | links.forEach(link => { |
455 | 482 | const linkText = link.match(/\[.*\]/)[0].slice(1, -1); |
456 | 483 | var linkHref = link.match(/\(.*\)/)[0].slice(1, -1); |
457 | | - if (isRelativePath(linkHref)) { |
| 484 | + if (isExternalLink(linkHref)) { |
| 485 | + ; |
| 486 | + } else if (isRelativePath(linkHref)) { |
458 | 487 | if (pValue) { |
459 | 488 | linkHref = getDirectory(mdPath) + linkHref; |
460 | 489 | } else { |
|
466 | 495 | markdown_content = markdown_content.replace(link, newLink); |
467 | 496 | }); |
468 | 497 | } |
| 498 | + const images = markdown_content.match(/!\[.*\]\(.*\)/g); |
| 499 | + if (images) { |
| 500 | + images.forEach(image => { |
| 501 | + const imageText = image.match(/\[.*\]/)[0].slice(1, -1); |
| 502 | + var imageHref = image.match(/\(.*\)/)[0].slice(1, -1); |
| 503 | + if (isExternalLink(imageHref)) { |
| 504 | + ; |
| 505 | + } else if (isRelativePath(imageHref)) { |
| 506 | + if (pValue) { |
| 507 | + imageHref = getDirectory(mdPath) + imageHref; |
| 508 | + } else { |
| 509 | + imageHref = getPath() + imageHref; |
| 510 | + } |
| 511 | + imageHref = new URL(imageHref, 'http://example.com').pathname; |
| 512 | + } |
| 513 | + const newImage = ``; |
| 514 | + markdown_content = markdown_content.replace(image, newImage); |
| 515 | + }); |
| 516 | + } |
469 | 517 | var content = marked.parse(markdown_content); |
470 | 518 | if (content === '') { |
471 | 519 | content = '<i>空文件</i>'; |
|
625 | 673 | // console.error(`ID 为 ${targetId} 的元素不存在。`); |
626 | 674 | // } |
627 | 675 | // } |
628 | | - } else if (event.target.closest('.content a:not([href^="?"]):not([href^="#"]):not([href^="javascript:"])')) { |
629 | | - const link = event.target.closest('a'); |
630 | | - if (link && link.href) { |
631 | | - window.open(link.href, '_blank'); |
| 676 | + } else if (event.target.closest('.content a[href]:not([href=""])')) { |
| 677 | + const href = event.target.getAttribute('href'); |
| 678 | + if (isExternalLink(href)) { |
| 679 | + window.open(href, '_blank'); |
632 | 680 | event.preventDefault(); |
633 | | - return; |
634 | 681 | } |
635 | 682 | } |
636 | 683 | }); |
|
0 commit comments