codemirror 3.14
This commit is contained in:
+325
-572
@@ -1,582 +1,335 @@
|
||||
(function () {
|
||||
function htmlHint(editor, htmlStructure, getToken) {
|
||||
var cur = editor.getCursor();
|
||||
var token = getToken(editor, cur);
|
||||
var keywords = [];
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
var k = 0;
|
||||
var from = {line: cur.line, ch: cur.ch};
|
||||
var to = {line: cur.line, ch: cur.ch};
|
||||
var flagClean = true;
|
||||
var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");
|
||||
var targets = ["_blank", "_self", "_top", "_parent"];
|
||||
var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
|
||||
var methods = ["get", "post", "put", "delete"];
|
||||
var encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
|
||||
var media = ["all", "screen", "print", "embossed", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "speech",
|
||||
"3d-glasses", "resolution [>][<][=] [X]", "device-aspect-ratio: X/Y", "orientation:portrait",
|
||||
"orientation:landscape", "device-height: [X]", "device-width: [X]"];
|
||||
var s = { attrs: {} }; // Simple tag, reused for a whole lot of tags
|
||||
|
||||
var text = editor.getRange({line: 0, ch: 0}, cur);
|
||||
|
||||
var open = text.lastIndexOf('<');
|
||||
var close = text.lastIndexOf('>');
|
||||
var tokenString = token.string.replace("<","");
|
||||
|
||||
if(open > close) {
|
||||
var last = editor.getRange({line: cur.line, ch: cur.ch - 1}, cur);
|
||||
if(last == "<") {
|
||||
for(i = 0; i < htmlStructure.length; i++) {
|
||||
keywords.push(htmlStructure[i].tag);
|
||||
}
|
||||
from.ch = token.start + 1;
|
||||
} else {
|
||||
var counter = 0;
|
||||
var found = function(token, type, position) {
|
||||
counter++;
|
||||
if(counter > 50) return;
|
||||
if(token.type == type) {
|
||||
return token;
|
||||
} else {
|
||||
position.ch = token.start;
|
||||
var newToken = editor.getTokenAt(position);
|
||||
return found(newToken, type, position);
|
||||
}
|
||||
};
|
||||
|
||||
var nodeToken = found(token, "tag", {line: cur.line, ch: cur.ch});
|
||||
var node = nodeToken.string.substring(1);
|
||||
|
||||
if(token.type === null && token.string.trim() === "") {
|
||||
for(i = 0; i < htmlStructure.length; i++) {
|
||||
if(htmlStructure[i].tag == node) {
|
||||
for(j = 0; j < htmlStructure[i].attr.length; j++) {
|
||||
keywords.push(htmlStructure[i].attr[j].key + "=\"\" ");
|
||||
}
|
||||
|
||||
for(k = 0; k < globalAttributes.length; k++) {
|
||||
keywords.push(globalAttributes[k].key + "=\"\" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(token.type == "string") {
|
||||
tokenString = tokenString.substring(1, tokenString.length - 1);
|
||||
var attributeToken = found(token, "attribute", {line: cur.line, ch: cur.ch});
|
||||
var attribute = attributeToken.string;
|
||||
|
||||
for(i = 0; i < htmlStructure.length; i++) {
|
||||
if(htmlStructure[i].tag == node) {
|
||||
for(j = 0; j < htmlStructure[i].attr.length; j++) {
|
||||
if(htmlStructure[i].attr[j].key == attribute) {
|
||||
for(k = 0; k < htmlStructure[i].attr[j].values.length; k++) {
|
||||
keywords.push(htmlStructure[i].attr[j].values[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(j = 0; j < globalAttributes.length; j++) {
|
||||
if(globalAttributes[j].key == attribute) {
|
||||
for(k = 0; k < globalAttributes[j].values.length; k++) {
|
||||
keywords.push(globalAttributes[j].values[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
from.ch = token.start + 1;
|
||||
} else if(token.type == "attribute") {
|
||||
for(i = 0; i < htmlStructure.length; i++) {
|
||||
if(htmlStructure[i].tag == node) {
|
||||
for(j = 0; j < htmlStructure[i].attr.length; j++) {
|
||||
keywords.push(htmlStructure[i].attr[j].key + "=\"\" ");
|
||||
}
|
||||
|
||||
for(k = 0; k < globalAttributes.length; k++) {
|
||||
keywords.push(globalAttributes[k].key + "=\"\" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
from.ch = token.start;
|
||||
} else if(token.type == "tag") {
|
||||
for(i = 0; i < htmlStructure.length; i++) {
|
||||
keywords.push(htmlStructure[i].tag);
|
||||
}
|
||||
|
||||
from.ch = token.start + 1;
|
||||
}
|
||||
var data = {
|
||||
a: {
|
||||
attrs: {
|
||||
href: null, ping: null, type: null,
|
||||
media: media,
|
||||
target: targets,
|
||||
hreflang: langs
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < htmlStructure.length; i++) {
|
||||
keywords.push("<" + htmlStructure[i].tag);
|
||||
},
|
||||
abbr: s,
|
||||
acronym: s,
|
||||
address: s,
|
||||
applet: s,
|
||||
area: {
|
||||
attrs: {
|
||||
alt: null, coords: null, href: null, target: null, ping: null,
|
||||
media: media, hreflang: langs, type: null,
|
||||
shape: ["default", "rect", "circle", "poly"]
|
||||
}
|
||||
},
|
||||
article: s,
|
||||
aside: s,
|
||||
audio: {
|
||||
attrs: {
|
||||
src: null, mediagroup: null,
|
||||
crossorigin: ["anonymous", "use-credentials"],
|
||||
preload: ["none", "metadata", "auto"],
|
||||
autoplay: ["", "autoplay"],
|
||||
loop: ["", "loop"],
|
||||
controls: ["", "controls"]
|
||||
}
|
||||
},
|
||||
b: s,
|
||||
base: { attrs: { href: null, target: targets } },
|
||||
basefont: s,
|
||||
bdi: s,
|
||||
bdo: s,
|
||||
big: s,
|
||||
blockquote: { attrs: { cite: null } },
|
||||
body: s,
|
||||
br: s,
|
||||
button: {
|
||||
attrs: {
|
||||
form: null, formaction: null, name: null, value: null,
|
||||
autofocus: ["", "autofocus"],
|
||||
disabled: ["", "autofocus"],
|
||||
formenctype: encs,
|
||||
formmethod: methods,
|
||||
formnovalidate: ["", "novalidate"],
|
||||
formtarget: targets,
|
||||
type: ["submit", "reset", "button"]
|
||||
}
|
||||
},
|
||||
canvas: { attrs: { width: null, height: null } },
|
||||
caption: s,
|
||||
center: s,
|
||||
cite: s,
|
||||
code: s,
|
||||
col: { attrs: { span: null } },
|
||||
colgroup: { attrs: { span: null } },
|
||||
command: {
|
||||
attrs: {
|
||||
type: ["command", "checkbox", "radio"],
|
||||
label: null, icon: null, radiogroup: null, command: null, title: null,
|
||||
disabled: ["", "disabled"],
|
||||
checked: ["", "checked"]
|
||||
}
|
||||
},
|
||||
data: { attrs: { value: null } },
|
||||
datagrid: { attrs: { disabled: ["", "disabled"], multiple: ["", "multiple"] } },
|
||||
datalist: { attrs: { data: null } },
|
||||
dd: s,
|
||||
del: { attrs: { cite: null, datetime: null } },
|
||||
details: { attrs: { open: ["", "open"] } },
|
||||
dfn: s,
|
||||
dir: s,
|
||||
div: s,
|
||||
dl: s,
|
||||
dt: s,
|
||||
em: s,
|
||||
embed: { attrs: { src: null, type: null, width: null, height: null } },
|
||||
eventsource: { attrs: { src: null } },
|
||||
fieldset: { attrs: { disabled: ["", "disabled"], form: null, name: null } },
|
||||
figcaption: s,
|
||||
figure: s,
|
||||
font: s,
|
||||
footer: s,
|
||||
form: {
|
||||
attrs: {
|
||||
action: null, name: null,
|
||||
"accept-charset": charsets,
|
||||
autocomplete: ["on", "off"],
|
||||
enctype: encs,
|
||||
method: methods,
|
||||
novalidate: ["", "novalidate"],
|
||||
target: targets
|
||||
}
|
||||
},
|
||||
frame: s,
|
||||
frameset: s,
|
||||
h1: s, h2: s, h3: s, h4: s, h5: s, h6: s,
|
||||
head: {
|
||||
attrs: {},
|
||||
children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
|
||||
},
|
||||
header: s,
|
||||
hgroup: s,
|
||||
hr: s,
|
||||
html: {
|
||||
attrs: { manifest: null },
|
||||
children: ["head", "body"]
|
||||
},
|
||||
i: s,
|
||||
iframe: {
|
||||
attrs: {
|
||||
src: null, srcdoc: null, name: null, width: null, height: null,
|
||||
sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
|
||||
seamless: ["", "seamless"]
|
||||
}
|
||||
},
|
||||
img: {
|
||||
attrs: {
|
||||
alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
|
||||
crossorigin: ["anonymous", "use-credentials"]
|
||||
}
|
||||
},
|
||||
input: {
|
||||
attrs: {
|
||||
alt: null, dirname: null, form: null, formaction: null,
|
||||
height: null, list: null, max: null, maxlength: null, min: null,
|
||||
name: null, pattern: null, placeholder: null, size: null, src: null,
|
||||
step: null, value: null, width: null,
|
||||
accept: ["audio/*", "video/*", "image/*"],
|
||||
autocomplete: ["on", "off"],
|
||||
autofocus: ["", "autofocus"],
|
||||
checked: ["", "checked"],
|
||||
disabled: ["", "disabled"],
|
||||
formenctype: encs,
|
||||
formmethod: methods,
|
||||
formnovalidate: ["", "novalidate"],
|
||||
formtarget: targets,
|
||||
multiple: ["", "multiple"],
|
||||
readonly: ["", "readonly"],
|
||||
required: ["", "required"],
|
||||
type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
|
||||
"week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
|
||||
"file", "submit", "image", "reset", "button"]
|
||||
}
|
||||
},
|
||||
ins: { attrs: { cite: null, datetime: null } },
|
||||
kbd: s,
|
||||
keygen: {
|
||||
attrs: {
|
||||
challenge: null, form: null, name: null,
|
||||
autofocus: ["", "autofocus"],
|
||||
disabled: ["", "disabled"],
|
||||
keytype: ["RSA"]
|
||||
}
|
||||
},
|
||||
label: { attrs: { "for": null, form: null } },
|
||||
legend: s,
|
||||
li: { attrs: { value: null } },
|
||||
link: {
|
||||
attrs: {
|
||||
href: null, type: null,
|
||||
hreflang: langs,
|
||||
media: media,
|
||||
sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
|
||||
}
|
||||
},
|
||||
map: { attrs: { name: null } },
|
||||
mark: s,
|
||||
menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
|
||||
meta: {
|
||||
attrs: {
|
||||
content: null,
|
||||
charset: charsets,
|
||||
name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
|
||||
"http-equiv": ["content-language", "content-type", "default-style", "refresh"]
|
||||
}
|
||||
},
|
||||
meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
|
||||
nav: s,
|
||||
noframes: s,
|
||||
noscript: s,
|
||||
object: {
|
||||
attrs: {
|
||||
data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
|
||||
typemustmatch: ["", "typemustmatch"]
|
||||
}
|
||||
},
|
||||
ol: { attrs: { reversed: ["", "reversed"], start: null, type: ["1", "a", "A", "i", "I"] } },
|
||||
optgroup: { attrs: { disabled: ["", "disabled"], label: null } },
|
||||
option: { attrs: { disabled: ["", "disabled"], label: null, selected: ["", "selected"], value: null } },
|
||||
output: { attrs: { "for": null, form: null, name: null } },
|
||||
p: s,
|
||||
param: { attrs: { name: null, value: null } },
|
||||
pre: s,
|
||||
progress: { attrs: { value: null, max: null } },
|
||||
q: { attrs: { cite: null } },
|
||||
rp: s,
|
||||
rt: s,
|
||||
ruby: s,
|
||||
s: s,
|
||||
samp: s,
|
||||
script: {
|
||||
attrs: {
|
||||
type: ["text/javascript"],
|
||||
src: null,
|
||||
async: ["", "async"],
|
||||
defer: ["", "defer"],
|
||||
charset: charsets
|
||||
}
|
||||
},
|
||||
section: s,
|
||||
select: {
|
||||
attrs: {
|
||||
form: null, name: null, size: null,
|
||||
autofocus: ["", "autofocus"],
|
||||
disabled: ["", "disabled"],
|
||||
multiple: ["", "multiple"]
|
||||
}
|
||||
},
|
||||
small: s,
|
||||
source: { attrs: { src: null, type: null, media: null } },
|
||||
span: s,
|
||||
strike: s,
|
||||
strong: s,
|
||||
style: {
|
||||
attrs: {
|
||||
type: ["text/css"],
|
||||
media: media,
|
||||
scoped: null
|
||||
}
|
||||
},
|
||||
sub: s,
|
||||
summary: s,
|
||||
sup: s,
|
||||
table: s,
|
||||
tbody: s,
|
||||
td: { attrs: { colspan: null, rowspan: null, headers: null } },
|
||||
textarea: {
|
||||
attrs: {
|
||||
dirname: null, form: null, maxlength: null, name: null, placeholder: null,
|
||||
rows: null, cols: null,
|
||||
autofocus: ["", "autofocus"],
|
||||
disabled: ["", "disabled"],
|
||||
readonly: ["", "readonly"],
|
||||
required: ["", "required"],
|
||||
wrap: ["soft", "hard"]
|
||||
}
|
||||
},
|
||||
tfoot: s,
|
||||
th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
|
||||
thead: s,
|
||||
time: { attrs: { datetime: null } },
|
||||
title: s,
|
||||
tr: s,
|
||||
track: {
|
||||
attrs: {
|
||||
src: null, label: null, "default": null,
|
||||
kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
|
||||
srclang: langs
|
||||
}
|
||||
},
|
||||
tt: s,
|
||||
u: s,
|
||||
ul: s,
|
||||
"var": s,
|
||||
video: {
|
||||
attrs: {
|
||||
src: null, poster: null, width: null, height: null,
|
||||
crossorigin: ["anonymous", "use-credentials"],
|
||||
preload: ["auto", "metadata", "none"],
|
||||
autoplay: ["", "autoplay"],
|
||||
mediagroup: ["movie"],
|
||||
muted: ["", "muted"],
|
||||
controls: ["", "controls"]
|
||||
}
|
||||
},
|
||||
wbr: s
|
||||
};
|
||||
|
||||
tokenString = ("<" + tokenString).trim();
|
||||
from.ch = token.start;
|
||||
}
|
||||
|
||||
if(flagClean === true && tokenString.trim() === "") {
|
||||
flagClean = false;
|
||||
}
|
||||
|
||||
if(flagClean) {
|
||||
keywords = cleanResults(tokenString, keywords);
|
||||
}
|
||||
|
||||
return {list: keywords, from: from, to: to};
|
||||
var globalAttrs = {
|
||||
accesskey: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
|
||||
"class": null,
|
||||
contenteditable: ["true", "false"],
|
||||
contextmenu: null,
|
||||
dir: ["ltr", "rtl", "auto"],
|
||||
draggable: ["true", "false", "auto"],
|
||||
dropzone: ["copy", "move", "link", "string:", "file:"],
|
||||
hidden: ["hidden"],
|
||||
id: null,
|
||||
inert: ["inert"],
|
||||
itemid: null,
|
||||
itemprop: null,
|
||||
itemref: null,
|
||||
itemscope: ["itemscope"],
|
||||
itemtype: null,
|
||||
lang: ["en", "es"],
|
||||
spellcheck: ["true", "false"],
|
||||
style: null,
|
||||
tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
|
||||
title: null,
|
||||
translate: ["yes", "no"],
|
||||
onclick: null,
|
||||
rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"]
|
||||
};
|
||||
function populate(obj) {
|
||||
for (var attr in globalAttrs) if (globalAttrs.hasOwnProperty(attr))
|
||||
obj.attrs[attr] = globalAttrs[attr];
|
||||
}
|
||||
|
||||
populate(s);
|
||||
for (var tag in data) if (data.hasOwnProperty(tag) && data[tag] != s)
|
||||
populate(data[tag]);
|
||||
|
||||
var cleanResults = function(text, keywords) {
|
||||
var results = [];
|
||||
var i = 0;
|
||||
|
||||
for(i = 0; i < keywords.length; i++) {
|
||||
if(keywords[i].substring(0, text.length) == text) {
|
||||
results.push(keywords[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
var htmlStructure = [
|
||||
{tag: '!DOCTYPE', attr: []},
|
||||
{tag: 'a', attr: [
|
||||
{key: 'href', values: ["#"]},
|
||||
{key: 'target', values: ["_blank","_self","_top","_parent"]},
|
||||
{key: 'ping', values: [""]},
|
||||
{key: 'media', values: ["#"]},
|
||||
{key: 'hreflang', values: ["en","es"]},
|
||||
{key: 'type', values: []}
|
||||
]},
|
||||
{tag: 'abbr', attr: []},
|
||||
{tag: 'acronym', attr: []},
|
||||
{tag: 'address', attr: []},
|
||||
{tag: 'applet', attr: []},
|
||||
{tag: 'area', attr: [
|
||||
{key: 'alt', values: [""]},
|
||||
{key: 'coords', values: ["rect: left, top, right, bottom","circle: center-x, center-y, radius","poly: x1, y1, x2, y2, ..."]},
|
||||
{key: 'shape', values: ["default","rect","circle","poly"]},
|
||||
{key: 'href', values: ["#"]},
|
||||
{key: 'target', values: ["#"]},
|
||||
{key: 'ping', values: []},
|
||||
{key: 'media', values: []},
|
||||
{key: 'hreflang', values: []},
|
||||
{key: 'type', values: []}
|
||||
|
||||
]},
|
||||
{tag: 'article', attr: []},
|
||||
{tag: 'aside', attr: []},
|
||||
{tag: 'audio', attr: [
|
||||
{key: 'src', values: []},
|
||||
{key: 'crossorigin', values: ["anonymous","use-credentials"]},
|
||||
{key: 'preload', values: ["none","metadata","auto"]},
|
||||
{key: 'autoplay', values: ["","autoplay"]},
|
||||
{key: 'mediagroup', values: []},
|
||||
{key: 'loop', values: ["","loop"]},
|
||||
{key: 'controls', values: ["","controls"]}
|
||||
]},
|
||||
{tag: 'b', attr: []},
|
||||
{tag: 'base', attr: [
|
||||
{key: 'href', values: ["#"]},
|
||||
{key: 'target', values: ["_blank","_self","_top","_parent"]}
|
||||
]},
|
||||
{tag: 'basefont', attr: []},
|
||||
{tag: 'bdi', attr: []},
|
||||
{tag: 'bdo', attr: []},
|
||||
{tag: 'big', attr: []},
|
||||
{tag: 'blockquote', attr: [
|
||||
{key: 'cite', values: ["http://"]}
|
||||
]},
|
||||
{tag: 'body', attr: []},
|
||||
{tag: 'br', attr: []},
|
||||
{tag: 'button', attr: [
|
||||
{key: 'autofocus', values: ["","autofocus"]},
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'form', values: []},
|
||||
{key: 'formaction', values: []},
|
||||
{key: 'formenctype', values: ["application/x-www-form-urlencoded","multipart/form-data","text/plain"]},
|
||||
{key: 'formmethod', values: ["get","post","put","delete"]},
|
||||
{key: 'formnovalidate', values: ["","novalidate"]},
|
||||
{key: 'formtarget', values: ["_blank","_self","_top","_parent"]},
|
||||
{key: 'name', values: []},
|
||||
{key: 'type', values: ["submit","reset","button"]},
|
||||
{key: 'value', values: []}
|
||||
]},
|
||||
{tag: 'canvas', attr: [
|
||||
{key: 'width', values: []},
|
||||
{key: 'height', values: []}
|
||||
]},
|
||||
{tag: 'caption', attr: []},
|
||||
{tag: 'center', attr: []},
|
||||
{tag: 'cite', attr: []},
|
||||
{tag: 'code', attr: []},
|
||||
{tag: 'col', attr: [
|
||||
{key: 'span', values: []}
|
||||
]},
|
||||
{tag: 'colgroup', attr: [
|
||||
{key: 'span', values: []}
|
||||
]},
|
||||
{tag: 'command', attr: [
|
||||
{key: 'type', values: ["command","checkbox","radio"]},
|
||||
{key: 'label', values: []},
|
||||
{key: 'icon', values: []},
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'checked', values: ["","checked"]},
|
||||
{key: 'radiogroup', values: []},
|
||||
{key: 'command', values: []},
|
||||
{key: 'title', values: []}
|
||||
]},
|
||||
{tag: 'data', attr: [
|
||||
{key: 'value', values: []}
|
||||
]},
|
||||
{tag: 'datagrid', attr: [
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'multiple', values: ["","multiple"]}
|
||||
]},
|
||||
{tag: 'datalist', attr: [
|
||||
{key: 'data', values: []}
|
||||
]},
|
||||
{tag: 'dd', attr: []},
|
||||
{tag: 'del', attr: [
|
||||
{key: 'cite', values: []},
|
||||
{key: 'datetime', values: []}
|
||||
]},
|
||||
{tag: 'details', attr: [
|
||||
{key: 'open', values: ["","open"]}
|
||||
]},
|
||||
{tag: 'dfn', attr: []},
|
||||
{tag: 'dir', attr: []},
|
||||
{tag: 'div', attr: [
|
||||
{key: 'id', values: []},
|
||||
{key: 'class', values: []},
|
||||
{key: 'style', values: []}
|
||||
]},
|
||||
{tag: 'dl', attr: []},
|
||||
{tag: 'dt', attr: []},
|
||||
{tag: 'em', attr: []},
|
||||
{tag: 'embed', attr: [
|
||||
{key: 'src', values: []},
|
||||
{key: 'type', values: []},
|
||||
{key: 'width', values: []},
|
||||
{key: 'height', values: []}
|
||||
]},
|
||||
{tag: 'eventsource', attr: [
|
||||
{key: 'src', values: []}
|
||||
]},
|
||||
{tag: 'fieldset', attr: [
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'form', values: []},
|
||||
{key: 'name', values: []}
|
||||
]},
|
||||
{tag: 'figcaption', attr: []},
|
||||
{tag: 'figure', attr: []},
|
||||
{tag: 'font', attr: []},
|
||||
{tag: 'footer', attr: []},
|
||||
{tag: 'form', attr: [
|
||||
{key: 'accept-charset', values: ["UNKNOWN","utf-8"]},
|
||||
{key: 'action', values: []},
|
||||
{key: 'autocomplete', values: ["on","off"]},
|
||||
{key: 'enctype', values: ["application/x-www-form-urlencoded","multipart/form-data","text/plain"]},
|
||||
{key: 'method', values: ["get","post","put","delete","dialog"]},
|
||||
{key: 'name', values: []},
|
||||
{key: 'novalidate', values: ["","novalidate"]},
|
||||
{key: 'target', values: ["_blank","_self","_top","_parent"]}
|
||||
]},
|
||||
{tag: 'frame', attr: []},
|
||||
{tag: 'frameset', attr: []},
|
||||
{tag: 'h1', attr: []},
|
||||
{tag: 'h2', attr: []},
|
||||
{tag: 'h3', attr: []},
|
||||
{tag: 'h4', attr: []},
|
||||
{tag: 'h5', attr: []},
|
||||
{tag: 'h6', attr: []},
|
||||
{tag: 'head', attr: []},
|
||||
{tag: 'header', attr: []},
|
||||
{tag: 'hgroup', attr: []},
|
||||
{tag: 'hr', attr: []},
|
||||
{tag: 'html', attr: [
|
||||
{key: 'manifest', values: []}
|
||||
]},
|
||||
{tag: 'i', attr: []},
|
||||
{tag: 'iframe', attr: [
|
||||
{key: 'src', values: []},
|
||||
{key: 'srcdoc', values: []},
|
||||
{key: 'name', values: []},
|
||||
{key: 'sandbox', values: ["allow-top-navigation","allow-same-origin","allow-forms","allow-scripts"]},
|
||||
{key: 'seamless', values: ["","seamless"]},
|
||||
{key: 'width', values: []},
|
||||
{key: 'height', values: []}
|
||||
]},
|
||||
{tag: 'img', attr: [
|
||||
{key: 'alt', values: []},
|
||||
{key: 'src', values: []},
|
||||
{key: 'crossorigin', values: ["anonymous","use-credentials"]},
|
||||
{key: 'ismap', values: []},
|
||||
{key: 'usemap', values: []},
|
||||
{key: 'width', values: []},
|
||||
{key: 'height', values: []}
|
||||
]},
|
||||
{tag: 'input', attr: [
|
||||
{key: 'accept', values: ["audio/*","video/*","image/*"]},
|
||||
{key: 'alt', values: []},
|
||||
{key: 'autocomplete', values: ["on","off"]},
|
||||
{key: 'autofocus', values: ["","autofocus"]},
|
||||
{key: 'checked', values: ["","checked"]},
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'dirname', values: []},
|
||||
{key: 'form', values: []},
|
||||
{key: 'formaction', values: []},
|
||||
{key: 'formenctype', values: ["application/x-www-form-urlencoded","multipart/form-data","text/plain"]},
|
||||
{key: 'formmethod', values: ["get","post","put","delete"]},
|
||||
{key: 'formnovalidate', values: ["","novalidate"]},
|
||||
{key: 'formtarget', values: ["_blank","_self","_top","_parent"]},
|
||||
{key: 'height', values: []},
|
||||
{key: 'list', values: []},
|
||||
{key: 'max', values: []},
|
||||
{key: 'maxlength', values: []},
|
||||
{key: 'min', values: []},
|
||||
{key: 'multiple', values: ["","multiple"]},
|
||||
{key: 'name', values: []},
|
||||
{key: 'pattern', values: []},
|
||||
{key: 'placeholder', values: []},
|
||||
{key: 'readonly', values: ["","readonly"]},
|
||||
{key: 'required', values: ["","required"]},
|
||||
{key: 'size', values: []},
|
||||
{key: 'src', values: []},
|
||||
{key: 'step', values: []},
|
||||
{key: 'type', values: [
|
||||
"hidden","text","search","tel","url","email","password","datetime","date","month","week","time","datetime-local",
|
||||
"number","range","color","checkbox","radio","file","submit","image","reset","button"
|
||||
]},
|
||||
{key: 'value', values: []},
|
||||
{key: 'width', values: []}
|
||||
]},
|
||||
{tag: 'ins', attr: [
|
||||
{key: 'cite', values: []},
|
||||
{key: 'datetime', values: []}
|
||||
]},
|
||||
{tag: 'kbd', attr: []},
|
||||
{tag: 'keygen', attr: [
|
||||
{key: 'autofocus', values: ["","autofocus"]},
|
||||
{key: 'challenge', values: []},
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'form', values: []},
|
||||
{key: 'keytype', values: ["RSA"]},
|
||||
{key: 'name', values: []}
|
||||
]},
|
||||
{tag: 'label', attr: [
|
||||
{key: 'for', values: []},
|
||||
{key: 'form', values: []}
|
||||
]},
|
||||
{tag: 'legend', attr: []},
|
||||
{tag: 'li', attr: [
|
||||
{key: 'value', values: []}
|
||||
]},
|
||||
{tag: 'link', attr: [
|
||||
{key: 'href', values: []},
|
||||
{key: 'hreflang', values: ["en","es"]},
|
||||
{key: 'media', values: [
|
||||
"all","screen","print","embossed","braille","handheld","print","projection","screen","tty","tv","speech","3d-glasses",
|
||||
"resolution [>][<][=] [X]dpi","resolution [>][<][=] [X]dpcm","device-aspect-ratio: 16/9","device-aspect-ratio: 4/3",
|
||||
"device-aspect-ratio: 32/18","device-aspect-ratio: 1280/720","device-aspect-ratio: 2560/1440","orientation:portrait",
|
||||
"orientation:landscape","device-height: [X]px","device-width: [X]px","-webkit-min-device-pixel-ratio: 2"
|
||||
]},
|
||||
{key: 'type', values: []},
|
||||
{key: 'sizes', values: ["all","16x16","16x16 32x32","16x16 32x32 64x64"]}
|
||||
]},
|
||||
{tag: 'map', attr: [
|
||||
{key: 'name', values: []}
|
||||
]},
|
||||
{tag: 'mark', attr: []},
|
||||
{tag: 'menu', attr: [
|
||||
{key: 'type', values: ["list","context","toolbar"]},
|
||||
{key: 'label', values: []}
|
||||
]},
|
||||
{tag: 'meta', attr: [
|
||||
{key: 'charset', attr: ["utf-8"]},
|
||||
{key: 'name', attr: ["viewport","application-name","author","description","generator","keywords"]},
|
||||
{key: 'content', attr: ["","width=device-width","initial-scale=1, maximum-scale=1, minimun-scale=1, user-scale=no"]},
|
||||
{key: 'http-equiv', attr: ["content-language","content-type","default-style","refresh"]}
|
||||
]},
|
||||
{tag: 'meter', attr: [
|
||||
{key: 'value', values: []},
|
||||
{key: 'min', values: []},
|
||||
{key: 'low', values: []},
|
||||
{key: 'high', values: []},
|
||||
{key: 'max', values: []},
|
||||
{key: 'optimum', values: []}
|
||||
]},
|
||||
{tag: 'nav', attr: []},
|
||||
{tag: 'noframes', attr: []},
|
||||
{tag: 'noscript', attr: []},
|
||||
{tag: 'object', attr: [
|
||||
{key: 'data', values: []},
|
||||
{key: 'type', values: []},
|
||||
{key: 'typemustmatch', values: ["","typemustmatch"]},
|
||||
{key: 'name', values: []},
|
||||
{key: 'usemap', values: []},
|
||||
{key: 'form', values: []},
|
||||
{key: 'width', values: []},
|
||||
{key: 'height', values: []}
|
||||
]},
|
||||
{tag: 'ol', attr: [
|
||||
{key: 'reversed', values: ["", "reversed"]},
|
||||
{key: 'start', values: []},
|
||||
{key: 'type', values: ["1","a","A","i","I"]}
|
||||
]},
|
||||
{tag: 'optgroup', attr: [
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'label', values: []}
|
||||
]},
|
||||
{tag: 'option', attr: [
|
||||
{key: 'disabled', values: ["", "disabled"]},
|
||||
{key: 'label', values: []},
|
||||
{key: 'selected', values: ["", "selected"]},
|
||||
{key: 'value', values: []}
|
||||
]},
|
||||
{tag: 'output', attr: [
|
||||
{key: 'for', values: []},
|
||||
{key: 'form', values: []},
|
||||
{key: 'name', values: []}
|
||||
]},
|
||||
{tag: 'p', attr: []},
|
||||
{tag: 'param', attr: [
|
||||
{key: 'name', values: []},
|
||||
{key: 'value', values: []}
|
||||
]},
|
||||
{tag: 'pre', attr: []},
|
||||
{tag: 'progress', attr: [
|
||||
{key: 'value', values: []},
|
||||
{key: 'max', values: []}
|
||||
]},
|
||||
{tag: 'q', attr: [
|
||||
{key: 'cite', values: []}
|
||||
]},
|
||||
{tag: 'rp', attr: []},
|
||||
{tag: 'rt', attr: []},
|
||||
{tag: 'ruby', attr: []},
|
||||
{tag: 's', attr: []},
|
||||
{tag: 'samp', attr: []},
|
||||
{tag: 'script', attr: [
|
||||
{key: 'type', values: ["text/javascript"]},
|
||||
{key: 'src', values: []},
|
||||
{key: 'async', values: ["","async"]},
|
||||
{key: 'defer', values: ["","defer"]},
|
||||
{key: 'charset', values: ["utf-8"]}
|
||||
]},
|
||||
{tag: 'section', attr: []},
|
||||
{tag: 'select', attr: [
|
||||
{key: 'autofocus', values: ["", "autofocus"]},
|
||||
{key: 'disabled', values: ["", "disabled"]},
|
||||
{key: 'form', values: []},
|
||||
{key: 'multiple', values: ["", "multiple"]},
|
||||
{key: 'name', values: []},
|
||||
{key: 'size', values: []}
|
||||
]},
|
||||
{tag: 'small', attr: []},
|
||||
{tag: 'source', attr: [
|
||||
{key: 'src', values: []},
|
||||
{key: 'type', values: []},
|
||||
{key: 'media', values: []}
|
||||
]},
|
||||
{tag: 'span', attr: []},
|
||||
{tag: 'strike', attr: []},
|
||||
{tag: 'strong', attr: []},
|
||||
{tag: 'style', attr: [
|
||||
{key: 'type', values: ["text/css"]},
|
||||
{key: 'media', values: ["all","braille","print","projection","screen","speech"]},
|
||||
{key: 'scoped', values: []}
|
||||
]},
|
||||
{tag: 'sub', attr: []},
|
||||
{tag: 'summary', attr: []},
|
||||
{tag: 'sup', attr: []},
|
||||
{tag: 'table', attr: [
|
||||
{key: 'border', values: []}
|
||||
]},
|
||||
{tag: 'tbody', attr: []},
|
||||
{tag: 'td', attr: [
|
||||
{key: 'colspan', values: []},
|
||||
{key: 'rowspan', values: []},
|
||||
{key: 'headers', values: []}
|
||||
]},
|
||||
{tag: 'textarea', attr: [
|
||||
{key: 'autofocus', values: ["","autofocus"]},
|
||||
{key: 'disabled', values: ["","disabled"]},
|
||||
{key: 'dirname', values: []},
|
||||
{key: 'form', values: []},
|
||||
{key: 'maxlength', values: []},
|
||||
{key: 'name', values: []},
|
||||
{key: 'placeholder', values: []},
|
||||
{key: 'readonly', values: ["","readonly"]},
|
||||
{key: 'required', values: ["","required"]},
|
||||
{key: 'rows', values: []},
|
||||
{key: 'cols', values: []},
|
||||
{key: 'wrap', values: ["soft","hard"]}
|
||||
]},
|
||||
{tag: 'tfoot', attr: []},
|
||||
{tag: 'th', attr: [
|
||||
{key: 'colspan', values: []},
|
||||
{key: 'rowspan', values: []},
|
||||
{key: 'headers', values: []},
|
||||
{key: 'scope', values: ["row","col","rowgroup","colgroup"]}
|
||||
]},
|
||||
{tag: 'thead', attr: []},
|
||||
{tag: 'time', attr: [
|
||||
{key: 'datetime', values: []}
|
||||
]},
|
||||
{tag: 'title', attr: []},
|
||||
{tag: 'tr', attr: []},
|
||||
{tag: 'track', attr: [
|
||||
{key: 'kind', values: ["subtitles","captions","descriptions","chapters","metadata"]},
|
||||
{key: 'src', values: []},
|
||||
{key: 'srclang', values: ["en","es"]},
|
||||
{key: 'label', values: []},
|
||||
{key: 'default', values: []}
|
||||
]},
|
||||
{tag: 'tt', attr: []},
|
||||
{tag: 'u', attr: []},
|
||||
{tag: 'ul', attr: []},
|
||||
{tag: 'var', attr: []},
|
||||
{tag: 'video', attr: [
|
||||
{key: "src", values: []},
|
||||
{key: "crossorigin", values: ["anonymous","use-credentials"]},
|
||||
{key: "poster", values: []},
|
||||
{key: "preload", values: ["auto","metadata","none"]},
|
||||
{key: "autoplay", values: ["","autoplay"]},
|
||||
{key: "mediagroup", values: ["movie"]},
|
||||
{key: "loop", values: ["","loop"]},
|
||||
{key: "muted", values: ["","muted"]},
|
||||
{key: "controls", values: ["","controls"]},
|
||||
{key: "width", values: []},
|
||||
{key: "height", values: []}
|
||||
]},
|
||||
{tag: 'wbr', attr: []}
|
||||
];
|
||||
|
||||
var globalAttributes = [
|
||||
{key: "accesskey", values: ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9"]},
|
||||
{key: "class", values: []},
|
||||
{key: "contenteditable", values: ["true", "false"]},
|
||||
{key: "contextmenu", values: []},
|
||||
{key: "dir", values: ["ltr","rtl","auto"]},
|
||||
{key: "draggable", values: ["true","false","auto"]},
|
||||
{key: "dropzone", values: ["copy","move","link","string:","file:"]},
|
||||
{key: "hidden", values: ["hidden"]},
|
||||
{key: "id", values: []},
|
||||
{key: "inert", values: ["inert"]},
|
||||
{key: "itemid", values: []},
|
||||
{key: "itemprop", values: []},
|
||||
{key: "itemref", values: []},
|
||||
{key: "itemscope", values: ["itemscope"]},
|
||||
{key: "itemtype", values: []},
|
||||
{key: "lang", values: ["en","es"]},
|
||||
{key: "spellcheck", values: ["true","false"]},
|
||||
{key: "style", values: []},
|
||||
{key: "tabindex", values: ["1","2","3","4","5","6","7","8","9"]},
|
||||
{key: "title", values: []},
|
||||
{key: "translate", values: ["yes","no"]},
|
||||
{key: "onclick", values: []},
|
||||
{key: 'rel', values: ["stylesheet","alternate","author","bookmark","help","license","next","nofollow","noreferrer","prefetch","prev","search","tag"]}
|
||||
];
|
||||
|
||||
CodeMirror.htmlHint = function(editor) {
|
||||
if(String.prototype.trim == undefined) {
|
||||
String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g, '');};
|
||||
}
|
||||
return htmlHint(editor, htmlStructure, function (e, cur) { return e.getTokenAt(cur); });
|
||||
CodeMirror.htmlSchema = data;
|
||||
CodeMirror.htmlHint = function(cm, options) {
|
||||
var local = {schemaInfo: data};
|
||||
if (options) for (var opt in options) local[opt] = options[opt];
|
||||
return CodeMirror.xmlHint(cm, local);
|
||||
};
|
||||
})();
|
||||
|
||||
+200
-110
@@ -1,57 +1,168 @@
|
||||
CodeMirror.showHint = function(cm, getHints, options) {
|
||||
if (!options) options = {};
|
||||
var startCh = cm.getCursor().ch, continued = false;
|
||||
var closeOn = options.closeCharacters || /[\s()\[\]{};:]/;
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
function startHinting() {
|
||||
CodeMirror.showHint = function(cm, getHints, options) {
|
||||
// We want a single cursor position.
|
||||
if (cm.somethingSelected()) return;
|
||||
|
||||
if (options.async)
|
||||
getHints(cm, showHints, options);
|
||||
if (cm.state.completionActive) cm.state.completionActive.close();
|
||||
|
||||
var completion = cm.state.completionActive = new Completion(cm, getHints, options || {});
|
||||
CodeMirror.signal(cm, "startCompletion", cm);
|
||||
if (completion.options.async)
|
||||
getHints(cm, function(hints) { completion.showHints(hints); }, completion.options);
|
||||
else
|
||||
return showHints(getHints(cm, options));
|
||||
return completion.showHints(getHints(cm, completion.options));
|
||||
};
|
||||
|
||||
function Completion(cm, getHints, options) {
|
||||
this.cm = cm;
|
||||
this.getHints = getHints;
|
||||
this.options = options;
|
||||
this.widget = this.onClose = null;
|
||||
}
|
||||
|
||||
Completion.prototype = {
|
||||
close: function() {
|
||||
if (!this.active()) return;
|
||||
|
||||
if (this.widget) this.widget.close();
|
||||
if (this.onClose) this.onClose();
|
||||
this.cm.state.completionActive = null;
|
||||
CodeMirror.signal(this.cm, "endCompletion", this.cm);
|
||||
},
|
||||
|
||||
active: function() {
|
||||
return this.cm.state.completionActive == this;
|
||||
},
|
||||
|
||||
pick: function(data, i) {
|
||||
var completion = data.list[i];
|
||||
if (completion.hint) completion.hint(this.cm, data, completion);
|
||||
else this.cm.replaceRange(getText(completion), data.from, data.to);
|
||||
this.close();
|
||||
},
|
||||
|
||||
showHints: function(data) {
|
||||
if (!data || !data.list.length || !this.active()) return this.close();
|
||||
|
||||
if (this.options.completeSingle != false && data.list.length == 1)
|
||||
this.pick(data, 0);
|
||||
else
|
||||
this.showWidget(data);
|
||||
},
|
||||
|
||||
showWidget: function(data) {
|
||||
this.widget = new Widget(this, data);
|
||||
CodeMirror.signal(data, "shown");
|
||||
|
||||
var debounce = null, completion = this, finished;
|
||||
var closeOn = this.options.closeCharacters || /[\s()\[\]{};:>,]/;
|
||||
var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
|
||||
|
||||
function done() {
|
||||
if (finished) return;
|
||||
finished = true;
|
||||
completion.close();
|
||||
completion.cm.off("cursorActivity", activity);
|
||||
CodeMirror.signal(data, "close");
|
||||
}
|
||||
function isDone() {
|
||||
if (finished) return true;
|
||||
if (!completion.widget) { done(); return true; }
|
||||
}
|
||||
|
||||
function update() {
|
||||
if (isDone()) return;
|
||||
if (completion.options.async)
|
||||
completion.getHints(completion.cm, finishUpdate, completion.options);
|
||||
else
|
||||
finishUpdate(completion.getHints(completion.cm, completion.options));
|
||||
}
|
||||
function finishUpdate(data) {
|
||||
if (isDone()) return;
|
||||
if (!data || !data.list.length) return done();
|
||||
completion.widget.close();
|
||||
completion.widget = new Widget(completion, data);
|
||||
}
|
||||
|
||||
function activity() {
|
||||
clearTimeout(debounce);
|
||||
var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
|
||||
if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
|
||||
pos.ch < startPos.ch || completion.cm.somethingSelected() ||
|
||||
(pos.ch && closeOn.test(line.charAt(pos.ch - 1))))
|
||||
completion.close();
|
||||
else
|
||||
debounce = setTimeout(update, 170);
|
||||
}
|
||||
this.cm.on("cursorActivity", activity);
|
||||
this.onClose = done;
|
||||
}
|
||||
};
|
||||
|
||||
function getText(completion) {
|
||||
if (typeof completion == "string") return completion;
|
||||
else return completion.text;
|
||||
}
|
||||
|
||||
function pickCompletion(cm, data, completion) {
|
||||
if (completion.hint) completion.hint(cm, data, completion);
|
||||
else cm.replaceRange(getText(completion), data.from, data.to);
|
||||
function buildKeyMap(options, handle) {
|
||||
var baseMap = {
|
||||
Up: function() {handle.moveFocus(-1);},
|
||||
Down: function() {handle.moveFocus(1);},
|
||||
PageUp: function() {handle.moveFocus(-handle.menuSize());},
|
||||
PageDown: function() {handle.moveFocus(handle.menuSize());},
|
||||
Home: function() {handle.setFocus(0);},
|
||||
End: function() {handle.setFocus(handle.length);},
|
||||
Enter: handle.pick,
|
||||
Tab: handle.pick,
|
||||
Esc: handle.close
|
||||
};
|
||||
var ourMap = options.customKeys ? {} : baseMap;
|
||||
function addBinding(key, val) {
|
||||
var bound;
|
||||
if (typeof val != "string")
|
||||
bound = function(cm) { return val(cm, handle); };
|
||||
// This mechanism is deprecated
|
||||
else if (baseMap.hasOwnProperty(val))
|
||||
bound = baseMap[val];
|
||||
else
|
||||
bound = val;
|
||||
ourMap[key] = bound;
|
||||
}
|
||||
if (options.customKeys)
|
||||
for (var key in options.customKeys) if (options.customKeys.hasOwnProperty(key))
|
||||
addBinding(key, options.customKeys[key]);
|
||||
if (options.extraKeys)
|
||||
for (var key in options.extraKeys) if (options.extraKeys.hasOwnProperty(key))
|
||||
addBinding(key, options.extraKeys[key]);
|
||||
return ourMap;
|
||||
}
|
||||
|
||||
function showHints(data) {
|
||||
if (!data || !data.list.length) return;
|
||||
var completions = data.list;
|
||||
// When there is only one completion, use it directly.
|
||||
if (!continued && options.completeSingle !== false && completions.length == 1) {
|
||||
pickCompletion(cm, data, completions[0]);
|
||||
CodeMirror.signal(data, "close");
|
||||
return true;
|
||||
}
|
||||
function Widget(completion, data) {
|
||||
this.completion = completion;
|
||||
this.data = data;
|
||||
var widget = this, cm = completion.cm, options = completion.options;
|
||||
|
||||
// Build the select widget
|
||||
var hints = document.createElement("ul"), selectedHint = 0;
|
||||
var hints = this.hints = document.createElement("ul");
|
||||
hints.className = "CodeMirror-hints";
|
||||
this.selectedHint = 0;
|
||||
|
||||
var completions = data.list;
|
||||
for (var i = 0; i < completions.length; ++i) {
|
||||
var elt = hints.appendChild(document.createElement("li")), completion = completions[i];
|
||||
var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
|
||||
var className = "CodeMirror-hint" + (i ? "" : " CodeMirror-hint-active");
|
||||
if (completion.className != null) className = completion.className + " " + className;
|
||||
if (cur.className != null) className = cur.className + " " + className;
|
||||
elt.className = className;
|
||||
if (completion.render) completion.render(elt, data, completion);
|
||||
else elt.appendChild(document.createTextNode(completion.displayText || getText(completion)));
|
||||
if (cur.render) cur.render(elt, data, cur);
|
||||
else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
|
||||
elt.hintId = i;
|
||||
}
|
||||
|
||||
var pos = cm.cursorCoords(options.alignWithWord !== false ? data.from : null);
|
||||
var left = pos.left, top = pos.bottom, below = true;
|
||||
hints.style.left = left + "px";
|
||||
hints.style.top = top + "px";
|
||||
document.body.appendChild(hints);
|
||||
CodeMirror.signal(data, "shown");
|
||||
|
||||
// If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
|
||||
var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
|
||||
var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
|
||||
@@ -75,106 +186,85 @@ CodeMirror.showHint = function(cm, getHints, options) {
|
||||
}
|
||||
hints.style.top = (top = pos.bottom - overlapY) + "px";
|
||||
}
|
||||
(options.container || document.body).appendChild(hints);
|
||||
|
||||
function changeActive(i) {
|
||||
i = Math.max(0, Math.min(i, completions.length - 1));
|
||||
if (selectedHint == i) return;
|
||||
var node = hints.childNodes[selectedHint];
|
||||
node.className = node.className.replace(" CodeMirror-hint-active", "");
|
||||
node = hints.childNodes[selectedHint = i];
|
||||
node.className += " CodeMirror-hint-active";
|
||||
if (node.offsetTop < hints.scrollTop)
|
||||
hints.scrollTop = node.offsetTop - 3;
|
||||
else if (node.offsetTop + node.offsetHeight > hints.scrollTop + hints.clientHeight)
|
||||
hints.scrollTop = node.offsetTop + node.offsetHeight - hints.clientHeight + 3;
|
||||
CodeMirror.signal(data, "select", completions[selectedHint], node);
|
||||
cm.addKeyMap(this.keyMap = buildKeyMap(options, {
|
||||
moveFocus: function(n) { widget.changeActive(widget.selectedHint + n); },
|
||||
setFocus: function(n) { widget.changeActive(n); },
|
||||
menuSize: function() { return widget.screenAmount(); },
|
||||
length: completions.length,
|
||||
close: function() { completion.close(); },
|
||||
pick: function() { widget.pick(); }
|
||||
}));
|
||||
|
||||
if (options.closeOnUnfocus !== false) {
|
||||
var closingOnBlur;
|
||||
cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
|
||||
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
|
||||
}
|
||||
|
||||
function screenAmount() {
|
||||
return Math.floor(hints.clientHeight / hints.firstChild.offsetHeight) || 1;
|
||||
}
|
||||
|
||||
var ourMap, baseMap = {
|
||||
Up: function() {changeActive(selectedHint - 1);},
|
||||
Down: function() {changeActive(selectedHint + 1);},
|
||||
PageUp: function() {changeActive(selectedHint - screenAmount());},
|
||||
PageDown: function() {changeActive(selectedHint + screenAmount());},
|
||||
Home: function() {changeActive(0);},
|
||||
End: function() {changeActive(completions.length - 1);},
|
||||
Enter: pick,
|
||||
Tab: pick,
|
||||
Esc: close
|
||||
};
|
||||
if (options.customKeys) {
|
||||
ourMap = {};
|
||||
for (var key in options.customKeys) if (options.customKeys.hasOwnProperty(key)) {
|
||||
var val = options.customKeys[key];
|
||||
if (baseMap.hasOwnProperty(val)) val = baseMap[val];
|
||||
ourMap[key] = val;
|
||||
}
|
||||
} else ourMap = baseMap;
|
||||
|
||||
cm.addKeyMap(ourMap);
|
||||
cm.on("cursorActivity", cursorActivity);
|
||||
var closingOnBlur;
|
||||
function onBlur(){ closingOnBlur = setTimeout(close, 100); };
|
||||
function onFocus(){ clearTimeout(closingOnBlur); };
|
||||
cm.on("blur", onBlur);
|
||||
cm.on("focus", onFocus);
|
||||
var startScroll = cm.getScrollInfo();
|
||||
function onScroll() {
|
||||
cm.on("scroll", this.onScroll = function() {
|
||||
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
|
||||
var newTop = top + startScroll.top - curScroll.top, point = newTop;
|
||||
var newTop = top + startScroll.top - curScroll.top;
|
||||
var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
|
||||
if (!below) point += hints.offsetHeight;
|
||||
if (point <= editor.top || point >= editor.bottom) return close();
|
||||
if (point <= editor.top || point >= editor.bottom) return completion.close();
|
||||
hints.style.top = newTop + "px";
|
||||
hints.style.left = (left + startScroll.left - curScroll.left) + "px";
|
||||
}
|
||||
cm.on("scroll", onScroll);
|
||||
});
|
||||
|
||||
CodeMirror.on(hints, "dblclick", function(e) {
|
||||
var t = e.target || e.srcElement;
|
||||
if (t.hintId != null) {selectedHint = t.hintId; pick();}
|
||||
if (t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
|
||||
});
|
||||
CodeMirror.on(hints, "click", function(e) {
|
||||
var t = e.target || e.srcElement;
|
||||
if (t.hintId != null) changeActive(t.hintId);
|
||||
if (t.hintId != null) widget.changeActive(t.hintId);
|
||||
});
|
||||
CodeMirror.on(hints, "mousedown", function() {
|
||||
setTimeout(function(){cm.focus();}, 20);
|
||||
});
|
||||
|
||||
var done = false, once;
|
||||
function close(willContinue) {
|
||||
if (done) return;
|
||||
done = true;
|
||||
clearTimeout(once);
|
||||
hints.parentNode.removeChild(hints);
|
||||
cm.removeKeyMap(ourMap);
|
||||
cm.off("cursorActivity", cursorActivity);
|
||||
cm.off("blur", onBlur);
|
||||
cm.off("focus", onFocus);
|
||||
cm.off("scroll", onScroll);
|
||||
if (willContinue !== true) CodeMirror.signal(data, "close");
|
||||
}
|
||||
function pick() {
|
||||
pickCompletion(cm, data, completions[selectedHint]);
|
||||
close();
|
||||
}
|
||||
var once, lastPos = cm.getCursor(), lastLen = cm.getLine(lastPos.line).length;
|
||||
function cursorActivity() {
|
||||
clearTimeout(once);
|
||||
|
||||
var pos = cm.getCursor(), line = cm.getLine(pos.line);
|
||||
if (pos.line != lastPos.line || line.length - pos.ch != lastLen - lastPos.ch ||
|
||||
pos.ch < startCh || cm.somethingSelected() ||
|
||||
(pos.ch && closeOn.test(line.charAt(pos.ch - 1))))
|
||||
close();
|
||||
else
|
||||
once = setTimeout(function(){close(true); continued = true; startHinting();}, 70);
|
||||
}
|
||||
CodeMirror.signal(data, "select", completions[0], hints.firstChild);
|
||||
return true;
|
||||
}
|
||||
|
||||
return startHinting();
|
||||
};
|
||||
Widget.prototype = {
|
||||
close: function() {
|
||||
if (this.completion.widget != this) return;
|
||||
this.completion.widget = null;
|
||||
this.hints.parentNode.removeChild(this.hints);
|
||||
this.completion.cm.removeKeyMap(this.keyMap);
|
||||
|
||||
var cm = this.completion.cm;
|
||||
if (this.completion.options.closeOnUnfocus !== false) {
|
||||
cm.off("blur", this.onBlur);
|
||||
cm.off("focus", this.onFocus);
|
||||
}
|
||||
cm.off("scroll", this.onScroll);
|
||||
},
|
||||
|
||||
pick: function() {
|
||||
this.completion.pick(this.data, this.selectedHint);
|
||||
},
|
||||
|
||||
changeActive: function(i) {
|
||||
i = Math.max(0, Math.min(i, this.data.list.length - 1));
|
||||
if (this.selectedHint == i) return;
|
||||
var node = this.hints.childNodes[this.selectedHint];
|
||||
node.className = node.className.replace(" CodeMirror-hint-active", "");
|
||||
node = this.hints.childNodes[this.selectedHint = i];
|
||||
node.className += " CodeMirror-hint-active";
|
||||
if (node.offsetTop < this.hints.scrollTop)
|
||||
this.hints.scrollTop = node.offsetTop - 3;
|
||||
else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
|
||||
this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
|
||||
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
|
||||
},
|
||||
|
||||
screenAmount: function() {
|
||||
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
+58
-111
@@ -1,118 +1,65 @@
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.xmlHints = [];
|
||||
var Pos = CodeMirror.Pos;
|
||||
|
||||
CodeMirror.xmlHint = function(cm) {
|
||||
|
||||
var cursor = cm.getCursor();
|
||||
|
||||
if (cursor.ch > 0) {
|
||||
|
||||
var text = cm.getRange(CodeMirror.Pos(0, 0), cursor);
|
||||
var typed = '';
|
||||
var simbol = '';
|
||||
for(var i = text.length - 1; i >= 0; i--) {
|
||||
if(text[i] == ' ' || text[i] == '<') {
|
||||
simbol = text[i];
|
||||
break;
|
||||
}
|
||||
else {
|
||||
typed = text[i] + typed;
|
||||
}
|
||||
}
|
||||
|
||||
text = text.slice(0, text.length - typed.length);
|
||||
|
||||
var path = getActiveElement(text) + simbol;
|
||||
var hints = CodeMirror.xmlHints[path];
|
||||
|
||||
if(typeof hints === 'undefined')
|
||||
hints = [''];
|
||||
else {
|
||||
hints = hints.slice(0);
|
||||
for (var i = hints.length - 1; i >= 0; i--) {
|
||||
if(hints[i].indexOf(typed) != 0)
|
||||
hints.splice(i, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
list: hints,
|
||||
from: CodeMirror.Pos(cursor.line, cursor.ch - typed.length),
|
||||
to: cursor
|
||||
};
|
||||
CodeMirror.xmlHint = function(cm, options) {
|
||||
var tags = options && options.schemaInfo;
|
||||
var quote = (options && options.quoteChar) || '"';
|
||||
if (!tags) return;
|
||||
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
|
||||
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
|
||||
if (inner.mode.name != "xml") return;
|
||||
var result = [], replaceToken = false, prefix;
|
||||
var isTag = token.string.charAt(0) == "<";
|
||||
if (!inner.state.tagName || isTag) { // Tag completion
|
||||
if (isTag) {
|
||||
prefix = token.string.slice(1);
|
||||
replaceToken = true;
|
||||
}
|
||||
var cx = inner.state.context, curTag = cx && tags[cx.tagName];
|
||||
var childList = cx ? curTag && curTag.children : tags["!top"];
|
||||
if (childList) {
|
||||
for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].indexOf(prefix) == 0)
|
||||
result.push("<" + childList[i]);
|
||||
} else {
|
||||
for (var name in tags) if (tags.hasOwnProperty(name) && name != "!top" && (!prefix || name.indexOf(prefix) == 0))
|
||||
result.push("<" + name);
|
||||
}
|
||||
if (cx && (!prefix || ("/" + cx.tagName).indexOf(prefix) == 0))
|
||||
result.push("</" + cx.tagName + ">");
|
||||
} else {
|
||||
// Attribute completion
|
||||
var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
|
||||
if (!attrs) return;
|
||||
if (token.type == "string" || token.string == "=") { // A value
|
||||
var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
|
||||
Pos(cur.line, token.type == "string" ? token.start : token.end));
|
||||
var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
|
||||
if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
|
||||
if (token.type == "string") {
|
||||
prefix = token.string;
|
||||
if (/['"]/.test(token.string.charAt(0))) {
|
||||
quote = token.string.charAt(0);
|
||||
prefix = token.string.slice(1);
|
||||
}
|
||||
replaceToken = true;
|
||||
}
|
||||
};
|
||||
|
||||
var getActiveElement = function(text) {
|
||||
|
||||
var element = '';
|
||||
|
||||
if(text.length >= 0) {
|
||||
|
||||
var regex = new RegExp('<([^!?][^\\s/>]*)[\\s\\S]*?>', 'g');
|
||||
|
||||
var matches = [];
|
||||
var match;
|
||||
while ((match = regex.exec(text)) != null) {
|
||||
matches.push({
|
||||
tag: match[1],
|
||||
selfclose: (match[0].slice(match[0].length - 2) === '/>')
|
||||
});
|
||||
}
|
||||
|
||||
for (var i = matches.length - 1, skip = 0; i >= 0; i--) {
|
||||
|
||||
var item = matches[i];
|
||||
|
||||
if (item.tag[0] == '/')
|
||||
{
|
||||
skip++;
|
||||
}
|
||||
else if (item.selfclose == false)
|
||||
{
|
||||
if (skip > 0)
|
||||
{
|
||||
skip--;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = '<' + item.tag + '>' + element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
element += getOpenTag(text);
|
||||
for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].indexOf(prefix) == 0)
|
||||
result.push(quote + atValues[i] + quote);
|
||||
} else { // An attribute name
|
||||
if (token.type == "attribute") {
|
||||
prefix = token.string;
|
||||
replaceToken = true;
|
||||
}
|
||||
|
||||
return element;
|
||||
for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.indexOf(prefix) == 0))
|
||||
result.push(attr);
|
||||
}
|
||||
}
|
||||
return {
|
||||
list: result,
|
||||
from: replaceToken ? Pos(cur.line, token.start) : cur,
|
||||
to: replaceToken ? Pos(cur.line, token.end) : cur
|
||||
};
|
||||
|
||||
var getOpenTag = function(text) {
|
||||
|
||||
var open = text.lastIndexOf('<');
|
||||
var close = text.lastIndexOf('>');
|
||||
|
||||
if (close < open)
|
||||
{
|
||||
text = text.slice(open);
|
||||
|
||||
if(text != '<') {
|
||||
|
||||
var space = text.indexOf(' ');
|
||||
if(space < 0)
|
||||
space = text.indexOf('\t');
|
||||
if(space < 0)
|
||||
space = text.indexOf('\n');
|
||||
|
||||
if (space < 0)
|
||||
space = text.length;
|
||||
|
||||
return text.slice(0, space);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
};
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user