markdown-it-deflist.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*!
  2. markdown-it-deflist
  3. https://github.com/markdown-it/markdown-it-deflist
  4. */
  5. (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.markdownitDeflist = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({"/":[function(require,module,exports){
  6. // Process definition lists
  7. //
  8. 'use strict';
  9. module.exports = function deflist_plugin(md) {
  10. var isSpace = md.utils.isSpace;
  11. // Search `[:~][\n ]`, returns next pos after marker on success
  12. // or -1 on fail.
  13. function skipMarker(state, line) {
  14. var pos, marker,
  15. start = state.bMarks[line] + state.tShift[line],
  16. max = state.eMarks[line];
  17. if (start >= max) { return -1; }
  18. // Check bullet
  19. marker = state.src.charCodeAt(start++);
  20. if (marker !== 0x7E/* ~ */ && marker !== 0x3A/* : */) { return -1; }
  21. pos = state.skipSpaces(start);
  22. // require space after ":"
  23. if (start === pos) { return -1; }
  24. // no empty definitions, e.g. " : "
  25. if (pos >= max) { return -1; }
  26. return start;
  27. }
  28. function markTightParagraphs(state, idx) {
  29. var i, l,
  30. level = state.level + 2;
  31. for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
  32. if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
  33. state.tokens[i + 2].hidden = true;
  34. state.tokens[i].hidden = true;
  35. i += 2;
  36. }
  37. }
  38. }
  39. function deflist(state, startLine, endLine, silent) {
  40. var ch,
  41. contentStart,
  42. ddLine,
  43. dtLine,
  44. itemLines,
  45. listLines,
  46. listTokIdx,
  47. max,
  48. nextLine,
  49. offset,
  50. oldDDIndent,
  51. oldIndent,
  52. oldParentType,
  53. oldSCount,
  54. oldTShift,
  55. oldTight,
  56. pos,
  57. prevEmptyEnd,
  58. tight,
  59. token;
  60. if (silent) {
  61. // quirk: validation mode validates a dd block only, not a whole deflist
  62. if (state.ddIndent < 0) { return false; }
  63. return skipMarker(state, startLine) >= 0;
  64. }
  65. nextLine = startLine + 1;
  66. if (nextLine >= endLine) { return false; }
  67. if (state.isEmpty(nextLine)) {
  68. nextLine++;
  69. if (nextLine >= endLine) { return false; }
  70. }
  71. if (state.sCount[nextLine] < state.blkIndent) { return false; }
  72. contentStart = skipMarker(state, nextLine);
  73. if (contentStart < 0) { return false; }
  74. // Start list
  75. listTokIdx = state.tokens.length;
  76. tight = true;
  77. token = state.push('dl_open', 'dl', 1);
  78. token.map = listLines = [ startLine, 0 ];
  79. //
  80. // Iterate list items
  81. //
  82. dtLine = startLine;
  83. ddLine = nextLine;
  84. // One definition list can contain multiple DTs,
  85. // and one DT can be followed by multiple DDs.
  86. //
  87. // Thus, there is two loops here, and label is
  88. // needed to break out of the second one
  89. //
  90. /*eslint no-labels:0,block-scoped-var:0*/
  91. OUTER:
  92. for (;;) {
  93. prevEmptyEnd = false;
  94. token = state.push('dt_open', 'dt', 1);
  95. token.map = [ dtLine, dtLine ];
  96. token = state.push('inline', '', 0);
  97. token.map = [ dtLine, dtLine ];
  98. token.content = state.getLines(dtLine, dtLine + 1, state.blkIndent, false).trim();
  99. token.children = [];
  100. token = state.push('dt_close', 'dt', -1);
  101. for (;;) {
  102. token = state.push('dd_open', 'dd', 1);
  103. token.map = itemLines = [ nextLine, 0 ];
  104. pos = contentStart;
  105. max = state.eMarks[ddLine];
  106. offset = state.sCount[ddLine] + contentStart - (state.bMarks[ddLine] + state.tShift[ddLine]);
  107. while (pos < max) {
  108. ch = state.src.charCodeAt(pos);
  109. if (isSpace(ch)) {
  110. if (ch === 0x09) {
  111. offset += 4 - offset % 4;
  112. } else {
  113. offset++;
  114. }
  115. } else {
  116. break;
  117. }
  118. pos++;
  119. }
  120. contentStart = pos;
  121. oldTight = state.tight;
  122. oldDDIndent = state.ddIndent;
  123. oldIndent = state.blkIndent;
  124. oldTShift = state.tShift[ddLine];
  125. oldSCount = state.sCount[ddLine];
  126. oldParentType = state.parentType;
  127. state.blkIndent = state.ddIndent = state.sCount[ddLine] + 2;
  128. state.tShift[ddLine] = contentStart - state.bMarks[ddLine];
  129. state.sCount[ddLine] = offset;
  130. state.tight = true;
  131. state.parentType = 'deflist';
  132. state.md.block.tokenize(state, ddLine, endLine, true);
  133. // If any of list item is tight, mark list as tight
  134. if (!state.tight || prevEmptyEnd) {
  135. tight = false;
  136. }
  137. // Item become loose if finish with empty line,
  138. // but we should filter last element, because it means list finish
  139. prevEmptyEnd = (state.line - ddLine) > 1 && state.isEmpty(state.line - 1);
  140. state.tShift[ddLine] = oldTShift;
  141. state.sCount[ddLine] = oldSCount;
  142. state.tight = oldTight;
  143. state.parentType = oldParentType;
  144. state.blkIndent = oldIndent;
  145. state.ddIndent = oldDDIndent;
  146. token = state.push('dd_close', 'dd', -1);
  147. itemLines[1] = nextLine = state.line;
  148. if (nextLine >= endLine) { break OUTER; }
  149. if (state.sCount[nextLine] < state.blkIndent) { break OUTER; }
  150. contentStart = skipMarker(state, nextLine);
  151. if (contentStart < 0) { break; }
  152. ddLine = nextLine;
  153. // go to the next loop iteration:
  154. // insert DD tag and repeat checking
  155. }
  156. if (nextLine >= endLine) { break; }
  157. dtLine = nextLine;
  158. if (state.isEmpty(dtLine)) { break; }
  159. if (state.sCount[dtLine] < state.blkIndent) { break; }
  160. ddLine = dtLine + 1;
  161. if (ddLine >= endLine) { break; }
  162. if (state.isEmpty(ddLine)) { ddLine++; }
  163. if (ddLine >= endLine) { break; }
  164. if (state.sCount[ddLine] < state.blkIndent) { break; }
  165. contentStart = skipMarker(state, ddLine);
  166. if (contentStart < 0) { break; }
  167. // go to the next loop iteration:
  168. // insert DT and DD tags and repeat checking
  169. }
  170. // Finilize list
  171. token = state.push('dl_close', 'dl', -1);
  172. listLines[1] = nextLine;
  173. state.line = nextLine;
  174. // mark paragraphs tight if needed
  175. if (tight) {
  176. markTightParagraphs(state, listTokIdx);
  177. }
  178. return true;
  179. }
  180. md.block.ruler.before('paragraph', 'deflist', deflist, { alt: [ 'paragraph', 'reference', 'blockquote' ] });
  181. };
  182. },{}]},{},[])("/")
  183. });