Initial commit
This commit is contained in:
277
lib/assets/javascripts/utils/carto.codemirror.js
Normal file
277
lib/assets/javascripts/utils/carto.codemirror.js
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
LESS mode - http://www.lesscss.org/
|
||||
Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>
|
||||
Report bugs/issues here: https://github.com/marijnh/CodeMirror/issues GitHub: @peterkroon
|
||||
*/
|
||||
|
||||
CodeMirror.defineMode("carto", function(config) {
|
||||
var indentUnit = config.indentUnit, type;
|
||||
function ret(style, tp) {type = tp; return style;}
|
||||
//html tags
|
||||
var tags = "a abbr acronym address applet area article aside audio b base basefont bdi bdo big blockquote body br button canvas caption cite code col colgroup command datalist dd del details dfn dir div dl dt em embed fieldset figcaption figure font footer form frame frameset h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins keygen kbd label legend li link map mark menu meta meter nav noframes noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strike strong style sub summary sup table tbody td textarea tfoot th thead time title tr track tt u ul var video wbr".split(' ');
|
||||
var colorKeywords = keySet(color_keywords);
|
||||
|
||||
function inTagsArray(val){
|
||||
for(var i=0; i<tags.length; i++)if(val === tags[i])return true;
|
||||
}
|
||||
|
||||
var selectors = /(^\:root$|^\:nth\-child$|^\:nth\-last\-child$|^\:nth\-of\-type$|^\:nth\-last\-of\-type$|^\:first\-child$|^\:last\-child$|^\:first\-of\-type$|^\:last\-of\-type$|^\:only\-child$|^\:only\-of\-type$|^\:empty$|^\:link|^\:visited$|^\:active$|^\:hover$|^\:focus$|^\:target$|^\:lang$|^\:enabled^\:disabled$|^\:checked$|^\:first\-line$|^\:first\-letter$|^\:before$|^\:after$|^\:not$|^\:required$|^\:invalid$)/;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch == "@") {stream.eatWhile(/[\w\-]/); return ret("meta", stream.current());}
|
||||
else if (ch == "/" && stream.eat("*")) {
|
||||
state.tokenize = tokenCComment;
|
||||
return tokenCComment(stream, state);
|
||||
}
|
||||
else if (ch == "<" && stream.eat("!")) {
|
||||
state.tokenize = tokenSGMLComment;
|
||||
return tokenSGMLComment(stream, state);
|
||||
}
|
||||
else if (ch == "=") ret(null, "compare");
|
||||
else if (ch == "|" && stream.eat("=")) return ret(null, "compare");
|
||||
else if (ch == "\"" || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
else if (ch == "/") { // e.g.: .png will not be parsed as a class
|
||||
if(stream.eat("/")){
|
||||
state.tokenize = tokenSComment;
|
||||
return tokenSComment(stream, state);
|
||||
}else{
|
||||
if(type == "string" || type == "(")return ret("string", "string");
|
||||
if(state.stack[state.stack.length-1] != undefined)return ret(null, ch);
|
||||
stream.eatWhile(/[\a-zA-Z0-9\-_.\s]/);
|
||||
if( /\/|\)|#/.test(stream.peek() || (stream.eatSpace() && stream.peek() == ")")) || stream.eol() )return ret("string", "string"); // let url(/images/logo.png) without quotes return as string
|
||||
}
|
||||
}
|
||||
else if (ch == "!") {
|
||||
stream.match(/^\s*\w*/);
|
||||
return ret("keyword", "important");
|
||||
}
|
||||
else if (/\d/.test(ch)) {
|
||||
stream.eatWhile(/[\w.%]/);
|
||||
return ret("number", "unit");
|
||||
}
|
||||
else if (/[,+<>*\/]/.test(ch)) {
|
||||
if(stream.peek() == "=" || type == "a")return ret("string", "string");
|
||||
return ret(null, "select-op");
|
||||
}
|
||||
else if (/[;{}:\[\]()~\|]/.test(ch)) {
|
||||
if(ch == ":"){
|
||||
stream.eatWhile(/[a-z\\\-]/);
|
||||
if( selectors.test(stream.current()) ){
|
||||
return ret("tag", "tag");
|
||||
}else if(stream.peek() == ":"){//::-webkit-search-decoration
|
||||
stream.next();
|
||||
stream.eatWhile(/[a-z\\\-]/);
|
||||
if(stream.current().match(/\:\:\-(o|ms|moz|webkit)\-/))return ret("string", "string");
|
||||
if( selectors.test(stream.current().substring(1)) )return ret("tag", "tag");
|
||||
return ret(null, ch);
|
||||
}else{
|
||||
return ret(null, ch);
|
||||
}
|
||||
}else if(ch == "~"){
|
||||
if(type == "r")return ret("string", "string");
|
||||
}else{
|
||||
return ret(null, ch);
|
||||
}
|
||||
}
|
||||
else if (ch == ".") {
|
||||
if(type == "(" || type == "string")return ret("string", "string"); // allow url(../image.png)
|
||||
stream.eatWhile(/[\a-zA-Z0-9\-_]/);
|
||||
if(stream.peek() == " ")stream.eatSpace();
|
||||
if(stream.peek() == ")")return ret("number", "unit");//rgba(0,0,0,.25);
|
||||
return ret("tag", "tag");
|
||||
}
|
||||
else if (ch == "#") {
|
||||
//we don't eat white-space, we want the hex color and or id only
|
||||
stream.eatWhile(/[A-Za-z0-9]/);
|
||||
//check if there is a proper hex color length e.g. #eee || #eeeEEE
|
||||
if(stream.current().length == 4 || stream.current().length == 7){
|
||||
if(stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false) != null){//is there a valid hex color value present in the current stream
|
||||
//when not a valid hex value, parse as id
|
||||
if(stream.current().substring(1) != stream.current().match(/[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/,false))return ret("atom", "tag");
|
||||
//eat white-space
|
||||
stream.eatSpace();
|
||||
//when hex value declaration doesn't end with [;,] but is does with a slash/cc comment treat it as an id, just like the other hex values that don't end with[;,]
|
||||
if( /[\/<>.(){!$%^&*_\-\\?=+\|#'~`]/.test(stream.peek()) )return ret("atom", "tag");
|
||||
//#time { color: #aaa }
|
||||
else if(stream.peek() == "}" )return ret("color", "unit");
|
||||
//we have a valid hex color value, parse as id whenever an element/class is defined after the hex(id) value e.g. #eee aaa || #eee .aaa
|
||||
else if( /[a-zA-Z\\]/.test(stream.peek()) )return ret("color", "unit");
|
||||
//when a hex value is on the end of a line, parse as id
|
||||
else if(stream.eol())return ret("color", "unit");
|
||||
//default
|
||||
else return ret("color", "unit");
|
||||
}else{//when not a valid hexvalue in the current stream e.g. #footer
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
return ret("atom", "tag");
|
||||
}
|
||||
}else{//when not a valid hexvalue length
|
||||
stream.eatWhile(/[\w\\\-]/);
|
||||
return ret("atom", "tag");
|
||||
}
|
||||
}
|
||||
else if (ch == "&") {
|
||||
stream.eatWhile(/[\w\-]/);
|
||||
return ret(null, ch);
|
||||
}
|
||||
else {
|
||||
stream.eatWhile(/[\w\\\-_%.{]/);
|
||||
if(type == "string"){
|
||||
return ret("string", "string");
|
||||
}else if(stream.current().match(/(^http$|^https$)/) != null){
|
||||
stream.eatWhile(/[\w\\\-_%.{:\/]/);
|
||||
return ret("string", "string");
|
||||
}else if(stream.peek() == "<" || stream.peek() == ">"){
|
||||
return ret("tag", "tag");
|
||||
}else if( /\(/.test(stream.peek()) ){
|
||||
return ret(null, ch);
|
||||
}else if (stream.peek() == "/" && state.stack[state.stack.length-1] != undefined){ // url(dir/center/image.png)
|
||||
return ret("string", "string");
|
||||
}else if( stream.current().match(/\-\d|\-.\d/) ){ // match e.g.: -5px -0.4 etc... only colorize the minus sign
|
||||
//commment out these 2 comment if you want the minus sign to be parsed as null -500px
|
||||
//stream.backUp(stream.current().length-1);
|
||||
//return ret(null, ch); //console.log( stream.current() );
|
||||
return ret("number", "unit");
|
||||
}else if( inTagsArray(stream.current().toLowerCase()) ){ // match html tags
|
||||
return ret("tag", "tag");
|
||||
}else if( /\/|[\s\)]/.test(stream.peek() || stream.eol() || (stream.eatSpace() && stream.peek() == "/")) && stream.current().indexOf(".") !== -1){
|
||||
if(stream.current().substring(stream.current().length-1,stream.current().length) == "{"){
|
||||
stream.backUp(1);
|
||||
return ret("tag", "tag");
|
||||
}//end if
|
||||
stream.eatSpace();
|
||||
if( /[{<>.a-zA-Z\/]/.test(stream.peek()) || stream.eol() )return ret("tag", "tag"); // e.g. button.icon-plus
|
||||
return ret("string", "string"); // let url(/images/logo.png) without quotes return as string
|
||||
}else if( stream.eol() || stream.peek() == "[" || stream.peek() == "#" || type == "tag" ){
|
||||
if(stream.current().substring(stream.current().length-1,stream.current().length) == "{")stream.backUp(1);
|
||||
return ret("tag", "tag");
|
||||
}else if(type == "compare" || type == "a" || type == "("){
|
||||
return ret("string", "string");
|
||||
}else if(type == "|" || stream.current() == "-" || type == "["){
|
||||
return ret(null, ch);
|
||||
}else if(stream.peek() == ":") {
|
||||
stream.next();
|
||||
var t_v = stream.peek() == ":" ? true : false;
|
||||
if(!t_v){
|
||||
var old_pos = stream.pos;
|
||||
var sc = stream.current().length;
|
||||
stream.eatWhile(/[a-z\\\-]/);
|
||||
var new_pos = stream.pos;
|
||||
if(stream.current().substring(sc-1).match(selectors) != null){
|
||||
stream.backUp(new_pos-(old_pos-1));
|
||||
return ret("tag", "tag");
|
||||
} else stream.backUp(new_pos-(old_pos-1));
|
||||
}else{
|
||||
stream.backUp(1);
|
||||
}
|
||||
if(t_v)return ret("tag", "tag"); else return ret("variable", "variable");
|
||||
|
||||
// It is a color variable?
|
||||
} else if (colorKeywords.hasOwnProperty(stream.current())) {
|
||||
return ret('color', 'unit');
|
||||
}else{
|
||||
return ret("variable", "variable");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function keySet(array) {
|
||||
var keys = {};
|
||||
for (var i = 0; i < array.length; ++i) {
|
||||
keys[array[i]] = true;
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
function tokenSComment(stream, state) { // SComment = Slash comment
|
||||
stream.skipToEnd();
|
||||
state.tokenize = tokenBase;
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
|
||||
function tokenCComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (maybeEnd && ch == "/") {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
|
||||
function tokenSGMLComment(stream, state) {
|
||||
var dashes = 0, ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (dashes >= 2 && ch == ">") {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
dashes = (ch == "-") ? dashes + 1 : 0;
|
||||
}
|
||||
return ret("comment", "comment");
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (ch == quote && !escaped)
|
||||
break;
|
||||
escaped = !escaped && ch == "\\";
|
||||
}
|
||||
if (!escaped) state.tokenize = tokenBase;
|
||||
return ret("string", "string");
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function(base) {
|
||||
return {tokenize: tokenBase,
|
||||
baseIndent: base || 0,
|
||||
stack: []};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream.eatSpace()) return null;
|
||||
var style = state.tokenize(stream, state);
|
||||
|
||||
var context = state.stack[state.stack.length-1];
|
||||
if (type == "hash" && context == "rule") style = "atom";
|
||||
else if (style == "variable") {
|
||||
if (context == "rule") style = null; //"tag"
|
||||
else if (!context || context == "@media{") {
|
||||
style = stream.current() == "when" ? "variable" :
|
||||
/[\s,|\s\)|\s]/.test(stream.peek()) ? "tag" : type;
|
||||
}
|
||||
}
|
||||
|
||||
if (context == "rule" && /^[\{\};]$/.test(type))
|
||||
state.stack.pop();
|
||||
if (type == "{") {
|
||||
if (context == "@media") state.stack[state.stack.length-1] = "@media{";
|
||||
else state.stack.push("{");
|
||||
}
|
||||
else if (type == "}") state.stack.pop();
|
||||
else if (type == "@media") state.stack.push("@media");
|
||||
else if (context == "{" && type != "comment") state.stack.push("rule");
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
var n = state.stack.length;
|
||||
if (/^\}/.test(textAfter))
|
||||
n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
|
||||
return state.baseIndent + n * indentUnit;
|
||||
},
|
||||
|
||||
electricChars: "}"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-carto", "carto");
|
||||
28
lib/assets/javascripts/utils/color.keywords.js
Normal file
28
lib/assets/javascripts/utils/color.keywords.js
Normal file
@@ -0,0 +1,28 @@
|
||||
var color_keywords = [
|
||||
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
|
||||
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
|
||||
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
|
||||
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
|
||||
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
|
||||
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
|
||||
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
|
||||
"deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
|
||||
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
|
||||
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
|
||||
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
|
||||
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
|
||||
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
|
||||
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
|
||||
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
|
||||
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
|
||||
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
|
||||
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
|
||||
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
|
||||
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
|
||||
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
|
||||
"purple", "red", "rosybrown", "royalblue", "saddlebrown", "salmon",
|
||||
"sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
|
||||
"slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
|
||||
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
|
||||
"whitesmoke", "yellow", "yellowgreen"
|
||||
];
|
||||
204
lib/assets/javascripts/utils/draggable.js
Normal file
204
lib/assets/javascripts/utils/draggable.js
Normal file
@@ -0,0 +1,204 @@
|
||||
$.fn.draggableOverlay = function(opt) {
|
||||
|
||||
var self = this;
|
||||
var $rule = null;
|
||||
var $ruleH = null;
|
||||
var $elements = this;
|
||||
|
||||
if (opt === "disable" || opt.container == undefined) {
|
||||
|
||||
this.addClass("disabled");
|
||||
this.css('cursor', '')
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
opt = $.extend({ horizontal_guides: [], vertical_guides: [], padding: 0, stickiness: 7, cursor: "move" }, opt);
|
||||
|
||||
var $container = opt.container;
|
||||
|
||||
// Guide offsets
|
||||
var horizontal_guides = opt.horizontal_guides;
|
||||
var vertical_guides = opt.vertical_guides;
|
||||
|
||||
var vertical_limits, horizontal_limits, verticals, horizontals = [];
|
||||
|
||||
$(".rule").remove();
|
||||
|
||||
$rule = $("<div class='rule' />");
|
||||
$container.append($rule)
|
||||
$rule.offset({ top: 0 }).css( { left: 0 });
|
||||
|
||||
$ruleH = $("<div class='rule horizontal' />");
|
||||
$container.append($ruleH);
|
||||
$ruleH.offset({ top: 0 }).css( { left: 0 });
|
||||
|
||||
for (var i = 0; i < horizontal_guides.length; i++) {
|
||||
|
||||
var position = horizontal_guides[i];
|
||||
|
||||
var $el = $("<div class='guide horizontal' />");
|
||||
|
||||
$container.append($el)
|
||||
|
||||
$el.offset( { top: position }).css( { left: 0 });
|
||||
|
||||
}
|
||||
|
||||
for (var i = 0; i < vertical_guides.length; i++) {
|
||||
|
||||
var position = vertical_guides[i];
|
||||
|
||||
var $el = $("<div class='guide vertical' />");
|
||||
$container.append($el)
|
||||
$el.offset( { left: position }).css( { top: 0 });
|
||||
}
|
||||
|
||||
var onMouseDown = function(e) {
|
||||
|
||||
if (self.hasClass("disabled")) {
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
||||
var $drag = $(this).addClass('draggable');
|
||||
|
||||
$(this).css({ bottom: "auto", right: "auto", left: $(this).position().left, top: $(this).position().top })
|
||||
|
||||
var
|
||||
//z_idx = $drag.css('z-index'),
|
||||
drg_h = $drag.outerHeight(),
|
||||
drg_w = $drag.outerWidth(),
|
||||
pos_y = $drag.offset().top + drg_h - e.pageY,
|
||||
pos_x = $drag.offset().left + drg_w - e.pageX,
|
||||
container_x = $container.offset().left,
|
||||
container_y = $container.offset().top,
|
||||
container_w = $container.width(),
|
||||
container_h = $container.height();
|
||||
|
||||
verticals = [];
|
||||
horizontals = [];
|
||||
vertical_limits = [];
|
||||
horizontal_limits = [];
|
||||
|
||||
var device = $(this).hasClass("desktop") ? "desktop" : "mobile";
|
||||
|
||||
if ($(this).hasClass("snap")) {
|
||||
$elements.each(function(i, e) {
|
||||
if (!$(e).hasClass("draggable") && $(e).hasClass(device) && !$(e).hasClass("disabled") && $(e).hasClass("snap")) {
|
||||
|
||||
var t = $(e).offset().top;
|
||||
horizontal_limits.push(t);
|
||||
horizontal_limits.push(t + $(e).height());
|
||||
|
||||
var l = $(e).offset().left;
|
||||
vertical_limits.push(l);
|
||||
vertical_limits.push(l + $(e).width());
|
||||
}
|
||||
});
|
||||
|
||||
verticals = verticals.concat(vertical_limits, vertical_guides);
|
||||
horizontals = horizontals.concat(horizontal_limits, horizontal_guides);
|
||||
}
|
||||
|
||||
var onMouseMove = function(e) {
|
||||
|
||||
var top = e.pageY + pos_y - drg_h;
|
||||
var left = e.pageX + pos_x - drg_w;
|
||||
|
||||
var otop = top;
|
||||
var oleft = left;
|
||||
|
||||
var container_right = container_x + container_w;
|
||||
var container_bottom = container_y + container_h;
|
||||
|
||||
// CHECK GUIDES
|
||||
for (var i = 0; i < horizontals.length; i++) {
|
||||
|
||||
var target_l = horizontals[i];
|
||||
|
||||
if ( ( top >= target_l - opt.stickiness - opt.padding ) && ( top <= target_l + opt.stickiness + opt.padding) ) {
|
||||
top = target_l;
|
||||
$ruleH.offset( { top: top }).css({ left: 0, opacity: 1 })
|
||||
break;
|
||||
} else if ( ( top + drg_h <= target_l + opt.stickiness + opt.padding ) && ( top + drg_h >= target_l - opt.stickiness - opt.padding ) ) {
|
||||
top = target_l - drg_h ;
|
||||
$ruleH.offset( { top: top + drg_h }).css({ left: 0, opacity: 1 })
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (var i = 0; i < verticals.length; i++) {
|
||||
|
||||
var target_l = verticals[i];
|
||||
|
||||
if ( ( left >= target_l - opt.stickiness - opt.padding) && ( left <= target_l + opt.stickiness + opt.padding ) ) {
|
||||
left = target_l;
|
||||
$rule.offset( { left: left }).css({ top: 0, opacity: 1 })
|
||||
break;
|
||||
} else if ( ( left + drg_w <= target_l + opt.stickiness + opt.padding ) && ( left + drg_w >= target_l - opt.stickiness - opt.padding) ) {
|
||||
left = target_l - drg_w ;
|
||||
$rule.offset( { left: left + drg_w }).css({ top: 0, opacity: 1 })
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// LEFT
|
||||
if (left - opt.stickiness < container_x) {
|
||||
left = container_x;
|
||||
} else if (left + drg_w + opt.stickiness > container_right ) {
|
||||
left = container_right - drg_w;
|
||||
}
|
||||
|
||||
// TOP
|
||||
if (top - opt.stickiness < container_y) {
|
||||
top = container_y;
|
||||
} else if (top + drg_h + opt.stickiness > container_bottom ) {
|
||||
top = container_bottom - drg_h;
|
||||
}
|
||||
|
||||
|
||||
if (top == otop && left == oleft) {
|
||||
$(this).find(".draggable").removeClass("sticky");
|
||||
$(".rule").css({ opacity: 0 });
|
||||
} else {
|
||||
$(this).find(".draggable").addClass("sticky");
|
||||
}
|
||||
|
||||
var offset = { top: top, left: left };
|
||||
|
||||
$('.draggable').offset(offset);
|
||||
|
||||
var updateLayout = _.throttle(function(e) {
|
||||
opt.drag && opt.drag();
|
||||
}, 100);
|
||||
updateLayout();
|
||||
|
||||
}
|
||||
|
||||
$drag.parents().on("mousemove", onMouseMove);
|
||||
|
||||
};
|
||||
|
||||
var onExit = function() {
|
||||
|
||||
$(".draggable").parents().off("mousemove");
|
||||
$(".rule").css({ opacity: 0 });
|
||||
|
||||
$(".draggable").removeClass('sticky');
|
||||
$(".draggable").removeClass('draggable');
|
||||
|
||||
};
|
||||
|
||||
$("body").on("mouseup", onExit);
|
||||
|
||||
return this.on("mousedown", onMouseDown).on("mouseup", onExit);
|
||||
|
||||
}
|
||||
191
lib/assets/javascripts/utils/postgres.codemirror.js
Normal file
191
lib/assets/javascripts/utils/postgres.codemirror.js
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Postgres Model for codemirror based on:
|
||||
* MySQL Mode for CodeMirror 2 by MySQL-Tools
|
||||
* @author James Thorne (partydroid)
|
||||
* @link http://github.com/partydroid/MySQL-Tools
|
||||
* @link http://mysqltools.org
|
||||
* @version 02/Jan/2012
|
||||
*/
|
||||
CodeMirror.defineMode("postgres", function(config) {
|
||||
var indentUnit = config.indentUnit;
|
||||
var curPunc;
|
||||
|
||||
function wordRegexp(words) {
|
||||
return new RegExp("^(?:" + words.join("|") + ")$", "i");
|
||||
}
|
||||
var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
|
||||
"isblank", "isliteral", "union", "a"]);
|
||||
var keywords = wordRegexp([
|
||||
('ABS'),('ACCESSIBLE'),('ADD'),('ALL'),('ALTER'),('ANALYZE'),('AND'),('ANY'),('ARRAY'),('ARRAY_AGG'),('ARRAY_MAX_CARDINALITY'),('AS'),('ASC'),('ASENSITIVE'),('AT'),('AVG'),('BEFORE'),('BEGIN'),
|
||||
('BETWEEN'),('BIGINT'),('BINARY'),('BLOB'),('BOOLEAN'),('BOTH'),('BY'),('CALL'),('CASCADE'),('CASE'),('CAST'),('CEIL'),('CEILING'),('CHANGE'),('CHAR'),('CHARACTER'),('CHARACTER_LENGTH'),
|
||||
('CHAR_LENGTH'),('CHECK'),('CLOB'),('CLOSE'),('COLLATE'),('COLLECT'),('COLUMN'),('COLUMNS'),('CONDITION'),('CONSTRAINT'),('CONTAINS'),('CONTINUE'),('CONVERT'),('CORR'),('COUNT'),('CREATE'),
|
||||
('CROSS'),('CUBE'),('CURRENT_DATE'),('CURRENT_TIME'),('CURRENT_TIMESTAMP'),('CURRENT_USER'),('CURSOR'),('CYCLE'),('DATABASE'),('DATABASES'),('DATE'),('DAY'),('DAY_HOUR'),('DAY_MICROSECOND'),
|
||||
('DAY_MINUTE'),('DAY_SECOND'),('DEC'),('DECIMAL'),('DECLARE'),('DEFAULT'),('DELAYED'),('DELETE'),('DESC'),('DESCRIBE'),('DETERMINISTIC'),('DISTINCT'),('DISTINCTROW'),('DIV'),('DOUBLE'),('DROP'),
|
||||
('DUAL'),('EACH'),('ELEMENT'),('ELSE'),('ELSEIF'),('ENCLOSED'),('END'),('EQUALS'),('ESCAPE'),('ESCAPED'),('EVERY'),('EXCEPT'),('EXEC'),('EXISTS'),('EXIT'),('EXP'),('EXPLAIN'),('EXTRACT'),
|
||||
('FALSE'),('FETCH'),('FILTER'),('FLOAT'),('FLOAT4'),('FLOAT8'),('FLOOR'),('FOR'),('FORCE'),('FOREIGN'),('FROM'),('FULL'),('FULLTEXT'),('GRANT'),('GROUP'),('GROUPS'),('HAVING'),('HIGH_PRIORITY'),
|
||||
('HOLD'),('HOUR'),('HOUR_MICROSECOND'),('HOUR_MINUTE'),('HOUR_SECOND'),('IDENTITY'),('IF'),('IGNORE'),('ILIKE'),('IN'),('INDEX'),('INFILE'),('INNER'),('INOUT'),('INSENSITIVE'),('INSERT'),('INT'),
|
||||
('INT1'),('INT2'),('INT3'),('INT4'),('INT8'),('INTEGER'),('INTERSECT'),('INTERSECTION'),('INTERVAL'),('INTO'),('IS'),('ITERATE'),('JOIN'),('KEY'),('KEYS'),('KILL'),('LAG'),('LARGE'),('LEADING'),
|
||||
('LEAVE'),('LEFT'),('LIKE'),('LIKE_REGEX'),('LIMIT'),('LINEAR'),('LINES'),('LN'),('LOAD'),('LOCALTIME'),('LOCALTIMESTAMP'),('LOCK'),('LONG'),('LONGBLOB'),('LONGTEXT'),('LOOP'),('LOWER'),
|
||||
('LOW_PRIORITY'),('MASTER_SSL_VERIFY_SERVER_CERT'),('MATCH'),('MAX'),('MEDIUMBLOB'),('MEDIUMINT'),('MEDIUMTEXT'),('MIDDLEINT'),('MIN'),('MINUTE'),('MINUTE_MICROSECOND'),('MINUTE_SECOND'),('MOD'),
|
||||
('MODIFIES'),('MODULE'),('MONTH'),('MULTISET'),('NATURAL'),('NO'),('NONE'),('NORMALIZE'),('NOT'),('NO_WRITE_TO_BINLOG'),('NULL'),('NULLIF'),('NUMERIC'),('OF'),('OFFSET'),('OLD'),('ON'),('ONLY'),
|
||||
('OPEN'),('OPTIMIZE'),('OPTION'),('OPTIONALLY'),('OR'),('ORDER'),('OUT'),('OUTER'),('OUTFILE'),('OVER'),('OVERLAY'),('PARAMETER'),('PERCENT'),('PERIOD'),('POSITION'),('POWER'),('PRECISION'),
|
||||
('PRIMARY'),('PROCEDURE'),('PURGE'),('RANGE'),('READ'),('READS'),('READ_WRITE'),('REAL'),('REFERENCES'),('REGEXP'),('RELEASE'),('RENAME'),('REPEAT'),('REPLACE'),('REQUIRE'),('RESTRICT'),
|
||||
('RESULT'),('RETURN'),('REVOKE'),('RIGHT'),('RLIKE'),('ROWS'),('SCHEMA'),('SCHEMAS'),('SECOND_MICROSECOND'),('SELECT'),('SENSITIVE'),('SEPARATOR'),('SET'),('SHOW'),('SIMILAR'),('SMALLINT'),
|
||||
('SOME'),('SPATIAL'),('SPECIFIC'),('SQL'),('SQLEXCEPTION'),('SQLSTATE'),('SQLWARNING'),('SQL_BIG_RESULT'),('SQL_CALC_FOUND_ROWS'),('SQL_SMALL_RESULT'),('SQRT'),('SSL'),('STARTING'),('STDEV'),
|
||||
('STRAIGHT_JOIN'),('SUBSTRING'),('SUM'),('TABLE'),('TERMINATED'),('THEN'),('TIME'),('TIMESTAMP'),('TINYBLOB'),('TINYINT'),('TINYTEXT'),('TO'),('TRAILING'),('TRIGGER'),('TRIM'),('TRIM_ARRAY'),
|
||||
('TRUE'),('TRUNCATE'),('UNDO'),('UNION'),('UNIQUE'),('UNKNOWN'),('UNLOCK'),('UNSIGNED'),('UPDATE'),('UPPER'),('USAGE'),('USE'),('USING'),('UTC_DATE'),('UTC_TIME'),('UTC_TIMESTAMP'),('VALUE'),
|
||||
('VALUES'),('VALUE_OF'),('VARBINARY'),('VARCHAR'),('VARCHARACTER'),('VARYING'),('WHEN'),('WHENEVER'),('WHERE'),('WHILE'),('WITH'),('WITHIN'),('WITHOUT'),('WRITE'),('XOR'),('YEAR_MONTH'),('ZEROFILL')
|
||||
]);
|
||||
var operatorChars = /[*+\-<>=&|]/;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
curPunc = null;
|
||||
if (ch == "$" || ch == "?") {
|
||||
stream.match(/^[\w\d]*/);
|
||||
return "variable-2";
|
||||
}
|
||||
else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) {
|
||||
stream.match(/^[^\s\u00a0>]*>?/);
|
||||
return "atom";
|
||||
}
|
||||
else if (ch == "\"" || ch == "'") {
|
||||
state.tokenize = tokenLiteral(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
else if (ch == "`") {
|
||||
state.tokenize = tokenOpLiteral(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
else if (/[{}\(\),\.;\[\]]/.test(ch)) {
|
||||
curPunc = ch;
|
||||
return null;
|
||||
}
|
||||
else if (ch == "-") {
|
||||
var ch2 = stream.next();
|
||||
if (ch2=="-") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
else if (operatorChars.test(ch)) {
|
||||
stream.eatWhile(operatorChars);
|
||||
return null;
|
||||
}
|
||||
else if (ch == ":") {
|
||||
stream.eatWhile(/[\w\d\._\-]/);
|
||||
return "atom";
|
||||
}
|
||||
else {
|
||||
stream.eatWhile(/[_\w\d]/);
|
||||
if (stream.eat(":")) {
|
||||
stream.eatWhile(/[\w\d_\-]/);
|
||||
return "atom";
|
||||
}
|
||||
var word = stream.current(), type;
|
||||
if (ops.test(word))
|
||||
return null;
|
||||
else if (keywords.test(word))
|
||||
return "keyword";
|
||||
else
|
||||
return "variable";
|
||||
}
|
||||
}
|
||||
|
||||
function tokenLiteral(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (ch == quote && !escaped) {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && ch == "\\";
|
||||
}
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
function tokenOpLiteral(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (ch == quote && !escaped) {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && ch == "\\";
|
||||
}
|
||||
return "variable-2";
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function pushContext(state, type, col) {
|
||||
state.context = {prev: state.context, indent: state.indent, col: col, type: type};
|
||||
}
|
||||
function popContext(state) {
|
||||
state.indent = state.context.indent;
|
||||
state.context = state.context.prev;
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function(base) {
|
||||
return {tokenize: tokenBase,
|
||||
context: null,
|
||||
indent: 0,
|
||||
col: 0};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream.sol()) {
|
||||
if (state.context && state.context.align == null) state.context.align = false;
|
||||
state.indent = stream.indentation();
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
var style = state.tokenize(stream, state);
|
||||
|
||||
if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") {
|
||||
state.context.align = true;
|
||||
}
|
||||
|
||||
if (curPunc == "(") pushContext(state, ")", stream.column());
|
||||
else if (curPunc == "[") pushContext(state, "]", stream.column());
|
||||
else if (curPunc == "{") pushContext(state, "}", stream.column());
|
||||
else if (/[\]\}\)]/.test(curPunc)) {
|
||||
while (state.context && state.context.type == "pattern") popContext(state);
|
||||
if (state.context && curPunc == state.context.type) popContext(state);
|
||||
}
|
||||
else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state);
|
||||
else if (/atom|string|variable/.test(style) && state.context) {
|
||||
if (/[\}\]]/.test(state.context.type))
|
||||
pushContext(state, "pattern", stream.column());
|
||||
else if (state.context.type == "pattern" && !state.context.align) {
|
||||
state.context.align = true;
|
||||
state.context.col = stream.column();
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
var firstChar = textAfter && textAfter.charAt(0);
|
||||
var context = state.context;
|
||||
if (/[\]\}]/.test(firstChar))
|
||||
while (context && context.type == "pattern") context = context.prev;
|
||||
|
||||
var closing = context && firstChar == context.type;
|
||||
if (!context)
|
||||
return 0;
|
||||
else if (context.type == "pattern")
|
||||
return context.col;
|
||||
else if (context.align)
|
||||
return context.col + (closing ? 0 : 1);
|
||||
else
|
||||
return context.indent + (closing ? 0 : indentUnit);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-postgres", "postgres");
|
||||
76
lib/assets/javascripts/utils/simple-hint.js
Normal file
76
lib/assets/javascripts/utils/simple-hint.js
Normal file
@@ -0,0 +1,76 @@
|
||||
(function() {
|
||||
CodeMirror.simpleHint = function(editor, getHints) {
|
||||
// We want a single cursor position.
|
||||
if (editor.somethingSelected()) return;
|
||||
//don't show completion if the token is empty
|
||||
var tempToken = editor.getTokenAt(editor.getCursor());
|
||||
if(!(/[\S]/gi.test(tempToken.string))) return;
|
||||
|
||||
var result = getHints(editor);
|
||||
if (!result || !result.list.length) return;
|
||||
var completions = result.list;
|
||||
function insert(str) {
|
||||
editor.replaceRange(str, result.from, result.to);
|
||||
}
|
||||
// When there is only one completion, use it directly.
|
||||
if (completions.length == 1) {insert(completions[0]); return true;}
|
||||
|
||||
// Build the select widget
|
||||
var complete = document.createElement("div");
|
||||
complete.className = "CodeMirror-completions";
|
||||
var sel = complete.appendChild(document.createElement("select"));
|
||||
// Opera doesn't move the selection when pressing up/down in a
|
||||
// multi-select, but it does properly support the size property on
|
||||
// single-selects, so no multi-select is necessary.
|
||||
if (!window.opera) sel.multiple = true;
|
||||
for (var i = 0; i < completions.length; ++i) {
|
||||
var opt = sel.appendChild(document.createElement("option"));
|
||||
opt.appendChild(document.createTextNode(completions[i]));
|
||||
}
|
||||
sel.firstChild.selected = true;
|
||||
sel.size = Math.min(10, completions.length);
|
||||
var pos = editor.cursorCoords();
|
||||
complete.style.left = pos.x + "px";
|
||||
complete.style.top = pos.yBot + "px";
|
||||
document.body.appendChild(complete);
|
||||
// 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);
|
||||
if(winW - pos.x < sel.clientWidth)
|
||||
complete.style.left = (pos.x - sel.clientWidth) + "px";
|
||||
// Hack to hide the scrollbar.
|
||||
if (completions.length <= 10)
|
||||
complete.style.width = (sel.clientWidth - 1) + "px";
|
||||
|
||||
var done = false;
|
||||
function close() {
|
||||
if (done) return;
|
||||
done = true;
|
||||
complete.parentNode.removeChild(complete);
|
||||
}
|
||||
function pick() {
|
||||
insert(completions[sel.selectedIndex]);
|
||||
close();
|
||||
setTimeout(function(){editor.focus();}, 50);
|
||||
}
|
||||
CodeMirror.connect(sel, "blur", close);
|
||||
CodeMirror.connect(sel, "keydown", function(event) {
|
||||
var code = event.keyCode;
|
||||
// Enter
|
||||
if (code == 13) {CodeMirror.e_stop(event); pick();}
|
||||
// Escape
|
||||
else if (code == 27) {CodeMirror.e_stop(event); close(); editor.focus();}
|
||||
else if (code != 38 && code != 40) {
|
||||
close(); editor.focus();
|
||||
// Pass the event to the CodeMirror instance so that it can handle things like backspace properly.
|
||||
editor.triggerOnKeyDown(event);
|
||||
setTimeout(function(){CodeMirror.simpleHint(editor, getHints);}, 50);
|
||||
}
|
||||
});
|
||||
CodeMirror.connect(sel, "dblclick", pick);
|
||||
|
||||
sel.focus();
|
||||
// Opera sometimes ignores focusing a freshly created node
|
||||
if (window.opera) setTimeout(function(){if (!done) sel.focus();}, 100);
|
||||
return true;
|
||||
};
|
||||
})();
|
||||
381
lib/assets/javascripts/utils/xml.codemirror.js
Normal file
381
lib/assets/javascripts/utils/xml.codemirror.js
Normal file
@@ -0,0 +1,381 @@
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("xml", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit;
|
||||
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
|
||||
var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
|
||||
if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
|
||||
|
||||
var Kludges = parserConfig.htmlMode ? {
|
||||
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
|
||||
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
|
||||
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
|
||||
'track': true, 'wbr': true},
|
||||
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
|
||||
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
|
||||
'th': true, 'tr': true},
|
||||
contextGrabbers: {
|
||||
'dd': {'dd': true, 'dt': true},
|
||||
'dt': {'dd': true, 'dt': true},
|
||||
'li': {'li': true},
|
||||
'option': {'option': true, 'optgroup': true},
|
||||
'optgroup': {'optgroup': true},
|
||||
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
|
||||
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
|
||||
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
|
||||
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
|
||||
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
|
||||
'rp': {'rp': true, 'rt': true},
|
||||
'rt': {'rp': true, 'rt': true},
|
||||
'tbody': {'tbody': true, 'tfoot': true},
|
||||
'td': {'td': true, 'th': true},
|
||||
'tfoot': {'tbody': true},
|
||||
'th': {'td': true, 'th': true},
|
||||
'thead': {'tbody': true, 'tfoot': true},
|
||||
'tr': {'tr': true}
|
||||
},
|
||||
doNotIndent: {"pre": true},
|
||||
allowUnquoted: true,
|
||||
allowMissing: true,
|
||||
caseFold: true
|
||||
} : {
|
||||
autoSelfClosers: {},
|
||||
implicitlyClosed: {},
|
||||
contextGrabbers: {},
|
||||
doNotIndent: {},
|
||||
allowUnquoted: false,
|
||||
allowMissing: false,
|
||||
caseFold: false
|
||||
};
|
||||
var alignCDATA = parserConfig.alignCDATA;
|
||||
|
||||
// Return variables for tokenizers
|
||||
var type, setStyle;
|
||||
|
||||
function inText(stream, state) {
|
||||
function chain(parser) {
|
||||
state.tokenize = parser;
|
||||
return parser(stream, state);
|
||||
}
|
||||
|
||||
var ch = stream.next();
|
||||
if (ch == "<") {
|
||||
if (stream.eat("!")) {
|
||||
if (stream.eat("[")) {
|
||||
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
|
||||
else return null;
|
||||
} else if (stream.match("--")) {
|
||||
return chain(inBlock("comment", "-->"));
|
||||
} else if (stream.match("DOCTYPE", true, true)) {
|
||||
stream.eatWhile(/[\w\._\-]/);
|
||||
return chain(doctype(1));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (stream.eat("?")) {
|
||||
stream.eatWhile(/[\w\._\-]/);
|
||||
state.tokenize = inBlock("meta", "?>");
|
||||
return "meta";
|
||||
} else {
|
||||
type = stream.eat("/") ? "closeTag" : "openTag";
|
||||
state.tokenize = inTag;
|
||||
return "tag bracket";
|
||||
}
|
||||
} else if (ch == "&") {
|
||||
var ok;
|
||||
if (stream.eat("#")) {
|
||||
if (stream.eat("x")) {
|
||||
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
|
||||
} else {
|
||||
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
|
||||
}
|
||||
} else {
|
||||
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
|
||||
}
|
||||
return ok ? "atom" : "error";
|
||||
} else {
|
||||
stream.eatWhile(/[^&<]/);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function inTag(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
|
||||
state.tokenize = inText;
|
||||
type = ch == ">" ? "endTag" : "selfcloseTag";
|
||||
return "tag bracket";
|
||||
} else if (ch == "=") {
|
||||
type = "equals";
|
||||
return null;
|
||||
} else if (ch == "<") {
|
||||
state.tokenize = inText;
|
||||
state.state = baseState;
|
||||
state.tagName = state.tagStart = null;
|
||||
var next = state.tokenize(stream, state);
|
||||
return next ? next + " error" : "error";
|
||||
} else if (/[\'\"]/.test(ch)) {
|
||||
state.tokenize = inAttribute(ch);
|
||||
state.stringStartCol = stream.column();
|
||||
return state.tokenize(stream, state);
|
||||
} else {
|
||||
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
|
||||
return "word";
|
||||
}
|
||||
}
|
||||
|
||||
function inAttribute(quote) {
|
||||
var closure = function(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
if (stream.next() == quote) {
|
||||
state.tokenize = inTag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "string";
|
||||
};
|
||||
closure.isInAttribute = true;
|
||||
return closure;
|
||||
}
|
||||
|
||||
function inBlock(style, terminator) {
|
||||
return function(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
if (stream.match(terminator)) {
|
||||
state.tokenize = inText;
|
||||
break;
|
||||
}
|
||||
stream.next();
|
||||
}
|
||||
return style;
|
||||
};
|
||||
}
|
||||
function doctype(depth) {
|
||||
return function(stream, state) {
|
||||
var ch;
|
||||
while ((ch = stream.next()) != null) {
|
||||
if (ch == "<") {
|
||||
state.tokenize = doctype(depth + 1);
|
||||
return state.tokenize(stream, state);
|
||||
} else if (ch == ">") {
|
||||
if (depth == 1) {
|
||||
state.tokenize = inText;
|
||||
break;
|
||||
} else {
|
||||
state.tokenize = doctype(depth - 1);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
return "meta";
|
||||
};
|
||||
}
|
||||
|
||||
function Context(state, tagName, startOfLine) {
|
||||
this.prev = state.context;
|
||||
this.tagName = tagName;
|
||||
this.indent = state.indented;
|
||||
this.startOfLine = startOfLine;
|
||||
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
|
||||
this.noIndent = true;
|
||||
}
|
||||
function popContext(state) {
|
||||
if (state.context) state.context = state.context.prev;
|
||||
}
|
||||
function maybePopContext(state, nextTagName) {
|
||||
var parentTagName;
|
||||
while (true) {
|
||||
if (!state.context) {
|
||||
return;
|
||||
}
|
||||
parentTagName = state.context.tagName;
|
||||
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
|
||||
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
|
||||
return;
|
||||
}
|
||||
popContext(state);
|
||||
}
|
||||
}
|
||||
|
||||
function baseState(type, stream, state) {
|
||||
if (type == "openTag") {
|
||||
state.tagStart = stream.column();
|
||||
return tagNameState;
|
||||
} else if (type == "closeTag") {
|
||||
return closeTagNameState;
|
||||
} else {
|
||||
return baseState;
|
||||
}
|
||||
}
|
||||
function tagNameState(type, stream, state) {
|
||||
if (type == "word") {
|
||||
state.tagName = stream.current();
|
||||
setStyle = "tag";
|
||||
return attrState;
|
||||
} else {
|
||||
setStyle = "error";
|
||||
return tagNameState;
|
||||
}
|
||||
}
|
||||
function closeTagNameState(type, stream, state) {
|
||||
if (type == "word") {
|
||||
var tagName = stream.current();
|
||||
if (state.context && state.context.tagName != tagName &&
|
||||
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
|
||||
popContext(state);
|
||||
if (state.context && state.context.tagName == tagName) {
|
||||
setStyle = "tag";
|
||||
return closeState;
|
||||
} else {
|
||||
setStyle = "tag error";
|
||||
return closeStateErr;
|
||||
}
|
||||
} else {
|
||||
setStyle = "error";
|
||||
return closeStateErr;
|
||||
}
|
||||
}
|
||||
|
||||
function closeState(type, _stream, state) {
|
||||
if (type != "endTag") {
|
||||
setStyle = "error";
|
||||
return closeState;
|
||||
}
|
||||
popContext(state);
|
||||
return baseState;
|
||||
}
|
||||
function closeStateErr(type, stream, state) {
|
||||
setStyle = "error";
|
||||
return closeState(type, stream, state);
|
||||
}
|
||||
|
||||
function attrState(type, _stream, state) {
|
||||
if (type == "word") {
|
||||
setStyle = "attribute";
|
||||
return attrEqState;
|
||||
} else if (type == "endTag" || type == "selfcloseTag") {
|
||||
var tagName = state.tagName, tagStart = state.tagStart;
|
||||
state.tagName = state.tagStart = null;
|
||||
if (type == "selfcloseTag" ||
|
||||
Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
|
||||
maybePopContext(state, tagName);
|
||||
} else {
|
||||
maybePopContext(state, tagName);
|
||||
state.context = new Context(state, tagName, tagStart == state.indented);
|
||||
}
|
||||
return baseState;
|
||||
}
|
||||
setStyle = "error";
|
||||
return attrState;
|
||||
}
|
||||
function attrEqState(type, stream, state) {
|
||||
if (type == "equals") return attrValueState;
|
||||
if (!Kludges.allowMissing) setStyle = "error";
|
||||
return attrState(type, stream, state);
|
||||
}
|
||||
function attrValueState(type, stream, state) {
|
||||
if (type == "string") return attrContinuedState;
|
||||
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
|
||||
setStyle = "error";
|
||||
return attrState(type, stream, state);
|
||||
}
|
||||
function attrContinuedState(type, stream, state) {
|
||||
if (type == "string") return attrContinuedState;
|
||||
return attrState(type, stream, state);
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {tokenize: inText,
|
||||
state: baseState,
|
||||
indented: 0,
|
||||
tagName: null, tagStart: null,
|
||||
context: null};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (!state.tagName && stream.sol())
|
||||
state.indented = stream.indentation();
|
||||
|
||||
if (stream.eatSpace()) return null;
|
||||
type = null;
|
||||
var style = state.tokenize(stream, state);
|
||||
if ((style || type) && style != "comment") {
|
||||
setStyle = null;
|
||||
state.state = state.state(type || style, stream, state);
|
||||
if (setStyle)
|
||||
style = setStyle == "error" ? style + " error" : setStyle;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter, fullLine) {
|
||||
var context = state.context;
|
||||
// Indent multi-line strings (e.g. css).
|
||||
if (state.tokenize.isInAttribute) {
|
||||
if (state.tagStart == state.indented)
|
||||
return state.stringStartCol + 1;
|
||||
else
|
||||
return state.indented + indentUnit;
|
||||
}
|
||||
if (context && context.noIndent) return CodeMirror.Pass;
|
||||
if (state.tokenize != inTag && state.tokenize != inText)
|
||||
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
|
||||
// Indent the starts of attribute names.
|
||||
if (state.tagName) {
|
||||
if (multilineTagIndentPastTag)
|
||||
return state.tagStart + state.tagName.length + 2;
|
||||
else
|
||||
return state.tagStart + indentUnit * multilineTagIndentFactor;
|
||||
}
|
||||
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
|
||||
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
|
||||
if (tagAfter && tagAfter[1]) { // Closing tag spotted
|
||||
while (context) {
|
||||
if (context.tagName == tagAfter[2]) {
|
||||
context = context.prev;
|
||||
break;
|
||||
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
|
||||
context = context.prev;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (tagAfter) { // Opening tag spotted
|
||||
while (context) {
|
||||
var grabbers = Kludges.contextGrabbers[context.tagName];
|
||||
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
|
||||
context = context.prev;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (context && !context.startOfLine)
|
||||
context = context.prev;
|
||||
if (context) return context.indent + indentUnit;
|
||||
else return 0;
|
||||
},
|
||||
|
||||
electricInput: /<\/[\s\w:]+>$/,
|
||||
blockCommentStart: "<!--",
|
||||
blockCommentEnd: "-->",
|
||||
|
||||
configuration: parserConfig.htmlMode ? "html" : "xml",
|
||||
helperType: parserConfig.htmlMode ? "html" : "xml"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/xml", "xml");
|
||||
CodeMirror.defineMIME("application/xml", "xml");
|
||||
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
|
||||
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user