PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 2.0.2
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v2.0.2
4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 All 340 releases
profile-builder / assets / lib / codemirror / addon / fold / xml-fold.js

xml-fold.js in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 2.0.2, at assets/lib/codemirror/addon/fold/xml-fold.js

168 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function() {
2 "use strict";
3
4 var Pos = CodeMirror.Pos;
5 function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
6
7 var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
8 var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
9 var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
10
11 function Iter(cm, line, ch, range) {
12 this.line = line; this.ch = ch;
13 this.cm = cm; this.text = cm.getLine(line);
14 this.min = range ? range.from : cm.firstLine();
15 this.max = range ? range.to - 1 : cm.lastLine();
16 }
17
18 function tagAt(iter, ch) {
19 var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch));
20 return type && /\btag\b/.test(type);
21 }
22
23 function nextLine(iter) {
24 if (iter.line >= iter.max) return;
25 iter.ch = 0;
26 iter.text = iter.cm.getLine(++iter.line);
27 return true;
28 }
29 function prevLine(iter) {
30 if (iter.line <= iter.min) return;
31 iter.text = iter.cm.getLine(--iter.line);
32 iter.ch = iter.text.length;
33 return true;
34 }
35
36 function toTagEnd(iter) {
37 for (;;) {
38 var gt = iter.text.indexOf(">", iter.ch);
39 if (gt == -1) { if (nextLine(iter)) continue; else return; }
40 if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; }
41 var lastSlash = iter.text.lastIndexOf("/", gt);
42 var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
43 iter.ch = gt + 1;
44 return selfClose ? "selfClose" : "regular";
45 }
46 }
47 function toTagStart(iter) {
48 for (;;) {
49 var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
50 if (lt == -1) { if (prevLine(iter)) continue; else return; }
51 if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
52 xmlTagStart.lastIndex = lt;
53 iter.ch = lt;
54 var match = xmlTagStart.exec(iter.text);
55 if (match && match.index == lt) return match;
56 }
57 }
58
59 function toNextTag(iter) {
60 for (;;) {
61 xmlTagStart.lastIndex = iter.ch;
62 var found = xmlTagStart.exec(iter.text);
63 if (!found) { if (nextLine(iter)) continue; else return; }
64 if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; }
65 iter.ch = found.index + found[0].length;
66 return found;
67 }
68 }
69 function toPrevTag(iter) {
70 for (;;) {
71 var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
72 if (gt == -1) { if (prevLine(iter)) continue; else return; }
73 if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
74 var lastSlash = iter.text.lastIndexOf("/", gt);
75 var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
76 iter.ch = gt + 1;
77 return selfClose ? "selfClose" : "regular";
78 }
79 }
80
81 function findMatchingClose(iter, tag) {
82 var stack = [];
83 for (;;) {
84 var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0);
85 if (!next || !(end = toTagEnd(iter))) return;
86 if (end == "selfClose") continue;
87 if (next[1]) { // closing tag
88 for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
89 stack.length = i;
90 break;
91 }
92 if (i < 0 && (!tag || tag == next[2])) return {
93 tag: next[2],
94 from: Pos(startLine, startCh),
95 to: Pos(iter.line, iter.ch)
96 };
97 } else { // opening tag
98 stack.push(next[2]);
99 }
100 }
101 }
102 function findMatchingOpen(iter, tag) {
103 var stack = [];
104 for (;;) {
105 var prev = toPrevTag(iter);
106 if (!prev) return;
107 if (prev == "selfClose") { toTagStart(iter); continue; }
108 var endLine = iter.line, endCh = iter.ch;
109 var start = toTagStart(iter);
110 if (!start) return;
111 if (start[1]) { // closing tag
112 stack.push(start[2]);
113 } else { // opening tag
114 for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) {
115 stack.length = i;
116 break;
117 }
118 if (i < 0 && (!tag || tag == start[2])) return {
119 tag: start[2],
120 from: Pos(iter.line, iter.ch),
121 to: Pos(endLine, endCh)
122 };
123 }
124 }
125 }
126
127 CodeMirror.registerHelper("fold", "xml", function(cm, start) {
128 var iter = new Iter(cm, start.line, 0);
129 for (;;) {
130 var openTag = toNextTag(iter), end;
131 if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
132 if (!openTag[1] && end != "selfClose") {
133 var start = Pos(iter.line, iter.ch);
134 var close = findMatchingClose(iter, openTag[2]);
135 return close && {from: start, to: close.from};
136 }
137 }
138 });
139 CodeMirror.tagRangeFinder = CodeMirror.fold.xml; // deprecated
140
141 CodeMirror.findMatchingTag = function(cm, pos, range) {
142 var iter = new Iter(cm, pos.line, pos.ch, range);
143 if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
144 var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
145 var start = end && toTagStart(iter);
146 if (!end || end == "selfClose" || !start || cmp(iter, pos) > 0) return;
147 var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
148
149 if (start[1]) { // closing tag
150 return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
151 } else { // opening tag
152 iter = new Iter(cm, to.line, to.ch, range);
153 return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
154 }
155 };
156
157 CodeMirror.findEnclosingTag = function(cm, pos, range) {
158 var iter = new Iter(cm, pos.line, pos.ch, range);
159 for (;;) {
160 var open = findMatchingOpen(iter);
161 if (!open) break;
162 var forward = new Iter(cm, pos.line, pos.ch, range);
163 var close = findMatchingClose(forward, open.tag);
164 if (close) return {open: open, close: close};
165 }
166 };
167 })();
168