v2exMarkdown

为v2ex而生的markdown渲染

当前为 2018-08-13 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name v2exMarkdown
  3. // @version 0.66
  4. // @description 为v2ex而生的markdown渲染
  5. // @author hundan
  6. // @match https://*.v2ex.com/t/*
  7. // @require https://cdn.staticfile.org/showdown/1.8.6/showdown.min.js
  8. // @require https://cdn.staticfile.org/fancybox/3.3.5/jquery.fancybox.min.js
  9. // @grant none
  10. // @namespace https://github.com/hundan2020/v2exMarkdown
  11. // ==/UserScript==
  12.  
  13.  
  14. (function () {
  15. // jquery.js和highlight.js都由v2ex自身提供,不再向外部重复请求
  16. // markdown处理
  17. var preFix = function(rawReply){
  18. var picRe = function(reply){
  19. reply = reply.replace(/(?:!\[.*?\])?!\[.*?\]\(\s*((?:https?)?:\/\/i\.loli\.net\/\d{4}\/\d{2}\/\d{2}\/[a-z0-9]+.[a-z]+)\)|(https:\/\/i\.loli\.net\/\d{4}\/\d{2}\/\d{2}\/[a-z0-9]+.[a-z]+)/ig, '![]( ' + encodeURI('$1$2') + ' )'); // sm.ms
  20. reply = reply.replace(/(?:!\[.*?\])?!\[.*?\]\(\s*((?:https?)?:\/\/imgurl\.org\/temp\/\d{4}\/[a-z0-9]+\.[a-z0-9]+)\)|(https?:\/\/imgurl\.org\/temp\/\d{4}\/[a-z0-9]+\.[a-z0-9]+)/ig, '![]( ' + encodeURI('$1$2') + ' )'); // 小z图床
  21. reply = reply.replace(/(?<!http:|https:)\/\/([a-z0-9]+\.sinaimg.cn\/(?:[a-z]+)\/[a-z0-9]+\.(?:jpg|png|gif|bmp))/ig, '![]( ' + encodeURI('https://$1') + ' )'); // 新浪微博不规则图片链接
  22. return reply;
  23. }
  24. var xssFilter = function(reply){
  25. var sReply = reply;
  26. sReply = sReply.replace(/(!?\[.*?\]\(\s*?javascript.*?\))/igs, '`$1`');
  27. return sReply;
  28. }
  29. var fixedReply = rawReply;
  30. fixedReply = fixedReply.replace(/#(\d{1,3}\s)/ig, '&#x23;$1 '); // 避免楼层号加粗 safe
  31. // debugger;
  32. fixedReply = fixedReply.replace(/(!\[(\S*?)\]\(\s+?)<a target="_blank" href="(\S+?)".*?><img src="(\S+?)" class="embedded_image".*?><\/a>\)+/ig, '![$2]($3)'); // 正常显示的图片处理 safe
  33. fixedReply = fixedReply.replace(/&lt;img src="(.+?)" \/&gt;/ig, '$1'); // 不规则图片链接处理 safe
  34. fixedReply = fixedReply.replace(/@<a href="\/member\/(\S+?)">(\S+?)<\/a>/ig, '@[$1](/member/$2)'); // 论坛内@处理,考虑到代码段中的@应当正常显示 safe
  35. fixedReply = fixedReply.replace(/<a target="_blank" href="(\/t\/\d+)"\s*?(?:rel="nofollow")?>\/t\/\d+<\/a>/ig, '[$1]($1)'); // 论坛内链处理,考虑到在代码段中应当正常显示 safe
  36. // debugger;
  37. fixedReply = fixedReply.replace(/<a.*? href="(\S+?)".*?>(\S+?)<\/a>/ig, '$2'); // 链接处理 safe
  38. fixedReply = fixedReply.replace(/\[!\[(\S+?)\]\(\s*(\S+?)\)\]\(\s*\S+?\)/ig, '![$1]($2)'); // 不规则图片链接处理,不规则案例见 `https://www.v2ex.com/t/463469#r_5792042`
  39. fixedReply = fixedReply.replace(/(\n)?<br *\/?>/ig, "\n"); // 换行处理,避免多行代码无法正常工作 safe
  40. fixedReply = picRe(fixedReply);
  41. fixedReply = xssFilter(fixedReply);
  42. // 不安全的是,从原生markdown格式转变到html
  43. return fixedReply;
  44. }
  45. var endFix = function(markedReply){
  46. var fixedReply = markedReply;
  47. fixedReply = fixedReply.replace(/\n/ig, '<br />'); //safe markdown软回车转硬回车
  48. fixedReply = fixedReply.replace(/(<\/ul>|<\/li>|<\/p>|<\/table>|<\/h\d>)\s*<br\s*\/?>/ig, '$1'); // safe 表格换行删除
  49. fixedReply = fixedReply.replace(/<br\s*\/?>(<li>|<ul>|<p>|<table>|<h\d>)/ig, '$1'); // safe 表格换行删除
  50. fixedReply = fixedReply.replace(/(<\/?table>|<\/?tbody>|<\/?thead>|<\/?tr>|<\/?th>|<\/?td>)<br\s*\/?>/ig, '$1'); // safe 表格换行删除
  51. fixedReply = fixedReply.replace(/(<br\s*\/?>\s*){2,}/ig, '<br />'); // safe 多重换行转单行
  52. fixedReply = fixedReply.replace(/@\[(\S+?)\]\(\/member\/\S+\)/ig, '@$1'); // 代码段中的@ 还原
  53. // debugger;
  54. fixedReply = fixedReply.replace(/\[(\/t\/\d+)\]\(\/t\/\d+\)/ig, '$1'); // 代码段中的内链还原
  55. fixedReply = fixedReply.replace(/&amp;/ig, '&'); // 对重复转义的 & 进行还原,而不必对<>进行操作,有效的避免了XSS发生
  56. return fixedReply;
  57. }
  58. var processMarkdown = function(){
  59. $("div.reply_content").each(function () {
  60. var reply = $(this)[0];
  61. var rawReply = reply.innerHTML;
  62. var converter = new showdown.Converter({
  63. omitExtraWLInCodeBlocks: true,
  64. parseImgDimensions: true,
  65. simplifiedAutoLink: true,
  66. literalMidWordUnderscores: true,
  67. strikethrough: true,
  68. tables: true,
  69. ghCodeBlocks: true,
  70. tasklists: true,
  71. smoothLivePreview: true,
  72. ghCompatibleHeaderId: true,
  73. encodeEmails: true,
  74. emoji: true
  75. });
  76. var markedReply = converter.makeHtml(preFix(rawReply));
  77. reply.innerHTML = endFix(markedReply);
  78. reply.className = 'reply_content markdown_body';
  79. // 开启代码高亮
  80. hljs.configure({useBR: true});
  81. $('div.reply_content code').each(function(i, block) {
  82. hljs.highlightBlock(block);
  83. });
  84. });
  85. }
  86. processMarkdown();
  87. // 加载看图插件
  88. function loadStyle(url){
  89. var link = document.createElement('link');
  90. link.type = 'text/css';
  91. link.rel = 'stylesheet';
  92. link.href = url;
  93. var head = document.getElementsByTagName('head')[0];
  94. head.appendChild(link);
  95. }
  96. loadStyle('https://cdn.staticfile.org/fancybox/3.3.5/jquery.fancybox.min.css');
  97. var a_wrap = $('<a></a>');
  98. var imgs = $('.markdown_body img');
  99. imgs.wrap('<a></a>');
  100. $.each(imgs, function (i, j) {
  101. $(j).css({'max-height':'25vh'});
  102. $(j).parent().attr('id', 'img' + i).attr('href', $(this).attr('src'));
  103. $("#img" + i).fancybox({
  104. 'zoomSpeedIn': 300,
  105. 'zoomSpeedOut': 300,
  106. 'overlayShow': false,
  107. 'overlayOpacity': 0.3
  108. })
  109. });
  110. // 添加楼主标记
  111. let author = $('#Main > div:nth-child(2) > div.header > small > a').text();
  112. $('table > tbody > tr > td > strong > a').each(function(){
  113. debugger;
  114. if ($(this).text() == author){
  115. var sign = $('<span></span>');
  116. sign.text('楼主');
  117. sign.css({"padding": "1px 5px", "margin": "0 6px", "font-size": "x-small", "color": "#777", "border-radius": "8px", "border": "1px solid"});
  118. // sign.appendTo();
  119. $(this).parent().after(sign);
  120. //$(this).parent().append()
  121. }
  122. //$(this).css({"padding": "1px 6px;"},{"margin": "0 6px;"},{"font-size": "x-small"},{"color": "#05a1ff;"},{"border-radius": "9px;"},{"border": "1px solid;"});
  123. });
  124. console.clear();
  125. console.log("\n\n\n Thanks for using my script~\n\n\n\n");
  126. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址