Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
51007 views
1
/**
2
* Tag-closer extension for CodeMirror.
3
*
4
* This extension adds an "autoCloseTags" option that can be set to
5
* either true to get the default behavior, or an object to further
6
* configure its behavior.
7
*
8
* These are supported options:
9
*
10
* `whenClosing` (default true)
11
* Whether to autoclose when the '/' of a closing tag is typed.
12
* `whenOpening` (default true)
13
* Whether to autoclose the tag when the final '>' of an opening
14
* tag is typed.
15
* `dontCloseTags` (default is empty tags for HTML, none for XML)
16
* An array of tag names that should not be autoclosed.
17
* `indentTags` (default is block tags for HTML, none for XML)
18
* An array of tag names that should, when opened, cause a
19
* blank line to be added inside the tag, and the blank line and
20
* closing line to be indented.
21
*
22
* See demos/closetag.html for a usage example.
23
*/
24
25
(function() {
26
CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
27
if (old != CodeMirror.Init && old)
28
cm.removeKeyMap("autoCloseTags");
29
if (!val) return;
30
var map = {name: "autoCloseTags"};
31
if (typeof val != "object" || val.whenClosing)
32
map["'/'"] = function(cm) { return autoCloseSlash(cm); };
33
if (typeof val != "object" || val.whenOpening)
34
map["'>'"] = function(cm) { return autoCloseGT(cm); };
35
cm.addKeyMap(map);
36
});
37
38
var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
39
"source", "track", "wbr"];
40
var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
41
"h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
42
43
function autoCloseGT(cm) {
44
var pos = cm.getCursor(), tok = cm.getTokenAt(pos);
45
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
46
if (inner.mode.name != "xml" || !state.tagName || cm.getOption("disableInput")) return CodeMirror.Pass;
47
48
var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
49
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
50
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
51
52
var tagName = state.tagName;
53
if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
54
var lowerTagName = tagName.toLowerCase();
55
// Don't process the '>' at the end of an end-tag or self-closing tag
56
if (!tagName ||
57
tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
58
tok.type == "tag" && state.type == "closeTag" ||
59
tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />
60
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
61
CodeMirror.scanForClosingTag && CodeMirror.scanForClosingTag(cm, pos, tagName,
62
Math.min(cm.lastLine() + 1, pos.line + 50)))
63
return CodeMirror.Pass;
64
65
var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1;
66
var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1);
67
cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "</" + tagName + ">",
68
{head: curPos, anchor: curPos});
69
if (doIndent) {
70
cm.indentLine(pos.line + 1, null, true);
71
cm.indentLine(pos.line + 2, null);
72
}
73
}
74
75
function autoCloseSlash(cm) {
76
var pos = cm.getCursor(), tok = cm.getTokenAt(pos);
77
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
78
if (tok.type == "string" || tok.string.charAt(0) != "<" ||
79
tok.start != pos.ch - 1 || inner.mode.name != "xml" ||
80
cm.getOption("disableInput"))
81
return CodeMirror.Pass;
82
83
var tagName = state.context && state.context.tagName;
84
if (tagName) cm.replaceSelection("/" + tagName + ">", "end");
85
else return CodeMirror.Pass;
86
}
87
88
function indexOf(collection, elt) {
89
if (collection.indexOf) return collection.indexOf(elt);
90
for (var i = 0, e = collection.length; i < e; ++i)
91
if (collection[i] == elt) return i;
92
return -1;
93
}
94
})();
95
96