annotate .cms/lib/codemirror/addon/hint/xml-hint.js @ 0:78edf6b517a0 draft

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