1 CodeMirror
.tagRangeFinder
= (function() {
2 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";
3 var nameChar
= nameStartChar
+ "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
4 var xmlTagStart
= new RegExp("<(/?)([" + nameStartChar
+ "][" + nameChar
+ "]*)", "g");
6 return function(cm
, start
) {
7 var line
= start
.line
, ch
= start
.ch
, lineText
= cm
.getLine(line
);
10 if (line
>= cm
.lastLine()) return;
12 lineText
= cm
.getLine(++line
);
17 var gt
= lineText
.indexOf(">", ch
);
18 if (gt
== -1) { if (nextLine()) continue; else return; }
19 var lastSlash
= lineText
.lastIndexOf("/", gt
);
20 var selfClose
= lastSlash
> -1 && /^\s*$/.test(lineText
.slice(lastSlash
+ 1, gt
));
22 return selfClose
? "selfClose" : "regular";
25 function toNextTag() {
27 xmlTagStart
.lastIndex
= ch
;
28 var found
= xmlTagStart
.exec(lineText
);
29 if (!found
) { if (nextLine()) continue; else return; }
30 ch
= found
.index
+ found
[0].length
;
35 var stack
= [], startCh
;
37 var openTag
= toNextTag(), end
;
38 if (!openTag
|| line
!= start
.line
|| !(end
= toTagEnd())) return;
39 if (!openTag
[1] && end
!= "selfClose") {
40 stack
.push(openTag
[2]);
47 var next
= toNextTag(), end
, tagLine
= line
, tagCh
= ch
- (next
? next
[0].length
: 0);
48 if (!next
|| !(end
= toTagEnd())) return;
49 if (end
== "selfClose") continue;
50 if (next
[1]) { // closing tag
51 for (var i
= stack
.length
- 1; i
>= 0; --i
) if (stack
[i
] == next
[2]) {
55 if (!stack
.length
) return {
56 from: CodeMirror
.Pos(start
.line
, startCh
),
57 to
: CodeMirror
.Pos(tagLine
, tagCh
)
59 } else { // opening tag