9aa68850074d547e4043bcd0088c092717e1634db10a194ae73637522871c7da78b25c97c372159b1ca6f0172c8753df21dfe6af422d378a823e2778816a5b 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { getContextBefore, highlightLine, processLine } from "../line/highlight.js"
  2. import { copyState } from "../modes.js"
  3. import { bind } from "../util/misc.js"
  4. import { runInOp } from "./operations.js"
  5. import { regLineChange } from "./view_tracking.js"
  6. // HIGHLIGHT WORKER
  7. export function startWorker(cm, time) {
  8. if (cm.doc.highlightFrontier < cm.display.viewTo)
  9. cm.state.highlight.set(time, bind(highlightWorker, cm))
  10. }
  11. function highlightWorker(cm) {
  12. let doc = cm.doc
  13. if (doc.highlightFrontier >= cm.display.viewTo) return
  14. let end = +new Date + cm.options.workTime
  15. let context = getContextBefore(cm, doc.highlightFrontier)
  16. let changedLines = []
  17. doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), line => {
  18. if (context.line >= cm.display.viewFrom) { // Visible
  19. let oldStyles = line.styles
  20. let resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null
  21. let highlighted = highlightLine(cm, line, context, true)
  22. if (resetState) context.state = resetState
  23. line.styles = highlighted.styles
  24. let oldCls = line.styleClasses, newCls = highlighted.classes
  25. if (newCls) line.styleClasses = newCls
  26. else if (oldCls) line.styleClasses = null
  27. let ischange = !oldStyles || oldStyles.length != line.styles.length ||
  28. oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass)
  29. for (let i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]
  30. if (ischange) changedLines.push(context.line)
  31. line.stateAfter = context.save()
  32. context.nextLine()
  33. } else {
  34. if (line.text.length <= cm.options.maxHighlightLength)
  35. processLine(cm, line.text, context)
  36. line.stateAfter = context.line % 5 == 0 ? context.save() : null
  37. context.nextLine()
  38. }
  39. if (+new Date > end) {
  40. startWorker(cm, cm.options.workDelay)
  41. return true
  42. }
  43. })
  44. doc.highlightFrontier = context.line
  45. doc.modeFrontier = Math.max(doc.modeFrontier, context.line)
  46. if (changedLines.length) runInOp(cm, () => {
  47. for (let i = 0; i < changedLines.length; i++)
  48. regLineChange(cm, changedLines[i], "text")
  49. })
  50. }