File modules/editor/codemirror/addon/edit/closetag.min.js
Last commit: Tue May 22 22:39:53 2018 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 // Distributed under an MIT license: http://codemirror.net/LICENSE 3 4 /** 5 * Tag-closer extension for CodeMirror. 6 * 7 * This extension adds an "autoCloseTags" option that can be set to 8 * either true to get the default behavior, or an object to further 9 * configure its behavior. 10 * 11 * These are supported options: 12 * 13 * `whenClosing` (default true) 14 * Whether to autoclose when the '/' of a closing tag is typed. 15 * `whenOpening` (default true) 16 * Whether to autoclose the tag when the final '>' of an opening 17 * tag is typed. 18 * `dontCloseTags` (default is empty tags for HTML, none for XML) 19 * An array of tag names that should not be autoclosed. 20 * `indentTags` (default is block tags for HTML, none for XML) 21 * An array of tag names that should, when opened, cause a 22 * blank line to be added inside the tag, and the blank line and 23 * closing line to be indented. 24 * 25 * See demos/closetag.html for a usage example. 26 */ 27 28 (function(mod) { 29 if (typeof exports == "object" && typeof module == "object") // CommonJS 30 mod(require("../../lib/codemirror"), require("../fold/xml-fold")); 31 else if (typeof define == "function" && define.amd) // AMD 32 define(["../../lib/codemirror", "../fold/xml-fold"], mod); 33 else // Plain browser env 34 mod(CodeMirror); 35 })(function(CodeMirror) { 36 CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) { 37 if (old != CodeMirror.Init && old) 38 cm.removeKeyMap("autoCloseTags"); 39 if (!val) return; 40 var map = {name: "autoCloseTags"}; 41 if (typeof val != "object" || val.whenClosing) 42 map["'/'"] = function(cm) { return autoCloseSlash(cm); }; 43 if (typeof val != "object" || val.whenOpening) 44 map["'>'"] = function(cm) { return autoCloseGT(cm); }; 45 cm.addKeyMap(map); 46 }); 47 48 var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", 49 "source", "track", "wbr"]; 50 var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4", 51 "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"]; 52 53 function autoCloseGT(cm) { 54 if (cm.getOption("disableInput")) return CodeMirror.Pass; 55 var ranges = cm.listSelections(), replacements = []; 56 for (var i = 0; i < ranges.length; i++) { 57 if (!ranges[i].empty()) return CodeMirror.Pass; 58 var pos = ranges[i].head, tok = cm.getTokenAt(pos); 59 var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; 60 if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass; 61 62 var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; 63 var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); 64 var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); 65 66 var tagName = state.tagName; 67 if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch); 68 var lowerTagName = tagName.toLowerCase(); 69 // Don't process the '>' at the end of an end-tag or self-closing tag 70 if (!tagName || 71 tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || 72 tok.type == "tag" && state.type == "closeTag" || 73 tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName /> 74 dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || 75 closingTagExists(cm, tagName, pos, state, true)) 76 return CodeMirror.Pass; 77 78 var indent = indentTags && indexOf(indentTags, lowerTagName) > -1; 79 replacements[i] = {indent: indent, 80 text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">", 81 newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)}; 82 } 83 84 for (var i = ranges.length - 1; i >= 0; i--) { 85 var info = replacements[i]; 86 cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert"); 87 var sel = cm.listSelections().slice(0); 88 sel[i] = {head: info.newPos, anchor: info.newPos}; 89 cm.setSelections(sel); 90 if (info.indent) { 91 cm.indentLine(info.newPos.line, null, true); 92 cm.indentLine(info.newPos.line + 1, null, true); 93 } 94 } 95 } 96 97 function autoCloseCurrent(cm, typingSlash) { 98 var ranges = cm.listSelections(), replacements = []; 99 var head = typingSlash ? "/" : "</"; 100 for (var i = 0; i < ranges.length; i++) { 101 if (!ranges[i].empty()) return CodeMirror.Pass; 102 var pos = ranges[i].head, tok = cm.getTokenAt(pos); 103 var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; 104 if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" || 105 tok.start != pos.ch - 1)) 106 return CodeMirror.Pass; 107 // Kludge to get around the fact that we are not in XML mode 108 // when completing in JS/CSS snippet in htmlmixed mode. Does not 109 // work for other XML embedded languages (there is no general 110 // way to go from a mixed mode to its current XML state). 111 var replacement; 112 if (inner.mode.name != "xml") { 113 if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript") 114 replacement = head + "script"; 115 else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css") 116 replacement = head + "style"; 117 else 118 return CodeMirror.Pass; 119 } else { 120 if (!state.context || !state.context.tagName || 121 closingTagExists(cm, state.context.tagName, pos, state)) 122 return CodeMirror.Pass; 123 replacement = head + state.context.tagName; 124 } 125 if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">"; 126 replacements[i] = replacement; 127 } 128 cm.replaceSelections(replacements); 129 ranges = cm.listSelections(); 130 for (var i = 0; i < ranges.length; i++) 131 if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line) 132 cm.indentLine(ranges[i].head.line); 133 } 134 135 function autoCloseSlash(cm) { 136 if (cm.getOption("disableInput")) return CodeMirror.Pass; 137 return autoCloseCurrent(cm, true); 138 } 139 140 CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); }; 141 142 function indexOf(collection, elt) { 143 if (collection.indexOf) return collection.indexOf(elt); 144 for (var i = 0, e = collection.length; i < e; ++i) 145 if (collection[i] == elt) return i; 146 return -1; 147 } 148 149 // If xml-fold is loaded, we use its functionality to try and verify 150 // whether a given tag is actually unclosed. 151 function closingTagExists(cm, tagName, pos, state, newTag) { 152 if (!CodeMirror.scanForClosingTag) return false; 153 var end = Math.min(cm.lastLine() + 1, pos.line + 500); 154 var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end); 155 if (!nextClose || nextClose.tag != tagName) return false; 156 var cx = state.context; 157 // If the immediate wrapping context contains onCx instances of 158 // the same tag, a closing tag only exists if there are at least 159 // that many closing tags of that type following. 160 for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx; 161 pos = nextClose.to; 162 for (var i = 1; i < onCx; i++) { 163 var next = CodeMirror.scanForClosingTag(cm, pos, null, end); 164 if (!next || next.tag != tagName) return false; 165 pos = next.to; 166 } 167 return true; 168 } 169 });
Downloadmodules/editor/codemirror/addon/edit/closetag.min.js
History Tue, 22 May 2018 22:39:53 +0200 Jan Dankert Fix für PHP 7.2: 'Object' darf nun nicht mehr als Klassennamen verwendet werden. AUCH NICHT IN EINEM NAMESPACE! WTF, wozu habe ich das in einen verfickten Namespace gepackt? Wozu soll der sonst da sein??? Amateure. Daher nun notgedrungen unbenannt in 'BaseObject'.