setext-underline.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. 'use strict'
  2. var assert = require('assert')
  3. var codes = require('../character/codes.js')
  4. var markdownLineEnding = require('../character/markdown-line-ending.js')
  5. var types = require('../constant/types.js')
  6. var shallow = require('../util/shallow.js')
  7. var factorySpace = require('./factory-space.js')
  8. function _interopDefaultLegacy(e) {
  9. return e && typeof e === 'object' && 'default' in e ? e : {default: e}
  10. }
  11. var assert__default = /*#__PURE__*/ _interopDefaultLegacy(assert)
  12. var setextUnderline = {
  13. name: 'setextUnderline',
  14. tokenize: tokenizeSetextUnderline,
  15. resolveTo: resolveToSetextUnderline
  16. }
  17. function resolveToSetextUnderline(events, context) {
  18. var index = events.length
  19. var content
  20. var text
  21. var definition
  22. var heading
  23. // Find the opening of the content.
  24. // It’ll always exist: we don’t tokenize if it isn’t there.
  25. while (index--) {
  26. if (events[index][0] === 'enter') {
  27. if (events[index][1].type === types.content) {
  28. content = index
  29. break
  30. }
  31. if (events[index][1].type === types.paragraph) {
  32. text = index
  33. }
  34. }
  35. // Exit
  36. else {
  37. if (events[index][1].type === types.content) {
  38. // Remove the content end (if needed we’ll add it later)
  39. events.splice(index, 1)
  40. }
  41. if (!definition && events[index][1].type === types.definition) {
  42. definition = index
  43. }
  44. }
  45. }
  46. heading = {
  47. type: types.setextHeading,
  48. start: shallow(events[text][1].start),
  49. end: shallow(events[events.length - 1][1].end)
  50. }
  51. // Change the paragraph to setext heading text.
  52. events[text][1].type = types.setextHeadingText
  53. // If we have definitions in the content, we’ll keep on having content,
  54. // but we need move it.
  55. if (definition) {
  56. events.splice(text, 0, ['enter', heading, context])
  57. events.splice(definition + 1, 0, ['exit', events[content][1], context])
  58. events[content][1].end = shallow(events[definition][1].end)
  59. } else {
  60. events[content][1] = heading
  61. }
  62. // Add the heading exit at the end.
  63. events.push(['exit', heading, context])
  64. return events
  65. }
  66. function tokenizeSetextUnderline(effects, ok, nok) {
  67. var self = this
  68. var index = self.events.length
  69. var marker
  70. var paragraph
  71. // Find an opening.
  72. while (index--) {
  73. // Skip enter/exit of line ending, line prefix, and content.
  74. // We can now either have a definition or a paragraph.
  75. if (
  76. self.events[index][1].type !== types.lineEnding &&
  77. self.events[index][1].type !== types.linePrefix &&
  78. self.events[index][1].type !== types.content
  79. ) {
  80. paragraph = self.events[index][1].type === types.paragraph
  81. break
  82. }
  83. }
  84. return start
  85. function start(code) {
  86. assert__default['default'](
  87. code === codes.dash || code === codes.equalsTo,
  88. 'expected `=` or `-`'
  89. )
  90. if (!self.lazy && (self.interrupt || paragraph)) {
  91. effects.enter(types.setextHeadingLine)
  92. effects.enter(types.setextHeadingLineSequence)
  93. marker = code
  94. return closingSequence(code)
  95. }
  96. return nok(code)
  97. }
  98. function closingSequence(code) {
  99. if (code === marker) {
  100. effects.consume(code)
  101. return closingSequence
  102. }
  103. effects.exit(types.setextHeadingLineSequence)
  104. return factorySpace(effects, closingSequenceEnd, types.lineSuffix)(code)
  105. }
  106. function closingSequenceEnd(code) {
  107. if (code === codes.eof || markdownLineEnding(code)) {
  108. effects.exit(types.setextHeadingLine)
  109. return ok(code)
  110. }
  111. return nok(code)
  112. }
  113. }
  114. module.exports = setextUnderline