diff --git a/javascript/build/copy.js b/javascript/build/copy.js index bac3d4925a3bb1fabe9c5a595fd3d3a295776b8c..c8d411c2ecd7cb3b45b92f3d2a62653b2648a546 100644 --- a/javascript/build/copy.js +++ b/javascript/build/copy.js @@ -91,7 +91,7 @@ const todos = [ custom: [ { from: "javascript/src/Helper/codemirror/qfq.js", - to: target.js + "codemirror/" + to: target.js + "codemirror/qfq.js" } ] },{ diff --git a/javascript/build/terser.js b/javascript/build/terser.js index 0ac9f153109b76ab857e4c7c09fb83fefa18fad9..8106f05927396774ac7686a6982c272beb1240aa 100644 --- a/javascript/build/terser.js +++ b/javascript/build/terser.js @@ -18,14 +18,6 @@ const todos = [ name: "qfqValidator", input: "javascript/src/Plugins/validator.js", output: jsPath + "validator.min.js" - },{ - name: "codemirror qfq", - input: "javascript/build/dist/codemirror/codemirror-qfq.js", - output: jsPath + "codemirror/codemirror-qfq.min.js", - },{ - name: "codemirror BE qfq mode", - input: "javascript/src/Helper/codemirror/qfq.js", - output: jsPath + "codemirror/qfq.min.js", } ] diff --git a/javascript/src/Helper/codemirror/addon-matchbrackets.js b/javascript/src/Helper/codemirror/addon-matchbrackets.js deleted file mode 100644 index 971c41f22d83223f586d22611f8d21a96840cec3..0000000000000000000000000000000000000000 --- a/javascript/src/Helper/codemirror/addon-matchbrackets.js +++ /dev/null @@ -1,162 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: https://codemirror.net/5/LICENSE -// This file was duplicated and only edited to include matching for <> -// (couldn't figure out how to pass as config, if even possible) - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && - (document.documentMode == null || document.documentMode < 8); - - var Pos = CodeMirror.Pos; - - var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<"}; - - function bracketRegex(config) { - return config && config.bracketRegex || /[(){}<>[\]]/ - } - - function findMatchingBracket(cm, where, config) { - var line = cm.getLineHandle(where.line), pos = where.ch - 1; - var afterCursor = config && config.afterCursor - if (afterCursor == null) - afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className) - var re = bracketRegex(config) - - // A cursor is defined as between two characters, but in in vim command mode - // (i.e. not insert mode), the cursor is visually represented as a - // highlighted box on top of the 2nd character. Otherwise, we allow matches - // from before or after the cursor. - var match = (!afterCursor && pos >= 0 && re.test(line.text.charAt(pos)) && matching[line.text.charAt(pos)]) || - re.test(line.text.charAt(pos + 1)) && matching[line.text.charAt(++pos)]; - if (!match) return null; - var dir = match.charAt(1) == ">" ? 1 : -1; - if (config && config.strict && (dir > 0) != (pos == where.ch)) return null; - var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); - - var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style, config); - if (found == null) return null; - return {from: Pos(where.line, pos), to: found && found.pos, - match: found && found.ch == match.charAt(0), forward: dir > 0}; - } - - // bracketRegex is used to specify which type of bracket to scan - // should be a regexp, e.g. /[[\]]/ - // - // Note: If "where" is on an open bracket, then this bracket is ignored. - // - // Returns false when no bracket was found, null when it reached - // maxScanLines and gave up - function scanForBracket(cm, where, dir, style, config) { - var maxScanLen = (config && config.maxScanLineLength) || 10000; - var maxScanLines = (config && config.maxScanLines) || 1000; - - var stack = []; - var re = bracketRegex(config) - var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) - : Math.max(cm.firstLine() - 1, where.line - maxScanLines); - for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { - var line = cm.getLine(lineNo); - if (!line) continue; - var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; - if (line.length > maxScanLen) continue; - if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); - for (; pos != end; pos += dir) { - var ch = line.charAt(pos); - if (re.test(ch) && (style === undefined || - (cm.getTokenTypeAt(Pos(lineNo, pos + 1)) || "") == (style || ""))) { - var match = matching[ch]; - if (match && (match.charAt(1) == ">") == (dir > 0)) stack.push(ch); - else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; - else stack.pop(); - } - } - } - return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; - } - - function matchBrackets(cm, autoclear, config) { - // Disable brace matching in long lines, since it'll cause hugely slow updates - var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000, - highlightNonMatching = config && config.highlightNonMatching; - var marks = [], ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config); - if (match && (match.match || highlightNonMatching !== false) && cm.getLine(match.from.line).length <= maxHighlightLen) { - var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; - marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); - if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) - marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); - } - } - - if (marks.length) { - // Kludge to work around the IE bug from issue #1193, where text - // input stops going to the textarea whenever this fires. - if (ie_lt8 && cm.state.focused) cm.focus(); - - var clear = function() { - cm.operation(function() { - for (var i = 0; i < marks.length; i++) marks[i].clear(); - }); - }; - if (autoclear) setTimeout(clear, 800); - else return clear; - } - } - - function doMatchBrackets(cm) { - cm.operation(function() { - if (cm.state.matchBrackets.currentlyHighlighted) { - cm.state.matchBrackets.currentlyHighlighted(); - cm.state.matchBrackets.currentlyHighlighted = null; - } - cm.state.matchBrackets.currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); - }); - } - - function clearHighlighted(cm) { - if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) { - cm.state.matchBrackets.currentlyHighlighted(); - cm.state.matchBrackets.currentlyHighlighted = null; - } - } - - CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - cm.off("cursorActivity", doMatchBrackets); - cm.off("focus", doMatchBrackets) - cm.off("blur", clearHighlighted) - clearHighlighted(cm); - } - if (val) { - cm.state.matchBrackets = typeof val == "object" ? val : {}; - cm.on("cursorActivity", doMatchBrackets); - cm.on("focus", doMatchBrackets) - cm.on("blur", clearHighlighted) - } - }); - - CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); - CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){ - // Backwards-compatibility kludge - if (oldConfig || typeof config == "boolean") { - if (!oldConfig) { - config = config ? {strict: true} : null - } else { - oldConfig.strict = config - config = oldConfig - } - } - return findMatchingBracket(this, pos, config) - }); - CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ - return scanForBracket(this, pos, dir, style, config); - }); -}); diff --git a/javascript/src/Helper/codemirror/qfq.js b/javascript/src/Helper/codemirror/qfq.js index 7f0d83a1bd2ee62288cc9b835598759b4500a9f6..c1816c346b76c7a5d545f8eb92fa346208d280f0 100644 --- a/javascript/src/Helper/codemirror/qfq.js +++ b/javascript/src/Helper/codemirror/qfq.js @@ -624,7 +624,13 @@ list.push(h); }); - return { list: list, from: from, to: to }; + var onpick = function(completion) { + if (completion.tokenType === "qfq-level") + cm.execCommand("indentAuto"); + }; + var completions = { list: list, from: from, to: to }; + CodeMirror.on(completions, "pick", onpick); + return completions; } }); @@ -648,24 +654,30 @@ }); }); + CodeMirror.defineOption("qfq-brackets", false, function(cm) { + // matchBrackets needs to be loaded first in order for this to work + // couldn't figure out how to pass a RegExp through JSON (which would be the proper way to configure this addon) + cm.state.matchBrackets.bracketRegex = /[(){}[\]<>]/; + }); + CodeMirror.defineOption("qfq-keymap", false, function(cm) { - cm.setOption("extraKeys", { - Tab: function(cm) { - if (cm.getSelections()[0].length) { - // something selected: indent more - cm.execCommand("indentMore"); - } else { - // insert one indentUnit worth of spaces - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - }, - "Shift-Tab": function(cm) { - cm.execCommand("indentLess"); - }, - "Ctrl-Enter": function (cm) { - cm.execCommand("indentAuto"); - } - }) + cm.setOption("extraKeys", { + Tab: function(cm) { + if (cm.getSelections()[0].length) { + // something selected: indent more + cm.execCommand("indentMore"); + } else { + // insert one indentUnit worth of spaces + var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); + cm.replaceSelection(spaces); + } + }, + "Shift-Tab": function(cm) { + cm.execCommand("indentLess"); + }, + "Ctrl-Enter": function (cm) { + cm.execCommand("indentAuto"); + } + }) }); }); \ No newline at end of file diff --git a/package.json b/package.json index 81d8ebd717faf4b2d32e867ba3ec687058bc7882..bc2cfce4b7c25b9aa327ae96b67e4fb400f88e2a 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "copy": "node javascript/build/copy.js", "echo": "echo \"$npm_package_config_js_dir\"", "concat": "concat -o javascript/build/dist/qfq.debug.js javascript/src/Core/QfqEvents.js javascript/src/Core/FormGroup.js javascript/src/*.js javascript/src/Helper/*.js javascript/src/Element/*.js", - "concat-cm": "concat -o javascript/build/dist/codemirror/codemirror-qfq.js node_modules/codemirror/lib/codemirror.js javascript/src/Helper/codemirror/qfq.js javascript/src/Helper/codemirror/addon-matchbrackets.js node_modules/codemirror/addon/search/match-highlighter.js node_modules/codemirror/addon/hint/show-hint.js node_modules/codemirror/addon/edit/closebrackets.js && concat -o less/dist/codemirror.css node_modules/codemirror/lib/codemirror.css node_modules/codemirror/theme/*.css node_modules/codemirror/addon/hint/show-hint.css less/codemirror-custom.css", + "concat-cm": "concat -o javascript/build/dist/codemirror/codemirror-qfq.js node_modules/codemirror/lib/codemirror.js node_modules/codemirror/addon/edit/matchbrackets.js node_modules/codemirror/addon/edit/closebrackets.js javascript/src/Helper/codemirror/qfq.js node_modules/codemirror/addon/search/match-highlighter.js node_modules/codemirror/addon/hint/show-hint.js && concat -o less/dist/codemirror.css node_modules/codemirror/lib/codemirror.css node_modules/codemirror/theme/*.css node_modules/codemirror/addon/hint/show-hint.css less/codemirror-custom.css", "terser": "node javascript/build/terser.js", "jshint": "jshint javascript/src --exclude javascript/src/Plugins", "less": "lessc -clean-css less/qfq-bs.css.less less/dist/qfq-bs.css && lessc -clean-css less/qfq-letter.css.less less/dist/qfq-letter.css && lessc -clean-css less/qfq-plain.css.less less/dist/qfq-plain.css && lessc -clean-css less/tablesorter-bootstrap.less less/dist/tablesorter-bootstrap.css",