diff --git a/_server/CodeMirror/codemirror.css b/_server/CodeMirror/codemirror.css index c7a8ae70..07ccdf75 100644 --- a/_server/CodeMirror/codemirror.css +++ b/_server/CodeMirror/codemirror.css @@ -1,154 +1,285 @@ /* BASICS */ .CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; - color: black; - direction: ltr; + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; + color: black; + direction: ltr; } /* PADDING */ .CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ + padding: 4px 0; /* Vertical padding around content */ } + .CodeMirror pre { - padding: 0 4px; /* Horizontal padding of content */ + padding: 0 4px; /* Horizontal padding of content */ } .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: white; /* The little square between H and V scrollbars */ + background-color: white; /* The little square between H and V scrollbars */ } /* GUTTER */ .CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - white-space: nowrap; + border-right: 1px solid #ddd; + background-color: #f7f7f7; + white-space: nowrap; } -.CodeMirror-guttermarker { color: black; } -.CodeMirror-guttermarker-subtle { color: #999; } +.CodeMirror-linenumbers { +} + +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; + white-space: nowrap; +} + +.CodeMirror-guttermarker { + color: black; +} + +.CodeMirror-guttermarker-subtle { + color: #999; +} /* CURSOR */ .CodeMirror-cursor { - border-left: 1px solid black; - border-right: none; - width: 0; + border-left: 1px solid black; + border-right: none; + width: 0; } + /* Shown when moving in bi-directional text */ .CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; + border-left: 1px solid silver; } + .cm-fat-cursor .CodeMirror-cursor { - width: auto; - border: 0 !important; - background: #7e7; + width: auto; + border: 0 !important; + background: #7e7; } + .cm-fat-cursor div.CodeMirror-cursors { - z-index: 1; + z-index: 1; } + .cm-fat-cursor-mark { - background-color: rgba(20, 255, 20, 0.5); - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; + background-color: rgba(20, 255, 20, 0.5); + -webkit-animation: blink 1.06s steps(1) infinite; + -moz-animation: blink 1.06s steps(1) infinite; + animation: blink 1.06s steps(1) infinite; } + .cm-animate-fat-cursor { - width: auto; - border: 0; - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; - background-color: #7e7; + width: auto; + border: 0; + -webkit-animation: blink 1.06s steps(1) infinite; + -moz-animation: blink 1.06s steps(1) infinite; + animation: blink 1.06s steps(1) infinite; + background-color: #7e7; } + @-moz-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} + 0% { + } + 50% { + background-color: transparent; + } + 100% { + } } + @-webkit-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} + 0% { + } + 50% { + background-color: transparent; + } + 100% { + } } + @keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} + 0% { + } + 50% { + background-color: transparent; + } + 100% { + } } /* Can style cursor different in overwrite (non-insert) mode */ -.CodeMirror-overwrite .CodeMirror-cursor {} +.CodeMirror-overwrite .CodeMirror-cursor { +} -.cm-tab { display: inline-block; text-decoration: inherit; } +.cm-tab { + display: inline-block; + text-decoration: inherit; +} .CodeMirror-rulers { - position: absolute; - left: 0; right: 0; top: -50px; bottom: -20px; - overflow: hidden; + position: absolute; + left: 0; + right: 0; + top: -50px; + bottom: -20px; + overflow: hidden; } + .CodeMirror-ruler { - border-left: 1px solid #ccc; - top: 0; bottom: 0; - position: absolute; + border-left: 1px solid #ccc; + top: 0; + bottom: 0; + position: absolute; } /* DEFAULT THEME */ -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} -.cm-strikethrough {text-decoration: line-through;} +.cm-s-default .cm-header { + color: blue; +} + +.cm-s-default .cm-quote { + color: #090; +} + +.cm-negative { + color: #d44; +} + +.cm-positive { + color: #292; +} + +.cm-header, .cm-strong { + font-weight: bold; +} + +.cm-em { + font-style: italic; +} + +.cm-link { + text-decoration: underline; +} + +.cm-strikethrough { + text-decoration: line-through; +} + +.cm-s-default .cm-keyword { + color: #708; +} + +.cm-s-default .cm-atom { + color: #219; +} + +.cm-s-default .cm-number { + color: #164; +} + +.cm-s-default .cm-def { + color: #00f; +} -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} .cm-s-default .cm-variable, .cm-s-default .cm-punctuation, .cm-s-default .cm-property, -.cm-s-default .cm-operator {} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} +.cm-s-default .cm-operator { +} -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} +.cm-s-default .cm-variable-2 { + color: #05a; +} -.CodeMirror-composing { border-bottom: 2px solid; } +.cm-s-default .cm-variable-3, .cm-s-default .cm-type { + color: #085; +} + +.cm-s-default .cm-comment { + color: #a50; +} + +.cm-s-default .cm-string { + color: #a11; +} + +.cm-s-default .cm-string-2 { + color: #f50; +} + +.cm-s-default .cm-meta { + color: #555; +} + +.cm-s-default .cm-qualifier { + color: #555; +} + +.cm-s-default .cm-builtin { + color: #30a; +} + +.cm-s-default .cm-bracket { + color: #997; +} + +.cm-s-default .cm-tag { + color: #170; +} + +.cm-s-default .cm-attribute { + color: #00c; +} + +.cm-s-default .cm-hr { + color: #999; +} + +.cm-s-default .cm-link { + color: #00c; +} + +.cm-s-default .cm-error { + color: #f00; +} + +.cm-invalidchar { + color: #f00; +} + +.CodeMirror-composing { + border-bottom: 2px solid; +} /* Default styles for common addons */ -div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} -.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } -.CodeMirror-activeline-background {background: #e8f2ff;} +div.CodeMirror span.CodeMirror-matchingbracket { + color: #0b0; +} + +div.CodeMirror span.CodeMirror-nonmatchingbracket { + color: #a22; +} + +.CodeMirror-matchingtag { + background: rgba(255, 150, 0, .3); +} + +.CodeMirror-activeline-background { + background: #e8f2ff; +} /* STOP */ @@ -156,129 +287,162 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} the editor. You probably shouldn't touch them. */ .CodeMirror { - position: relative; - overflow: hidden; - background: white; + position: relative; + overflow: hidden; + background: white; } .CodeMirror-scroll { - overflow: scroll !important; /* Things will break if this is overridden */ - /* 30px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; + overflow: scroll !important; /* Things will break if this is overridden */ + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror */ + margin-bottom: -30px; + margin-right: -30px; + padding-bottom: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; } + .CodeMirror-sizer { - position: relative; - border-right: 30px solid transparent; + position: relative; + border-right: 30px solid transparent; } /* The fake, visible scrollbars. Used to force redraw during scrolling before actual scrolling happens, thus preventing shaking and flickering artifacts. */ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; + position: absolute; + z-index: 6; + display: none; } + .CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; + right: 0; + top: 0; + overflow-x: hidden; + overflow-y: scroll; } + .CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; + bottom: 0; + left: 0; + overflow-y: hidden; + overflow-x: scroll; } + .CodeMirror-scrollbar-filler { - right: 0; bottom: 0; + right: 0; + bottom: 0; } + .CodeMirror-gutter-filler { - left: 0; bottom: 0; + left: 0; + bottom: 0; } .CodeMirror-gutters { - position: absolute; left: 0; top: 0; - min-height: 100%; - z-index: 3; + position: absolute; + left: 0; + top: 0; + min-height: 100%; + z-index: 3; } + .CodeMirror-gutter { - white-space: normal; - height: 100%; - display: inline-block; - vertical-align: top; - margin-bottom: -30px; + white-space: normal; + height: 100%; + display: inline-block; + vertical-align: top; + margin-bottom: -30px; } + .CodeMirror-gutter-wrapper { - position: absolute; - z-index: 4; - background: none !important; - border: none !important; + position: absolute; + z-index: 4; + background: none !important; + border: none !important; } + .CodeMirror-gutter-background { - position: absolute; - top: 0; bottom: 0; - z-index: 4; + position: absolute; + top: 0; + bottom: 0; + z-index: 4; } + .CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; + position: absolute; + cursor: default; + z-index: 4; +} + +.CodeMirror-gutter-wrapper ::selection { + background-color: transparent +} + +.CodeMirror-gutter-wrapper ::-moz-selection { + background-color: transparent } -.CodeMirror-gutter-wrapper ::selection { background-color: transparent } -.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent } .CodeMirror-lines { - cursor: text; - min-height: 1px; /* prevents collapsing before first draw */ + cursor: text; + min-height: 1px; /* prevents collapsing before first draw */ } + .CodeMirror pre { - /* Reset some styles that the rest of the page might have set */ - -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; - -webkit-tap-highlight-color: transparent; - -webkit-font-variant-ligatures: contextual; - font-variant-ligatures: contextual; + /* Reset some styles that the rest of the page might have set */ + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; + border-width: 0; + background: transparent; + font-family: inherit; + font-size: inherit; + margin: 0; + white-space: pre; + word-wrap: normal; + line-height: inherit; + color: inherit; + z-index: 2; + position: relative; + overflow: visible; + -webkit-tap-highlight-color: transparent; + -webkit-font-variant-ligatures: contextual; + font-variant-ligatures: contextual; } + .CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; + word-wrap: break-word; + white-space: pre-wrap; + word-break: normal; } .CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + z-index: 0; } .CodeMirror-linewidget { - position: relative; - z-index: 2; - padding: 0.1px; /* Force widget margins to stay inside of the container */ + position: relative; + z-index: 2; + padding: 0.1px; /* Force widget margins to stay inside of the container */ } -.CodeMirror-widget {} +.CodeMirror-widget { +} -.CodeMirror-rtl pre { direction: rtl; } +.CodeMirror-rtl pre { + direction: rtl; +} .CodeMirror-code { - outline: none; + outline: none; } /* Force content-box sizing for the elements where we expect it */ @@ -287,60 +451,84 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} .CodeMirror-gutter, .CodeMirror-gutters, .CodeMirror-linenumber { - -moz-box-sizing: content-box; - box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; } .CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; + position: absolute; + width: 100%; + height: 0; + overflow: hidden; + visibility: hidden; } .CodeMirror-cursor { - position: absolute; - pointer-events: none; + position: absolute; + pointer-events: none; +} + +.CodeMirror-measure pre { + position: static; } -.CodeMirror-measure pre { position: static; } div.CodeMirror-cursors { - visibility: hidden; - position: relative; - z-index: 3; + visibility: hidden; + position: relative; + z-index: 3; } + div.CodeMirror-dragcursors { - visibility: visible; + visibility: visible; } .CodeMirror-focused div.CodeMirror-cursors { - visibility: visible; + visibility: visible; } -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } -.CodeMirror-crosshair { cursor: crosshair; } -.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } -.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } +.CodeMirror-selected { + background: #d9d9d9; +} + +.CodeMirror-focused .CodeMirror-selected { + background: #d7d4f0; +} + +.CodeMirror-crosshair { + cursor: crosshair; +} + +.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { + background: #d7d4f0; +} + +.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { + background: #d7d4f0; +} .cm-searching { - background-color: #ffa; - background-color: rgba(255, 255, 0, .4); + background-color: #ffa; + background-color: rgba(255, 255, 0, .4); } /* Used to force a border model for a node */ -.cm-force-border { padding-right: .1px; } +.cm-force-border { + padding-right: .1px; +} @media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursors { - visibility: hidden; - } + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursors { + visibility: hidden; + } } /* See issue #2901 */ -.cm-tab-wrap-hack:after { content: ''; } +.cm-tab-wrap-hack:after { + content: ''; +} /* Help users use markselection to safely style text background */ -span.CodeMirror-selectedtext { background: none; } +span.CodeMirror-selectedtext { + background: none; +} diff --git a/_server/CodeMirror/javascript-hint.js b/_server/CodeMirror/javascript-hint.js index 21d1fe9a..e84049f1 100644 --- a/_server/CodeMirror/javascript-hint.js +++ b/_server/CodeMirror/javascript-hint.js @@ -1,156 +1,165 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE -(function(mod) { +(function (mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror"], mod); else // Plain browser env - mod(CodeMirror); - })(function(CodeMirror) { + mod(CodeMirror); +})(function (CodeMirror) { var Pos = CodeMirror.Pos; - + function forEach(arr, f) { - for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); + for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); } - + function arrayContains(arr, item) { - if (!Array.prototype.indexOf) { - var i = arr.length; - while (i--) { - if (arr[i] === item) { - return true; - } + if (!Array.prototype.indexOf) { + var i = arr.length; + while (i--) { + if (arr[i] === item) { + return true; + } + } + return false; } - return false; - } - return arr.indexOf(item) != -1; + return arr.indexOf(item) != -1; } - + function scriptHint(editor, keywords, getToken, options) { - // Find the token at the cursor - var cur = editor.getCursor(), token = getToken(editor, cur); - if (/\b(?:string|comment)\b/.test(token.type)) return; - token.state = CodeMirror.innerMode(editor.getMode(), token.state).state; - - // If it's not a 'word-style' token, ignore the token. - if (!/^[\w$_]*$/.test(token.string)) { - token = {start: cur.ch, end: cur.ch, string: "", state: token.state, - type: token.string == "." ? "property" : null}; - } else if (token.end > cur.ch) { - token.end = cur.ch; - token.string = token.string.slice(0, cur.ch - token.start); - } - - var tprop = token; - // If it is a property, find out what it is a property of. - while (tprop.type == "property") { - tprop = getToken(editor, Pos(cur.line, tprop.start)); - if (tprop.string != ".") return; - tprop = getToken(editor, Pos(cur.line, tprop.start)); - if (!context) var context = []; - context.push(tprop); - } - return {list: getCompletions(token, context, keywords, options), - from: Pos(cur.line, token.start), - to: Pos(cur.line, token.end)}; + // Find the token at the cursor + var cur = editor.getCursor(), token = getToken(editor, cur); + if (/\b(?:string|comment)\b/.test(token.type)) return; + token.state = CodeMirror.innerMode(editor.getMode(), token.state).state; + + // If it's not a 'word-style' token, ignore the token. + if (!/^[\w$_]*$/.test(token.string)) { + token = { + start: cur.ch, end: cur.ch, string: "", state: token.state, + type: token.string == "." ? "property" : null + }; + } else if (token.end > cur.ch) { + token.end = cur.ch; + token.string = token.string.slice(0, cur.ch - token.start); + } + + var tprop = token; + // If it is a property, find out what it is a property of. + while (tprop.type == "property") { + tprop = getToken(editor, Pos(cur.line, tprop.start)); + if (tprop.string != ".") return; + tprop = getToken(editor, Pos(cur.line, tprop.start)); + if (!context) var context = []; + context.push(tprop); + } + return { + list: getCompletions(token, context, keywords, options), + from: Pos(cur.line, token.start), + to: Pos(cur.line, token.end) + }; } - + function javascriptHint(editor, options) { - return scriptHint(editor, javascriptKeywords, - function (e, cur) {return e.getTokenAt(cur);}, - options); + return scriptHint(editor, javascriptKeywords, + function (e, cur) { + return e.getTokenAt(cur); + }, + options); }; CodeMirror.registerHelper("hint", "javascript", javascriptHint); - + function getCoffeeScriptToken(editor, cur) { - // This getToken, it is for coffeescript, imitates the behavior of - // getTokenAt method in javascript.js, that is, returning "property" - // type and treat "." as indepenent token. - var token = editor.getTokenAt(cur); - if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') { - token.end = token.start; - token.string = '.'; - token.type = "property"; - } - else if (/^\.[\w$_]*$/.test(token.string)) { - token.type = "property"; - token.start++; - token.string = token.string.replace(/\./, ''); - } - return token; + // This getToken, it is for coffeescript, imitates the behavior of + // getTokenAt method in javascript.js, that is, returning "property" + // type and treat "." as indepenent token. + var token = editor.getTokenAt(cur); + if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') { + token.end = token.start; + token.string = '.'; + token.type = "property"; + } + else if (/^\.[\w$_]*$/.test(token.string)) { + token.type = "property"; + token.start++; + token.string = token.string.replace(/\./, ''); + } + return token; } - + function coffeescriptHint(editor, options) { - return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options); + return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options); } + CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint); - + var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " + - "toUpperCase toLowerCase split concat match replace search").split(" "); + "toUpperCase toLowerCase split concat match replace search").split(" "); var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " + - "lastIndexOf every some filter forEach map reduce reduceRight ").split(" "); + "lastIndexOf every some filter forEach map reduce reduceRight ").split(" "); var funcProps = "prototype apply call bind".split(" "); var javascriptKeywords = ("break case catch class const continue debugger default delete do else export extends false finally for function " + - "if in import instanceof new null return super switch this throw true try typeof var void while with yield").split(" "); + "if in import instanceof new null return super switch this throw true try typeof var void while with yield").split(" "); var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " + - "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" "); - + "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" "); + function forAllProps(obj, callback) { - if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) { - for (var name in obj) callback(name) - } else { - for (var o = obj; o; o = Object.getPrototypeOf(o)) - Object.getOwnPropertyNames(o).forEach(callback) - } - } - - function getCompletions(token, context, keywords, options) { - var found = [], start = token.string, global = options && options.globalScope || window; - function maybeAdd(str) { - if (str==null || str==undefined) return; - if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); - } - function gatherCompletions(obj) { - if (typeof obj == "string") forEach(stringProps, maybeAdd); - else if (obj instanceof Array) forEach(arrayProps, maybeAdd); - else if (obj instanceof Function) forEach(funcProps, maybeAdd); - forAllProps(obj, maybeAdd) - } - - if (context && context.length) { - // If this is a property, see if it belongs to some object we can - // find in the current environment. - var obj = context.pop(), base; - if (obj.type && obj.type.indexOf("variable") === 0) { - if (options && options.additionalContext) - base = options.additionalContext[obj.string]; - if (!options || options.useGlobalScope !== false) - base = base || global[obj.string]; - } else if (obj.type == "string") { - base = ""; - } else if (obj.type == "atom") { - base = 1; - } else if (obj.type == "function") { - if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') && - (typeof global.jQuery == 'function')) - base = global.jQuery(); - else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function')) - base = global._(); + if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) { + for (var name in obj) callback(name) + } else { + for (var o = obj; o; o = Object.getPrototypeOf(o)) + Object.getOwnPropertyNames(o).forEach(callback) } - while (base != null && context.length) - base = base[context.pop().string]; - if (base != null) gatherCompletions(base); - } else { - // If not, just look in the global object and any local scope - // (reading into JS mode internals to get at the local and global variables) - for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); - for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name); - if (!options || options.useGlobalScope !== false) - gatherCompletions(global); - forEach(keywords, maybeAdd); - } - return found; } - }); \ No newline at end of file + + function getCompletions(token, context, keywords, options) { + var found = [], start = token.string, global = options && options.globalScope || window; + + function maybeAdd(str) { + if (str == null || str == undefined) return; + if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); + } + + function gatherCompletions(obj) { + if (typeof obj == "string") forEach(stringProps, maybeAdd); + else if (obj instanceof Array) forEach(arrayProps, maybeAdd); + else if (obj instanceof Function) forEach(funcProps, maybeAdd); + forAllProps(obj, maybeAdd) + } + + if (context && context.length) { + // If this is a property, see if it belongs to some object we can + // find in the current environment. + var obj = context.pop(), base; + if (obj.type && obj.type.indexOf("variable") === 0) { + if (options && options.additionalContext) + base = options.additionalContext[obj.string]; + if (!options || options.useGlobalScope !== false) + base = base || global[obj.string]; + } else if (obj.type == "string") { + base = ""; + } else if (obj.type == "atom") { + base = 1; + } else if (obj.type == "function") { + if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') && + (typeof global.jQuery == 'function')) + base = global.jQuery(); + else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function')) + base = global._(); + } + while (base != null && context.length) + base = base[context.pop().string]; + if (base != null) gatherCompletions(base); + } else { + // If not, just look in the global object and any local scope + // (reading into JS mode internals to get at the local and global variables) + for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); + for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name); + if (!options || options.useGlobalScope !== false) + gatherCompletions(global); + forEach(keywords, maybeAdd); + } + return found; + } +}); \ No newline at end of file diff --git a/_server/CodeMirror/javascript-lint.js b/_server/CodeMirror/javascript-lint.js index fc3dfdc2..a350ce66 100644 --- a/_server/CodeMirror/javascript-lint.js +++ b/_server/CodeMirror/javascript-lint.js @@ -1,63 +1,64 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE -(function(mod) { +(function (mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror"], mod); else // Plain browser env - mod(CodeMirror); - })(function(CodeMirror) { + mod(CodeMirror); +})(function (CodeMirror) { "use strict"; + // declare global: JSHINT - + function validator(text, options) { - if (!window.JSHINT) { - if (window.console) { - window.console.error("Error: window.JSHINT not defined, CodeMirror JavaScript linting cannot run."); - } - return []; - } - if (!options.indent) // JSHint error.character actually is a column index, this fixes underlining on lines using tabs for indentation - options.indent = 1; // JSHint default value is 4 - JSHINT(text, options, options.globals); - var errors = JSHINT.data().errors, result = []; - if (errors) parseErrors(errors, result); - return result; - } - - CodeMirror.registerHelper("lint", "javascript", validator); - - function parseErrors(errors, output) { - for ( var i = 0; i < errors.length; i++) { - var error = errors[i]; - if (error) { - if (error.line <= 0) { + if (!window.JSHINT) { if (window.console) { - window.console.warn("Cannot display JSHint error (invalid line " + error.line + ")", error); + window.console.error("Error: window.JSHINT not defined, CodeMirror JavaScript linting cannot run."); } - continue; - } - - var start = error.character - 1, end = start + 1; - if (error.evidence) { - var index = error.evidence.substring(start).search(/.\b/); - if (index > -1) { - end += index; - } - } - - // Convert to format expected by validation service - var hint = { - message: error.reason, - severity: error.code ? (error.code.startsWith('W') ? "warning" : "error") : "error", - from: CodeMirror.Pos(error.line - 1, start), - to: CodeMirror.Pos(error.line - 1, end) - }; - - output.push(hint); + return []; } - } + if (!options.indent) // JSHint error.character actually is a column index, this fixes underlining on lines using tabs for indentation + options.indent = 1; // JSHint default value is 4 + JSHINT(text, options, options.globals); + var errors = JSHINT.data().errors, result = []; + if (errors) parseErrors(errors, result); + return result; } - }); \ No newline at end of file + + CodeMirror.registerHelper("lint", "javascript", validator); + + function parseErrors(errors, output) { + for (var i = 0; i < errors.length; i++) { + var error = errors[i]; + if (error) { + if (error.line <= 0) { + if (window.console) { + window.console.warn("Cannot display JSHint error (invalid line " + error.line + ")", error); + } + continue; + } + + var start = error.character - 1, end = start + 1; + if (error.evidence) { + var index = error.evidence.substring(start).search(/.\b/); + if (index > -1) { + end += index; + } + } + + // Convert to format expected by validation service + var hint = { + message: error.reason, + severity: error.code ? (error.code.startsWith('W') ? "warning" : "error") : "error", + from: CodeMirror.Pos(error.line - 1, start), + to: CodeMirror.Pos(error.line - 1, end) + }; + + output.push(hint); + } + } + } +}); \ No newline at end of file diff --git a/_server/CodeMirror/lint.css b/_server/CodeMirror/lint.css index 037a451d..a9a0e65b 100644 --- a/_server/CodeMirror/lint.css +++ b/_server/CodeMirror/lint.css @@ -1,9 +1,9 @@ /* The lint marker gutter */ .CodeMirror-lint-markers { width: 16px; - } - - .CodeMirror-lint-tooltip { +} + +.CodeMirror-lint-tooltip { background-color: #ffd; border: 1px solid black; border-radius: 4px 4px 4px 4px; @@ -23,24 +23,22 @@ -webkit-transition: opacity .4s; -o-transition: opacity .4s; -ms-transition: opacity .4s; - } - - .CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning { +} + +.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning { background-position: left bottom; background-repeat: repeat-x; - } - - .CodeMirror-lint-mark-error { - background-image: - url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==") - ; - } - - .CodeMirror-lint-mark-warning { +} + +.CodeMirror-lint-mark-error { + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg=="); +} + +.CodeMirror-lint-mark-warning { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII="); - } - - .CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning { +} + +.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning { background-position: center center; background-repeat: no-repeat; cursor: pointer; @@ -49,25 +47,26 @@ width: 16px; vertical-align: middle; position: relative; - } - - .CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { +} + +.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { padding-left: 18px; background-position: top left; background-repeat: no-repeat; - } - - .CodeMirror-lint-marker-error, .CodeMirror-lint-message-error { +} + +.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII="); - } - - .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { +} + +.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII="); - } - - .CodeMirror-lint-marker-multiple { +} + +.CodeMirror-lint-marker-multiple { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC"); background-repeat: no-repeat; background-position: right bottom; - width: 100%; height: 100%; - } \ No newline at end of file + width: 100%; + height: 100%; +} \ No newline at end of file diff --git a/_server/CodeMirror/lint.js b/_server/CodeMirror/lint.js index df8a60b2..53b1e07d 100644 --- a/_server/CodeMirror/lint.js +++ b/_server/CodeMirror/lint.js @@ -1,252 +1,277 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE -(function(mod) { +(function (mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror"], mod); else // Plain browser env - mod(CodeMirror); - })(function(CodeMirror) { + mod(CodeMirror); +})(function (CodeMirror) { "use strict"; var GUTTER_ID = "CodeMirror-lint-markers"; - + function showTooltip(e, content) { - var tt = document.createElement("div"); - tt.className = "CodeMirror-lint-tooltip"; - tt.appendChild(content.cloneNode(true)); - document.body.appendChild(tt); - - function position(e) { - if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position); - tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px"; - tt.style.left = (e.clientX + 5) + "px"; - } - CodeMirror.on(document, "mousemove", position); - position(e); - if (tt.style.opacity != null) tt.style.opacity = 1; - return tt; + var tt = document.createElement("div"); + tt.className = "CodeMirror-lint-tooltip"; + tt.appendChild(content.cloneNode(true)); + document.body.appendChild(tt); + + function position(e) { + if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position); + tt.style.top = Math.max(0, e.clientY - tt.offsetHeight - 5) + "px"; + tt.style.left = (e.clientX + 5) + "px"; + } + + CodeMirror.on(document, "mousemove", position); + position(e); + if (tt.style.opacity != null) tt.style.opacity = 1; + return tt; } + function rm(elt) { - if (elt.parentNode) elt.parentNode.removeChild(elt); + if (elt.parentNode) elt.parentNode.removeChild(elt); } + function hideTooltip(tt) { - if (!tt.parentNode) return; - if (tt.style.opacity == null) rm(tt); - tt.style.opacity = 0; - setTimeout(function() { rm(tt); }, 600); + if (!tt.parentNode) return; + if (tt.style.opacity == null) rm(tt); + tt.style.opacity = 0; + setTimeout(function () { + rm(tt); + }, 600); } - + function showTooltipFor(e, content, node) { - var tooltip = showTooltip(e, content); - function hide() { - CodeMirror.off(node, "mouseout", hide); - if (tooltip) { hideTooltip(tooltip); tooltip = null; } - } - var poll = setInterval(function() { - if (tooltip) for (var n = node;; n = n.parentNode) { - if (n && n.nodeType == 11) n = n.host; - if (n == document.body) return; - if (!n) { hide(); break; } + var tooltip = showTooltip(e, content); + + function hide() { + CodeMirror.off(node, "mouseout", hide); + if (tooltip) { + hideTooltip(tooltip); + tooltip = null; + } } - if (!tooltip) return clearInterval(poll); - }, 400); - CodeMirror.on(node, "mouseout", hide); + + var poll = setInterval(function () { + if (tooltip) for (var n = node; ; n = n.parentNode) { + if (n && n.nodeType == 11) n = n.host; + if (n == document.body) return; + if (!n) { + hide(); + break; + } + } + if (!tooltip) return clearInterval(poll); + }, 400); + CodeMirror.on(node, "mouseout", hide); } - + function LintState(cm, options, hasGutter) { - this.marked = []; - this.options = options; - this.timeout = null; - this.hasGutter = hasGutter; - this.onMouseOver = function(e) { onMouseOver(cm, e); }; - this.waitingFor = 0 + this.marked = []; + this.options = options; + this.timeout = null; + this.hasGutter = hasGutter; + this.onMouseOver = function (e) { + onMouseOver(cm, e); + }; + this.waitingFor = 0 } - + function parseOptions(_cm, options) { - if (options instanceof Function) return {getAnnotations: options}; - if (!options || options === true) options = {}; - return options; + if (options instanceof Function) return {getAnnotations: options}; + if (!options || options === true) options = {}; + return options; } - + function clearMarks(cm) { - var state = cm.state.lint; - if (state.hasGutter) cm.clearGutter(GUTTER_ID); - for (var i = 0; i < state.marked.length; ++i) - state.marked[i].clear(); - state.marked.length = 0; + var state = cm.state.lint; + if (state.hasGutter) cm.clearGutter(GUTTER_ID); + for (var i = 0; i < state.marked.length; ++i) + state.marked[i].clear(); + state.marked.length = 0; } - + function makeMarker(labels, severity, multiple, tooltips) { - var marker = document.createElement("div"), inner = marker; - marker.className = "CodeMirror-lint-marker-" + severity; - if (multiple) { - inner = marker.appendChild(document.createElement("div")); - inner.className = "CodeMirror-lint-marker-multiple"; - } - - if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) { - showTooltipFor(e, labels, inner); - }); - - return marker; - } - - function getMaxSeverity(a, b) { - if (a == "error") return a; - else return b; - } - - function groupByLine(annotations) { - var lines = []; - for (var i = 0; i < annotations.length; ++i) { - var ann = annotations[i], line = ann.from.line; - (lines[line] || (lines[line] = [])).push(ann); - } - return lines; - } - - function annotationTooltip(ann) { - var severity = ann.severity; - if (!severity) severity = "error"; - var tip = document.createElement("div"); - tip.className = "CodeMirror-lint-message-" + severity; - if (typeof ann.messageHTML != 'undefined') { - tip.innerHTML = ann.messageHTML; - } else { - tip.appendChild(document.createTextNode(ann.message)); - } - return tip; - } - - function lintAsync(cm, getAnnotations, passOptions) { - var state = cm.state.lint - var id = ++state.waitingFor - function abort() { - id = -1 - cm.off("change", abort) - } - cm.on("change", abort) - getAnnotations(cm.getValue(), function(annotations, arg2) { - cm.off("change", abort) - if (state.waitingFor != id) return - if (arg2 && annotations instanceof CodeMirror) annotations = arg2 - cm.operation(function() {updateLinting(cm, annotations)}) - }, passOptions, cm); - } - - function startLinting(cm) { - var state = cm.state.lint, options = state.options; - /* - * Passing rules in `options` property prevents JSHint (and other linters) from complaining - * about unrecognized rules like `onUpdateLinting`, `delay`, `lintOnChange`, etc. - */ - var passOptions = options.options || options; - var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint"); - if (!getAnnotations) return; - if (options.async || getAnnotations.async) { - lintAsync(cm, getAnnotations, passOptions) - } else { - var annotations = getAnnotations(cm.getValue(), passOptions, cm); - if (!annotations) return; - if (annotations.then) annotations.then(function(issues) { - cm.operation(function() {updateLinting(cm, issues)}) - }); - else cm.operation(function() {updateLinting(cm, annotations)}) - } - } - - function updateLinting(cm, annotationsNotSorted) { - clearMarks(cm); - var state = cm.state.lint, options = state.options; - - var annotations = groupByLine(annotationsNotSorted); - - for (var line = 0; line < annotations.length; ++line) { - var anns = annotations[line]; - if (!anns) continue; - - var maxSeverity = null; - var tipLabel = state.hasGutter && document.createDocumentFragment(); - - for (var i = 0; i < anns.length; ++i) { - var ann = anns[i]; - var severity = ann.severity; - if (!severity) severity = "error"; - maxSeverity = getMaxSeverity(maxSeverity, severity); - - if (options.formatAnnotation) ann = options.formatAnnotation(ann); - if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann)); - - if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, { - className: "CodeMirror-lint-mark-" + severity, - __annotation: ann - })); + var marker = document.createElement("div"), inner = marker; + marker.className = "CodeMirror-lint-marker-" + severity; + if (multiple) { + inner = marker.appendChild(document.createElement("div")); + inner.className = "CodeMirror-lint-marker-multiple"; } - - if (state.hasGutter) - cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1, - state.options.tooltips)); - } - if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm); + + if (tooltips != false) CodeMirror.on(inner, "mouseover", function (e) { + showTooltipFor(e, labels, inner); + }); + + return marker; } - - function onChange(cm) { - var state = cm.state.lint; - if (!state) return; - clearTimeout(state.timeout); - state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500); + + function getMaxSeverity(a, b) { + if (a == "error") return a; + else return b; } - - function popupTooltips(annotations, e) { - var target = e.target || e.srcElement; - var tooltip = document.createDocumentFragment(); - for (var i = 0; i < annotations.length; i++) { - var ann = annotations[i]; - tooltip.appendChild(annotationTooltip(ann)); - } - showTooltipFor(e, tooltip, target); + + function groupByLine(annotations) { + var lines = []; + for (var i = 0; i < annotations.length; ++i) { + var ann = annotations[i], line = ann.from.line; + (lines[line] || (lines[line] = [])).push(ann); + } + return lines; } - - function onMouseOver(cm, e) { - var target = e.target || e.srcElement; - if (!/\bCodeMirror-lint-mark-/.test(target.className)) return; - var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2; - var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client")); - - var annotations = []; - for (var i = 0; i < spans.length; ++i) { - var ann = spans[i].__annotation; - if (ann) annotations.push(ann); - } - if (annotations.length) popupTooltips(annotations, e); + + function annotationTooltip(ann) { + var severity = ann.severity; + if (!severity) severity = "error"; + var tip = document.createElement("div"); + tip.className = "CodeMirror-lint-message-" + severity; + if (typeof ann.messageHTML != 'undefined') { + tip.innerHTML = ann.messageHTML; + } else { + tip.appendChild(document.createTextNode(ann.message)); + } + return tip; } - - CodeMirror.defineOption("lint", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { + + function lintAsync(cm, getAnnotations, passOptions) { + var state = cm.state.lint + var id = ++state.waitingFor + + function abort() { + id = -1 + cm.off("change", abort) + } + + cm.on("change", abort) + getAnnotations(cm.getValue(), function (annotations, arg2) { + cm.off("change", abort) + if (state.waitingFor != id) return + if (arg2 && annotations instanceof CodeMirror) annotations = arg2 + cm.operation(function () { + updateLinting(cm, annotations) + }) + }, passOptions, cm); + } + + function startLinting(cm) { + var state = cm.state.lint, options = state.options; + /* + * Passing rules in `options` property prevents JSHint (and other linters) from complaining + * about unrecognized rules like `onUpdateLinting`, `delay`, `lintOnChange`, etc. + */ + var passOptions = options.options || options; + var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint"); + if (!getAnnotations) return; + if (options.async || getAnnotations.async) { + lintAsync(cm, getAnnotations, passOptions) + } else { + var annotations = getAnnotations(cm.getValue(), passOptions, cm); + if (!annotations) return; + if (annotations.then) annotations.then(function (issues) { + cm.operation(function () { + updateLinting(cm, issues) + }) + }); + else cm.operation(function () { + updateLinting(cm, annotations) + }) + } + } + + function updateLinting(cm, annotationsNotSorted) { clearMarks(cm); - if (cm.state.lint.options.lintOnChange !== false) - cm.off("change", onChange); - CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver); - clearTimeout(cm.state.lint.timeout); - delete cm.state.lint; - } - - if (val) { - var gutters = cm.getOption("gutters"), hasLintGutter = false; - for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true; - var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter); - if (state.options.lintOnChange !== false) - cm.on("change", onChange); - if (state.options.tooltips != false && state.options.tooltips != "gutter") - CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver); - - startLinting(cm); - } + var state = cm.state.lint, options = state.options; + + var annotations = groupByLine(annotationsNotSorted); + + for (var line = 0; line < annotations.length; ++line) { + var anns = annotations[line]; + if (!anns) continue; + + var maxSeverity = null; + var tipLabel = state.hasGutter && document.createDocumentFragment(); + + for (var i = 0; i < anns.length; ++i) { + var ann = anns[i]; + var severity = ann.severity; + if (!severity) severity = "error"; + maxSeverity = getMaxSeverity(maxSeverity, severity); + + if (options.formatAnnotation) ann = options.formatAnnotation(ann); + if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann)); + + if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, { + className: "CodeMirror-lint-mark-" + severity, + __annotation: ann + })); + } + + if (state.hasGutter) + cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1, + state.options.tooltips)); + } + if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm); + } + + function onChange(cm) { + var state = cm.state.lint; + if (!state) return; + clearTimeout(state.timeout); + state.timeout = setTimeout(function () { + startLinting(cm); + }, state.options.delay || 500); + } + + function popupTooltips(annotations, e) { + var target = e.target || e.srcElement; + var tooltip = document.createDocumentFragment(); + for (var i = 0; i < annotations.length; i++) { + var ann = annotations[i]; + tooltip.appendChild(annotationTooltip(ann)); + } + showTooltipFor(e, tooltip, target); + } + + function onMouseOver(cm, e) { + var target = e.target || e.srcElement; + if (!/\bCodeMirror-lint-mark-/.test(target.className)) return; + var box = target.getBoundingClientRect(), x = (box.left + box.right) / 2, y = (box.top + box.bottom) / 2; + var spans = cm.findMarksAt(cm.coordsChar({left: x, top: y}, "client")); + + var annotations = []; + for (var i = 0; i < spans.length; ++i) { + var ann = spans[i].__annotation; + if (ann) annotations.push(ann); + } + if (annotations.length) popupTooltips(annotations, e); + } + + CodeMirror.defineOption("lint", false, function (cm, val, old) { + if (old && old != CodeMirror.Init) { + clearMarks(cm); + if (cm.state.lint.options.lintOnChange !== false) + cm.off("change", onChange); + CodeMirror.off(cm.getWrapperElement(), "mouseover", cm.state.lint.onMouseOver); + clearTimeout(cm.state.lint.timeout); + delete cm.state.lint; + } + + if (val) { + var gutters = cm.getOption("gutters"), hasLintGutter = false; + for (var i = 0; i < gutters.length; ++i) if (gutters[i] == GUTTER_ID) hasLintGutter = true; + var state = cm.state.lint = new LintState(cm, parseOptions(cm, val), hasLintGutter); + if (state.options.lintOnChange !== false) + cm.on("change", onChange); + if (state.options.tooltips != false && state.options.tooltips != "gutter") + CodeMirror.on(cm.getWrapperElement(), "mouseover", state.onMouseOver); + + startLinting(cm); + } }); - - CodeMirror.defineExtension("performLint", function() { - if (this.state.lint) startLinting(this); + + CodeMirror.defineExtension("performLint", function () { + if (this.state.lint) startLinting(this); }); - }); \ No newline at end of file +}); \ No newline at end of file diff --git a/_server/CodeMirror/show-hint.css b/_server/CodeMirror/show-hint.css index 88c93df1..1d26fbeb 100644 --- a/_server/CodeMirror/show-hint.css +++ b/_server/CodeMirror/show-hint.css @@ -3,34 +3,34 @@ z-index: 301; overflow: hidden; list-style: none; - + margin: 0; padding: 2px; - - -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2); - -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2); - box-shadow: 2px 3px 5px rgba(0,0,0,.2); + + -webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); + -moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); + box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); border-radius: 3px; border: 1px solid silver; - + background: white; font-size: 90%; font-family: monospace; - + max-height: 20em; overflow-y: auto; - } - - .CodeMirror-hint { +} + +.CodeMirror-hint { margin: 0; padding: 0 4px; border-radius: 2px; white-space: pre; color: black; cursor: pointer; - } - - li.CodeMirror-hint-active { +} + +li.CodeMirror-hint-active { background: #08f; color: white; - } \ No newline at end of file +} \ No newline at end of file diff --git a/_server/CodeMirror/show-hint.js b/_server/CodeMirror/show-hint.js index d7cd9427..ddf0cfa7 100644 --- a/_server/CodeMirror/show-hint.js +++ b/_server/CodeMirror/show-hint.js @@ -1,432 +1,484 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: http://codemirror.net/LICENSE -(function(mod) { +(function (mod) { if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); + mod(require("../../lib/codemirror")); else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); + define(["../../lib/codemirror"], mod); else // Plain browser env - mod(CodeMirror); - })(function(CodeMirror) { + mod(CodeMirror); +})(function (CodeMirror) { "use strict"; - - var HINT_ELEMENT_CLASS = "CodeMirror-hint"; + + var HINT_ELEMENT_CLASS = "CodeMirror-hint"; var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active"; - + // This is the old interface, kept around for now to stay // backwards-compatible. - CodeMirror.showHint = function(cm, getHints, options) { - if (!getHints) return cm.showHint(options); - if (options && options.async) getHints.async = true; - var newOpts = {hint: getHints}; - if (options) for (var prop in options) newOpts[prop] = options[prop]; - return cm.showHint(newOpts); + CodeMirror.showHint = function (cm, getHints, options) { + if (!getHints) return cm.showHint(options); + if (options && options.async) getHints.async = true; + var newOpts = {hint: getHints}; + if (options) for (var prop in options) newOpts[prop] = options[prop]; + return cm.showHint(newOpts); }; - - CodeMirror.defineExtension("showHint", function(options) { - options = parseOptions(this, this.getCursor("start"), options); - var selections = this.listSelections() - if (selections.length > 1) return; - // By default, don't allow completion when something is selected. - // A hint function can have a `supportsSelection` property to - // indicate that it can handle selections. - if (this.somethingSelected()) { - if (!options.hint.supportsSelection) return; - // Don't try with cross-line selections - for (var i = 0; i < selections.length; i++) - if (selections[i].head.line != selections[i].anchor.line) return; - } - - if (this.state.completionActive) this.state.completionActive.close(); - var completion = this.state.completionActive = new Completion(this, options); - if (!completion.options.hint) return; - - CodeMirror.signal(this, "startCompletion", this); - completion.update(true); + + CodeMirror.defineExtension("showHint", function (options) { + options = parseOptions(this, this.getCursor("start"), options); + var selections = this.listSelections() + if (selections.length > 1) return; + // By default, don't allow completion when something is selected. + // A hint function can have a `supportsSelection` property to + // indicate that it can handle selections. + if (this.somethingSelected()) { + if (!options.hint.supportsSelection) return; + // Don't try with cross-line selections + for (var i = 0; i < selections.length; i++) + if (selections[i].head.line != selections[i].anchor.line) return; + } + + if (this.state.completionActive) this.state.completionActive.close(); + var completion = this.state.completionActive = new Completion(this, options); + if (!completion.options.hint) return; + + CodeMirror.signal(this, "startCompletion", this); + completion.update(true); }); - + function Completion(cm, options) { - this.cm = cm; - this.options = options; - this.widget = null; - this.debounce = 0; - this.tick = 0; - this.startPos = this.cm.getCursor("start"); - this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length; - - var self = this; - cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); }); + this.cm = cm; + this.options = options; + this.widget = null; + this.debounce = 0; + this.tick = 0; + this.startPos = this.cm.getCursor("start"); + this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length; + + var self = this; + cm.on("cursorActivity", this.activityFunc = function () { + self.cursorActivity(); + }); } - - var requestAnimationFrame = window.requestAnimationFrame || function(fn) { - return setTimeout(fn, 1000/60); + + var requestAnimationFrame = window.requestAnimationFrame || function (fn) { + return setTimeout(fn, 1000 / 60); }; var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout; - + Completion.prototype = { - close: function() { - if (!this.active()) return; - this.cm.state.completionActive = null; - this.tick = null; - this.cm.off("cursorActivity", this.activityFunc); - - if (this.widget && this.data) CodeMirror.signal(this.data, "close"); - if (this.widget) this.widget.close(); - 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), completion.from || data.from, - completion.to || data.to, "complete"); - CodeMirror.signal(data, "pick", completion); - this.close(); - }, - - cursorActivity: function() { - if (this.debounce) { - cancelAnimationFrame(this.debounce); - this.debounce = 0; - } - - var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line); - if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch || - pos.ch < this.startPos.ch || this.cm.somethingSelected() || - (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { - this.close(); - } else { - var self = this; - this.debounce = requestAnimationFrame(function() {self.update();}); - if (this.widget) this.widget.disable(); - } - }, - - update: function(first) { - if (this.tick == null) return - var self = this, myTick = ++this.tick - fetchHints(this.options.hint, this.cm, this.options, function(data) { - if (self.tick == myTick) self.finishUpdate(data, first) - }) - }, - - finishUpdate: function(data, first) { - if (this.data) CodeMirror.signal(this.data, "update"); - - var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle); - if (this.widget) this.widget.close(); - - this.data = data; - - if (data && data.list.length) { - if (picked && data.list.length == 1) { - this.pick(data, 0); - } else { - this.widget = new Widget(this, data); - CodeMirror.signal(data, "shown"); - } - } - } - }; - - function parseOptions(cm, pos, options) { - var editor = cm.options.hintOptions; - var out = {}; - for (var prop in defaultOptions) out[prop] = defaultOptions[prop]; - if (editor) for (var prop in editor) - if (editor[prop] !== undefined) out[prop] = editor[prop]; - if (options) for (var prop in options) - if (options[prop] !== undefined) out[prop] = options[prop]; - if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos) - return out; - } - - function getText(completion) { - if (typeof completion == "string") return completion; - else return completion.text; - } - - function buildKeyMap(completion, handle) { - var baseMap = { - Up: function() {handle.moveFocus(-1);}, - Down: function() {handle.moveFocus(1);}, - PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);}, - PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);}, - Home: function() {handle.setFocus(0);}, - End: function() {handle.setFocus(handle.length - 1);}, - Enter: handle.pick, - Tab: handle.pick, - Esc: handle.close - }; - var custom = completion.options.customKeys; - var ourMap = custom ? {} : 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 (custom) - for (var key in custom) if (custom.hasOwnProperty(key)) - addBinding(key, custom[key]); - var extra = completion.options.extraKeys; - if (extra) - for (var key in extra) if (extra.hasOwnProperty(key)) - addBinding(key, extra[key]); - return ourMap; - } - - function getHintElement(hintsElement, el) { - while (el && el != hintsElement) { - if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el; - el = el.parentNode; - } - } - - function Widget(completion, data) { - this.completion = completion; - this.data = data; - this.picked = false; - var widget = this, cm = completion.cm; - - var hints = this.hints = document.createElement("ul"); - hints.className = "CodeMirror-hints"; - this.selectedHint = data.selectedHint || 0; - - var completions = data.list; - for (var i = 0; i < completions.length; ++i) { - var elt = hints.appendChild(document.createElement("li")), cur = completions[i]; - var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS); - if (cur.className != null) className = cur.className + " " + className; - elt.className = className; - if (cur.render) cur.render(elt, data, cur); - else elt.appendChild(document.createTextNode(cur.displayText || getText(cur))); - elt.hintId = i; - } - - var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null); - var left = pos.left, top = pos.bottom, below = true; - hints.style.left = left + "px"; - hints.style.top = top + "px"; - // 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); - (completion.options.container || document.body).appendChild(hints); - var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH; - var scrolls = hints.scrollHeight > hints.clientHeight + 1 - var startScroll = cm.getScrollInfo(); - - if (overlapY > 0) { - var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top); - if (curTop - height > 0) { // Fits above cursor - hints.style.top = (top = pos.top - height) + "px"; - below = false; - } else if (height > winH) { - hints.style.height = (winH - 5) + "px"; - hints.style.top = (top = pos.bottom - box.top) + "px"; - var cursor = cm.getCursor(); - if (data.from.ch != cursor.ch) { - pos = cm.cursorCoords(cursor); - hints.style.left = (left = pos.left) + "px"; - box = hints.getBoundingClientRect(); - } - } - } - var overlapX = box.right - winW; - if (overlapX > 0) { - if (box.right - box.left > winW) { - hints.style.width = (winW - 5) + "px"; - overlapX -= (box.right - box.left) - winW; - } - hints.style.left = (left = pos.left - overlapX) + "px"; - } - if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling) - node.style.paddingRight = cm.display.nativeBarWidth + "px" - - cm.addKeyMap(this.keyMap = buildKeyMap(completion, { - moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); }, - setFocus: function(n) { widget.changeActive(n); }, - menuSize: function() { return widget.screenAmount(); }, - length: completions.length, - close: function() { completion.close(); }, - pick: function() { widget.pick(); }, - data: data - })); - - if (completion.options.closeOnUnfocus) { - var closingOnBlur; - cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); }); - cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); }); - } - - cm.on("scroll", this.onScroll = function() { - var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect(); - 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 completion.close(); - hints.style.top = newTop + "px"; - hints.style.left = (left + startScroll.left - curScroll.left) + "px"; - }); - - CodeMirror.on(hints, "dblclick", function(e) { - var t = getHintElement(hints, e.target || e.srcElement); - if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();} - }); - - CodeMirror.on(hints, "click", function(e) { - var t = getHintElement(hints, e.target || e.srcElement); - if (t && t.hintId != null) { - widget.changeActive(t.hintId); - if (completion.options.completeOnSingleClick) widget.pick(); - } - }); - - CodeMirror.on(hints, "mousedown", function() { - setTimeout(function(){cm.focus();}, 20); - }); - - CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); - return true; - } - - 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) { - cm.off("blur", this.onBlur); - cm.off("focus", this.onFocus); - } - cm.off("scroll", this.onScroll); - }, - - disable: function() { - this.completion.cm.removeKeyMap(this.keyMap); - var widget = this; - this.keyMap = {Enter: function() { widget.picked = true; }}; - this.completion.cm.addKeyMap(this.keyMap); - }, - - pick: function() { - this.completion.pick(this.data, this.selectedHint); - }, - - changeActive: function(i, avoidWrap) { - if (i >= this.data.list.length) - i = avoidWrap ? this.data.list.length - 1 : 0; - else if (i < 0) - i = avoidWrap ? 0 : this.data.list.length - 1; - if (this.selectedHint == i) return; - var node = this.hints.childNodes[this.selectedHint]; - node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); - node = this.hints.childNodes[this.selectedHint = i]; - node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; - 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; - } - }; - - function applicableHelpers(cm, helpers) { - if (!cm.somethingSelected()) return helpers - var result = [] - for (var i = 0; i < helpers.length; i++) - if (helpers[i].supportsSelection) result.push(helpers[i]) - return result - } - - function fetchHints(hint, cm, options, callback) { - if (hint.async) { - hint(cm, callback, options) - } else { - var result = hint(cm, options) - if (result && result.then) result.then(callback) - else callback(result) - } - } - - function resolveAutoHints(cm, pos) { - var helpers = cm.getHelpers(pos, "hint"), words - if (helpers.length) { - var resolved = function(cm, callback, options) { - var app = applicableHelpers(cm, helpers); - function run(i) { - if (i == app.length) return callback(null) - fetchHints(app[i], cm, options, function(result) { - if (result && result.list.length > 0) callback(result) - else run(i + 1) + close: function () { + if (!this.active()) return; + this.cm.state.completionActive = null; + this.tick = null; + this.cm.off("cursorActivity", this.activityFunc); + + if (this.widget && this.data) CodeMirror.signal(this.data, "close"); + if (this.widget) this.widget.close(); + 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), completion.from || data.from, + completion.to || data.to, "complete"); + CodeMirror.signal(data, "pick", completion); + this.close(); + }, + + cursorActivity: function () { + if (this.debounce) { + cancelAnimationFrame(this.debounce); + this.debounce = 0; + } + + var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line); + if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch || + pos.ch < this.startPos.ch || this.cm.somethingSelected() || + (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { + this.close(); + } else { + var self = this; + this.debounce = requestAnimationFrame(function () { + self.update(); + }); + if (this.widget) this.widget.disable(); + } + }, + + update: function (first) { + if (this.tick == null) return + var self = this, myTick = ++this.tick + fetchHints(this.options.hint, this.cm, this.options, function (data) { + if (self.tick == myTick) self.finishUpdate(data, first) }) - } - run(0) + }, + + finishUpdate: function (data, first) { + if (this.data) CodeMirror.signal(this.data, "update"); + + var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle); + if (this.widget) this.widget.close(); + + this.data = data; + + if (data && data.list.length) { + if (picked && data.list.length == 1) { + this.pick(data, 0); + } else { + this.widget = new Widget(this, data); + CodeMirror.signal(data, "shown"); + } + } } - resolved.async = true - resolved.supportsSelection = true - return resolved - } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) { - return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) } - } else if (CodeMirror.hint.anyword) { - return function(cm, options) { return CodeMirror.hint.anyword(cm, options) } - } else { - return function() {} - } - } - - CodeMirror.registerHelper("hint", "auto", { - resolve: resolveAutoHints - }); - - CodeMirror.registerHelper("hint", "fromList", function(cm, options) { - var cur = cm.getCursor(), token = cm.getTokenAt(cur); - var to = CodeMirror.Pos(cur.line, token.end); - if (token.string && /\w/.test(token.string[token.string.length - 1])) { - var term = token.string, from = CodeMirror.Pos(cur.line, token.start); - } else { - var term = "", from = to; - } - var found = []; - for (var i = 0; i < options.words.length; i++) { - var word = options.words[i]; - if (word.slice(0, term.length) == term) - found.push(word); - } - - if (found.length) return {list: found, from: from, to: to}; - }); - - CodeMirror.commands.autocomplete = CodeMirror.showHint; - - var defaultOptions = { - hint: CodeMirror.hint.auto, - completeSingle: true, - alignWithWord: true, - closeCharacters: /[\s()\[\]{};:>,]/, - closeOnUnfocus: true, - completeOnSingleClick: true, - container: null, - customKeys: null, - extraKeys: null }; - + + function parseOptions(cm, pos, options) { + var editor = cm.options.hintOptions; + var out = {}; + for (var prop in defaultOptions) out[prop] = defaultOptions[prop]; + if (editor) for (var prop in editor) + if (editor[prop] !== undefined) out[prop] = editor[prop]; + if (options) for (var prop in options) + if (options[prop] !== undefined) out[prop] = options[prop]; + if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos) + return out; + } + + function getText(completion) { + if (typeof completion == "string") return completion; + else return completion.text; + } + + function buildKeyMap(completion, handle) { + var baseMap = { + Up: function () { + handle.moveFocus(-1); + }, + Down: function () { + handle.moveFocus(1); + }, + PageUp: function () { + handle.moveFocus(-handle.menuSize() + 1, true); + }, + PageDown: function () { + handle.moveFocus(handle.menuSize() - 1, true); + }, + Home: function () { + handle.setFocus(0); + }, + End: function () { + handle.setFocus(handle.length - 1); + }, + Enter: handle.pick, + Tab: handle.pick, + Esc: handle.close + }; + var custom = completion.options.customKeys; + var ourMap = custom ? {} : 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 (custom) + for (var key in custom) if (custom.hasOwnProperty(key)) + addBinding(key, custom[key]); + var extra = completion.options.extraKeys; + if (extra) + for (var key in extra) if (extra.hasOwnProperty(key)) + addBinding(key, extra[key]); + return ourMap; + } + + function getHintElement(hintsElement, el) { + while (el && el != hintsElement) { + if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el; + el = el.parentNode; + } + } + + function Widget(completion, data) { + this.completion = completion; + this.data = data; + this.picked = false; + var widget = this, cm = completion.cm; + + var hints = this.hints = document.createElement("ul"); + hints.className = "CodeMirror-hints"; + this.selectedHint = data.selectedHint || 0; + + var completions = data.list; + for (var i = 0; i < completions.length; ++i) { + var elt = hints.appendChild(document.createElement("li")), cur = completions[i]; + var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS); + if (cur.className != null) className = cur.className + " " + className; + elt.className = className; + if (cur.render) cur.render(elt, data, cur); + else elt.appendChild(document.createTextNode(cur.displayText || getText(cur))); + elt.hintId = i; + } + + var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null); + var left = pos.left, top = pos.bottom, below = true; + hints.style.left = left + "px"; + hints.style.top = top + "px"; + // 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); + (completion.options.container || document.body).appendChild(hints); + var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH; + var scrolls = hints.scrollHeight > hints.clientHeight + 1 + var startScroll = cm.getScrollInfo(); + + if (overlapY > 0) { + var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top); + if (curTop - height > 0) { // Fits above cursor + hints.style.top = (top = pos.top - height) + "px"; + below = false; + } else if (height > winH) { + hints.style.height = (winH - 5) + "px"; + hints.style.top = (top = pos.bottom - box.top) + "px"; + var cursor = cm.getCursor(); + if (data.from.ch != cursor.ch) { + pos = cm.cursorCoords(cursor); + hints.style.left = (left = pos.left) + "px"; + box = hints.getBoundingClientRect(); + } + } + } + var overlapX = box.right - winW; + if (overlapX > 0) { + if (box.right - box.left > winW) { + hints.style.width = (winW - 5) + "px"; + overlapX -= (box.right - box.left) - winW; + } + hints.style.left = (left = pos.left - overlapX) + "px"; + } + if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling) + node.style.paddingRight = cm.display.nativeBarWidth + "px" + + cm.addKeyMap(this.keyMap = buildKeyMap(completion, { + moveFocus: function (n, avoidWrap) { + widget.changeActive(widget.selectedHint + n, avoidWrap); + }, + setFocus: function (n) { + widget.changeActive(n); + }, + menuSize: function () { + return widget.screenAmount(); + }, + length: completions.length, + close: function () { + completion.close(); + }, + pick: function () { + widget.pick(); + }, + data: data + })); + + if (completion.options.closeOnUnfocus) { + var closingOnBlur; + cm.on("blur", this.onBlur = function () { + closingOnBlur = setTimeout(function () { + completion.close(); + }, 100); + }); + cm.on("focus", this.onFocus = function () { + clearTimeout(closingOnBlur); + }); + } + + cm.on("scroll", this.onScroll = function () { + var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect(); + 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 completion.close(); + hints.style.top = newTop + "px"; + hints.style.left = (left + startScroll.left - curScroll.left) + "px"; + }); + + CodeMirror.on(hints, "dblclick", function (e) { + var t = getHintElement(hints, e.target || e.srcElement); + if (t && t.hintId != null) { + widget.changeActive(t.hintId); + widget.pick(); + } + }); + + CodeMirror.on(hints, "click", function (e) { + var t = getHintElement(hints, e.target || e.srcElement); + if (t && t.hintId != null) { + widget.changeActive(t.hintId); + if (completion.options.completeOnSingleClick) widget.pick(); + } + }); + + CodeMirror.on(hints, "mousedown", function () { + setTimeout(function () { + cm.focus(); + }, 20); + }); + + CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); + return true; + } + + 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) { + cm.off("blur", this.onBlur); + cm.off("focus", this.onFocus); + } + cm.off("scroll", this.onScroll); + }, + + disable: function () { + this.completion.cm.removeKeyMap(this.keyMap); + var widget = this; + this.keyMap = { + Enter: function () { + widget.picked = true; + } + }; + this.completion.cm.addKeyMap(this.keyMap); + }, + + pick: function () { + this.completion.pick(this.data, this.selectedHint); + }, + + changeActive: function (i, avoidWrap) { + if (i >= this.data.list.length) + i = avoidWrap ? this.data.list.length - 1 : 0; + else if (i < 0) + i = avoidWrap ? 0 : this.data.list.length - 1; + if (this.selectedHint == i) return; + var node = this.hints.childNodes[this.selectedHint]; + node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); + node = this.hints.childNodes[this.selectedHint = i]; + node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; + 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; + } + }; + + function applicableHelpers(cm, helpers) { + if (!cm.somethingSelected()) return helpers + var result = [] + for (var i = 0; i < helpers.length; i++) + if (helpers[i].supportsSelection) result.push(helpers[i]) + return result + } + + function fetchHints(hint, cm, options, callback) { + if (hint.async) { + hint(cm, callback, options) + } else { + var result = hint(cm, options) + if (result && result.then) result.then(callback) + else callback(result) + } + } + + function resolveAutoHints(cm, pos) { + var helpers = cm.getHelpers(pos, "hint"), words + if (helpers.length) { + var resolved = function (cm, callback, options) { + var app = applicableHelpers(cm, helpers); + + function run(i) { + if (i == app.length) return callback(null) + fetchHints(app[i], cm, options, function (result) { + if (result && result.list.length > 0) callback(result) + else run(i + 1) + }) + } + + run(0) + } + resolved.async = true + resolved.supportsSelection = true + return resolved + } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) { + return function (cm) { + return CodeMirror.hint.fromList(cm, {words: words}) + } + } else if (CodeMirror.hint.anyword) { + return function (cm, options) { + return CodeMirror.hint.anyword(cm, options) + } + } else { + return function () { + } + } + } + + CodeMirror.registerHelper("hint", "auto", { + resolve: resolveAutoHints + }); + + CodeMirror.registerHelper("hint", "fromList", function (cm, options) { + var cur = cm.getCursor(), token = cm.getTokenAt(cur); + var to = CodeMirror.Pos(cur.line, token.end); + if (token.string && /\w/.test(token.string[token.string.length - 1])) { + var term = token.string, from = CodeMirror.Pos(cur.line, token.start); + } else { + var term = "", from = to; + } + var found = []; + for (var i = 0; i < options.words.length; i++) { + var word = options.words[i]; + if (word.slice(0, term.length) == term) + found.push(word); + } + + if (found.length) return {list: found, from: from, to: to}; + }); + + CodeMirror.commands.autocomplete = CodeMirror.showHint; + + var defaultOptions = { + hint: CodeMirror.hint.auto, + completeSingle: true, + alignWithWord: true, + closeCharacters: /[\s()\[\]{};:>,]/, + closeOnUnfocus: true, + completeOnSingleClick: true, + container: null, + customKeys: null, + extraKeys: null + }; + CodeMirror.defineOption("hintOptions", null); - }); \ No newline at end of file +}); \ No newline at end of file diff --git a/_server/blockly/blockly_compressed.js b/_server/blockly/blockly_compressed.js index 75586e3d..6478672d 100644 --- a/_server/blockly/blockly_compressed.js +++ b/_server/blockly/blockly_compressed.js @@ -1,1604 +1,18850 @@ // Do not edit this file; automatically generated by build.py. 'use strict'; -var $jscomp=$jscomp||{};$jscomp.scope={};var COMPILED=!0,goog=goog||{};goog.global=this;goog.isDef=function(a){return void 0!==a};goog.isString=function(a){return"string"==typeof a};goog.isBoolean=function(a){return"boolean"==typeof a};goog.isNumber=function(a){return"number"==typeof a}; -goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]&&c[d]!==Object.prototype[d]?c[d]:c[d]={}}; -goog.define=function(a,b){var c=b;COMPILED||(goog.global.CLOSURE_UNCOMPILED_DEFINES&&void 0===goog.global.CLOSURE_UNCOMPILED_DEFINES.nodeType&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES,a)?c=goog.global.CLOSURE_UNCOMPILED_DEFINES[a]:goog.global.CLOSURE_DEFINES&&void 0===goog.global.CLOSURE_DEFINES.nodeType&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]));goog.exportPath_(a,c)};goog.DEBUG=!1;goog.LOCALE="en"; -goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG;goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1;goog.provide=function(a){if(goog.isInModuleLoader_())throw Error("goog.provide can not be used within a goog.module.");if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');goog.constructNamespace_(a)}; -goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(".")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)};goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/; -goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInModuleLoader_())throw Error("Module "+a+" has been loaded incorrectly. Note, modules cannot be loaded as normal scripts. They require some kind of pre-processing step. You're likely trying to load a module via a script tag or as a part of a concatenated bundle without rewriting the module. For more info see: https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.");if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module."); -goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a]}};goog.module.get=function(a){return goog.module.getInternal_(a)};goog.module.getInternal_=function(a){if(!COMPILED){if(a in goog.loadedModules_)return goog.loadedModules_[a];if(!goog.implicitNamespaces_[a])return a=goog.getObjectByName(a),null!=a?a:null}return null};goog.moduleLoaderState_=null; -goog.isInModuleLoader_=function(){return null!=goog.moduleLoaderState_};goog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInModuleLoader_())throw Error("goog.module.declareLegacyNamespace must be called from within a goog.module");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error("goog.module must be called prior to goog.module.declareLegacyNamespace.");goog.moduleLoaderState_.declareLegacyNamespace=!0}; -goog.setTestOnly=function(a){if(goog.DISALLOW_TEST_ONLY_CODE)throw a=a||"",Error("Importing test-only code into non-debug environment"+(a?": "+a:"."));};goog.forwardDeclare=function(a){};COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={"goog.module":!0}); -goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e=0;e>>0);goog.uidCounter_=0;goog.getHashCode=goog.getUid; -goog.removeHashCode=goog.removeUid;goog.cloneObject=function(a){var b=goog.typeOf(a);if("object"==b||"array"==b){if(a.clone)return a.clone();b="array"==b?[]:{};for(var c in a)b[c]=goog.cloneObject(a[c]);return b}return a};goog.bindNative_=function(a,b,c){return a.call.apply(a.bind,arguments)}; -goog.bindJs_=function(a,b,c){if(!a)throw Error();if(2Number(a[1])?!1:b('(()=>{"use strict";class X{constructor(){if(new.target!=String)throw 1;this.x=42}}let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof String))throw 1;for(const a of[2,3]){if(a==2)continue;function f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()==3}})()')});a("es6-impl",function(){return!0});a("es7",function(){return b("2 ** 2 == 4")});a("es8",function(){return b("async () => 1, true")});return c},goog.Transpiler.prototype.needsTranspile= -function(a){if("always"==goog.TRANSPILE)return!0;if("never"==goog.TRANSPILE)return!1;this.requiresTranspilation_||(this.requiresTranspilation_=this.createRequiresTranspilation_());if(a in this.requiresTranspilation_)return this.requiresTranspilation_[a];throw Error("Unknown language mode: "+a);},goog.Transpiler.prototype.transpile=function(a,b){return goog.transpile_(a,b)},goog.transpiler_=new goog.Transpiler,goog.DebugLoader=function(){this.dependencies_={loadFlags:{},nameToPath:{},requires:{},visited:{}, -written:{},deferred:{}};this.oldIeWaiting_=!1;this.queuedModules_=[];this.lastNonModuleScriptIndex_=0},goog.DebugLoader.IS_OLD_IE_=!(goog.global.atob||!goog.global.document||!goog.global.document.all),goog.DebugLoader.prototype.earlyProcessLoad=function(a){goog.DebugLoader.IS_OLD_IE_&&this.maybeProcessDeferredDep_(a)},goog.DebugLoader.prototype.load=function(a){var b=this.getPathFromDeps_(a);if(b){var c=function(a){if(!(a in f.written||a in f.visited)){f.visited[a]=!0;if(a in f.requires)for(var b in f.requires[a])if(!g.isProvided(b))if(b in -f.nameToPath)c(f.nameToPath[b]);else throw Error("Undefined nameToPath for "+b);a in e||(e[a]=!0,d.push(a))}},d=[],e={},f=this.dependencies_,g=this;c(b);for(a=0;a\x3c/script>')},goog.DebugLoader.prototype.appendScriptSrcNode_=function(a){var b=goog.global.document,c=b.createElement("script");c.type="text/javascript";c.src=a;c.defer=!1;c.async=!1;b.head.appendChild(c)},goog.DebugLoader.prototype.writeScriptTag_=function(a,b){if(this.inHtmlDocument()){var c=goog.global.document;if(!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING&& -"complete"==c.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}if(void 0===b)if(goog.DebugLoader.IS_OLD_IE_){this.oldIeWaiting_=!0;var d=" onreadystatechange='goog.debugLoader_.onScriptLoad_(this, "+ ++this.lastNonModuleScriptIndex_+")' ";c.write(' - - + + + + + + + \ No newline at end of file diff --git a/_server/vm.js b/_server/vm.js index 6168489e..64471533 100644 --- a/_server/vm.js +++ b/_server/vm.js @@ -1,339 +1,375 @@ // vue 相关处理 -document.body.onmousedown = function(e){ - //console.log(e); - var eid=[]; - e.path.forEach(function(node){ - if(!node.getAttribute)return; - var id_ = node.getAttribute('id'); - if (id_){ - if(['left','left1','left2','left3','left4','left5','left8'].indexOf(id_)!==-1)eid.push('edit'); - eid.push(id_); - } - }); - //console.log(eid); - if(eid.indexOf('edit')===-1){ - if(eid.indexOf('tip')===-1) { - if (selectBox.isSelected) { - editor_mode.onmode(''); - editor.file.saveFloorFile(function(err){if(err){printe(err);throw(err)};printf('地图保存成功');}); - } - selectBox.isSelected = false; - } - } - //editor.mode.onmode(''); - editor.info = {}; -} -iconLib.onmousedown = function(e){ - e.stopPropagation(); -} -var exportM = new Vue({ - el: '#exportM', - data: { - isExport: false, - }, - methods: { - exportMap: function(){ - editor.updateMap(); - - var filestr=''; - for (var yy = 0; yy < 13; yy++){ - filestr+='[' - for (var xx = 0; xx < 13; xx++) { - var mapxy=editor.map[yy][xx]; - if(typeof(mapxy)==typeof({})){ - if ('idnum' in mapxy)mapxy=mapxy.idnum; - else { - // mapxy='!!?'; - tip.whichShow = 3; - return; - } - }else if(typeof(mapxy)=='undefined'){ - tip.whichShow = 3; - return; - } - mapxy=String(mapxy); - mapxy=Array(Math.max(4-mapxy.length,0)).join(' ')+mapxy; - filestr+=mapxy+(xx==12?'':',') +document.body.onmousedown = function (e) { + //console.log(e); + var eid = []; + e.path.forEach(function (node) { + if (!node.getAttribute) return; + var id_ = node.getAttribute('id'); + if (id_) { + if (['left', 'left1', 'left2', 'left3', 'left4', 'left5', 'left8'].indexOf(id_) !== -1) eid.push('edit'); + eid.push(id_); + } + }); + //console.log(eid); + if (eid.indexOf('edit') === -1) { + if (eid.indexOf('tip') === -1) { + if (selectBox.isSelected) { + editor_mode.onmode(''); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('地图保存成功'); + }); + } + selectBox.isSelected = false; + } + } + //editor.mode.onmode(''); + editor.info = {}; +} +iconLib.onmousedown = function (e) { + e.stopPropagation(); +} +var exportMap = new Vue({ + el: '#exportMap', + data: { + isExport: false, + }, + methods: { + exportMap: function () { + editor.updateMap(); + + var filestr = ''; + for (var yy = 0; yy < 13; yy++) { + filestr += '[' + for (var xx = 0; xx < 13; xx++) { + var mapxy = editor.map[yy][xx]; + if (typeof(mapxy) == typeof({})) { + if ('idnum' in mapxy) mapxy = mapxy.idnum; + else { + // mapxy='!!?'; + tip.whichShow = 3; + return; + } + } else if (typeof(mapxy) == 'undefined') { + tip.whichShow = 3; + return; + } + mapxy = String(mapxy); + mapxy = Array(Math.max(4 - mapxy.length, 0)).join(' ') + mapxy; + filestr += mapxy + (xx == 12 ? '' : ',') + } + + filestr += ']' + (yy == 12 ? '' : ',\n'); + } + pout.value = filestr; + editArea.mapArr = filestr; + this.isExport = true; + editArea.error = 0; + tip.whichShow = 2; } - - filestr += ']'+(yy==12?'':',\n'); - } - pout.value = filestr; - editArea.mapArr = filestr; - this.isExport = true; - editArea.error = 0; - tip.whichShow = 2; } - } }) var editArea = new Vue({ - el: '#editArea', - data: { - mapArr: '', - errors: [ // 编号1,2,3,4 - "格式错误!请使用正确格式(13*13数组,如不清楚,可先点击生成地图查看正确格式)", - "当前有未定义ID(在地图区域显示红块),请修改ID或者到icons.js和maps.js中进行定义!", - "ID越界(在地图区域显示红块),当前编辑器暂时支持编号小于400,请修改编号!", - // "发生错误!", - ], - error: 0, - formatTimer: null, - }, - watch: { - mapArr: function (val, oldval) { - var that = this; - if(val=='') return; - if(exportM.isExport){ - exportM.isExport = false; - return; - } - if(that.formatArr()){ - that.error = 0; - - setTimeout(function(){ - that.mapArr = that.formatArr(); - that.drawMap(); - tip.whichShow = 8 - }, 1000); - that.formatTimer = setTimeout(function(){ - pout.value = that.formatArr(); - }, 5000); //5s后再格式化,不然光标跳到最后很烦 - }else{ - that.error = 1; - } + el: '#editArea', + data: { + mapArr: '', + errors: [ // 编号1,2,3,4 + "格式错误!请使用正确格式(13*13数组,如不清楚,可先点击生成地图查看正确格式)", + "当前有未定义ID(在地图区域显示红块),请修改ID或者到icons.js和maps.js中进行定义!", + "ID越界(在地图区域显示红块),当前编辑器暂时支持编号小于400,请修改编号!", + // "发生错误!", + ], + error: 0, + formatTimer: null, }, - error: function(){ - // console.log(editArea.mapArr); - } - }, - methods: { - drawMap: function(){ - var that = this; + watch: { + mapArr: function (val, oldval) { + var that = this; + if (val == '') return; + if (exportMap.isExport) { + exportMap.isExport = false; + return; + } + if (that.formatArr()) { + that.error = 0; - // var mapArray = that.mapArr.split(/\D+/).join(' ').trim().split(' '); - var mapArray = JSON.parse('['+that.mapArr+']'); - for(var y=0; y<13; y++) - for(var x=0; x<13; x++){ - var num = mapArray[y][x]; - if(num == 0 ) - editor.map[y][x] = 0; - else if(num >= 1000){ - that.error = 3; - editor.map[y][x] = undefined; - }else if(typeof(editor.indexs[num][0]) == 'undefined'){ - that.error = 2; - editor.map[y][x] = undefined; - }else editor.map[y][x] = editor.ids[[editor.indexs[num][0]]]; + setTimeout(function () { + that.mapArr = that.formatArr(); + that.drawMap(); + tip.whichShow = 8 + }, 1000); + that.formatTimer = setTimeout(function () { + pout.value = that.formatArr(); + }, 5000); //5s后再格式化,不然光标跳到最后很烦 + } else { + that.error = 1; + } + }, + error: function () { + // console.log(editArea.mapArr); } - - editor.updateMap(); - }, - formatArr: function(){ - var formatArrStr = ''; - var that = this; - clearTimeout(that.formatTimer); - if(this.mapArr.split(/\D+/).join(' ').trim().split(' ').length != 169) return false; - var arr = this.mapArr.replace(/\s+/g, '').split('],['); - - if(arr.length != 13) return ; - for(var i =0; i<13; i++){ - var a = []; - formatArrStr +='['; - if(i==0||i==12) a = arr[i].split(/\D+/).join(' ').trim().split(' '); - else a = arr[i].split(/\D+/); - if(a.length != 13){ - formatArrStr = ''; - return ; - } + methods: { + drawMap: function () { + var that = this; - for(var k=0; k<13; k++){ - var num = parseInt(a[k]); - formatArrStr += Array(Math.max(4-String(num).length,0)).join(' ')+num+(k==12?'':','); + // var mapArray = that.mapArr.split(/\D+/).join(' ').trim().split(' '); + var mapArray = JSON.parse('[' + that.mapArr + ']'); + for (var y = 0; y < 13; y++) + for (var x = 0; x < 13; x++) { + var num = mapArray[y][x]; + if (num == 0) + editor.map[y][x] = 0; + else if (num >= 1000) { + that.error = 3; + editor.map[y][x] = undefined; + } else if (typeof(editor.indexs[num][0]) == 'undefined') { + that.error = 2; + editor.map[y][x] = undefined; + } else editor.map[y][x] = editor.ids[[editor.indexs[num][0]]]; + } + + editor.updateMap(); + + }, + formatArr: function () { + var formatArrStr = ''; + var that = this; + clearTimeout(that.formatTimer); + if (this.mapArr.split(/\D+/).join(' ').trim().split(' ').length != 169) return false; + var arr = this.mapArr.replace(/\s+/g, '').split('],['); + + if (arr.length != 13) return; + for (var i = 0; i < 13; i++) { + var a = []; + formatArrStr += '['; + if (i == 0 || i == 12) a = arr[i].split(/\D+/).join(' ').trim().split(' '); + else a = arr[i].split(/\D+/); + if (a.length != 13) { + formatArrStr = ''; + return; + } + + for (var k = 0; k < 13; k++) { + var num = parseInt(a[k]); + formatArrStr += Array(Math.max(4 - String(num).length, 0)).join(' ') + num + (k == 12 ? '' : ','); + } + formatArrStr += ']' + (i == 12 ? '' : ',\n'); + } + return formatArrStr; } - formatArrStr += ']'+(i==12?'':',\n'); - } - return formatArrStr; } - } }); -var editTip = new Vue({ - el: '#editTip', - data: { - err: '' - }, - methods: { - copyMap: function(){ +var copyMap = new Vue({ + el: '#copyMap', + data: { + err: '' + }, + methods: { + copyMap: function () { - tip.whichShow = 0; - if(pout.value.trim() != ''){ - if(editArea.error) { - this.err = editArea.errors[editArea.error-1]; - tip.whichShow = 5 - return; + tip.whichShow = 0; + if (pout.value.trim() != '') { + if (editArea.error) { + this.err = editArea.errors[editArea.error - 1]; + tip.whichShow = 5 + return; + } + try { + pout.select(); + document.execCommand("Copy"); + tip.whichShow = 6; + } catch (e) { + this.err = e; + tip.whichShow = 5; + } + } else { + tip.whichShow = 7; + } } - try{ - pout.select(); - document.execCommand("Copy"); - tip.whichShow = 6; - }catch(e){ - this.err= e; - tip.whichShow = 5; - } - }else{ - tip.whichShow = 7; - } - } - }, + }, }) -var clear = new Vue({ - el: '#clear', +var clearMap = new Vue({ + el: '#clearMap', - methods: { - clearMap: function(){ - editor.mapInit(); - editor.updateMap(); - clearTimeout(editArea.formatTimer); - clearTimeout(tip.timer); - pout.value = ''; - editArea.mapArr = ''; - tip.whichShow = 4; - editArea.error = 0; + methods: { + clearMap: function () { + editor.mapInit(); + editor_mode.onmode(''); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('地图清除成功'); + }); + editor.updateMap(); + clearTimeout(editArea.formatTimer); + clearTimeout(tip.timer); + pout.value = ''; + editArea.mapArr = ''; + tip.whichShow = 4; + editArea.error = 0; + } } - } }) -printf = function(str_,type) { - selectBox.isSelected = false; - if(!type){ - tip.whichShow=11; - } else { - tip.whichShow=12; - } - setTimeout(function(){ - if(!type){ - tip.msgs[11]=String(str_); - tip.whichShow=12; +var deleteMap = new Vue({ + el: '#deleteMap', + methods: { + deleteMap: function () { + editor_mode.onmode(''); + var index = core.floorIds.indexOf(editor.currentFloorId); + if (index>=0) { + core.floorIds.splice(index,1); + editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {/*console.log(objs_);*/ + if (objs_.slice(-1)[0] != null) { + printe(objs_.slice(-1)[0]); + throw(objs_.slice(-1)[0]) + } + ;printe('删除成功,请F5刷新编辑器生效'); + }); + } + else printe('删除成功,请F5刷新编辑器生效'); + } + } +}) +printf = function (str_, type) { + selectBox.isSelected = false; + if (!type) { + tip.whichShow = 11; } else { - tip.msgs[10]=String(str_); - tip.whichShow=11; + tip.whichShow = 12; } - },1); + setTimeout(function () { + if (!type) { + tip.msgs[11] = String(str_); + tip.whichShow = 12; + } else { + tip.msgs[10] = String(str_); + tip.whichShow = 11; + } + }, 1); +} +printe = function (str_) { + printf(str_, 'error') } -printe = function(str_){printf(str_,'error')} tip_in_showMode = [ - '涉及图片的更改需要F5刷新浏览器来生效', - '文本域可以通过双击,在文本编辑器或事件编辑器中编辑', - '事件编辑器中的显示文本和自定义脚本的方块也可以双击', - "画出的地图要点击\"保存地图\"才会写入到文件中", + '涉及图片的更改需要F5刷新浏览器来生效', + '文本域可以通过双击,在文本编辑器或事件编辑器中编辑', + '事件编辑器中的显示文本和自定义脚本的方块也可以双击', + "画出的地图要点击\"保存地图\"才会写入到文件中", ]; var tip = new Vue({ - el: '#tip', - data: { - infos: {}, - hasId: true, - isAutotile: false, - isSelectedBlock: false, - isClearBlock: false, - geneMapSuccess: false, - timer: null, - msgs: [ //分别编号1,2,3,4,5,6,7,8,9,10;奇数警告,偶数成功 - "当前未选择任何图块,请先在右边选择要画的图块!", - "生成地图成功!可点击复制按钮复制地图数组到剪切板", - "生成失败! 地图中有未定义的图块,建议先用其他有效图块覆盖或点击清除地图!", - "地图清除成功!", - "复制失败!", - "复制成功!可直接粘贴到楼层文件的地图数组中。", - "复制失败!当前还没有数据", - "修改成功!可点击复制按钮复制地图数组到剪切板", - "选择背景图片失败!文件名格式错误或图片不存在!", - "更新背景图片成功!", - "11:警告", - "12:成功" - ], - mapMsg: '', - whichShow: 0, - }, - watch: { - infos: { - handler: function(val, oldval){ - this.isClearBlock = false; - if(typeof(val) != 'undefined'){ - if(val==0) { - this.isClearBlock = true; - return; - } - if('id' in val){ - this.hasId = true; - }else{ - this.hasId = false; - } - this.isAutotile = false; - if(val.images == "autotile" && this.hasId) this.isAutotile = true; - } - }, - deep: true + el: '#tip', + data: { + infos: {}, + hasId: true, + isAutotile: false, + isSelectedBlock: false, + isClearBlock: false, + geneMapSuccess: false, + timer: null, + msgs: [ //分别编号1,2,3,4,5,6,7,8,9,10;奇数警告,偶数成功 + "当前未选择任何图块,请先在右边选择要画的图块!", + "生成地图成功!可点击复制按钮复制地图数组到剪切板", + "生成失败! 地图中有未定义的图块,建议先用其他有效图块覆盖或点击清除地图!", + "地图清除成功!", + "复制失败!", + "复制成功!可直接粘贴到楼层文件的地图数组中。", + "复制失败!当前还没有数据", + "修改成功!可点击复制按钮复制地图数组到剪切板", + "选择背景图片失败!文件名格式错误或图片不存在!", + "更新背景图片成功!", + "11:警告", + "12:成功" + ], + mapMsg: '', + whichShow: 0, }, + watch: { + infos: { + handler: function (val, oldval) { + this.isClearBlock = false; + if (typeof(val) != 'undefined') { + if (val == 0) { + this.isClearBlock = true; + return; + } + if ('id' in val) { + this.hasId = true; + } else { + this.hasId = false; + } + this.isAutotile = false; + if (val.images == "autotile" && this.hasId) this.isAutotile = true; + } + }, + deep: true + }, - whichShow: function(){ - var that = this; - that.mapMsg = ''; - that.msgs[4] = "复制失败!"+editTip.err; - clearTimeout(that.timer); - if(that.whichShow){ - that.mapMsg = that.msgs[that.whichShow-1]; - that.timer = setTimeout(function() { - if(!(that.whichShow%2)) - that.whichShow = 0; - }, 5000); //5秒后自动清除success,warn不清除 - } + whichShow: function () { + var that = this; + that.mapMsg = ''; + that.msgs[4] = "复制失败!" + editTip.err; + clearTimeout(that.timer); + if (that.whichShow) { + that.mapMsg = that.msgs[that.whichShow - 1]; + that.timer = setTimeout(function () { + if (!(that.whichShow % 2)) + that.whichShow = 0; + }, 5000); //5秒后自动清除success,warn不清除 + } + } } - } }) var selectBox = new Vue({ - el: '#selectBox', - data: { - isSelected: false - }, - watch: { - isSelected: function(){ - tip.isSelectedBlock = this.isSelected; - tip.whichShow = 0; - clearTimeout(tip.timer); + el: '#selectBox', + data: { + isSelected: false + }, + watch: { + isSelected: function () { + tip.isSelectedBlock = this.isSelected; + tip.whichShow = 0; + clearTimeout(tip.timer); + } } - } }) var bgSelect = new Vue({ - el: '#bgSelect', - data: { - bgs: {}, - selectedBg: 'ground', - imgname: '' - }, - watch:{ - selectedBg: function(){ - editor.bgY = this.bgs.indexOf(this.selectedBg); - editor.drawMapBg(); + el: '#bgSelect', + data: { + bgs: {}, + selectedBg: 'ground', + imgname: '' + }, + watch: { + selectedBg: function () { + editor.bgY = this.bgs.indexOf(this.selectedBg); + editor.drawMapBg(); + } + }, + methods: { + updatebg: function () { + tip.whichShow = 0; + var regx = /\S+\.(png|bmp|jpg|jpeg|gif)$/i; + if (regx.test(this.imgname)) { + var url = 'images/' + this.imgname; + editor.loadImg(url).then(function (img) { + editor.drawMapBg(img); + tip.whichShow = 10; + }).catch(function (err) { + console.log(err); + tip.whichShow = 9; + }); + } else { + tip.whichShow = 9; + } + } } - }, - methods: { - updatebg: function(){ - tip.whichShow = 0; - var regx = /\S+\.(png|bmp|jpg|jpeg|gif)$/i; - if(regx.test(this.imgname)){ - var url = 'images/'+this.imgname; - editor.loadImg(url).then(function(img){ - editor.drawMapBg(img); - tip.whichShow = 10; - }).catch(function(err){ - console.log(err); - tip.whichShow = 9; - }); - }else{ - tip.whichShow = 9; - } - } - } }) \ No newline at end of file diff --git a/editor.html b/editor.html index 327ae7a0..47d845cb 100644 --- a/editor.html +++ b/editor.html @@ -1,229 +1,267 @@ - + - + -
+
-
-
-
-
- -

