openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

xml-hint.min.js (4735B)


      1 // CodeMirror, copyright (c) by Marijn Haverbeke and others
      2 // Distributed under an MIT license: http://codemirror.net/LICENSE
      3 
      4 (function(mod) {
      5   if (typeof exports == "object" && typeof module == "object") // CommonJS
      6     mod(require("../../lib/codemirror"));
      7   else if (typeof define == "function" && define.amd) // AMD
      8     define(["../../lib/codemirror"], mod);
      9   else // Plain browser env
     10     mod(CodeMirror);
     11 })(function(CodeMirror) {
     12   "use strict";
     13 
     14   var Pos = CodeMirror.Pos;
     15 
     16   function getHints(cm, options) {
     17     var tags = options && options.schemaInfo;
     18     var quote = (options && options.quoteChar) || '"';
     19     if (!tags) return;
     20     var cur = cm.getCursor(), token = cm.getTokenAt(cur);
     21     if (token.end > cur.ch) {
     22       token.end = cur.ch;
     23       token.string = token.string.slice(0, cur.ch - token.start);
     24     }
     25     var inner = CodeMirror.innerMode(cm.getMode(), token.state);
     26     if (inner.mode.name != "xml") return;
     27     var result = [], replaceToken = false, prefix;
     28     var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
     29     var tagName = tag && /^\w/.test(token.string), tagStart;
     30 
     31     if (tagName) {
     32       var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
     33       var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
     34       if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
     35     } else if (tag && token.string == "<") {
     36       tagType = "open";
     37     } else if (tag && token.string == "</") {
     38       tagType = "close";
     39     }
     40 
     41     if (!tag && !inner.state.tagName || tagType) {
     42       if (tagName)
     43         prefix = token.string;
     44       replaceToken = tagType;
     45       var cx = inner.state.context, curTag = cx && tags[cx.tagName];
     46       var childList = cx ? curTag && curTag.children : tags["!top"];
     47       if (childList && tagType != "close") {
     48         for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
     49           result.push("<" + childList[i]);
     50       } else if (tagType != "close") {
     51         for (var name in tags)
     52           if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
     53             result.push("<" + name);
     54       }
     55       if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))
     56         result.push("</" + cx.tagName + ">");
     57     } else {
     58       // Attribute completion
     59       var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
     60       var globalAttrs = tags["!attrs"];
     61       if (!attrs && !globalAttrs) return;
     62       if (!attrs) {
     63         attrs = globalAttrs;
     64       } else if (globalAttrs) { // Combine tag-local and global attributes
     65         var set = {};
     66         for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
     67         for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
     68         attrs = set;
     69       }
     70       if (token.type == "string" || token.string == "=") { // A value
     71         var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
     72                                  Pos(cur.line, token.type == "string" ? token.start : token.end));
     73         var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
     74         if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
     75         if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
     76         if (token.type == "string") {
     77           prefix = token.string;
     78           var n = 0;
     79           if (/['"]/.test(token.string.charAt(0))) {
     80             quote = token.string.charAt(0);
     81             prefix = token.string.slice(1);
     82             n++;
     83           }
     84           var len = token.string.length;
     85           if (/['"]/.test(token.string.charAt(len - 1))) {
     86             quote = token.string.charAt(len - 1);
     87             prefix = token.string.substr(n, len - 2);
     88           }
     89           replaceToken = true;
     90         }
     91         for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0)
     92           result.push(quote + atValues[i] + quote);
     93       } else { // An attribute name
     94         if (token.type == "attribute") {
     95           prefix = token.string;
     96           replaceToken = true;
     97         }
     98         for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0))
     99           result.push(attr);
    100       }
    101     }
    102     return {
    103       list: result,
    104       from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
    105       to: replaceToken ? Pos(cur.line, token.end) : cur
    106     };
    107   }
    108 
    109   CodeMirror.registerHelper("hint", "xml", getHints);
    110 });