Merge remote-tracking branch 'remotes/dp/htmlcompleter'
Conflicts: lib/ace/ext/language_tools.js
This commit is contained in:
commit
71d382d43b
4 changed files with 339 additions and 14 deletions
|
|
@ -38,18 +38,9 @@ var config = require("../config");
|
|||
var textCompleter = require("../autocomplete/text_completer");
|
||||
var keyWordCompleter = {
|
||||
getCompletions: function(editor, session, pos, prefix, callback) {
|
||||
var keywords = session.$mode.$keywordList || [];
|
||||
keywords = keywords.filter(function(w) {
|
||||
return w.lastIndexOf(prefix, 0) == 0;
|
||||
});
|
||||
callback(null, keywords.map(function(word) {
|
||||
return {
|
||||
name: word,
|
||||
value: word,
|
||||
score: 0,
|
||||
meta: "keyword"
|
||||
};
|
||||
}));
|
||||
var state = editor.session.getState(pos.row);
|
||||
var completions = session.$mode.getCompletions(state, session, pos, prefix);
|
||||
callback(null, completions);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,11 +39,13 @@ var Tokenizer = require("../tokenizer").Tokenizer;
|
|||
var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules;
|
||||
var HtmlBehaviour = require("./behaviour/html").HtmlBehaviour;
|
||||
var HtmlFoldMode = require("./folding/html").FoldMode;
|
||||
var HtmlCompletions = require("./html_completions").HtmlCompletions;
|
||||
|
||||
var Mode = function() {
|
||||
var highlighter = new HtmlHighlightRules();
|
||||
this.$tokenizer = new Tokenizer(highlighter.getRules());
|
||||
this.$behaviour = new HtmlBehaviour();
|
||||
this.$completer = new HtmlCompletions();
|
||||
|
||||
this.$embeds = highlighter.getEmbeds();
|
||||
this.createModeDelegates({
|
||||
|
|
@ -67,6 +69,10 @@ oop.inherits(Mode, TextMode);
|
|||
return false;
|
||||
};
|
||||
|
||||
this.getCompletions = function(state, session, pos, prefix) {
|
||||
return this.$completer.getCompletions(state, session, pos, prefix);
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
|
|
|
|||
313
lib/ace/mode/html_completions.js
Normal file
313
lib/ace/mode/html_completions.js
Normal file
|
|
@ -0,0 +1,313 @@
|
|||
/* ***** 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",
|
||||
"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 = {
|
||||
"html": ["manifest"],
|
||||
"head": [],
|
||||
"title": [],
|
||||
"base": ["href", "target"],
|
||||
"link": ["href", "hreflang", "rel", "media", "type", "sizes"],
|
||||
"meta": ["http-equiv", "name", "content", "charset"],
|
||||
"style": ["type", "media", "scoped"],
|
||||
"script": ["charset", "type", "src", "defer", "async"],
|
||||
"noscript": ["href"],
|
||||
"body": ["onafterprint", "onbeforeprint", "onbeforeunload", "onhashchange", "onmessage", "onoffline", "onpopstate", "onredo", "onresize", "onstorage", "onundo", "onunload"],
|
||||
"section": [],
|
||||
"nav": [],
|
||||
"article": ["pubdate"],
|
||||
"aside": [],
|
||||
"h1": [],
|
||||
"h2": [],
|
||||
"h3": [],
|
||||
"h4": [],
|
||||
"h5": [],
|
||||
"h6": [],
|
||||
"header": [],
|
||||
"footer": [],
|
||||
"address": [],
|
||||
"main": [],
|
||||
"p": [],
|
||||
"hr": [],
|
||||
"pre": [],
|
||||
"blockquote": ["cite"],
|
||||
"ol": ["start", "reversed"],
|
||||
"ul": [],
|
||||
"li": ["value"],
|
||||
"dl": [],
|
||||
"dt": [],
|
||||
"dd": [],
|
||||
"figure": [],
|
||||
"figcaption": [],
|
||||
"div": [],
|
||||
"a": ["href", "target", "ping", "rel", "media", "hreflang", "type"],
|
||||
"em": [],
|
||||
"strong": [],
|
||||
"small": [],
|
||||
"s": [],
|
||||
"cite": [],
|
||||
"q": ["cite"],
|
||||
"dfn": [],
|
||||
"abbr": [],
|
||||
"data": [],
|
||||
"time": ["datetime"],
|
||||
"code": [],
|
||||
"var": [],
|
||||
"samp": [],
|
||||
"kbd": [],
|
||||
"sub": [],
|
||||
"sup": [],
|
||||
"i": [],
|
||||
"b": [],
|
||||
"u": [],
|
||||
"mark": [],
|
||||
"ruby": [],
|
||||
"rt": [],
|
||||
"rp": [],
|
||||
"bdi": [],
|
||||
"bdo": [],
|
||||
"span": [],
|
||||
"br": [],
|
||||
"wbr": [],
|
||||
"ins": ["cite", "datetime"],
|
||||
"del": ["cite", "datetime"],
|
||||
"img": ["alt", "src", "height", "width", "usemap", "ismap"],
|
||||
"iframe": ["name", "src", "height", "width", "sandbox", "seamless"],
|
||||
"embed": ["src", "height", "width", "type"],
|
||||
"object": ["param", "data", "type", "height" , "width", "usemap", "name", "form", "classid"],
|
||||
"param": ["name", "value"],
|
||||
"video": ["src", "autobuffer", "autoplay", "loop", "controls", "width", "height", "poster"],
|
||||
"audio": ["src", "autobuffer", "autoplay", "loop", "controls"],
|
||||
"source": ["src", "type", "media"],
|
||||
"track": ["kind", "src", "srclang", "label", "default"],
|
||||
"canvas": ["width", "height"],
|
||||
"map": ["name"],
|
||||
"area": ["shape", "coords", "href", "hreflang", "alt", "target", "media", "rel", "ping", "type"],
|
||||
"svg": [],
|
||||
"math": [],
|
||||
"table": ["summary"],
|
||||
"caption": [],
|
||||
"colgroup": ["span"],
|
||||
"col": ["span"],
|
||||
"tbody": [],
|
||||
"thead": [],
|
||||
"tfoot": [],
|
||||
"tr": [],
|
||||
"td": ["headers", "rowspan", "colspan"],
|
||||
"th": ["headers", "rowspan", "colspan", "scope"],
|
||||
"form": ["accept-charset", "action", "autocomplete", "enctype", "method", "name", "novalidate", "target"],
|
||||
"fieldset": ["disabled", "form", "name"],
|
||||
"legend": [],
|
||||
"label": ["form", "for"],
|
||||
"input": ["type", "accept", "alt", "autocomplete", "checked", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "height", "list", "max", "maxlength", "min", "multiple", "pattern", "placeholder", "readonly", "required", "size", "src", "step", "width", "files", "value"],
|
||||
"button": ["autofocus", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "name", "value", "type"],
|
||||
"select": ["autofocus", "disabled", "form", "multiple", "name", "size"],
|
||||
"datalist": [],
|
||||
"optgroup": ["disabled", "label"],
|
||||
"option": ["disabled", "selected", "label", "value"],
|
||||
"textarea": ["autofocus", "disabled", "form", "maxlength", "name", "placeholder", "readonly", "required", "rows", "cols", "wrap"],
|
||||
"keygen": ["autofocus", "challenge", "disabled", "form", "keytype", "name"],
|
||||
"output": ["for", "form", "name"],
|
||||
"progress": ["value", "max"],
|
||||
"meter": ["value", "min", "max", "low", "high", "optimum"],
|
||||
"details": ["open"],
|
||||
"summary": [],
|
||||
"command": ["type", "label", "icon", "disabled", "checked", "radiogroup", "command"],
|
||||
"menu": ["type", "label"],
|
||||
"dialog": ["open"]
|
||||
};
|
||||
|
||||
var allElements = Object.keys(attributeMap);
|
||||
|
||||
function hasType(token, type) {
|
||||
var tokenTypes = token.type.split('.');
|
||||
return type.split('.').every(function(type){
|
||||
return (tokenTypes.indexOf(type) !== -1);
|
||||
});
|
||||
}
|
||||
|
||||
function findTagName(session, pos) {
|
||||
var iterator = new TokenIterator(session, pos.row, pos.column);
|
||||
var token = iterator.getCurrentToken();
|
||||
if (!token || !hasType(token, 'tag') && !(hasType(token, 'text') && token.value.match('/'))){
|
||||
do {
|
||||
token = iterator.stepBackward();
|
||||
} while (token && (hasType(token, 'string') || hasType(token, 'operator') || hasType(token, 'attribute-name') || hasType(token, 'text')));
|
||||
}
|
||||
if (token && hasType(token, 'tag-name') && !iterator.stepBackward().value.match('/'))
|
||||
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 (hasType(token, "tag-name") || (token.value == '<' && hasType(token, "text")))
|
||||
return this.getTagCompletions(state, session, pos, prefix);
|
||||
|
||||
// tag attribute
|
||||
if (hasType(token, 'text') || hasType(token, 'attribute-name'))
|
||||
return this.getAttributeCompetions(state, session, pos, prefix);
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
this.getTagCompletions = function(state, session, pos, prefix) {
|
||||
var elements = allElements;
|
||||
if (prefix) {
|
||||
elements = elements.filter(function(element){
|
||||
return element.indexOf(prefix) === 0;
|
||||
});
|
||||
}
|
||||
return elements.map(function(element){
|
||||
return {
|
||||
value: element,
|
||||
meta: "tag"
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
this.getAttributeCompetions = function(state, session, pos, prefix) {
|
||||
var tagName = findTagName(session, pos);
|
||||
if (!tagName)
|
||||
return [];
|
||||
var attributes = globalAttributes;
|
||||
if (tagName in attributeMap) {
|
||||
attributes = attributes.concat(attributeMap[tagName]);
|
||||
}
|
||||
if (prefix) {
|
||||
attributes = attributes.filter(function(attribute){
|
||||
return attribute.indexOf(prefix) === 0;
|
||||
});
|
||||
}
|
||||
return attributes.map(function(attribute){
|
||||
return {
|
||||
caption: attribute,
|
||||
snippet: attribute + '="$0"',
|
||||
meta: "attribute"
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
}).call(HtmlCompletions.prototype);
|
||||
|
||||
exports.HtmlCompletions = HtmlCompletions;
|
||||
});
|
||||
|
|
@ -281,7 +281,7 @@ var Mode = function() {
|
|||
}
|
||||
}
|
||||
|
||||
var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction'];
|
||||
var delegations = ['toggleCommentLines', 'getNextLineIndent', 'checkOutdent', 'autoOutdent', 'transformAction', 'getCompletions'];
|
||||
|
||||
for (var i = 0; i < delegations.length; i++) {
|
||||
(function(scope) {
|
||||
|
|
@ -356,7 +356,22 @@ var Mode = function() {
|
|||
return this.$keywordList;
|
||||
return completionKeywords.concat(this.$keywordList || []);
|
||||
};
|
||||
|
||||
|
||||
this.getCompletions = function(state, session, pos, prefix) {
|
||||
var keywords = this.$keywordList || [];
|
||||
keywords = keywords.filter(function(w) {
|
||||
return w.lastIndexOf(prefix, 0) == 0;
|
||||
});
|
||||
return keywords.map(function(word) {
|
||||
return {
|
||||
name: word,
|
||||
value: word,
|
||||
score: 0,
|
||||
meta: "keyword"
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
}).call(Mode.prototype);
|
||||
|
||||
exports.Mode = Mode;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue