[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/vendor/codemirror/addon/edit/ -> closetag.js (source)

   1  // CodeMirror, copyright (c) by Marijn Haverbeke and others
   2  // Distributed under an MIT license: https://codemirror.net/5/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   * `emptyTags` (default is none)
  25   *   An array of XML tag names that should be autoclosed with '/>'.
  26   *
  27   * See demos/closetag.html for a usage example.
  28   */
  29  
  30  (function(mod) {
  31    if (typeof exports == "object" && typeof module == "object") // CommonJS
  32      mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
  33    else if (typeof define == "function" && define.amd) // AMD
  34      define(["../../lib/codemirror", "../fold/xml-fold"], mod);
  35    else // Plain browser env
  36      mod(CodeMirror);
  37  })(function(CodeMirror) {
  38    CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
  39      if (old != CodeMirror.Init && old)
  40        cm.removeKeyMap("autoCloseTags");
  41      if (!val) return;
  42      var map = {name: "autoCloseTags"};
  43      if (typeof val != "object" || val.whenClosing !== false)
  44        map["'/'"] = function(cm) { return autoCloseSlash(cm); };
  45      if (typeof val != "object" || val.whenOpening !== false)
  46        map["'>'"] = function(cm) { return autoCloseGT(cm); };
  47      cm.addKeyMap(map);
  48    });
  49  
  50    var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
  51                         "source", "track", "wbr"];
  52    var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
  53                      "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
  54  
  55    function autoCloseGT(cm) {
  56      if (cm.getOption("disableInput")) return CodeMirror.Pass;
  57      var ranges = cm.listSelections(), replacements = [];
  58      var opt = cm.getOption("autoCloseTags");
  59      for (var i = 0; i < ranges.length; i++) {
  60        if (!ranges[i].empty()) return CodeMirror.Pass;
  61        var pos = ranges[i].head, tok = cm.getTokenAt(pos);
  62        var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
  63        var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state)
  64        var tagName = tagInfo && tagInfo.name
  65        if (!tagName) return CodeMirror.Pass
  66  
  67        var html = inner.mode.configuration == "html";
  68        var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
  69        var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
  70  
  71        if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
  72        var lowerTagName = tagName.toLowerCase();
  73        // Don't process the '>' at the end of an end-tag or self-closing tag
  74        if (!tagName ||
  75            tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
  76            tok.type == "tag" && tagInfo.close ||
  77            tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like <someTagName />
  78            dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
  79            closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true))
  80          return CodeMirror.Pass;
  81  
  82        var emptyTags = typeof opt == "object" && opt.emptyTags;
  83        if (emptyTags && indexOf(emptyTags, tagName) > -1) {
  84          replacements[i] = { text: "/>", newPos: CodeMirror.Pos(pos.line, pos.ch + 2) };
  85          continue;
  86        }
  87  
  88        var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
  89        replacements[i] = {indent: indent,
  90                           text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
  91                           newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
  92      }
  93  
  94      var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnAutoClose);
  95      for (var i = ranges.length - 1; i >= 0; i--) {
  96        var info = replacements[i];
  97        cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
  98        var sel = cm.listSelections().slice(0);
  99        sel[i] = {head: info.newPos, anchor: info.newPos};
 100        cm.setSelections(sel);
 101        if (!dontIndentOnAutoClose && info.indent) {
 102          cm.indentLine(info.newPos.line, null, true);
 103          cm.indentLine(info.newPos.line + 1, null, true);
 104        }
 105      }
 106    }
 107  
 108    function autoCloseCurrent(cm, typingSlash) {
 109      var ranges = cm.listSelections(), replacements = [];
 110      var head = typingSlash ? "/" : "</";
 111      var opt = cm.getOption("autoCloseTags");
 112      var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnSlash);
 113      for (var i = 0; i < ranges.length; i++) {
 114        if (!ranges[i].empty()) return CodeMirror.Pass;
 115        var pos = ranges[i].head, tok = cm.getTokenAt(pos);
 116        var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
 117        if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
 118                            tok.start != pos.ch - 1))
 119          return CodeMirror.Pass;
 120        // Kludge to get around the fact that we are not in XML mode
 121        // when completing in JS/CSS snippet in htmlmixed mode. Does not
 122        // work for other XML embedded languages (there is no general
 123        // way to go from a mixed mode to its current XML state).
 124        var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
 125        if (mixed && inner.mode.name == "javascript") {
 126          replacement = head + "script";
 127        } else if (mixed && inner.mode.name == "css") {
 128          replacement = head + "style";
 129        } else {
 130          var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
 131          var top = context.length ? context[context.length - 1] : ""
 132          if (!context || (context.length && closingTagExists(cm, context, top, pos)))
 133            return CodeMirror.Pass;
 134          replacement = head + top
 135        }
 136        if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
 137        replacements[i] = replacement;
 138      }
 139      cm.replaceSelections(replacements);
 140      ranges = cm.listSelections();
 141      if (!dontIndentOnAutoClose) {
 142          for (var i = 0; i < ranges.length; i++)
 143              if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
 144                  cm.indentLine(ranges[i].head.line);
 145      }
 146    }
 147  
 148    function autoCloseSlash(cm) {
 149      if (cm.getOption("disableInput")) return CodeMirror.Pass;
 150      return autoCloseCurrent(cm, true);
 151    }
 152  
 153    CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
 154  
 155    function indexOf(collection, elt) {
 156      if (collection.indexOf) return collection.indexOf(elt);
 157      for (var i = 0, e = collection.length; i < e; ++i)
 158        if (collection[i] == elt) return i;
 159      return -1;
 160    }
 161  
 162    // If xml-fold is loaded, we use its functionality to try and verify
 163    // whether a given tag is actually unclosed.
 164    function closingTagExists(cm, context, tagName, pos, newTag) {
 165      if (!CodeMirror.scanForClosingTag) return false;
 166      var end = Math.min(cm.lastLine() + 1, pos.line + 500);
 167      var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
 168      if (!nextClose || nextClose.tag != tagName) return false;
 169      // If the immediate wrapping context contains onCx instances of
 170      // the same tag, a closing tag only exists if there are at least
 171      // that many closing tags of that type following.
 172      var onCx = newTag ? 1 : 0
 173      for (var i = context.length - 1; i >= 0; i--) {
 174        if (context[i] == tagName) ++onCx
 175        else break
 176      }
 177      pos = nextClose.to;
 178      for (var i = 1; i < onCx; i++) {
 179        var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
 180        if (!next || next.tag != tagName) return false;
 181        pos = next.to;
 182      }
 183      return true;
 184    }
 185  });


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer