content.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /**
  2. * @typedef {import('micromark-util-types').InitialConstruct} InitialConstruct
  3. * @typedef {import('micromark-util-types').Initializer} Initializer
  4. * @typedef {import('micromark-util-types').State} State
  5. * @typedef {import('micromark-util-types').Token} Token
  6. * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext
  7. */
  8. import {factorySpace} from 'micromark-factory-space'
  9. import {markdownLineEnding} from 'micromark-util-character'
  10. import {codes, constants, types} from 'micromark-util-symbol'
  11. import {ok as assert} from 'devlop'
  12. /** @type {InitialConstruct} */
  13. export const content = {tokenize: initializeContent}
  14. /**
  15. * @this {TokenizeContext}
  16. * @type {Initializer}
  17. */
  18. function initializeContent(effects) {
  19. const contentStart = effects.attempt(
  20. this.parser.constructs.contentInitial,
  21. afterContentStartConstruct,
  22. paragraphInitial
  23. )
  24. /** @type {Token} */
  25. let previous
  26. return contentStart
  27. /** @type {State} */
  28. function afterContentStartConstruct(code) {
  29. assert(
  30. code === codes.eof || markdownLineEnding(code),
  31. 'expected eol or eof'
  32. )
  33. if (code === codes.eof) {
  34. effects.consume(code)
  35. return
  36. }
  37. effects.enter(types.lineEnding)
  38. effects.consume(code)
  39. effects.exit(types.lineEnding)
  40. return factorySpace(effects, contentStart, types.linePrefix)
  41. }
  42. /** @type {State} */
  43. function paragraphInitial(code) {
  44. assert(
  45. code !== codes.eof && !markdownLineEnding(code),
  46. 'expected anything other than a line ending or EOF'
  47. )
  48. effects.enter(types.paragraph)
  49. return lineStart(code)
  50. }
  51. /** @type {State} */
  52. function lineStart(code) {
  53. const token = effects.enter(types.chunkText, {
  54. contentType: constants.contentTypeText,
  55. previous
  56. })
  57. if (previous) {
  58. previous.next = token
  59. }
  60. previous = token
  61. return data(code)
  62. }
  63. /** @type {State} */
  64. function data(code) {
  65. if (code === codes.eof) {
  66. effects.exit(types.chunkText)
  67. effects.exit(types.paragraph)
  68. effects.consume(code)
  69. return
  70. }
  71. if (markdownLineEnding(code)) {
  72. effects.consume(code)
  73. effects.exit(types.chunkText)
  74. return lineStart
  75. }
  76. // Data.
  77. effects.consume(code)
  78. return data
  79. }
  80. }