GPQAPP

Форк
0
132 строки · 5.6 Кб
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: https://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 matches(hint, typed, matchInMiddle) {
17
    if (matchInMiddle) return hint.indexOf(typed) >= 0;
18
    else return hint.lastIndexOf(typed, 0) == 0;
19
  }
20

21
  function getHints(cm, options) {
22
    var tags = options && options.schemaInfo;
23
    var quote = (options && options.quoteChar) || '"';
24
    var matchInMiddle = options && options.matchInMiddle;
25
    if (!tags) return;
26
    var cur = cm.getCursor(), token = cm.getTokenAt(cur);
27
    if (token.end > cur.ch) {
28
      token.end = cur.ch;
29
      token.string = token.string.slice(0, cur.ch - token.start);
30
    }
31
    var inner = CodeMirror.innerMode(cm.getMode(), token.state);
32
    if (!inner.mode.xmlCurrentTag) return
33
    var result = [], replaceToken = false, prefix;
34
    var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
35
    var tagName = tag && /^\w/.test(token.string), tagStart;
36

37
    if (tagName) {
38
      var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
39
      var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
40
      if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
41
    } else if (tag && token.string == "<") {
42
      tagType = "open";
43
    } else if (tag && token.string == "</") {
44
      tagType = "close";
45
    }
46

47
    var tagInfo = inner.mode.xmlCurrentTag(inner.state)
48
    if (!tag && !tagInfo || tagType) {
49
      if (tagName)
50
        prefix = token.string;
51
      replaceToken = tagType;
52
      var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
53
      var inner = context.length && context[context.length - 1]
54
      var curTag = inner && tags[inner]
55
      var childList = inner ? curTag && curTag.children : tags["!top"];
56
      if (childList && tagType != "close") {
57
        for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
58
          result.push("<" + childList[i]);
59
      } else if (tagType != "close") {
60
        for (var name in tags)
61
          if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
62
            result.push("<" + name);
63
      }
64
      if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
65
        result.push("</" + inner + ">");
66
    } else {
67
      // Attribute completion
68
      var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs;
69
      var globalAttrs = tags["!attrs"];
70
      if (!attrs && !globalAttrs) return;
71
      if (!attrs) {
72
        attrs = globalAttrs;
73
      } else if (globalAttrs) { // Combine tag-local and global attributes
74
        var set = {};
75
        for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
76
        for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
77
        attrs = set;
78
      }
79
      if (token.type == "string" || token.string == "=") { // A value
80
        var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
81
                                 Pos(cur.line, token.type == "string" ? token.start : token.end));
82
        var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
83
        if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
84
        if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
85
        if (token.type == "string") {
86
          prefix = token.string;
87
          var n = 0;
88
          if (/['"]/.test(token.string.charAt(0))) {
89
            quote = token.string.charAt(0);
90
            prefix = token.string.slice(1);
91
            n++;
92
          }
93
          var len = token.string.length;
94
          if (/['"]/.test(token.string.charAt(len - 1))) {
95
            quote = token.string.charAt(len - 1);
96
            prefix = token.string.substr(n, len - 2);
97
          }
98
          if (n) { // an opening quote
99
            var line = cm.getLine(cur.line);
100
            if (line.length > token.end && line.charAt(token.end) == quote) token.end++; // include a closing quote
101
          }
102
          replaceToken = true;
103
        }
104
        var returnHintsFromAtValues = function(atValues) {
105
          if (atValues)
106
            for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
107
              result.push(quote + atValues[i] + quote);
108
          return returnHints();
109
        };
110
        if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
111
        return returnHintsFromAtValues(atValues);
112
      } else { // An attribute name
113
        if (token.type == "attribute") {
114
          prefix = token.string;
115
          replaceToken = true;
116
        }
117
        for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || matches(attr, prefix, matchInMiddle)))
118
          result.push(attr);
119
      }
120
    }
121
    function returnHints() {
122
      return {
123
        list: result,
124
        from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
125
        to: replaceToken ? Pos(cur.line, token.end) : cur
126
      };
127
    }
128
    return returnHints();
129
  }
130

131
  CodeMirror.registerHelper("hint", "xml", getHints);
132
});
133

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.