paragraph.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. 'use strict';
  2. var trim = require('trim');
  3. var decimal = require('is-decimal');
  4. var trimTrailingLines = require('trim-trailing-lines');
  5. var interrupt = require('../util/interrupt');
  6. module.exports = paragraph;
  7. var C_NEWLINE = '\n';
  8. var C_TAB = '\t';
  9. var C_SPACE = ' ';
  10. var TAB_SIZE = 4;
  11. /* Tokenise paragraph. */
  12. function paragraph(eat, value, silent) {
  13. var self = this;
  14. var settings = self.options;
  15. var commonmark = settings.commonmark;
  16. var gfm = settings.gfm;
  17. var tokenizers = self.blockTokenizers;
  18. var interruptors = self.interruptParagraph;
  19. var index = value.indexOf(C_NEWLINE);
  20. var length = value.length;
  21. var position;
  22. var subvalue;
  23. var character;
  24. var size;
  25. var now;
  26. while (index < length) {
  27. /* Eat everything if there’s no following newline. */
  28. if (index === -1) {
  29. index = length;
  30. break;
  31. }
  32. /* Stop if the next character is NEWLINE. */
  33. if (value.charAt(index + 1) === C_NEWLINE) {
  34. break;
  35. }
  36. /* In commonmark-mode, following indented lines
  37. * are part of the paragraph. */
  38. if (commonmark) {
  39. size = 0;
  40. position = index + 1;
  41. while (position < length) {
  42. character = value.charAt(position);
  43. if (character === C_TAB) {
  44. size = TAB_SIZE;
  45. break;
  46. } else if (character === C_SPACE) {
  47. size++;
  48. } else {
  49. break;
  50. }
  51. position++;
  52. }
  53. if (size >= TAB_SIZE) {
  54. index = value.indexOf(C_NEWLINE, index + 1);
  55. continue;
  56. }
  57. }
  58. subvalue = value.slice(index + 1);
  59. /* Check if the following code contains a possible
  60. * block. */
  61. if (interrupt(interruptors, tokenizers, self, [eat, subvalue, true])) {
  62. break;
  63. }
  64. /* Break if the following line starts a list, when
  65. * already in a list, or when in commonmark, or when
  66. * in gfm mode and the bullet is *not* numeric. */
  67. if (
  68. tokenizers.list.call(self, eat, subvalue, true) &&
  69. (
  70. self.inList ||
  71. commonmark ||
  72. (gfm && !decimal(trim.left(subvalue).charAt(0)))
  73. )
  74. ) {
  75. break;
  76. }
  77. position = index;
  78. index = value.indexOf(C_NEWLINE, index + 1);
  79. if (index !== -1 && trim(value.slice(position, index)) === '') {
  80. index = position;
  81. break;
  82. }
  83. }
  84. subvalue = value.slice(0, index);
  85. if (trim(subvalue) === '') {
  86. eat(subvalue);
  87. return null;
  88. }
  89. /* istanbul ignore if - never used (yet) */
  90. if (silent) {
  91. return true;
  92. }
  93. now = eat.now();
  94. subvalue = trimTrailingLines(subvalue);
  95. return eat(subvalue)({
  96. type: 'paragraph',
  97. children: self.tokenizeInline(subvalue, now)
  98. });
  99. }