diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.ckeditor.css b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.ckeditor.css new file mode 100644 index 000000000..58c7f9620 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.ckeditor.css @@ -0,0 +1,112 @@ +/* Extra for the CKEditor CodeMirror Plugin */ + +.CodeMirror {font:13px/1.4em monospace;} + +.CodeMirror .activeline { background: #e8f2ff; } + +.CodeMirror .CodeMirror-foldmarker { + color: blue; + text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px; + font-family: arial; + line-height: .3; + cursor: pointer; +} + +/* Fixes for themes */ +.cm-s-cobalt .CodeMirror-selected { background: #b36539 !important; } +.cm-s-erlang-dark .CodeMirror-selected { background: #b36539 !important; } +.cm-s-lesser-dark .CodeMirror-selected {background: #45443B !important;} +.cm-s-monokai .CodeMirror-selected {background: #49483E !important;} +.cm-s-night .CodeMirror-selected { background: #447 !important; } +.cm-s-rubyblue .CodeMirror-selected { background: #38566F !important; } +.cm-s-twilight .CodeMirror-selected { background: #323232 !important; } +.cm-s-xq-dark .CodeMirror-selected { background: #a8f !important; } + +.cm-s-blackboard .activeline, +.cm-s-cobalt .activeline, +.cm-s-erlang-dark .activeline, +.cm-s-lesser-dark .activeline, +.cm-s-monokai .activeline, +.cm-s-night .activeline, +.cm-s-rubyblue .activeline, +.cm-s-vibrant-ink .activeline, +.cm-s-xq-dark .activeline { background: #757575; } +.cm-s-twilight .activeline { background:#494949; } + +.CodeMirror-focused .cm-matchhighlight { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==); + background-position: bottom; + background-repeat: repeat-x; +} + +/* Dialog Addon */ +.CodeMirror-dialog { + position: absolute; + left: 0; right: 0; + background: white; + z-index: 15; + padding: .1em .8em; + overflow: hidden; + color: #333; +} + +.CodeMirror-dialog-top { + border-bottom: 1px solid #eee; + top: 0; +} + +.CodeMirror-dialog-bottom { + border-top: 1px solid #eee; + bottom: 0; +} + +.CodeMirror-dialog input { + border: none; + outline: none; + background: transparent; + width: 20em; + color: inherit; + font-family: monospace; +} + +.CodeMirror-dialog button { + font-size: 70%; +} +.CodeMirror-hints { + position: absolute; + z-index: 10; + 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); + border-radius: 3px; + border: 1px solid silver; + + background: white; + font-size: 90%; + font-family: monospace; + + max-height: 20em; + overflow-y: auto; +} + +.CodeMirror-hint { + margin: 0; + padding: 0 4px; + border-radius: 2px; + max-width: 19em; + overflow: hidden; + white-space: pre; + color: black; + cursor: pointer; +} + +.CodeMirror-hint-active { + background: #08f; + color: white; +} \ No newline at end of file diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.css b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.css new file mode 100644 index 000000000..4e126154f --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.css @@ -0,0 +1,246 @@ +/* BASICS */ + +.CodeMirror { + /* Set height, width, borders, and global font properties here */ + font-family: monospace; + height: 300px; +} +.CodeMirror-scroll { + /* Set scrolling behaviour here */ + overflow: auto; +} + +/* PADDING */ + +.CodeMirror-lines { + padding: 4px 0; /* Vertical padding around content */ +} +.CodeMirror pre { + padding: 0 4px; /* Horizontal padding of content */ +} + +.CodeMirror-scrollbar-filler { + background-color: white; /* The little square between H and V scrollbars */ +} + +/* GUTTER */ + +.CodeMirror-gutters { + border-right: 1px solid #ddd; + background-color: #f7f7f7; +} +.CodeMirror-linenumbers {} +.CodeMirror-linenumber { + padding: 0 3px 0 5px; + min-width: 20px; + text-align: right; + color: #999; +} + +/* CURSOR */ + +.CodeMirror div.CodeMirror-cursor { + border-left: 1px solid black; + z-index: 3; +} +/* Shown when moving in bi-directional text */ +.CodeMirror div.CodeMirror-secondarycursor { + border-left: 1px solid silver; +} +.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { + width: auto; + border: 0; + background: #7e7; + z-index: 1; +} +/* Can style cursor different in overwrite (non-insert) mode */ +.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {} + +.cm-tab { display: inline-block; } + +/* DEFAULT THEME */ + +.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 {color: black;} +.cm-s-default .cm-variable-2 {color: #05a;} +.cm-s-default .cm-variable-3 {color: #085;} +.cm-s-default .cm-property {color: black;} +.cm-s-default .cm-operator {color: black;} +.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-error {color: #f00;} +.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-header {color: blue;} +.cm-s-default .cm-quote {color: #090;} +.cm-s-default .cm-hr {color: #999;} +.cm-s-default .cm-link {color: #00c;} + +.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-invalidchar {color: #f00;} + +div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} +div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} + +/* STOP */ + +/* The rest of this file contains styles related to the mechanics of + the editor. You probably shouldn't touch them. */ + +.CodeMirror { + line-height: 1; + position: relative; + overflow: hidden; + background: white; + color: black; +} + +.CodeMirror-scroll { + /* 30px is the magic margin used to hide the element's real scrollbars */ + /* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */ + margin-bottom: -30px; margin-right: -30px; + padding-bottom: 30px; padding-right: 30px; + height: 100%; + outline: none; /* Prevent dragging from highlighting the element */ + position: relative; +} +.CodeMirror-sizer { + position: relative; +} + +/* The fake, visible scrollbars. Used to force redraw during scrolling + before actuall scrolling happens, thus preventing shaking and + flickering artifacts. */ +.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler { + position: absolute; + z-index: 6; + display: none; +} +.CodeMirror-vscrollbar { + right: 0; top: 0; + overflow-x: hidden; + overflow-y: scroll; +} +.CodeMirror-hscrollbar { + bottom: 0; left: 0; + overflow-y: hidden; + overflow-x: scroll; +} +.CodeMirror-scrollbar-filler { + right: 0; bottom: 0; + z-index: 6; +} + +.CodeMirror-gutters { + position: absolute; left: 0; top: 0; + height: 100%; + padding-bottom: 30px; + z-index: 3; +} +.CodeMirror-gutter { + height: 100%; + padding-bottom: 30px; + margin-bottom: -32px; + display: inline-block; + /* Hack to make IE7 behave */ + *zoom:1; + *display:inline; +} +.CodeMirror-gutter-elt { + position: absolute; + cursor: default; + z-index: 4; +} + +.CodeMirror-lines { + cursor: text; +} +.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; +} +.CodeMirror-wrap pre { + 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; +} + +.CodeMirror-linewidget { + position: relative; + z-index: 2; + overflow: auto; +} + +.CodeMirror-widget { + display: inline-block; +} + +.CodeMirror-wrap .CodeMirror-scroll { + overflow-x: hidden; +} + +.CodeMirror-measure { + position: absolute; + width: 100%; height: 0px; + overflow: hidden; + visibility: hidden; +} +.CodeMirror-measure pre { position: static; } + +.CodeMirror div.CodeMirror-cursor { + position: absolute; + visibility: hidden; + border-right: none; + width: 0; +} +.CodeMirror-focused div.CodeMirror-cursor { + visibility: visible; +} + +.CodeMirror-selected { background: #d9d9d9; } +.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } + +.cm-searching { + background: #ffa; + background: rgba(255, 255, 0, .4); +} + +/* IE7 hack to prevent it from returning funny offsetTops on the spans */ +.CodeMirror span { *vertical-align: text-bottom; } + +@media print { + /* Hide the cursor when printing */ + .CodeMirror div.CodeMirror-cursor { + visibility: hidden; + } +} diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.min.css b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.min.css new file mode 100644 index 000000000..43935ad0f --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/css/codemirror.min.css @@ -0,0 +1 @@ +.CodeMirror{font-family:monospace;height:300px}.CodeMirror-scroll{overflow:auto}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7}.CodeMirror-linenumbers{}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999}.CodeMirror div.CodeMirror-cursor{border-left:1px solid #000;z-index:3}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor{width:auto;border:0;background:#7e7;z-index:1}.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite{}.cm-tab{display:inline-block}.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{color:#000}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-property{color:#000}.cm-s-default .cm-operator{color:#000}.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-error{color:red}.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-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.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-invalidchar{color:red}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror{line-height:1;position:relative;overflow:hidden;background:#fff;color:#000}.CodeMirror-scroll{margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;padding-right:30px;height:100%;outline:none;position:relative}.CodeMirror-sizer{position:relative}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0;z-index:6}.CodeMirror-gutters{position:absolute;left:0;top:0;height:100%;padding-bottom:30px;z-index:3}.CodeMirror-gutter{height:100%;padding-bottom:30px;margin-bottom:-32px;display:inline-block;*zoom:1;*display:inline}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-lines{cursor:text}.CodeMirror pre{-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}.CodeMirror-wrap pre{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}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-widget{display:inline-block}.CodeMirror-wrap .CodeMirror-scroll{overflow-x:hidden}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-measure pre{position:static}.CodeMirror div.CodeMirror-cursor{position:absolute;visibility:hidden;border-right:none;width:0}.CodeMirror-focused div.CodeMirror-cursor{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}@media print{.CodeMirror div.CodeMirror-cursor{visibility:hidden}}.CodeMirror{font:13px/1.4em monospace}.CodeMirror .activeline{background:#e8f2ff}.CodeMirror .CodeMirror-foldmarker{color:blue;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.cm-s-cobalt .CodeMirror-selected{background:#b36539!important}.cm-s-erlang-dark .CodeMirror-selected{background:#b36539!important}.cm-s-lesser-dark .CodeMirror-selected{background:#45443b!important}.cm-s-monokai .CodeMirror-selected{background:#49483e!important}.cm-s-night .CodeMirror-selected{background:#447!important}.cm-s-rubyblue .CodeMirror-selected{background:#38566f!important}.cm-s-twilight .CodeMirror-selected{background:#323232!important}.cm-s-xq-dark .CodeMirror-selected{background:#a8f!important}.cm-s-blackboard .activeline,.cm-s-cobalt .activeline,.cm-s-erlang-dark .activeline,.cm-s-lesser-dark .activeline,.cm-s-monokai .activeline,.cm-s-night .activeline,.cm-s-rubyblue .activeline,.cm-s-vibrant-ink .activeline,.cm-s-xq-dark .activeline{background:#757575}.cm-s-twilight .activeline{background:#494949}.CodeMirror-focused .cm-matchhighlight{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAFklEQVQI12NgYGBgkKzc8x9CMDAwAAAmhwSbidEoSQAAAABJRU5ErkJggg==);background-position:bottom;background-repeat:repeat-x}.CodeMirror-dialog{position:absolute;left:0;right:0;background:#fff;z-index:15;padding:.1em .8em;overflow:hidden;color:#333}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.CodeMirror-dialog button{font-size:70%}.CodeMirror-hints{position:absolute;z-index:10;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);border-radius:3px;border:1px solid silver;background:#fff;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;max-width:19em;overflow:hidden;white-space:pre;color:#000;cursor:pointer}.CodeMirror-hint-active{background:#08f;color:#fff} \ No newline at end of file diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/AutoComplete.png b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/AutoComplete.png new file mode 100644 index 000000000..fd37b42ed Binary files /dev/null and b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/AutoComplete.png differ diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/AutoFormat.png b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/AutoFormat.png new file mode 100644 index 000000000..d7a53a745 Binary files /dev/null and b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/AutoFormat.png differ diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/CommentSelectedRange.png b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/CommentSelectedRange.png new file mode 100644 index 000000000..a982fb305 Binary files /dev/null and b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/CommentSelectedRange.png differ diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/SearchCode.png b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/SearchCode.png new file mode 100644 index 000000000..1dea4b1e6 Binary files /dev/null and b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/SearchCode.png differ diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/UncommentSelectedRange.png b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/UncommentSelectedRange.png new file mode 100644 index 000000000..035f99fac Binary files /dev/null and b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/icons/UncommentSelectedRange.png differ diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/dialog/dialog.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/dialog/dialog.js new file mode 100644 index 000000000..f090017e9 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/dialog/dialog.js @@ -0,0 +1,81 @@ +// Open simple dialogs on top of an editor. Relies on dialog.css. + +(function() { + function dialogDiv(cm, template, bottom) { + var wrap = cm.getWrapperElement(); + var dialog; + + dialog = wrap.appendChild(document.createElement("div")); + if (bottom) { + dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; + } else { + dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; + } + dialog.innerHTML = template; + return dialog; + } + + CodeMirror.defineExtension("openDialog", function(template, callback, options) { + var dialog = dialogDiv(this, template, options && options.bottom); + var closed = false, me = this; + function close() { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + } + var inp = dialog.getElementsByTagName("input")[0], button; + if (inp) { + CodeMirror.on(inp, "keydown", function(e) { + if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } + if (e.keyCode == 13 || e.keyCode == 27) { + CodeMirror.e_stop(e); + close(); + me.focus(); + if (e.keyCode == 13) callback(inp.value); + } + }); + if (options && options.onKeyUp) { + CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); + } + if (options && options.value) inp.value = options.value; + inp.focus(); + CodeMirror.on(inp, "blur", close); + } else if (button = dialog.getElementsByTagName("button")[0]) { + CodeMirror.on(button, "click", function() { + close(); + me.focus(); + }); + button.focus(); + CodeMirror.on(button, "blur", close); + } + return close; + }); + + CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { + var dialog = dialogDiv(this, template, options && options.bottom); + var buttons = dialog.getElementsByTagName("button"); + var closed = false, me = this, blurring = 1; + function close() { + if (closed) return; + closed = true; + dialog.parentNode.removeChild(dialog); + me.focus(); + } + buttons[0].focus(); + for (var i = 0; i < buttons.length; ++i) { + var b = buttons[i]; + (function(callback) { + CodeMirror.on(b, "click", function(e) { + CodeMirror.e_preventDefault(e); + close(); + if (callback) callback(me); + }); + })(callbacks[i]); + CodeMirror.on(b, "blur", function() { + --blurring; + setTimeout(function() { if (blurring <= 0) close(); }, 200); + }); + CodeMirror.on(b, "focus", function() { ++blurring; }); + } + }); +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/closebrackets.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/closebrackets.js new file mode 100644 index 000000000..b46caca02 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/closebrackets.js @@ -0,0 +1,52 @@ +(function() { + var DEFAULT_BRACKETS = "()[]{}''\"\""; + var SPACE_CHAR_REGEX = /\s/; + + CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { + var wasOn = old && old != CodeMirror.Init; + if (val && !wasOn) + cm.addKeyMap(buildKeymap(typeof val == "string" ? val : DEFAULT_BRACKETS)); + else if (!val && wasOn) + cm.removeKeyMap("autoCloseBrackets"); + }); + + function buildKeymap(pairs) { + var map = { + name : "autoCloseBrackets", + Backspace: function(cm) { + if (cm.somethingSelected()) return CodeMirror.Pass; + var cur = cm.getCursor(), line = cm.getLine(cur.line); + if (cur.ch && cur.ch < line.length && + pairs.indexOf(line.slice(cur.ch - 1, cur.ch + 1)) % 2 == 0) + cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1)); + else + return CodeMirror.Pass; + } + }; + var closingBrackets = []; + for (var i = 0; i < pairs.length; i += 2) (function(left, right) { + if (left != right) closingBrackets.push(right); + function surround(cm) { + var selection = cm.getSelection(); + cm.replaceSelection(left + selection + right); + } + function maybeOverwrite(cm) { + var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1)); + if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass; + else cm.execCommand("goCharRight"); + } + map["'" + left + "'"] = function(cm) { + if (cm.somethingSelected()) return surround(cm); + if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return; + var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1); + var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch); + if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar)) + cm.replaceSelection(left + right, {head: ahead, anchor: ahead}); + else + return CodeMirror.Pass; + }; + if (left != right) map["'" + right + "'"] = maybeOverwrite; + })(pairs.charAt(i), pairs.charAt(i + 1)); + return map; + } +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/closetag.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/closetag.js new file mode 100644 index 000000000..54fa19546 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/closetag.js @@ -0,0 +1,85 @@ +/** + * Tag-closer extension for CodeMirror. + * + * This extension adds an "autoCloseTags" option that can be set to + * either true to get the default behavior, or an object to further + * configure its behavior. + * + * These are supported options: + * + * `whenClosing` (default true) + * Whether to autoclose when the '/' of a closing tag is typed. + * `whenOpening` (default true) + * Whether to autoclose the tag when the final '>' of an opening + * tag is typed. + * `dontCloseTags` (default is empty tags for HTML, none for XML) + * An array of tag names that should not be autoclosed. + * `indentTags` (default is block tags for HTML, none for XML) + * An array of tag names that should, when opened, cause a + * blank line to be added inside the tag, and the blank line and + * closing line to be indented. + * + * See demos/closetag.html for a usage example. + */ + +(function() { + CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) { + if (val && (old == CodeMirror.Init || !old)) { + var map = {name: "autoCloseTags"}; + if (typeof val != "object" || val.whenClosing) + map["'/'"] = function(cm) { return autoCloseTag(cm, '/'); }; + if (typeof val != "object" || val.whenOpening) + map["'>'"] = function(cm) { return autoCloseTag(cm, '>'); }; + cm.addKeyMap(map); + } else if (!val && (old != CodeMirror.Init && old)) { + cm.removeKeyMap("autoCloseTags"); + } + }); + + var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", + "source", "track", "wbr"]; + var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4", + "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"]; + + function autoCloseTag(cm, ch) { + var pos = cm.getCursor(), tok = cm.getTokenAt(pos); + var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; + if (inner.mode.name != "xml") return CodeMirror.Pass; + + var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; + var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); + var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); + + if (ch == ">" && state.tagName) { + var tagName = state.tagName; + if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch); + var lowerTagName = tagName.toLowerCase(); + // Don't process the '>' at the end of an end-tag or self-closing tag + if (tok.type == "tag" && state.type == "closeTag" || tok.string.indexOf("/") > -1 || + dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1) + return CodeMirror.Pass; + + var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1; + var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1); + cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "", + {head: curPos, anchor: curPos}); + if (doIndent) { + cm.indentLine(pos.line + 1); + cm.indentLine(pos.line + 2); + } + return; + } else if (ch == "/" && tok.string == "<") { + var tagName = state.context && state.context.tagName; + if (tagName) cm.replaceSelection("/" + tagName + ">", "end"); + return; + } + return CodeMirror.Pass; + } + + function indexOf(collection, elt) { + if (collection.indexOf) return collection.indexOf(elt); + for (var i = 0, e = collection.length; i < e; ++i) + if (collection[i] == elt) return i; + return -1; + } +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/continuecomment.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/continuecomment.js new file mode 100644 index 000000000..308026229 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/continuecomment.js @@ -0,0 +1,44 @@ +(function() { + var modes = ["clike", "css", "javascript"]; + for (var i = 0; i < modes.length; ++i) + CodeMirror.extendMode(modes[i], {blockCommentStart: "/*", + blockCommentEnd: "*/", + blockCommentContinue: " * "}); + + function continueComment(cm) { + var pos = cm.getCursor(), token = cm.getTokenAt(pos); + var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode; + var space; + + if (token.type == "comment" && mode.blockCommentStart) { + var end = token.string.indexOf(mode.blockCommentEnd); + var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found; + if (end != -1 && end == token.string.length - mode.blockCommentEnd.length) { + // Comment ended, don't continue it + } else if (token.string.indexOf(mode.blockCommentStart) == 0) { + space = full.slice(0, token.start); + if (!/^\s*$/.test(space)) { + space = ""; + for (var i = 0; i < token.start; ++i) space += " "; + } + } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 && + found + mode.blockCommentContinue.length > token.start && + /^\s*$/.test(full.slice(0, found))) { + space = full.slice(0, found); + } + } + + if (space != null) + cm.replaceSelection("\n" + space + mode.blockCommentContinue, "end"); + else + return CodeMirror.Pass; + } + + CodeMirror.defineOption("continueComments", null, function(cm, val, prev) { + if (prev && prev != CodeMirror.Init) + cm.removeKeyMap("continueComment"); + var map = {name: "continueComment"}; + map[typeof val == "string" ? val : "Enter"] = continueComment; + cm.addKeyMap(map); + }); +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/continuelist.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/continuelist.js new file mode 100644 index 000000000..fb1fc38ba --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/continuelist.js @@ -0,0 +1,25 @@ +(function() { + 'use strict'; + + var listRE = /^(\s*)([*+-]|(\d+)\.)(\s*)/, + unorderedBullets = '*+-'; + + CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { + var pos = cm.getCursor(), + inList = cm.getStateAfter(pos.line).list, + match; + + if (!inList || !(match = cm.getLine(pos.line).match(listRE))) { + cm.execCommand('newlineAndIndent'); + return; + } + + var indent = match[1], after = match[4]; + var bullet = unorderedBullets.indexOf(match[2]) >= 0 + ? match[2] + : (parseInt(match[3], 10) + 1) + '.'; + + cm.replaceSelection('\n' + indent + bullet + after, 'end'); + }; + +}()); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/matchbrackets.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/matchbrackets.js new file mode 100644 index 000000000..f4925b725 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/edit/matchbrackets.js @@ -0,0 +1,74 @@ +(function() { + var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && + (document.documentMode == null || document.documentMode < 8); + + var Pos = CodeMirror.Pos; + // Disable brace matching in long lines, since it'll cause hugely slow updates + var maxLineLen = 1000; + + var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; + function findMatchingBracket(cm) { + var cur = cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1; + var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; + if (!match) return null; + var forward = match.charAt(1) == ">", d = forward ? 1 : -1; + var style = cm.getTokenAt(Pos(cur.line, pos + 1)).type; + + var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; + function scan(line, lineNo, start) { + if (!line.text) return; + var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1; + if (start != null) pos = start + d; + for (; pos != end; pos += d) { + var ch = line.text.charAt(pos); + if (re.test(ch) && cm.getTokenAt(Pos(lineNo, pos + 1)).type == style) { + var match = matching[ch]; + if (match.charAt(1) == ">" == forward) stack.push(ch); + else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false}; + else if (!stack.length) return {pos: pos, match: true}; + } + } + } + for (var i = cur.line, found, e = forward ? Math.min(i + 100, cm.lineCount()) : Math.max(-1, i - 100); i != e; i+=d) { + if (i == cur.line) found = scan(line, i, pos); + else found = scan(cm.getLineHandle(i), i); + if (found) break; + } + return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos), match: found && found.match}; + } + + function matchBrackets(cm, autoclear) { + var found = findMatchingBracket(cm); + if (!found || cm.getLine(found.from.line).length > maxLineLen || + found.to && cm.getLine(found.to.line).length > maxLineLen) + return; + + var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; + var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style}); + var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style}); + // Kludge to work around the IE bug from issue #1193, where text + // input stops going to the textare whever this fires. + if (ie_lt8 && cm.state.focused) cm.display.input.focus(); + var clear = function() { + cm.operation(function() { one.clear(); two && two.clear(); }); + }; + if (autoclear) setTimeout(clear, 800); + else return clear; + } + + var currentlyHighlighted = null; + function doMatchBrackets(cm) { + cm.operation(function() { + if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} + if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false); + }); + } + + CodeMirror.defineOption("matchBrackets", false, function(cm, val) { + if (val) cm.on("cursorActivity", doMatchBrackets); + else cm.off("cursorActivity", doMatchBrackets); + }); + + CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); + CodeMirror.defineExtension("findMatchingBracket", function(){return findMatchingBracket(this);}); +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/brace-fold.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/brace-fold.js new file mode 100644 index 000000000..aad6e0141 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/brace-fold.js @@ -0,0 +1,31 @@ +CodeMirror.braceRangeFinder = function(cm, start) { + var line = start.line, lineText = cm.getLine(line); + var at = lineText.length, startChar, tokenType; + for (;;) { + var found = lineText.lastIndexOf("{", at); + if (found < start.ch) break; + tokenType = cm.getTokenAt(CodeMirror.Pos(line, found + 1)).type; + if (!/^(comment|string)/.test(tokenType)) { startChar = found; break; } + at = found - 1; + } + if (startChar == null || lineText.lastIndexOf("}") > startChar) return; + var count = 1, lastLine = cm.lineCount(), end, endCh; + outer: for (var i = line + 1; i < lastLine; ++i) { + var text = cm.getLine(i), pos = 0; + for (;;) { + var nextOpen = text.indexOf("{", pos), nextClose = text.indexOf("}", pos); + if (nextOpen < 0) nextOpen = text.length; + if (nextClose < 0) nextClose = text.length; + pos = Math.min(nextOpen, nextClose); + if (pos == text.length) break; + if (cm.getTokenAt(CodeMirror.Pos(i, pos + 1)).type == tokenType) { + if (pos == nextOpen) ++count; + else if (!--count) { end = i; endCh = pos; break outer; } + } + ++pos; + } + } + if (end == null || end == line + 1) return; + return {from: CodeMirror.Pos(line, startChar + 1), + to: CodeMirror.Pos(end, endCh)}; +}; diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/foldcode.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/foldcode.js new file mode 100644 index 000000000..b8b4b0da9 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/foldcode.js @@ -0,0 +1,32 @@ +CodeMirror.newFoldFunction = function(rangeFinder, widget) { + if (widget == null) widget = "\u2194"; + if (typeof widget == "string") { + var text = document.createTextNode(widget); + widget = document.createElement("span"); + widget.appendChild(text); + widget.className = "CodeMirror-foldmarker"; + } + + return function(cm, pos) { + if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0); + var range = rangeFinder(cm, pos); + if (!range) return; + + var present = cm.findMarksAt(range.from), cleared = 0; + for (var i = 0; i < present.length; ++i) { + if (present[i].__isFold) { + ++cleared; + present[i].clear(); + } + } + if (cleared) return; + + var myWidget = widget.cloneNode(true); + CodeMirror.on(myWidget, "mousedown", function() {myRange.clear();}); + var myRange = cm.markText(range.from, range.to, { + replacedWith: myWidget, + clearOnEnter: true, + __isFold: true + }); + }; +}; diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/xml-fold.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/xml-fold.js new file mode 100644 index 000000000..79c524d48 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/fold/xml-fold.js @@ -0,0 +1,64 @@ +CodeMirror.tagRangeFinder = (function() { + var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; + var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; + var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g"); + + return function(cm, start) { + var line = start.line, ch = start.ch, lineText = cm.getLine(line); + + function nextLine() { + if (line >= cm.lastLine()) return; + ch = 0; + lineText = cm.getLine(++line); + return true; + } + function toTagEnd() { + for (;;) { + var gt = lineText.indexOf(">", ch); + if (gt == -1) { if (nextLine()) continue; else return; } + var lastSlash = lineText.lastIndexOf("/", gt); + var selfClose = lastSlash > -1 && /^\s*$/.test(lineText.slice(lastSlash + 1, gt)); + ch = gt + 1; + return selfClose ? "selfClose" : "regular"; + } + } + function toNextTag() { + for (;;) { + xmlTagStart.lastIndex = ch; + var found = xmlTagStart.exec(lineText); + if (!found) { if (nextLine()) continue; else return; } + ch = found.index + found[0].length; + return found; + } + } + + var stack = [], startCh; + for (;;) { + var openTag = toNextTag(), end; + if (!openTag || line != start.line || !(end = toTagEnd())) return; + if (!openTag[1] && end != "selfClose") { + stack.push(openTag[2]); + startCh = ch; + break; + } + } + + for (;;) { + var next = toNextTag(), end, tagLine = line, tagCh = ch - (next ? next[0].length : 0); + if (!next || !(end = toTagEnd())) return; + if (end == "selfClose") continue; + if (next[1]) { // closing tag + for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) { + stack.length = i; + break; + } + if (!stack.length) return { + from: CodeMirror.Pos(start.line, startCh), + to: CodeMirror.Pos(tagLine, tagCh) + }; + } else { // opening tag + stack.push(next[2]); + } + } + }; +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/format/autoFormatAll.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/format/autoFormatAll.js new file mode 100644 index 000000000..2e44a6949 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/format/autoFormatAll.js @@ -0,0 +1,43 @@ +(function() { + + // Applies automatic formatting to the specified range + CodeMirror.defineExtension("autoFormatAll", function (from, to) { + var cm = this; + var outer = cm.getMode(), text = cm.getRange(from, to).split("\n"); + var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state); + var tabSize = cm.getOption("tabSize"); + + var out = "", lines = 0, atSol = from.ch == 0; + function newline() { + out += "\n"; + atSol = true; + ++lines; + } + + for (var i = 0; i < text.length; ++i) { + var stream = new CodeMirror.StringStream(text[i], tabSize); + while (!stream.eol()) { + var inner = CodeMirror.innerMode(outer, state); + var style = outer.token(stream, state), cur = stream.current(); + stream.start = stream.pos; + if (!atSol || /\S/.test(cur)) { + out += cur; + atSol = false; + } + if (!atSol && inner.mode.newlineAfterToken && + inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state)) + newline(); + } + if (!stream.pos && outer.blankLine) outer.blankLine(state); + if (!atSol && i < text.length - 1) newline(); + } + + cm.operation(function () { + cm.replaceRange(out, from, to); + for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur) + cm.indentLine(cur, "smart"); + + cm.setCursor({ line:0, ch:0 }); + }); + }); +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/format/formatting.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/format/formatting.js new file mode 100644 index 000000000..88b84307f --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/format/formatting.js @@ -0,0 +1,114 @@ +(function() { + + CodeMirror.extendMode("css", { + commentStart: "/*", + commentEnd: "*/", + newlineAfterToken: function(_type, content) { + return /^[;{}]$/.test(content); + } + }); + + CodeMirror.extendMode("javascript", { + commentStart: "/*", + commentEnd: "*/", + // FIXME semicolons inside of for + newlineAfterToken: function(_type, content, textAfter, state) { + if (this.jsonMode) { + return /^[\[,{]$/.test(content) || /^}/.test(textAfter); + } else { + if (content == ";" && state.lexical && state.lexical.type == ")") return false; + return /^[;{}]$/.test(content) && !/^;/.test(textAfter); + } + } + }); + + var inlineElements = /^(a|abbr|acronym|area|base|bdo|big|br|button|caption|cite|code|col|colgroup|dd|del|dfn|em|frame|hr|iframe|img|input|ins|kbd|label|legend|link|map|object|optgroup|option|param|q|samp|script|select|small|span|strong|sub|sup|textarea|tt|var)$/; + + CodeMirror.extendMode("xml", { + commentStart: "", + newlineAfterToken: function(type, content, textAfter, state) { + var inline = false; + if (this.configuration == "html") + inline = state.context ? inlineElements.test(state.context.tagName) : false; + return !inline && ((type == "tag" && />$/.test(content) && state.context) || + /^ -1 && endIndex > -1 && endIndex > startIndex) { + // Take string till comment start + selText = selText.substr(0, startIndex) + // From comment start till comment end + + selText.substring(startIndex + curMode.commentStart.length, endIndex) + // From comment end till string end + + selText.substr(endIndex + curMode.commentEnd.length); + } + cm.replaceRange(selText, from, to); + } + }); + }); + + // Applies automatic mode-aware indentation to the specified range + CodeMirror.defineExtension("autoIndentRange", function (from, to) { + var cmInstance = this; + this.operation(function () { + for (var i = from.line; i <= to.line; i++) { + cmInstance.indentLine(i, "smart"); + } + }); + }); + + // Applies automatic formatting to the specified range + CodeMirror.defineExtension("autoFormatRange", function (from, to) { + var cm = this; + var outer = cm.getMode(), text = cm.getRange(from, to).split("\n"); + var state = CodeMirror.copyState(outer, cm.getTokenAt(from).state); + var tabSize = cm.getOption("tabSize"); + + var out = "", lines = 0, atSol = from.ch == 0; + function newline() { + out += "\n"; + atSol = true; + ++lines; + } + + for (var i = 0; i < text.length; ++i) { + var stream = new CodeMirror.StringStream(text[i], tabSize); + while (!stream.eol()) { + var inner = CodeMirror.innerMode(outer, state); + var style = outer.token(stream, state), cur = stream.current(); + stream.start = stream.pos; + if (!atSol || /\S/.test(cur)) { + out += cur; + atSol = false; + } + if (!atSol && inner.mode.newlineAfterToken && + inner.mode.newlineAfterToken(style, cur, stream.string.slice(stream.pos) || text[i+1] || "", inner.state)) + newline(); + } + if (!stream.pos && outer.blankLine) outer.blankLine(state); + if (!atSol && i < text.length - 1) newline(); + } + + cm.operation(function () { + cm.replaceRange(out, from, to); + for (var cur = from.line + 1, end = from.line + lines; cur <= end; ++cur) + cm.indentLine(cur, "smart"); + cm.setSelection(from, cm.getCursor(false)); + }); + }); +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/match-highlighter.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/match-highlighter.js new file mode 100644 index 000000000..c6e35cd97 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/match-highlighter.js @@ -0,0 +1,60 @@ +// Highlighting text that matches the selection +// +// Defines an option highlightSelectionMatches, which, when enabled, +// will style strings that match the selection throughout the +// document. +// +// The option can be set to true to simply enable it, or to a +// {minChars, style} object to explicitly configure it. minChars is +// the minimum amount of characters that should be selected for the +// behavior to occur, and style is the token style to apply to the +// matches. This will be prefixed by "cm-" to create an actual CSS +// class name. + +(function() { + var DEFAULT_MIN_CHARS = 2; + var DEFAULT_TOKEN_STYLE = "matchhighlight"; + + function State(options) { + this.minChars = typeof options == "object" && options.minChars || DEFAULT_MIN_CHARS; + this.style = typeof options == "object" && options.style || DEFAULT_TOKEN_STYLE; + this.overlay = null; + } + + CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) { + var prev = old && old != CodeMirror.Init; + if (val && !prev) { + cm._matchHighlightState = new State(val); + cm.on("cursorActivity", highlightMatches); + } else if (!val && prev) { + var over = cm._matchHighlightState.overlay; + if (over) cm.removeOverlay(over); + cm._matchHighlightState = null; + cm.off("cursorActivity", highlightMatches); + } + }); + + function highlightMatches(cm) { + cm.operation(function() { + var state = cm._matchHighlightState; + if (state.overlay) { + cm.removeOverlay(state.overlay); + state.overlay = null; + } + + if (!cm.somethingSelected()) return; + var selection = cm.getSelection().replace(/^\s+|\s+$/g, ""); + if (selection.length < state.minChars) return; + + cm.addOverlay(state.overlay = makeOverlay(selection, state.style)); + }); + } + + function makeOverlay(query, style) { + return {token: function(stream) { + if (stream.match(query)) return style; + stream.next(); + stream.skipTo(query.charAt(0)) || stream.skipToEnd(); + }}; + } +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/search.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/search.js new file mode 100644 index 000000000..cb4aa1c2b --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/search.js @@ -0,0 +1,131 @@ +// Define search commands. Depends on dialog.js or another +// implementation of the openDialog method. + +// Replace works a little oddly -- it will do the replace on the next +// Ctrl-G (or whatever is bound to findNext) press. You prevent a +// replace by making sure the match is no longer selected when hitting +// Ctrl-G. + +(function() { + function searchOverlay(query) { + if (typeof query == "string") return {token: function(stream) { + if (stream.match(query)) return "searching"; + stream.next(); + stream.skipTo(query.charAt(0)) || stream.skipToEnd(); + }}; + return {token: function(stream) { + if (stream.match(query)) return "searching"; + while (!stream.eol()) { + stream.next(); + if (stream.match(query, false)) break; + } + }}; + } + + function SearchState() { + this.posFrom = this.posTo = this.query = null; + this.overlay = null; + } + function getSearchState(cm) { + return cm._searchState || (cm._searchState = new SearchState()); + } + function getSearchCursor(cm, query, pos) { + // Heuristic: if the query string is all lowercase, do a case insensitive search. + return cm.getSearchCursor(query, pos, typeof query == "string" && query == query.toLowerCase()); + } + function dialog(cm, text, shortText, f) { + if (cm.openDialog) cm.openDialog(text, f); + else f(prompt(shortText, "")); + } + function confirmDialog(cm, text, shortText, fs) { + if (cm.openConfirm) cm.openConfirm(text, fs); + else if (confirm(shortText)) fs[0](); + } + function parseQuery(query) { + var isRE = query.match(/^\/(.*)\/([a-z]*)$/); + return isRE ? new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i") : query; + } + var queryDialog = + 'Search: (Use /re/ syntax for regexp search)'; + function doSearch(cm, rev) { + var state = getSearchState(cm); + if (state.query) return findNext(cm, rev); + dialog(cm, queryDialog, "Search for:", function(query) { + cm.operation(function() { + if (!query || state.query) return; + state.query = parseQuery(query); + cm.removeOverlay(state.overlay); + state.overlay = searchOverlay(query); + cm.addOverlay(state.overlay); + state.posFrom = state.posTo = cm.getCursor(); + findNext(cm, rev); + }); + }); + } + function findNext(cm, rev) {cm.operation(function() { + var state = getSearchState(cm); + var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); + if (!cursor.find(rev)) { + cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0)); + if (!cursor.find(rev)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + state.posFrom = cursor.from(); state.posTo = cursor.to(); + });} + function clearSearch(cm) {cm.operation(function() { + var state = getSearchState(cm); + if (!state.query) return; + state.query = null; + cm.removeOverlay(state.overlay); + });} + + var replaceQueryDialog = + 'Replace: (Use /re/ syntax for regexp search)'; + var replacementQueryDialog = 'With: '; + var doReplaceConfirm = "Replace? "; + function replace(cm, all) { + dialog(cm, replaceQueryDialog, "Replace:", function(query) { + if (!query) return; + query = parseQuery(query); + dialog(cm, replacementQueryDialog, "Replace with:", function(text) { + if (all) { + cm.operation(function() { + for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { + if (typeof query != "string") { + var match = cm.getRange(cursor.from(), cursor.to()).match(query); + cursor.replace(text.replace(/\$(\d)/, function(_, i) {return match[i];})); + } else cursor.replace(text); + } + }); + } else { + clearSearch(cm); + var cursor = getSearchCursor(cm, query, cm.getCursor()); + var advance = function() { + var start = cursor.from(), match; + if (!(match = cursor.findNext())) { + cursor = getSearchCursor(cm, query); + if (!(match = cursor.findNext()) || + (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + confirmDialog(cm, doReplaceConfirm, "Replace?", + [function() {doReplace(match);}, advance]); + }; + var doReplace = function(match) { + cursor.replace(typeof query == "string" ? text : + text.replace(/\$(\d)/, function(_, i) {return match[i];})); + advance(); + }; + advance(); + } + }); + }); + } + + CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; + CodeMirror.commands.findNext = doSearch; + CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; + CodeMirror.commands.clearSearch = clearSearch; + CodeMirror.commands.replace = replace; + CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/searchcursor.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/searchcursor.js new file mode 100644 index 000000000..fd134636e --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/addon/search/searchcursor.js @@ -0,0 +1,130 @@ +(function(){ + var Pos = CodeMirror.Pos; + + function SearchCursor(cm, query, pos, caseFold) { + this.atOccurrence = false; this.cm = cm; + if (caseFold == null && typeof query == "string") caseFold = false; + + pos = pos ? cm.clipPos(pos) : Pos(0, 0); + this.pos = {from: pos, to: pos}; + + // The matches method is filled in based on the type of query. + // It takes a position and a direction, and returns an object + // describing the next occurrence of the query, or null if no + // more matches were found. + if (typeof query != "string") { // Regexp match + if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g"); + this.matches = function(reverse, pos) { + if (reverse) { + query.lastIndex = 0; + var line = cm.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start; + for (;;) { + query.lastIndex = cutOff; + var newMatch = query.exec(line); + if (!newMatch) break; + match = newMatch; + start = match.index; + cutOff = match.index + 1; + } + } else { + query.lastIndex = pos.ch; + var line = cm.getLine(pos.line), match = query.exec(line), + start = match && match.index; + } + if (match && match[0]) + return {from: Pos(pos.line, start), + to: Pos(pos.line, start + match[0].length), + match: match}; + }; + } else { // String query + if (caseFold) query = query.toLowerCase(); + var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;}; + var target = query.split("\n"); + // Different methods for single-line and multi-line queries + if (target.length == 1) { + if (!query.length) { + // Empty string would match anything and never progress, so + // we define it to match nothing instead. + this.matches = function() {}; + } else { + this.matches = function(reverse, pos) { + var line = fold(cm.getLine(pos.line)), len = query.length, match; + if (reverse ? (pos.ch >= len && (match = line.lastIndexOf(query, pos.ch - len)) != -1) + : (match = line.indexOf(query, pos.ch)) != -1) + return {from: Pos(pos.line, match), + to: Pos(pos.line, match + len)}; + }; + } + } else { + this.matches = function(reverse, pos) { + var ln = pos.line, idx = (reverse ? target.length - 1 : 0), match = target[idx], line = fold(cm.getLine(ln)); + var offsetA = (reverse ? line.indexOf(match) + match.length : line.lastIndexOf(match)); + if (reverse ? offsetA >= pos.ch || offsetA != match.length + : offsetA <= pos.ch || offsetA != line.length - match.length) + return; + for (;;) { + if (reverse ? !ln : ln == cm.lineCount() - 1) return; + line = fold(cm.getLine(ln += reverse ? -1 : 1)); + match = target[reverse ? --idx : ++idx]; + if (idx > 0 && idx < target.length - 1) { + if (line != match) return; + else continue; + } + var offsetB = (reverse ? line.lastIndexOf(match) : line.indexOf(match) + match.length); + if (reverse ? offsetB != line.length - match.length : offsetB != match.length) + return; + var start = Pos(pos.line, offsetA), end = Pos(ln, offsetB); + return {from: reverse ? end : start, to: reverse ? start : end}; + } + }; + } + } + } + + SearchCursor.prototype = { + findNext: function() {return this.find(false);}, + findPrevious: function() {return this.find(true);}, + + find: function(reverse) { + var self = this, pos = this.cm.clipPos(reverse ? this.pos.from : this.pos.to); + function savePosAndFail(line) { + var pos = Pos(line, 0); + self.pos = {from: pos, to: pos}; + self.atOccurrence = false; + return false; + } + + for (;;) { + if (this.pos = this.matches(reverse, pos)) { + if (!this.pos.from || !this.pos.to) { console.log(this.matches, this.pos); } + this.atOccurrence = true; + return this.pos.match || true; + } + if (reverse) { + if (!pos.line) return savePosAndFail(0); + pos = Pos(pos.line-1, this.cm.getLine(pos.line-1).length); + } + else { + var maxLine = this.cm.lineCount(); + if (pos.line == maxLine - 1) return savePosAndFail(maxLine); + pos = Pos(pos.line + 1, 0); + } + } + }, + + from: function() {if (this.atOccurrence) return this.pos.from;}, + to: function() {if (this.atOccurrence) return this.pos.to;}, + + replace: function(newText) { + if (!this.atOccurrence) return; + var lines = CodeMirror.splitLines(newText); + this.cm.replaceRange(lines, this.pos.from, this.pos.to); + this.pos.to = Pos(this.pos.from.line + lines.length - 1, + lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)); + } + }; + + CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { + return new SearchCursor(this, query, pos, caseFold); + }); +})(); diff --git a/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/codemirror.addons.min.js b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/codemirror.addons.min.js new file mode 100644 index 000000000..f1550c2a3 --- /dev/null +++ b/public/plugin_assets/redmine_ckeditor/ckeditor-contrib/plugins/codemirror/js/codemirror.addons.min.js @@ -0,0 +1 @@ +(function(){function i(n){for(var r={name:"autoCloseBrackets",Backspace:function(t){if(t.somethingSelected())return CodeMirror.Pass;var i=t.getCursor(),r=t.getLine(i.line);if(i.ch&&i.ch=0||t.test(c))r.replaceSelection(n+i,{head:s,anchor:s});else return CodeMirror.Pass}},n!=i&&(r["'"+i+"'"]=f)})(n.charAt(i),n.charAt(i+1));return r}var n="()[]{}''\"\"",t=/\s/;CodeMirror.defineOption("autoCloseBrackets",!1,function(t,r,u){var f=u&&u!=CodeMirror.Init;r&&!f?t.addKeyMap(i(typeof r=="string"?r:n)):!r&&f&&t.removeKeyMap("autoCloseBrackets")})})(),function(){function n(n,u){var e=n.getCursor(),o=n.getTokenAt(e),l=CodeMirror.innerMode(n.getMode(),o.state),s=l.state,a,c,v,f;if(l.mode.name!="xml")return CodeMirror.Pass;var h=n.getOption("autoCloseTags"),y=l.mode.configuration=="html",p=typeof h=="object"&&h.dontCloseTags||y&&i,w=typeof h=="object"&&h.indentTags||y&&r;if(u==">"&&s.tagName){if(f=s.tagName,o.end>e.ch&&(f=f.slice(0,f.length-o.end+e.ch)),a=f.toLowerCase(),o.type=="tag"&&s.type=="closeTag"||o.string.indexOf("/")>-1||p&&t(p,a)>-1)return CodeMirror.Pass;c=w&&t(w,a)>-1,v=c?CodeMirror.Pos(e.line+1,0):CodeMirror.Pos(e.line,e.ch+1),n.replaceSelection(">"+(c?"\n\n":"")+"<\/"+f+">",{head:v,anchor:v}),c&&(n.indentLine(e.line+1),n.indentLine(e.line+2));return}if(u=="/"&&o.string=="<"){f=s.context&&s.context.tagName,f&&n.replaceSelection("/"+f+">","end");return}return CodeMirror.Pass}function t(n,t){if(n.indexOf)return n.indexOf(t);for(var i=0,r=n.length;i'"]=function(t){return n(t,">")}),t.addKeyMap(u)}else!i&&r!=CodeMirror.Init&&r&&t.removeKeyMap("autoCloseTags")});var i=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],r=["applet","blockquote","body","button","div","dl","fieldset","form","frameset","h1","h2","h3","h4","h5","h6","head","html","iframe","layer","legend","object","ol","p","select","table","ul"]}(),function(){function i(n){var e=n.getCursor(),t=n.getTokenAt(e),i=CodeMirror.innerMode(n.getMode(),t.state).mode,r,o,u,f,s;if(t.type=="comment"&&i.blockCommentStart&&(o=t.string.indexOf(i.blockCommentEnd),u=n.getRange(CodeMirror.Pos(e.line,0),CodeMirror.Pos(e.line,t.end)),o==-1||o!=t.string.length-i.blockCommentEnd.length))if(t.string.indexOf(i.blockCommentStart)==0){if(r=u.slice(0,t.start),!/^\s*$/.test(r))for(r="",s=0;st.start&&/^\s*$/.test(u.slice(0,f))&&(r=u.slice(0,f));if(r!=null)n.replaceSelection("\n"+r+i.blockCommentContinue,"end");else return CodeMirror.Pass}for(var t=["clike","css","javascript"],n=0;n"==o)c.push(s);else{if(c.pop()!=l.charAt(0))return{pos:e,match:!1};if(!c.length)return{pos:e,match:!0}}}var f=t.getCursor(),s=t.getLineHandle(f.line),u=f.ch-1,l=u>=0&&i[s.text.charAt(u)]||i[s.text.charAt(++u)],r,e,v;if(!l)return null;var o=l.charAt(1)==">",h=o?1:-1,y=t.getTokenAt(n(f.line,u+1)).type,c=[s.text.charAt(u)],p=/[(){}[\]]/;for(r=f.line,v=o?Math.min(r+100,t.lineCount()):Math.max(-1,r-100);r!=v;r+=h)if(e=r==f.line?a(s,r,u):a(t.getLineHandle(r),r),e)break;return{from:n(f.line,u),to:e&&n(r,e.pos),match:e&&e.match}}function f(t,i){var f=u(t),e;if(f&&!(t.getLine(f.from.line).length>r)&&(!f.to||!(t.getLine(f.to.line).length>r))){var s=f.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket",c=t.markText(f.from,n(f.from.line,f.from.ch+1),{className:s}),h=f.to&&t.markText(f.to,n(f.to.line,f.to.ch+1),{className:s});if(o&&t.state.focused&&t.display.input.focus(),e=function(){t.operation(function(){c.clear(),h&&h.clear()})},i)setTimeout(e,800);else return e}}function e(n){n.operation(function(){t&&(t(),t=null),n.somethingSelected()||(t=f(n,!1))})}var o=/MSIE \d/.test(navigator.userAgent)&&(document.documentMode==null||document.documentMode<8),n=CodeMirror.Pos,r=1e3,i={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"},t=null;CodeMirror.defineOption("matchBrackets",!1,function(n,t){if(t)n.on("cursorActivity",e);else n.off("cursorActivity",e)}),CodeMirror.defineExtension("matchBrackets",function(){f(this,!0)}),CodeMirror.defineExtension("findMatchingBracket",function(){return u(this)})}(),CodeMirror.newFoldFunction=function(n,t){if(t==null&&(t="↔"),typeof t=="string"){var i=document.createTextNode(t);t=document.createElement("span"),t.appendChild(i),t.className="CodeMirror-foldmarker"}return function(i,r){var u,e,o,f,s,h;if(typeof r=="number"&&(r=CodeMirror.Pos(r,0)),u=n(i,r),u){for(e=i.findMarksAt(u.from),o=0,f=0;fs)){v=1,p=n.lineCount();n:for(r=f+1;r=n.lastLine()))return r=0,o=n.getLine(++e),!0}function a(){for(var n,t,i;;){if(n=o.indexOf(">",r),n==-1)if(l())continue;else return;return t=o.lastIndexOf("/",n),i=t>-1&&/^\s*$/.test(o.slice(t+1,n)),r=n+1,i?"selfClose":"regular"}}function v(){for(;;){t.lastIndex=r;var n=t.exec(o);if(!n)if(l())continue;else return;return r=n.index+n[0].length,n}}for(var e=i.line,r=i.ch,o=n.getLine(e),u=[],y,h,c,s;;){if(h=v(),!h||e!=i.line||!(c=a()))return;if(!h[1]&&c!="selfClose"){u.push(h[2]),y=r;break}}for(;;){var f=v(),c,p=e,w=r-(f?f[0].length:0);if(!f||!(c=a()))return;if(c!="selfClose")if(f[1]){for(s=u.length-1;s>=0;--s)if(u[s]==f[2]){u.length=s;break}if(!u.length)return{from:CodeMirror.Pos(i.line,y),to:CodeMirror.Pos(p,w)}}else u.push(f[2])}}}(),function(){CodeMirror.defineExtension("autoFormatAll",function(n,t){function v(){h+="\n",e=!0,++a}for(var r=this,f=r.getMode(),o=r.getRange(n,t).split("\n"),s=CodeMirror.copyState(f,r.getTokenAt(n).state),y=r.getOption("tabSize"),h="",a=0,e=n.ch==0,i,u=0;u",newlineAfterToken:function(t,i,r,u){var f=!1;return this.configuration=="html"&&(f=u.context?n.test(u.context.tagName):!1),!f&&(t=="tag"&&/>$/.test(i)&&u.context||/^-1&&o>-1&&o>e&&(f=f.substr(0,e)+f.substring(e+u.commentStart.length,o)+f.substr(o+u.commentEnd.length)),r.replaceRange(f,t,i)}})}),CodeMirror.defineExtension("autoIndentRange",function(n,t){var i=this;this.operation(function(){for(var r=n.line;r<=t.line;r++)i.indentLine(r,"smart")})}),CodeMirror.defineExtension("autoFormatRange",function(n,t){function v(){h+="\n",e=!0,++a}for(var i=this,f=i.getMode(),o=i.getRange(n,t).split("\n"),s=CodeMirror.copyState(f,i.getTokenAt(n).state),y=i.getOption("tabSize"),h="",a=0,e=n.ch==0,r,u=0;u