admin(major): add YAMLField for attributes, add codemirror editor
This commit is contained in:
		
							
								
								
									
										304
									
								
								passbook/admin/static/codemirror/addon/hint/sql-hint.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										304
									
								
								passbook/admin/static/codemirror/addon/hint/sql-hint.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,304 @@ | ||||
| // CodeMirror, copyright (c) by Marijn Haverbeke and others | ||||
| // Distributed under an MIT license: https://codemirror.net/LICENSE | ||||
|  | ||||
| (function(mod) { | ||||
|   if (typeof exports == "object" && typeof module == "object") // CommonJS | ||||
|     mod(require("../../lib/codemirror"), require("../../mode/sql/sql")); | ||||
|   else if (typeof define == "function" && define.amd) // AMD | ||||
|     define(["../../lib/codemirror", "../../mode/sql/sql"], mod); | ||||
|   else // Plain browser env | ||||
|     mod(CodeMirror); | ||||
| })(function(CodeMirror) { | ||||
|   "use strict"; | ||||
|  | ||||
|   var tables; | ||||
|   var defaultTable; | ||||
|   var keywords; | ||||
|   var identifierQuote; | ||||
|   var CONS = { | ||||
|     QUERY_DIV: ";", | ||||
|     ALIAS_KEYWORD: "AS" | ||||
|   }; | ||||
|   var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos; | ||||
|  | ||||
|   function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" } | ||||
|  | ||||
|   function getKeywords(editor) { | ||||
|     var mode = editor.doc.modeOption; | ||||
|     if (mode === "sql") mode = "text/x-sql"; | ||||
|     return CodeMirror.resolveMode(mode).keywords; | ||||
|   } | ||||
|  | ||||
|   function getIdentifierQuote(editor) { | ||||
|     var mode = editor.doc.modeOption; | ||||
|     if (mode === "sql") mode = "text/x-sql"; | ||||
|     return CodeMirror.resolveMode(mode).identifierQuote || "`"; | ||||
|   } | ||||
|  | ||||
|   function getText(item) { | ||||
|     return typeof item == "string" ? item : item.text; | ||||
|   } | ||||
|  | ||||
|   function wrapTable(name, value) { | ||||
|     if (isArray(value)) value = {columns: value} | ||||
|     if (!value.text) value.text = name | ||||
|     return value | ||||
|   } | ||||
|  | ||||
|   function parseTables(input) { | ||||
|     var result = {} | ||||
|     if (isArray(input)) { | ||||
|       for (var i = input.length - 1; i >= 0; i--) { | ||||
|         var item = input[i] | ||||
|         result[getText(item).toUpperCase()] = wrapTable(getText(item), item) | ||||
|       } | ||||
|     } else if (input) { | ||||
|       for (var name in input) | ||||
|         result[name.toUpperCase()] = wrapTable(name, input[name]) | ||||
|     } | ||||
|     return result | ||||
|   } | ||||
|  | ||||
|   function getTable(name) { | ||||
|     return tables[name.toUpperCase()] | ||||
|   } | ||||
|  | ||||
|   function shallowClone(object) { | ||||
|     var result = {}; | ||||
|     for (var key in object) if (object.hasOwnProperty(key)) | ||||
|       result[key] = object[key]; | ||||
|     return result; | ||||
|   } | ||||
|  | ||||
|   function match(string, word) { | ||||
|     var len = string.length; | ||||
|     var sub = getText(word).substr(0, len); | ||||
|     return string.toUpperCase() === sub.toUpperCase(); | ||||
|   } | ||||
|  | ||||
|   function addMatches(result, search, wordlist, formatter) { | ||||
|     if (isArray(wordlist)) { | ||||
|       for (var i = 0; i < wordlist.length; i++) | ||||
|         if (match(search, wordlist[i])) result.push(formatter(wordlist[i])) | ||||
|     } else { | ||||
|       for (var word in wordlist) if (wordlist.hasOwnProperty(word)) { | ||||
|         var val = wordlist[word] | ||||
|         if (!val || val === true) | ||||
|           val = word | ||||
|         else | ||||
|           val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text | ||||
|         if (match(search, val)) result.push(formatter(val)) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function cleanName(name) { | ||||
|     // Get rid name from identifierQuote and preceding dot(.) | ||||
|     if (name.charAt(0) == ".") { | ||||
|       name = name.substr(1); | ||||
|     } | ||||
|     // replace doublicated identifierQuotes with single identifierQuotes | ||||
|     // and remove single identifierQuotes | ||||
|     var nameParts = name.split(identifierQuote+identifierQuote); | ||||
|     for (var i = 0; i < nameParts.length; i++) | ||||
|       nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), ""); | ||||
|     return nameParts.join(identifierQuote); | ||||
|   } | ||||
|  | ||||
|   function insertIdentifierQuotes(name) { | ||||
|     var nameParts = getText(name).split("."); | ||||
|     for (var i = 0; i < nameParts.length; i++) | ||||
|       nameParts[i] = identifierQuote + | ||||
|         // doublicate identifierQuotes | ||||
|         nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) + | ||||
|         identifierQuote; | ||||
|     var escaped = nameParts.join("."); | ||||
|     if (typeof name == "string") return escaped; | ||||
|     name = shallowClone(name); | ||||
|     name.text = escaped; | ||||
|     return name; | ||||
|   } | ||||
|  | ||||
|   function nameCompletion(cur, token, result, editor) { | ||||
|     // Try to complete table, column names and return start position of completion | ||||
|     var useIdentifierQuotes = false; | ||||
|     var nameParts = []; | ||||
|     var start = token.start; | ||||
|     var cont = true; | ||||
|     while (cont) { | ||||
|       cont = (token.string.charAt(0) == "."); | ||||
|       useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote); | ||||
|  | ||||
|       start = token.start; | ||||
|       nameParts.unshift(cleanName(token.string)); | ||||
|  | ||||
|       token = editor.getTokenAt(Pos(cur.line, token.start)); | ||||
|       if (token.string == ".") { | ||||
|         cont = true; | ||||
|         token = editor.getTokenAt(Pos(cur.line, token.start)); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     // Try to complete table names | ||||
|     var string = nameParts.join("."); | ||||
|     addMatches(result, string, tables, function(w) { | ||||
|       return useIdentifierQuotes ? insertIdentifierQuotes(w) : w; | ||||
|     }); | ||||
|  | ||||
|     // Try to complete columns from defaultTable | ||||
|     addMatches(result, string, defaultTable, function(w) { | ||||
|       return useIdentifierQuotes ? insertIdentifierQuotes(w) : w; | ||||
|     }); | ||||
|  | ||||
|     // Try to complete columns | ||||
|     string = nameParts.pop(); | ||||
|     var table = nameParts.join("."); | ||||
|  | ||||
|     var alias = false; | ||||
|     var aliasTable = table; | ||||
|     // Check if table is available. If not, find table by Alias | ||||
|     if (!getTable(table)) { | ||||
|       var oldTable = table; | ||||
|       table = findTableByAlias(table, editor); | ||||
|       if (table !== oldTable) alias = true; | ||||
|     } | ||||
|  | ||||
|     var columns = getTable(table); | ||||
|     if (columns && columns.columns) | ||||
|       columns = columns.columns; | ||||
|  | ||||
|     if (columns) { | ||||
|       addMatches(result, string, columns, function(w) { | ||||
|         var tableInsert = table; | ||||
|         if (alias == true) tableInsert = aliasTable; | ||||
|         if (typeof w == "string") { | ||||
|           w = tableInsert + "." + w; | ||||
|         } else { | ||||
|           w = shallowClone(w); | ||||
|           w.text = tableInsert + "." + w.text; | ||||
|         } | ||||
|         return useIdentifierQuotes ? insertIdentifierQuotes(w) : w; | ||||
|       }); | ||||
|     } | ||||
|  | ||||
|     return start; | ||||
|   } | ||||
|  | ||||
|   function eachWord(lineText, f) { | ||||
|     var words = lineText.split(/\s+/) | ||||
|     for (var i = 0; i < words.length; i++) | ||||
|       if (words[i]) f(words[i].replace(/[,;]/g, '')) | ||||
|   } | ||||
|  | ||||
|   function findTableByAlias(alias, editor) { | ||||
|     var doc = editor.doc; | ||||
|     var fullQuery = doc.getValue(); | ||||
|     var aliasUpperCase = alias.toUpperCase(); | ||||
|     var previousWord = ""; | ||||
|     var table = ""; | ||||
|     var separator = []; | ||||
|     var validRange = { | ||||
|       start: Pos(0, 0), | ||||
|       end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length) | ||||
|     }; | ||||
|  | ||||
|     //add separator | ||||
|     var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV); | ||||
|     while(indexOfSeparator != -1) { | ||||
|       separator.push(doc.posFromIndex(indexOfSeparator)); | ||||
|       indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1); | ||||
|     } | ||||
|     separator.unshift(Pos(0, 0)); | ||||
|     separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length)); | ||||
|  | ||||
|     //find valid range | ||||
|     var prevItem = null; | ||||
|     var current = editor.getCursor() | ||||
|     for (var i = 0; i < separator.length; i++) { | ||||
|       if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) { | ||||
|         validRange = {start: prevItem, end: separator[i]}; | ||||
|         break; | ||||
|       } | ||||
|       prevItem = separator[i]; | ||||
|     } | ||||
|  | ||||
|     if (validRange.start) { | ||||
|       var query = doc.getRange(validRange.start, validRange.end, false); | ||||
|  | ||||
|       for (var i = 0; i < query.length; i++) { | ||||
|         var lineText = query[i]; | ||||
|         eachWord(lineText, function(word) { | ||||
|           var wordUpperCase = word.toUpperCase(); | ||||
|           if (wordUpperCase === aliasUpperCase && getTable(previousWord)) | ||||
|             table = previousWord; | ||||
|           if (wordUpperCase !== CONS.ALIAS_KEYWORD) | ||||
|             previousWord = word; | ||||
|         }); | ||||
|         if (table) break; | ||||
|       } | ||||
|     } | ||||
|     return table; | ||||
|   } | ||||
|  | ||||
|   CodeMirror.registerHelper("hint", "sql", function(editor, options) { | ||||
|     tables = parseTables(options && options.tables) | ||||
|     var defaultTableName = options && options.defaultTable; | ||||
|     var disableKeywords = options && options.disableKeywords; | ||||
|     defaultTable = defaultTableName && getTable(defaultTableName); | ||||
|     keywords = getKeywords(editor); | ||||
|     identifierQuote = getIdentifierQuote(editor); | ||||
|  | ||||
|     if (defaultTableName && !defaultTable) | ||||
|       defaultTable = findTableByAlias(defaultTableName, editor); | ||||
|  | ||||
|     defaultTable = defaultTable || []; | ||||
|  | ||||
|     if (defaultTable.columns) | ||||
|       defaultTable = defaultTable.columns; | ||||
|  | ||||
|     var cur = editor.getCursor(); | ||||
|     var result = []; | ||||
|     var token = editor.getTokenAt(cur), start, end, search; | ||||
|     if (token.end > cur.ch) { | ||||
|       token.end = cur.ch; | ||||
|       token.string = token.string.slice(0, cur.ch - token.start); | ||||
|     } | ||||
|  | ||||
|     if (token.string.match(/^[.`"\w@]\w*$/)) { | ||||
|       search = token.string; | ||||
|       start = token.start; | ||||
|       end = token.end; | ||||
|     } else { | ||||
|       start = end = cur.ch; | ||||
|       search = ""; | ||||
|     } | ||||
|     if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) { | ||||
|       start = nameCompletion(cur, token, result, editor); | ||||
|     } else { | ||||
|       var objectOrClass = function(w, className) { | ||||
|         if (typeof w === "object") { | ||||
|           w.className = className; | ||||
|         } else { | ||||
|           w = { text: w, className: className }; | ||||
|         } | ||||
|         return w; | ||||
|       }; | ||||
|     addMatches(result, search, defaultTable, function(w) { | ||||
|         return objectOrClass(w, "CodeMirror-hint-table CodeMirror-hint-default-table"); | ||||
|     }); | ||||
|     addMatches( | ||||
|         result, | ||||
|         search, | ||||
|         tables, function(w) { | ||||
|           return objectOrClass(w, "CodeMirror-hint-table"); | ||||
|         } | ||||
|     ); | ||||
|     if (!disableKeywords) | ||||
|       addMatches(result, search, keywords, function(w) { | ||||
|           return objectOrClass(w.toUpperCase(), "CodeMirror-hint-keyword"); | ||||
|       }); | ||||
|   } | ||||
|  | ||||
|     return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)}; | ||||
|   }); | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user
	 Langhammer, Jens
					Langhammer, Jens