Mercurial
comparison .cms/lib/codemirror/src/model/document_data.js @ 0:78edf6b517a0 draft
24.10
author | Coffee CMS <info@coffee-cms.ru> |
---|---|
date | Fri, 11 Oct 2024 22:40:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:78edf6b517a0 |
---|---|
1 import { loadMode } from "../display/mode_state.js" | |
2 import { runInOp } from "../display/operations.js" | |
3 import { regChange } from "../display/view_tracking.js" | |
4 import { Line, updateLine } from "../line/line_data.js" | |
5 import { findMaxLine } from "../line/spans.js" | |
6 import { getLine } from "../line/utils_line.js" | |
7 import { estimateLineHeights } from "../measurement/position_measurement.js" | |
8 import { addClass, rmClass } from "../util/dom.js" | |
9 import { lst } from "../util/misc.js" | |
10 import { signalLater } from "../util/operation_group.js" | |
11 | |
12 // DOCUMENT DATA STRUCTURE | |
13 | |
14 // By default, updates that start and end at the beginning of a line | |
15 // are treated specially, in order to make the association of line | |
16 // widgets and marker elements with the text behave more intuitive. | |
17 export function isWholeLineUpdate(doc, change) { | |
18 return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && | |
19 (!doc.cm || doc.cm.options.wholeLineUpdateBefore) | |
20 } | |
21 | |
22 // Perform a change on the document data structure. | |
23 export function updateDoc(doc, change, markedSpans, estimateHeight) { | |
24 function spansFor(n) {return markedSpans ? markedSpans[n] : null} | |
25 function update(line, text, spans) { | |
26 updateLine(line, text, spans, estimateHeight) | |
27 signalLater(line, "change", line, change) | |
28 } | |
29 function linesFor(start, end) { | |
30 let result = [] | |
31 for (let i = start; i < end; ++i) | |
32 result.push(new Line(text[i], spansFor(i), estimateHeight)) | |
33 return result | |
34 } | |
35 | |
36 let from = change.from, to = change.to, text = change.text | |
37 let firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line) | |
38 let lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line | |
39 | |
40 // Adjust the line structure | |
41 if (change.full) { | |
42 doc.insert(0, linesFor(0, text.length)) | |
43 doc.remove(text.length, doc.size - text.length) | |
44 } else if (isWholeLineUpdate(doc, change)) { | |
45 // This is a whole-line replace. Treated specially to make | |
46 // sure line objects move the way they are supposed to. | |
47 let added = linesFor(0, text.length - 1) | |
48 update(lastLine, lastLine.text, lastSpans) | |
49 if (nlines) doc.remove(from.line, nlines) | |
50 if (added.length) doc.insert(from.line, added) | |
51 } else if (firstLine == lastLine) { | |
52 if (text.length == 1) { | |
53 update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans) | |
54 } else { | |
55 let added = linesFor(1, text.length - 1) | |
56 added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)) | |
57 update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) | |
58 doc.insert(from.line + 1, added) | |
59 } | |
60 } else if (text.length == 1) { | |
61 update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)) | |
62 doc.remove(from.line + 1, nlines) | |
63 } else { | |
64 update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) | |
65 update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans) | |
66 let added = linesFor(1, text.length - 1) | |
67 if (nlines > 1) doc.remove(from.line + 1, nlines - 1) | |
68 doc.insert(from.line + 1, added) | |
69 } | |
70 | |
71 signalLater(doc, "change", doc, change) | |
72 } | |
73 | |
74 // Call f for all linked documents. | |
75 export function linkedDocs(doc, f, sharedHistOnly) { | |
76 function propagate(doc, skip, sharedHist) { | |
77 if (doc.linked) for (let i = 0; i < doc.linked.length; ++i) { | |
78 let rel = doc.linked[i] | |
79 if (rel.doc == skip) continue | |
80 let shared = sharedHist && rel.sharedHist | |
81 if (sharedHistOnly && !shared) continue | |
82 f(rel.doc, shared) | |
83 propagate(rel.doc, doc, shared) | |
84 } | |
85 } | |
86 propagate(doc, null, true) | |
87 } | |
88 | |
89 // Attach a document to an editor. | |
90 export function attachDoc(cm, doc) { | |
91 if (doc.cm) throw new Error("This document is already in use.") | |
92 cm.doc = doc | |
93 doc.cm = cm | |
94 estimateLineHeights(cm) | |
95 loadMode(cm) | |
96 setDirectionClass(cm) | |
97 cm.options.direction = doc.direction | |
98 if (!cm.options.lineWrapping) findMaxLine(cm) | |
99 cm.options.mode = doc.modeOption | |
100 regChange(cm) | |
101 } | |
102 | |
103 function setDirectionClass(cm) { | |
104 ;(cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl") | |
105 } | |
106 | |
107 export function directionChanged(cm) { | |
108 runInOp(cm, () => { | |
109 setDirectionClass(cm) | |
110 regChange(cm) | |
111 }) | |
112 } |