code.js 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /**
  2. * @typedef {import('mdast').Code} Code
  3. * @typedef {import('mdast').Parents} Parents
  4. * @typedef {import('../types.js').Info} Info
  5. * @typedef {import('../types.js').Map} Map
  6. * @typedef {import('../types.js').State} State
  7. */
  8. import {longestStreak} from 'longest-streak'
  9. import {formatCodeAsIndented} from '../util/format-code-as-indented.js'
  10. import {checkFence} from '../util/check-fence.js'
  11. /**
  12. * @param {Code} node
  13. * @param {Parents | undefined} _
  14. * @param {State} state
  15. * @param {Info} info
  16. * @returns {string}
  17. */
  18. export function code(node, _, state, info) {
  19. const marker = checkFence(state)
  20. const raw = node.value || ''
  21. const suffix = marker === '`' ? 'GraveAccent' : 'Tilde'
  22. if (formatCodeAsIndented(node, state)) {
  23. const exit = state.enter('codeIndented')
  24. const value = state.indentLines(raw, map)
  25. exit()
  26. return value
  27. }
  28. const tracker = state.createTracker(info)
  29. const sequence = marker.repeat(Math.max(longestStreak(raw, marker) + 1, 3))
  30. const exit = state.enter('codeFenced')
  31. let value = tracker.move(sequence)
  32. if (node.lang) {
  33. const subexit = state.enter(`codeFencedLang${suffix}`)
  34. value += tracker.move(
  35. state.safe(node.lang, {
  36. before: value,
  37. after: ' ',
  38. encode: ['`'],
  39. ...tracker.current()
  40. })
  41. )
  42. subexit()
  43. }
  44. if (node.lang && node.meta) {
  45. const subexit = state.enter(`codeFencedMeta${suffix}`)
  46. value += tracker.move(' ')
  47. value += tracker.move(
  48. state.safe(node.meta, {
  49. before: value,
  50. after: '\n',
  51. encode: ['`'],
  52. ...tracker.current()
  53. })
  54. )
  55. subexit()
  56. }
  57. value += tracker.move('\n')
  58. if (raw) {
  59. value += tracker.move(raw + '\n')
  60. }
  61. value += tracker.move(sequence)
  62. exit()
  63. return value
  64. }
  65. /** @type {Map} */
  66. function map(line, _, blank) {
  67. return (blank ? '' : ' ') + line
  68. }