codemirror 3, thnaks Roberto Perdomo and Mariano Reingart
This commit is contained in:
+59
-73
@@ -1,15 +1,15 @@
|
||||
// the tagRangeFinder function is
|
||||
// Copyright (C) 2011 by Daniel Glazman <daniel@glazman.org>
|
||||
// released under the MIT license (../../LICENSE) like the rest of CodeMirror
|
||||
CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
|
||||
CodeMirror.tagRangeFinder = function(cm, start) {
|
||||
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";
|
||||
var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
|
||||
var xmlNAMERegExp = new RegExp("^[" + nameStartChar + "][" + nameChar + "]*");
|
||||
|
||||
var lineText = cm.getLine(line);
|
||||
var lineText = cm.getLine(start.line);
|
||||
var found = false;
|
||||
var tag = null;
|
||||
var pos = 0;
|
||||
var pos = start.ch;
|
||||
while (!found) {
|
||||
pos = lineText.indexOf("<", pos);
|
||||
if (-1 == pos) // no tag on line
|
||||
@@ -18,28 +18,26 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
// ok we weem to have a start tag
|
||||
// ok we seem to have a start tag
|
||||
if (!lineText.substr(pos + 1).match(xmlNAMERegExp)) { // not a tag name...
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
var gtPos = lineText.indexOf(">", pos + 1);
|
||||
if (-1 == gtPos) { // end of start tag not in line
|
||||
var l = line + 1;
|
||||
var l = start.line + 1;
|
||||
var foundGt = false;
|
||||
var lastLine = cm.lineCount();
|
||||
while (l < lastLine && !foundGt) {
|
||||
var lt = cm.getLine(l);
|
||||
var gt = lt.indexOf(">");
|
||||
if (-1 != gt) { // found a >
|
||||
gtPos = lt.indexOf(">");
|
||||
if (-1 != gtPos) { // found a >
|
||||
foundGt = true;
|
||||
var slash = lt.lastIndexOf("/", gt);
|
||||
if (-1 != slash && slash < gt) {
|
||||
var str = lineText.substr(slash, gt - slash + 1);
|
||||
if (!str.match( /\/\s*\>/ )) { // yep, that's the end of empty tag
|
||||
if (hideEnd === true) l++;
|
||||
return l;
|
||||
}
|
||||
var slash = lt.lastIndexOf("/", gtPos);
|
||||
if (-1 != slash && slash < gtPos) {
|
||||
var str = lineText.substr(slash, gtPos - slash + 1);
|
||||
if (!str.match( /\/\s*\>/ )) // yep, that's the end of empty tag
|
||||
return;
|
||||
}
|
||||
}
|
||||
l++;
|
||||
@@ -83,10 +81,10 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
|
||||
|
||||
if (found) {
|
||||
var startTag = "(\\<\\/" + tag + "\\>)|(\\<" + tag + "\\>)|(\\<" + tag + "\\s)|(\\<" + tag + "$)";
|
||||
var startTagRegExp = new RegExp(startTag, "g");
|
||||
var startTagRegExp = new RegExp(startTag);
|
||||
var endTag = "</" + tag + ">";
|
||||
var depth = 1;
|
||||
var l = line + 1;
|
||||
var l = start.line + 1;
|
||||
var lastLine = cm.lineCount();
|
||||
while (l < lastLine) {
|
||||
lineText = cm.getLine(l);
|
||||
@@ -97,10 +95,8 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
|
||||
depth--;
|
||||
else
|
||||
depth++;
|
||||
if (!depth) {
|
||||
if (hideEnd === true) l++;
|
||||
return l;
|
||||
}
|
||||
if (!depth) return {from: {line: start.line, ch: gtPos + 1},
|
||||
to: {line: l, ch: match.index}};
|
||||
}
|
||||
}
|
||||
l++;
|
||||
@@ -109,17 +105,18 @@ CodeMirror.tagRangeFinder = function(cm, line, hideEnd) {
|
||||
}
|
||||
};
|
||||
|
||||
CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
|
||||
var lineText = cm.getLine(line), at = lineText.length, startChar, tokenType;
|
||||
CodeMirror.braceRangeFinder = function(cm, start) {
|
||||
var line = start.line, lineText = cm.getLine(line);
|
||||
var at = lineText.length, startChar, tokenType;
|
||||
for (;;) {
|
||||
var found = lineText.lastIndexOf("{", at);
|
||||
if (found < 0) break;
|
||||
tokenType = cm.getTokenAt({line: line, ch: found}).className;
|
||||
if (found < start.ch) break;
|
||||
tokenType = cm.getTokenAt({line: line, ch: found}).type;
|
||||
if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; }
|
||||
at = found - 1;
|
||||
}
|
||||
if (startChar == null || lineText.lastIndexOf("}") > startChar) return;
|
||||
var count = 1, lastLine = cm.lineCount(), end;
|
||||
var count = 1, lastLine = cm.lineCount(), end, endCh;
|
||||
outer: for (var i = line + 1; i < lastLine; ++i) {
|
||||
var text = cm.getLine(i), pos = 0;
|
||||
for (;;) {
|
||||
@@ -128,69 +125,58 @@ CodeMirror.braceRangeFinder = function(cm, line, hideEnd) {
|
||||
if (nextClose < 0) nextClose = text.length;
|
||||
pos = Math.min(nextOpen, nextClose);
|
||||
if (pos == text.length) break;
|
||||
if (cm.getTokenAt({line: i, ch: pos + 1}).className == tokenType) {
|
||||
if (cm.getTokenAt({line: i, ch: pos + 1}).type == tokenType) {
|
||||
if (pos == nextOpen) ++count;
|
||||
else if (!--count) { end = i; break outer; }
|
||||
else if (!--count) { end = i; endCh = pos; break outer; }
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
if (end == null || end == line + 1) return;
|
||||
if (hideEnd === true) end++;
|
||||
return end;
|
||||
return {from: {line: line, ch: startChar + 1},
|
||||
to: {line: end, ch: endCh}};
|
||||
};
|
||||
|
||||
CodeMirror.indentRangeFinder = function(cm, line) {
|
||||
var tabSize = cm.getOption("tabSize");
|
||||
var myIndent = cm.getLineHandle(line).indentation(tabSize), last;
|
||||
for (var i = line + 1, end = cm.lineCount(); i < end; ++i) {
|
||||
var handle = cm.getLineHandle(i);
|
||||
if (!/^\s*$/.test(handle.text)) {
|
||||
if (handle.indentation(tabSize) <= myIndent) break;
|
||||
last = i;
|
||||
}
|
||||
CodeMirror.indentRangeFinder = function(cm, start) {
|
||||
var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
|
||||
var myIndent = CodeMirror.countColumn(firstLine, null, tabSize);
|
||||
for (var i = start.line + 1, end = cm.lineCount(); i < end; ++i) {
|
||||
var curLine = cm.getLine(i);
|
||||
if (CodeMirror.countColumn(curLine, null, tabSize) < myIndent)
|
||||
return {from: {line: start.line, ch: firstLine.length},
|
||||
to: {line: i, ch: curLine.length}};
|
||||
}
|
||||
if (!last) return null;
|
||||
return last + 1;
|
||||
};
|
||||
|
||||
CodeMirror.newFoldFunction = function(rangeFinder, markText, hideEnd) {
|
||||
var folded = [];
|
||||
if (markText == null) markText = '<div style="position: absolute; left: 2px; color:#600">▼</div>%N%';
|
||||
|
||||
function isFolded(cm, n) {
|
||||
for (var i = 0; i < folded.length; ++i) {
|
||||
var start = cm.lineInfo(folded[i].start);
|
||||
if (!start) folded.splice(i--, 1);
|
||||
else if (start.line == n) return {pos: i, region: folded[i]};
|
||||
}
|
||||
CodeMirror.newFoldFunction = function(rangeFinder, widget) {
|
||||
if (widget == null) widget = "\u2194";
|
||||
if (typeof widget == "string") {
|
||||
var text = document.createTextNode(widget);
|
||||
widget = document.createElement("span");
|
||||
widget.appendChild(text);
|
||||
widget.className = "CodeMirror-foldmarker";
|
||||
}
|
||||
|
||||
function expand(cm, region) {
|
||||
cm.clearMarker(region.start);
|
||||
for (var i = 0; i < region.hidden.length; ++i)
|
||||
cm.showLine(region.hidden[i]);
|
||||
}
|
||||
return function(cm, pos) {
|
||||
if (typeof pos == "number") pos = {line: pos, ch: 0};
|
||||
var range = rangeFinder(cm, pos);
|
||||
if (!range) return;
|
||||
|
||||
return function(cm, line) {
|
||||
cm.operation(function() {
|
||||
var known = isFolded(cm, line);
|
||||
if (known) {
|
||||
folded.splice(known.pos, 1);
|
||||
expand(cm, known.region);
|
||||
} else {
|
||||
var end = rangeFinder(cm, line, hideEnd);
|
||||
if (end == null) return;
|
||||
var hidden = [];
|
||||
for (var i = line + 1; i < end; ++i) {
|
||||
var handle = cm.hideLine(i);
|
||||
if (handle) hidden.push(handle);
|
||||
}
|
||||
var first = cm.setMarker(line, markText);
|
||||
var region = {start: first, hidden: hidden};
|
||||
cm.onDeleteLine(first, function() { expand(cm, region); });
|
||||
folded.push(region);
|
||||
var present = cm.findMarksAt(range.from), cleared = 0;
|
||||
for (var i = 0; i < present.length; ++i) {
|
||||
if (present[i].__isFold) {
|
||||
++cleared;
|
||||
present[i].clear();
|
||||
}
|
||||
}
|
||||
if (cleared) return;
|
||||
|
||||
var myWidget = widget.cloneNode(true);
|
||||
CodeMirror.on(myWidget, "mousedown", function() {myRange.clear();});
|
||||
var myRange = cm.markText(range.from, range.to, {
|
||||
replacedWith: myWidget,
|
||||
clearOnEnter: true,
|
||||
__isFold: true
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user