comparison .cms/lib/codemirror/src/edit/options.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 { onBlur } from "../display/focus.js"
2 import { getGutters, updateGutters } from "../display/gutters.js"
3 import { loadMode, resetModeState } from "../display/mode_state.js"
4 import { initScrollbars, updateScrollbars } from "../display/scrollbars.js"
5 import { updateSelection } from "../display/selection.js"
6 import { regChange } from "../display/view_tracking.js"
7 import { getKeyMap } from "../input/keymap.js"
8 import { defaultSpecialCharPlaceholder } from "../line/line_data.js"
9 import { Pos } from "../line/pos.js"
10 import { findMaxLine } from "../line/spans.js"
11 import { clearCaches, compensateForHScroll, estimateLineHeights } from "../measurement/position_measurement.js"
12 import { replaceRange } from "../model/changes.js"
13 import { mobile, windows } from "../util/browser.js"
14 import { addClass, rmClass } from "../util/dom.js"
15 import { off, on } from "../util/event.js"
16
17 import { themeChanged } from "./utils.js"
18
19 export let Init = {toString: function(){return "CodeMirror.Init"}}
20
21 export let defaults = {}
22 export let optionHandlers = {}
23
24 export function defineOptions(CodeMirror) {
25 let optionHandlers = CodeMirror.optionHandlers
26
27 function option(name, deflt, handle, notOnInit) {
28 CodeMirror.defaults[name] = deflt
29 if (handle) optionHandlers[name] =
30 notOnInit ? (cm, val, old) => {if (old != Init) handle(cm, val, old)} : handle
31 }
32
33 CodeMirror.defineOption = option
34
35 // Passed to option handlers when there is no old value.
36 CodeMirror.Init = Init
37
38 // These two are, on init, called from the constructor because they
39 // have to be initialized before the editor can start at all.
40 option("value", "", (cm, val) => cm.setValue(val), true)
41 option("mode", null, (cm, val) => {
42 cm.doc.modeOption = val
43 loadMode(cm)
44 }, true)
45
46 option("indentUnit", 2, loadMode, true)
47 option("indentWithTabs", false)
48 option("smartIndent", true)
49 option("tabSize", 4, cm => {
50 resetModeState(cm)
51 clearCaches(cm)
52 regChange(cm)
53 }, true)
54
55 option("lineSeparator", null, (cm, val) => {
56 cm.doc.lineSep = val
57 if (!val) return
58 let newBreaks = [], lineNo = cm.doc.first
59 cm.doc.iter(line => {
60 for (let pos = 0;;) {
61 let found = line.text.indexOf(val, pos)
62 if (found == -1) break
63 pos = found + val.length
64 newBreaks.push(Pos(lineNo, found))
65 }
66 lineNo++
67 })
68 for (let i = newBreaks.length - 1; i >= 0; i--)
69 replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length))
70 })
71 option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\u202d\u202e\u2066\u2067\u2069\ufeff\ufff9-\ufffc]/g, (cm, val, old) => {
72 cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g")
73 if (old != Init) cm.refresh()
74 })
75 option("specialCharPlaceholder", defaultSpecialCharPlaceholder, cm => cm.refresh(), true)
76 option("electricChars", true)
77 option("inputStyle", mobile ? "contenteditable" : "textarea", () => {
78 throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
79 }, true)
80 option("spellcheck", false, (cm, val) => cm.getInputField().spellcheck = val, true)
81 option("autocorrect", false, (cm, val) => cm.getInputField().autocorrect = val, true)
82 option("autocapitalize", false, (cm, val) => cm.getInputField().autocapitalize = val, true)
83 option("rtlMoveVisually", !windows)
84 option("wholeLineUpdateBefore", true)
85
86 option("theme", "default", cm => {
87 themeChanged(cm)
88 updateGutters(cm)
89 }, true)
90 option("keyMap", "default", (cm, val, old) => {
91 let next = getKeyMap(val)
92 let prev = old != Init && getKeyMap(old)
93 if (prev && prev.detach) prev.detach(cm, next)
94 if (next.attach) next.attach(cm, prev || null)
95 })
96 option("extraKeys", null)
97 option("configureMouse", null)
98
99 option("lineWrapping", false, wrappingChanged, true)
100 option("gutters", [], (cm, val) => {
101 cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers)
102 updateGutters(cm)
103 }, true)
104 option("fixedGutter", true, (cm, val) => {
105 cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"
106 cm.refresh()
107 }, true)
108 option("coverGutterNextToScrollbar", false, cm => updateScrollbars(cm), true)
109 option("scrollbarStyle", "native", cm => {
110 initScrollbars(cm)
111 updateScrollbars(cm)
112 cm.display.scrollbars.setScrollTop(cm.doc.scrollTop)
113 cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft)
114 }, true)
115 option("lineNumbers", false, (cm, val) => {
116 cm.display.gutterSpecs = getGutters(cm.options.gutters, val)
117 updateGutters(cm)
118 }, true)
119 option("firstLineNumber", 1, updateGutters, true)
120 option("lineNumberFormatter", integer => integer, updateGutters, true)
121 option("showCursorWhenSelecting", false, updateSelection, true)
122
123 option("resetSelectionOnContextMenu", true)
124 option("lineWiseCopyCut", true)
125 option("pasteLinesPerSelection", true)
126 option("selectionsMayTouch", false)
127
128 option("readOnly", false, (cm, val) => {
129 if (val == "nocursor") {
130 onBlur(cm)
131 cm.display.input.blur()
132 }
133 cm.display.input.readOnlyChanged(val)
134 })
135
136 option("screenReaderLabel", null, (cm, val) => {
137 val = (val === '') ? null : val
138 cm.display.input.screenReaderLabelChanged(val)
139 })
140
141 option("disableInput", false, (cm, val) => {if (!val) cm.display.input.reset()}, true)
142 option("dragDrop", true, dragDropChanged)
143 option("allowDropFileTypes", null)
144
145 option("cursorBlinkRate", 530)
146 option("cursorScrollMargin", 0)
147 option("cursorHeight", 1, updateSelection, true)
148 option("singleCursorHeightPerLine", true, updateSelection, true)
149 option("workTime", 100)
150 option("workDelay", 100)
151 option("flattenSpans", true, resetModeState, true)
152 option("addModeClass", false, resetModeState, true)
153 option("pollInterval", 100)
154 option("undoDepth", 200, (cm, val) => cm.doc.history.undoDepth = val)
155 option("historyEventDelay", 1250)
156 option("viewportMargin", 10, cm => cm.refresh(), true)
157 option("maxHighlightLength", 10000, resetModeState, true)
158 option("moveInputWithCursor", true, (cm, val) => {
159 if (!val) cm.display.input.resetPosition()
160 })
161
162 option("tabindex", null, (cm, val) => cm.display.input.getField().tabIndex = val || "")
163 option("autofocus", null)
164 option("direction", "ltr", (cm, val) => cm.doc.setDirection(val), true)
165 option("phrases", null)
166 }
167
168 function dragDropChanged(cm, value, old) {
169 let wasOn = old && old != Init
170 if (!value != !wasOn) {
171 let funcs = cm.display.dragFunctions
172 let toggle = value ? on : off
173 toggle(cm.display.scroller, "dragstart", funcs.start)
174 toggle(cm.display.scroller, "dragenter", funcs.enter)
175 toggle(cm.display.scroller, "dragover", funcs.over)
176 toggle(cm.display.scroller, "dragleave", funcs.leave)
177 toggle(cm.display.scroller, "drop", funcs.drop)
178 }
179 }
180
181 function wrappingChanged(cm) {
182 if (cm.options.lineWrapping) {
183 addClass(cm.display.wrapper, "CodeMirror-wrap")
184 cm.display.sizer.style.minWidth = ""
185 cm.display.sizerWidth = null
186 } else {
187 rmClass(cm.display.wrapper, "CodeMirror-wrap")
188 findMaxLine(cm)
189 }
190 estimateLineHeights(cm)
191 regChange(cm)
192 clearCaches(cm)
193 setTimeout(() => updateScrollbars(cm), 100)
194 }