{{ errors[error-1] }}

+
+
+
+
+ +

{{ errors[error-1] }}

+
+
+ + +
+
+ + + + +
-
-
- - - -
-
- - -
-
-
+
-
-
+
+
+ +
-
-
-

追加素材

-
-

- - - -

-
- - - - -
-
1
-
2
-
3
-
4
+

追加素材

+
+

+ + + + +

+
+ + + + +
+
1
+
2
+
3
+
4
+
+
-
-
+
-

地图选点  

-
-

0,0

-
- - - - -
条目注释
-
-
-
-

图块属性  

-
-
- - - -
-
-
- - - - -
条目注释
+

地图选点   +

+
+

0,0

+
+ + + + + + + + +
条目注释
+
-
-
+
+
+

图块属性   +

+
+
+ + + +
+
+
+ + + + + + + + +
条目注释
+
+
+
+
-

楼层属性  

-
-
- - - - -
条目注释
-
-
+

楼层属性   +

+
+
+ + + + + + + + +
条目注释
+
+
+
-

全塔属性  

-
-
- - - - -
条目注释
-
-
-
-

事件编辑器    - - - - - - - -

-
-
- -
-
+

全塔属性   +

+
+
+ + + + + + + + +
条目注释
+
+
+
+
+
+

事件编辑器    + + + + + + + +

