360 lines
15 KiB
JavaScript
Executable File
360 lines
15 KiB
JavaScript
Executable File
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Distributed under the BSD license:
|
|
*
|
|
* Copyright (c) 2010, Ajax.org B.V.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* * Neither the name of Ajax.org B.V. nor the
|
|
* names of its contributors may be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
define(function(require, exports, module) {
|
|
"use strict";
|
|
|
|
var TokenIterator = require("../token_iterator").TokenIterator;
|
|
|
|
var commonAttributes = [
|
|
"accesskey",
|
|
"class",
|
|
"contenteditable",
|
|
"contextmenu",
|
|
"dir",
|
|
"draggable",
|
|
"dropzone",
|
|
"hidden",
|
|
"id",
|
|
"inert",
|
|
"itemid",
|
|
"itemprop",
|
|
"itemref",
|
|
"itemscope",
|
|
"itemtype",
|
|
"lang",
|
|
"spellcheck",
|
|
"style",
|
|
"tabindex",
|
|
"title",
|
|
"translate"
|
|
];
|
|
|
|
var eventAttributes = [
|
|
"onabort",
|
|
"onblur",
|
|
"oncancel",
|
|
"oncanplay",
|
|
"oncanplaythrough",
|
|
"onchange",
|
|
"onclick",
|
|
"onclose",
|
|
"oncontextmenu",
|
|
"oncuechange",
|
|
"ondblclick",
|
|
"ondrag",
|
|
"ondragend",
|
|
"ondragenter",
|
|
"ondragleave",
|
|
"ondragover",
|
|
"ondragstart",
|
|
"ondrop",
|
|
"ondurationchange",
|
|
"onemptied",
|
|
"onended",
|
|
"onerror",
|
|
"onfocus",
|
|
"oninput",
|
|
"oninvalid",
|
|
"onkeydown",
|
|
"onkeypress",
|
|
"onkeyup",
|
|
"onload",
|
|
"onloadeddata",
|
|
"onloadedmetadata",
|
|
"onloadstart",
|
|
"onmousedown",
|
|
"onmousemove",
|
|
"onmouseout",
|
|
"onmouseover",
|
|
"onmouseup",
|
|
"onmousewheel",
|
|
"onpause",
|
|
"onplay",
|
|
"onplaying",
|
|
"onprogress",
|
|
"onratechange",
|
|
"onreset",
|
|
"onscroll",
|
|
"onseeked",
|
|
"onseeking",
|
|
"onselect",
|
|
"onshow",
|
|
"onstalled",
|
|
"onsubmit",
|
|
"onsuspend",
|
|
"ontimeupdate",
|
|
"onvolumechange",
|
|
"onwaiting"
|
|
];
|
|
|
|
var globalAttributes = commonAttributes.concat(eventAttributes);
|
|
|
|
var attributeMap = {
|
|
"a": {"href": 1, "target": {"_blank": 1, "top": 1}, "ping": 1, "rel": {"nofollow": 1, "alternate": 1, "author": 1, "bookmark": 1, "help": 1, "license": 1, "next": 1, "noreferrer": 1, "prefetch": 1, "prev": 1, "search": 1, "tag": 1}, "media": 1, "hreflang": 1, "type": 1},
|
|
"abbr": {},
|
|
"address": {},
|
|
"area": {"shape": 1, "coords": 1, "href": 1, "hreflang": 1, "alt": 1, "target": 1, "media": 1, "rel": 1, "ping": 1, "type": 1},
|
|
"article": {"pubdate": 1},
|
|
"aside": {},
|
|
"audio": {"src": 1, "autobuffer": 1, "autoplay": {"autoplay": 1}, "loop": {"loop": 1}, "controls": {"controls": 1}, "muted": {"muted": 1}, "preload": {"auto": 1, "metadata": 1, "none": 1 }},
|
|
"b": {},
|
|
"base": {"href": 1, "target": 1},
|
|
"bdi": {},
|
|
"bdo": {},
|
|
"blockquote": {"cite": 1},
|
|
"body": {"onafterprint": 1, "onbeforeprint": 1, "onbeforeunload": 1, "onhashchange": 1, "onmessage": 1, "onoffline": 1, "onpopstate": 1, "onredo": 1, "onresize": 1, "onstorage": 1, "onundo": 1, "onunload": 1},
|
|
"br": {},
|
|
"button": {"autofocus": 1, "disabled": {"disabled": 1}, "form": 1, "formaction": 1, "formenctype": 1, "formmethod": 1, "formnovalidate": 1, "formtarget": 1, "name": 1, "value": 1, "type": {"button": 1, "submit": 1}},
|
|
"canvas": {"width": 1, "height": 1},
|
|
"caption": {},
|
|
"cite": {},
|
|
"code": {},
|
|
"col": {"span": 1},
|
|
"colgroup": {"span": 1},
|
|
"command": {"type": 1, "label": 1, "icon": 1, "disabled": 1, "checked": 1, "radiogroup": 1, "command": 1},
|
|
"data": {},
|
|
"datalist": {},
|
|
"dd": {},
|
|
"del": {"cite": 1, "datetime": 1},
|
|
"details": {"open": 1},
|
|
"dfn": {},
|
|
"dialog": {"open": 1},
|
|
"div": {},
|
|
"dl": {},
|
|
"dt": {},
|
|
"em": {},
|
|
"embed": {"src": 1, "height": 1, "width": 1, "type": 1},
|
|
"fieldset": {"disabled": 1, "form": 1, "name": 1},
|
|
"figcaption": {},
|
|
"figure": {},
|
|
"footer": {},
|
|
"form": {"accept-charset": 1, "action": 1, "autocomplete": 1, "enctype": {"multipart/form-data": 1, "application/x-www-form-urlencoded": 1}, "method": {"get": 1, "post": 1}, "name": 1, "novalidate": 1, "target": {"_blank": 1, "top": 1}},
|
|
"h1": {},
|
|
"h2": {},
|
|
"h3": {},
|
|
"h4": {},
|
|
"h5": {},
|
|
"h6": {},
|
|
"head": {},
|
|
"header": {},
|
|
"hr": {},
|
|
"html": {"manifest": 1},
|
|
"i": {},
|
|
"iframe": {"name": 1, "src": 1, "height": 1, "width": 1, "sandbox": {"allow-same-origin": 1, "allow-top-navigation": 1, "allow-forms": 1, "allow-scripts": 1}, "seamless": {"seamless": 1}},
|
|
"img": {"alt": 1, "src": 1, "height": 1, "width": 1, "usemap": 1, "ismap": 1},
|
|
"input": {
|
|
"type": {"text": 1, "password": 1, "hidden": 1, "checkbox": 1, "submit": 1, "radio": 1, "file": 1, "button": 1, "reset": 1, "image": 31, "color": 1, "date": 1, "datetime": 1, "datetime-local": 1, "email": 1, "month": 1, "number": 1, "range": 1, "search": 1, "tel": 1, "time": 1, "url": 1, "week": 1},
|
|
"accept": 1, "alt": 1, "autocomplete": {"on": 1, "off": 1}, "autofocus": {"autofocus": 1}, "checked": {"checked": 1}, "disabled": {"disabled": 1}, "form": 1, "formaction": 1, "formenctype": {"application/x-www-form-urlencoded": 1, "multipart/form-data": 1, "text/plain": 1}, "formmethod": {"get": 1, "post": 1}, "formnovalidate": {"formnovalidate": 1}, "formtarget": {"_blank": 1, "_self": 1, "_parent": 1, "_top": 1}, "height": 1, "list": 1, "max": 1, "maxlength": 1, "min": 1, "multiple": {"multiple": 1}, "name": 1, "pattern": 1, "placeholder": 1, "readonly": {"readonly": 1}, "required": {"required": 1}, "size": 1, "src": 1, "step": 1, "width": 1, "files": 1, "value": 1},
|
|
"ins": {"cite": 1, "datetime": 1},
|
|
"kbd": {},
|
|
"keygen": {"autofocus": 1, "challenge": {"challenge": 1}, "disabled": {"disabled": 1}, "form": 1, "keytype": {"rsa": 1, "dsa": 1, "ec": 1}, "name": 1},
|
|
"label": {"form": 1, "for": 1},
|
|
"legend": {},
|
|
"li": {"value": 1},
|
|
"link": {"href": 1, "hreflang": 1, "rel": {"stylesheet": 1, "icon": 1}, "media": {"all": 1, "screen": 1, "print": 1}, "type": {"text/css": 1, "image/png": 1, "image/jpeg": 1, "image/gif": 1}, "sizes": 1},
|
|
"main": {},
|
|
"map": {"name": 1},
|
|
"mark": {},
|
|
"math": {},
|
|
"menu": {"type": 1, "label": 1},
|
|
"meta": {"http-equiv": {"content-type": 1}, "name": {"description": 1, "keywords": 1}, "content": {"text/html; charset=UTF-8": 1}, "charset": 1},
|
|
"meter": {"value": 1, "min": 1, "max": 1, "low": 1, "high": 1, "optimum": 1},
|
|
"nav": {},
|
|
"noscript": {"href": 1},
|
|
"object": {"param": 1, "data": 1, "type": 1, "height" : 1, "width": 1, "usemap": 1, "name": 1, "form": 1, "classid": 1},
|
|
"ol": {"start": 1, "reversed": 1},
|
|
"optgroup": {"disabled": 1, "label": 1},
|
|
"option": {"disabled": 1, "selected": 1, "label": 1, "value": 1},
|
|
"output": {"for": 1, "form": 1, "name": 1},
|
|
"p": {},
|
|
"param": {"name": 1, "value": 1},
|
|
"pre": {},
|
|
"progress": {"value": 1, "max": 1},
|
|
"q": {"cite": 1},
|
|
"rp": {},
|
|
"rt": {},
|
|
"ruby": {},
|
|
"s": {},
|
|
"samp": {},
|
|
"script": {"charset": 1, "type": {"text/javascript": 1}, "src": 1, "defer": 1, "async": 1},
|
|
"select": {"autofocus": 1, "disabled": 1, "form": 1, "multiple": {"multiple": 1}, "name": 1, "size": 1, "readonly":{"readonly": 1}},
|
|
"small": {},
|
|
"source": {"src": 1, "type": 1, "media": 1},
|
|
"span": {},
|
|
"strong": {},
|
|
"style": {"type": 1, "media": {"all": 1, "screen": 1, "print": 1}, "scoped": 1},
|
|
"sub": {},
|
|
"sup": {},
|
|
"svg": {},
|
|
"table": {"summary": 1},
|
|
"tbody": {},
|
|
"td": {"headers": 1, "rowspan": 1, "colspan": 1},
|
|
"textarea": {"autofocus": {"autofocus": 1}, "disabled": {"disabled": 1}, "form": 1, "maxlength": 1, "name": 1, "placeholder": 1, "readonly": {"readonly": 1}, "required": {"required": 1}, "rows": 1, "cols": 1, "wrap": {"on": 1, "off": 1, "hard": 1, "soft": 1}},
|
|
"tfoot": {},
|
|
"th": {"headers": 1, "rowspan": 1, "colspan": 1, "scope": 1},
|
|
"thead": {},
|
|
"time": {"datetime": 1},
|
|
"title": {},
|
|
"tr": {},
|
|
"track": {"kind": 1, "src": 1, "srclang": 1, "label": 1, "default": 1},
|
|
"section": {},
|
|
"summary": {},
|
|
"u": {},
|
|
"ul": {},
|
|
"var": {},
|
|
"video": {"src": 1, "autobuffer": 1, "autoplay": {"autoplay": 1}, "loop": {"loop": 1}, "controls": {"controls": 1}, "width": 1, "height": 1, "poster": 1, "muted": {"muted": 1}, "preload": {"auto": 1, "metadata": 1, "none": 1}},
|
|
"wbr": {}
|
|
};
|
|
|
|
var elements = Object.keys(attributeMap);
|
|
|
|
function is(token, type) {
|
|
return token.type.lastIndexOf(type + ".xml") > -1;
|
|
}
|
|
|
|
function findTagName(session, pos) {
|
|
var iterator = new TokenIterator(session, pos.row, pos.column);
|
|
var token = iterator.getCurrentToken();
|
|
while (token && !is(token, "tag-name")){
|
|
token = iterator.stepBackward();
|
|
}
|
|
if (token)
|
|
return token.value;
|
|
}
|
|
|
|
function findAttributeName(session, pos) {
|
|
var iterator = new TokenIterator(session, pos.row, pos.column);
|
|
var token = iterator.getCurrentToken();
|
|
while (token && !is(token, "attribute-name")){
|
|
token = iterator.stepBackward();
|
|
}
|
|
if (token)
|
|
return token.value;
|
|
}
|
|
|
|
var HtmlCompletions = function() {
|
|
|
|
};
|
|
|
|
(function() {
|
|
|
|
this.getCompletions = function(state, session, pos, prefix) {
|
|
var token = session.getTokenAt(pos.row, pos.column);
|
|
|
|
if (!token)
|
|
return [];
|
|
|
|
// tag name
|
|
if (is(token, "tag-name") || is(token, "tag-open") || is(token, "end-tag-open"))
|
|
return this.getTagCompletions(state, session, pos, prefix);
|
|
|
|
// tag attribute
|
|
if (is(token, "tag-whitespace") || is(token, "attribute-name"))
|
|
return this.getAttributeCompletions(state, session, pos, prefix);
|
|
|
|
// tag attribute values
|
|
if (is(token, "attribute-value"))
|
|
return this.getAttributeValueCompletions(state, session, pos, prefix);
|
|
|
|
// HTML entities
|
|
var line = session.getLine(pos.row).substr(0, pos.column);
|
|
if (/&[a-z]*$/i.test(line))
|
|
return this.getHTMLEntityCompletions(state, session, pos, prefix);
|
|
|
|
return [];
|
|
};
|
|
|
|
this.getTagCompletions = function(state, session, pos, prefix) {
|
|
return elements.map(function(element){
|
|
return {
|
|
value: element,
|
|
meta: "tag",
|
|
score: 1000000
|
|
};
|
|
});
|
|
};
|
|
|
|
this.getAttributeCompletions = function(state, session, pos, prefix) {
|
|
var tagName = findTagName(session, pos);
|
|
if (!tagName)
|
|
return [];
|
|
var attributes = globalAttributes;
|
|
if (tagName in attributeMap) {
|
|
attributes = attributes.concat(Object.keys(attributeMap[tagName]));
|
|
}
|
|
return attributes.map(function(attribute){
|
|
return {
|
|
caption: attribute,
|
|
snippet: attribute + '="$0"',
|
|
meta: "attribute",
|
|
score: 1000000
|
|
};
|
|
});
|
|
};
|
|
|
|
this.getAttributeValueCompletions = function(state, session, pos, prefix) {
|
|
var tagName = findTagName(session, pos);
|
|
var attributeName = findAttributeName(session, pos);
|
|
|
|
if (!tagName)
|
|
return [];
|
|
var values = [];
|
|
if (tagName in attributeMap && attributeName in attributeMap[tagName] && typeof attributeMap[tagName][attributeName] === "object") {
|
|
values = Object.keys(attributeMap[tagName][attributeName]);
|
|
}
|
|
return values.map(function(value){
|
|
return {
|
|
caption: value,
|
|
snippet: value,
|
|
meta: "attribute value",
|
|
score: 1000000
|
|
};
|
|
});
|
|
};
|
|
|
|
this.getHTMLEntityCompletions = function(state, session, pos, prefix) {
|
|
var values = ['Aacute;', 'aacute;', 'Acirc;', 'acirc;', 'acute;', 'AElig;', 'aelig;', 'Agrave;', 'agrave;', 'alefsym;', 'Alpha;', 'alpha;', 'amp;', 'and;', 'ang;', 'Aring;', 'aring;', 'asymp;', 'Atilde;', 'atilde;', 'Auml;', 'auml;', 'bdquo;', 'Beta;', 'beta;', 'brvbar;', 'bull;', 'cap;', 'Ccedil;', 'ccedil;', 'cedil;', 'cent;', 'Chi;', 'chi;', 'circ;', 'clubs;', 'cong;', 'copy;', 'crarr;', 'cup;', 'curren;', 'Dagger;', 'dagger;', 'dArr;', 'darr;', 'deg;', 'Delta;', 'delta;', 'diams;', 'divide;', 'Eacute;', 'eacute;', 'Ecirc;', 'ecirc;', 'Egrave;', 'egrave;', 'empty;', 'emsp;', 'ensp;', 'Epsilon;', 'epsilon;', 'equiv;', 'Eta;', 'eta;', 'ETH;', 'eth;', 'Euml;', 'euml;', 'euro;', 'exist;', 'fnof;', 'forall;', 'frac12;', 'frac14;', 'frac34;', 'frasl;', 'Gamma;', 'gamma;', 'ge;', 'gt;', 'hArr;', 'harr;', 'hearts;', 'hellip;', 'Iacute;', 'iacute;', 'Icirc;', 'icirc;', 'iexcl;', 'Igrave;', 'igrave;', 'image;', 'infin;', 'int;', 'Iota;', 'iota;', 'iquest;', 'isin;', 'Iuml;', 'iuml;', 'Kappa;', 'kappa;', 'Lambda;', 'lambda;', 'lang;', 'laquo;', 'lArr;', 'larr;', 'lceil;', 'ldquo;', 'le;', 'lfloor;', 'lowast;', 'loz;', 'lrm;', 'lsaquo;', 'lsquo;', 'lt;', 'macr;', 'mdash;', 'micro;', 'middot;', 'minus;', 'Mu;', 'mu;', 'nabla;', 'nbsp;', 'ndash;', 'ne;', 'ni;', 'not;', 'notin;', 'nsub;', 'Ntilde;', 'ntilde;', 'Nu;', 'nu;', 'Oacute;', 'oacute;', 'Ocirc;', 'ocirc;', 'OElig;', 'oelig;', 'Ograve;', 'ograve;', 'oline;', 'Omega;', 'omega;', 'Omicron;', 'omicron;', 'oplus;', 'or;', 'ordf;', 'ordm;', 'Oslash;', 'oslash;', 'Otilde;', 'otilde;', 'otimes;', 'Ouml;', 'ouml;', 'para;', 'part;', 'permil;', 'perp;', 'Phi;', 'phi;', 'Pi;', 'pi;', 'piv;', 'plusmn;', 'pound;', 'Prime;', 'prime;', 'prod;', 'prop;', 'Psi;', 'psi;', 'quot;', 'radic;', 'rang;', 'raquo;', 'rArr;', 'rarr;', 'rceil;', 'rdquo;', 'real;', 'reg;', 'rfloor;', 'Rho;', 'rho;', 'rlm;', 'rsaquo;', 'rsquo;', 'sbquo;', 'Scaron;', 'scaron;', 'sdot;', 'sect;', 'shy;', 'Sigma;', 'sigma;', 'sigmaf;', 'sim;', 'spades;', 'sub;', 'sube;', 'sum;', 'sup;', 'sup1;', 'sup2;', 'sup3;', 'supe;', 'szlig;', 'Tau;', 'tau;', 'there4;', 'Theta;', 'theta;', 'thetasym;', 'thinsp;', 'THORN;', 'thorn;', 'tilde;', 'times;', 'trade;', 'Uacute;', 'uacute;', 'uArr;', 'uarr;', 'Ucirc;', 'ucirc;', 'Ugrave;', 'ugrave;', 'uml;', 'upsih;', 'Upsilon;', 'upsilon;', 'Uuml;', 'uuml;', 'weierp;', 'Xi;', 'xi;', 'Yacute;', 'yacute;', 'yen;', 'Yuml;', 'yuml;', 'Zeta;', 'zeta;', 'zwj;', 'zwnj;'];
|
|
|
|
return values.map(function(value){
|
|
return {
|
|
caption: value,
|
|
snippet: value,
|
|
meta: "html entity",
|
|
score: 1000000
|
|
};
|
|
});
|
|
};
|
|
|
|
}).call(HtmlCompletions.prototype);
|
|
|
|
exports.HtmlCompletions = HtmlCompletions;
|
|
});
|