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