markdown-it-container.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*! markdown-it-container 2.0.0 https://github.com//markdown-it/markdown-it-container @license MIT */(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.markdownitContainer = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  2. // Process block-level custom containers
  3. //
  4. 'use strict';
  5. module.exports = function container_plugin(md, name, options) {
  6. function validateDefault(params) {
  7. return params.trim().split(' ', 2)[0] === name;
  8. }
  9. function renderDefault(tokens, idx, _options, env, self) {
  10. // add a class to the opening tag
  11. if (tokens[idx].nesting === 1) {
  12. tokens[idx].attrPush([ 'class', name ]);
  13. }
  14. return self.renderToken(tokens, idx, _options, env, self);
  15. }
  16. options = options || {};
  17. var min_markers = 3,
  18. marker_str = options.marker || ':',
  19. marker_char = marker_str.charCodeAt(0),
  20. marker_len = marker_str.length,
  21. validate = options.validate || validateDefault,
  22. render = options.render || renderDefault;
  23. function container(state, startLine, endLine, silent) {
  24. var pos, nextLine, marker_count, markup, params, token,
  25. old_parent, old_line_max,
  26. auto_closed = false,
  27. start = state.bMarks[startLine] + state.tShift[startLine],
  28. max = state.eMarks[startLine];
  29. // Check out the first character quickly,
  30. // this should filter out most of non-containers
  31. //
  32. if (marker_char !== state.src.charCodeAt(start)) { return false; }
  33. // Check out the rest of the marker string
  34. //
  35. for (pos = start + 1; pos <= max; pos++) {
  36. if (marker_str[(pos - start) % marker_len] !== state.src[pos]) {
  37. break;
  38. }
  39. }
  40. marker_count = Math.floor((pos - start) / marker_len);
  41. if (marker_count < min_markers) { return false; }
  42. pos -= (pos - start) % marker_len;
  43. markup = state.src.slice(start, pos);
  44. params = state.src.slice(pos, max);
  45. if (!validate(params)) { return false; }
  46. // Since start is found, we can report success here in validation mode
  47. //
  48. if (silent) { return true; }
  49. // Search for the end of the block
  50. //
  51. nextLine = startLine;
  52. for (;;) {
  53. nextLine++;
  54. if (nextLine >= endLine) {
  55. // unclosed block should be autoclosed by end of document.
  56. // also block seems to be autoclosed by end of parent
  57. break;
  58. }
  59. start = state.bMarks[nextLine] + state.tShift[nextLine];
  60. max = state.eMarks[nextLine];
  61. if (start < max && state.sCount[nextLine] < state.blkIndent) {
  62. // non-empty line with negative indent should stop the list:
  63. // - ```
  64. // test
  65. break;
  66. }
  67. if (marker_char !== state.src.charCodeAt(start)) { continue; }
  68. if (state.sCount[nextLine] - state.blkIndent >= 4) {
  69. // closing fence should be indented less than 4 spaces
  70. continue;
  71. }
  72. for (pos = start + 1; pos <= max; pos++) {
  73. if (marker_str[(pos - start) % marker_len] !== state.src[pos]) {
  74. break;
  75. }
  76. }
  77. // closing code fence must be at least as long as the opening one
  78. if (Math.floor((pos - start) / marker_len) < marker_count) { continue; }
  79. // make sure tail has spaces only
  80. pos -= (pos - start) % marker_len;
  81. pos = state.skipSpaces(pos);
  82. if (pos < max) { continue; }
  83. // found!
  84. auto_closed = true;
  85. break;
  86. }
  87. old_parent = state.parentType;
  88. old_line_max = state.lineMax;
  89. state.parentType = 'container';
  90. // this will prevent lazy continuations from ever going past our end marker
  91. state.lineMax = nextLine;
  92. token = state.push('container_' + name + '_open', 'div', 1);
  93. token.markup = markup;
  94. token.block = true;
  95. token.info = params;
  96. token.map = [ startLine, nextLine ];
  97. state.md.block.tokenize(state, startLine + 1, nextLine);
  98. token = state.push('container_' + name + '_close', 'div', -1);
  99. token.markup = state.src.slice(start, pos);
  100. token.block = true;
  101. state.parentType = old_parent;
  102. state.lineMax = old_line_max;
  103. state.line = nextLine + (auto_closed ? 1 : 0);
  104. return true;
  105. }
  106. md.block.ruler.before('fence', 'container_' + name, container, {
  107. alt: [ 'paragraph', 'reference', 'blockquote', 'list' ]
  108. });
  109. md.renderer.rules['container_' + name + '_open'] = render;
  110. md.renderer.rules['container_' + name + '_close'] = render;
  111. };
  112. },{}]},{},[1])(1)
  113. });