markdown.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. "use strict";
  2. class opennamu_render_markdown {
  3. // Init Part
  4. constructor(
  5. render_part_id,
  6. render_part_id_after,
  7. render_part_id_add,
  8. doc_name
  9. ) {
  10. this.doc_data = document.getElementById(render_part_id_add + render_part_id).innerHTML;
  11. this.doc_data = this.doc_data.replace(/&/g, '&');
  12. this.doc_data = '<brStart>\n' + this.doc_data + '\n<brEnd>';
  13. this.doc_data.replace(/\r/g, '');
  14. this.doc_name = doc_name;
  15. this.parser_data_temp = {};
  16. this.parser_data_temp_other = {};
  17. this.parser_data_temp_other['toc'] = '';
  18. this.parser_data_temp_other['footnote'] = '';
  19. this.parser_data_temp_other['category'] = '';
  20. this.parser_data_js = [];
  21. this.parser_count = {};
  22. this.parser_count['parser'] = 0;
  23. this.parser_count['nowiki'] = 0;
  24. this.render_part_id_add = render_part_id_add;
  25. this.render_part_id_after = render_part_id_after;
  26. }
  27. // Func Part
  28. do_func_parser_to_text(data, parser_type = 'parser') {
  29. let parser_data_temp = this.parser_data_temp;
  30. let parser_match;
  31. if(parser_type === 'nowiki') {
  32. parser_match = /<(\/?nowiki[0-9]+Span)>/;
  33. } else {
  34. parser_match = /<(\/?render[0-9]+Span)>/;
  35. }
  36. while(data.match(parser_match)) {
  37. data = data.replace(parser_match, function(match, x1) {
  38. return parser_data_temp[x1];
  39. });
  40. }
  41. return data;
  42. }
  43. do_func_xss_encode(data) {
  44. data = data.replace(/"/g, '&quot;');
  45. data = data.replace(/</g, '&lt;');
  46. data = data.replace(/</g, '&gt;');
  47. return data;
  48. }
  49. do_func_xss_decode(data) {
  50. data = data.replace(/&#x27;/g, '\'');
  51. data = data.replace(/&quot;/g, '"');
  52. data = data.replace(/&lt;/g, '<');
  53. data = data.replace(/&gt;/g, '<');
  54. return data;
  55. }
  56. do_func_url_encode(data) {
  57. return encodeURIComponent(data);
  58. }
  59. // Render Part
  60. do_part_text() {
  61. let parser_count = this.parser_count['parser'];
  62. let parser_data_temp = this.parser_data_temp;
  63. this.doc_data = this.doc_data.replace(/~~((?:(?!~~).)+)~~/g, function(match, x1) {
  64. parser_count += 1;
  65. let parser_count_str = String(parser_count);
  66. parser_data_temp['render' + parser_count_str + 'Span'] = '<s>';
  67. parser_data_temp['/render' + parser_count_str + 'Span'] = '</s>';
  68. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  69. });
  70. this.doc_data = this.doc_data.replace(/\*\*((?:(?!\*\*).)+)\*\*/g, function(match, x1) {
  71. parser_count += 1;
  72. let parser_count_str = String(parser_count);
  73. parser_data_temp['render' + parser_count_str + 'Span'] = '<b>';
  74. parser_data_temp['/render' + parser_count_str + 'Span'] = '</b>';
  75. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  76. });
  77. this.doc_data = this.doc_data.replace(/__((?:(?!__).)+)__/g, function(match, x1) {
  78. parser_count += 1;
  79. let parser_count_str = String(parser_count);
  80. parser_data_temp['render' + parser_count_str + 'Span'] = '<b>';
  81. parser_data_temp['/render' + parser_count_str + 'Span'] = '</b>';
  82. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  83. });
  84. this.doc_data = this.doc_data.replace(/\*([^*]+)\*/g, function(match, x1) {
  85. parser_count += 1;
  86. let parser_count_str = String(parser_count);
  87. parser_data_temp['render' + parser_count_str + 'Span'] = '<i>';
  88. parser_data_temp['/render' + parser_count_str + 'Span'] = '</i>';
  89. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  90. });
  91. this.doc_data = this.doc_data.replace(/_([^_]+)_/g, function(match, x1) {
  92. parser_count += 1;
  93. let parser_count_str = String(parser_count);
  94. parser_data_temp['render' + parser_count_str + 'Span'] = '<i>';
  95. parser_data_temp['/render' + parser_count_str + 'Span'] = '</i>';
  96. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  97. });
  98. this.doc_data = this.doc_data.replace(/&lt;ins&gt;((?:(?!&lt;ins&gt;|&lt;\/ins&gt;).)+)&lt;\/ins&gt;/g, function(match, x1) {
  99. parser_count += 1;
  100. let parser_count_str = String(parser_count);
  101. parser_data_temp['render' + parser_count_str + 'Span'] = '<u>';
  102. parser_data_temp['/render' + parser_count_str + 'Span'] = '</u>';
  103. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  104. });
  105. this.doc_data = this.doc_data.replace(/&lt;sub&gt;((?:(?!&lt;sub&gt;|&lt;\/sub&gt;).)+)&lt;\/sub&gt;/g, function(match, x1) {
  106. parser_count += 1;
  107. let parser_count_str = String(parser_count);
  108. parser_data_temp['render' + parser_count_str + 'Span'] = '<sub>';
  109. parser_data_temp['/render' + parser_count_str + 'Span'] = '</sub>';
  110. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  111. });
  112. this.doc_data = this.doc_data.replace(/&lt;sup&gt;((?:(?!&lt;sup&gt;|&lt;\/sup&gt;).)+)&lt;\/sup&gt;/g, function(match, x1) {
  113. parser_count += 1;
  114. let parser_count_str = String(parser_count);
  115. parser_data_temp['render' + parser_count_str + 'Span'] = '<sup>';
  116. parser_data_temp['/render' + parser_count_str + 'Span'] = '</sup>';
  117. return '<render' + parser_count_str + 'Span>' + x1 + '</render' + parser_count_str + 'Span>';
  118. });
  119. this.parser_count['parser'] = parser_count;
  120. this.parser_data_temp = parser_data_temp;
  121. }
  122. do_part_heading() {
  123. let parser_count = this.parser_count['parser'];
  124. let parser_data_temp = this.parser_data_temp;
  125. let toc_data = '';
  126. let toc_list = [0, 0, 0, 0, 0, 0];
  127. let toc_regex = /\n(#{1,6})([^\n]+)\n/;
  128. while(this.doc_data.match(toc_regex)) {
  129. this.doc_data = this.doc_data.replace(toc_regex, function(match, x1, x2) {
  130. let toc_level = x1.length - 1;
  131. let toc_level_str = String(toc_level + 1);
  132. toc_list[toc_level] += 1;
  133. for(let for_a = toc_level + 1; for_a < 6; for_a++) {
  134. toc_list[for_a] = 0;
  135. }
  136. let toc_list_str = '';
  137. for(let for_a = 0; for_a < 6; for_a++) {
  138. if(toc_list[for_a] !== 0) {
  139. toc_list_str += String(toc_list[for_a]) + '.'
  140. }
  141. }
  142. return '\n<brEnd><h' + toc_level_str + '>' + toc_list_str + x2 + '</h' + toc_level_str + '><brStart>\n';
  143. });
  144. }
  145. this.parser_data_temp_other['toc'] = toc_data;
  146. }
  147. do_part_image() {
  148. let render_main = this;
  149. let render_part_id_add = this.render_part_id_add;
  150. let parser_count = this.parser_count['parser'];
  151. let parser_data_temp = this.parser_data_temp;
  152. this.doc_data = this.doc_data.replace(/!\[([^\[\]]*)\]\(([^\(\)]*)\)/g, function(match, x1, x2) {
  153. if(x1 === '' && x2 === '') {
  154. return '<imageBlink>';
  155. } else {
  156. if(x2 !== '' && x2.match(/^https?:\/\//)) {
  157. parser_count += 1;
  158. let parser_count_str = String(parser_count);
  159. let image_src = render_main.do_func_xss_encode(x2);
  160. let image_alt;
  161. if(x1 !== '') {
  162. image_alt = render_main.do_func_xss_encode(x1);
  163. } else {
  164. image_alt = image_src;
  165. }
  166. parser_data_temp['render' + parser_count_str + 'Span'] = '<img alt="' + image_alt + '" src="' + image_src + '">';
  167. parser_data_temp['/render' + parser_count_str + 'Span'] = '';
  168. return '<render' + parser_count_str + 'Span></render' + parser_count_str + 'Span>';
  169. } else {
  170. parser_count += 1;
  171. let parser_count_str = String(parser_count);
  172. parser_data_temp['render' + parser_count_str + 'Span'] = '<img>';
  173. parser_data_temp['/render' + parser_count_str + 'Span'] = '';
  174. return '<render' + parser_count_str + 'Span></render' + parser_count_str + 'Span>';
  175. }
  176. }
  177. });
  178. this.doc_data = this.doc_data.replace(/<imageBlink>/g, '![]()');
  179. this.parser_count['parser'] = parser_count;
  180. this.parser_data_temp = parser_data_temp;
  181. }
  182. do_part_link() {
  183. let render_main = this;
  184. let render_part_id_add = this.render_part_id_add;
  185. let parser_count = this.parser_count['parser'];
  186. let parser_data_temp = this.parser_data_temp;
  187. this.doc_data = this.doc_data.replace(/\[([^\[\]]*)\]\(([^\(\)]*)\)/g, function(match, x1, x2) {
  188. if(x1 === '' && x2 === '') {
  189. return '<linkBlink>';
  190. } else {
  191. if(x2 !== '' && x2.match(/^https?:\/\//)) {
  192. parser_count += 1;
  193. let parser_count_str = String(parser_count);
  194. let link_main = render_main.do_func_xss_encode(x2);;
  195. let link_sub;
  196. if(x1 === '') {
  197. link_sub = x2;
  198. } else {
  199. link_sub = x1;
  200. }
  201. parser_data_temp['render' + parser_count_str + 'Span'] = '<a href="' + link_main + '">';
  202. parser_data_temp['/render' + parser_count_str + 'Span'] = '</a>';
  203. return '<render' + parser_count_str + 'Span>' + link_sub + '</render' + parser_count_str + 'Span>';
  204. } else {
  205. parser_count += 1;
  206. let parser_count_str = String(parser_count);
  207. let link_main;
  208. let link_sub;
  209. let link_title;
  210. if(x2 === '') {
  211. link_main = x1;
  212. link_sub = x1;
  213. } else if(x1 === '') {
  214. link_main = x2;
  215. link_sub = x2;
  216. } else {
  217. link_main = x2;
  218. link_sub = x1;
  219. }
  220. link_title = render_main.do_func_xss_encode(link_main);
  221. link_main = render_main.do_func_xss_decode(link_main);
  222. link_main = render_main.do_func_url_encode(link_main);
  223. parser_data_temp['render' + parser_count_str + 'Span'] = '<a class="' + render_part_id_add + 'opennamuLink" title="' + link_title + '" href="/w/' + link_main + '">';
  224. parser_data_temp['/render' + parser_count_str + 'Span'] = '</a>';
  225. return '<render' + parser_count_str + 'Span>' + link_sub + '</render' + parser_count_str + 'Span>';
  226. }
  227. }
  228. });
  229. this.doc_data = this.doc_data.replace(/<linkBlink>/g, '[]()');
  230. this.parser_count['parser'] = parser_count;
  231. this.parser_data_temp = parser_data_temp;
  232. }
  233. do_part_footnote_list() {
  234. if(this.parser_data_temp_other['footnote'] !== '') {
  235. let footnote = '';
  236. footnote += '<ul id="footnote<underBar>data">';
  237. footnote += this.parser_data_temp_other['footnote'];
  238. footnote += '</ul>';
  239. this.parser_data_temp_other['footnote'] = '';
  240. return footnote;
  241. } else {
  242. return '';
  243. }
  244. }
  245. do_part_footnote() {
  246. let render_main = this;
  247. let parser_count = this.parser_count['parser'];
  248. let parser_data_temp = this.parser_data_temp;
  249. let parser_data_temp_other = this.parser_data_temp_other;
  250. let footnote_n = 0;
  251. let footnote_name_all = {};
  252. this.doc_data = this.doc_data.replace(/(?:\[\^((?:(?!\[\^| ).)*)(?: ((?:(?!\[\^|\]).)+))?\]|(\[fnote\(\)]))/g, function(match, x1, x2, x3) {
  253. if(x3 === undefined) {
  254. if(x1 === '' && x2 === undefined) {
  255. return '<footnoteBlink>';
  256. } else {
  257. footnote_n += 1;
  258. let footnote_name;
  259. let footnote_id = String(footnote_n);
  260. if(x1 === '') {
  261. footnote_name = footnote_id;
  262. } else {
  263. footnote_name = x1;
  264. }
  265. let footnote_content;
  266. if(x2 === undefined) {
  267. if(footnote_name_all[footnote_name]) {
  268. footnote_content = footnote_name_all[footnote_name];
  269. } else {
  270. footnote_content = '';
  271. footnote_name_all[footnote_name] = footnote_content;
  272. }
  273. } else {
  274. footnote_content = x2;
  275. footnote_name_all[footnote_name] = footnote_content;
  276. }
  277. let footnote_list = '';
  278. footnote_list += '<li>';
  279. footnote_list += '<a id="opennamuFnGo' + footnote_id + '" href="#opennamuFnIn' + footnote_id + '">'
  280. footnote_list += '(' + footnote_name + ')';
  281. footnote_list += '</a>';
  282. footnote_list += ' ';
  283. footnote_list += footnote_content;
  284. footnote_list += '</li>';
  285. parser_data_temp_other['footnote'] += footnote_list;
  286. parser_count += 1;
  287. let parser_count_str = String(parser_count);
  288. let footnote_data = '';
  289. footnote_data += '<sup>'
  290. footnote_data += '<a id="opennamuFnIn' + footnote_id + '" href="#opennamuFnGo' + footnote_id + '">';
  291. footnote_data += '(' + footnote_name + ')';
  292. footnote_data += '</a>';
  293. footnote_data += '</sup>';
  294. parser_data_temp['render' + parser_count_str + 'Span'] = footnote_data;
  295. parser_data_temp['/render' + parser_count_str + 'Span'] = '';
  296. return '<render' + parser_count_str + 'Span></render' + parser_count_str + 'Span>';
  297. }
  298. } else {
  299. return render_main.do_part_footnote_list();
  300. }
  301. });
  302. this.doc_data = this.doc_data.replace(/<footnoteBlink>/g, '[^]');
  303. this.doc_data += this.do_part_footnote_list();
  304. this.parser_count['parser'] = parser_count;
  305. this.parser_data_temp = parser_data_temp;
  306. this.parser_data_temp_other = parser_data_temp_other;
  307. }
  308. do_part_macro() {
  309. let render_main = this;
  310. let render_part_id_add = this.render_part_id_add;
  311. let parser_count = this.parser_count['parser'];
  312. let parser_data_temp = this.parser_data_temp;
  313. let parser_data_temp_other = this.parser_data_temp_other;
  314. this.doc_data = this.doc_data.replace(/\[([^\[\(<>]+)\(((?:(?!\(|\)\]|<|>).)+)\)\]/g, function(match, x1, x2) {
  315. if(x1 === 'anchor') {
  316. parser_count += 1;
  317. let parser_count_str = String(parser_count);
  318. let anchor_data = render_main.do_func_parser_to_text(x2, 'nowiki');
  319. anchor_data = render_main.do_func_xss_encode(anchor_data);
  320. parser_data_temp['render' + parser_count_str + 'Span'] = '<span id="' + anchor_data + '">';
  321. parser_data_temp['/render' + parser_count_str + 'Span'] = '</span>';
  322. return '<render' + parser_count_str + 'Span></render' + parser_count_str + 'Span>'
  323. } else if(x1 === 'category') {
  324. let category = x2.split(',');
  325. let category_data = render_main.do_func_parser_to_text(category[0], 'nowiki');
  326. let link_main = 'category:' + category_data;
  327. let link_title = render_main.do_func_xss_encode(link_main);
  328. link_main = render_main.do_func_xss_decode(link_main);
  329. link_main = render_main.do_func_url_encode(link_main);
  330. parser_data_temp_other['category'] += '<a class="' + render_part_id_add + 'opennamuLink" title="' + link_title + '" href="/w/' + link_main + '">';
  331. parser_data_temp_other['category'] += category_data;
  332. parser_data_temp_other['category'] += '</a>';
  333. parser_data_temp_other['category'] += ' | ';
  334. return '';
  335. } else if(x1 === 'toc') {
  336. return parser_data_temp_other['toc'];
  337. }
  338. else {
  339. return '';
  340. }
  341. });
  342. this.parser_count['parser'] = parser_count;
  343. this.parser_data_temp = parser_data_temp;
  344. this.parser_data_temp_other = parser_data_temp_other;
  345. }
  346. do_part_final() {
  347. this.doc_data = this.doc_data.replace(/<brStart>\n?/g, '');
  348. this.doc_data = this.doc_data.replace(/\n?<brEnd>/g, '');
  349. this.doc_data = this.doc_data.replace(/<underBar>/g, '_');
  350. this.doc_data = this.doc_data.replace(/\n/g, '<br>');
  351. if(this.parser_data_temp_other['category'] !== '') {
  352. let category = this.parser_data_temp_other['category'];
  353. category = category.replace(/ \| $/, '');
  354. this.doc_data += '<hr class="main_hr">';
  355. this.doc_data += '<div id="cate_all"><div id="cate">';
  356. this.doc_data += 'Category : ';
  357. this.doc_data += category;
  358. this.doc_data += '</div></div>';
  359. }
  360. }
  361. // Main Part
  362. do_main() {
  363. this.do_part_heading();
  364. this.do_part_footnote();
  365. this.do_part_macro();
  366. this.do_part_image();
  367. this.do_part_link();
  368. this.do_part_text();
  369. this.do_part_final();
  370. this.doc_data = this.do_func_parser_to_text(this.doc_data);
  371. document.getElementById(this.render_part_id_add + this.render_part_id_after).innerHTML = this.doc_data;
  372. for(let x1 in this.parser_data_js) {
  373. eval(this.parser_data_js[x1]);
  374. }
  375. new opennamu_render_wiki(
  376. render_part_id_add = this.render_part_id_add
  377. ).do_main();
  378. }
  379. }