html_block.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // HTML block
  2. 'use strict';
  3. var block_names = require('../common/html_blocks');
  4. var HTML_OPEN_CLOSE_TAG_RE = require('../common/html_re').HTML_OPEN_CLOSE_TAG_RE;
  5. // An array of opening and corresponding closing sequences for html tags,
  6. // last argument defines whether it can terminate a paragraph or not
  7. //
  8. var HTML_SEQUENCES = [
  9. [ /^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true ],
  10. [ /^<!--/, /-->/, true ],
  11. [ /^<\?/, /\?>/, true ],
  12. [ /^<![A-Z]/, />/, true ],
  13. [ /^<!\[CDATA\[/, /\]\]>/, true ],
  14. [ new RegExp('^</?(' + block_names.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true ],
  15. [ new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false ]
  16. ];
  17. module.exports = function html_block(state, startLine, endLine, silent) {
  18. var i, nextLine, token, lineText,
  19. pos = state.bMarks[startLine] + state.tShift[startLine],
  20. max = state.eMarks[startLine];
  21. // if it's indented more than 3 spaces, it should be a code block
  22. if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
  23. if (!state.md.options.html) { return false; }
  24. if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
  25. lineText = state.src.slice(pos, max);
  26. for (i = 0; i < HTML_SEQUENCES.length; i++) {
  27. if (HTML_SEQUENCES[i][0].test(lineText)) { break; }
  28. }
  29. if (i === HTML_SEQUENCES.length) { return false; }
  30. if (silent) {
  31. // true if this sequence can be a terminator, false otherwise
  32. return HTML_SEQUENCES[i][2];
  33. }
  34. nextLine = startLine + 1;
  35. // If we are here - we detected HTML block.
  36. // Let's roll down till block end.
  37. if (!HTML_SEQUENCES[i][1].test(lineText)) {
  38. for (; nextLine < endLine; nextLine++) {
  39. if (state.sCount[nextLine] < state.blkIndent) { break; }
  40. pos = state.bMarks[nextLine] + state.tShift[nextLine];
  41. max = state.eMarks[nextLine];
  42. lineText = state.src.slice(pos, max);
  43. if (HTML_SEQUENCES[i][1].test(lineText)) {
  44. if (lineText.length !== 0) { nextLine++; }
  45. break;
  46. }
  47. }
  48. }
  49. state.line = nextLine;
  50. token = state.push('html_block', '', 0);
  51. token.map = [ startLine, nextLine ];
  52. token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
  53. return true;
  54. };