character-escape.js 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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 {asciiPunctuation} from 'micromark-util-character'
  8. import {codes, types} from 'micromark-util-symbol'
  9. import {ok as assert} from 'devlop'
  10. /** @type {Construct} */
  11. export const characterEscape = {
  12. name: 'characterEscape',
  13. tokenize: tokenizeCharacterEscape
  14. }
  15. /**
  16. * @this {TokenizeContext}
  17. * @type {Tokenizer}
  18. */
  19. function tokenizeCharacterEscape(effects, ok, nok) {
  20. return start
  21. /**
  22. * Start of character escape.
  23. *
  24. * ```markdown
  25. * > | a\*b
  26. * ^
  27. * ```
  28. *
  29. * @type {State}
  30. */
  31. function start(code) {
  32. assert(code === codes.backslash, 'expected `\\`')
  33. effects.enter(types.characterEscape)
  34. effects.enter(types.escapeMarker)
  35. effects.consume(code)
  36. effects.exit(types.escapeMarker)
  37. return inside
  38. }
  39. /**
  40. * After `\`, at punctuation.
  41. *
  42. * ```markdown
  43. * > | a\*b
  44. * ^
  45. * ```
  46. *
  47. * @type {State}
  48. */
  49. function inside(code) {
  50. // ASCII punctuation.
  51. if (asciiPunctuation(code)) {
  52. effects.enter(types.characterEscapeValue)
  53. effects.consume(code)
  54. effects.exit(types.characterEscapeValue)
  55. effects.exit(types.characterEscape)
  56. return ok
  57. }
  58. return nok(code)
  59. }
  60. }