label-start-image.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /**
  2. * @typedef {import('micromark-util-types').Construct} Construct
  3. * @typedef {import('micromark-util-types').State} State
  4. * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext
  5. * @typedef {import('micromark-util-types').Tokenizer} Tokenizer
  6. */
  7. import {codes, types} from 'micromark-util-symbol'
  8. import {ok as assert} from 'devlop'
  9. import {labelEnd} from './label-end.js'
  10. /** @type {Construct} */
  11. export const labelStartImage = {
  12. name: 'labelStartImage',
  13. tokenize: tokenizeLabelStartImage,
  14. resolveAll: labelEnd.resolveAll
  15. }
  16. /**
  17. * @this {TokenizeContext}
  18. * @type {Tokenizer}
  19. */
  20. function tokenizeLabelStartImage(effects, ok, nok) {
  21. const self = this
  22. return start
  23. /**
  24. * Start of label (image) start.
  25. *
  26. * ```markdown
  27. * > | a ![b] c
  28. * ^
  29. * ```
  30. *
  31. * @type {State}
  32. */
  33. function start(code) {
  34. assert(code === codes.exclamationMark, 'expected `!`')
  35. effects.enter(types.labelImage)
  36. effects.enter(types.labelImageMarker)
  37. effects.consume(code)
  38. effects.exit(types.labelImageMarker)
  39. return open
  40. }
  41. /**
  42. * After `!`, at `[`.
  43. *
  44. * ```markdown
  45. * > | a ![b] c
  46. * ^
  47. * ```
  48. *
  49. * @type {State}
  50. */
  51. function open(code) {
  52. if (code === codes.leftSquareBracket) {
  53. effects.enter(types.labelMarker)
  54. effects.consume(code)
  55. effects.exit(types.labelMarker)
  56. effects.exit(types.labelImage)
  57. return after
  58. }
  59. return nok(code)
  60. }
  61. /**
  62. * After `![`.
  63. *
  64. * ```markdown
  65. * > | a ![b] c
  66. * ^
  67. * ```
  68. *
  69. * This is needed in because, when GFM footnotes are enabled, images never
  70. * form when started with a `^`.
  71. * Instead, links form:
  72. *
  73. * ```markdown
  74. * ![^a](b)
  75. *
  76. * ![^a][b]
  77. *
  78. * [b]: c
  79. * ```
  80. *
  81. * ```html
  82. * <p>!<a href=\"b\">^a</a></p>
  83. * <p>!<a href=\"c\">^a</a></p>
  84. * ```
  85. *
  86. * @type {State}
  87. */
  88. function after(code) {
  89. // To do: use a new field to do this, this is still needed for
  90. // `micromark-extension-gfm-footnote`, but the `label-start-link`
  91. // behavior isn’t.
  92. // Hidden footnotes hook.
  93. /* c8 ignore next 3 */
  94. return code === codes.caret &&
  95. '_hiddenFootnoteSupport' in self.parser.constructs
  96. ? nok(code)
  97. : ok(code)
  98. }
  99. }