heading.mjs 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. // heading (#, ##, ...)
  2. import { isSpace } from '../common/utils.mjs'
  3. export default function heading (state, startLine, endLine, silent) {
  4. let pos = state.bMarks[startLine] + state.tShift[startLine]
  5. let max = state.eMarks[startLine]
  6. // if it's indented more than 3 spaces, it should be a code block
  7. if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
  8. let ch = state.src.charCodeAt(pos)
  9. if (ch !== 0x23/* # */ || pos >= max) { return false }
  10. // count heading level
  11. let level = 1
  12. ch = state.src.charCodeAt(++pos)
  13. while (ch === 0x23/* # */ && pos < max && level <= 6) {
  14. level++
  15. ch = state.src.charCodeAt(++pos)
  16. }
  17. if (level > 6 || (pos < max && !isSpace(ch))) { return false }
  18. if (silent) { return true }
  19. // Let's cut tails like ' ### ' from the end of string
  20. max = state.skipSpacesBack(max, pos)
  21. const tmp = state.skipCharsBack(max, 0x23, pos) // #
  22. if (tmp > pos && isSpace(state.src.charCodeAt(tmp - 1))) {
  23. max = tmp
  24. }
  25. state.line = startLine + 1
  26. const token_o = state.push('heading_open', 'h' + String(level), 1)
  27. token_o.markup = '########'.slice(0, level)
  28. token_o.map = [startLine, state.line]
  29. const token_i = state.push('inline', '', 0)
  30. token_i.content = state.src.slice(pos, max).trim()
  31. token_i.map = [startLine, state.line]
  32. token_i.children = []
  33. const token_c = state.push('heading_close', 'h' + String(level), -1)
  34. token_c.markup = '########'.slice(0, level)
  35. return true
  36. }