annotate .cms/lib/codemirror/addon/fold/foldgutter.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
2 // Distributed under an MIT license: https://codemirror.net/5/LICENSE
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
3
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
4 (function(mod) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
5 if (typeof exports == "object" && typeof module == "object") // CommonJS
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
6 mod(require("../../lib/codemirror"), require("./foldcode"));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
7 else if (typeof define == "function" && define.amd) // AMD
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
8 define(["../../lib/codemirror", "./foldcode"], mod);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
9 else // Plain browser env
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
10 mod(CodeMirror);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
11 })(function(CodeMirror) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
12 "use strict";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
13
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
14 CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
15 if (old && old != CodeMirror.Init) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
16 cm.clearGutter(cm.state.foldGutter.options.gutter);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
17 cm.state.foldGutter = null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
18 cm.off("gutterClick", onGutterClick);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
19 cm.off("changes", onChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
20 cm.off("viewportChange", onViewportChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
21 cm.off("fold", onFold);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
22 cm.off("unfold", onFold);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
23 cm.off("swapDoc", onChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
24 cm.off("optionChange", optionChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
25 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
26 if (val) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
27 cm.state.foldGutter = new State(parseOptions(val));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
28 updateInViewport(cm);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
29 cm.on("gutterClick", onGutterClick);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
30 cm.on("changes", onChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
31 cm.on("viewportChange", onViewportChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
32 cm.on("fold", onFold);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
33 cm.on("unfold", onFold);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
34 cm.on("swapDoc", onChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
35 cm.on("optionChange", optionChange);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
36 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
37 });
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
38
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
39 var Pos = CodeMirror.Pos;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
40
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
41 function State(options) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
42 this.options = options;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
43 this.from = this.to = 0;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
44 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
45
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
46 function parseOptions(opts) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
47 if (opts === true) opts = {};
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
48 if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
49 if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
50 if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
51 return opts;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
52 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
53
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
54 function isFolded(cm, line) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
55 var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
56 for (var i = 0; i < marks.length; ++i) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
57 if (marks[i].__isFold) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
58 var fromPos = marks[i].find(-1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
59 if (fromPos && fromPos.line === line)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
60 return marks[i];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
61 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
62 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
63 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
64
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
65 function marker(spec) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
66 if (typeof spec == "string") {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
67 var elt = document.createElement("div");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
68 elt.className = spec + " CodeMirror-guttermarker-subtle";
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
69 return elt;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
70 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
71 return spec.cloneNode(true);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
72 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
73 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
74
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
75 function updateFoldInfo(cm, from, to) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
76 var opts = cm.state.foldGutter.options, cur = from - 1;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
77 var minSize = cm.foldOption(opts, "minFoldSize");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
78 var func = cm.foldOption(opts, "rangeFinder");
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
79 // we can reuse the built-in indicator element if its className matches the new state
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
80 var clsFolded = typeof opts.indicatorFolded == "string" && classTest(opts.indicatorFolded);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
81 var clsOpen = typeof opts.indicatorOpen == "string" && classTest(opts.indicatorOpen);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
82 cm.eachLine(from, to, function(line) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
83 ++cur;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
84 var mark = null;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
85 var old = line.gutterMarkers;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
86 if (old) old = old[opts.gutter];
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
87 if (isFolded(cm, cur)) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
88 if (clsFolded && old && clsFolded.test(old.className)) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
89 mark = marker(opts.indicatorFolded);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
90 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
91 var pos = Pos(cur, 0);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
92 var range = func && func(cm, pos);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
93 if (range && range.to.line - range.from.line >= minSize) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
94 if (clsOpen && old && clsOpen.test(old.className)) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
95 mark = marker(opts.indicatorOpen);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
96 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
97 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
98 if (!mark && !old) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
99 cm.setGutterMarker(line, opts.gutter, mark);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
100 });
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
101 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
102
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
103 // copied from CodeMirror/src/util/dom.js
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
104 function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
105
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
106 function updateInViewport(cm) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
107 var vp = cm.getViewport(), state = cm.state.foldGutter;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
108 if (!state) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
109 cm.operation(function() {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
110 updateFoldInfo(cm, vp.from, vp.to);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
111 });
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
112 state.from = vp.from; state.to = vp.to;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
113 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
114
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
115 function onGutterClick(cm, line, gutter) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
116 var state = cm.state.foldGutter;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
117 if (!state) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
118 var opts = state.options;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
119 if (gutter != opts.gutter) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
120 var folded = isFolded(cm, line);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
121 if (folded) folded.clear();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
122 else cm.foldCode(Pos(line, 0), opts);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
123 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
124
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
125 function optionChange(cm, option) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
126 if (option == "mode") onChange(cm)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
127 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
128
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
129 function onChange(cm) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
130 var state = cm.state.foldGutter;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
131 if (!state) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
132 var opts = state.options;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
133 state.from = state.to = 0;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
134 clearTimeout(state.changeUpdate);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
135 state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
136 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
137
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
138 function onViewportChange(cm) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
139 var state = cm.state.foldGutter;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
140 if (!state) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
141 var opts = state.options;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
142 clearTimeout(state.changeUpdate);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
143 state.changeUpdate = setTimeout(function() {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
144 var vp = cm.getViewport();
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
145 if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
146 updateInViewport(cm);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
147 } else {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
148 cm.operation(function() {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
149 if (vp.from < state.from) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
150 updateFoldInfo(cm, vp.from, state.from);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
151 state.from = vp.from;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
152 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
153 if (vp.to > state.to) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
154 updateFoldInfo(cm, state.to, vp.to);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
155 state.to = vp.to;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
156 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
157 });
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
158 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
159 }, opts.updateViewportTimeSpan || 400);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
160 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
161
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
162 function onFold(cm, from) {
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
163 var state = cm.state.foldGutter;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
164 if (!state) return;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
165 var line = from.line;
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
166 if (line >= state.from && line < state.to)
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
167 updateFoldInfo(cm, line, line + 1);
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
168 }
Coffee CMS <info@coffee-cms.ru>
parents:
diff changeset
169 });