cmFold.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Header matching code by CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. import CodeMirror from 'codemirror'
  4. const maxDepth = 100
  5. const codeBlockStartMatch = /^`{3}[a-zA-Z0-9]+$/
  6. const codeBlockEndMatch = /^`{3}$/
  7. export default {
  8. register(lang) {
  9. CodeMirror.registerHelper('fold', lang, foldHandler)
  10. }
  11. }
  12. function foldHandler (cm, start) {
  13. const firstLine = cm.getLine(start.line)
  14. const lastLineNo = cm.lastLine()
  15. let end
  16. function isHeader(lineNo) {
  17. const tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0))
  18. return tokentype && /\bheader\b/.test(tokentype)
  19. }
  20. function headerLevel(lineNo, line, nextLine) {
  21. let match = line && line.match(/^#+/)
  22. if (match && isHeader(lineNo)) return match[0].length
  23. match = nextLine && nextLine.match(/^[=-]+\s*$/)
  24. if (match && isHeader(lineNo + 1)) return nextLine[0] === '=' ? 1 : 2
  25. return maxDepth
  26. }
  27. // -> CODE BLOCK
  28. if (codeBlockStartMatch.test(cm.getLine(start.line))) {
  29. end = start.line
  30. let nextNextLine = cm.getLine(end + 1)
  31. while (end < lastLineNo) {
  32. if (codeBlockEndMatch.test(nextNextLine)) {
  33. end++
  34. break
  35. }
  36. end++
  37. nextNextLine = cm.getLine(end + 1)
  38. }
  39. } else {
  40. // -> HEADER
  41. let nextLine = cm.getLine(start.line + 1)
  42. const level = headerLevel(start.line, firstLine, nextLine)
  43. if (level === maxDepth) return undefined
  44. end = start.line
  45. let nextNextLine = cm.getLine(end + 2)
  46. while (end < lastLineNo) {
  47. if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break
  48. ++end
  49. nextLine = nextNextLine
  50. nextNextLine = cm.getLine(end + 2)
  51. }
  52. }
  53. return {
  54. from: CodeMirror.Pos(start.line, firstLine.length),
  55. to: CodeMirror.Pos(end, cm.getLine(end).length)
  56. }
  57. }