+
+
+
+
+ +
+
+
- - - - Lint - + + + + Lint +
-

脚本编辑  

-
-
- - - - -
条目注释
-
-
-
-
-
-
- - - - -
-
-
-
-

当前选择为清除块,可擦除地图上块

-
-

图块编号:{{ infos['idnum'] }}

-

图块ID:{{ infos['id'] }}

-

该图块无对应的数字或ID存在,请先前往icons.js和maps.js中进行定义!

-

图块所在素材:{{ infos['images'] + (isAutotile ? '( '+infos['id']+' )' : '') }}

-

图块索引:{{ infos['y'] }}

+

脚本编辑   +

+
+
+ + + + + + + + +
条目注释
-
-
-

{{ mapMsg }}

-
- +
+
+
+
+
+ + + + +
+
+
+
+

当前选择为清除块,可擦除地图上块

+
+

图块编号:{{ infos['idnum'] }}

+

图块ID:{{ infos['id'] }}

+

该图块无对应的数字或ID存在,请先前往icons.js和maps.js中进行定义!

+

图块所在素材:{{ infos['images'] + (isAutotile ? '( '+infos['id']+' )' : '') }} +

+

图块索引:{{ infos['y'] }}

+
+
+
+

{{ mapMsg }}

+
+
- -



- - - - - -
- - + +