upgrade editor.md(many bug exists)

pull/939/head
gsw945 2024-03-27 16:26:01 +08:00
parent 93441cad0e
commit 8c2c69e433
448 changed files with 43080 additions and 16808 deletions

View File

@ -2,12 +2,12 @@
* Editor.md
*
* @file editormd.css
* @version v1.5.0
* @version v1.7.17
* @description Open source online markdown editor.
* @license MIT License
* @author Pandao
* {@link https://github.com/pandao/editor.md}
* @updateTime 2015-06-09
* @author IBM Skills Network
* {@link https://github.com/ibm-skills-network/editor.md}
* @updateTime 2024-03-27
*/
@charset "UTF-8";
@ -47,9 +47,9 @@
.editormd .editormd-markdown-textarea {
display: none;
}
.editormd input[type="text"],
.editormd input[type="button"],
.editormd input[type="submit"],
.editormd input[type=text],
.editormd input[type=button],
.editormd input[type=submit],
.editormd select, .editormd textarea, .editormd button {
-webkit-appearance: none;
-moz-appearance: none;
@ -73,16 +73,11 @@
border-radius: 6px;
}
.editormd ::-webkit-scrollbar-thumb:hover {
-webkit-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25);
/* Webkit browsers */
-moz-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25);
/* Firefox */
-ms-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25);
/* IE9 */
-o-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25);
/* Opera(Old) */
box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25);
/* IE9+, News */
-webkit-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); /* Webkit browsers */
-moz-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); /* Firefox */
-ms-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); /* IE9 */
-o-box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); /* Opera(Old) */
box-shadow: inset 1px 1px 1px rgba(0, 0, 0, 0.25); /* IE9+, News */
background-color: rgba(0, 0, 0, 0.4);
}
@ -148,12 +143,9 @@
-o-border-radius: 2px;
border-radius: 2px;
border: 1px solid #fff;
-webkit-transition: all 300ms ease-out;
/* Safari, Chrome */
-moz-transition: all 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: all 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: all 300ms ease-out; /* Safari, Chrome */
-moz-transition: all 300ms ease-out; /* Firefox 4.0~16.0 */
transition: all 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-menu > li > a:hover, .editormd-menu > li > a.active {
border: 1px solid #ddd;
@ -186,16 +178,11 @@
top: 33px;
left: 0;
z-index: 100;
-webkit-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15);
/* Webkit browsers */
-moz-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15);
/* Firefox */
-ms-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15);
/* IE9 */
-o-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15);
/* Opera(Old) */
box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15);
/* IE9+, News */
-webkit-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); /* Webkit browsers */
-moz-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); /* Firefox */
-ms-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); /* IE9 */
-o-box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); /* Opera(Old) */
box-shadow: 1px 2px 6px rgba(0, 0, 0, 0.15); /* IE9+, News */
}
.editormd-dropdown-menu:before, .editormd-dropdown-menu:after {
width: 0;
@ -222,12 +209,9 @@
}
.editormd-dropdown-menu > li > a:hover {
background: #f6f6f6;
-webkit-transition: all 300ms ease-out;
/* Safari, Chrome */
-moz-transition: all 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: all 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: all 300ms ease-out; /* Safari, Chrome */
-moz-transition: all 300ms ease-out; /* Firefox 4.0~16.0 */
transition: all 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-dropdown-menu > li + li {
border-top: 1px solid #ddd;
@ -256,16 +240,11 @@
-ms-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
/* Webkit browsers */
-moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
/* Firefox */
-ms-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
/* IE9 */
-o-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
/* Opera(Old) */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
/* IE9+, News */
-webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); /* Webkit browsers */
-moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); /* Firefox */
-ms-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); /* IE9 */
-o-box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); /* Opera(Old) */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); /* IE9+, News */
background: #fff;
font-size: 14px;
}
@ -301,12 +280,9 @@
right: 15px;
font-size: 18px;
color: #ccc;
-webkit-transition: color 300ms ease-out;
/* Safari, Chrome */
-moz-transition: color 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: color 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: color 300ms ease-out; /* Safari, Chrome */
-moz-transition: color 300ms ease-out; /* Firefox 4.0~16.0 */
transition: color 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-dialog-close:hover {
color: #999;
@ -315,12 +291,9 @@
.editormd-dialog-header {
padding: 11px 20px;
border-bottom: 1px solid #eee;
-webkit-transition: background 300ms ease-out;
/* Safari, Chrome */
-moz-transition: background 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: background 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background 300ms ease-out; /* Safari, Chrome */
-moz-transition: background 300ms ease-out; /* Firefox 4.0~16.0 */
transition: background 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-dialog-header:hover {
background: #f6f6f6;
@ -385,24 +358,18 @@
.editormd-mask {
position: fixed;
background: #000;
opacity: 0.2;
/* W3C */
filter: alpha(opacity=20);
/* IE */
opacity: 0.2; /* W3C */
filter: alpha(opacity=20); /* IE */
z-index: 99998;
}
.editormd-container-mask,
.editormd-dialog-mask-con {
background: url(../images/loading.gif) no-repeat center center;
-webkit-background-size: 32px 32px;
/* Chrome, iOS, Safari */
-moz-background-size: 32px 32px;
/* Firefox 3.6~4.0 */
-o-background-size: 32px 32px;
/* Opera 9.5 */
background-size: 32px 32px;
/* IE9+, New */
-webkit-background-size: 32px 32px; /* Chrome, iOS, Safari */
-moz-background-size: 32px 32px; /* Firefox 3.6~4.0 */
-o-background-size: 32px 32px; /* Opera 9.5 */
background-size: 32px 32px; /* IE9+, New */
}
.editormd-container-mask {
@ -462,12 +429,9 @@
vertical-align: middle;
border: 1px solid #ddd;
text-decoration: none;
-webkit-transition: background-color 300ms ease-out, color 100ms ease-in;
/* Safari, Chrome */
-moz-transition: background-color 300ms ease-out, color 100ms ease-in;
/* Firefox 4.0~16.0 */
transition: background-color 300ms ease-out, color 100ms ease-in;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background-color 300ms ease-out, color 100ms ease-in; /* Safari, Chrome */
-moz-transition: background-color 300ms ease-out, color 100ms ease-in; /* Firefox 4.0~16.0 */
transition: background-color 300ms ease-out, color 100ms ease-in; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-grid-table-row a.selected {
color: #666;
@ -504,12 +468,9 @@
-o-border-top-right-radius: 3px;
border-top-right-radius: 3px;
background: #f6f6f6;
-webkit-transition: all 300ms ease-out;
/* Safari, Chrome */
-moz-transition: all 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: all 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: all 300ms ease-out; /* Safari, Chrome */
-moz-transition: all 300ms ease-out; /* Firefox 4.0~16.0 */
transition: all 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-tab-head li a:hover {
color: #666;
@ -549,17 +510,17 @@
.editormd-form input:focus {
outline: 0;
}
.editormd-form input[type="text"], .editormd-form input[type="number"] {
.editormd-form input[type=text], .editormd-form input[type=number] {
color: #999;
padding: 8px;
border: 1px solid #ddd;
}
.editormd-form input[type="number"] {
.editormd-form input[type=number] {
width: 40px;
display: inline-block;
padding: 6px 8px;
}
.editormd-form input[type="text"] {
.editormd-form input[type=text] {
display: inline-block;
width: 264px;
}
@ -585,11 +546,11 @@
cursor: pointer;
}
.editormd-form input[type="submit"], .editormd-form .editormd-btn, .editormd-form button,
.editormd-dialog-container input[type="submit"],
.editormd-form input[type=submit], .editormd-form .editormd-btn, .editormd-form button,
.editormd-dialog-container input[type=submit],
.editormd-dialog-container .editormd-btn,
.editormd-dialog-container button,
.editormd-dialog-footer input[type="submit"],
.editormd-dialog-footer input[type=submit],
.editormd-dialog-footer .editormd-btn,
.editormd-dialog-footer button {
color: #666;
@ -603,18 +564,15 @@
-ms-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
-webkit-transition: background 300ms ease-out;
/* Safari, Chrome */
-moz-transition: background 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: background 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background 300ms ease-out; /* Safari, Chrome */
-moz-transition: background 300ms ease-out; /* Firefox 4.0~16.0 */
transition: background 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-form input[type="submit"]:hover, .editormd-form .editormd-btn:hover, .editormd-form button:hover,
.editormd-dialog-container input[type="submit"]:hover,
.editormd-form input[type=submit]:hover, .editormd-form .editormd-btn:hover, .editormd-form button:hover,
.editormd-dialog-container input[type=submit]:hover,
.editormd-dialog-container .editormd-btn:hover,
.editormd-dialog-container button:hover,
.editormd-dialog-footer input[type="submit"]:hover,
.editormd-dialog-footer input[type=submit]:hover,
.editormd-dialog-footer .editormd-btn:hover,
.editormd-dialog-footer button:hover {
background: #eee;
@ -622,7 +580,7 @@
.editormd-form .editormd-btn,
.editormd-dialog-container .editormd-btn,
.editormd-dialog-footer .editormd-btn {
padding: 5px 8px 4px\0;
padding: 5px 8px 4px\0 ;
}
.editormd-form .editormd-btn + .editormd-btn,
.editormd-dialog-container .editormd-btn + .editormd-btn,
@ -637,7 +595,7 @@
position: relative;
display: inline-block;
}
.editormd-file-input input[type="file"] {
.editormd-file-input input[type=file] {
width: 75px;
height: 32px;
opacity: 0;
@ -648,10 +606,10 @@
top: 0;
right: 0;
}
.editormd-file-input input[type="file"]::-webkit-file-upload-button {
.editormd-file-input input[type=file]::-webkit-file-upload-button {
visibility: hidden;
}
.editormd-file-input:hover input[type="submit"] {
.editormd-file-input:hover input[type=submit] {
background: #eee;
}
@ -670,11 +628,12 @@
position: absolute;
top: 35px;
right: 0;
right: -1px\0;
right: -1px\0 ;
overflow: auto;
line-height: 1.6;
display: none;
background: #fff;
z-index: 10;
}
.editormd .CodeMirror {
@ -735,7 +694,7 @@
/* FONT PATH
* -------------------------- */
@font-face {
font-family: 'FontAwesome';
font-family: "FontAwesome";
src: url("../fonts/fontawesome-webfont.eot?v=4.3.0");
src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.3.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff2?v=4.3.0") format("woff2"), url("../fonts/fontawesome-webfont.woff?v=4.3.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.3.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular") format("svg");
font-weight: normal;
@ -802,9 +761,9 @@
}
.fa-border {
padding: .2em .25em .15em;
padding: 0.2em 0.25em 0.15em;
border: solid 0.08em #eeeeee;
border-radius: .1em;
border-radius: 0.1em;
}
.pull-right {
@ -816,11 +775,11 @@
}
.fa.pull-left {
margin-right: .3em;
margin-right: 0.3em;
}
.fa.pull-right {
margin-left: .3em;
margin-left: 0.3em;
}
.fa-spin {
@ -3079,9 +3038,9 @@
/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */
@font-face {
font-family: 'editormd-logo';
font-family: "editormd-logo";
src: url("../fonts/editormd-logo.eot?-5y8q6h");
src: url(".../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg");
src: url("../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg");
font-weight: normal;
font-style: normal;
}
@ -3094,7 +3053,7 @@
.editormd-logo-6x,
.editormd-logo-7x,
.editormd-logo-8x {
font-family: 'editormd-logo';
font-family: "editormd-logo";
speak: none;
font-style: normal;
font-weight: normal;
@ -3233,7 +3192,7 @@
line-height: normal;
}
.markdown-body input[type="checkbox"] {
.markdown-body input[type=checkbox] {
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
@ -3259,7 +3218,7 @@
}
.markdown-body a {
color: #08c;
color: #4183c4;
text-decoration: none;
}
@ -3375,7 +3334,7 @@
}
.markdown-body .octicon-link:before {
content: '\f05c';
content: "\f05c";
}
.markdown-body > *:first-child {
@ -3613,7 +3572,7 @@
.markdown-body code:before,
.markdown-body code:after {
letter-spacing: -0.2em;
content: "\00a0";
content: " ";
}
.markdown-body pre > code {
@ -3636,6 +3595,7 @@
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f7f7f7;
border-radius: 3px;
}
@ -3656,6 +3616,7 @@
overflow: initial;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
@ -3834,36 +3795,12 @@
background-color: #fff;
}
.editormd-preview-container blockquote, .editormd-html-preview blockquote {
color: #2C3E50;
border-left: 5px solid #D6DBDF;
color: #666;
border-left: 4px solid #ddd;
padding-left: 20px;
margin-left: 0;
font-size: 14px;
background: none repeat scroll 0 0 rgba(102,128,153,.05);
margin: 8px 0;
padding: 8px 16px;
}
.editormd-preview-container blockquote.default, .editormd-html-preview blockquote.default {
}
.editormd-preview-container blockquote.info, .editormd-html-preview blockquote.info {
border-left-color: #5bc0de;
color: #5bc0de;
background-color: #f4f8fa
}
.editormd-preview-container blockquote.warning, .editormd-html-preview blockquote.warning {
background-color: #fcf8f2;
border-color: #f0ad4e;
color: #f0ad4e
}
.editormd-preview-container blockquote.danger, .editormd-html-preview blockquote.danger {
color: #d9534f;
background-color: #fdf7f7;
border-color: #d9534f
}
.editormd-preview-container blockquote.success, .editormd-html-preview blockquote.success {
background-color: #f3f8f3;
border-color: #50af51;
color: #50af51
font-style: italic;
}
.editormd-preview-container p code, .editormd-html-preview p code {
margin-left: 5px;
@ -3887,6 +3824,7 @@
}
.editormd-preview-container pre, .editormd-html-preview pre {
border: 1px solid #ddd;
background: #f6f6f6;
padding: 10px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
@ -3932,104 +3870,73 @@
/* SPAN elements with the classes below are added by prettyprint. */
.pln {
color: #000;
}
/* plain text */
} /* plain text */
@media screen {
.str {
color: #080;
}
/* string content */
} /* string content */
.kwd {
color: #008;
}
/* a keyword */
} /* a keyword */
.com {
color: #800;
}
/* a comment */
} /* a comment */
.typ {
color: #606;
}
/* a type name */
} /* a type name */
.lit {
color: #066;
}
/* a literal value */
} /* a literal value */
/* punctuation, lisp open bracket, lisp close bracket */
.pun, .opn, .clo {
color: #660;
}
.tag {
color: #008;
}
/* a markup tag name */
} /* a markup tag name */
.atn {
color: #606;
}
/* a markup attribute name */
} /* a markup attribute name */
.atv {
color: #080;
}
/* a markup attribute value */
} /* a markup attribute value */
.dec, .var {
color: #606;
}
/* a declaration; a variable name */
} /* a declaration; a variable name */
.fun {
color: red;
}
/* a function name */
} /* a function name */
}
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060;
}
.kwd {
color: #006;
font-weight: bold;
}
.com {
color: #600;
font-style: italic;
}
.typ {
color: #404;
font-weight: bold;
}
.lit {
color: #044;
}
.pun, .opn, .clo {
color: #440;
}
.tag {
color: #006;
font-weight: bold;
}
.atn {
color: #404;
}
.atv {
color: #060;
}
@ -4044,9 +3951,7 @@ pre.prettyprint {
ol.linenums {
margin-top: 0;
margin-bottom: 0;
}
/* IE indents via margin-left */
} /* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
@ -4117,16 +4022,11 @@ li.L9 {
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9+, News */
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9+, News */
}
.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul > li ul, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul > li ul {
width: 100%;
@ -4144,12 +4044,9 @@ li.L9 {
color: #666;
padding: 6px 10px;
display: block;
-webkit-transition: background-color 500ms ease-out;
/* Safari, Chrome */
-moz-transition: background-color 500ms ease-out;
/* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background-color 500ms ease-out; /* Safari, Chrome */
-moz-transition: background-color 500ms ease-out; /* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul > li a:hover, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul > li a:hover {
background-color: #f6f6f6;
@ -4162,16 +4059,11 @@ li.L9 {
top: 32px;
left: 10%;
display: none;
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9+, News */
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9+, News */
}
.editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:before, .editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:after, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:before, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:after {
pointer-events: pointer-events;
@ -4214,12 +4106,9 @@ li.L9 {
padding: 5px 10px;
border-radius: 4px;
display: inline-block;
-webkit-transition: background-color 500ms ease-out;
/* Safari, Chrome */
-moz-transition: background-color 500ms ease-out;
/* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background-color 500ms ease-out; /* Safari, Chrome */
-moz-transition: background-color 500ms ease-out; /* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-preview-container .editormd-toc-menu .toc-menu-btn:hover, .editormd-html-preview .editormd-toc-menu .toc-menu-btn:hover {
background-color: #f6f6f6;
@ -4274,12 +4163,9 @@ hr.editormd-page-break {
top: 25px;
right: 35px;
z-index: 19;
-webkit-transition: background-color 300ms ease-out;
/* Safari, Chrome */
-moz-transition: background-color 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: background-color 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background-color 300ms ease-out; /* Safari, Chrome */
-moz-transition: background-color 300ms ease-out; /* Firefox 4.0~16.0 */
transition: background-color 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-preview-close-btn:hover {
background-color: #999;
@ -4382,8 +4268,7 @@ hr.editormd-page-break {
}
@media screen {
.editormd-preview-theme-dark {
/* string content */
.editormd-preview-theme-dark { /* string content */
/* a keyword */
/* a comment */
/* a type name */
@ -4468,4 +4353,4 @@ hr.editormd-page-break {
}
.editormd-theme-dark .CodeMirror {
border-right: 1px solid rgba(0, 0, 0, 0.1);
}
}

View File

@ -2,19 +2,20 @@
* Editor.md
*
* @file editormd.logo.css
* @version v1.5.0
* @version v1.7.17
* @description Open source online markdown editor.
* @license MIT License
* @author Pandao
* {@link https://github.com/pandao/editor.md}
* @updateTime 2015-06-09
* @author IBM Skills Network
* {@link https://github.com/ibm-skills-network/editor.md}
* @updateTime 2024-03-27
*/
@charset "UTF-8";
/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */
@font-face {
font-family: 'editormd-logo';
font-family: "editormd-logo";
src: url("../fonts/editormd-logo.eot?-5y8q6h");
src: url(".../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg");
src: url("../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg");
font-weight: normal;
font-style: normal;
}
@ -27,7 +28,7 @@
.editormd-logo-6x,
.editormd-logo-7x,
.editormd-logo-8x {
font-family: 'editormd-logo';
font-family: "editormd-logo";
speak: none;
font-style: normal;
font-weight: normal;
@ -95,4 +96,4 @@
.editormd-logo-color {
color: #2196F3;
}
}

View File

@ -1,2 +1,2 @@
/*! Editor.md v1.5.0 | editormd.logo.min.css | Open source online markdown editor. | MIT License | By: Pandao | https://github.com/pandao/editor.md | 2015-06-09 */
/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */@font-face{font-family:editormd-logo;src:url(../fonts/editormd-logo.eot?-5y8q6h);src:url(.../fonts/editormd-logo.eot?#iefix-5y8q6h)format("embedded-opentype"),url(../fonts/editormd-logo.woff?-5y8q6h)format("woff"),url(../fonts/editormd-logo.ttf?-5y8q6h)format("truetype"),url(../fonts/editormd-logo.svg?-5y8q6h#icomoon)format("svg");font-weight:400;font-style:normal}.editormd-logo,.editormd-logo-1x,.editormd-logo-2x,.editormd-logo-3x,.editormd-logo-4x,.editormd-logo-5x,.editormd-logo-6x,.editormd-logo-7x,.editormd-logo-8x{font-family:editormd-logo;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;font-size:inherit;line-height:1;display:inline-block;text-rendering:auto;vertical-align:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.editormd-logo-1x:before,.editormd-logo-2x:before,.editormd-logo-3x:before,.editormd-logo-4x:before,.editormd-logo-5x:before,.editormd-logo-6x:before,.editormd-logo-7x:before,.editormd-logo-8x:before,.editormd-logo:before{content:"\e1987"}.editormd-logo-1x{font-size:1em}.editormd-logo-lg{font-size:1.2em}.editormd-logo-2x{font-size:2em}.editormd-logo-3x{font-size:3em}.editormd-logo-4x{font-size:4em}.editormd-logo-5x{font-size:5em}.editormd-logo-6x{font-size:6em}.editormd-logo-7x{font-size:7em}.editormd-logo-8x{font-size:8em}.editormd-logo-color{color:#2196F3}
/*! Editor.md v1.7.17 | editormd.logo.min.css | Open source online markdown editor. | MIT License | By: IBM Skills Network | https://github.com/ibm-skills-network/editor.md | 2024-03-27 */
@charset "UTF-8";/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */@font-face{font-family:editormd-logo;src:url(../fonts/editormd-logo.eot?-5y8q6h);src:url(../fonts/editormd-logo.eot?#iefix-5y8q6h) format("embedded-opentype"),url(../fonts/editormd-logo.woff?-5y8q6h) format("woff"),url(../fonts/editormd-logo.ttf?-5y8q6h) format("truetype"),url(../fonts/editormd-logo.svg?-5y8q6h#icomoon) format("svg");font-weight:400;font-style:normal}.editormd-logo,.editormd-logo-1x,.editormd-logo-2x,.editormd-logo-3x,.editormd-logo-4x,.editormd-logo-5x,.editormd-logo-6x,.editormd-logo-7x,.editormd-logo-8x{font-family:editormd-logo;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;font-size:inherit;line-height:1;display:inline-block;text-rendering:auto;vertical-align:inherit;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.editormd-logo-1x:before,.editormd-logo-2x:before,.editormd-logo-3x:before,.editormd-logo-4x:before,.editormd-logo-5x:before,.editormd-logo-6x:before,.editormd-logo-7x:before,.editormd-logo-8x:before,.editormd-logo:before{content:"󡦇"}.editormd-logo-1x{font-size:1em}.editormd-logo-lg{font-size:1.2em}.editormd-logo-2x{font-size:2em}.editormd-logo-3x{font-size:3em}.editormd-logo-4x{font-size:4em}.editormd-logo-5x{font-size:5em}.editormd-logo-6x{font-size:6em}.editormd-logo-7x{font-size:7em}.editormd-logo-8x{font-size:8em}.editormd-logo-color{color:#2196f3}

File diff suppressed because one or more lines are too long

View File

@ -2,12 +2,12 @@
* Editor.md
*
* @file editormd.preview.css
* @version v1.5.0
* @version v1.7.17
* @description Open source online markdown editor.
* @license MIT License
* @author Pandao
* {@link https://github.com/pandao/editor.md}
* @updateTime 2015-06-09
* @author IBM Skills Network
* {@link https://github.com/ibm-skills-network/editor.md}
* @updateTime 2024-03-27
*/
@charset "UTF-8";
@ -19,7 +19,7 @@
/* FONT PATH
* -------------------------- */
@font-face {
font-family: 'FontAwesome';
font-family: "FontAwesome";
src: url("../fonts/fontawesome-webfont.eot?v=4.3.0");
src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.3.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff2?v=4.3.0") format("woff2"), url("../fonts/fontawesome-webfont.woff?v=4.3.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.3.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.3.0#fontawesomeregular") format("svg");
font-weight: normal;
@ -86,9 +86,9 @@
}
.fa-border {
padding: .2em .25em .15em;
padding: 0.2em 0.25em 0.15em;
border: solid 0.08em #eeeeee;
border-radius: .1em;
border-radius: 0.1em;
}
.pull-right {
@ -100,11 +100,11 @@
}
.fa.pull-left {
margin-right: .3em;
margin-right: 0.3em;
}
.fa.pull-right {
margin-left: .3em;
margin-left: 0.3em;
}
.fa-spin {
@ -2363,9 +2363,9 @@
/*! prefixes.scss v0.1.0 | Author: Pandao | https://github.com/pandao/prefixes.scss | MIT license | Copyright (c) 2015 */
@font-face {
font-family: 'editormd-logo';
font-family: "editormd-logo";
src: url("../fonts/editormd-logo.eot?-5y8q6h");
src: url(".../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg");
src: url("../fonts/editormd-logo.eot?#iefix-5y8q6h") format("embedded-opentype"), url("../fonts/editormd-logo.woff?-5y8q6h") format("woff"), url("../fonts/editormd-logo.ttf?-5y8q6h") format("truetype"), url("../fonts/editormd-logo.svg?-5y8q6h#icomoon") format("svg");
font-weight: normal;
font-style: normal;
}
@ -2378,7 +2378,7 @@
.editormd-logo-6x,
.editormd-logo-7x,
.editormd-logo-8x {
font-family: 'editormd-logo';
font-family: "editormd-logo";
speak: none;
font-style: normal;
font-weight: normal;
@ -2517,7 +2517,7 @@
line-height: normal;
}
.markdown-body input[type="checkbox"] {
.markdown-body input[type=checkbox] {
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 0;
@ -2659,7 +2659,7 @@
}
.markdown-body .octicon-link:before {
content: '\f05c';
content: "\f05c";
}
.markdown-body > *:first-child {
@ -2897,7 +2897,7 @@
.markdown-body code:before,
.markdown-body code:after {
letter-spacing: -0.2em;
content: "\00a0";
content: " ";
}
.markdown-body pre > code {
@ -2920,6 +2920,7 @@
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f7f7f7;
border-radius: 3px;
}
@ -2940,6 +2941,7 @@
overflow: initial;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
@ -3111,17 +3113,19 @@
.editormd-preview-container, .editormd-html-preview {
text-align: left;
font-size: 14px;
line-height: 1.6;
padding: 20px;
overflow: auto;
width: 100%;
line-height: 1.6em;
background-color: #fff;
}
.editormd-preview-container blockquote, .editormd-html-preview blockquote {
color: #2C3E50;
border-left: 4px solid #D6DBDF;
color: #666;
border-left: 4px solid #ddd;
padding-left: 20px;
margin-left: 0;
font-size: 14px;
background: none repeat scroll 0 0 rgba(102,128,153,.05);
margin: 8px 0;
padding: 8px 16px;
font-style: italic;
}
.editormd-preview-container p code, .editormd-html-preview p code {
margin-left: 5px;
@ -3145,6 +3149,7 @@
}
.editormd-preview-container pre, .editormd-html-preview pre {
border: 1px solid #ddd;
background: #f6f6f6;
padding: 10px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
@ -3186,129 +3191,77 @@
font-family: "YaHei Consolas Hybrid", Consolas, "Microsoft YaHei", "Malgun Gothic", "Segoe UI", Helvetica, Arial !important;
}
.editormd-preview-container blockquote.info, .editormd-html-preview blockquote.info {
border-left-color: #5bc0de;
color: #5bc0de;
background-color: #f4f8fa
}
.editormd-preview-container blockquote.warning, .editormd-html-preview blockquote.warning {
background-color: #fcf8f2;
border-color: #f0ad4e;
color: #f0ad4e
}
.editormd-preview-container blockquote.danger, .editormd-html-preview blockquote.danger {
color: #d9534f;
background-color: #fdf7f7;
border-color: #d9534f
}
.editormd-preview-container blockquote.success, .editormd-html-preview blockquote.success {
background-color: #f3f8f3;
border-color: #50af51;
color: #50af51
}
/*! Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
.pln {
color: #000;
}
/* plain text */
} /* plain text */
@media screen {
.str {
color: #080;
}
/* string content */
} /* string content */
.kwd {
color: #008;
}
/* a keyword */
} /* a keyword */
.com {
color: #800;
}
/* a comment */
} /* a comment */
.typ {
color: #606;
}
/* a type name */
} /* a type name */
.lit {
color: #066;
}
/* a literal value */
} /* a literal value */
/* punctuation, lisp open bracket, lisp close bracket */
.pun, .opn, .clo {
color: #660;
}
.tag {
color: #008;
}
/* a markup tag name */
} /* a markup tag name */
.atn {
color: #606;
}
/* a markup attribute name */
} /* a markup attribute name */
.atv {
color: #080;
}
/* a markup attribute value */
} /* a markup attribute value */
.dec, .var {
color: #606;
}
/* a declaration; a variable name */
} /* a declaration; a variable name */
.fun {
color: red;
}
/* a function name */
} /* a function name */
}
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060;
}
.kwd {
color: #006;
font-weight: bold;
}
.com {
color: #600;
font-style: italic;
}
.typ {
color: #404;
font-weight: bold;
}
.lit {
color: #044;
}
.pun, .opn, .clo {
color: #440;
}
.tag {
color: #006;
font-weight: bold;
}
.atn {
color: #404;
}
.atv {
color: #060;
}
@ -3323,9 +3276,7 @@ pre.prettyprint {
ol.linenums {
margin-top: 0;
margin-bottom: 0;
}
/* IE indents via margin-left */
} /* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
@ -3396,16 +3347,11 @@ li.L9 {
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9+, News */
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9+, News */
}
.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul > li ul, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul > li ul {
width: 100%;
@ -3423,12 +3369,9 @@ li.L9 {
color: #666;
padding: 6px 10px;
display: block;
-webkit-transition: background-color 500ms ease-out;
/* Safari, Chrome */
-moz-transition: background-color 500ms ease-out;
/* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background-color 500ms ease-out; /* Safari, Chrome */
-moz-transition: background-color 500ms ease-out; /* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-preview-container .editormd-toc-menu > .markdown-toc > ul > li a:hover, .editormd-html-preview .editormd-toc-menu > .markdown-toc > ul > li a:hover {
background-color: #f6f6f6;
@ -3441,16 +3384,11 @@ li.L9 {
top: 32px;
left: 10%;
display: none;
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2);
/* IE9+, News */
-webkit-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Webkit browsers */
-moz-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Firefox */
-ms-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9 */
-o-box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* Opera(Old) */
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.2); /* IE9+, News */
}
.editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:before, .editormd-preview-container .editormd-toc-menu > .markdown-toc li > ul:after, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:before, .editormd-html-preview .editormd-toc-menu > .markdown-toc li > ul:after {
pointer-events: pointer-events;
@ -3493,12 +3431,9 @@ li.L9 {
padding: 5px 10px;
border-radius: 4px;
display: inline-block;
-webkit-transition: background-color 500ms ease-out;
/* Safari, Chrome */
-moz-transition: background-color 500ms ease-out;
/* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background-color 500ms ease-out; /* Safari, Chrome */
-moz-transition: background-color 500ms ease-out; /* Firefox 4.0~16.0 */
transition: background-color 500ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-preview-container .editormd-toc-menu .toc-menu-btn:hover, .editormd-html-preview .editormd-toc-menu .toc-menu-btn:hover {
background-color: #f6f6f6;
@ -3553,12 +3488,9 @@ hr.editormd-page-break {
top: 25px;
right: 35px;
z-index: 19;
-webkit-transition: background-color 300ms ease-out;
/* Safari, Chrome */
-moz-transition: background-color 300ms ease-out;
/* Firefox 4.0~16.0 */
transition: background-color 300ms ease-out;
/* IE >9, FF >15, Opera >12.0 */
-webkit-transition: background-color 300ms ease-out; /* Safari, Chrome */
-moz-transition: background-color 300ms ease-out; /* Firefox 4.0~16.0 */
transition: background-color 300ms ease-out; /* IE >9, FF >15, Opera >12.0 */
}
.editormd-preview-close-btn:hover {
background-color: #999;
@ -3567,4 +3499,4 @@ hr.editormd-page-break {
.editormd-preview-active {
width: 100%;
padding: 40px;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -5,8 +5,8 @@
description : "Open source online Markdown editor.",
tocTitle : "Table of Contents",
toolbar : {
undo : "Undo(Ctrl+Z)",
redo : "Redo(Ctrl+Y)",
undo : "Undo",
redo : "Redo",
bold : "Bold",
del : "Strikethrough",
italic : "Italic",
@ -22,13 +22,13 @@
h6 : "Heading 6",
"list-ul" : "Unordered list",
"list-ol" : "Ordered list",
hr : "Horizontal rule",
hr : "Horizontal line",
link : "Link",
"reference-link" : "Reference link",
image : "Image",
code : "Code inline",
code : "Inline code",
"preformatted-text" : "Preformatted text / Code block (Tab indent)",
"code-block" : "Code block (Multi-languages)",
"code-block" : "Code block",
table : "Tables",
datetime : "Datetime",
emoji : "Emoji",
@ -76,16 +76,18 @@
formatNotAllowed : "Error: only allows to upload pictures file, upload allowed image file format:"
},
preformattedText : {
title : "Preformatted text / Codes",
emptyAlert : "Error: Please fill in the Preformatted text or content of the codes."
title : "Preformatted text / Codes",
emptyAlert : "Error: Please fill in the Preformatted text or content of the codes.",
placeholder : "coding now...."
},
codeBlock : {
title : "Code block",
title : "Code block",
selectLabel : "Languages: ",
selectDefaultText : "select a code language...",
otherLanguage : "Other languages",
unselectedLanguageAlert : "Error: Please select the code language.",
codeEmptyAlert : "Error: Please fill in the code content."
codeEmptyAlert : "Error: Please fill in the code content.",
placeholder : "coding now...."
},
htmlEntities : {
title : "HTML Entities"
@ -95,13 +97,13 @@
}
}
};
exports.defaults.lang = lang;
};
// CommonJS/Node.js
if (typeof require === "function" && typeof exports === "object" && typeof module === "object")
{
{
module.exports = factory;
}
else if (typeof define === "function") // AMD/CMD/Sea.js
@ -118,10 +120,10 @@
factory(editormd);
});
}
}
}
else
{
factory(window.editormd);
}
})();
})();

View File

@ -77,7 +77,8 @@
},
preformattedText : {
title : "添加預格式文本或代碼塊",
emptyAlert : "錯誤:請填寫預格式文本或代碼的內容。"
emptyAlert : "錯誤:請填寫預格式文本或代碼的內容。",
placeholder : "coding now...."
},
codeBlock : {
title : "添加代碼塊",
@ -85,7 +86,8 @@
selectDefaultText : "請語言代碼語言",
otherLanguage : "其他語言",
unselectedLanguageAlert : "錯誤:請選擇代碼所屬的語言類型。",
codeEmptyAlert : "錯誤:請填寫代碼內容。"
codeEmptyAlert : "錯誤:請填寫代碼內容。",
placeholder : "coding now...."
},
htmlEntities : {
title : "HTML實體字符"
@ -124,4 +126,4 @@
factory(window.editormd);
}
})();
})();

View File

@ -1,30 +1,51 @@
List of CodeMirror contributors. Updated before every release.
4oo4
4r2r
Aaron Brooks
Abdelouahab
Abdussalam Abdurrahman
Abe Fettig
Abhishek Gahlot
Adam Ahmed
Adam King
Adam Particka
Adam Wight
adanlobato
Adán Lobato
Aditya Toshniwal
Adrian Aichner
Adrian Heine
Adrian Kunz
Adrien Bertrand
aeroson
Ahmad Amireh
Ahmad M. Zawawi
AHOHNMYC
ahoward
Ajin Abraham
Akeksandr Motsjonov
Alasdair Smith
AlbertHilb
Alberto González Palomo
Alberto Pose
Albert Xing
Alexander Marks
Alexander Pavlov
Alexander Schepanovski
Alexander Shvets
Alexander Solovyov
Alexandre Bique
Alex Churchill
alexey-k
Alex Piggott
Alf Eaton
Aliaksei Chapyzhenka
Allen Sarkisyan
Ami Fischman
Amin Shali
Amin Ullah Khan
amshali@google.com
Amsul
amuntean
Amy
@ -33,62 +54,142 @@ anaran
AndersMad
Anders Nawroth
Anderson Mesquita
Anders Wåglund
Andrea G
Andreas Reischuck
Andres Taylor
Andre von Houck
Andrew Cheng
Andrew Dassonville
Andrey Fedorov
Andrey Klyuchnikov
Andrey Lushnikov
Andrey Shchekin
Andy Joslin
Andy Kimball
Andy Li
Angelo
angelozerr
angelo.zerr@gmail.com
Ankit
Ankit Ahuja
Ansel Santosa
Anthony Dugois
anthonygego
Anthony Gégo
Anthony Grimes
Anthony Stewart
Anton Kovalyov
antosarho
aoki ken
Apollo Zhu
AQNOUCH Mohammed
Aram Shatakhtsyan
areos
Arnab Bose
Arnoud Buzing
Arsène von Wyss
Arthur Müller
Arun Narasani
as3boyan
asolove
atelierbram
AtomicPages LLC
Atul Bhouraskar
Aurelian Oancea
Axel Lewenhaupt
Baptiste Augrain
Barret Rennie
Bartosz Dziewoński
Basarat Ali Syed
Bastian Müller
belhaj
Bem Jones-Bey
benbro
Benedikt Meurer
benhormann
Ben Hormann
Beni Cherniavsky-Paskin
Benjamin DeCoste
Benjamin Young
Ben Keen
Ben Miller
Ben Mosher
Bernhard Sirlinger
Bert Chang
Bharad
BigBlueHat
Billiam
Billy Moon
Bin Ni
binny
Bjorn Hansen
B Krishna Chaitanya
Blaine G
blukat29
Bo
boomyjee
Bo Peng
borawjm
Boris K
Brad Metcalf
Brandon Frohs
Brandon Wamboldt
Bret Little
Brett Zamir
Brian Grinstead
BrianHung
Brian Sletten
brrd
Bruce Mitchener
Bruno Logerfo
Bryan Gin-ge Chen
Bryan Massoth
Caitlin Potter
Calin Barbat
callodacity
Camilo Roca
Casey Klebba
cBiscuit87
César González Íñiguez
Chad Jolly
Chandra Sekhar Pydi
Charles Skelton
Cheah Chu Yeow
Chhekur
Chris Colborne
Chris Coyier
Chris Ford
Chris Granger
Chris Houseknecht
Chris Lohfink
Chris Morgan
Chris Reeves
Chris Smith
Christian Gruen
Christian Oyarzun
Christian Petrov
Christian Sonne
christopherblaser
Christopher Brown
Christopher Kramer
Christopher Mitchell
Christopher Pfohl
Christopher Wallis
Chunliang Lyu
ciaranj
clone-it
clso
CodeAnimal
CodeBitt
coderaiser
Cole R Lawrence
ComFreek
Cornelius Weig
Cristian Prieto
Curran Kelleher
Curtis Gagliardi
d8888
dagsta
daines
Dale Jung
@ -97,38 +198,74 @@ Dan Heberden
Daniel, Dao Quang Minh
Daniele Di Sarli
Daniel Faust
Daniel Hanggi
Daniel Huigens
Daniel Kesler
Daniel KJ
Daniel Neel
Daniel Parnell
Daniel Thwaites
Danila Malyutin
Danny Yoo
darealshinji
Darius Roberts
databricks-david-lewis
Dave Brondsema
Dave MacLachlan
Dave Myers
David Barnett
David H. Bronke
David Mignot
David Pathakjee
David R. Myers
David Rodrigues
David Santana
David Vázquez
David Whittington
deebugger
Deep Thought
Denis Ovsienko
Devin Abbott
Devon Carew
Dick Choi
Diego Fernandez
dignifiedquire
Dimage Sapelkin
Dimitri Mitropoulos
Dinindu D. Wanniarachchi
dmaclach
Dmitry Kiselyov
domagoj412
Dominator008
Domizio Demichelis
Doug Blank
Doug Wikle
Drew Bratcher
Drew Hintz
Drew Khoury
Drini Cami
Dror BG
Duncan Lilley
duralog
dwelle
Ealton
eborden
edoroshenko
edsharp
ekhaled
Elisée
Elmar Peise
elpnt
Emmanuel Schanzer
Enam Mijbah Noor
Eric Allam
Eric Bogard
Erik Demaine
Erik Welander
erosman
eustas
Evan Minsk
Fabien Dubosson
Fabien O'Carroll
Fabio Zendhi Nagao
Faiza Alsaied
@ -136,130 +273,281 @@ Fauntleroy
fbuchinger
feizhang365
Felipe Lalanne
Felipe S. S. Schneider
Felix Raab
ficristo
Filip Noetzel
Filip Stollár
Filype Pereira
finalfantasia
flack
ForbesLindesay
Florian Felten
Fons van der Plas
Forbes Lindesay
ForbesLindesay
Ford_Lawnmower
Forrest Oliphant
Franco Catena
Frank Seifferth
Frank Wiegand
fraxx001
Fredrik Borg
FUJI Goro (gfx)
Gabriel Gheorghian
Gabriel Horner
Gabriel Nahmias
galambalazs
Gary Sheng
Gautam Mehta
Gavin Douglas
gekkoe
Geordie Hall
George Stephanis
geowarin
Gerard Braad
Gergely Hegykozi
Germain Chazot
Giovanni Calò
Glebov Boris
Glenn Jorde
Glenn Ruehle
goldsmcb
Golevka
Google LLC
Gordon Smith
Grant Skinner
greengiant
Gregory Koberger
Grzegorz Mazur
Guang Li
Guan Gui
Guillaume Massé
Guillaume Massé
guraga
Gustavo Rodrigues
Hakan Tunc
Hanno Fellmann
Hans Engel
Hanzhao Deng
Haoran Yu
Harald Schilly
Hardest
Harshvardhan Gupta
Hasan Delibaş
Hasan Karahan
Heanes
Hector Oswaldo Caballero
Hein Htat
Hélio
Hendrik Erz
Hendrik Wallbaum
Henrik Haugbølle
Herculano Campos
hidaiy
Hiroyuki Makino
hitsthings
Hocdoc
Howard
Howard Jing
Hugues Malphettes
Ian Beck
Ian Davies
Ian Dickinson
Ian Henderson
ianhi
Ian Rose
Ian Wehrman
Ian Wetherbee
Ice White
ICHIKAWA, Yuji
idleberg
Igor Petruk
ilvalle
Ilya Kharlamov
Ilya Zverev
Ingo Richter
Intervue
Irakli Gozalishvili
iteriani
Ivan Kurnosov
Ivoah
Jack Douglas
Jacob Lee
Jaimin
Jake Peyser
Jake Zimmerman
Jakob Kummerow
Jakob Miland
Jakub T. Jankiewicz
Jakub Vrana
Jakub Vrána
James Campos
James Cockshull
James Howard
James Thorne
Jamie Hill
Jamie Morris
Janice Leung
Jan Jongboom
jankeromnes
Jan Keromnes
Jan Odvarko
Jan Schär
Jan T. Sott
Jared Dean
Jared Forsyth
Jared Jacobs
Jason
Jason Barnabe
Jason Grout
Jason Heeris
Jason Johnston
Jason San Jose
Jason Siefken
Jayaprabhakar
Jay Contonio
Jaydeep Solanki
Jean Boussier
Jeff Blaisdell
Jeff Hanke
Jeff Jenkins
jeffkenton
Jeff Pickhardt
jem (graphite)
Jeremy Parmenter
Jim
Jim Avery
jkaplon
JobJob
jochenberger
Jochen Berger
Joel Einbinder
joelpinheiro
Joe Predham
joewalsh
Johan Ask
Johannes
John Chen
John Connor
John-David Dalton
John Engler
John Lees-Miller
John Ryan
John Snelson
johnspiegel
John Van Der Loo
Jon Ander Peñalba
Jonas Döbertin
Jonas Helfer
Jonathan Dierksen
Jonathan Hart
Jonathan Malmaud
Jonathan Rascher
Jon Gacnik
jongalloway
Jon Malmaud
Jon Sangster
Joo
Joost-Wim Boekesteijn
José dBruxelles
Joseph Pecoraro
Josh Barnes
Josh Cohen
Josh Soref
Joshua Newman
Josh Watzman
jots
Joy Zhong
jsoojeon
ju1ius
Juan Benavides Romero
Jucovschi Constantin
Juho Vuori
Julien CROUZET
Julien Rebetez
Justin Andresen
Justin Hileman
jwallers@gmail.com
kaniga
karevn
Karol
Kaushik Kulkarni
Kayur Patel
Kazuhisa Ishizaka
Kazuhito Hokamura
kcwiakala
Kees de Kooter
Keldan Chapman
Kenan Christian Dimas
Ken Newman
ken restivo
Ken Rockot
Kevin Earls
Kevin Kwok
Kevin Muret
Kevin Sawicki
Kevin Ushey
Kier Darby
Kim-Anh Tran
Klaus Silveira
Koh Zi Han, Cliff
komakino
Konstantin Chernenko
Konstantin Lopuhin
koops
Kris Ciccarello
ks-ifware
kubelsmieci
kvncp
KwanEsq
Kyle Kelley
KyleMcNutt
LaKing
Lanfei
Lanny
laobubu
Laszlo Vidacs
leaf
leaf corcoran
Lemmon
Leo Baschy
Leonid Khachaturov
Leon Sorokin
Leonya Khachaturov
lexer2086
Liam Newman
Libo Cannici
Lior Goldberg
Lior Shub
lishid
LloydMilligan
LM
lochel
Lonnie Abelbeck
Lorenzo Simionato
Lorenzo Stoakes
Louis Mauchet
Luca Fabbri
Lucas Buchala
Luciano Longo
Luciano Santana
Lu Fangjian
Łukasz Wielgus
Luke Browning
Luke Granger-Brown
Luke Stagner
lynschinzer
M1cha
Madhura Jayaratne
Maksim Lin
Maksym Taran
Malay Majithia
Manideep
Manuel Rego Casasnovas
Marat Dreizin
Marcel Gerber
Marcelo Camargo
Marc Espín
Marco Aurélio
Marco Munizaga
Marcus Bointon
@ -267,18 +555,38 @@ Marek Rudnicki
Marijn Haverbeke
Mário Gonçalves
Mario Pietsch
Mark Anderson
Mark Boyes
Mark Dalgleish
Mark Hamstra
Mark Lentczner
Marko Bonaci
Mark Peace
Markus Bordihn
Markus Olsson
Martin Balek
Martín Gaitán
Martin Hasoň
Martin Hunt
Martin Laine
Martin Zagora
Masahiro MATAYOSHI
Mason Malone
Mateusz Paprocki
Mathias Bynens
mats cronqvist
Matt Diehl
Matt Gaide
Matthew Bauer
Matthew Beale
Matthew Casperson
matthewhayes
Matthew Rathbone
Matthew Suozzo
Matthias Bussonnier
Matthias BUSSONNIER
Mattia Astorino
Matt MacPherson
Matt McDonald
Matt Pass
Matt Sacks
@ -286,151 +594,362 @@ mauricio
Maximilian Hils
Maxim Kraev
Max Kirsch
Max Schaefer
Max Wu
Max Xiantu
mbarkhau
McBrainy
mce2
Mélanie Chauvel
melpon
meshuamam
Metatheos
Micah Dubinko
Michael
Michael Chirico
Michael Goderbauer
Michael Grey
Michael Kaminsky
Michael Lehenbauer
Michael Wadman
Michael Walker
Michael Zhou
Michal Čihař
Michal Dorner
Michal Kapiczynski
Mighty Guava
Miguel Castillo
mihailik
Mika Andrianarijaona
Mike
Mike Bostock
Mike Brevoort
Mike Diaz
Mike Ivanov
Mike Kadin
Mike Kobit
Milan Szekely
MinJune Kim
MinRK
Miraculix87
misfo
mkaminsky11
mloginov
mlsad3
Moritz Schubotz (physikerwelt)
Moritz Schwörer
Moshe Wajnberg
mps
ms
mtaran-google
Mu-An ✌️ Chiou
Mu-An Chiou
Mykola Martynovets
mzabuawala
Narciso Jaramillo
nathanlesage
Nathan Williams
ndr
Neil Anderson
neon-dev
nerbert
NetworkNode
nextrevision
ngn
nguillaumin
Ng Zhi An
Nicholas Bollweg
Nicholas Bollweg (Nick)
NickKolok
Nick Kreeger
Nick Small
Nicolas Chevobbe
Nicolas Kick
Nicolò Ribaudo
Niels van Groningen
nightwing
Nikita Beloglazov
Nikita Vasilyev
Nikolaj Kappler
Nikolay Kostov
nilp0inter
Nils Knappmeier
Nina Pypchenko
Nisarg Jhaveri
nlwillia
noragrossman
Norman Rzepka
Nouzbe
Oleksandr Yakovenko
Olivia Ytterbrink
Ondřej Mirtes
Opender Singh
opl-
Oreoluwa Onatemowo
orionlee
oscar.lofwenhamn
Oskar Segersvärd
ossdev
overdodactyl
pablo
pabloferz
Pablo Zubieta
paddya
Page
paladox
Panupong Pasupat
paris
Paris
Paris Kasidiaris
Patil Arpith
Patrick Kettner
Patrick Stoica
Patrick Strawderman
Paul Garvin
Paul Ivanov
Paul Masson
Paul Schmidt
Pavel
Pavel Feldman
Pavel Petržela
Pavel Strashkin
Paweł Bartkiewicz
peteguhl
peter
Peter Flynn
peterkroon
Peter Kroon
Peter László
Phil DeJarnett
Philipp A
Philipp Markovics
Philip Stadermann
Pi Delport
Pierre Gerold
Pieter Ouwerkerk
Piyush
Pontus Melke
prasanthj
Prasanth J
Prayag Verma
prendota
Prendota
ps173
Qiang Li
quiddity-wp
Radek Piórkowski
Rahul
Rahul Anand
ramwin1
Randall Mason
Randy Burden
Randy Edmunds
Randy Luecke
Raphael Amorim
Rasmus Erik Voel Jensen
Rasmus Schultz
raymondf
Raymond Hill
ray ratchup
Ray Ratchup
Remi Nyborg
Renaud Durlin
Reynold Xin
Richard Denton
Richard van der Meer
Richard Z.H. Wang
Rishi Goomar
Robert Brignull
Robert Crossfield
Robert Martin
Roberto Abdelkader Martínez Pérez
robertop23
Roberto Vidal
Robert Plummer
Roman Frolov
Roman Janusz
Rongjian Zhang
Rrandom
Rrrandom
Ruslan Bekenev
Ruslan Osmanov
rvalavicius
Ryan Pangrle
Ryan Petrello
Ryan Prior
ryu-sato
sabaca
Sachin Gupta
Sam Lee
Sam Rawlins
Samuel Ainsworth
Sam Wilson
sandeepshetty
Sander AKA Redsandro
Sander Verweij
santec
Sarah McAlear and Wenlin Zhang
Sascha Peilicke
Sasha Varlamov
satamas
satchmorun
sathyamoorthi
Saul Costa
S. Chris Colbert
SCLINIC\jdecker
Scott Aikin
Scott Feeney
Scott Goodhew
Seb35
Sebastian Ślepowroński
Sebastian Wilzbach
Sebastian Zaha
Seren D
Sergey Goder
Sergey Tselovalnikov
Se-Won Kim
Shane Liesegang
shaund
shaun gilchrist
Shawn A
Shea Bunge
sheopory
Shil S
Shiv Deepak
Shmuel Englard
Shubham Jain
Siamak Mokhtari
Siddhartha Gunti
silverwind
Simon Edwards
Simon Huber
sinkuu
Slava Rozhnev
snasa
soliton4
sonson
Sorab Bisht
spastorelli
srajanpaliwal
Stanislav Oaserele
stan-z
Stas Kobzar
stasoid
Stefan Borsje
Steffen Beyer
Steffen Bruchmann
Steffen Kowalski
Stephane Moore
Stephen Lavelle
Steve Champagne
Steve Hoover
Steven Yung
Steve O'Hara
stockiNail
stoskov
Stryder Crown
Stu Kennedy
Sungho Kim
sverweij
Taha Jahangir
takamori
Tako Schotanus
Takuji Shimokawa
Takuya Matsuyama
Tarmil
T. Brandon Ashley
TDaglis
Teja
tel
Tentone
tfjgeorge
Thaddee Tyl
thanasis
TheHowl
themrmax
Thiemo Kreuz
think
Thomas Brouard
Thomas Dvornik
Thomas Kluyver
thomasmaclean
Thomas Schmid
Tim Alby
Tim Baumann
Tim Gates
Tim Nguyen
Timothy Farrell
Timothy Gu
Timothy Hatcher
Tim van der Lippe
Tobias Bertelsen
TobiasBg
Todd Berman
Todd Kennedy
tokafew420
Tomas-A
Tomas Varaneckas
Tom Erik Støwer
Tom Klancer
Tom MacWright
Tom McLaughlin
Tony Jian
tophf
Torben Bundt
Torgeir Thoresen
totalamd
Travis Heppe
Triangle717
Tristan Tarrant
TSUYUSATO Kitsune
Tugrul Elmas
twifkak
Tyler Long
Tyler Makaro
Vadim Dyachenko
Vadzim Ramanenka
Vaibhav Sagar
vamshi.revu
VapidWorx
Vestimir Markov
vf
Victor Bocharsky
Vincent Woo
Volker Mische
vtripolitakis
wdouglashall
Weiyan Shao
wenli
Wes Cossick
Wesley Wiser
Weston Ruter
Will Binns-Smith
Will Cassella
Will Dean
Will Hernandez
William Desportes
William Jamieson
William Stein
Willy
Wojtek Ptak
wonderboyjon
Wu Cheng-Han
Xavier Mendez
Yang Guo
Yash Singh
Yash-Singh1
Yassin N. Hassan
YNH Webdev
yoongu
Yunchi Luo
Yuvi Panda
Yvonnick Esnault
Zac Anger
Zachary Dremann
ZeeshanNoor
Zeno Rocha
Zhang Hao
Ziv
zoobestik
zziuni
魏鹏刚

View File

@ -1,4 +1,6 @@
Copyright (C) 2014 by Marijn Haverbeke <marijnh@gmail.com> and others
MIT License
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,12 +1,47 @@
# CodeMirror
[![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)
[![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)
[Funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png)](https://marijnhaverbeke.nl/fund/)
CodeMirror is a JavaScript component that provides a code editor in
the browser. When a mode is available for the language you are coding
in, it will color your code, and optionally help with indentation.
[![Build Status](https://github.com/codemirror/codemirror/workflows/main/badge.svg)](https://github.com/codemirror/codemirror/actions)
[![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)
The project page is http://codemirror.net
The manual is at http://codemirror.net/doc/manual.html
The contributing guidelines are in [CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
CodeMirror is a versatile text editor implemented in JavaScript for
the browser. It is specialized for editing code, and comes with over
100 language modes and various addons that implement more advanced
editing functionality. Every language comes with fully-featured code
and syntax highlighting to help with reading and editing complex code.
A rich programming API and a CSS theming system are available for
customizing CodeMirror to fit your application, and extending it with
new functionality.
You can find more information (and the
[manual](https://codemirror.net/doc/manual.html)) on the [project
page](https://codemirror.net). For questions and discussion, use the
[discussion forum](https://discuss.codemirror.net/).
See
[CONTRIBUTING.md](https://github.com/codemirror/CodeMirror/blob/master/CONTRIBUTING.md)
for contributing guidelines.
The CodeMirror community aims to be welcoming to everybody. We use the
[Contributor Covenant
(1.1)](http://contributor-covenant.org/version/1/1/0/) as our code of
conduct.
### Installation
Either get the [zip file](https://codemirror.net/codemirror.zip) with
the latest version, or make sure you have [Node](https://nodejs.org/)
installed and run:
npm install codemirror
**NOTE**: This is the source repository for the library, and not the
distribution channel. Cloning it is not the recommended way to install
the library, and will in fact not work unless you also run the build
step.
### Quickstart
To build the project, make sure you have Node.js installed (at least version 6)
and then `npm install`. To run, just open `index.html` in your
browser (you don't need to run a webserver). Run the tests with `npm test`.

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -13,7 +13,7 @@
var noOptions = {};
var nonWS = /[^\s\u00a0]/;
var Pos = CodeMirror.Pos;
var Pos = CodeMirror.Pos, cmp = CodeMirror.cmpPos;
function firstNonWS(str) {
var found = str.search(nonWS);
@ -21,26 +21,45 @@
}
CodeMirror.commands.toggleComment = function(cm) {
var minLine = Infinity, ranges = cm.listSelections(), mode = null;
cm.toggleComment();
};
CodeMirror.defineExtension("toggleComment", function(options) {
if (!options) options = noOptions;
var cm = this;
var minLine = Infinity, ranges = this.listSelections(), mode = null;
for (var i = ranges.length - 1; i >= 0; i--) {
var from = ranges[i].from(), to = ranges[i].to();
if (from.line >= minLine) continue;
if (to.line >= minLine) to = Pos(minLine, 0);
minLine = from.line;
if (mode == null) {
if (cm.uncomment(from, to)) mode = "un";
else { cm.lineComment(from, to); mode = "line"; }
if (cm.uncomment(from, to, options)) mode = "un";
else { cm.lineComment(from, to, options); mode = "line"; }
} else if (mode == "un") {
cm.uncomment(from, to);
cm.uncomment(from, to, options);
} else {
cm.lineComment(from, to);
cm.lineComment(from, to, options);
}
}
};
});
// Rough heuristic to try and detect lines that are part of multi-line string
function probablyInsideString(cm, pos, line) {
return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
}
function getMode(cm, pos) {
var mode = cm.getMode()
return mode.useInnerComments === false || !mode.innerMode ? mode : cm.getModeAt(pos)
}
CodeMirror.defineExtension("lineComment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from);
var self = this, mode = getMode(self, from);
var firstLine = self.getLine(from.line);
if (firstLine == null || probablyInsideString(self, from, firstLine)) return;
var commentString = options.lineComment || mode.lineComment;
if (!commentString) {
if (options.blockCommentStart || mode.blockCommentStart) {
@ -49,15 +68,21 @@
}
return;
}
var firstLine = self.getLine(from.line);
if (firstLine == null) return;
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1);
var pad = options.padding == null ? " " : options.padding;
var blankLines = options.commentBlankLines || from.line == to.line;
self.operation(function() {
if (options.indent) {
var baseString = firstLine.slice(0, firstNonWS(firstLine));
var baseString = null;
for (var i = from.line; i < end; ++i) {
var line = self.getLine(i);
var whitespace = line.slice(0, firstNonWS(line));
if (baseString == null || baseString.length > whitespace.length) {
baseString = whitespace;
}
}
for (var i = from.line; i < end; ++i) {
var line = self.getLine(i), cut = baseString.length;
if (!blankLines && !nonWS.test(line)) continue;
@ -75,7 +100,7 @@
CodeMirror.defineExtension("blockComment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from);
var self = this, mode = getMode(self, from);
var startString = options.blockCommentStart || mode.blockCommentStart;
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) {
@ -83,6 +108,7 @@
self.lineComment(from, to, options);
return;
}
if (/\bcomment\b/.test(self.getTokenTypeAt(Pos(from.line, 0)))) return
var end = Math.min(to.line, self.lastLine());
if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end;
@ -100,7 +126,9 @@
if (i != end || lastLineHasText)
self.replaceRange(lead + pad, Pos(i, 0));
} else {
var atCursor = cmp(self.getCursor("to"), to) == 0, empty = !self.somethingSelected()
self.replaceRange(endString, to);
if (atCursor) self.setSelection(empty ? to : self.getCursor("from"), to)
self.replaceRange(startString, from);
}
});
@ -108,7 +136,7 @@
CodeMirror.defineExtension("uncomment", function(from, to, options) {
if (!options) options = noOptions;
var self = this, mode = self.getModeAt(from);
var self = this, mode = getMode(self, from);
var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end);
// Try finding line comments
@ -120,7 +148,7 @@
var line = self.getLine(i);
var found = line.indexOf(lineString);
if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1;
if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment;
if (found == -1 && nonWS.test(line)) break lineComment;
if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment;
lines.push(line);
}
@ -142,15 +170,15 @@
var endString = options.blockCommentEnd || mode.blockCommentEnd;
if (!startString || !endString) return false;
var lead = options.blockCommentLead || mode.blockCommentLead;
var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end);
var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString);
if (close == -1 && start != end) {
endLine = self.getLine(--end);
close = endLine.lastIndexOf(endString);
}
if (open == -1 || close == -1 ||
!/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) ||
!/comment/.test(self.getTokenTypeAt(Pos(end, close + 1))))
var startLine = self.getLine(start), open = startLine.indexOf(startString)
if (open == -1) return false
var endLine = end == start ? startLine : self.getLine(end)
var close = endLine.indexOf(endString, end == start ? open + startString.length : 0);
var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1)
if (close == -1 ||
!/comment/.test(self.getTokenTypeAt(insideStart)) ||
!/comment/.test(self.getTokenTypeAt(insideEnd)) ||
self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
return false;
// Avoid killing block comments completely outside the selection.

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -9,46 +9,69 @@
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var modes = ["clike", "css", "javascript"];
for (var i = 0; i < modes.length; ++i)
CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});
var nonspace = /\S/g;
var repeat = String.prototype.repeat || function (n) { return Array(n + 1).join(this); };
function continueComment(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), mode, inserts = [];
for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head, token = cm.getTokenAt(pos);
if (token.type != "comment") return CodeMirror.Pass;
var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode;
var pos = ranges[i].head
if (!/\bcomment\b/.test(cm.getTokenTypeAt(pos))) return CodeMirror.Pass;
var modeHere = cm.getModeAt(pos)
if (!mode) mode = modeHere;
else if (mode != modeHere) return CodeMirror.Pass;
var insert = null;
if (mode.blockCommentStart && mode.blockCommentContinue) {
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 && pos.ch >= end) {
// Comment ended, don't continue it
} else if (token.string.indexOf(mode.blockCommentStart) == 0) {
insert = full.slice(0, token.start);
if (!/^\s*$/.test(insert)) {
insert = "";
for (var j = 0; j < token.start; ++j) insert += " ";
var insert = null, line, found;
var blockStart = mode.blockCommentStart, lineCmt = mode.lineComment;
if (blockStart && mode.blockCommentContinue) {
line = cm.getLine(pos.line);
var end = line.lastIndexOf(mode.blockCommentEnd, pos.ch - mode.blockCommentEnd.length);
// 1. if this block comment ended
// 2. if this is actually inside a line comment
if (end != -1 && end == pos.ch - mode.blockCommentEnd.length ||
lineCmt && (found = line.lastIndexOf(lineCmt, pos.ch - 1)) > -1 &&
/\bcomment\b/.test(cm.getTokenTypeAt({line: pos.line, ch: found + 1}))) {
// ...then don't continue it
} else if (pos.ch >= blockStart.length &&
(found = line.lastIndexOf(blockStart, pos.ch - blockStart.length)) > -1 &&
found > end) {
// reuse the existing leading spaces/tabs/mixed
// or build the correct indent using CM's tab/indent options
if (nonspaceAfter(0, line) >= found) {
insert = line.slice(0, found);
} else {
var tabSize = cm.options.tabSize, numTabs;
found = CodeMirror.countColumn(line, found, tabSize);
insert = !cm.options.indentWithTabs ? repeat.call(" ", found) :
repeat.call("\t", (numTabs = Math.floor(found / tabSize))) +
repeat.call(" ", found - tabSize * numTabs);
}
} else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
found + mode.blockCommentContinue.length > token.start &&
/^\s*$/.test(full.slice(0, found))) {
insert = full.slice(0, found);
}
if (insert != null) insert += mode.blockCommentContinue;
}
if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {
var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);
if (found > -1) {
} else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 &&
found <= pos.ch &&
found <= nonspaceAfter(0, line)) {
insert = line.slice(0, found);
if (/\S/.test(insert)) insert = null;
else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0];
}
if (insert != null) insert += mode.blockCommentContinue
}
if (insert == null && lineCmt && continueLineCommentEnabled(cm)) {
if (line == null) line = cm.getLine(pos.line);
found = line.indexOf(lineCmt);
// cursor at pos 0, line comment also at pos 0 => shift it down, don't continue
if (!pos.ch && !found) insert = "";
// continue only if the line starts with an optional space + line comment
else if (found > -1 && nonspaceAfter(0, line) >= found) {
// don't continue if there's only space(s) after cursor or the end of the line
insert = nonspaceAfter(pos.ch, line) > -1;
// but always continue if the next line starts with a line comment too
if (!insert) {
var next = cm.getLine(pos.line + 1) || '',
nextFound = next.indexOf(lineCmt);
insert = nextFound > -1 && nonspaceAfter(0, next) >= nextFound || null;
}
if (insert) {
insert = line.slice(0, found) + lineCmt +
line.slice(found + lineCmt.length).match(/^\s*/)[0];
}
}
}
if (insert == null) return CodeMirror.Pass;
@ -61,6 +84,12 @@
});
}
function nonspaceAfter(ch, str) {
nonspace.lastIndex = ch;
var m = nonspace.exec(str);
return m ? m.index : -1;
}
function continueLineCommentEnabled(cm) {
var opt = cm.getOption("continueComments");
if (opt && typeof opt == "object")

View File

@ -1,11 +1,11 @@
.CodeMirror-dialog {
position: absolute;
left: 0; right: 0;
background: white;
background: inherit;
z-index: 15;
padding: .1em .8em;
overflow: hidden;
color: #333;
color: inherit;
}
.CodeMirror-dialog-top {

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Open simple dialogs on top of an editor. Relies on dialog.css.
@ -25,6 +25,7 @@
} else { // Assuming it's a detached DOM element.
dialog.appendChild(template);
}
CodeMirror.addClass(wrap, 'dialog-opened');
return dialog;
}
@ -47,6 +48,7 @@
} else {
if (closed) return;
closed = true;
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog);
me.focus();
@ -56,9 +58,13 @@
var inp = dialog.getElementsByTagName("input")[0], button;
if (inp) {
inp.focus();
if (options.value) {
inp.value = options.value;
inp.select();
if (options.selectValueOnOpen !== false) {
inp.select();
}
}
if (options.onInput)
@ -76,9 +82,9 @@
if (e.keyCode == 13) callback(inp.value, e);
});
if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
inp.focus();
if (options.closeOnBlur !== false) CodeMirror.on(dialog, "focusout", function (evt) {
if (evt.relatedTarget !== null) close();
});
} else if (button = dialog.getElementsByTagName("button")[0]) {
CodeMirror.on(button, "click", function() {
close();
@ -100,6 +106,7 @@
function close() {
if (closed) return;
closed = true;
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog);
me.focus();
}
@ -139,6 +146,7 @@
if (closed) return;
closed = true;
clearTimeout(doneTimer);
CodeMirror.rmClass(dialog.parentNode, 'dialog-opened');
dialog.parentNode.removeChild(dialog);
}

View File

@ -0,0 +1,47 @@
// 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"))
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod)
else // Plain browser env
mod(CodeMirror)
})(function(CodeMirror) {
"use strict"
CodeMirror.defineOption("autoRefresh", false, function(cm, val) {
if (cm.state.autoRefresh) {
stopListening(cm, cm.state.autoRefresh)
cm.state.autoRefresh = null
}
if (val && cm.display.wrapper.offsetHeight == 0)
startListening(cm, cm.state.autoRefresh = {delay: val.delay || 250})
})
function startListening(cm, state) {
function check() {
if (cm.display.wrapper.offsetHeight) {
stopListening(cm, state)
if (cm.display.lastWrapHeight != cm.display.wrapper.clientHeight)
cm.refresh()
} else {
state.timeout = setTimeout(check, state.delay)
}
}
state.timeout = setTimeout(check, state.delay)
state.hurry = function() {
clearTimeout(state.timeout)
state.timeout = setTimeout(check, 50)
}
CodeMirror.on(window, "mouseup", state.hurry)
CodeMirror.on(window, "keyup", state.hurry)
}
function stopListening(_cm, state) {
clearTimeout(state.timeout)
CodeMirror.off(window, "mouseup", state.hurry)
CodeMirror.off(window, "keyup", state.hurry)
}
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS

View File

@ -1,26 +1,51 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
(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) {
CodeMirror.defineExtension("addPanel", function(node, options) {
})(function (CodeMirror) {
CodeMirror.defineExtension("addPanel", function (node, options) {
options = options || {};
if (!this.state.panels) initPanels(this);
var info = this.state.panels;
if (options && options.position == "bottom")
info.wrapper.appendChild(node);
else
info.wrapper.insertBefore(node, info.wrapper.firstChild);
var wrapper = info.wrapper;
var cmWrapper = this.getWrapperElement();
var replace = options.replace instanceof Panel && !options.replace.cleared;
if (options.after instanceof Panel && !options.after.cleared) {
wrapper.insertBefore(node, options.before.node.nextSibling);
} else if (options.before instanceof Panel && !options.before.cleared) {
wrapper.insertBefore(node, options.before.node);
} else if (replace) {
wrapper.insertBefore(node, options.replace.node);
options.replace.clear(true);
} else if (options.position == "bottom") {
wrapper.appendChild(node);
} else if (options.position == "before-bottom") {
wrapper.insertBefore(node, cmWrapper.nextSibling);
} else if (options.position == "after-top") {
wrapper.insertBefore(node, cmWrapper);
} else {
wrapper.insertBefore(node, wrapper.firstChild);
}
var height = (options && options.height) || node.offsetHeight;
this._setSize(null, info.heightLeft -= height);
info.panels++;
return new Panel(this, node, options, height);
var panel = new Panel(this, node, options, height);
info.panels.push(panel);
this.setSize();
if (options.stable && isAtTop(this, node))
this.scrollTo(null, this.getScrollInfo().top + height);
return panel;
});
function Panel(cm, node, options, height) {
@ -31,40 +56,43 @@
this.cleared = false;
}
Panel.prototype.clear = function() {
/* when skipRemove is true, clear() was called from addPanel().
* Thus removePanels() should not be called (issue 5518) */
Panel.prototype.clear = function (skipRemove) {
if (this.cleared) return;
this.cleared = true;
var info = this.cm.state.panels;
this.cm._setSize(null, info.heightLeft += this.height);
info.panels.splice(info.panels.indexOf(this), 1);
this.cm.setSize();
if (this.options.stable && isAtTop(this.cm, this.node))
this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height)
info.wrapper.removeChild(this.node);
if (--info.panels == 0) removePanels(this.cm);
if (info.panels.length == 0 && !skipRemove) removePanels(this.cm);
};
Panel.prototype.changed = function(height) {
var newHeight = height == null ? this.node.offsetHeight : height;
var info = this.cm.state.panels;
this.cm._setSize(null, info.height += (newHeight - this.height));
this.height = newHeight;
Panel.prototype.changed = function () {
this.height = this.node.getBoundingClientRect().height;
this.cm.setSize();
};
function initPanels(cm) {
var wrap = cm.getWrapperElement();
var wrap = cm.getWrapperElement()
var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
var height = parseInt(style.height);
var info = cm.state.panels = {
setHeight: wrap.style.height,
heightLeft: height,
panels: 0,
panels: [],
wrapper: document.createElement("div")
};
var hasFocus = cm.hasFocus(), scrollPos = cm.getScrollInfo()
wrap.parentNode.insertBefore(info.wrapper, wrap);
var hasFocus = cm.hasFocus();
info.wrapper.appendChild(wrap);
cm.scrollTo(scrollPos.left, scrollPos.top)
if (hasFocus) cm.focus();
cm._setSize = cm.setSize;
if (height != null) cm.setSize = function(width, newHeight) {
if (newHeight == null) return this._setSize(width, newHeight);
if (height != null) cm.setSize = function (width, newHeight) {
if (!newHeight) newHeight = info.wrapper.offsetHeight;
info.setHeight = newHeight;
if (typeof newHeight != "number") {
var px = /^(\d+\.?\d*)px$/.exec(newHeight);
@ -73,10 +101,12 @@
} else {
info.wrapper.style.height = newHeight;
newHeight = info.wrapper.offsetHeight;
info.wrapper.style.height = "";
}
}
cm._setSize(width, info.heightLeft += (newHeight - height));
var editorheight = newHeight - info.panels
.map(function (p) { return p.node.getBoundingClientRect().height; })
.reduce(function (a, b) { return a + b; }, 0);
cm._setSize(width, editorheight);
height = newHeight;
};
}
@ -85,10 +115,19 @@
var info = cm.state.panels;
cm.state.panels = null;
var wrap = cm.getWrapperElement();
var wrap = cm.getWrapperElement()
var hasFocus = cm.hasFocus(), scrollPos = cm.getScrollInfo()
info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
cm.scrollTo(scrollPos.left, scrollPos.top)
if (hasFocus) cm.focus();
wrap.style.height = info.setHeight;
cm.setSize = cm._setSize;
cm.setSize();
}
function isAtTop(cm, dom) {
for (var sibling = dom.nextSibling; sibling; sibling = sibling.nextSibling)
if (sibling == cm.getWrapperElement()) return true
return false
}
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -14,10 +14,14 @@
if (val && !prev) {
cm.on("blur", onBlur);
cm.on("change", onChange);
cm.on("swapDoc", onChange);
CodeMirror.on(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose = function() { onComposition(cm) })
onChange(cm);
} else if (!val && prev) {
cm.off("blur", onBlur);
cm.off("change", onChange);
cm.off("swapDoc", onChange);
CodeMirror.off(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose)
clearPlaceholder(cm);
var wrapper = cm.getWrapperElement();
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
@ -36,11 +40,27 @@
clearPlaceholder(cm);
var elt = cm.state.placeholder = document.createElement("pre");
elt.style.cssText = "height: 0; overflow: visible";
elt.className = "CodeMirror-placeholder";
elt.appendChild(document.createTextNode(cm.getOption("placeholder")));
elt.style.direction = cm.getOption("direction");
elt.className = "CodeMirror-placeholder CodeMirror-line-like";
var placeHolder = cm.getOption("placeholder")
if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
elt.appendChild(placeHolder)
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
}
function onComposition(cm) {
setTimeout(function() {
var empty = false
if (cm.lineCount() == 1) {
var input = cm.getInputField()
empty = input.nodeName == "TEXTAREA" ? !cm.getLine(0).length
: !/[^\u200b]/.test(input.querySelector(".CodeMirror-line").textContent)
}
if (empty) setPlaceholder(cm)
else clearPlaceholder(cm)
}, 20)
}
function onBlur(cm) {
if (isEmpty(cm)) setPlaceholder(cm);
}

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,34 +11,30 @@
})(function(CodeMirror) {
"use strict";
CodeMirror.defineOption("rulers", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
clearRulers(cm);
cm.off("refresh", refreshRulers);
CodeMirror.defineOption("rulers", false, function(cm, val) {
if (cm.state.rulerDiv) {
cm.state.rulerDiv.parentElement.removeChild(cm.state.rulerDiv)
cm.state.rulerDiv = null
cm.off("refresh", drawRulers)
}
if (val && val.length) {
setRulers(cm);
cm.on("refresh", refreshRulers);
cm.state.rulerDiv = cm.display.lineSpace.parentElement.insertBefore(document.createElement("div"), cm.display.lineSpace)
cm.state.rulerDiv.className = "CodeMirror-rulers"
drawRulers(cm)
cm.on("refresh", drawRulers)
}
});
function clearRulers(cm) {
for (var i = cm.display.lineSpace.childNodes.length - 1; i >= 0; i--) {
var node = cm.display.lineSpace.childNodes[i];
if (/(^|\s)CodeMirror-ruler($|\s)/.test(node.className))
node.parentNode.removeChild(node);
}
}
function setRulers(cm) {
function drawRulers(cm) {
cm.state.rulerDiv.textContent = ""
var val = cm.getOption("rulers");
var cw = cm.defaultCharWidth();
var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;
var minH = cm.display.scroller.offsetHeight + 30;
cm.state.rulerDiv.style.minHeight = (cm.display.scroller.offsetHeight + 30) + "px";
for (var i = 0; i < val.length; i++) {
var elt = document.createElement("div");
elt.className = "CodeMirror-ruler";
var col, cls = null, conf = val[i];
var col, conf = val[i];
if (typeof conf == "number") {
col = conf;
} else {
@ -47,18 +43,9 @@
if (conf.color) elt.style.borderColor = conf.color;
if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
if (conf.width) elt.style.borderLeftWidth = conf.width;
cls = val[i].className;
}
elt.style.left = (left + col * cw) + "px";
elt.style.top = "-50px";
elt.style.bottom = "-20px";
elt.style.minHeight = minH + "px";
cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv);
cm.state.rulerDiv.appendChild(elt)
}
}
function refreshRulers(cm) {
clearRulers(cm);
setRulers(cm);
}
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -9,153 +9,193 @@
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
var DEFAULT_BRACKETS = "()[]{}''\"\"";
var DEFAULT_TRIPLES = "'\"";
var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
var SPACE_CHAR_REGEX = /\s/;
var defaults = {
pairs: "()[]{}''\"\"",
closeBefore: ")]}'\":;>",
triples: "",
explode: "[]{}"
};
var Pos = CodeMirror.Pos;
CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
if (old != CodeMirror.Init && old)
cm.removeKeyMap("autoCloseBrackets");
if (!val) return;
var pairs = DEFAULT_BRACKETS, triples = DEFAULT_TRIPLES, explode = DEFAULT_EXPLODE_ON_ENTER;
if (typeof val == "string") pairs = val;
else if (typeof val == "object") {
if (val.pairs != null) pairs = val.pairs;
if (val.triples != null) triples = val.triples;
if (val.explode != null) explode = val.explode;
if (old && old != CodeMirror.Init) {
cm.removeKeyMap(keyMap);
cm.state.closeBrackets = null;
}
if (val) {
ensureBound(getOption(val, "pairs"))
cm.state.closeBrackets = val;
cm.addKeyMap(keyMap);
}
var map = buildKeymap(pairs, triples);
if (explode) map.Enter = buildExplodeHandler(explode);
cm.addKeyMap(map);
});
function getOption(conf, name) {
if (name == "pairs" && typeof conf == "string") return conf;
if (typeof conf == "object" && conf[name] != null) return conf[name];
return defaults[name];
}
var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
function ensureBound(chars) {
for (var i = 0; i < chars.length; i++) {
var ch = chars.charAt(i), key = "'" + ch + "'"
if (!keyMap[key]) keyMap[key] = handler(ch)
}
}
ensureBound(defaults.pairs + "`")
function handler(ch) {
return function(cm) { return handleChar(cm, ch); };
}
function getConfig(cm) {
var deflt = cm.state.closeBrackets;
if (!deflt || deflt.override) return deflt;
var mode = cm.getModeAt(cm.getCursor());
return mode.closeBrackets || deflt;
}
function handleBackspace(cm) {
var conf = getConfig(cm);
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
var pairs = getOption(conf, "pairs");
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
for (var i = ranges.length - 1; i >= 0; i--) {
var cur = ranges[i].head;
cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
}
}
function handleEnter(cm) {
var conf = getConfig(cm);
var explode = conf && getOption(conf, "explode");
if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
cm.operation(function() {
var linesep = cm.lineSeparator() || "\n";
cm.replaceSelection(linesep + linesep, null);
moveSel(cm, -1)
ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var line = ranges[i].head.line;
cm.indentLine(line, null, true);
cm.indentLine(line + 1, null, true);
}
});
}
function moveSel(cm, dir) {
var newRanges = [], ranges = cm.listSelections(), primary = 0
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i]
if (range.head == cm.getCursor()) primary = i
var pos = range.head.ch || dir > 0 ? {line: range.head.line, ch: range.head.ch + dir} : {line: range.head.line - 1}
newRanges.push({anchor: pos, head: pos})
}
cm.setSelections(newRanges, primary)
}
function contractSelection(sel) {
var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
}
function handleChar(cm, ch) {
var conf = getConfig(cm);
if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
var pairs = getOption(conf, "pairs");
var pos = pairs.indexOf(ch);
if (pos == -1) return CodeMirror.Pass;
var closeBefore = getOption(conf,"closeBefore");
var triples = getOption(conf, "triples");
var identical = pairs.charAt(pos + 1) == ch;
var ranges = cm.listSelections();
var opening = pos % 2 == 0;
var type;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i], cur = range.head, curType;
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
if (opening && !range.empty()) {
curType = "surround";
} else if ((identical || !opening) && next == ch) {
if (identical && stringStartsAfter(cm, cur))
curType = "both";
else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
curType = "skipThree";
else
curType = "skip";
} else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) {
if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass;
curType = "addFour";
} else if (identical) {
var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
else return CodeMirror.Pass;
} else if (opening && (next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)) {
curType = "both";
} else {
return CodeMirror.Pass;
}
if (!type) type = curType;
else if (type != curType) return CodeMirror.Pass;
}
var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
var right = pos % 2 ? ch : pairs.charAt(pos + 1);
cm.operation(function() {
if (type == "skip") {
moveSel(cm, 1)
} else if (type == "skipThree") {
moveSel(cm, 3)
} else if (type == "surround") {
var sels = cm.getSelections();
for (var i = 0; i < sels.length; i++)
sels[i] = left + sels[i] + right;
cm.replaceSelections(sels, "around");
sels = cm.listSelections().slice();
for (var i = 0; i < sels.length; i++)
sels[i] = contractSelection(sels[i]);
cm.setSelections(sels);
} else if (type == "both") {
cm.replaceSelection(left + right, null);
cm.triggerElectric(left + right);
moveSel(cm, -1)
} else if (type == "addFour") {
cm.replaceSelection(left + left + left + left, "before");
moveSel(cm, 1)
}
});
}
function charsAround(cm, pos) {
var str = cm.getRange(Pos(pos.line, pos.ch - 1),
Pos(pos.line, pos.ch + 1));
return str.length == 2 ? str : null;
}
// Project the token type that will exists after the given char is
// typed, and use it to determine whether it would cause the start
// of a string token.
function enteringString(cm, pos, ch) {
var line = cm.getLine(pos.line);
var token = cm.getTokenAt(pos);
if (/\bstring2?\b/.test(token.type)) return false;
var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
stream.pos = stream.start = token.start;
for (;;) {
var type1 = cm.getMode().token(stream, token.state);
if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
stream.start = stream.pos;
}
}
function buildKeymap(pairs, triples) {
var map = {
name : "autoCloseBrackets",
Backspace: function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
for (var i = ranges.length - 1; i >= 0; i--) {
var cur = ranges[i].head;
cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
}
}
};
var closingBrackets = "";
for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
closingBrackets += right;
map["'" + left + "'"] = function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), type, next;
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i], cur = range.head, curType;
var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
if (!range.empty()) {
curType = "surround";
} else if (left == right && next == right) {
if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
curType = "skipThree";
else
curType = "skip";
} else if (left == right && cur.ch > 1 && triples.indexOf(left) >= 0 &&
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&
(cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left)) {
curType = "addFour";
} else if (left == '"' || left == "'") {
if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, left)) curType = "both";
else return CodeMirror.Pass;
} else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next)) {
curType = "both";
} else {
return CodeMirror.Pass;
}
if (!type) type = curType;
else if (type != curType) return CodeMirror.Pass;
}
cm.operation(function() {
if (type == "skip") {
cm.execCommand("goCharRight");
} else if (type == "skipThree") {
for (var i = 0; i < 3; i++)
cm.execCommand("goCharRight");
} else if (type == "surround") {
var sels = cm.getSelections();
for (var i = 0; i < sels.length; i++)
sels[i] = left + sels[i] + right;
cm.replaceSelections(sels, "around");
} else if (type == "both") {
cm.replaceSelection(left + right, null);
cm.execCommand("goCharLeft");
} else if (type == "addFour") {
cm.replaceSelection(left + left + left + left, "before");
cm.execCommand("goCharRight");
}
});
};
if (left != right) map["'" + right + "'"] = function(cm) {
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (!range.empty() ||
cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
return CodeMirror.Pass;
}
cm.execCommand("goCharRight");
};
})(pairs.charAt(i), pairs.charAt(i + 1));
return map;
}
function buildExplodeHandler(pairs) {
return function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var around = charsAround(cm, ranges[i].head);
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
}
cm.operation(function() {
cm.replaceSelection("\n\n", null);
cm.execCommand("goCharLeft");
ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) {
var line = ranges[i].head.line;
cm.indentLine(line, null, true);
cm.indentLine(line + 1, null, true);
}
});
};
function stringStartsAfter(cm, pos) {
var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
return /\bstring/.test(token.type) && token.start == pos.ch &&
(pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
}
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
/**
* Tag-closer extension for CodeMirror.
@ -21,6 +21,8 @@
* 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.
* `emptyTags` (default is none)
* An array of XML tag names that should be autoclosed with '/>'.
*
* See demos/closetag.html for a usage example.
*/
@ -38,9 +40,9 @@
cm.removeKeyMap("autoCloseTags");
if (!val) return;
var map = {name: "autoCloseTags"};
if (typeof val != "object" || val.whenClosing)
if (typeof val != "object" || val.whenClosing !== false)
map["'/'"] = function(cm) { return autoCloseSlash(cm); };
if (typeof val != "object" || val.whenOpening)
if (typeof val != "object" || val.whenOpening !== false)
map["'>'"] = function(cm) { return autoCloseGT(cm); };
cm.addKeyMap(map);
});
@ -53,41 +55,50 @@
function autoCloseGT(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = [];
var opt = cm.getOption("autoCloseTags");
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;
var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state)
var tagName = tagInfo && tagInfo.name
if (!tagName) return CodeMirror.Pass
var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
var html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
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 (!tagName ||
tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
tok.type == "tag" && state.type == "closeTag" ||
tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />
tok.type == "tag" && tagInfo.close ||
tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like <someTagName />
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
closingTagExists(cm, tagName, pos, state, true))
closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true))
return CodeMirror.Pass;
var emptyTags = typeof opt == "object" && opt.emptyTags;
if (emptyTags && indexOf(emptyTags, tagName) > -1) {
replacements[i] = { text: "/>", newPos: CodeMirror.Pos(pos.line, pos.ch + 2) };
continue;
}
var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
replacements[i] = {indent: indent,
text: ">" + (indent ? "\n\n" : "") + "</" + tagName + ">",
newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
}
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnAutoClose);
for (var i = ranges.length - 1; i >= 0; i--) {
var info = replacements[i];
cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
var sel = cm.listSelections().slice(0);
sel[i] = {head: info.newPos, anchor: info.newPos};
cm.setSelections(sel);
if (info.indent) {
if (!dontIndentOnAutoClose && info.indent) {
cm.indentLine(info.newPos.line, null, true);
cm.indentLine(info.newPos.line + 1, null, true);
}
@ -97,6 +108,8 @@
function autoCloseCurrent(cm, typingSlash) {
var ranges = cm.listSelections(), replacements = [];
var head = typingSlash ? "/" : "</";
var opt = cm.getOption("autoCloseTags");
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnSlash);
for (var i = 0; i < ranges.length; i++) {
if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos);
@ -108,25 +121,28 @@
// when completing in JS/CSS snippet in htmlmixed mode. Does not
// work for other XML embedded languages (there is no general
// way to go from a mixed mode to its current XML state).
if (inner.mode.name != "xml") {
if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
replacements[i] = head + "script>";
else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
replacements[i] = head + "style>";
else
return CodeMirror.Pass;
var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
if (mixed && inner.mode.name == "javascript") {
replacement = head + "script";
} else if (mixed && inner.mode.name == "css") {
replacement = head + "style";
} else {
if (!state.context || !state.context.tagName ||
closingTagExists(cm, state.context.tagName, pos, state))
var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
var top = context.length ? context[context.length - 1] : ""
if (!context || (context.length && closingTagExists(cm, context, top, pos)))
return CodeMirror.Pass;
replacements[i] = head + state.context.tagName + ">";
replacement = head + top
}
if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
replacements[i] = replacement;
}
cm.replaceSelections(replacements);
ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++)
if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
cm.indentLine(ranges[i].head.line);
if (!dontIndentOnAutoClose) {
for (var i = 0; i < ranges.length; i++)
if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
cm.indentLine(ranges[i].head.line);
}
}
function autoCloseSlash(cm) {
@ -145,16 +161,19 @@
// If xml-fold is loaded, we use its functionality to try and verify
// whether a given tag is actually unclosed.
function closingTagExists(cm, tagName, pos, state, newTag) {
function closingTagExists(cm, context, tagName, pos, newTag) {
if (!CodeMirror.scanForClosingTag) return false;
var end = Math.min(cm.lastLine() + 1, pos.line + 500);
var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!nextClose || nextClose.tag != tagName) return false;
var cx = state.context;
// If the immediate wrapping context contains onCx instances of
// the same tag, a closing tag only exists if there are at least
// that many closing tags of that type following.
for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx;
var onCx = newTag ? 1 : 0
for (var i = context.length - 1; i >= 0; i--) {
if (context[i] == tagName) ++onCx
else break
}
pos = nextClose.to;
for (var i = 1; i < onCx; i++) {
var next = CodeMirror.scanForClosingTag(cm, pos, null, end);

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,41 +11,91 @@
})(function(CodeMirror) {
"use strict";
var listRE = /^(\s*)(>[> ]*|[*+-]\s|(\d+)\.)(\s*)/,
emptyListRE = /^(\s*)(>[> ]*|[*+-]|(\d+)\.)(\s*)$/,
var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/,
emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,
unorderedListRE = /[*+-]\s/;
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = [];
for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head, match;
var eolState = cm.getStateAfter(pos.line);
var inList = eolState.list !== false;
var inQuote = eolState.quote !== false;
var pos = ranges[i].head;
if (!ranges[i].empty() || (!inList && !inQuote) || !(match = cm.getLine(pos.line).match(listRE))) {
// If we're not in Markdown mode, fall back to normal newlineAndIndent
var eolState = cm.getStateAfter(pos.line);
var inner = CodeMirror.innerMode(cm.getMode(), eolState);
if (inner.mode.name !== "markdown") {
cm.execCommand("newlineAndIndent");
return;
} else {
eolState = inner.state;
}
var inList = eolState.list !== false;
var inQuote = eolState.quote !== 0;
var line = cm.getLine(pos.line), match = listRE.exec(line);
var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch));
if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) {
cm.execCommand("newlineAndIndent");
return;
}
if (cm.getLine(pos.line).match(emptyListRE)) {
cm.replaceRange("", {
if (emptyListRE.test(line)) {
var endOfQuote = inQuote && />\s*$/.test(line)
var endOfList = !/>\s*$/.test(line)
if (endOfQuote || endOfList) cm.replaceRange("", {
line: pos.line, ch: 0
}, {
line: pos.line, ch: pos.ch + 1
});
replacements[i] = "\n";
} else {
var indent = match[1], after = match[4];
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0
? match[2]
: (parseInt(match[3], 10) + 1) + ".";
var indent = match[1], after = match[5];
var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " ");
replacements[i] = "\n" + indent + bullet + after;
if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
}
}
cm.replaceSelections(replacements);
};
// Auto-updating Markdown list numbers when a new item is added to the
// middle of a list
function incrementRemainingMarkdownListNumbers(cm, pos) {
var startLine = pos.line, lookAhead = 0, skipCount = 0;
var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1];
do {
lookAhead += 1;
var nextLineNumber = startLine + lookAhead;
var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine);
if (nextItem) {
var nextIndent = nextItem[1];
var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount);
var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber;
if (startIndent === nextIndent && !isNaN(nextNumber)) {
if (newNumber === nextNumber) itemNumber = nextNumber + 1;
if (newNumber > nextNumber) itemNumber = newNumber + 1;
cm.replaceRange(
nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
{
line: nextLineNumber, ch: 0
}, {
line: nextLineNumber, ch: nextLine.length
});
} else {
if (startIndent.length > nextIndent.length) return;
// This doesn't run if the next line immediately indents, as it is
// not clear of the users intention (new indented item or same level)
if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return;
skipCount += 1;
}
}
} while (nextItem);
}
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -14,17 +14,31 @@
var Pos = CodeMirror.Pos;
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<", "<": ">>", ">": "<<"};
function findMatchingBracket(cm, where, strict, config) {
function bracketRegex(config) {
return config && config.bracketRegex || /[(){}[\]]/
}
function findMatchingBracket(cm, where, config) {
var line = cm.getLineHandle(where.line), pos = where.ch - 1;
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
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 (strict && (dir > 0) != (pos == where.ch)) return null;
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 || null, config);
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};
@ -42,7 +56,7 @@
var maxScanLines = (config && config.maxScanLines) || 1000;
var stack = [];
var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
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) {
@ -53,9 +67,10 @@
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)) {
if (re.test(ch) && (style === undefined ||
(cm.getTokenTypeAt(Pos(lineNo, pos + 1)) || "") == (style || ""))) {
var match = matching[ch];
if ((match.charAt(1) == ">") == (dir > 0)) stack.push(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();
}
@ -66,11 +81,12 @@
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;
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, false, config);
if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
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)
@ -80,7 +96,7 @@
if (marks.length) {
// Kludge to work around the IE bug from issue #1193, where text
// input stops going to the textare whever this fires.
// input stops going to the textarea whenever this fires.
if (ie_lt8 && cm.state.focused) cm.focus();
var clear = function() {
@ -93,26 +109,50 @@
}
}
var currentlyHighlighted = null;
function doMatchBrackets(cm) {
cm.operation(function() {
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
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)
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, strict, config){
return findMatchingBracket(this, pos, strict, config);
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);

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,53 +11,67 @@
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("fold", "brace", function(cm, start) {
var line = start.line, lineText = cm.getLine(line);
var startCh, tokenType;
function bracketFolding(pairs) {
return function(cm, start) {
var line = start.line, lineText = cm.getLine(line);
function findOpening(openCh) {
for (var at = start.ch, pass = 0;;) {
var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
if (found == -1) {
if (pass == 1) break;
pass = 1;
at = lineText.length;
continue;
function findOpening(pair) {
var tokenType;
for (var at = start.ch, pass = 0;;) {
var found = at <= 0 ? -1 : lineText.lastIndexOf(pair[0], at - 1);
if (found == -1) {
if (pass == 1) break;
pass = 1;
at = lineText.length;
continue;
}
if (pass == 1 && found < start.ch) break;
tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
if (!/^(comment|string)/.test(tokenType)) return {ch: found + 1, tokenType: tokenType, pair: pair};
at = found - 1;
}
if (pass == 1 && found < start.ch) break;
tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
if (!/^(comment|string)/.test(tokenType)) return found + 1;
at = found - 1;
}
}
var startToken = "{", endToken = "}", startCh = findOpening("{");
if (startCh == null) {
startToken = "[", endToken = "]";
startCh = findOpening("[");
}
if (startCh == null) return;
var count = 1, lastLine = cm.lastLine(), end, endCh;
outer: for (var i = line; i <= lastLine; ++i) {
var text = cm.getLine(i), pos = i == line ? startCh : 0;
for (;;) {
var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, 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.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; endCh = pos; break outer; }
function findRange(found) {
var count = 1, lastLine = cm.lastLine(), end, startCh = found.ch, endCh
outer: for (var i = line; i <= lastLine; ++i) {
var text = cm.getLine(i), pos = i == line ? startCh : 0;
for (;;) {
var nextOpen = text.indexOf(found.pair[0], pos), nextClose = text.indexOf(found.pair[1], 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.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == found.tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; endCh = pos; break outer; }
}
++pos;
}
}
++pos;
if (end == null || line == end) return null
return {from: CodeMirror.Pos(line, startCh),
to: CodeMirror.Pos(end, endCh)};
}
var found = []
for (var i = 0; i < pairs.length; i++) {
var open = findOpening(pairs[i])
if (open) found.push(open)
}
found.sort(function(a, b) { return a.ch - b.ch })
for (var i = 0; i < found.length; i++) {
var range = findRange(found[i])
if (range) return range
}
return null
}
if (end == null || line == end && endCh == startCh) return;
return {from: CodeMirror.Pos(line, startCh),
to: CodeMirror.Pos(end, endCh)};
});
}
CodeMirror.registerHelper("fold", "brace", bracketFolding([["{", "}"], ["[", "]"]]));
CodeMirror.registerHelper("fold", "brace-paren", bracketFolding([["{", "}"], ["[", "]"], ["(", ")"]]));
CodeMirror.registerHelper("fold", "import", function(cm, start) {
function hasImport(line) {
@ -72,15 +86,15 @@ CodeMirror.registerHelper("fold", "import", function(cm, start) {
}
}
var start = start.line, has = hasImport(start), prev;
if (!has || hasImport(start - 1) || ((prev = hasImport(start - 2)) && prev.end.line == start - 1))
var startLine = start.line, has = hasImport(startLine), prev;
if (!has || hasImport(startLine - 1) || ((prev = hasImport(startLine - 2)) && prev.end.line == startLine - 1))
return null;
for (var end = has.end;;) {
var next = hasImport(end.line + 1);
if (next == null) break;
end = next.end;
}
return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
return {from: cm.clipPos(CodeMirror.Pos(startLine, has.startCh + 1)), to: end};
});
CodeMirror.registerHelper("fold", "include", function(cm, start) {
@ -91,14 +105,14 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) {
if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
}
var start = start.line, has = hasInclude(start);
if (has == null || hasInclude(start - 1) != null) return null;
for (var end = start;;) {
var startLine = start.line, has = hasInclude(startLine);
if (has == null || hasInclude(startLine - 1) != null) return null;
for (var end = startLine;;) {
var next = hasInclude(end + 1);
if (next == null) break;
++end;
}
return {from: CodeMirror.Pos(start, has + 1),
return {from: CodeMirror.Pos(startLine, has + 1),
to: cm.clipPos(CodeMirror.Pos(end))};
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -28,7 +28,9 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
continue;
}
if (pass == 1 && found < start.ch) return;
if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)))) {
if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1))) &&
(found == 0 || lineText.slice(found - endToken.length, found) == endToken ||
!/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found))))) {
startCh = found + startToken.length;
break;
}

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -24,9 +24,11 @@
function getRange(allowFolded) {
var range = finder(cm, pos);
if (!range || range.to.line - range.from.line < minSize) return null;
if (force === "fold") return range;
var marks = cm.findMarksAt(range.from);
for (var i = 0; i < marks.length; ++i) {
if (marks[i].__isFold && force !== "fold") {
if (marks[i].__isFold) {
if (!allowFolded) return null;
range.cleared = true;
marks[i].clear();
@ -42,14 +44,14 @@
}
if (!range || range.cleared || force === "unfold") return;
var myWidget = makeWidget(cm, options);
var myWidget = makeWidget(cm, options, range);
CodeMirror.on(myWidget, "mousedown", function(e) {
myRange.clear();
CodeMirror.e_preventDefault(e);
});
var myRange = cm.markText(range.from, range.to, {
replacedWith: myWidget,
clearOnEnter: true,
clearOnEnter: getOption(cm, options, "clearOnEnter"),
__isFold: true
});
myRange.on("clear", function(from, to) {
@ -58,13 +60,20 @@
CodeMirror.signal(cm, "fold", cm, range.from, range.to);
}
function makeWidget(cm, options) {
function makeWidget(cm, options, range) {
var widget = getOption(cm, options, "widget");
if (typeof widget == "function") {
widget = widget(range.from, range.to);
}
if (typeof widget == "string") {
var text = document.createTextNode(widget);
widget = document.createElement("span");
widget.appendChild(text);
widget.className = "CodeMirror-foldmarker";
} else if (widget) {
widget = widget.cloneNode(true)
}
return widget;
}
@ -92,18 +101,18 @@
cm.foldCode(cm.getCursor(), null, "fold");
};
CodeMirror.commands.unfold = function(cm) {
cm.foldCode(cm.getCursor(), null, "unfold");
cm.foldCode(cm.getCursor(), { scanUp: false }, "unfold");
};
CodeMirror.commands.foldAll = function(cm) {
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, "fold");
});
};
CodeMirror.commands.unfoldAll = function(cm) {
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, "unfold");
});
};
@ -129,7 +138,8 @@
rangeFinder: CodeMirror.fold.auto,
widget: "\u2194",
minFoldSize: 0,
scanUp: false
scanUp: false,
clearOnEnter: true
};
CodeMirror.defineOption("foldOptions", null);

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -16,21 +16,21 @@
cm.clearGutter(cm.state.foldGutter.options.gutter);
cm.state.foldGutter = null;
cm.off("gutterClick", onGutterClick);
cm.off("change", onChange);
cm.off("changes", onChange);
cm.off("viewportChange", onViewportChange);
cm.off("fold", onFold);
cm.off("unfold", onFold);
cm.off("swapDoc", updateInViewport);
cm.off("swapDoc", onChange);
}
if (val) {
cm.state.foldGutter = new State(parseOptions(val));
updateInViewport(cm);
cm.on("gutterClick", onGutterClick);
cm.on("change", onChange);
cm.on("changes", onChange);
cm.on("viewportChange", onViewportChange);
cm.on("fold", onFold);
cm.on("unfold", onFold);
cm.on("swapDoc", updateInViewport);
cm.on("swapDoc", onChange);
}
});
@ -50,9 +50,14 @@
}
function isFolded(cm, line) {
var marks = cm.findMarksAt(Pos(line));
for (var i = 0; i < marks.length; ++i)
if (marks[i].__isFold && marks[i].find().from.line == line) return true;
var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
for (var i = 0; i < marks.length; ++i) {
if (marks[i].__isFold) {
var fromPos = marks[i].find(-1);
if (fromPos && fromPos.line === line)
return marks[i];
}
}
}
function marker(spec) {
@ -66,24 +71,36 @@
}
function updateFoldInfo(cm, from, to) {
var opts = cm.state.foldGutter.options, cur = from;
var opts = cm.state.foldGutter.options, cur = from - 1;
var minSize = cm.foldOption(opts, "minFoldSize");
var func = cm.foldOption(opts, "rangeFinder");
// we can reuse the built-in indicator element if its className matches the new state
var clsFolded = typeof opts.indicatorFolded == "string" && classTest(opts.indicatorFolded);
var clsOpen = typeof opts.indicatorOpen == "string" && classTest(opts.indicatorOpen);
cm.eachLine(from, to, function(line) {
++cur;
var mark = null;
var old = line.gutterMarkers;
if (old) old = old[opts.gutter];
if (isFolded(cm, cur)) {
if (clsFolded && old && clsFolded.test(old.className)) return;
mark = marker(opts.indicatorFolded);
} else {
var pos = Pos(cur, 0);
var range = func && func(cm, pos);
if (range && range.to.line - range.from.line >= minSize)
if (range && range.to.line - range.from.line >= minSize) {
if (clsOpen && old && clsOpen.test(old.className)) return;
mark = marker(opts.indicatorOpen);
}
}
if (!mark && !old) return;
cm.setGutterMarker(line, opts.gutter, mark);
++cur;
});
}
// copied from CodeMirror/src/util/dom.js
function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
function updateInViewport(cm) {
var vp = cm.getViewport(), state = cm.state.foldGutter;
if (!state) return;
@ -98,7 +115,9 @@
if (!state) return;
var opts = state.options;
if (gutter != opts.gutter) return;
cm.foldCode(Pos(line, 0), opts.rangeFinder);
var folded = isFolded(cm, line);
if (folded) folded.clear();
else cm.foldCode(Pos(line, 0), opts);
}
function onChange(cm) {

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,32 +11,36 @@
})(function(CodeMirror) {
"use strict";
function lineIndent(cm, lineNo) {
var text = cm.getLine(lineNo)
var spaceTo = text.search(/\S/)
if (spaceTo == -1 || /\bcomment\b/.test(cm.getTokenTypeAt(CodeMirror.Pos(lineNo, spaceTo + 1))))
return -1
return CodeMirror.countColumn(text, null, cm.getOption("tabSize"))
}
CodeMirror.registerHelper("fold", "indent", function(cm, start) {
var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line);
if (!/\S/.test(firstLine)) return;
var getIndent = function(line) {
return CodeMirror.countColumn(line, null, tabSize);
};
var myIndent = getIndent(firstLine);
var lastLineInFold = null;
var myIndent = lineIndent(cm, start.line)
if (myIndent < 0) return
var lastLineInFold = null
// Go through lines until we find a line that definitely doesn't belong in
// the block we're folding, or to the end.
for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) {
var curLine = cm.getLine(i);
var curIndent = getIndent(curLine);
if (curIndent > myIndent) {
var indent = lineIndent(cm, i)
if (indent == -1) {
} else if (indent > myIndent) {
// Lines with a greater indent are considered part of the block.
lastLineInFold = i;
} else if (!/\S/.test(curLine)) {
// Empty lines might be breaks within the block we're trying to fold.
} else {
// A non-empty line at an indent equal to or less than ours marks the
// start of another block.
// If this line has non-space, non-comment content, and is
// indented less or equal to the start line, it is the start of
// another block.
break;
}
}
if (lastLineInFold) return {
from: CodeMirror.Pos(start.line, firstLine.length),
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length)
};
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -21,8 +21,8 @@
function Iter(cm, line, ch, range) {
this.line = line; this.ch = ch;
this.cm = cm; this.text = cm.getLine(line);
this.min = range ? range.from : cm.firstLine();
this.max = range ? range.to - 1 : cm.lastLine();
this.min = range ? Math.max(range.from, cm.firstLine()) : cm.firstLine();
this.max = range ? Math.min(range.to - 1, cm.lastLine()) : cm.lastLine();
}
function tagAt(iter, ch) {
@ -137,12 +137,14 @@
CodeMirror.registerHelper("fold", "xml", function(cm, start) {
var iter = new Iter(cm, start.line, 0);
for (;;) {
var openTag = toNextTag(iter), end;
if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
var openTag = toNextTag(iter)
if (!openTag || iter.line != start.line) return
var end = toTagEnd(iter)
if (!end) return
if (!openTag[1] && end != "selfClose") {
var start = Pos(iter.line, iter.ch);
var close = findMatchingClose(iter, openTag[2]);
return close && {from: start, to: close.from};
var startPos = Pos(iter.line, iter.ch);
var endPos = findMatchingClose(iter, openTag[2]);
return endPos && cmp(endPos.from, startPos) > 0 ? {from: startPos, to: endPos.from} : null
}
}
});
@ -163,10 +165,10 @@
}
};
CodeMirror.findEnclosingTag = function(cm, pos, range) {
CodeMirror.findEnclosingTag = function(cm, pos, range, tag) {
var iter = new Iter(cm, pos.line, pos.ch, range);
for (;;) {
var open = findMatchingOpen(iter);
var open = findMatchingOpen(iter, tag);
if (!open) break;
var forward = new Iter(cm, pos.line, pos.ch, range);
var close = findMatchingClose(forward, open.tag);

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -21,7 +21,7 @@
while (start && word.test(curLine.charAt(start - 1))) --start;
var curWord = start != end && curLine.slice(start, end);
var list = [], seen = {};
var list = options && options.list || [], seen = {};
var re = new RegExp(word.source, "g");
for (var dir = -1; dir <= 1; dir += 2) {
var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,15 +11,25 @@
})(function(CodeMirror) {
"use strict";
var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
"first-letter": 1, "first-line": 1, "first-child": 1,
before: 1, after: 1, lang: 1};
var pseudoClasses = {"active":1, "after":1, "before":1, "checked":1, "default":1,
"disabled":1, "empty":1, "enabled":1, "first-child":1, "first-letter":1,
"first-line":1, "first-of-type":1, "focus":1, "hover":1, "in-range":1,
"indeterminate":1, "invalid":1, "lang":1, "last-child":1, "last-of-type":1,
"link":1, "not":1, "nth-child":1, "nth-last-child":1, "nth-last-of-type":1,
"nth-of-type":1, "only-of-type":1, "only-child":1, "optional":1, "out-of-range":1,
"placeholder":1, "read-only":1, "read-write":1, "required":1, "root":1,
"selection":1, "target":1, "valid":1, "visited":1
};
CodeMirror.registerHelper("hint", "css", function(cm) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (inner.mode.name != "css") return;
if (token.type == "keyword" && "!important".indexOf(token.string) == 0)
return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, token.end)};
var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
if (/[^\w$_-]/.test(word)) {
word = ""; start = end = cur.ch;

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -98,6 +98,7 @@
dfn: s,
dir: s,
div: s,
dialog: { attrs: { open: null } },
dl: s,
dt: s,
em: s,
@ -322,6 +323,8 @@
itemtype: null,
lang: ["en", "es"],
spellcheck: ["true", "false"],
autocorrect: ["true", "false"],
autocapitalize: ["true", "false"],
style: null,
tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
title: null,

View File

@ -25,8 +25,6 @@
margin: 0;
padding: 0 4px;
border-radius: 2px;
max-width: 19em;
overflow: hidden;
white-space: pre;
color: black;
cursor: pointer;

View File

@ -1,5 +1,7 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// declare global: DOMRect
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -24,44 +26,63 @@
return cm.showHint(newOpts);
};
var asyncRunID = 0;
function retrieveHints(getter, cm, options, then) {
if (getter.async) {
var id = ++asyncRunID;
getter(cm, function(hints) {
if (asyncRunID == id) then(hints);
}, options);
} else {
then(getter(cm, options));
}
}
CodeMirror.defineExtension("showHint", function(options) {
// We want a single cursor position.
if (this.listSelections().length > 1 || this.somethingSelected()) return;
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);
var getHints = completion.options.hint;
if (!getHints) return;
if (!completion.options.hint) return;
CodeMirror.signal(this, "startCompletion", this);
return retrieveHints(getHints, this, completion.options, function(hints) { completion.showHints(hints); });
completion.update(true);
});
CodeMirror.defineExtension("closeHint", function() {
if (this.state.completionActive) this.state.completionActive.close()
})
function Completion(cm, options) {
this.cm = cm;
this.options = this.buildOptions(options);
this.widget = this.onClose = null;
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;
if (this.options.updateOnCursorActivity) {
var self = this;
cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
}
}
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;
if (this.options.updateOnCursorActivity) {
this.cm.off("cursorActivity", this.activityFunc);
}
if (this.widget && this.data) CodeMirror.signal(this.data, "close");
if (this.widget) this.widget.close();
if (this.onClose) this.onClose();
CodeMirror.signal(this.cm, "endCompletion", this.cm);
},
@ -70,92 +91,83 @@
},
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();
var completion = data.list[i], self = this;
this.cm.operation(function() {
if (completion.hint)
completion.hint(self.cm, data, completion);
else
self.cm.replaceRange(getText(completion), completion.from || data.from,
completion.to || data.to, "complete");
CodeMirror.signal(data, "pick", completion);
self.cm.scrollIntoView();
});
if (this.options.closeOnPick) {
this.close();
}
},
showHints: function(data) {
if (!data || !data.list.length || !this.active()) return this.close();
cursorActivity: function() {
if (this.debounce) {
cancelAnimationFrame(this.debounce);
this.debounce = 0;
}
if (this.options.completeSingle && data.list.length == 1)
this.pick(data, 0);
else
this.showWidget(data);
var identStart = this.startPos;
if(this.data) {
identStart = this.data.from;
}
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 < identStart.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();
}
},
showWidget: function(data) {
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
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)
})
},
var debounce = 0, completion = this, finished;
var closeOn = this.options.closeCharacters;
var startPos = this.cm.getCursor(), startLen = this.cm.getLine(startPos.line).length;
finishUpdate: function(data, first) {
if (this.data) CodeMirror.signal(this.data, "update");
var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
return setTimeout(fn, 1000/60);
};
var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close();
function done() {
if (finished) return;
finished = true;
completion.close();
completion.cm.off("cursorActivity", activity);
if (data) CodeMirror.signal(data, "close");
}
this.data = data;
function update() {
if (finished) return;
CodeMirror.signal(data, "update");
retrieveHints(completion.options.hint, completion.cm, completion.options, finishUpdate);
}
function finishUpdate(data_) {
data = data_;
if (finished) return;
if (!data || !data.list.length) return done();
if (completion.widget) completion.widget.close();
completion.widget = new Widget(completion, data);
}
function clearDebounce() {
if (debounce) {
cancelAnimationFrame(debounce);
debounce = 0;
}
}
function activity() {
clearDebounce();
var pos = completion.cm.getCursor(), line = completion.cm.getLine(pos.line);
if (pos.line != startPos.line || line.length - pos.ch != startLen - startPos.ch ||
pos.ch < startPos.ch || completion.cm.somethingSelected() ||
(pos.ch && closeOn.test(line.charAt(pos.ch - 1)))) {
completion.close();
if (data && data.list.length) {
if (picked && data.list.length == 1) {
this.pick(data, 0);
} else {
debounce = requestAnimationFrame(update);
if (completion.widget) completion.widget.close();
this.widget = new Widget(this, data);
CodeMirror.signal(data, "shown");
}
}
this.cm.on("cursorActivity", activity);
this.onClose = done;
},
buildOptions: function(options) {
var editor = this.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];
return out;
}
};
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;
@ -173,6 +185,14 @@
Tab: handle.pick,
Esc: handle.close
};
var mac = /Mac/.test(navigator.platform);
if (mac) {
baseMap["Ctrl-P"] = function() {handle.moveFocus(-1);};
baseMap["Ctrl-N"] = function() {handle.moveFocus(1);};
}
var custom = completion.options.customKeys;
var ourMap = custom ? {} : baseMap;
function addBinding(key, val) {
@ -204,58 +224,95 @@
}
function Widget(completion, data) {
this.id = "cm-complete-" + Math.floor(Math.random(1e6))
this.completion = completion;
this.data = data;
this.picked = false;
var widget = this, cm = completion.cm;
var ownerDocument = cm.getInputField().ownerDocument;
var parentWindow = ownerDocument.defaultView || ownerDocument.parentWindow;
var hints = this.hints = document.createElement("ul");
hints.className = "CodeMirror-hints";
var hints = this.hints = ownerDocument.createElement("ul");
hints.setAttribute("role", "listbox")
hints.setAttribute("aria-expanded", "true")
hints.id = this.id
var theme = completion.cm.options.theme;
hints.className = "CodeMirror-hints " + theme;
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 elt = hints.appendChild(ownerDocument.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 (i == this.selectedHint) elt.setAttribute("aria-selected", "true")
elt.id = this.id + "-" + i
elt.setAttribute("role", "option")
if (cur.render) cur.render(elt, data, cur);
else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
else elt.appendChild(ownerDocument.createTextNode(cur.displayText || getText(cur)));
elt.hintId = i;
}
var container = completion.options.container || ownerDocument.body;
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";
var offsetLeft = 0, offsetTop = 0;
if (container !== ownerDocument.body) {
// We offset the cursor position because left and top are relative to the offsetParent's top left corner.
var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
var offsetParent = isContainerPositioned ? container : container.offsetParent;
var offsetParentPosition = offsetParent.getBoundingClientRect();
var bodyPosition = ownerDocument.body.getBoundingClientRect();
offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
}
hints.style.left = (left - offsetLeft) + "px";
hints.style.top = (top - offsetTop) + "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 winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
container.appendChild(hints);
cm.getInputField().setAttribute("aria-autocomplete", "list")
cm.getInputField().setAttribute("aria-owns", this.id)
cm.getInputField().setAttribute("aria-activedescendant", this.id + "-" + this.selectedHint)
var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect();
var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false;
// Compute in the timeout to avoid reflow on init
var startScroll;
setTimeout(function() { startScroll = cm.getScrollInfo(); });
var overlapY = box.bottom - winH;
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";
hints.style.top = (top = pos.top - height - offsetTop) + "px";
below = false;
} else if (height > winH) {
hints.style.height = (winH - 5) + "px";
hints.style.top = (top = pos.bottom - box.top) + "px";
hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px";
var cursor = cm.getCursor();
if (data.from.ch != cursor.ch) {
pos = cm.cursorCoords(cursor);
hints.style.left = (left = pos.left) + "px";
hints.style.left = (left = pos.left - offsetLeft) + "px";
box = hints.getBoundingClientRect();
}
}
}
var overlapX = box.right - winW;
if (scrolls) overlapX += cm.display.nativeBarWidth;
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";
hints.style.left = (left = pos.left - overlapX - offsetLeft) + "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); },
@ -273,11 +330,11 @@
cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
}
var startScroll = cm.getScrollInfo();
cm.on("scroll", this.onScroll = function() {
var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
if (!startScroll) startScroll = cm.getScrollInfo();
var newTop = top + startScroll.top - curScroll.top;
var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
if (!below) point += hints.offsetHeight;
if (point <= editor.top || point >= editor.bottom) return completion.close();
hints.style.top = newTop + "px";
@ -301,7 +358,13 @@
setTimeout(function(){cm.focus();}, 20);
});
CodeMirror.signal(data, "select", completions[0], hints.firstChild);
// The first hint doesn't need to be scrolled to on init
var selectedHintRange = this.getSelectedHintRange();
if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
this.scrollToActive();
}
CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
return true;
}
@ -309,8 +372,11 @@
close: function() {
if (this.completion.widget != this) return;
this.completion.widget = null;
this.hints.parentNode.removeChild(this.hints);
if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints);
this.completion.cm.removeKeyMap(this.keyMap);
var input = this.completion.cm.getInputField()
input.removeAttribute("aria-activedescendant")
input.removeAttribute("aria-owns")
var cm = this.completion.cm;
if (this.completion.options.closeOnUnfocus) {
@ -320,6 +386,13 @@
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);
},
@ -331,49 +404,107 @@
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, "");
if (node) {
node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node.removeAttribute("aria-selected")
}
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;
node.setAttribute("aria-selected", "true")
this.completion.cm.getInputField().setAttribute("aria-activedescendant", node.id)
this.scrollToActive()
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
},
scrollToActive: function() {
var selectedHintRange = this.getSelectedHintRange();
var node1 = this.hints.childNodes[selectedHintRange.from];
var node2 = this.hints.childNodes[selectedHintRange.to];
var firstNode = this.hints.firstChild;
if (node1.offsetTop < this.hints.scrollTop)
this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
},
screenAmount: function() {
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
},
getSelectedHintRange: function() {
var margin = this.completion.options.scrollMargin || 0;
return {
from: Math.max(0, this.selectedHint - margin),
to: Math.min(this.data.list.length - 1, this.selectedHint + margin),
};
}
};
CodeMirror.registerHelper("hint", "auto", function(cm, options) {
var helpers = cm.getHelpers(cm.getCursor(), "hint"), words;
if (helpers.length) {
for (var i = 0; i < helpers.length; i++) {
var cur = helpers[i](cm, options);
if (cur && cur.list.length) return cur;
}
} else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
if (words) return CodeMirror.hint.fromList(cm, {words: words});
} else if (CodeMirror.hint.anyword) {
return CodeMirror.hint.anyword(cm, options);
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 cur = cm.getCursor(), token = cm.getTokenAt(cur)
var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
term = token.string.substr(0, cur.ch - token.start)
} else {
term = ""
from = cur
}
var found = [];
for (var i = 0; i < options.words.length; i++) {
var word = options.words[i];
if (word.slice(0, token.string.length) == token.string)
if (word.slice(0, term.length) == term)
found.push(word);
}
if (found.length) return {
list: found,
from: CodeMirror.Pos(cur.line, token.start),
to: CodeMirror.Pos(cur.line, token.end)
};
if (found.length) return {list: found, from: from, to: to};
});
CodeMirror.commands.autocomplete = CodeMirror.showHint;
@ -383,11 +514,15 @@
completeSingle: true,
alignWithWord: true,
closeCharacters: /[\s()\[\]{};:>,]/,
closeOnPick: true,
closeOnUnfocus: true,
completeOnSingleClick: false,
updateOnCursorActivity: true,
completeOnSingleClick: true,
container: null,
customKeys: null,
extraKeys: null
extraKeys: null,
paddingForScrollbar: true,
moveOnOverlap: true,
};
CodeMirror.defineOption("hintOptions", null);

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -14,11 +14,14 @@
var tables;
var defaultTable;
var keywords;
var identifierQuote;
var CONS = {
QUERY_DIV: ";",
ALIAS_KEYWORD: "AS"
};
var Pos = CodeMirror.Pos;
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;
@ -26,14 +29,38 @@
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 getItem(list, item) {
if (!list.slice) return list[item];
for (var i = list.length - 1; i >= 0; i--) if (getText(list[i]) == item)
return list[i];
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) {
@ -50,29 +77,41 @@
}
function addMatches(result, search, wordlist, formatter) {
for (var word in wordlist) {
if (!wordlist.hasOwnProperty(word)) continue;
if (Array.isArray(wordlist)) {
word = wordlist[word];
}
if (match(search, word)) {
result.push(formatter(word));
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 backticks(`) and preceding dot(.)
// Get rid name from identifierQuote and preceding dot(.)
if (name.charAt(0) == ".") {
name = name.substr(1);
}
return name.replace(/`/g, "");
// replace duplicated 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 insertBackticks(name) {
function insertIdentifierQuotes(name) {
var nameParts = getText(name).split(".");
for (var i = 0; i < nameParts.length; i++)
nameParts[i] = "`" + nameParts[i] + "`";
nameParts[i] = identifierQuote +
// duplicate identifierQuotes
nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
identifierQuote;
var escaped = nameParts.join(".");
if (typeof name == "string") return escaped;
name = shallowClone(name);
@ -81,14 +120,14 @@
}
function nameCompletion(cur, token, result, editor) {
// Try to complete table, colunm names and return start position of completion
var useBacktick = false;
// 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) == ".");
useBacktick = useBacktick || (token.string.charAt(0) == "`");
useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);
start = token.start;
nameParts.unshift(cleanName(token.string));
@ -103,35 +142,42 @@
// Try to complete table names
var string = nameParts.join(".");
addMatches(result, string, tables, function(w) {
return useBacktick ? insertBackticks(w) : w;
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
});
// Try to complete columns from defaultTable
addMatches(result, string, defaultTable, function(w) {
return useBacktick ? insertBackticks(w) : 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 (!getItem(tables, table))
if (!getTable(table)) {
var oldTable = table;
table = findTableByAlias(table, editor);
if (table !== oldTable) alias = true;
}
var columns = getItem(tables, table);
if (columns && Array.isArray(tables) && columns.columns)
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 = table + "." + w;
w = tableInsert + "." + w;
} else {
w = shallowClone(w);
w.text = table + "." + w.text;
w.text = tableInsert + "." + w.text;
}
return useBacktick ? insertBackticks(w) : w;
return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
});
}
@ -139,21 +185,9 @@
}
function eachWord(lineText, f) {
if (!lineText) return;
var excepted = /[,;]/g;
var words = lineText.split(" ");
for (var i = 0; i < words.length; i++) {
f(words[i]?words[i].replace(excepted, '') : '');
}
}
function convertCurToNumber(cur) {
// max characters of a line is 999,999.
return cur.line + cur.ch / Math.pow(10, 6);
}
function convertNumberToCur(num) {
return Pos(Math.floor(num), +num.toString().split('.').pop());
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) {
@ -178,38 +212,49 @@
separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
//find valid range
var prevItem = 0;
var current = convertCurToNumber(editor.getCursor());
for (var i=0; i< separator.length; i++) {
var _v = convertCurToNumber(separator[i]);
if (current > prevItem && current <= _v) {
validRange = { start: convertNumberToCur(prevItem), end: convertNumberToCur(_v) };
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 = _v;
prevItem = separator[i];
}
var query = doc.getRange(validRange.start, validRange.end, false);
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 && getItem(tables, previousWord))
table = previousWord;
if (wordUpperCase !== CONS.ALIAS_KEYWORD)
previousWord = word;
});
if (table) break;
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 = (options && options.tables) || {};
tables = parseTables(options && options.tables)
var defaultTableName = options && options.defaultTable;
defaultTable = (defaultTableName && getItem(tables, defaultTableName)) || [];
keywords = keywords || getKeywords(editor);
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 = [];
@ -219,7 +264,7 @@
token.string = token.string.slice(0, cur.ch - token.start);
}
if (token.string.match(/^[.`\w@]\w*$/)) {
if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
search = token.string;
start = token.start;
end = token.end;
@ -227,13 +272,32 @@
start = end = cur.ch;
search = "";
}
if (search.charAt(0) == "." || search.charAt(0) == "`") {
if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {
start = nameCompletion(cur, token, result, editor);
} else {
addMatches(result, search, tables, function(w) {return w;});
addMatches(result, search, defaultTable, function(w) {return w;});
addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
}
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)};
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -13,9 +13,15 @@
var Pos = CodeMirror.Pos;
function matches(hint, typed, matchInMiddle) {
if (matchInMiddle) return hint.indexOf(typed) >= 0;
else return hint.lastIndexOf(typed, 0) == 0;
}
function getHints(cm, options) {
var tags = options && options.schemaInfo;
var quote = (options && options.quoteChar) || '"';
var matchInMiddle = options && options.matchInMiddle;
if (!tags) return;
var cur = cm.getCursor(), token = cm.getTokenAt(cur);
if (token.end > cur.ch) {
@ -23,7 +29,7 @@
token.string = token.string.slice(0, cur.ch - token.start);
}
var inner = CodeMirror.innerMode(cm.getMode(), token.state);
if (inner.mode.name != "xml") return;
if (!inner.mode.xmlCurrentTag) return
var result = [], replaceToken = false, prefix;
var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
var tagName = tag && /^\w/.test(token.string), tagStart;
@ -38,25 +44,28 @@
tagType = "close";
}
if (!tag && !inner.state.tagName || tagType) {
var tagInfo = inner.mode.xmlCurrentTag(inner.state)
if (!tag && !tagInfo || tagType) {
if (tagName)
prefix = token.string;
replaceToken = tagType;
var cx = inner.state.context, curTag = cx && tags[cx.tagName];
var childList = cx ? curTag && curTag.children : tags["!top"];
var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
var inner = context.length && context[context.length - 1]
var curTag = inner && tags[inner]
var childList = inner ? curTag && curTag.children : tags["!top"];
if (childList && tagType != "close") {
for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
result.push("<" + childList[i]);
} else if (tagType != "close") {
for (var name in tags)
if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
result.push("<" + name);
}
if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))
result.push("</" + cx.tagName + ">");
if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
result.push("</" + inner + ">");
} else {
// Attribute completion
var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs;
var globalAttrs = tags["!attrs"];
if (!attrs && !globalAttrs) return;
if (!attrs) {
@ -86,24 +95,37 @@
quote = token.string.charAt(len - 1);
prefix = token.string.substr(n, len - 2);
}
if (n) { // an opening quote
var line = cm.getLine(cur.line);
if (line.length > token.end && line.charAt(token.end) == quote) token.end++; // include a closing quote
}
replaceToken = true;
}
for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0)
result.push(quote + atValues[i] + quote);
var returnHintsFromAtValues = function(atValues) {
if (atValues)
for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
result.push(quote + atValues[i] + quote);
return returnHints();
};
if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
return returnHintsFromAtValues(atValues);
} else { // An attribute name
if (token.type == "attribute") {
prefix = token.string;
replaceToken = true;
}
for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0))
for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || matches(attr, prefix, matchInMiddle)))
result.push(attr);
}
}
return {
list: result,
from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
to: replaceToken ? Pos(cur.line, token.end) : cur
};
function returnHints() {
return {
list: result,
from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
to: replaceToken ? Pos(cur.line, token.end) : cur
};
}
return returnHints();
}
CodeMirror.registerHelper("hint", "xml", getHints);

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Depends on coffeelint.js from http://www.coffeelint.org/js/coffeelint.js
@ -17,6 +17,12 @@
CodeMirror.registerHelper("lint", "coffeescript", function(text) {
var found = [];
if (!window.coffeelint) {
if (window.console) {
window.console.error("Error: window.coffeelint not defined, CodeMirror CoffeeScript linting cannot run.");
}
return found;
}
var parseError = function(err) {
var loc = err.lineNumber;
found.push({from: CodeMirror.Pos(loc-1, 0),

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Depends on csslint.js from https://github.com/stubbornella/csslint
@ -15,10 +15,15 @@
})(function(CodeMirror) {
"use strict";
CodeMirror.registerHelper("lint", "css", function(text) {
CodeMirror.registerHelper("lint", "css", function(text, options) {
var found = [];
if (!window.CSSLint) return found;
var results = CSSLint.verify(text), messages = results.messages, message = null;
if (!window.CSSLint) {
if (window.console) {
window.console.error("Error: window.CSSLint not defined, CodeMirror CSS linting cannot run.");
}
return found;
}
var results = CSSLint.verify(text, options), messages = results.messages, message = null;
for ( var i = 0; i < messages.length; i++) {
message = messages[i];
var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;

View File

@ -0,0 +1,59 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Depends on htmlhint.js from http://htmlhint.com/js/htmlhint.js
// declare global: HTMLHint
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("htmlhint"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "htmlhint"], mod);
else // Plain browser env
mod(CodeMirror, window.HTMLHint);
})(function(CodeMirror, HTMLHint) {
"use strict";
var defaultRules = {
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": false,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"attr-no-duplication": true
};
CodeMirror.registerHelper("lint", "html", function(text, options) {
var found = [];
if (HTMLHint && !HTMLHint.verify) {
if(typeof HTMLHint.default !== 'undefined') {
HTMLHint = HTMLHint.default;
} else {
HTMLHint = HTMLHint.HTMLHint;
}
}
if (!HTMLHint) HTMLHint = window.HTMLHint;
if (!HTMLHint) {
if (window.console) {
window.console.error("Error: HTMLHint not found, not defined on window, or not available through define/require, CodeMirror HTML linting cannot run.");
}
return found;
}
var messages = HTMLHint.verify(text, options && options.rules || defaultRules);
for (var i = 0; i < messages.length; i++) {
var message = messages[i];
var startLine = message.line - 1, endLine = message.line - 1, startCol = message.col - 1, endCol = message.col;
found.push({
from: CodeMirror.Pos(startLine, startCol),
to: CodeMirror.Pos(endLine, endCol),
message: message.message,
severity : message.type
});
}
return found;
});
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Depends on jsonlint.js from https://github.com/zaach/jsonlint
@ -17,6 +17,15 @@
CodeMirror.registerHelper("lint", "json", function(text) {
var found = [];
if (!window.jsonlint) {
if (window.console) {
window.console.error("Error: window.jsonlint not defined, CodeMirror JSON linting cannot run.");
}
return found;
}
// for jsonlint's web dist jsonlint is exported as an object with a single property parser, of which parseError
// is a subproperty
var jsonlint = window.jsonlint.parser || window.jsonlint
jsonlint.parseError = function(str, hash) {
var loc = hash.loc;
found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),

View File

@ -4,10 +4,10 @@
}
.CodeMirror-lint-tooltip {
background-color: infobackground;
background-color: #ffd;
border: 1px solid black;
border-radius: 4px 4px 4px 4px;
color: infotext;
color: black;
font-family: monospace;
font-size: 10pt;
overflow: hidden;
@ -25,22 +25,20 @@
-ms-transition: opacity .4s;
}
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
.CodeMirror-lint-mark {
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 {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
.CodeMirror-lint-mark-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==");
}
.CodeMirror-lint-marker {
background-position: center center;
background-repeat: no-repeat;
cursor: pointer;
@ -51,23 +49,31 @@
position: relative;
}
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
.CodeMirror-lint-message {
padding-left: 18px;
background-position: top left;
background-repeat: no-repeat;
}
.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 {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.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%;
}
.CodeMirror-lint-line-error {
background-color: rgba(183, 76, 81, 0.08);
}
.CodeMirror-lint-line-warning {
background-color: rgba(255, 211, 0, 0.1);
}

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,12 +11,16 @@
})(function(CodeMirror) {
"use strict";
var GUTTER_ID = "CodeMirror-lint-markers";
var LINT_LINE_ID = "CodeMirror-lint-line-";
function showTooltip(e, content) {
function showTooltip(cm, e, content) {
var tt = document.createElement("div");
tt.className = "CodeMirror-lint-tooltip";
tt.className = "CodeMirror-lint-tooltip cm-s-" + cm.options.theme;
tt.appendChild(content.cloneNode(true));
document.body.appendChild(tt);
if (cm.state.lint.options.selfContain)
cm.getWrapperElement().appendChild(tt);
else
document.body.appendChild(tt);
function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
@ -38,8 +42,8 @@
setTimeout(function() { rm(tt); }, 600);
}
function showTooltipFor(e, content, node) {
var tooltip = showTooltip(e, content);
function showTooltipFor(cm, e, content, node) {
var tooltip = showTooltip(cm, e, content);
function hide() {
CodeMirror.off(node, "mouseout", hide);
if (tooltip) { hideTooltip(tooltip); tooltip = null; }
@ -55,40 +59,64 @@
CodeMirror.on(node, "mouseout", hide);
}
function LintState(cm, options, hasGutter) {
function LintState(cm, conf, hasGutter) {
this.marked = [];
this.options = options;
if (conf instanceof Function) conf = {getAnnotations: conf};
if (!conf || conf === true) conf = {};
this.options = {};
this.linterOptions = conf.options || {};
for (var prop in defaults) this.options[prop] = defaults[prop];
for (var prop in conf) {
if (defaults.hasOwnProperty(prop)) {
if (conf[prop] != null) this.options[prop] = conf[prop];
} else if (!conf.options) {
this.linterOptions[prop] = conf[prop];
}
}
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 = {};
if (!options.getAnnotations) options.getAnnotations = cm.getHelper(CodeMirror.Pos(0, 0), "lint");
if (!options.getAnnotations) throw new Error("Required option 'getAnnotations' missing (lint addon)");
return options;
var defaults = {
highlightLines: false,
tooltips: true,
delay: 500,
lintOnChange: true,
getAnnotations: null,
async: false,
selfContain: null,
formatAnnotation: null,
onUpdateLinting: null
}
function clearMarks(cm) {
var state = cm.state.lint;
if (state.hasGutter) cm.clearGutter(GUTTER_ID);
if (state.options.highlightLines) clearErrorLines(cm);
for (var i = 0; i < state.marked.length; ++i)
state.marked[i].clear();
state.marked.length = 0;
}
function makeMarker(labels, severity, multiple, tooltips) {
function clearErrorLines(cm) {
cm.eachLine(function(line) {
var has = line.wrapClass && /\bCodeMirror-lint-line-\w+\b/.exec(line.wrapClass);
if (has) cm.removeLineClass(line, "wrap", has[0]);
})
}
function makeMarker(cm, labels, severity, multiple, tooltips) {
var marker = document.createElement("div"), inner = marker;
marker.className = "CodeMirror-lint-marker-" + severity;
marker.className = "CodeMirror-lint-marker CodeMirror-lint-marker-" + severity;
if (multiple) {
inner = marker.appendChild(document.createElement("div"));
inner.className = "CodeMirror-lint-marker-multiple";
inner.className = "CodeMirror-lint-marker CodeMirror-lint-marker-multiple";
}
if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
showTooltipFor(e, labels, inner);
showTooltipFor(cm, e, labels, inner);
});
return marker;
@ -112,23 +140,58 @@
var severity = ann.severity;
if (!severity) severity = "error";
var tip = document.createElement("div");
tip.className = "CodeMirror-lint-message-" + severity;
tip.appendChild(document.createTextNode(ann.message));
tip.className = "CodeMirror-lint-message 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) {
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)})
}, state.linterOptions, cm);
}
function startLinting(cm) {
var state = cm.state.lint, options = state.options;
var passOptions = options.options || options; // Support deprecated passing of `options` property in options
if (options.async || options.getAnnotations.async)
options.getAnnotations(cm.getValue(), updateLinting, passOptions, cm);
else
updateLinting(cm, options.getAnnotations(cm.getValue(), passOptions, cm));
var state = cm.state.lint;
if (!state) return;
var options = state.options;
/*
* Passing rules in `options` property prevents JSHint (and other linters) from complaining
* about unrecognized rules like `onUpdateLinting`, `delay`, `lintOnChange`, etc.
*/
var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
if (!getAnnotations) return;
if (options.async || getAnnotations.async) {
lintAsync(cm, getAnnotations)
} else {
var annotations = getAnnotations(cm.getValue(), state.linterOptions, 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) {
var state = cm.state.lint;
if (!state) return;
var options = state.options;
clearMarks(cm);
var state = cm.state.lint, options = state.options;
var annotations = groupByLine(annotationsNotSorted);
@ -136,6 +199,10 @@
var anns = annotations[line];
if (!anns) continue;
// filter out duplicate messages
var message = [];
anns = anns.filter(function(item) { return message.indexOf(item.message) > -1 ? false : message.push(item.message) });
var maxSeverity = null;
var tipLabel = state.hasGutter && document.createDocumentFragment();
@ -149,27 +216,36 @@
if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
className: "CodeMirror-lint-mark-" + severity,
className: "CodeMirror-lint-mark CodeMirror-lint-mark-" + severity,
__annotation: ann
}));
}
// use original annotations[line] to show multiple messages
if (state.hasGutter)
cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
state.options.tooltips));
cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, annotations[line].length > 1,
options.tooltips));
if (options.highlightLines)
cm.addLineClass(line, "wrap", LINT_LINE_ID + maxSeverity);
}
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);
state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay);
}
function popupSpanTooltip(ann, e) {
function popupTooltips(cm, annotations, e) {
var target = e.target || e.srcElement;
showTooltipFor(e, annotationTooltip(ann), target);
var tooltip = document.createDocumentFragment();
for (var i = 0; i < annotations.length; i++) {
var ann = annotations[i];
tooltip.appendChild(annotationTooltip(ann));
}
showTooltipFor(cm, e, tooltip, target);
}
function onMouseOver(cm, e) {
@ -177,29 +253,39 @@
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) return popupSpanTooltip(ann, e);
if (ann) annotations.push(ann);
}
if (annotations.length) popupTooltips(cm, annotations, e);
}
CodeMirror.defineOption("lint", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
clearMarks(cm);
cm.off("change", onChange);
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);
cm.on("change", onChange);
if (state.options.tooltips != false)
var state = cm.state.lint = new LintState(cm, val, hasLintGutter);
if (state.options.lintOnChange)
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() {
startLinting(this);
});
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -17,10 +17,23 @@
CodeMirror.registerHelper("lint", "yaml", function(text) {
var found = [];
try { jsyaml.load(text); }
if (!window.jsyaml) {
if (window.console) {
window.console.error("Error: window.jsyaml not defined, CodeMirror YAML linting cannot run.");
}
return found;
}
try { jsyaml.loadAll(text); }
catch(e) {
var loc = e.mark;
found.push({ from: CodeMirror.Pos(loc.line, loc.column), to: CodeMirror.Pos(loc.line, loc.column), message: e.message });
var loc = e.mark,
// js-yaml YAMLException doesn't always provide an accurate lineno
// e.g., when there are multiple yaml docs
// ---
// ---
// foo:bar
from = loc ? CodeMirror.Pos(loc.line, loc.column) : CodeMirror.Pos(0, 0),
to = from;
found.push({ from: from, to: to, message: e.message });
}
return found;
});

View File

@ -48,6 +48,12 @@
color: #555;
line-height: 1;
}
.CodeMirror-merge-scrolllock:after {
content: "\21db\00a0\00a0\21da";
}
.CodeMirror-merge-scrolllock.CodeMirror-merge-scrolllock-enabled:after {
content: "\21db\21da";
}
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
position: absolute;
@ -60,6 +66,7 @@
position: absolute;
cursor: pointer;
color: #44c;
z-index: 3;
}
.CodeMirror-merge-copy-reverse {

View File

@ -1,16 +1,16 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// declare global: diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("diff_match_patch"));
mod(require("../../lib/codemirror")); // Note non-packaged dependency diff_match_patch
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "diff_match_patch"], mod);
else // Plain browser env
mod(CodeMirror, diff_match_patch);
})(function(CodeMirror, diff_match_patch) {
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
var svgNS = "http://www.w3.org/2000/svg";
@ -37,16 +37,30 @@
constructor: DiffView,
init: function(pane, orig, options) {
this.edit = this.mv.edit;
;(this.edit.state.diffViews || (this.edit.state.diffViews = [])).push(this);
this.orig = CodeMirror(pane, copyObj({value: orig, readOnly: !this.mv.options.allowEditingOriginals}, copyObj(options)));
if (this.mv.options.connect == "align") {
if (!this.edit.state.trackAlignable) this.edit.state.trackAlignable = new TrackAlignable(this.edit)
this.orig.state.trackAlignable = new TrackAlignable(this.orig)
}
this.lockButton.title = this.edit.phrase("Toggle locked scrolling");
this.diff = getDiff(asString(orig), asString(options.value));
this.orig.state.diffViews = [this];
var classLocation = options.chunkClassLocation || "background";
if (Object.prototype.toString.call(classLocation) != "[object Array]") classLocation = [classLocation]
this.classes.classLocation = classLocation
this.diff = getDiff(asString(orig), asString(options.value), this.mv.options.ignoreWhitespace);
this.chunks = getChunks(this.diff);
this.diffOutOfDate = this.dealigned = false;
this.needsScrollSync = null
this.showDifferences = options.showDifferences !== false;
},
registerEvents: function(otherDv) {
this.forceUpdate = registerUpdate(this);
setScrollLock(this, true, false);
registerScroll(this);
registerScroll(this, otherDv);
},
setShowDifferences: function(val) {
val = val !== false;
@ -59,7 +73,7 @@
function ensureDiff(dv) {
if (dv.diffOutOfDate) {
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue());
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue(), dv.mv.options.ignoreWhitespace);
dv.chunks = getChunks(dv.diff);
dv.diffOutOfDate = false;
CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
@ -86,10 +100,12 @@
updateMarks(dv.edit, dv.diff, edit, DIFF_INSERT, dv.classes);
updateMarks(dv.orig, dv.diff, orig, DIFF_DELETE, dv.classes);
}
makeConnections(dv);
if (dv.mv.options.connect == "align")
alignChunks(dv);
makeConnections(dv);
if (dv.needsScrollSync != null) syncScroll(dv, dv.needsScrollSync)
updating = false;
}
function setDealign(fast) {
@ -111,37 +127,49 @@
// Update faster when a line was added/removed
setDealign(change.text.length - 1 != change.to.line - change.from.line);
}
function swapDoc() {
dv.diffOutOfDate = true;
dv.dealigned = true;
update("full");
}
dv.edit.on("change", change);
dv.orig.on("change", change);
dv.edit.on("markerAdded", setDealign);
dv.edit.on("markerCleared", setDealign);
dv.orig.on("markerAdded", setDealign);
dv.orig.on("markerCleared", setDealign);
dv.edit.on("swapDoc", swapDoc);
dv.orig.on("swapDoc", swapDoc);
if (dv.mv.options.connect == "align") {
CodeMirror.on(dv.edit.state.trackAlignable, "realign", setDealign)
CodeMirror.on(dv.orig.state.trackAlignable, "realign", setDealign)
}
dv.edit.on("viewportChange", function() { set(false); });
dv.orig.on("viewportChange", function() { set(false); });
update();
return update;
}
function registerScroll(dv) {
function registerScroll(dv, otherDv) {
dv.edit.on("scroll", function() {
syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
syncScroll(dv, true) && makeConnections(dv);
});
dv.orig.on("scroll", function() {
syncScroll(dv, DIFF_DELETE) && makeConnections(dv);
syncScroll(dv, false) && makeConnections(dv);
if (otherDv) syncScroll(otherDv, true) && makeConnections(otherDv);
});
}
function syncScroll(dv, type) {
function syncScroll(dv, toOrig) {
// Change handler will do a refresh after a timeout when diff is out of date
if (dv.diffOutOfDate) return false;
if (dv.diffOutOfDate) {
if (dv.lockScroll && dv.needsScrollSync == null) dv.needsScrollSync = toOrig
return false
}
dv.needsScrollSync = null
if (!dv.lockScroll) return true;
var editor, other, now = +new Date;
if (type == DIFF_INSERT) { editor = dv.edit; other = dv.orig; }
if (toOrig) { editor = dv.edit; other = dv.orig; }
else { editor = dv.orig; other = dv.edit; }
// Don't take action if the position of this editor was recently set
// (to prevent feedback loops)
if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 50 > now) return false;
if (editor.state.scrollSetBy == dv && (editor.state.scrollSetAt || 0) + 250 > now) return false;
var sInfo = editor.getScrollInfo();
if (dv.mv.options.connect == "align") {
@ -149,9 +177,9 @@
} else {
var halfScreen = .5 * sInfo.clientHeight, midY = sInfo.top + halfScreen;
var mid = editor.lineAtHeight(midY, "local");
var around = chunkBoundariesAround(dv.chunks, mid, type == DIFF_INSERT);
var off = getOffsets(editor, type == DIFF_INSERT ? around.edit : around.orig);
var offOther = getOffsets(other, type == DIFF_INSERT ? around.orig : around.edit);
var around = chunkBoundariesAround(dv.chunks, mid, toOrig);
var off = getOffsets(editor, toOrig ? around.edit : around.orig);
var offOther = getOffsets(other, toOrig ? around.orig : around.edit);
var ratio = (midY - off.top) / (off.bot - off.top);
var targetPos = (offOther.top - halfScreen) + ratio * (offOther.bot - offOther.top);
@ -184,21 +212,27 @@
function setScrollLock(dv, val, action) {
dv.lockScroll = val;
if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db&nbsp;&nbsp;\u21da";
(val ? CodeMirror.addClass : CodeMirror.rmClass)(dv.lockButton, "CodeMirror-merge-scrolllock-enabled");
}
// Updating the marks for editor content
function removeClass(editor, line, classes) {
var locs = classes.classLocation
for (var i = 0; i < locs.length; i++) {
editor.removeLineClass(line, locs[i], classes.chunk);
editor.removeLineClass(line, locs[i], classes.start);
editor.removeLineClass(line, locs[i], classes.end);
}
}
function clearMarks(editor, arr, classes) {
for (var i = 0; i < arr.length; ++i) {
var mark = arr[i];
if (mark instanceof CodeMirror.TextMarker) {
if (mark instanceof CodeMirror.TextMarker)
mark.clear();
} else if (mark.parent) {
editor.removeLineClass(mark, "background", classes.chunk);
editor.removeLineClass(mark, "background", classes.start);
editor.removeLineClass(mark, "background", classes.end);
}
else if (mark.parent)
removeClass(editor, mark, classes);
}
arr.length = 0;
}
@ -224,28 +258,34 @@
});
}
function addClass(editor, lineNr, classes, main, start, end) {
var locs = classes.classLocation, line = editor.getLineHandle(lineNr);
for (var i = 0; i < locs.length; i++) {
if (main) editor.addLineClass(line, locs[i], classes.chunk);
if (start) editor.addLineClass(line, locs[i], classes.start);
if (end) editor.addLineClass(line, locs[i], classes.end);
}
return line;
}
function markChanges(editor, diff, type, marks, from, to, classes) {
var pos = Pos(0, 0);
var top = Pos(from, 0), bot = editor.clipPos(Pos(to - 1));
var cls = type == DIFF_DELETE ? classes.del : classes.insert;
function markChunk(start, end) {
var bfrom = Math.max(from, start), bto = Math.min(to, end);
for (var i = bfrom; i < bto; ++i) {
var line = editor.addLineClass(i, "background", classes.chunk);
if (i == start) editor.addLineClass(line, "background", classes.start);
if (i == end - 1) editor.addLineClass(line, "background", classes.end);
marks.push(line);
}
for (var i = bfrom; i < bto; ++i)
marks.push(addClass(editor, i, classes, true, i == start, i == end - 1));
// When the chunk is empty, make sure a horizontal line shows up
if (start == end && bfrom == end && bto == end) {
if (bfrom)
marks.push(editor.addLineClass(bfrom - 1, "background", classes.end));
marks.push(addClass(editor, bfrom - 1, classes, false, false, true));
else
marks.push(editor.addLineClass(bfrom, "background", classes.start));
marks.push(addClass(editor, bfrom, classes, false, true, false));
}
}
var chunkStart = 0;
var chunkStart = 0, pending = false;
for (var i = 0; i < diff.length; ++i) {
var part = diff[i], tp = part[0], str = part[1];
if (tp == DIFF_EQUAL) {
@ -253,10 +293,11 @@
moveOver(pos, str);
var cleanTo = pos.line + (endOfLineClean(diff, i) ? 1 : 0);
if (cleanTo > cleanFrom) {
if (i) markChunk(chunkStart, cleanFrom);
if (pending) { markChunk(chunkStart, cleanFrom); pending = false }
chunkStart = cleanTo;
}
} else {
pending = true
if (tp == type) {
var end = moveOver(pos, str, true);
var a = posMax(top, pos), b = posMin(bot, end);
@ -266,7 +307,7 @@
}
}
}
if (chunkStart <= pos.line) markChunk(chunkStart, pos.line + 1);
if (pending) markChunk(chunkStart, pos.line + 1);
}
// Updating the gap between editor and original
@ -282,7 +323,9 @@
if (dv.copyButtons) clear(dv.copyButtons);
var vpEdit = dv.edit.getViewport(), vpOrig = dv.orig.getViewport();
var sTopEdit = dv.edit.getScrollInfo().top, sTopOrig = dv.orig.getScrollInfo().top;
var outerTop = dv.mv.wrap.getBoundingClientRect().top
var sTopEdit = outerTop - dv.edit.getScrollerElement().getBoundingClientRect().top + dv.edit.getScrollInfo().top
var sTopOrig = outerTop - dv.orig.getScrollerElement().getBoundingClientRect().top + dv.orig.getScrollInfo().top;
for (var i = 0; i < dv.chunks.length; i++) {
var ch = dv.chunks[i];
if (ch.editFrom <= vpEdit.to && ch.editTo >= vpEdit.from &&
@ -303,29 +346,81 @@
return origStart + (editLine - editStart);
}
function findAlignedLines(dv, other) {
var linesToAlign = [];
for (var i = 0; i < dv.chunks.length; i++) {
var chunk = dv.chunks[i];
linesToAlign.push([chunk.origTo, chunk.editTo, other ? getMatchingOrigLine(chunk.editTo, other.chunks) : null]);
// Combines information about chunks and widgets/markers to return
// an array of lines, in a single editor, that probably need to be
// aligned with their counterparts in the editor next to it.
function alignableFor(cm, chunks, isOrig) {
var tracker = cm.state.trackAlignable
var start = cm.firstLine(), trackI = 0
var result = []
for (var i = 0;; i++) {
var chunk = chunks[i]
var chunkStart = !chunk ? 1e9 : isOrig ? chunk.origFrom : chunk.editFrom
for (; trackI < tracker.alignable.length; trackI += 2) {
var n = tracker.alignable[trackI] + 1
if (n <= start) continue
if (n <= chunkStart) result.push(n)
else break
}
if (!chunk) break
result.push(start = isOrig ? chunk.origTo : chunk.editTo)
}
if (other) {
for (var i = 0; i < other.chunks.length; i++) {
var chunk = other.chunks[i];
for (var j = 0; j < linesToAlign.length; j++) {
var align = linesToAlign[j];
if (align[1] == chunk.editTo) {
j = -1;
break;
} else if (align[1] > chunk.editTo) {
break;
}
return result
}
// Given information about alignable lines in two editors, fill in
// the result (an array of three-element arrays) to reflect the
// lines that need to be aligned with each other.
function mergeAlignable(result, origAlignable, chunks, setIndex) {
var rI = 0, origI = 0, chunkI = 0, diff = 0
outer: for (;; rI++) {
var nextR = result[rI], nextO = origAlignable[origI]
if (!nextR && nextO == null) break
var rLine = nextR ? nextR[0] : 1e9, oLine = nextO == null ? 1e9 : nextO
while (chunkI < chunks.length) {
var chunk = chunks[chunkI]
if (chunk.origFrom <= oLine && chunk.origTo > oLine) {
origI++
rI--
continue outer;
}
if (j > -1)
linesToAlign.splice(j - 1, 0, [getMatchingOrigLine(chunk.editTo, dv.chunks), chunk.editTo, chunk.origTo]);
if (chunk.editTo > rLine) {
if (chunk.editFrom <= rLine) continue outer;
break
}
diff += (chunk.origTo - chunk.origFrom) - (chunk.editTo - chunk.editFrom)
chunkI++
}
if (rLine == oLine - diff) {
nextR[setIndex] = oLine
origI++
} else if (rLine < oLine - diff) {
nextR[setIndex] = rLine + diff
} else {
var record = [oLine - diff, null, null]
record[setIndex] = oLine
result.splice(rI, 0, record)
origI++
}
}
return linesToAlign;
}
function findAlignedLines(dv, other) {
var alignable = alignableFor(dv.edit, dv.chunks, false), result = []
if (other) for (var i = 0, j = 0; i < other.chunks.length; i++) {
var n = other.chunks[i].editTo
while (j < alignable.length && alignable[j] < n) j++
if (j == alignable.length || alignable[j] != n) alignable.splice(j++, 0, n)
}
for (var i = 0; i < alignable.length; i++)
result.push([alignable[i], null, null])
mergeAlignable(result, alignableFor(dv.orig, dv.chunks, true), dv.chunks, 1)
if (other)
mergeAlignable(result, alignableFor(other.orig, other.chunks, true), other.chunks, 2)
return result
}
function alignChunks(dv, force) {
@ -348,22 +443,26 @@
aligners[i].clear();
aligners.length = 0;
var cm = [dv.orig, dv.edit], scroll = [];
var cm = [dv.edit, dv.orig], scroll = [], offset = []
if (other) cm.push(other.orig);
for (var i = 0; i < cm.length; i++)
for (var i = 0; i < cm.length; i++) {
scroll.push(cm[i].getScrollInfo().top);
offset.push(-cm[i].getScrollerElement().getBoundingClientRect().top)
}
if (offset[0] != offset[1] || cm.length == 3 && offset[1] != offset[2])
alignLines(cm, offset, [0, 0, 0], aligners)
for (var ln = 0; ln < linesToAlign.length; ln++)
alignLines(cm, linesToAlign[ln], aligners);
alignLines(cm, offset, linesToAlign[ln], aligners);
for (var i = 0; i < cm.length; i++)
cm[i].scrollTo(null, scroll[i]);
}
function alignLines(cm, lines, aligners) {
var maxOffset = 0, offset = [];
function alignLines(cm, cmOffset, lines, aligners) {
var maxOffset = -1e8, offset = [];
for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
var off = cm[i].heightAtLine(lines[i], "local");
var off = cm[i].heightAtLine(lines[i], "local") - cmOffset[i];
offset[i] = off;
maxOffset = Math.max(maxOffset, off);
}
@ -383,18 +482,18 @@
var elt = document.createElement("div");
elt.className = "CodeMirror-merge-spacer";
elt.style.height = size + "px"; elt.style.minWidth = "1px";
return cm.addLineWidget(line, elt, {height: size, above: above});
return cm.addLineWidget(line, elt, {height: size, above: above, mergeSpacer: true, handleMouseEvents: true});
}
function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
var flip = dv.type == "left";
var top = dv.orig.heightAtLine(chunk.origFrom, "local") - sTopOrig;
var top = dv.orig.heightAtLine(chunk.origFrom, "local", true) - sTopOrig;
if (dv.svg) {
var topLpx = top;
var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
var topRpx = dv.edit.heightAtLine(chunk.editFrom, "local", true) - sTopEdit;
if (flip) { var tmp = topLpx; topLpx = topRpx; topRpx = tmp; }
var botLpx = dv.orig.heightAtLine(chunk.origTo, "local") - sTopOrig;
var botRpx = dv.edit.heightAtLine(chunk.editTo, "local") - sTopEdit;
var botLpx = dv.orig.heightAtLine(chunk.origTo, "local", true) - sTopOrig;
var botRpx = dv.edit.heightAtLine(chunk.editTo, "local", true) - sTopEdit;
if (flip) { var tmp = botLpx; botLpx = botRpx; botRpx = tmp; }
var curveTop = " C " + w/2 + " " + topRpx + " " + w/2 + " " + topLpx + " " + (w + 2) + " " + topLpx;
var curveBot = " C " + w/2 + " " + botLpx + " " + w/2 + " " + botRpx + " -1 " + botRpx;
@ -406,12 +505,13 @@
var copy = dv.copyButtons.appendChild(elt("div", dv.type == "left" ? "\u21dd" : "\u21dc",
"CodeMirror-merge-copy"));
var editOriginals = dv.mv.options.allowEditingOriginals;
copy.title = editOriginals ? "Push to left" : "Revert chunk";
copy.title = dv.edit.phrase(editOriginals ? "Push to left" : "Revert chunk");
copy.chunk = chunk;
copy.style.top = top + "px";
copy.style.top = (chunk.origTo > chunk.origFrom ? top : dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit) + "px";
copy.setAttribute("role", "button");
if (editOriginals) {
var topReverse = dv.orig.heightAtLine(chunk.editFrom, "local") - sTopEdit;
var topReverse = dv.edit.heightAtLine(chunk.editFrom, "local") - sTopEdit;
var copyReverse = dv.copyButtons.appendChild(elt("div", dv.type == "right" ? "\u21dd" : "\u21dc",
"CodeMirror-merge-copy-reverse"));
copyReverse.title = "Push to right";
@ -419,14 +519,22 @@
origFrom: chunk.editFrom, origTo: chunk.editTo};
copyReverse.style.top = topReverse + "px";
dv.type == "right" ? copyReverse.style.left = "2px" : copyReverse.style.right = "2px";
copyReverse.setAttribute("role", "button");
}
}
}
function copyChunk(dv, to, from, chunk) {
if (dv.diffOutOfDate) return;
to.replaceRange(from.getRange(Pos(chunk.origFrom, 0), Pos(chunk.origTo, 0)),
Pos(chunk.editFrom, 0), Pos(chunk.editTo, 0));
var origStart = chunk.origTo > from.lastLine() ? Pos(chunk.origFrom - 1) : Pos(chunk.origFrom, 0)
var origEnd = Pos(chunk.origTo, 0)
var editStart = chunk.editTo > to.lastLine() ? Pos(chunk.editFrom - 1) : Pos(chunk.editFrom, 0)
var editEnd = Pos(chunk.editTo, 0)
var handler = dv.mv.options.revertChunk
if (handler)
handler(dv.mv, from, origStart, origEnd, to, editStart, editEnd)
else
to.replaceRange(from.getRange(origStart, origEnd), editStart, editEnd)
}
// Merge view, containing 0, 1, or 2 diff views.
@ -444,18 +552,18 @@
if (hasLeft) {
left = this.left = new DiffView(this, "left");
var leftPane = elt("div", null, "CodeMirror-merge-pane");
var leftPane = elt("div", null, "CodeMirror-merge-pane CodeMirror-merge-left");
wrap.push(leftPane);
wrap.push(buildGap(left));
}
var editPane = elt("div", null, "CodeMirror-merge-pane");
var editPane = elt("div", null, "CodeMirror-merge-pane CodeMirror-merge-editor");
wrap.push(editPane);
if (hasRight) {
right = this.right = new DiffView(this, "right");
wrap.push(buildGap(right));
var rightPane = elt("div", null, "CodeMirror-merge-pane");
var rightPane = elt("div", null, "CodeMirror-merge-pane CodeMirror-merge-right");
wrap.push(rightPane);
}
@ -468,18 +576,17 @@
if (left) left.init(leftPane, origLeft, options);
if (right) right.init(rightPane, origRight, options);
if (options.collapseIdentical) {
updating = true;
if (options.collapseIdentical)
this.editor().operation(function() {
collapseIdenticalStretches(self, options.collapseIdentical);
});
updating = false;
}
if (options.connect == "align") {
this.aligners = [];
alignChunks(this.left || this.right, true);
}
if (left) left.registerEvents(right)
if (right) right.registerEvents(left)
var onResize = function() {
if (left) makeConnections(left);
@ -494,7 +601,7 @@
function buildGap(dv) {
var lock = dv.lockButton = elt("div", null, "CodeMirror-merge-scrolllock");
lock.title = "Toggle locked scrolling";
lock.setAttribute("role", "button");
var lockWrap = elt("div", [lock], "CodeMirror-merge-scrolllock-wrap");
CodeMirror.on(lock, "click", function() { setScrollLock(dv, !dv.lockScroll); });
var gapElts = [lockWrap];
@ -522,7 +629,7 @@
}
MergeView.prototype = {
constuctor: MergeView,
constructor: MergeView,
editor: function() { return this.edit; },
rightOriginal: function() { return this.right && this.right.orig; },
leftOriginal: function() { return this.left && this.left.orig; },
@ -544,15 +651,15 @@
}
// Operations on diffs
var dmp;
function getDiff(a, b, ignoreWhitespace) {
if (!dmp) dmp = new diff_match_patch();
var dmp = new diff_match_patch();
function getDiff(a, b) {
var diff = dmp.diff_main(a, b);
dmp.diff_cleanupSemantic(diff);
// The library sometimes leaves in empty parts, which confuse the algorithm
for (var i = 0; i < diff.length; ++i) {
var part = diff[i];
if (!part[1]) {
if (ignoreWhitespace ? !/[^ \t]/.test(part[1]) : !part[1]) {
diff.splice(i--, 1);
} else if (i && diff[i - 1][0] == part[0]) {
diff.splice(i--, 1);
@ -564,12 +671,13 @@
function getChunks(diff) {
var chunks = [];
if (!diff.length) return chunks;
var startEdit = 0, startOrig = 0;
var edit = Pos(0, 0), orig = Pos(0, 0);
for (var i = 0; i < diff.length; ++i) {
var part = diff[i], tp = part[0];
if (tp == DIFF_EQUAL) {
var startOff = startOfLineClean(diff, i) ? 0 : 1;
var startOff = !startOfLineClean(diff, i) || edit.line < startEdit || orig.line < startOrig ? 1 : 0;
var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
moveOver(edit, part[1], null, orig);
var endOff = endOfLineClean(diff, i) ? 1 : 0;
@ -592,10 +700,10 @@
function endOfLineClean(diff, i) {
if (i == diff.length - 1) return true;
var next = diff[i + 1][1];
if (next.length == 1 || next.charCodeAt(0) != 10) return false;
if ((next.length == 1 && i < diff.length - 2) || next.charCodeAt(0) != 10) return false;
if (i == diff.length - 2) return true;
next = diff[i + 2][1];
return next.length > 1 && next.charCodeAt(0) == 10;
return (next.length > 1 || i == diff.length - 3) && next.charCodeAt(0) == 10;
}
function startOfLineClean(diff, i) {
@ -627,7 +735,7 @@
cm.addLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
var widget = document.createElement("span");
widget.className = "CodeMirror-merge-collapsed-widget";
widget.title = "Identical text collapsed. Click to expand.";
widget.title = cm.phrase("Identical text collapsed. Click to expand.");
var mark = cm.markText(Pos(from, 0), Pos(to - 1), {
inclusiveLeft: true,
inclusiveRight: true,
@ -638,7 +746,10 @@
mark.clear();
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
}
widget.addEventListener("click", clear);
if (mark.explicitlyCleared) clear();
CodeMirror.on(widget, "click", clear);
mark.on("clear", clear);
CodeMirror.on(widget, "click", clear);
return {mark: mark, clear: clear};
}
@ -729,7 +840,170 @@
return out;
}
// Tracks collapsed markers and line widgets, in order to be able to
// accurately align the content of two editors.
var F_WIDGET = 1, F_WIDGET_BELOW = 2, F_MARKER = 4
function TrackAlignable(cm) {
this.cm = cm
this.alignable = []
this.height = cm.doc.height
var self = this
cm.on("markerAdded", function(_, marker) {
if (!marker.collapsed) return
var found = marker.find(1)
if (found != null) self.set(found.line, F_MARKER)
})
cm.on("markerCleared", function(_, marker, _min, max) {
if (max != null && marker.collapsed)
self.check(max, F_MARKER, self.hasMarker)
})
cm.on("markerChanged", this.signal.bind(this))
cm.on("lineWidgetAdded", function(_, widget, lineNo) {
if (widget.mergeSpacer) return
if (widget.above) self.set(lineNo - 1, F_WIDGET_BELOW)
else self.set(lineNo, F_WIDGET)
})
cm.on("lineWidgetCleared", function(_, widget, lineNo) {
if (widget.mergeSpacer) return
if (widget.above) self.check(lineNo - 1, F_WIDGET_BELOW, self.hasWidgetBelow)
else self.check(lineNo, F_WIDGET, self.hasWidget)
})
cm.on("lineWidgetChanged", this.signal.bind(this))
cm.on("change", function(_, change) {
var start = change.from.line, nBefore = change.to.line - change.from.line
var nAfter = change.text.length - 1, end = start + nAfter
if (nBefore || nAfter) self.map(start, nBefore, nAfter)
self.check(end, F_MARKER, self.hasMarker)
if (nBefore || nAfter) self.check(change.from.line, F_MARKER, self.hasMarker)
})
cm.on("viewportChange", function() {
if (self.cm.doc.height != self.height) self.signal()
})
}
TrackAlignable.prototype = {
signal: function() {
CodeMirror.signal(this, "realign")
this.height = this.cm.doc.height
},
set: function(n, flags) {
var pos = -1
for (; pos < this.alignable.length; pos += 2) {
var diff = this.alignable[pos] - n
if (diff == 0) {
if ((this.alignable[pos + 1] & flags) == flags) return
this.alignable[pos + 1] |= flags
this.signal()
return
}
if (diff > 0) break
}
this.signal()
this.alignable.splice(pos, 0, n, flags)
},
find: function(n) {
for (var i = 0; i < this.alignable.length; i += 2)
if (this.alignable[i] == n) return i
return -1
},
check: function(n, flag, pred) {
var found = this.find(n)
if (found == -1 || !(this.alignable[found + 1] & flag)) return
if (!pred.call(this, n)) {
this.signal()
var flags = this.alignable[found + 1] & ~flag
if (flags) this.alignable[found + 1] = flags
else this.alignable.splice(found, 2)
}
},
hasMarker: function(n) {
var handle = this.cm.getLineHandle(n)
if (handle.markedSpans) for (var i = 0; i < handle.markedSpans.length; i++)
if (handle.markedSpans[i].marker.collapsed && handle.markedSpans[i].to != null)
return true
return false
},
hasWidget: function(n) {
var handle = this.cm.getLineHandle(n)
if (handle.widgets) for (var i = 0; i < handle.widgets.length; i++)
if (!handle.widgets[i].above && !handle.widgets[i].mergeSpacer) return true
return false
},
hasWidgetBelow: function(n) {
if (n == this.cm.lastLine()) return false
var handle = this.cm.getLineHandle(n + 1)
if (handle.widgets) for (var i = 0; i < handle.widgets.length; i++)
if (handle.widgets[i].above && !handle.widgets[i].mergeSpacer) return true
return false
},
map: function(from, nBefore, nAfter) {
var diff = nAfter - nBefore, to = from + nBefore, widgetFrom = -1, widgetTo = -1
for (var i = 0; i < this.alignable.length; i += 2) {
var n = this.alignable[i]
if (n == from && (this.alignable[i + 1] & F_WIDGET_BELOW)) widgetFrom = i
if (n == to && (this.alignable[i + 1] & F_WIDGET_BELOW)) widgetTo = i
if (n <= from) continue
else if (n < to) this.alignable.splice(i--, 2)
else this.alignable[i] += diff
}
if (widgetFrom > -1) {
var flags = this.alignable[widgetFrom + 1]
if (flags == F_WIDGET_BELOW) this.alignable.splice(widgetFrom, 2)
else this.alignable[widgetFrom + 1] = flags & ~F_WIDGET_BELOW
}
if (widgetTo > -1 && nAfter)
this.set(from + nAfter, F_WIDGET_BELOW)
}
}
function posMin(a, b) { return (a.line - b.line || a.ch - b.ch) < 0 ? a : b; }
function posMax(a, b) { return (a.line - b.line || a.ch - b.ch) > 0 ? a : b; }
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
function findPrevDiff(chunks, start, isOrig) {
for (var i = chunks.length - 1; i >= 0; i--) {
var chunk = chunks[i];
var to = (isOrig ? chunk.origTo : chunk.editTo) - 1;
if (to < start) return to;
}
}
function findNextDiff(chunks, start, isOrig) {
for (var i = 0; i < chunks.length; i++) {
var chunk = chunks[i];
var from = (isOrig ? chunk.origFrom : chunk.editFrom);
if (from > start) return from;
}
}
function goNearbyDiff(cm, dir) {
var found = null, views = cm.state.diffViews, line = cm.getCursor().line;
if (views) for (var i = 0; i < views.length; i++) {
var dv = views[i], isOrig = cm == dv.orig;
ensureDiff(dv);
var pos = dir < 0 ? findPrevDiff(dv.chunks, line, isOrig) : findNextDiff(dv.chunks, line, isOrig);
if (pos != null && (found == null || (dir < 0 ? pos > found : pos < found)))
found = pos;
}
if (found != null)
cm.setCursor(found, 0);
else
return CodeMirror.Pass;
}
CodeMirror.commands.goNextDiff = function(cm) {
return goNearbyDiff(cm, 1);
};
CodeMirror.commands.goPrevDiff = function(cm) {
return goNearbyDiff(cm, -1);
};
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -16,8 +16,8 @@
var countDown = n;
return function() { if (--countDown == 0) cont(); };
}
function ensureDeps(mode, cont) {
var deps = CodeMirror.modes[mode].dependencies;
function ensureDeps(mode, cont, options) {
var modeObj = CodeMirror.modes[mode], deps = modeObj && modeObj.dependencies;
if (!deps) return cont();
var missing = [];
for (var i = 0; i < deps.length; ++i) {
@ -27,16 +27,18 @@
if (!missing.length) return cont();
var split = splitCallback(cont, missing.length);
for (var i = 0; i < missing.length; ++i)
CodeMirror.requireMode(missing[i], split);
CodeMirror.requireMode(missing[i], split, options);
}
CodeMirror.requireMode = function(mode, cont) {
CodeMirror.requireMode = function(mode, cont, options) {
if (typeof mode != "string") mode = mode.name;
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont, options);
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
var file = CodeMirror.modeURL.replace(/%N/g, mode);
if (env == "plain") {
var file = options && options.path ? options.path(mode) : CodeMirror.modeURL.replace(/%N/g, mode);
if (options && options.loadMode) {
options.loadMode(file, function() { ensureDeps(mode, cont, options) })
} else if (env == "plain") {
var script = document.createElement("script");
script.src = file;
var others = document.getElementsByTagName("script")[0];
@ -44,7 +46,7 @@
CodeMirror.on(script, "load", function() {
ensureDeps(mode, function() {
for (var i = 0; i < list.length; ++i) list[i]();
});
}, options);
});
others.parentNode.insertBefore(script, others);
} else if (env == "cjs") {
@ -55,10 +57,10 @@
}
};
CodeMirror.autoLoadMode = function(instance, mode) {
CodeMirror.autoLoadMode = function(instance, mode, options) {
if (!CodeMirror.modes.hasOwnProperty(mode))
CodeMirror.requireMode(mode, function() {
instance.setOption("mode", instance.getOption("mode"));
});
}, options);
};
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -12,14 +12,16 @@
"use strict";
CodeMirror.multiplexingMode = function(outer /*, others */) {
// Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
// Others should be {open, close, mode [, delimStyle] [, innerStyle] [, parseDelimiters]} objects
var others = Array.prototype.slice.call(arguments, 1);
var n_others = others.length;
function indexOf(string, pattern, from) {
if (typeof pattern == "string") return string.indexOf(pattern, from);
function indexOf(string, pattern, from, returnEnd) {
if (typeof pattern == "string") {
var found = string.indexOf(pattern, from);
return returnEnd && found > -1 ? found + pattern.length : found;
}
var m = pattern.exec(from ? string.slice(from) : string);
return m ? m.index + from : -1;
return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
}
return {
@ -27,7 +29,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
return {
outer: CodeMirror.startState(outer),
innerActive: null,
inner: null
inner: null,
startingInner: false
};
},
@ -35,21 +38,31 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
return {
outer: CodeMirror.copyState(outer, state.outer),
innerActive: state.innerActive,
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner),
startingInner: state.startingInner
};
},
token: function(stream, state) {
if (!state.innerActive) {
var cutOff = Infinity, oldContent = stream.string;
for (var i = 0; i < n_others; ++i) {
for (var i = 0; i < others.length; ++i) {
var other = others[i];
var found = indexOf(oldContent, other.open, stream.pos);
if (found == stream.pos) {
stream.match(other.open);
if (!other.parseDelimiters) stream.match(other.open);
state.startingInner = !!other.parseDelimiters
state.innerActive = other;
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
return other.delimStyle;
// Get the outer indent, making sure to handle CodeMirror.Pass
var outerIndent = 0;
if (outer.indent) {
var possibleOuterIndent = outer.indent(state.outer, "", "");
if (possibleOuterIndent !== CodeMirror.Pass) outerIndent = possibleOuterIndent;
}
state.inner = CodeMirror.startState(other.mode, outerIndent);
return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
} else if (found != -1 && found < cutOff) {
cutOff = found;
}
@ -64,18 +77,23 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
state.innerActive = state.inner = null;
return this.token(stream, state);
}
var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos) : -1;
if (found == stream.pos) {
var found = curInner.close && !state.startingInner ?
indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
if (found == stream.pos && !curInner.parseDelimiters) {
stream.match(curInner.close);
state.innerActive = state.inner = null;
return curInner.delimStyle;
return curInner.delimStyle && (curInner.delimStyle + " " + curInner.delimStyle + "-close");
}
if (found > -1) stream.string = oldContent.slice(0, found);
var innerToken = curInner.mode.token(stream, state.inner);
if (found > -1) stream.string = oldContent;
else if (stream.pos > stream.start) state.startingInner = false
if (found == stream.pos && curInner.parseDelimiters)
state.innerActive = state.inner = null;
if (curInner.innerStyle) {
if (innerToken) innerToken = innerToken + ' ' + curInner.innerStyle;
if (innerToken) innerToken = innerToken + " " + curInner.innerStyle;
else innerToken = curInner.innerStyle;
}
@ -83,10 +101,10 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
}
},
indent: function(state, textAfter) {
indent: function(state, textAfter, line) {
var mode = state.innerActive ? state.innerActive.mode : outer;
if (!mode.indent) return CodeMirror.Pass;
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter, line);
},
blankLine: function(state) {
@ -95,11 +113,11 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
mode.blankLine(state.innerActive ? state.inner : state.outer);
}
if (!state.innerActive) {
for (var i = 0; i < n_others; ++i) {
for (var i = 0; i < others.length; ++i) {
var other = others[i];
if (other.open === "\n") {
state.innerActive = other;
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "", "") : 0);
}
}
} else if (state.innerActive.close === "\n") {

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function() {
CodeMirror.defineMode("markdown_with_stex", function(){
@ -29,5 +29,21 @@
MT(
"stexInsideMarkdown",
"[strong **Equation:**] [delim $][inner&tag \\pi][delim $]");
"[strong **Equation:**] [delim&delim-open $][inner&tag \\pi][delim&delim-close $]");
CodeMirror.defineMode("identical_delim_multiplex", function() {
return CodeMirror.multiplexingMode(CodeMirror.getMode({indentUnit: 2}, "javascript"), {
open: "#",
close: "#",
mode: CodeMirror.getMode({}, "markdown"),
parseDelimiters: true,
innerStyle: "q"
});
});
var mode2 = CodeMirror.getMode({}, "identical_delim_multiplex");
test.mode("identical_delimiters_with_parseDelimiters", mode2, [
"[keyword let] [def x] [operator =] [q #foo][q&em *bar*][q #];"
], "multiplexing")
})();

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Utility function that allows modes to be combined. The mode given
// as the base argument takes care of most of the normal mode
@ -68,16 +68,21 @@ CodeMirror.overlayMode = function(base, overlay, combine) {
else return state.overlayCur;
},
indent: base.indent && function(state, textAfter) {
return base.indent(state.base, textAfter);
indent: base.indent && function(state, textAfter, line) {
return base.indent(state.base, textAfter, line);
},
electricChars: base.electricChars,
innerMode: function(state) { return {state: state.base, mode: base}; },
blankLine: function(state) {
if (base.blankLine) base.blankLine(state.base);
if (overlay.blankLine) overlay.blankLine(state.overlay);
var baseToken, overlayToken;
if (base.blankLine) baseToken = base.blankLine(state.base);
if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay);
return overlayToken == null ?
baseToken :
(combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken);
}
};
};

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -60,7 +60,7 @@
function ensureState(states, name) {
if (!states.hasOwnProperty(name))
throw new Error("Undefined state " + name + "in simple mode");
throw new Error("Undefined state " + name + " in simple mode");
}
function toRegex(val, caret) {
@ -68,6 +68,7 @@
var flags = "";
if (val instanceof RegExp) {
if (val.ignoreCase) flags = "i";
if (val.unicode) flags += "u"
val = val.source;
} else {
val = String(val);
@ -77,6 +78,7 @@
function asToken(val) {
if (!val) return null;
if (val.apply) return val
if (typeof val == "string") return val.replace(/\./g, " ");
var result = [];
for (var i = 0; i < val.length; i++)
@ -133,17 +135,18 @@
state.indent.push(stream.indentation() + config.indentUnit);
if (rule.data.dedent)
state.indent.pop();
if (matches.length > 2) {
state.pending = [];
var token = rule.token
if (token && token.apply) token = token(matches)
if (matches.length > 2 && rule.token && typeof rule.token != "string") {
for (var j = 2; j < matches.length; j++)
if (matches[j])
state.pending.push({text: matches[j], token: rule.token[j - 1]});
(state.pending || (state.pending = [])).push({text: matches[j], token: rule.token[j - 1]});
stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
return rule.token[0];
} else if (rule.token && rule.token.join) {
return rule.token[0];
return token[0];
} else if (token && token.join) {
return token[0];
} else {
return rule.token;
return token;
}
}
}

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS

View File

@ -1,157 +1,334 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function () {
'use strict';
window.CodeMirror = {};
function copyObj(obj, target, overwrite) {
if (!target) { target = {}; }
for (var prop in obj)
{ if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
{ target[prop] = obj[prop]; } }
return target
}
(function() {
"use strict";
// Counts the column offset in a string, taking tabs into account.
// Used mostly to find indentation.
function countColumn(string, end, tabSize, startIndex, startValue) {
if (end == null) {
end = string.search(/[^\s\u00a0]/);
if (end == -1) { end = string.length; }
}
for (var i = startIndex || 0, n = startValue || 0;;) {
var nextTab = string.indexOf("\t", i);
if (nextTab < 0 || nextTab >= end)
{ return n + (end - i) }
n += nextTab - i;
n += tabSize - (n % tabSize);
i = nextTab + 1;
}
}
function splitLines(string){ return string.split(/\r?\n|\r/); };
function nothing() {}
function StringStream(string) {
this.pos = this.start = 0;
this.string = string;
this.lineStart = 0;
}
StringStream.prototype = {
eol: function() {return this.pos >= this.string.length;},
sol: function() {return this.pos == 0;},
peek: function() {return this.string.charAt(this.pos) || null;},
next: function() {
function createObj(base, props) {
var inst;
if (Object.create) {
inst = Object.create(base);
} else {
nothing.prototype = base;
inst = new nothing();
}
if (props) { copyObj(props, inst); }
return inst
}
// STRING STREAM
// Fed to the mode parsers, provides helper functions to make
// parsers more succinct.
var StringStream = function(string, tabSize, lineOracle) {
this.pos = this.start = 0;
this.string = string;
this.tabSize = tabSize || 8;
this.lastColumnPos = this.lastColumnValue = 0;
this.lineStart = 0;
this.lineOracle = lineOracle;
};
StringStream.prototype.eol = function () {return this.pos >= this.string.length};
StringStream.prototype.sol = function () {return this.pos == this.lineStart};
StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
StringStream.prototype.next = function () {
if (this.pos < this.string.length)
return this.string.charAt(this.pos++);
},
eat: function(match) {
{ return this.string.charAt(this.pos++) }
};
StringStream.prototype.eat = function (match) {
var ch = this.string.charAt(this.pos);
if (typeof match == "string") var ok = ch == match;
else var ok = ch && (match.test ? match.test(ch) : match(ch));
if (ok) {++this.pos; return ch;}
},
eatWhile: function(match) {
var ok;
if (typeof match == "string") { ok = ch == match; }
else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
if (ok) {++this.pos; return ch}
};
StringStream.prototype.eatWhile = function (match) {
var start = this.pos;
while (this.eat(match)){}
return this.pos > start;
},
eatSpace: function() {
return this.pos > start
};
StringStream.prototype.eatSpace = function () {
var start = this.pos;
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
return this.pos > start;
},
skipToEnd: function() {this.pos = this.string.length;},
skipTo: function(ch) {
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
return this.pos > start
};
StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
StringStream.prototype.skipTo = function (ch) {
var found = this.string.indexOf(ch, this.pos);
if (found > -1) {this.pos = found; return true;}
},
backUp: function(n) {this.pos -= n;},
column: function() {return this.start - this.lineStart;},
indentation: function() {return 0;},
match: function(pattern, consume, caseInsensitive) {
if (found > -1) {this.pos = found; return true}
};
StringStream.prototype.backUp = function (n) {this.pos -= n;};
StringStream.prototype.column = function () {
if (this.lastColumnPos < this.start) {
this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
this.lastColumnPos = this.start;
}
return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
};
StringStream.prototype.indentation = function () {
return countColumn(this.string, null, this.tabSize) -
(this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
};
StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
var substr = this.string.substr(this.pos, pattern.length);
if (cased(substr) == cased(pattern)) {
if (consume !== false) this.pos += pattern.length;
return true;
if (consume !== false) { this.pos += pattern.length; }
return true
}
} else {
var match = this.string.slice(this.pos).match(pattern);
if (match && match.index > 0) return null;
if (match && consume !== false) this.pos += match[0].length;
return match;
if (match && match.index > 0) { return null }
if (match && consume !== false) { this.pos += match[0].length; }
return match
}
},
current: function(){return this.string.slice(this.start, this.pos);},
hideFirstChars: function(n, inner) {
};
StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
StringStream.prototype.hideFirstChars = function (n, inner) {
this.lineStart += n;
try { return inner(); }
try { return inner() }
finally { this.lineStart -= n; }
}
};
CodeMirror.StringStream = StringStream;
};
StringStream.prototype.lookAhead = function (n) {
var oracle = this.lineOracle;
return oracle && oracle.lookAhead(n)
};
StringStream.prototype.baseToken = function () {
var oracle = this.lineOracle;
return oracle && oracle.baseToken(this.pos)
};
CodeMirror.startState = function (mode, a1, a2) {
return mode.startState ? mode.startState(a1, a2) : true;
};
// Known modes, by name and by MIME
var modes = {}, mimeModes = {};
var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
CodeMirror.defineMode = function (name, mode) {
if (arguments.length > 2)
mode.dependencies = Array.prototype.slice.call(arguments, 2);
modes[name] = mode;
};
CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
CodeMirror.resolveMode = function(spec) {
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
spec = mimeModes[spec];
} else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
spec = mimeModes[spec.name];
}
if (typeof spec == "string") return {name: spec};
else return spec || {name: "null"};
};
CodeMirror.getMode = function (options, spec) {
spec = CodeMirror.resolveMode(spec);
var mfactory = modes[spec.name];
if (!mfactory) throw new Error("Unknown mode: " + spec);
return mfactory(options, spec);
};
CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
CodeMirror.defineMode("null", function() {
return {token: function(stream) {stream.skipToEnd();}};
});
CodeMirror.defineMIME("text/plain", "null");
CodeMirror.runMode = function (string, modespec, callback, options) {
var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
if (callback.nodeType == 1) {
var tabSize = (options && options.tabSize) || 4;
var node = callback, col = 0;
node.innerHTML = "";
callback = function (text, style) {
if (text == "\n") {
node.appendChild(document.createElement("br"));
col = 0;
return;
}
var content = "";
// replace tabs
for (var pos = 0; ;) {
var idx = text.indexOf("\t", pos);
if (idx == -1) {
content += text.slice(pos);
col += text.length - pos;
break;
} else {
col += idx - pos;
content += text.slice(pos, idx);
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) content += " ";
pos = idx + 1;
}
}
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
sp.appendChild(document.createTextNode(content));
} else {
node.appendChild(document.createTextNode(content));
}
};
// Extra arguments are stored as the mode's dependencies, which is
// used by (legacy) mechanisms like loadmode.js to automatically
// load a mode. (Preferred mechanism is the require/define calls.)
function defineMode(name, mode) {
if (arguments.length > 2)
{ mode.dependencies = Array.prototype.slice.call(arguments, 2); }
modes[name] = mode;
}
var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]);
if (!stream.string && mode.blankLine) mode.blankLine(state);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state);
stream.start = stream.pos;
function defineMIME(mime, spec) {
mimeModes[mime] = spec;
}
// Given a MIME type, a {name, ...options} config object, or a name
// string, return a mode config object.
function resolveMode(spec) {
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
spec = mimeModes[spec];
} else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
var found = mimeModes[spec.name];
if (typeof found == "string") { found = {name: found}; }
spec = createObj(found, spec);
spec.name = found.name;
} else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
return resolveMode("application/xml")
} else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
return resolveMode("application/json")
}
if (typeof spec == "string") { return {name: spec} }
else { return spec || {name: "null"} }
}
};
})();
// Given a mode spec (anything that resolveMode accepts), find and
// initialize an actual mode object.
function getMode(options, spec) {
spec = resolveMode(spec);
var mfactory = modes[spec.name];
if (!mfactory) { return getMode(options, "text/plain") }
var modeObj = mfactory(options, spec);
if (modeExtensions.hasOwnProperty(spec.name)) {
var exts = modeExtensions[spec.name];
for (var prop in exts) {
if (!exts.hasOwnProperty(prop)) { continue }
if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
modeObj[prop] = exts[prop];
}
}
modeObj.name = spec.name;
if (spec.helperType) { modeObj.helperType = spec.helperType; }
if (spec.modeProps) { for (var prop$1 in spec.modeProps)
{ modeObj[prop$1] = spec.modeProps[prop$1]; } }
return modeObj
}
// This can be used to attach properties to mode objects from
// outside the actual mode definition.
var modeExtensions = {};
function extendMode(mode, properties) {
var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
copyObj(properties, exts);
}
function copyState(mode, state) {
if (state === true) { return state }
if (mode.copyState) { return mode.copyState(state) }
var nstate = {};
for (var n in state) {
var val = state[n];
if (val instanceof Array) { val = val.concat([]); }
nstate[n] = val;
}
return nstate
}
// Given a mode and a state (for that mode), find the inner mode and
// state at the position that the state refers to.
function innerMode(mode, state) {
var info;
while (mode.innerMode) {
info = mode.innerMode(state);
if (!info || info.mode == mode) { break }
state = info.state;
mode = info.mode;
}
return info || {mode: mode, state: state}
}
function startState(mode, a1, a2) {
return mode.startState ? mode.startState(a1, a2) : true
}
var modeMethods = {
__proto__: null,
modes: modes,
mimeModes: mimeModes,
defineMode: defineMode,
defineMIME: defineMIME,
resolveMode: resolveMode,
getMode: getMode,
modeExtensions: modeExtensions,
extendMode: extendMode,
copyState: copyState,
innerMode: innerMode,
startState: startState
};
// declare global: globalThis, CodeMirror
// Create a minimal CodeMirror needed to use runMode, and assign to root.
var root = typeof globalThis !== 'undefined' ? globalThis : window;
root.CodeMirror = {};
// Copy StringStream and mode methods into CodeMirror object.
CodeMirror.StringStream = StringStream;
for (var exported in modeMethods) { CodeMirror[exported] = modeMethods[exported]; }
// Minimal default mode.
CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
CodeMirror.defineMIME("text/plain", "null");
CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
CodeMirror.splitLines = function(string) { return string.split(/\r?\n|\r/) };
CodeMirror.countColumn = countColumn;
CodeMirror.defaults = { indentUnit: 2 };
// 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")); }
else if (typeof define == "function" && define.amd) // AMD
{ define(["../../lib/codemirror"], mod); }
else // Plain browser env
{ mod(CodeMirror); }
})(function(CodeMirror) {
CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
// Create a tokenizing callback function if passed-in callback is a DOM element.
if (callback.appendChild) {
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
var node = callback, col = 0;
node.innerHTML = "";
callback = function(text, style) {
if (text == "\n") {
// Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
// Emitting a carriage return makes everything ok.
node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
col = 0;
return;
}
var content = "";
// replace tabs
for (var pos = 0;;) {
var idx = text.indexOf("\t", pos);
if (idx == -1) {
content += text.slice(pos);
col += text.length - pos;
break;
} else {
col += idx - pos;
content += text.slice(pos, idx);
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) { content += " "; }
pos = idx + 1;
}
}
// Create a node with token style and append it to the callback DOM element.
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
sp.appendChild(document.createTextNode(content));
} else {
node.appendChild(document.createTextNode(content));
}
};
}
var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) { callback("\n"); }
var stream = new CodeMirror.StringStream(lines[i], null, {
lookAhead: function(n) { return lines[i + n] },
baseToken: function() {}
});
if (!stream.string && mode.blankLine) { mode.blankLine(state); }
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state, mode);
stream.start = stream.pos;
}
}
};
});
}());

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -13,11 +13,12 @@
CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
if (callback.nodeType == 1) {
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
// Create a tokenizing callback function if passed-in callback is a DOM element.
if (callback.appendChild) {
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
var node = callback, col = 0;
node.innerHTML = "";
callback = function(text, style) {
@ -45,7 +46,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
pos = idx + 1;
}
}
// Create a node with token style and append it to the callback DOM element.
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
@ -59,11 +60,14 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new CodeMirror.StringStream(lines[i]);
var stream = new CodeMirror.StringStream(lines[i], null, {
lookAhead: function(n) { return lines[i + n] },
baseToken: function() {}
});
if (!stream.string && mode.blankLine) mode.blankLine(state);
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state);
callback(stream.current(), style, i, stream.start, state, mode);
stream.start = stream.pos;
}
}

View File

@ -1,120 +1,329 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
'use strict';
/* Just enough of CodeMirror to run runMode under node.js */
function copyObj(obj, target, overwrite) {
if (!target) { target = {}; }
for (var prop in obj)
{ if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
{ target[prop] = obj[prop]; } }
return target
}
// declare global: StringStream
// Counts the column offset in a string, taking tabs into account.
// Used mostly to find indentation.
function countColumn(string, end, tabSize, startIndex, startValue) {
if (end == null) {
end = string.search(/[^\s\u00a0]/);
if (end == -1) { end = string.length; }
}
for (var i = startIndex || 0, n = startValue || 0;;) {
var nextTab = string.indexOf("\t", i);
if (nextTab < 0 || nextTab >= end)
{ return n + (end - i) }
n += nextTab - i;
n += tabSize - (n % tabSize);
i = nextTab + 1;
}
}
function splitLines(string){ return string.split(/\r?\n|\r/); };
function nothing() {}
function StringStream(string) {
function createObj(base, props) {
var inst;
if (Object.create) {
inst = Object.create(base);
} else {
nothing.prototype = base;
inst = new nothing();
}
if (props) { copyObj(props, inst); }
return inst
}
// STRING STREAM
// Fed to the mode parsers, provides helper functions to make
// parsers more succinct.
var StringStream = function(string, tabSize, lineOracle) {
this.pos = this.start = 0;
this.string = string;
this.tabSize = tabSize || 8;
this.lastColumnPos = this.lastColumnValue = 0;
this.lineStart = 0;
}
StringStream.prototype = {
eol: function() {return this.pos >= this.string.length;},
sol: function() {return this.pos == 0;},
peek: function() {return this.string.charAt(this.pos) || null;},
next: function() {
if (this.pos < this.string.length)
return this.string.charAt(this.pos++);
},
eat: function(match) {
var ch = this.string.charAt(this.pos);
if (typeof match == "string") var ok = ch == match;
else var ok = ch && (match.test ? match.test(ch) : match(ch));
if (ok) {++this.pos; return ch;}
},
eatWhile: function(match) {
var start = this.pos;
while (this.eat(match)){}
return this.pos > start;
},
eatSpace: function() {
var start = this.pos;
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
return this.pos > start;
},
skipToEnd: function() {this.pos = this.string.length;},
skipTo: function(ch) {
var found = this.string.indexOf(ch, this.pos);
if (found > -1) {this.pos = found; return true;}
},
backUp: function(n) {this.pos -= n;},
column: function() {return this.start - this.lineStart;},
indentation: function() {return 0;},
match: function(pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
var substr = this.string.substr(this.pos, pattern.length);
if (cased(substr) == cased(pattern)) {
if (consume !== false) this.pos += pattern.length;
return true;
}
} else {
var match = this.string.slice(this.pos).match(pattern);
if (match && match.index > 0) return null;
if (match && consume !== false) this.pos += match[0].length;
return match;
this.lineOracle = lineOracle;
};
StringStream.prototype.eol = function () {return this.pos >= this.string.length};
StringStream.prototype.sol = function () {return this.pos == this.lineStart};
StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
StringStream.prototype.next = function () {
if (this.pos < this.string.length)
{ return this.string.charAt(this.pos++) }
};
StringStream.prototype.eat = function (match) {
var ch = this.string.charAt(this.pos);
var ok;
if (typeof match == "string") { ok = ch == match; }
else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
if (ok) {++this.pos; return ch}
};
StringStream.prototype.eatWhile = function (match) {
var start = this.pos;
while (this.eat(match)){}
return this.pos > start
};
StringStream.prototype.eatSpace = function () {
var start = this.pos;
while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
return this.pos > start
};
StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
StringStream.prototype.skipTo = function (ch) {
var found = this.string.indexOf(ch, this.pos);
if (found > -1) {this.pos = found; return true}
};
StringStream.prototype.backUp = function (n) {this.pos -= n;};
StringStream.prototype.column = function () {
if (this.lastColumnPos < this.start) {
this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
this.lastColumnPos = this.start;
}
return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
};
StringStream.prototype.indentation = function () {
return countColumn(this.string, null, this.tabSize) -
(this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
};
StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
if (typeof pattern == "string") {
var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
var substr = this.string.substr(this.pos, pattern.length);
if (cased(substr) == cased(pattern)) {
if (consume !== false) { this.pos += pattern.length; }
return true
}
},
current: function(){return this.string.slice(this.start, this.pos);},
hideFirstChars: function(n, inner) {
this.lineStart += n;
try { return inner(); }
finally { this.lineStart -= n; }
} else {
var match = this.string.slice(this.pos).match(pattern);
if (match && match.index > 0) { return null }
if (match && consume !== false) { this.pos += match[0].length; }
return match
}
};
exports.StringStream = StringStream;
exports.startState = function(mode, a1, a2) {
return mode.startState ? mode.startState(a1, a2) : true;
StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
StringStream.prototype.hideFirstChars = function (n, inner) {
this.lineStart += n;
try { return inner() }
finally { this.lineStart -= n; }
};
StringStream.prototype.lookAhead = function (n) {
var oracle = this.lineOracle;
return oracle && oracle.lookAhead(n)
};
StringStream.prototype.baseToken = function () {
var oracle = this.lineOracle;
return oracle && oracle.baseToken(this.pos)
};
var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
exports.defineMode = function(name, mode) {
// Known modes, by name and by MIME
var modes = {}, mimeModes = {};
// Extra arguments are stored as the mode's dependencies, which is
// used by (legacy) mechanisms like loadmode.js to automatically
// load a mode. (Preferred mechanism is the require/define calls.)
function defineMode(name, mode) {
if (arguments.length > 2)
mode.dependencies = Array.prototype.slice.call(arguments, 2);
{ mode.dependencies = Array.prototype.slice.call(arguments, 2); }
modes[name] = mode;
};
exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
}
exports.defineMode("null", function() {
return {token: function(stream) {stream.skipToEnd();}};
});
exports.defineMIME("text/plain", "null");
function defineMIME(mime, spec) {
mimeModes[mime] = spec;
}
exports.resolveMode = function(spec) {
// Given a MIME type, a {name, ...options} config object, or a name
// string, return a mode config object.
function resolveMode(spec) {
if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
spec = mimeModes[spec];
} else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
spec = mimeModes[spec.name];
var found = mimeModes[spec.name];
if (typeof found == "string") { found = {name: found}; }
spec = createObj(found, spec);
spec.name = found.name;
} else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
return resolveMode("application/xml")
} else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
return resolveMode("application/json")
}
if (typeof spec == "string") return {name: spec};
else return spec || {name: "null"};
};
exports.getMode = function(options, spec) {
spec = exports.resolveMode(spec);
var mfactory = modes[spec.name];
if (!mfactory) throw new Error("Unknown mode: " + spec);
return mfactory(options, spec);
};
exports.registerHelper = exports.registerGlobalHelper = Math.min;
if (typeof spec == "string") { return {name: spec} }
else { return spec || {name: "null"} }
}
exports.runMode = function(string, modespec, callback, options) {
var mode = exports.getMode({indentUnit: 2}, modespec);
var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
// Given a mode spec (anything that resolveMode accepts), find and
// initialize an actual mode object.
function getMode(options, spec) {
spec = resolveMode(spec);
var mfactory = modes[spec.name];
if (!mfactory) { return getMode(options, "text/plain") }
var modeObj = mfactory(options, spec);
if (modeExtensions.hasOwnProperty(spec.name)) {
var exts = modeExtensions[spec.name];
for (var prop in exts) {
if (!exts.hasOwnProperty(prop)) { continue }
if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
modeObj[prop] = exts[prop];
}
}
modeObj.name = spec.name;
if (spec.helperType) { modeObj.helperType = spec.helperType; }
if (spec.modeProps) { for (var prop$1 in spec.modeProps)
{ modeObj[prop$1] = spec.modeProps[prop$1]; } }
return modeObj
}
// This can be used to attach properties to mode objects from
// outside the actual mode definition.
var modeExtensions = {};
function extendMode(mode, properties) {
var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
copyObj(properties, exts);
}
function copyState(mode, state) {
if (state === true) { return state }
if (mode.copyState) { return mode.copyState(state) }
var nstate = {};
for (var n in state) {
var val = state[n];
if (val instanceof Array) { val = val.concat([]); }
nstate[n] = val;
}
return nstate
}
// Given a mode and a state (for that mode), find the inner mode and
// state at the position that the state refers to.
function innerMode(mode, state) {
var info;
while (mode.innerMode) {
info = mode.innerMode(state);
if (!info || info.mode == mode) { break }
state = info.state;
mode = info.mode;
}
return info || {mode: mode, state: state}
}
function startState(mode, a1, a2) {
return mode.startState ? mode.startState(a1, a2) : true
}
var modeMethods = {
__proto__: null,
modes: modes,
mimeModes: mimeModes,
defineMode: defineMode,
defineMIME: defineMIME,
resolveMode: resolveMode,
getMode: getMode,
modeExtensions: modeExtensions,
extendMode: extendMode,
copyState: copyState,
innerMode: innerMode,
startState: startState
};
// Copy StringStream and mode methods into exports (CodeMirror) object.
exports.StringStream = StringStream;
exports.countColumn = countColumn;
for (var exported in modeMethods) { exports[exported] = modeMethods[exported]; }
// Shim library CodeMirror with the minimal CodeMirror defined above.
require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
require.cache[require.resolve("../../addon/runmode/runmode")] = require.cache[require.resolve("./runmode.node")];
// Minimal default mode.
exports.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
exports.defineMIME("text/plain", "null");
exports.registerHelper = exports.registerGlobalHelper = Math.min;
exports.splitLines = function(string) { return string.split(/\r?\n|\r/) };
exports.defaults = { indentUnit: 2 };
// 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")); }
else if (typeof define == "function" && define.amd) // AMD
{ define(["../../lib/codemirror"], mod); }
else // Plain browser env
{ mod(CodeMirror); }
})(function(CodeMirror) {
CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
// Create a tokenizing callback function if passed-in callback is a DOM element.
if (callback.appendChild) {
var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
var node = callback, col = 0;
node.innerHTML = "";
callback = function(text, style) {
if (text == "\n") {
// Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
// Emitting a carriage return makes everything ok.
node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
col = 0;
return;
}
var content = "";
// replace tabs
for (var pos = 0;;) {
var idx = text.indexOf("\t", pos);
if (idx == -1) {
content += text.slice(pos);
col += text.length - pos;
break;
} else {
col += idx - pos;
content += text.slice(pos, idx);
var size = tabSize - col % tabSize;
col += size;
for (var i = 0; i < size; ++i) { content += " "; }
pos = idx + 1;
}
}
// Create a node with token style and append it to the callback DOM element.
if (style) {
var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-");
sp.appendChild(document.createTextNode(content));
} else {
node.appendChild(document.createTextNode(content));
}
};
}
var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n");
var stream = new exports.StringStream(lines[i]);
if (!stream.string && mode.blankLine) mode.blankLine(state);
if (i) { callback("\n"); }
var stream = new CodeMirror.StringStream(lines[i], null, {
lookAhead: function(n) { return lines[i + n] },
baseToken: function() {}
});
if (!stream.string && mode.blankLine) { mode.blankLine(state); }
while (!stream.eol()) {
var style = mode.token(stream, state);
callback(stream.current(), style, i, stream.start, state);
callback(stream.current(), style, i, stream.start, state, mode);
stream.start = stream.pos;
}
}
};
require.cache[require.resolve("../../lib/codemirror")] = require.cache[require.resolve("./runmode.node")];
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -43,7 +43,7 @@
cm.on("markerAdded", this.resizeHandler);
cm.on("markerCleared", this.resizeHandler);
if (options.listenForChanges !== false)
cm.on("change", this.changeHandler = function() {
cm.on("changes", this.changeHandler = function() {
scheduleRedraw(250);
});
}
@ -51,7 +51,7 @@
Annotation.prototype.computeScale = function() {
var cm = this.cm;
var hScale = (cm.getWrapperElement().clientHeight - cm.display.barHeight - this.buttonHeight * 2) /
cm.heightAtLine(cm.lastLine() + 1, "local");
cm.getScrollerElement().scrollHeight
if (hScale != this.hScale) {
this.hScale = hScale;
return true;
@ -68,15 +68,40 @@
var cm = this.cm, hScale = this.hScale;
var frag = document.createDocumentFragment(), anns = this.annotations;
var wrapping = cm.getOption("lineWrapping");
var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
var curLine = null, curLineObj = null;
function getY(pos, top) {
if (curLine != pos.line) {
curLine = pos.line
curLineObj = cm.getLineHandle(pos.line)
var visual = cm.getLineHandleVisualStart(curLineObj)
if (visual != curLineObj) {
curLine = cm.getLineNumber(visual)
curLineObj = visual
}
}
if ((curLineObj.widgets && curLineObj.widgets.length) ||
(wrapping && curLineObj.height > singleLineH))
return cm.charCoords(pos, "local")[top ? "top" : "bottom"];
var topY = cm.heightAtLine(curLineObj, "local");
return topY + (top ? 0 : curLineObj.height);
}
var lastLine = cm.lastLine()
if (cm.display.barWidth) for (var i = 0, nextTop; i < anns.length; i++) {
var ann = anns[i];
var top = nextTop || cm.charCoords(ann.from, "local").top * hScale;
var bottom = cm.charCoords(ann.to, "local").bottom * hScale;
if (ann.to.line > lastLine) continue;
var top = nextTop || getY(ann.from, true) * hScale;
var bottom = getY(ann.to, false) * hScale;
while (i < anns.length - 1) {
nextTop = cm.charCoords(anns[i + 1].from, "local").top * hScale;
if (anns[i + 1].to.line > lastLine) break;
nextTop = getY(anns[i + 1].from, true) * hScale;
if (nextTop > bottom + .9) break;
ann = anns[++i];
bottom = cm.charCoords(ann.to, "local").bottom * hScale;
bottom = getY(ann.to, false) * hScale;
}
if (bottom == top) continue;
var height = Math.max(bottom - top, 3);
@ -85,6 +110,9 @@
elt.style.cssText = "position: absolute; right: 0px; width: " + Math.max(cm.display.barWidth - 1, 2) + "px; top: "
+ (top + this.buttonHeight) + "px; height: " + height + "px";
elt.className = this.options.className;
if (ann.id) {
elt.setAttribute("annotation-id", ann.id);
}
}
this.div.textContent = "";
this.div.appendChild(frag);
@ -94,7 +122,7 @@
this.cm.off("refresh", this.resizeHandler);
this.cm.off("markerAdded", this.resizeHandler);
this.cm.off("markerCleared", this.resizeHandler);
if (this.changeHandler) this.cm.off("change", this.changeHandler);
if (this.changeHandler) this.cm.off("changes", this.changeHandler);
this.div.parentNode.removeChild(this.div);
};
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -40,7 +40,9 @@
if (cm.state.scrollPastEndPadding != padding) {
cm.state.scrollPastEndPadding = padding;
cm.display.lineSpace.parentNode.style.paddingBottom = padding;
cm.off("refresh", updateBottomMargin);
cm.setSize();
cm.on("refresh", updateBottomMargin);
}
}
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -59,26 +59,38 @@
CodeMirror.on(this.node, "DOMMouseScroll", onWheel);
}
Bar.prototype.moveTo = function(pos, update) {
Bar.prototype.setPos = function(pos, force) {
if (pos < 0) pos = 0;
if (pos > this.total - this.screen) pos = this.total - this.screen;
if (pos == this.pos) return;
if (!force && pos == this.pos) return false;
this.pos = pos;
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
(pos * (this.size / this.total)) + "px";
if (update !== false) this.scroll(pos, this.orientation);
return true
};
Bar.prototype.update = function(scrollSize, clientSize, barSize) {
this.screen = clientSize;
this.total = scrollSize;
this.size = barSize;
Bar.prototype.moveTo = function(pos) {
if (this.setPos(pos)) this.scroll(pos, this.orientation);
}
// FIXME clip to min size?
var minButtonSize = 10;
Bar.prototype.update = function(scrollSize, clientSize, barSize) {
var sizeChanged = this.screen != clientSize || this.total != scrollSize || this.size != barSize
if (sizeChanged) {
this.screen = clientSize;
this.total = scrollSize;
this.size = barSize;
}
var buttonSize = this.screen * (this.size / this.total);
if (buttonSize < minButtonSize) {
this.size -= minButtonSize - buttonSize;
buttonSize = minButtonSize;
}
this.inner.style[this.orientation == "horizontal" ? "width" : "height"] =
this.screen * (this.size / this.total) + "px";
this.inner.style[this.orientation == "horizontal" ? "left" : "top"] =
this.pos * (this.size / this.total) + "px";
buttonSize + "px";
this.setPos(this.pos, sizeChanged);
};
function SimpleScrollbars(cls, place, scroll) {
@ -105,7 +117,6 @@
if (needsV) {
this.vert.update(measure.scrollHeight, measure.clientHeight,
measure.viewHeight - (needsH ? width : 0));
this.vert.node.style.display = "block";
this.vert.node.style.bottom = needsH ? width + "px" : "0";
}
if (needsH) {
@ -119,11 +130,11 @@
};
SimpleScrollbars.prototype.setScrollTop = function(pos) {
this.vert.moveTo(pos, false);
this.vert.setPos(pos);
};
SimpleScrollbars.prototype.setScrollLeft = function(pos) {
this.horiz.moveTo(pos, false);
this.horiz.setPos(pos);
};
SimpleScrollbars.prototype.clear = function() {

View File

@ -0,0 +1,53 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Defines jumpToLine command. Uses dialog.js if present.
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../dialog/dialog"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../dialog/dialog"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
// default search panel location
CodeMirror.defineOption("search", {bottom: false});
function dialog(cm, text, shortText, deflt, f) {
if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom});
else f(prompt(shortText, deflt));
}
function getJumpDialog(cm) {
return cm.phrase("Jump to line:") + ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">' + cm.phrase("(Use line:column or scroll% syntax)") + '</span>';
}
function interpretLine(cm, string) {
var num = Number(string)
if (/^[-+]/.test(string)) return cm.getCursor().line + num
else return num - 1
}
CodeMirror.commands.jumpToLine = function(cm) {
var cur = cm.getCursor();
dialog(cm, getJumpDialog(cm), cm.phrase("Jump to line:"), (cur.line + 1) + ":" + cur.ch, function(posStr) {
if (!posStr) return;
var match;
if (match = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr)) {
cm.setCursor(interpretLine(cm, match[1]), Number(match[2]))
} else if (match = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr)) {
var line = Math.round(cm.lineCount() * Number(match[1]) / 100);
if (/^[-+]/.test(match[1])) line = cur.line + line + 1;
cm.setCursor(line - 1, cur.ch);
} else if (match = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr)) {
cm.setCursor(interpretLine(cm, match[1]), cur.ch);
}
});
};
CodeMirror.keyMap["default"]["Alt-G"] = "jumpToLine";
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Highlighting text that matches the selection
//
@ -16,81 +16,120 @@
// highlighted only if the selected text is a word. showToken, when enabled,
// will cause the current token to be highlighted when nothing is selected.
// delay is used to specify how much time to wait, in milliseconds, before
// highlighting the matches.
// highlighting the matches. If annotateScrollbar is enabled, the occurrences
// will be highlighted on the scrollbar via the matchesonscrollbar addon.
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
mod(require("../../lib/codemirror"), require("./matchesonscrollbar"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
define(["../../lib/codemirror", "./matchesonscrollbar"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
var DEFAULT_MIN_CHARS = 2;
var DEFAULT_TOKEN_STYLE = "matchhighlight";
var DEFAULT_DELAY = 100;
var DEFAULT_WORDS_ONLY = false;
var defaults = {
style: "matchhighlight",
minChars: 2,
delay: 100,
wordsOnly: false,
annotateScrollbar: false,
showToken: false,
trim: true
}
function State(options) {
if (typeof options == "object") {
this.minChars = options.minChars;
this.style = options.style;
this.showToken = options.showToken;
this.delay = options.delay;
this.wordsOnly = options.wordsOnly;
}
if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
if (this.delay == null) this.delay = DEFAULT_DELAY;
if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;
this.options = {}
for (var name in defaults)
this.options[name] = (options && options.hasOwnProperty(name) ? options : defaults)[name]
this.overlay = this.timeout = null;
this.matchesonscroll = null;
this.active = false;
}
CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
var over = cm.state.matchHighlighter.overlay;
if (over) cm.removeOverlay(over);
removeOverlay(cm);
clearTimeout(cm.state.matchHighlighter.timeout);
cm.state.matchHighlighter = null;
cm.off("cursorActivity", cursorActivity);
cm.off("focus", onFocus)
}
if (val) {
cm.state.matchHighlighter = new State(val);
highlightMatches(cm);
var state = cm.state.matchHighlighter = new State(val);
if (cm.hasFocus()) {
state.active = true
highlightMatches(cm)
} else {
cm.on("focus", onFocus)
}
cm.on("cursorActivity", cursorActivity);
}
});
function cursorActivity(cm) {
var state = cm.state.matchHighlighter;
if (state.active || cm.hasFocus()) scheduleHighlight(cm, state)
}
function onFocus(cm) {
var state = cm.state.matchHighlighter
if (!state.active) {
state.active = true
scheduleHighlight(cm, state)
}
}
function scheduleHighlight(cm, state) {
clearTimeout(state.timeout);
state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
state.timeout = setTimeout(function() {highlightMatches(cm);}, state.options.delay);
}
function addOverlay(cm, query, hasBoundary, style) {
var state = cm.state.matchHighlighter;
cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
var searchFor = hasBoundary ? new RegExp((/\w/.test(query.charAt(0)) ? "\\b" : "") +
query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") +
(/\w/.test(query.charAt(query.length - 1)) ? "\\b" : "")) : query;
state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
{className: "CodeMirror-selection-highlight-scrollbar"});
}
}
function removeOverlay(cm) {
var state = cm.state.matchHighlighter;
if (state.overlay) {
cm.removeOverlay(state.overlay);
state.overlay = null;
if (state.matchesonscroll) {
state.matchesonscroll.clear();
state.matchesonscroll = null;
}
}
}
function highlightMatches(cm) {
cm.operation(function() {
var state = cm.state.matchHighlighter;
if (state.overlay) {
cm.removeOverlay(state.overlay);
state.overlay = null;
}
if (!cm.somethingSelected() && state.showToken) {
var re = state.showToken === true ? /[\w$]/ : state.showToken;
removeOverlay(cm);
if (!cm.somethingSelected() && state.options.showToken) {
var re = state.options.showToken === true ? /[\w$]/ : state.options.showToken;
var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
while (start && re.test(line.charAt(start - 1))) --start;
while (end < line.length && re.test(line.charAt(end))) ++end;
if (start < end)
cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));
addOverlay(cm, line.slice(start, end), re, state.options.style);
return;
}
var from = cm.getCursor("from"), to = cm.getCursor("to");
if (from.line != to.line) return;
if (state.wordsOnly && !isWord(cm, from, to)) return;
var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
if (selection.length >= state.minChars)
cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
if (state.options.wordsOnly && !isWord(cm, from, to)) return;
var selection = cm.getRange(from, to)
if (state.options.trim) selection = selection.replace(/^\s+|\s+$/g, "")
if (selection.length >= state.options.minChars)
addOverlay(cm, selection, false, state.options.style);
});
}

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -19,6 +19,7 @@
function SearchAnnotation(cm, query, caseFold, options) {
this.cm = cm;
this.options = options;
var annotateOptions = {listenForChanges: false};
for (var prop in options) annotateOptions[prop] = options[prop];
if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
@ -45,12 +46,13 @@
if (match.from.line >= this.gap.to) break;
if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
}
var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), this.caseFold);
var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), {caseFold: this.caseFold, multiline: this.options.multiline});
var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES;
while (cursor.findNext()) {
var match = {from: cursor.from(), to: cursor.to()};
if (match.from.line >= this.gap.to) break;
this.matches.splice(i++, 0, match);
if (this.matches.length > MAX_MATCHES) break;
if (this.matches.length > maxMatches) break;
}
this.gap = null;
};

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Define search commands. Depends on dialog.js or another
// implementation of the openDialog method.
@ -18,6 +18,10 @@
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
// default search panel location
CodeMirror.defineOption("search", {bottom: false});
function searchOverlay(query, caseInsensitive) {
if (typeof query == "string")
query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
@ -28,7 +32,7 @@
query.lastIndex = stream.pos;
var match = query.exec(stream.string);
if (match && match.index == stream.pos) {
stream.pos += match[0].length;
stream.pos += match[0].length || 1;
return "searching";
} else if (match) {
stream.pos = match.index;
@ -39,59 +43,131 @@
}
function SearchState() {
this.posFrom = this.posTo = this.query = null;
this.posFrom = this.posTo = this.lastQuery = this.query = null;
this.overlay = null;
}
function getSearchState(cm) {
return cm.state.search || (cm.state.search = new SearchState());
}
function queryCaseInsensitive(query) {
return typeof query == "string" && query == query.toLowerCase();
}
function getSearchCursor(cm, query, pos) {
// Heuristic: if the query string is all lowercase, do a case insensitive search.
return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true});
}
function persistentDialog(cm, text, deflt, onEnter, onKeyDown) {
cm.openDialog(text, onEnter, {
value: deflt,
selectValueOnOpen: true,
closeOnEnter: false,
onClose: function() { clearSearch(cm); },
onKeyDown: onKeyDown,
bottom: cm.options.search.bottom
});
}
function dialog(cm, text, shortText, deflt, f) {
if (cm.openDialog) cm.openDialog(text, f, {value: deflt});
if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom});
else f(prompt(shortText, deflt));
}
function confirmDialog(cm, text, shortText, fs) {
if (cm.openConfirm) cm.openConfirm(text, fs);
else if (confirm(shortText)) fs[0]();
}
function parseString(string) {
return string.replace(/\\([nrt\\])/g, function(match, ch) {
if (ch == "n") return "\n"
if (ch == "r") return "\r"
if (ch == "t") return "\t"
if (ch == "\\") return "\\"
return match
})
}
function parseQuery(query) {
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
if (isRE) {
try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); }
catch(e) {} // Not a regular expression after all, do a string search
} else {
query = parseString(query)
}
if (typeof query == "string" ? query == "" : query.test(""))
query = /x^/;
return query;
}
var queryDialog =
'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
function doSearch(cm, rev) {
function startSearch(cm, state, query) {
state.queryText = query;
state.query = parseQuery(query);
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
cm.addOverlay(state.overlay);
if (cm.showMatchesOnScrollbar) {
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
}
}
function doSearch(cm, rev, persistent, immediate) {
var state = getSearchState(cm);
if (state.query) return findNext(cm, rev);
dialog(cm, queryDialog, "Search for:", cm.getSelection(), function(query) {
cm.operation(function() {
if (!query || state.query) return;
state.query = parseQuery(query);
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
cm.addOverlay(state.overlay);
if (cm.showMatchesOnScrollbar) {
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
var q = cm.getSelection() || state.lastQuery;
if (q instanceof RegExp && q.source == "x^") q = null
if (persistent && cm.openDialog) {
var hiding = null
var searchNext = function(query, event) {
CodeMirror.e_stop(event);
if (!query) return;
if (query != state.queryText) {
startSearch(cm, state, query);
state.posFrom = state.posTo = cm.getCursor();
}
if (hiding) hiding.style.opacity = 1
findNext(cm, event.shiftKey, function(_, to) {
var dialog
if (to.line < 3 && document.querySelector &&
(dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) &&
dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top)
(hiding = dialog).style.opacity = .4
})
};
persistentDialog(cm, getQueryDialog(cm), q, searchNext, function(event, query) {
var keyName = CodeMirror.keyName(event)
var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName]
if (cmd == "findNext" || cmd == "findPrev" ||
cmd == "findPersistentNext" || cmd == "findPersistentPrev") {
CodeMirror.e_stop(event);
startSearch(cm, getSearchState(cm), query);
cm.execCommand(cmd);
} else if (cmd == "find" || cmd == "findPersistent") {
CodeMirror.e_stop(event);
searchNext(query, event);
}
state.posFrom = state.posTo = cm.getCursor();
findNext(cm, rev);
});
});
if (immediate && q) {
startSearch(cm, state, q);
findNext(cm, rev);
}
} else {
dialog(cm, getQueryDialog(cm), "Search for:", q, function(query) {
if (query && !state.query) cm.operation(function() {
startSearch(cm, state, query);
state.posFrom = state.posTo = cm.getCursor();
findNext(cm, rev);
});
});
}
}
function findNext(cm, rev) {cm.operation(function() {
function findNext(cm, rev, callback) {cm.operation(function() {
var state = getSearchState(cm);
var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
if (!cursor.find(rev)) {
@ -99,39 +175,87 @@
if (!cursor.find(rev)) return;
}
cm.setSelection(cursor.from(), cursor.to());
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20);
state.posFrom = cursor.from(); state.posTo = cursor.to();
if (callback) callback(cursor.from(), cursor.to())
});}
function clearSearch(cm) {cm.operation(function() {
var state = getSearchState(cm);
state.lastQuery = state.query;
if (!state.query) return;
state.query = null;
state.query = state.queryText = null;
cm.removeOverlay(state.overlay);
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
});}
var replaceQueryDialog =
'Replace: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>Stop</button>";
function el(tag, attrs) {
var element = tag ? document.createElement(tag) : document.createDocumentFragment();
for (var key in attrs) {
element[key] = attrs[key];
}
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i]
element.appendChild(typeof child == "string" ? document.createTextNode(child) : child);
}
return element;
}
function getQueryDialog(cm) {
return el("", null,
el("span", {className: "CodeMirror-search-label"}, cm.phrase("Search:")), " ",
el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"}), " ",
el("span", {style: "color: #888", className: "CodeMirror-search-hint"},
cm.phrase("(Use /re/ syntax for regexp search)")));
}
function getReplaceQueryDialog(cm) {
return el("", null, " ",
el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"}), " ",
el("span", {style: "color: #888", className: "CodeMirror-search-hint"},
cm.phrase("(Use /re/ syntax for regexp search)")));
}
function getReplacementQueryDialog(cm) {
return el("", null,
el("span", {className: "CodeMirror-search-label"}, cm.phrase("With:")), " ",
el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"}));
}
function getDoReplaceConfirm(cm) {
return el("", null,
el("span", {className: "CodeMirror-search-label"}, cm.phrase("Replace?")), " ",
el("button", {}, cm.phrase("Yes")), " ",
el("button", {}, cm.phrase("No")), " ",
el("button", {}, cm.phrase("All")), " ",
el("button", {}, cm.phrase("Stop")));
}
function replaceAll(cm, query, text) {
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)/g, function(_, i) {return match[i];}));
} else cursor.replace(text);
}
});
}
function replace(cm, all) {
if (cm.getOption("readOnly")) return;
dialog(cm, replaceQueryDialog, "Replace:", cm.getSelection(), function(query) {
var query = cm.getSelection() || getSearchState(cm).lastQuery;
var dialogText = all ? cm.phrase("Replace all:") : cm.phrase("Replace:")
var fragment = el("", null,
el("span", {className: "CodeMirror-search-label"}, dialogText),
getReplaceQueryDialog(cm))
dialog(cm, fragment, dialogText, query, function(query) {
if (!query) return;
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) {
dialog(cm, getReplacementQueryDialog(cm), cm.phrase("Replace with:"), "", function(text) {
text = parseString(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)/g, function(_, i) {return match[i];}));
} else cursor.replace(text);
}
});
replaceAll(cm, query, text)
} else {
clearSearch(cm);
var cursor = getSearchCursor(cm, query, cm.getCursor());
var cursor = getSearchCursor(cm, query, cm.getCursor("from"));
var advance = function() {
var start = cursor.from(), match;
if (!(match = cursor.findNext())) {
@ -141,8 +265,9 @@
}
cm.setSelection(cursor.from(), cursor.to());
cm.scrollIntoView({from: cursor.from(), to: cursor.to()});
confirmDialog(cm, doReplaceConfirm, "Replace?",
[function() {doReplace(match);}, advance]);
confirmDialog(cm, getDoReplaceConfirm(cm), cm.phrase("Replace?"),
[function() {doReplace(match);}, advance,
function() {replaceAll(cm, query, text)}]);
};
var doReplace = function(match) {
cursor.replace(typeof query == "string" ? text :
@ -156,6 +281,9 @@
}
CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);};
CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);};
CodeMirror.commands.findPersistentNext = function(cm) {doSearch(cm, false, true, true);};
CodeMirror.commands.findPersistentPrev = function(cm) {doSearch(cm, true, true, true);};
CodeMirror.commands.findNext = doSearch;
CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);};
CodeMirror.commands.clearSearch = clearSearch;

View File

@ -1,189 +1,305 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(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);
mod(CodeMirror)
})(function(CodeMirror) {
"use strict";
var Pos = CodeMirror.Pos;
"use strict"
var Pos = CodeMirror.Pos
function SearchCursor(doc, query, pos, caseFold) {
this.atOccurrence = false; this.doc = doc;
if (caseFold == null && typeof query == "string") caseFold = false;
function regexpFlags(regexp) {
var flags = regexp.flags
return flags != null ? flags : (regexp.ignoreCase ? "i" : "")
+ (regexp.global ? "g" : "")
+ (regexp.multiline ? "m" : "")
}
pos = pos ? doc.clipPos(pos) : Pos(0, 0);
this.pos = {from: pos, to: pos};
function ensureFlags(regexp, flags) {
var current = regexpFlags(regexp), target = current
for (var i = 0; i < flags.length; i++) if (target.indexOf(flags.charAt(i)) == -1)
target += flags.charAt(i)
return current == target ? regexp : new RegExp(regexp.source, target)
}
// 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 = doc.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 + (match[0].length || 1);
if (cutOff == line.length) break;
}
var matchLen = (match && match[0].length) || 0;
if (!matchLen) {
if (start == 0 && line.length == 0) {match = undefined;}
else if (start != doc.getLine(pos.line).length) {
matchLen++;
}
}
} else {
query.lastIndex = pos.ch;
var line = doc.getLine(pos.line), match = query.exec(line);
var matchLen = (match && match[0].length) || 0;
var start = match && match.index;
if (start + matchLen != line.length && !matchLen) matchLen = 1;
}
if (match && matchLen)
return {from: Pos(pos.line, start),
to: Pos(pos.line, start + matchLen),
match: match};
};
} else { // String query
var origQuery = 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) {
if (reverse) {
var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig);
var match = line.lastIndexOf(query);
if (match > -1) {
match = adjustPos(orig, line, match);
return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
}
} else {
var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig);
var match = line.indexOf(query);
if (match > -1) {
match = adjustPos(orig, line, match) + pos.ch;
return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)};
}
}
};
}
} else {
var origTarget = origQuery.split("\n");
this.matches = function(reverse, pos) {
var last = target.length - 1;
if (reverse) {
if (pos.line - (target.length - 1) < doc.firstLine()) return;
if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return;
var to = Pos(pos.line, origTarget[last].length);
for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln)
if (target[i] != fold(doc.getLine(ln))) return;
var line = doc.getLine(ln), cut = line.length - origTarget[0].length;
if (fold(line.slice(cut)) != target[0]) return;
return {from: Pos(ln, cut), to: to};
} else {
if (pos.line + (target.length - 1) > doc.lastLine()) return;
var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length;
if (fold(line.slice(cut)) != target[0]) return;
var from = Pos(pos.line, cut);
for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln)
if (target[i] != fold(doc.getLine(ln))) return;
if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return;
return {from: from, to: Pos(ln, origTarget[last].length)};
}
};
function maybeMultiline(regexp) {
return /\\s|\\n|\n|\\W|\\D|\[\^/.test(regexp.source)
}
function searchRegexpForward(doc, regexp, start) {
regexp = ensureFlags(regexp, "g")
for (var line = start.line, ch = start.ch, last = doc.lastLine(); line <= last; line++, ch = 0) {
regexp.lastIndex = ch
var string = doc.getLine(line), match = regexp.exec(string)
if (match)
return {from: Pos(line, match.index),
to: Pos(line, match.index + match[0].length),
match: match}
}
}
function searchRegexpForwardMultiline(doc, regexp, start) {
if (!maybeMultiline(regexp)) return searchRegexpForward(doc, regexp, start)
regexp = ensureFlags(regexp, "gm")
var string, chunk = 1
for (var line = start.line, last = doc.lastLine(); line <= last;) {
// This grows the search buffer in exponentially-sized chunks
// between matches, so that nearby matches are fast and don't
// require concatenating the whole document (in case we're
// searching for something that has tons of matches), but at the
// same time, the amount of retries is limited.
for (var i = 0; i < chunk; i++) {
if (line > last) break
var curLine = doc.getLine(line++)
string = string == null ? curLine : string + "\n" + curLine
}
chunk = chunk * 2
regexp.lastIndex = start.ch
var match = regexp.exec(string)
if (match) {
var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
var startLine = start.line + before.length - 1, startCh = before[before.length - 1].length
return {from: Pos(startLine, startCh),
to: Pos(startLine + inside.length - 1,
inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
match: match}
}
}
}
function lastMatchIn(string, regexp, endMargin) {
var match, from = 0
while (from <= string.length) {
regexp.lastIndex = from
var newMatch = regexp.exec(string)
if (!newMatch) break
var end = newMatch.index + newMatch[0].length
if (end > string.length - endMargin) break
if (!match || end > match.index + match[0].length)
match = newMatch
from = newMatch.index + 1
}
return match
}
function searchRegexpBackward(doc, regexp, start) {
regexp = ensureFlags(regexp, "g")
for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
var string = doc.getLine(line)
var match = lastMatchIn(string, regexp, ch < 0 ? 0 : string.length - ch)
if (match)
return {from: Pos(line, match.index),
to: Pos(line, match.index + match[0].length),
match: match}
}
}
function searchRegexpBackwardMultiline(doc, regexp, start) {
if (!maybeMultiline(regexp)) return searchRegexpBackward(doc, regexp, start)
regexp = ensureFlags(regexp, "gm")
var string, chunkSize = 1, endMargin = doc.getLine(start.line).length - start.ch
for (var line = start.line, first = doc.firstLine(); line >= first;) {
for (var i = 0; i < chunkSize && line >= first; i++) {
var curLine = doc.getLine(line--)
string = string == null ? curLine : curLine + "\n" + string
}
chunkSize *= 2
var match = lastMatchIn(string, regexp, endMargin)
if (match) {
var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
var startLine = line + before.length, startCh = before[before.length - 1].length
return {from: Pos(startLine, startCh),
to: Pos(startLine + inside.length - 1,
inside.length == 1 ? startCh + inside[0].length : inside[inside.length - 1].length),
match: match}
}
}
}
var doFold, noFold
if (String.prototype.normalize) {
doFold = function(str) { return str.normalize("NFD").toLowerCase() }
noFold = function(str) { return str.normalize("NFD") }
} else {
doFold = function(str) { return str.toLowerCase() }
noFold = function(str) { return str }
}
// Maps a position in a case-folded line back to a position in the original line
// (compensating for codepoints increasing in number during folding)
function adjustPos(orig, folded, pos, foldFunc) {
if (orig.length == folded.length) return pos
for (var min = 0, max = pos + Math.max(0, orig.length - folded.length);;) {
if (min == max) return min
var mid = (min + max) >> 1
var len = foldFunc(orig.slice(0, mid)).length
if (len == pos) return mid
else if (len > pos) max = mid
else min = mid + 1
}
}
function searchStringForward(doc, query, start, caseFold) {
// Empty string would match anything and never progress, so we
// define it to match nothing instead.
if (!query.length) return null
var fold = caseFold ? doFold : noFold
var lines = fold(query).split(/\r|\n\r?/)
search: for (var line = start.line, ch = start.ch, last = doc.lastLine() + 1 - lines.length; line <= last; line++, ch = 0) {
var orig = doc.getLine(line).slice(ch), string = fold(orig)
if (lines.length == 1) {
var found = string.indexOf(lines[0])
if (found == -1) continue search
var start = adjustPos(orig, string, found, fold) + ch
return {from: Pos(line, adjustPos(orig, string, found, fold) + ch),
to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold) + ch)}
} else {
var cutFrom = string.length - lines[0].length
if (string.slice(cutFrom) != lines[0]) continue search
for (var i = 1; i < lines.length - 1; i++)
if (fold(doc.getLine(line + i)) != lines[i]) continue search
var end = doc.getLine(line + lines.length - 1), endString = fold(end), lastLine = lines[lines.length - 1]
if (endString.slice(0, lastLine.length) != lastLine) continue search
return {from: Pos(line, adjustPos(orig, string, cutFrom, fold) + ch),
to: Pos(line + lines.length - 1, adjustPos(end, endString, lastLine.length, fold))}
}
}
}
function searchStringBackward(doc, query, start, caseFold) {
if (!query.length) return null
var fold = caseFold ? doFold : noFold
var lines = fold(query).split(/\r|\n\r?/)
search: for (var line = start.line, ch = start.ch, first = doc.firstLine() - 1 + lines.length; line >= first; line--, ch = -1) {
var orig = doc.getLine(line)
if (ch > -1) orig = orig.slice(0, ch)
var string = fold(orig)
if (lines.length == 1) {
var found = string.lastIndexOf(lines[0])
if (found == -1) continue search
return {from: Pos(line, adjustPos(orig, string, found, fold)),
to: Pos(line, adjustPos(orig, string, found + lines[0].length, fold))}
} else {
var lastLine = lines[lines.length - 1]
if (string.slice(0, lastLine.length) != lastLine) continue search
for (var i = 1, start = line - lines.length + 1; i < lines.length - 1; i++)
if (fold(doc.getLine(start + i)) != lines[i]) continue search
var top = doc.getLine(line + 1 - lines.length), topString = fold(top)
if (topString.slice(topString.length - lines[0].length) != lines[0]) continue search
return {from: Pos(line + 1 - lines.length, adjustPos(top, topString, top.length - lines[0].length, fold)),
to: Pos(line, adjustPos(orig, string, lastLine.length, fold))}
}
}
}
function SearchCursor(doc, query, pos, options) {
this.atOccurrence = false
this.afterEmptyMatch = false
this.doc = doc
pos = pos ? doc.clipPos(pos) : Pos(0, 0)
this.pos = {from: pos, to: pos}
var caseFold
if (typeof options == "object") {
caseFold = options.caseFold
} else { // Backwards compat for when caseFold was the 4th argument
caseFold = options
options = null
}
if (typeof query == "string") {
if (caseFold == null) caseFold = false
this.matches = function(reverse, pos) {
return (reverse ? searchStringBackward : searchStringForward)(doc, query, pos, caseFold)
}
} else {
query = ensureFlags(query, "gm")
if (!options || options.multiline !== false)
this.matches = function(reverse, pos) {
return (reverse ? searchRegexpBackwardMultiline : searchRegexpForwardMultiline)(doc, query, pos)
}
else
this.matches = function(reverse, pos) {
return (reverse ? searchRegexpBackward : searchRegexpForward)(doc, query, pos)
}
}
}
SearchCursor.prototype = {
findNext: function() {return this.find(false);},
findPrevious: function() {return this.find(true);},
findNext: function() {return this.find(false)},
findPrevious: function() {return this.find(true)},
find: function(reverse) {
var self = this, pos = this.doc.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)) {
this.atOccurrence = true;
return this.pos.match || true;
}
var head = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
if (this.afterEmptyMatch && this.atOccurrence) {
// do not return the same 0 width match twice
head = Pos(head.line, head.ch)
if (reverse) {
if (!pos.line) return savePosAndFail(0);
pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length);
head.ch--;
if (head.ch < 0) {
head.line--;
head.ch = (this.doc.getLine(head.line) || "").length;
}
} else {
head.ch++;
if (head.ch > (this.doc.getLine(head.line) || "").length) {
head.ch = 0;
head.line++;
}
}
else {
var maxLine = this.doc.lineCount();
if (pos.line == maxLine - 1) return savePosAndFail(maxLine);
pos = Pos(pos.line + 1, 0);
if (CodeMirror.cmpPos(head, this.doc.clipPos(head)) != 0) {
return this.atOccurrence = false
}
}
var result = this.matches(reverse, head)
this.afterEmptyMatch = result && CodeMirror.cmpPos(result.from, result.to) == 0
if (result) {
this.pos = result
this.atOccurrence = true
return this.pos.match || true
} else {
var end = Pos(reverse ? this.doc.firstLine() : this.doc.lastLine() + 1, 0)
this.pos = {from: end, to: end}
return this.atOccurrence = false
}
},
from: function() {if (this.atOccurrence) return this.pos.from;},
to: function() {if (this.atOccurrence) return this.pos.to;},
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.doc.replaceRange(lines, this.pos.from, this.pos.to);
replace: function(newText, origin) {
if (!this.atOccurrence) return
var lines = CodeMirror.splitLines(newText)
this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin)
this.pos.to = Pos(this.pos.from.line + lines.length - 1,
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0));
}
};
// Maps a position in a case-folded line back to a position in the original line
// (compensating for codepoints increasing in number during folding)
function adjustPos(orig, folded, pos) {
if (orig.length == folded.length) return pos;
for (var pos1 = Math.min(pos, orig.length);;) {
var len1 = orig.slice(0, pos1).toLowerCase().length;
if (len1 < pos) ++pos1;
else if (len1 > pos) --pos1;
else return pos1;
lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0))
}
}
CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) {
return new SearchCursor(this.doc, query, pos, caseFold);
});
return new SearchCursor(this.doc, query, pos, caseFold)
})
CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
return new SearchCursor(this, query, pos, caseFold);
});
return new SearchCursor(this, query, pos, caseFold)
})
CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
var ranges = [], next;
var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
while (next = cur.findNext()) {
if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
ranges.push({anchor: cur.from(), head: cur.to()});
var ranges = []
var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold)
while (cur.findNext()) {
if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break
ranges.push({anchor: cur.from(), head: cur.to()})
}
if (ranges.length)
this.setSelections(ranges, 0);
});
this.setSelections(ranges, 0)
})
});

View File

@ -1,11 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Because sometimes you need to style the cursor's line.
//
// Adds an option 'styleActiveLine' which, when enabled, gives the
// active line's wrapping <div> the CSS class "CodeMirror-activeline",
// and gives its background <div> the class "CodeMirror-activeline-background".
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -18,24 +12,28 @@
"use strict";
var WRAP_CLASS = "CodeMirror-activeline";
var BACK_CLASS = "CodeMirror-activeline-background";
var GUTT_CLASS = "CodeMirror-activeline-gutter";
CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
var prev = old && old != CodeMirror.Init;
if (val && !prev) {
cm.state.activeLines = [];
updateActiveLines(cm, cm.listSelections());
cm.on("beforeSelectionChange", selectionChange);
} else if (!val && prev) {
var prev = old == CodeMirror.Init ? false : old;
if (val == prev) return
if (prev) {
cm.off("beforeSelectionChange", selectionChange);
clearActiveLines(cm);
delete cm.state.activeLines;
}
if (val) {
cm.state.activeLines = [];
updateActiveLines(cm, cm.listSelections());
cm.on("beforeSelectionChange", selectionChange);
}
});
function clearActiveLines(cm) {
for (var i = 0; i < cm.state.activeLines.length; i++) {
cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS);
}
}
@ -50,7 +48,9 @@
var active = [];
for (var i = 0; i < ranges.length; i++) {
var range = ranges[i];
if (!range.empty()) continue;
var option = cm.getOption("styleActiveLine");
if (typeof option == "object" && option.nonEmpty ? range.anchor.line != range.head.line : !range.empty())
continue
var line = cm.getLineHandleVisualStart(range.head.line);
if (active[active.length - 1] != line) active.push(line);
}
@ -60,6 +60,7 @@
for (var i = 0; i < active.length; i++) {
cm.addLineClass(active[i], "wrap", WRAP_CLASS);
cm.addLineClass(active[i], "background", BACK_CLASS);
cm.addLineClass(active[i], "gutter", GUTT_CLASS);
}
cm.state.activeLines = active;
});

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Because sometimes you need to mark the selected *text*.
//
@ -34,11 +34,12 @@
});
function onCursorActivity(cm) {
cm.operation(function() { update(cm); });
if (cm.state.markedSelection)
cm.operation(function() { update(cm); });
}
function onChange(cm) {
if (cm.state.markedSelection.length)
if (cm.state.markedSelection && cm.state.markedSelection.length)
cm.operation(function() { clear(cm); });
}
@ -85,7 +86,7 @@
if (!array.length) return coverRange(cm, from, to);
var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE ||
if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE ||
cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
return reset(cm);

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS

View File

@ -1,6 +1,7 @@
.CodeMirror-Tern-completion {
padding-left: 22px;
position: relative;
line-height: 1.5;
}
.CodeMirror-Tern-completion:before {
position: absolute;

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Glue code between CodeMirror and Tern.
//
@ -59,6 +59,7 @@
this.options = options || {};
var plugins = this.options.plugins || (this.options.plugins = {});
if (!plugins.doc_comment) plugins.doc_comment = true;
this.docs = Object.create(null);
if (this.options.useWorker) {
this.server = new WorkerServer(this);
} else {
@ -69,7 +70,6 @@
plugins: plugins
});
}
this.docs = Object.create(null);
this.trackChange = function(doc, change) { trackChange(self, doc, change); };
this.cachedArgHints = null;
@ -124,6 +124,8 @@
var self = this;
var doc = findDoc(this, cm.getDoc());
var request = buildRequest(this, doc, query, pos);
var extraOptions = request.query && this.options.queryOptions && this.options.queryOptions[request.query.type]
if (extraOptions) for (var prop in extraOptions) request.query[prop] = extraOptions[prop];
this.server.request(request, function (error, data) {
if (!error && self.options.responseFilter)
@ -133,6 +135,7 @@
},
destroy: function () {
closeArgHints(this)
if (this.worker) {
this.worker.terminate();
this.worker = null;
@ -176,7 +179,7 @@
var data = findDoc(ts, doc);
var argHints = ts.cachedArgHints;
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) <= 0)
if (argHints && argHints.doc == doc && cmpPos(argHints.start, change.to) >= 0)
ts.cachedArgHints = null;
var changed = data.changed;
@ -214,7 +217,7 @@
var completion = data.completions[i], className = typeToIcon(completion.type);
if (data.guess) className += " " + cls + "guess";
completions.push({text: completion.name + after,
displayText: completion.name,
displayText: completion.displayName || completion.name,
className: className,
data: completion});
}
@ -228,8 +231,7 @@
var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
if (content) {
tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
node.getBoundingClientRect().top + window.pageYOffset, content);
tooltip.className += " " + cls + "hint-doc";
node.getBoundingClientRect().top + window.pageYOffset, content, cm, cls + "hint-doc");
}
});
c(obj);
@ -264,7 +266,7 @@
child.target = "_blank";
}
}
tempTooltip(cm, tip);
tempTooltip(cm, tip, ts);
if (c) c();
}, pos);
}
@ -303,7 +305,7 @@
ts.request(cm, {type: "type", preferFunction: true, end: start}, function(error, data) {
if (error || !data.type || !(/^fn\(/).test(data.type)) return;
ts.cachedArgHints = {
start: pos,
start: start,
type: parseFnType(data.type),
name: data.exprName || data.name || "fn",
guess: data.guess,
@ -331,7 +333,11 @@
tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
var place = cm.cursorCoords(null, "page");
ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip);
var tooltip = ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip, cm)
setTimeout(function() {
tooltip.clear = onEditorActivity(cm, function() {
if (ts.activeArgHints == tooltip) closeArgHints(ts) })
}, 20)
}
function parseFnType(text) {
@ -442,8 +448,8 @@
function atInterestingExpression(cm) {
var pos = cm.getCursor("end"), tok = cm.getTokenAt(pos);
if (tok.start < pos.ch && (tok.type == "comment" || tok.type == "string")) return false;
return /\w/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
if (tok.start < pos.ch && tok.type == "comment") return false;
return /[\w)\]]/.test(cm.getLine(pos.line).slice(Math.max(pos.ch - 1, 0), pos.ch + 1));
}
// Variable renaming
@ -464,11 +470,12 @@
ts.request(cm, {type: "refs"}, function(error, data) {
if (error) return showError(ts, cm, error);
var ranges = [], cur = 0;
var curPos = cm.getCursor();
for (var i = 0; i < data.refs.length; i++) {
var ref = data.refs[i];
if (ref.file == name) {
ranges.push({anchor: ref.start, head: ref.end});
if (cmpPos(cur, ref.start) >= 0 && cmpPos(cur, ref.end) <= 0)
if (cmpPos(curPos, ref.start) >= 0 && cmpPos(curPos, ref.end) <= 0)
cur = ranges.length - 1;
}
}
@ -563,7 +570,7 @@
return {type: "part",
name: data.name,
offsetLines: from.line,
text: doc.getRange(from, Pos(endLine, 0))};
text: doc.getRange(from, Pos(endLine, end.line == endLine ? null : 0))};
}
// Generic utilities
@ -590,41 +597,83 @@
// Tooltips
function tempTooltip(cm, content) {
function tempTooltip(cm, content, ts) {
if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
var where = cm.cursorCoords();
var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content, cm);
function maybeClear() {
old = true;
if (!mouseOnTip) clear();
}
function clear() {
cm.state.ternTooltip = null;
if (!tip.parentNode) return;
cm.off("cursorActivity", clear);
cm.off('blur', clear);
cm.off('scroll', clear);
fadeOut(tip);
if (tip.parentNode) fadeOut(tip)
clearActivity()
}
var mouseOnTip = false, old = false;
CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
CodeMirror.on(tip, "mouseout", function(e) {
if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) {
var related = e.relatedTarget || e.toElement
if (!related || !CodeMirror.contains(tip, related)) {
if (old) clear();
else mouseOnTip = false;
}
});
setTimeout(maybeClear, 1700);
cm.on("cursorActivity", clear);
cm.on('blur', clear);
cm.on('scroll', clear);
setTimeout(maybeClear, ts.options.hintDelay ? ts.options.hintDelay : 1700);
var clearActivity = onEditorActivity(cm, clear)
}
function makeTooltip(x, y, content) {
var node = elt("div", cls + "tooltip", content);
function onEditorActivity(cm, f) {
cm.on("cursorActivity", f)
cm.on("blur", f)
cm.on("scroll", f)
cm.on("setDoc", f)
return function() {
cm.off("cursorActivity", f)
cm.off("blur", f)
cm.off("scroll", f)
cm.off("setDoc", f)
}
}
function makeTooltip(x, y, content, cm, className) {
var node = elt("div", cls + "tooltip" + " " + (className || ""), content);
node.style.left = x + "px";
node.style.top = y + "px";
document.body.appendChild(node);
var container = ((cm.options || {}).hintOptions || {}).container || document.body;
container.appendChild(node);
var pos = cm.cursorCoords();
var winW = window.innerWidth;
var winH = window.innerHeight;
var box = node.getBoundingClientRect();
var hints = document.querySelector(".CodeMirror-hints");
var overlapY = box.bottom - winH;
var overlapX = box.right - winW;
if (hints && overlapX > 0) {
node.style.left = 0;
var box = node.getBoundingClientRect();
node.style.left = (x = x - hints.offsetWidth - box.width) + "px";
overlapX = box.right - winW;
}
if (overlapY > 0) {
var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
if (curTop - height > 0) { // Fits above cursor
node.style.top = (pos.top - height) + "px";
} else if (height > winH) {
node.style.height = (winH - 5) + "px";
node.style.top = (pos.bottom - box.top) + "px";
}
}
if (overlapX > 0) {
if (box.right - box.left > winW) {
node.style.width = (winW - 5) + "px";
overlapX -= (box.right - box.left) - winW;
}
node.style.left = (x - overlapX) + "px";
}
return node;
}
@ -642,11 +691,15 @@
if (ts.options.showError)
ts.options.showError(cm, msg);
else
tempTooltip(cm, String(msg));
tempTooltip(cm, String(msg), ts);
}
function closeArgHints(ts) {
if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; }
if (ts.activeArgHints) {
if (ts.activeArgHints.clear) ts.activeArgHints.clear()
remove(ts.activeArgHints)
ts.activeArgHints = null
}
}
function docValue(ts, doc) {

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
// declare global: tern, server
@ -39,6 +39,6 @@ function startServer(defs, plugins, scripts) {
});
}
var console = {
this.console = {
log: function(v) { postMessage({type: "debug", message: v}); }
};

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -29,25 +29,40 @@
return {from: start, to: end};
}
function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
for (var at = column; at > 0; --at)
function findBreakPoint(text, column, wrapOn, killTrailingSpace, forceBreak) {
var at = column
while (at < text.length && text.charAt(at) == " ") at++
for (; at > 0; --at)
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
if (at == 0) at = column;
var endOfText = at;
if (killTrailingSpace)
while (text.charAt(endOfText - 1) == " ") --endOfText;
return {from: endOfText, to: at};
if (!forceBreak && at <= text.match(/^[ \t]*/)[0].length) {
// didn't find a break point before column, in non-forceBreak mode try to
// find one after 'column'.
for (at = column + 1; at < text.length - 1; ++at) {
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
}
}
for (var first = true;; first = false) {
var endOfText = at;
if (killTrailingSpace)
while (text.charAt(endOfText - 1) == " ") --endOfText;
if (endOfText == 0 && first) at = column;
else return {from: endOfText, to: at};
}
}
function wrapRange(cm, from, to, options) {
from = cm.clipPos(from); to = cm.clipPos(to);
var column = options.column || 80;
var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
var forceBreak = options.forceBreak !== false;
var killTrailing = options.killTrailingSpace !== false;
var changes = [], curLine = "", curNo = from.line;
var lines = cm.getRange(from, to, false);
if (!lines.length) return null;
var leadingSpace = lines[0].match(/^[ \t]*/)[0];
if (leadingSpace.length >= column) column = leadingSpace.length + 1
for (var i = 0; i < lines.length; ++i) {
var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
@ -63,7 +78,7 @@
curLine += text;
if (i) {
var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
findBreakPoint(curLine, column, wrapOn, killTrailing);
findBreakPoint(curLine, column, wrapOn, killTrailing, forceBreak);
// If this isn't broken, or is broken at a different point, remove old break
if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
changes.push({text: [spaceInserted ? " " : ""],
@ -75,18 +90,24 @@
}
}
while (curLine.length > column) {
var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
changes.push({text: ["", leadingSpace],
from: Pos(curNo, bp.from),
to: Pos(curNo, bp.to)});
curLine = leadingSpace + curLine.slice(bp.to);
++curNo;
var bp = findBreakPoint(curLine, column, wrapOn, killTrailing, forceBreak);
if (bp.from != bp.to ||
forceBreak && leadingSpace !== curLine.slice(0, bp.to)) {
changes.push({text: ["", leadingSpace],
from: Pos(curNo, bp.from),
to: Pos(curNo, bp.to)});
curLine = leadingSpace + curLine.slice(bp.to);
++curNo;
} else {
break;
}
}
}
if (changes.length) cm.operation(function() {
for (var i = 0; i < changes.length; ++i) {
var change = changes[i];
cm.replaceRange(change.text, change.from, change.to);
if (change.text || CodeMirror.cmpPos(change.from, change.to))
cm.replaceRange(change.text, change.from, change.to);
}
});
return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,3 @@
/*!
// CodeMirror v5.0, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// This is CodeMirror (http://codemirror.net), a code editor
// implemented in JavaScript on top of the browser's DOM.
//
// You can find some technical background for some of the code below
// at http://marijnhaverbeke.nl/blog/#cm-internals .
*/
/* BASICS */
.CodeMirror {
@ -16,6 +5,7 @@
font-family: monospace;
height: 300px;
color: black;
direction: ltr;
}
/* PADDING */
@ -23,7 +13,8 @@
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre {
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
padding: 0 4px; /* Horizontal padding of content */
}
@ -44,8 +35,7 @@
min-width: 20px;
text-align: right;
color: #999;
-moz-box-sizing: content-box;
box-sizing: content-box;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
@ -53,57 +43,73 @@
/* CURSOR */
.CodeMirror div.CodeMirror-cursor {
.CodeMirror-cursor {
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;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursor {
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0;
border: 0 !important;
background: #7e7;
}
.CodeMirror.cm-fat-cursor div.CodeMirror-cursors {
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.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;
}
.cm-fat-cursor .CodeMirror-line::selection,
.cm-fat-cursor .CodeMirror-line > span::selection,
.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; }
.cm-fat-cursor .CodeMirror-line::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; }
.cm-fat-cursor { caret-color: transparent; }
@-moz-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% { background: #7e7; }
50% { background: none; }
100% { background: #7e7; }
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
div.CodeMirror-overwrite div.CodeMirror-cursor {}
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-rulers {
position: absolute;
left: 0; right: 0; top: -50px; bottom: 0;
overflow: hidden;
}
.CodeMirror-ruler {
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-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
@ -113,7 +119,7 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3 {color: #085;}
.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;}
@ -123,25 +129,18 @@ div.CodeMirror-overwrite div.CodeMirror-cursor {}
.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-strikethrough {text-decoration: line-through;}
.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: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
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;}
@ -158,30 +157,28 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.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 */
/* 50px 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;
margin-bottom: -50px; margin-right: -50px;
padding-bottom: 50px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
z-index: 0;
}
.CodeMirror-sizer {
position: relative;
border-right: 30px solid transparent;
-moz-box-sizing: content-box;
box-sizing: content-box;
border-right: 50px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and
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;
outline: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
@ -202,40 +199,41 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
display: inline-block;
margin-bottom: -30px;
/* Hack to make IE7 behave */
*zoom:1;
*display:inline;
vertical-align: top;
margin-bottom: -50px;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
height: 100%;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.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 */
}
.CodeMirror pre {
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
/* 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;
@ -251,8 +249,11 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual;
}
.CodeMirror-wrap pre {
.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
@ -267,15 +268,27 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
overflow: auto;
padding: 0.1px; /* Force widget margins to stay inside of the container */
}
.CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
@ -283,19 +296,22 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
overflow: hidden;
visibility: hidden;
}
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor {
.CodeMirror-cursor {
position: absolute;
border-right: none;
width: 0;
pointer-events: none;
}
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
@ -303,17 +319,14 @@ div.CodeMirror-cursors {
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror ::selection { background: #d7d4f0; }
.CodeMirror ::-moz-selection { background: #d7d4f0; }
.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: #ffa;
background: rgba(255, 255, 0, .4);
background-color: #ffa;
background-color: rgba(255, 255, 0, .4);
}
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
.CodeMirror span { *vertical-align: text-bottom; }
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -102,7 +102,7 @@ CodeMirror.defineMode("apl", function() {
};
},
token: function(stream, state) {
var ch, funcName, word;
var ch, funcName;
if (stream.eatSpace()) {
return null;
}
@ -163,7 +163,6 @@ CodeMirror.defineMode("apl", function() {
return "function jot-dot";
}
stream.eatWhile(/[\w\$_]/);
word = stream.current();
state.prev = true;
return "keyword";
}

View File

@ -12,7 +12,7 @@
.CodeMirror { border: 2px inset #dee; }
</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul>
<li><a href="../../index.html">Home</a>

View File

@ -0,0 +1,74 @@
// 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"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
function errorIfNotEmpty(stream) {
var nonWS = stream.match(/^\s*\S/);
stream.skipToEnd();
return nonWS ? "error" : null;
}
CodeMirror.defineMode("asciiarmor", function() {
return {
token: function(stream, state) {
var m;
if (state.state == "top") {
if (stream.sol() && (m = stream.match(/^-----BEGIN (.*)?-----\s*$/))) {
state.state = "headers";
state.type = m[1];
return "tag";
}
return errorIfNotEmpty(stream);
} else if (state.state == "headers") {
if (stream.sol() && stream.match(/^\w+:/)) {
state.state = "header";
return "atom";
} else {
var result = errorIfNotEmpty(stream);
if (result) state.state = "body";
return result;
}
} else if (state.state == "header") {
stream.skipToEnd();
state.state = "headers";
return "string";
} else if (state.state == "body") {
if (stream.sol() && (m = stream.match(/^-----END (.*)?-----\s*$/))) {
if (m[1] != state.type) return "error";
state.state = "end";
return "tag";
} else {
if (stream.eatWhile(/[A-Za-z0-9+\/=]/)) {
return null;
} else {
stream.next();
return "error";
}
}
} else if (state.state == "end") {
return errorIfNotEmpty(stream);
}
},
blankLine: function(state) {
if (state.state == "headers") state.state = "body";
},
startState: function() {
return {state: "top", type: null};
}
};
});
CodeMirror.defineMIME("application/pgp", "asciiarmor");
CodeMirror.defineMIME("application/pgp-encrypted", "asciiarmor");
CodeMirror.defineMIME("application/pgp-keys", "asciiarmor");
CodeMirror.defineMIME("application/pgp-signature", "asciiarmor");
});

View File

@ -0,0 +1,46 @@
<!doctype html>
<title>CodeMirror: ASCII Armor (PGP) mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="asciiarmor.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#">ASCII Armor</a>
</ul>
</div>
<article>
<h2>ASCII Armor (PGP) mode</h2>
<form><textarea id="code" name="code">
-----BEGIN PGP MESSAGE-----
Version: OpenPrivacy 0.99
yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
vBSFjNSiVHsuAA==
=njUN
-----END PGP MESSAGE-----
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true
});
</script>
<p><strong>MIME types
defined:</strong> <code>application/pgp</code>, <code>application/pgp-encrypted</code>, <code>application/pgp-keys</code>, <code>application/pgp-signature</code></p>
</article>

View File

@ -0,0 +1,204 @@
// 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"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("asn.1", function(config, parserConfig) {
var indentUnit = config.indentUnit,
keywords = parserConfig.keywords || {},
cmipVerbs = parserConfig.cmipVerbs || {},
compareTypes = parserConfig.compareTypes || {},
status = parserConfig.status || {},
tags = parserConfig.tags || {},
storage = parserConfig.storage || {},
modifier = parserConfig.modifier || {},
accessTypes = parserConfig.accessTypes|| {},
multiLineStrings = parserConfig.multiLineStrings,
indentStatements = parserConfig.indentStatements !== false;
var isOperatorChar = /[\|\^]/;
var curPunc;
function tokenBase(stream, state) {
var ch = stream.next();
if (ch == '"' || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
if (/[\[\]\(\){}:=,;]/.test(ch)) {
curPunc = ch;
return "punctuation";
}
if (ch == "-"){
if (stream.eat("-")) {
stream.skipToEnd();
return "comment";
}
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);
return "number";
}
if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
return "operator";
}
stream.eatWhile(/[\w\-]/);
var cur = stream.current();
if (keywords.propertyIsEnumerable(cur)) return "keyword";
if (cmipVerbs.propertyIsEnumerable(cur)) return "variable cmipVerbs";
if (compareTypes.propertyIsEnumerable(cur)) return "atom compareTypes";
if (status.propertyIsEnumerable(cur)) return "comment status";
if (tags.propertyIsEnumerable(cur)) return "variable-3 tags";
if (storage.propertyIsEnumerable(cur)) return "builtin storage";
if (modifier.propertyIsEnumerable(cur)) return "string-2 modifier";
if (accessTypes.propertyIsEnumerable(cur)) return "atom accessTypes";
return "variable";
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next, end = false;
while ((next = stream.next()) != null) {
if (next == quote && !escaped){
var afterNext = stream.peek();
//look if the character if the quote is like the B in '10100010'B
if (afterNext){
afterNext = afterNext.toLowerCase();
if(afterNext == "b" || afterNext == "h" || afterNext == "o")
stream.next();
}
end = true; break;
}
escaped = !escaped && next == "\\";
}
if (end || !(escaped || multiLineStrings))
state.tokenize = null;
return "string";
};
}
function Context(indented, column, type, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type) {
var indent = state.indented;
if (state.context && state.context.type == "statement")
indent = state.context.indented;
return state.context = new Context(indent, col, type, null, state.context);
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" || t == "}")
state.indented = state.context.indented;
return state.context = state.context.prev;
}
//Interface
return {
startState: function(basecolumn) {
return {
tokenize: null,
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
indented: 0,
startOfLine: true
};
},
token: function(stream, state) {
var ctx = state.context;
if (stream.sol()) {
if (ctx.align == null) ctx.align = false;
state.indented = stream.indentation();
state.startOfLine = true;
}
if (stream.eatSpace()) return null;
curPunc = null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style == "comment") return style;
if (ctx.align == null) ctx.align = true;
if ((curPunc == ";" || curPunc == ":" || curPunc == ",")
&& ctx.type == "statement"){
popContext(state);
}
else if (curPunc == "{") pushContext(state, stream.column(), "}");
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
else if (curPunc == "}") {
while (ctx.type == "statement") ctx = popContext(state);
if (ctx.type == "}") ctx = popContext(state);
while (ctx.type == "statement") ctx = popContext(state);
}
else if (curPunc == ctx.type) popContext(state);
else if (indentStatements && (((ctx.type == "}" || ctx.type == "top")
&& curPunc != ';') || (ctx.type == "statement"
&& curPunc == "newstatement")))
pushContext(state, stream.column(), "statement");
state.startOfLine = false;
return style;
},
electricChars: "{}",
lineComment: "--",
fold: "brace"
};
});
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
CodeMirror.defineMIME("text/x-ttcn-asn", {
name: "asn.1",
keywords: words("DEFINITIONS OBJECTS IF DERIVED INFORMATION ACTION" +
" REPLY ANY NAMED CHARACTERIZED BEHAVIOUR REGISTERED" +
" WITH AS IDENTIFIED CONSTRAINED BY PRESENT BEGIN" +
" IMPORTS FROM UNITS SYNTAX MIN-ACCESS MAX-ACCESS" +
" MINACCESS MAXACCESS REVISION STATUS DESCRIPTION" +
" SEQUENCE SET COMPONENTS OF CHOICE DistinguishedName" +
" ENUMERATED SIZE MODULE END INDEX AUGMENTS EXTENSIBILITY" +
" IMPLIED EXPORTS"),
cmipVerbs: words("ACTIONS ADD GET NOTIFICATIONS REPLACE REMOVE"),
compareTypes: words("OPTIONAL DEFAULT MANAGED MODULE-TYPE MODULE_IDENTITY" +
" MODULE-COMPLIANCE OBJECT-TYPE OBJECT-IDENTITY" +
" OBJECT-COMPLIANCE MODE CONFIRMED CONDITIONAL" +
" SUBORDINATE SUPERIOR CLASS TRUE FALSE NULL" +
" TEXTUAL-CONVENTION"),
status: words("current deprecated mandatory obsolete"),
tags: words("APPLICATION AUTOMATIC EXPLICIT IMPLICIT PRIVATE TAGS" +
" UNIVERSAL"),
storage: words("BOOLEAN INTEGER OBJECT IDENTIFIER BIT OCTET STRING" +
" UTCTime InterfaceIndex IANAifType CMIP-Attribute" +
" REAL PACKAGE PACKAGES IpAddress PhysAddress" +
" NetworkAddress BITS BMPString TimeStamp TimeTicks" +
" TruthValue RowStatus DisplayString GeneralString" +
" GraphicString IA5String NumericString" +
" PrintableString SnmpAdminString TeletexString" +
" UTF8String VideotexString VisibleString StringStore" +
" ISO646String T61String UniversalString Unsigned32" +
" Integer32 Gauge Gauge32 Counter Counter32 Counter64"),
modifier: words("ATTRIBUTE ATTRIBUTES MANDATORY-GROUP MANDATORY-GROUPS" +
" GROUP GROUPS ELEMENTS EQUALITY ORDERING SUBSTRINGS" +
" DEFINED"),
accessTypes: words("not-accessible accessible-for-notify read-only" +
" read-create read-write"),
multiLineStrings: true
});
});

View File

@ -0,0 +1,78 @@
<!doctype html>
<title>CodeMirror: ASN.1 mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="asn.1.js"></script>
<style>
.CodeMirror {
border-top: 1px solid black;
border-bottom: 1px solid black;
}
</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1>
<img id=logo src="../../doc/logo.png" alt="">
</a>
<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One">ASN.1</a>
</ul>
</div>
<article>
<h2>ASN.1 example</h2>
<div>
<textarea id="ttcn-asn-code">
--
-- Sample ASN.1 Code
--
MyModule DEFINITIONS ::=
BEGIN
MyTypes ::= SEQUENCE {
myObjectId OBJECT IDENTIFIER,
mySeqOf SEQUENCE OF MyInt,
myBitString BIT STRING {
muxToken(0),
modemToken(1)
}
}
MyInt ::= INTEGER (0..65535)
END
</textarea>
</div>
<script>
var ttcnEditor = CodeMirror.fromTextArea(document.getElementById("ttcn-asn-code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-ttcn-asn"
});
ttcnEditor.setSize(400, 400);
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
</script>
<br/>
<p><strong>Language:</strong> Abstract Syntax Notation One
(<a href="http://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx">ASN.1</a>)
</p>
<p><strong>MIME types defined:</strong> <code>text/x-ttcn-asn</code></p>
<br/>
<p>The development of this mode has been sponsored by <a href="http://www.ericsson.com/">Ericsson
</a>.</p>
<p>Coded by Asmelash Tsegay Gebretsadkan </p>
</article>

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
/*
* =====================================================================================
@ -9,7 +9,7 @@
* Description: CodeMirror mode for Asterisk dialplan
*
* Created: 05/17/2012 09:20:25 PM
* Revision: none
* Revision: 08/05/2019 AstLinux Project: Support block-comments
*
* Author: Stas Kobzar (stas@modulis.ca),
* Company: Modulis.ca Inc.
@ -65,10 +65,28 @@ CodeMirror.defineMode("asterisk", function() {
function basicToken(stream,state){
var cur = '';
var ch = '';
ch = stream.next();
var ch = stream.next();
// comment
if (state.blockComment) {
if (ch == "-" && stream.match("-;", true)) {
state.blockComment = false;
} else if (stream.skipTo("--;")) {
stream.next();
stream.next();
stream.next();
state.blockComment = false;
} else {
stream.skipToEnd();
}
return "comment";
}
if(ch == ";") {
if (stream.match("--", true)) {
if (!stream.match("-", false)) { // Except ;--- is not a block comment
state.blockComment = true;
return "comment";
}
}
stream.skipToEnd();
return "comment";
}
@ -125,6 +143,7 @@ CodeMirror.defineMode("asterisk", function() {
return {
startState: function() {
return {
blockComment: false,
extenStart: false,
extenSame: false,
extenInclude: false,
@ -136,7 +155,6 @@ CodeMirror.defineMode("asterisk", function() {
token: function(stream, state) {
var cur = '';
var ch = '';
if(stream.eatSpace()) return null;
// extension started
if(state.extenStart){
@ -170,7 +188,7 @@ CodeMirror.defineMode("asterisk", function() {
} else if(state.extenPriority) {
state.extenPriority = false;
state.extenApplication = true;
ch = stream.next(); // get comma
stream.next(); // get comma
if(state.extenSame) return null;
stream.eatWhile(/[^,]/);
return "number";
@ -189,7 +207,11 @@ CodeMirror.defineMode("asterisk", function() {
}
return null;
}
},
blockCommentStart: ";--",
blockCommentEnd: "--;",
lineComment: ";"
};
});

View File

@ -6,13 +6,14 @@
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="asterisk.js"></script>
<style>
.CodeMirror {border: 1px solid #999;}
.cm-s-default span.cm-arrow { color: red; }
</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul>
<li><a href="../../index.html">Home</a>
@ -145,7 +146,7 @@ exten => 8500,n,Goto(s,6)
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "text/x-asterisk",
matchBrackets: true,
lineNumber: true
lineNumbers: true
});
</script>

View File

@ -0,0 +1,85 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
// Brainfuck mode created by Michael Kaminsky https://github.com/mkaminsky11
(function(mod) {
if (typeof exports == "object" && typeof module == "object")
mod(require("../../lib/codemirror"))
else if (typeof define == "function" && define.amd)
define(["../../lib/codemirror"], mod)
else
mod(CodeMirror)
})(function(CodeMirror) {
"use strict"
var reserve = "><+-.,[]".split("");
/*
comments can be either:
placed behind lines
+++ this is a comment
where reserved characters cannot be used
or in a loop
[
this is ok to use [ ] and stuff
]
or preceded by #
*/
CodeMirror.defineMode("brainfuck", function() {
return {
startState: function() {
return {
commentLine: false,
left: 0,
right: 0,
commentLoop: false
}
},
token: function(stream, state) {
if (stream.eatSpace()) return null
if(stream.sol()){
state.commentLine = false;
}
var ch = stream.next().toString();
if(reserve.indexOf(ch) !== -1){
if(state.commentLine === true){
if(stream.eol()){
state.commentLine = false;
}
return "comment";
}
if(ch === "]" || ch === "["){
if(ch === "["){
state.left++;
}
else{
state.right++;
}
return "bracket";
}
else if(ch === "+" || ch === "-"){
return "keyword";
}
else if(ch === "<" || ch === ">"){
return "atom";
}
else if(ch === "." || ch === ","){
return "def";
}
}
else{
state.commentLine = true;
if(stream.eol()){
state.commentLine = false;
}
return "comment";
}
if(stream.eol()){
state.commentLine = false;
}
}
};
});
CodeMirror.defineMIME("text/x-brainfuck","brainfuck")
});

View File

@ -0,0 +1,85 @@
<!doctype html>
<title>CodeMirror: Brainfuck mode</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../../doc/docs.css">
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="./brainfuck.js"></script>
<style>
.CodeMirror { border: 2px inset #dee; }
</style>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul>
<li><a href="../../index.html">Home</a>
<li><a href="../../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a href="../index.html">Language modes</a>
<li><a class=active href="#"></a>
</ul>
</div>
<article>
<h2>Brainfuck mode</h2>
<form><textarea id="code" name="code">
[ This program prints "Hello World!" and a newline to the screen, its
length is 106 active command characters [it is not the shortest.]
This loop is a "comment loop", it's a simple way of adding a comment
to a BF program such that you don't have to worry about any command
characters. Any ".", ",", "+", "-", "&lt;" and "&gt;" characters are simply
ignored, the "[" and "]" characters just have to be balanced.
]
+++++ +++ Set Cell #0 to 8
[
&gt;++++ Add 4 to Cell #1; this will always set Cell #1 to 4
[ as the cell will be cleared by the loop
&gt;++ Add 2 to Cell #2
&gt;+++ Add 3 to Cell #3
&gt;+++ Add 3 to Cell #4
&gt;+ Add 1 to Cell #5
&lt;&lt;&lt;&lt;- Decrement the loop counter in Cell #1
] Loop till Cell #1 is zero; number of iterations is 4
&gt;+ Add 1 to Cell #2
&gt;+ Add 1 to Cell #3
&gt;- Subtract 1 from Cell #4
&gt;&gt;+ Add 1 to Cell #6
[&lt;] Move back to the first zero cell you find; this will
be Cell #1 which was cleared by the previous loop
&lt;- Decrement the loop Counter in Cell #0
] Loop till Cell #0 is zero; number of iterations is 8
The result of this is:
Cell No : 0 1 2 3 4 5 6
Contents: 0 0 72 104 88 32 8
Pointer : ^
&gt;&gt;. Cell #2 has value 72 which is 'H'
&gt;---. Subtract 3 from Cell #3 to get 101 which is 'e'
+++++++..+++. Likewise for 'llo' from Cell #3
&gt;&gt;. Cell #5 is 32 for the space
&lt;-. Subtract 1 from Cell #4 for 87 to give a 'W'
&lt;. Cell #3 was set to 'o' from the end of 'Hello'
+++.------.--------. Cell #3 for 'rl' and 'd'
&gt;&gt;+. Add 1 to Cell #5 gives us an exclamation point
&gt;++. And finally a newline from Cell #6
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-brainfuck"
});
</script>
<p>A mode for Brainfuck</p>
<p><strong>MIME types defined:</strong> <code>text/x-brainfuck</code></p>
</article>

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -11,20 +11,66 @@
})(function(CodeMirror) {
"use strict";
function Context(indented, column, type, info, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.info = info;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type, info) {
var indent = state.indented;
if (state.context && state.context.type == "statement" && type != "statement")
indent = state.context.indented;
return state.context = new Context(indent, col, type, info, null, state.context);
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" || t == "}")
state.indented = state.context.indented;
return state.context = state.context.prev;
}
function typeBefore(stream, state, pos) {
if (state.prevToken == "variable" || state.prevToken == "type") return true;
if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
}
function isTopScope(context) {
for (;;) {
if (!context || context.type == "top") return true;
if (context.type == "}" && context.prev.info != "namespace") return false;
context = context.prev;
}
}
CodeMirror.defineMode("clike", function(config, parserConfig) {
var indentUnit = config.indentUnit,
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
dontAlignCalls = parserConfig.dontAlignCalls,
keywords = parserConfig.keywords || {},
types = parserConfig.types || {},
builtin = parserConfig.builtin || {},
blockKeywords = parserConfig.blockKeywords || {},
defKeywords = parserConfig.defKeywords || {},
atoms = parserConfig.atoms || {},
hooks = parserConfig.hooks || {},
multiLineStrings = parserConfig.multiLineStrings,
indentStatements = parserConfig.indentStatements !== false;
var isOperatorChar = /[+\-*&%=<>!?|\/]/;
indentStatements = parserConfig.indentStatements !== false,
indentSwitch = parserConfig.indentSwitch !== false,
namespaceSeparator = parserConfig.namespaceSeparator,
isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
numberStart = parserConfig.numberStart || /[\d\.]/,
number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,
isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
isIdentifierChar = parserConfig.isIdentifierChar || /[\w\$_\xa1-\uffff]/,
// An optional function that takes a {string} token and returns true if it
// should be treated as a builtin.
isReservedIdentifier = parserConfig.isReservedIdentifier || false;
var curPunc;
var curPunc, isDefKeyword;
function tokenBase(stream, state) {
var ch = stream.next();
@ -36,14 +82,15 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
if (numberStart.test(ch)) {
stream.backUp(1)
if (stream.match(number)) return "number"
stream.next()
}
if (isPunctuationChar.test(ch)) {
curPunc = ch;
return null;
}
if (/\d/.test(ch)) {
stream.eatWhile(/[\w\.]/);
return "number";
}
if (ch == "/") {
if (stream.eat("*")) {
state.tokenize = tokenComment;
@ -55,20 +102,26 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
}
}
if (isOperatorChar.test(ch)) {
stream.eatWhile(isOperatorChar);
while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {}
return "operator";
}
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
stream.eatWhile(isIdentifierChar);
if (namespaceSeparator) while (stream.match(namespaceSeparator))
stream.eatWhile(isIdentifierChar);
var cur = stream.current();
if (keywords.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
if (contains(keywords, cur)) {
if (contains(blockKeywords, cur)) curPunc = "newstatement";
if (contains(defKeywords, cur)) isDefKeyword = true;
return "keyword";
}
if (builtin.propertyIsEnumerable(cur)) {
if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
if (contains(types, cur)) return "type";
if (contains(builtin, cur)
|| (isReservedIdentifier && isReservedIdentifier(cur))) {
if (contains(blockKeywords, cur)) curPunc = "newstatement";
return "builtin";
}
if (atoms.propertyIsEnumerable(cur)) return "atom";
if (contains(atoms, cur)) return "atom";
return "variable";
}
@ -97,24 +150,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return "comment";
}
function Context(indented, column, type, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type) {
var indent = state.indented;
if (state.context && state.context.type == "statement")
indent = state.context.indented;
return state.context = new Context(indent, col, type, null, state.context);
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" || t == "}")
state.indented = state.context.indented;
return state.context = state.context.prev;
function maybeEOL(stream, state) {
if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
}
// Interface
@ -123,9 +161,10 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
startState: function(basecolumn) {
return {
tokenize: null,
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
indented: 0,
startOfLine: true
startOfLine: true,
prevToken: null
};
},
@ -136,13 +175,14 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
state.indented = stream.indentation();
state.startOfLine = true;
}
if (stream.eatSpace()) return null;
curPunc = null;
if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
curPunc = isDefKeyword = null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style == "comment" || style == "meta") return style;
if (ctx.align == null) ctx.align = true;
if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state);
if (curPunc == ";" || curPunc == ":" || (curPunc == "," && stream.match(/^\s*(?:\/\/.*)?$/, false)))
while (state.context.type == "statement") popContext(state);
else if (curPunc == "{") pushContext(state, stream.column(), "}");
else if (curPunc == "[") pushContext(state, stream.column(), "]");
else if (curPunc == "(") pushContext(state, stream.column(), ")");
@ -153,27 +193,62 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
}
else if (curPunc == ctx.type) popContext(state);
else if (indentStatements &&
(((ctx.type == "}" || ctx.type == "top") && curPunc != ';') ||
(ctx.type == "statement" && curPunc == "newstatement")))
pushContext(state, stream.column(), "statement");
(((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
(ctx.type == "statement" && curPunc == "newstatement"))) {
pushContext(state, stream.column(), "statement", stream.current());
}
if (style == "variable" &&
((state.prevToken == "def" ||
(parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
style = "def";
if (hooks.token) {
var result = hooks.token(stream, state, style);
if (result !== undefined) style = result;
}
if (style == "def" && parserConfig.styleDefs === false) style = "variable";
state.startOfLine = false;
state.prevToken = isDefKeyword ? "def" : style || curPunc;
maybeEOL(stream, state);
return style;
},
indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
var closing = firstChar == ctx.type;
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
else if (ctx.align && (!dontAlignCalls || ctx.type != ")")) return ctx.column + (closing ? 0 : 1);
else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
else return ctx.indented + (closing ? 0 : indentUnit);
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
if (parserConfig.dontIndentStatements)
while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
ctx = ctx.prev
if (hooks.indent) {
var hook = hooks.indent(state, ctx, textAfter, indentUnit);
if (typeof hook == "number") return hook
}
var switchBlock = ctx.prev && ctx.prev.info == "switch";
if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
return ctx.indented
}
if (ctx.type == "statement")
return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
return ctx.column + (closing ? 0 : 1);
if (ctx.type == ")" && !closing)
return ctx.indented + statementIndentUnit;
return ctx.indented + (closing ? 0 : indentUnit) +
(!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
},
electricChars: "{}",
electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
blockCommentStart: "/*",
blockCommentEnd: "*/",
blockCommentContinue: " * ",
lineComment: "//",
fold: "brace"
};
@ -184,33 +259,99 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
var cKeywords = "auto if break int case long char register continue return default short do sizeof " +
"double static else struct entry switch extern typedef float union for unsigned " +
"goto while enum void const signed volatile";
function contains(words, word) {
if (typeof words === "function") {
return words(word);
} else {
return words.propertyIsEnumerable(word);
}
}
var cKeywords = "auto if break case register continue return default do sizeof " +
"static else struct switch extern typedef union for goto while enum const " +
"volatile inline restrict asm fortran";
// Keywords from https://en.cppreference.com/w/cpp/keyword includes C++20.
var cppKeywords = "alignas alignof and and_eq audit axiom bitand bitor catch " +
"class compl concept constexpr const_cast decltype delete dynamic_cast " +
"explicit export final friend import module mutable namespace new noexcept " +
"not not_eq operator or or_eq override private protected public " +
"reinterpret_cast requires static_assert static_cast template this " +
"thread_local throw try typeid typename using virtual xor xor_eq";
var objCKeywords = "bycopy byref in inout oneway out self super atomic nonatomic retain copy " +
"readwrite readonly strong weak assign typeof nullable nonnull null_resettable _cmd " +
"@interface @implementation @end @protocol @encode @property @synthesize @dynamic @class " +
"@public @package @private @protected @required @optional @try @catch @finally @import " +
"@selector @encode @defs @synchronized @autoreleasepool @compatibility_alias @available";
var objCBuiltins = "FOUNDATION_EXPORT FOUNDATION_EXTERN NS_INLINE NS_FORMAT_FUNCTION " +
" NS_RETURNS_RETAINEDNS_ERROR_ENUM NS_RETURNS_NOT_RETAINED NS_RETURNS_INNER_POINTER " +
"NS_DESIGNATED_INITIALIZER NS_ENUM NS_OPTIONS NS_REQUIRES_NIL_TERMINATION " +
"NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_SWIFT_NAME NS_REFINED_FOR_SWIFT"
// Do not use this. Use the cTypes function below. This is global just to avoid
// excessive calls when cTypes is being called multiple times during a parse.
var basicCTypes = words("int long char short double float unsigned signed " +
"void bool");
// Do not use this. Use the objCTypes function below. This is global just to avoid
// excessive calls when objCTypes is being called multiple times during a parse.
var basicObjCTypes = words("SEL instancetype id Class Protocol BOOL");
// Returns true if identifier is a "C" type.
// C type is defined as those that are reserved by the compiler (basicTypes),
// and those that end in _t (Reserved by POSIX for types)
// http://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html
function cTypes(identifier) {
return contains(basicCTypes, identifier) || /.+_t$/.test(identifier);
}
// Returns true if identifier is a "Objective C" type.
function objCTypes(identifier) {
return cTypes(identifier) || contains(basicObjCTypes, identifier);
}
var cBlockKeywords = "case do else for if switch while struct enum union";
var cDefKeywords = "struct enum union";
function cppHook(stream, state) {
if (!state.startOfLine) return false;
for (;;) {
if (stream.skipTo("\\")) {
stream.next();
if (stream.eol()) {
state.tokenize = cppHook;
break;
}
} else {
stream.skipToEnd();
state.tokenize = null;
break;
if (!state.startOfLine) return false
for (var ch, next = null; ch = stream.peek();) {
if (ch == "\\" && stream.match(/^.$/)) {
next = cppHook
break
} else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) {
break
}
stream.next()
}
return "meta";
state.tokenize = next
return "meta"
}
function pointerHook(_stream, state) {
if (state.prevToken == "type") return "type";
return false;
}
// For C and C++ (and ObjC): identifiers starting with __
// or _ followed by a capital letter are reserved for the compiler.
function cIsReservedIdentifier(token) {
if (!token || token.length < 2) return false;
if (token[0] != '_') return false;
return (token[1] == '_') || (token[1] !== token[1].toLowerCase());
}
function cpp14Literal(stream) {
stream.eatWhile(/[\w\.']/);
return "number";
}
function cpp11StringHook(stream, state) {
stream.backUp(1);
// Raw strings.
if (stream.match(/(R|u8R|uR|UR|LR)/)) {
var match = stream.match(/"([^\s\\()]{0,16})\(/);
if (stream.match(/^(?:R|u8R|uR|UR|LR)/)) {
var match = stream.match(/^"([^\s\\()]{0,16})\(/);
if (!match) {
return false;
}
@ -219,8 +360,8 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return tokenRawString(stream, state);
}
// Unicode strings/chars.
if (stream.match(/(u8|u|U|L)/)) {
if (stream.match(/["']/, /* eat */ false)) {
if (stream.match(/^(?:u8|u|U|L)/)) {
if (stream.match(/^["']/, /* eat */ false)) {
return "string";
}
return false;
@ -230,6 +371,11 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return false;
}
function cppLooksLikeConstructor(word) {
var lastTwo = /(\w+)::~?(\w+)$/.exec(word);
return lastTwo && lastTwo[1] == lastTwo[2];
}
// C#-style strings where "" escapes a quote.
function tokenAtString(stream, state) {
var next;
@ -263,6 +409,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
words.push(prop);
}
add(mode.keywords);
add(mode.types);
add(mode.builtin);
add(mode.atoms);
if (words.length) {
@ -277,42 +424,78 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
name: "clike",
keywords: words(cKeywords),
blockKeywords: words("case do else for if switch while struct"),
atoms: words("null"),
hooks: {"#": cppHook},
types: cTypes,
blockKeywords: words(cBlockKeywords),
defKeywords: words(cDefKeywords),
typeFirstDefinitions: true,
atoms: words("NULL true false"),
isReservedIdentifier: cIsReservedIdentifier,
hooks: {
"#": cppHook,
"*": pointerHook,
},
modeProps: {fold: ["brace", "include"]}
});
def(["text/x-c++src", "text/x-c++hdr"], {
name: "clike",
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try bool explicit new " +
"static_cast typeid catch operator template typename class friend private " +
"this using const_cast inline public throw virtual delete mutable protected " +
"wchar_t alignas alignof constexpr decltype nullptr noexcept thread_local final " +
"static_assert override"),
blockKeywords: words("catch class do else finally for if struct switch try while"),
atoms: words("true false null"),
keywords: words(cKeywords + " " + cppKeywords),
types: cTypes,
blockKeywords: words(cBlockKeywords + " class try catch"),
defKeywords: words(cDefKeywords + " class namespace"),
typeFirstDefinitions: true,
atoms: words("true false NULL nullptr"),
dontIndentStatements: /^template$/,
isIdentifierChar: /[\w\$_~\xa1-\uffff]/,
isReservedIdentifier: cIsReservedIdentifier,
hooks: {
"#": cppHook,
"*": pointerHook,
"u": cpp11StringHook,
"U": cpp11StringHook,
"L": cpp11StringHook,
"R": cpp11StringHook
"R": cpp11StringHook,
"0": cpp14Literal,
"1": cpp14Literal,
"2": cpp14Literal,
"3": cpp14Literal,
"4": cpp14Literal,
"5": cpp14Literal,
"6": cpp14Literal,
"7": cpp14Literal,
"8": cpp14Literal,
"9": cpp14Literal,
token: function(stream, state, style) {
if (style == "variable" && stream.peek() == "(" &&
(state.prevToken == ";" || state.prevToken == null ||
state.prevToken == "}") &&
cppLooksLikeConstructor(stream.current()))
return "def";
}
},
namespaceSeparator: "::",
modeProps: {fold: ["brace", "include"]}
});
def("text/x-java", {
name: "clike",
keywords: words("abstract assert boolean break byte case catch char class const continue default " +
"do double else enum extends final finally float for goto if implements import " +
"instanceof int interface long native new package private protected public " +
"return short static strictfp super switch synchronized this throw throws transient " +
"try void volatile while"),
keywords: words("abstract assert break case catch class const continue default " +
"do else enum extends final finally for goto if implements import " +
"instanceof interface native new package private protected public " +
"return static strictfp super switch synchronized this throw throws transient " +
"try volatile while @interface"),
types: words("var byte short int long float double boolean char void Boolean Byte Character Double Float " +
"Integer Long Number Object Short String StringBuffer StringBuilder Void"),
blockKeywords: words("catch class do else finally for if switch try while"),
defKeywords: words("class interface enum @interface"),
typeFirstDefinitions: true,
atoms: words("true false null"),
number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
hooks: {
"@": function(stream) {
// Don't match the @interface keyword.
if (stream.match('interface', false)) return false;
stream.eatWhile(/[\w\$_]/);
return "meta";
}
@ -322,18 +505,20 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
def("text/x-csharp", {
name: "clike",
keywords: words("abstract as base break case catch checked class const continue" +
keywords: words("abstract as async await base break case catch checked class const continue" +
" default delegate do else enum event explicit extern finally fixed for" +
" foreach goto if implicit in interface internal is lock namespace new" +
" operator out override params private protected public readonly ref return sealed" +
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
" global group into join let orderby partial remove select set value var yield"),
types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" +
" Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" +
" UInt64 bool byte char decimal double short int long object" +
" sbyte float string ushort uint ulong"),
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
builtin: words("Boolean Byte Char DateTime DateTimeOffset Decimal Double" +
" Guid Int16 Int32 Int64 Object SByte Single String TimeSpan UInt16 UInt32" +
" UInt64 bool byte char decimal double short int long object" +
" sbyte float string ushort uint ulong"),
defKeywords: words("class interface namespace struct var"),
typeFirstDefinitions: true,
atoms: words("true false null"),
hooks: {
"@": function(stream, state) {
@ -359,25 +544,45 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
return "string";
}
function tokenNestedComment(depth) {
return function (stream, state) {
var ch
while (ch = stream.next()) {
if (ch == "*" && stream.eat("/")) {
if (depth == 1) {
state.tokenize = null
break
} else {
state.tokenize = tokenNestedComment(depth - 1)
return state.tokenize(stream, state)
}
} else if (ch == "/" && stream.eat("*")) {
state.tokenize = tokenNestedComment(depth + 1)
return state.tokenize(stream, state)
}
}
return "comment"
}
}
def("text/x-scala", {
name: "clike",
keywords: words(
/* scala */
"abstract case catch class def do else extends false final finally for forSome if " +
"abstract case catch class def do else extends final finally for forSome if " +
"implicit import lazy match new null object override package private protected return " +
"sealed super this throw trait try trye type val var while with yield _ : = => <- <: " +
"<% >: # @ " +
"sealed super this throw trait try type val var while with yield _ " +
/* package scala */
"assert assume require print println printf readLine readBoolean readByte readShort " +
"readChar readInt readLong readFloat readDouble " +
"readChar readInt readLong readFloat readDouble"
),
types: words(
"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
"Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " +
"Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable " +
"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector :: #:: " +
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " +
/* package java.lang */
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
@ -386,9 +591,12 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
),
multiLineStrings: true,
blockKeywords: words("catch class do else finally for forSome if match switch try while"),
blockKeywords: words("catch class enum do else finally for forSome if match switch try while"),
defKeywords: words("class enum def object package trait type val var"),
atoms: words("true false null"),
indentStatements: false,
indentSwitch: false,
isOperatorChar: /[+\-*&%=<>!?|\/#:@]/,
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
@ -402,21 +610,116 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"'": function(stream) {
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
return "atom";
},
"=": function(stream, state) {
var cx = state.context
if (cx.type == "}" && cx.align && stream.eat(">")) {
state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)
return "operator"
} else {
return false
}
},
"/": function(stream, state) {
if (!stream.eat("*")) return false
state.tokenize = tokenNestedComment(1)
return state.tokenize(stream, state)
}
},
modeProps: {closeBrackets: {pairs: '()[]{}""', triples: '"'}}
});
function tokenKotlinString(tripleString){
return function (stream, state) {
var escaped = false, next, end = false;
while (!stream.eol()) {
if (!tripleString && !escaped && stream.match('"') ) {end = true; break;}
if (tripleString && stream.match('"""')) {end = true; break;}
next = stream.next();
if(!escaped && next == "$" && stream.match('{'))
stream.skipTo("}");
escaped = !escaped && next == "\\" && !tripleString;
}
if (end || !tripleString)
state.tokenize = null;
return "string";
}
}
def("text/x-kotlin", {
name: "clike",
keywords: words(
/*keywords*/
"package as typealias class interface this super val operator " +
"var fun for is in This throw return annotation " +
"break continue object if else while do try when !in !is as? " +
/*soft keywords*/
"file import where by get set abstract enum open inner override private public internal " +
"protected catch finally out final vararg reified dynamic companion constructor init " +
"sealed field property receiver param sparam lateinit data inline noinline tailrec " +
"external annotation crossinline const operator infix suspend actual expect setparam value"
),
types: words(
/* package java.lang */
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void Annotation Any BooleanArray " +
"ByteArray Char CharArray DeprecationLevel DoubleArray Enum FloatArray Function Int IntArray Lazy " +
"LazyThreadSafetyMode LongArray Nothing ShortArray Unit"
),
intendSwitch: false,
indentStatements: false,
multiLineStrings: true,
number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+(\.\d+)?|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
blockKeywords: words("catch class do else finally for if where try while enum"),
defKeywords: words("class val var object interface fun"),
atoms: words("true false null this"),
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$_]/);
return "meta";
},
'*': function(_stream, state) {
return state.prevToken == '.' ? 'variable' : 'operator';
},
'"': function(stream, state) {
state.tokenize = tokenKotlinString(stream.match('""'));
return state.tokenize(stream, state);
},
"/": function(stream, state) {
if (!stream.eat("*")) return false;
state.tokenize = tokenNestedComment(1);
return state.tokenize(stream, state)
},
indent: function(state, ctx, textAfter, indentUnit) {
var firstChar = textAfter && textAfter.charAt(0);
if ((state.prevToken == "}" || state.prevToken == ")") && textAfter == "")
return state.indented;
if ((state.prevToken == "operator" && textAfter != "}" && state.context.type != "}") ||
state.prevToken == "variable" && firstChar == "." ||
(state.prevToken == "}" || state.prevToken == ")") && firstChar == ".")
return indentUnit * 2 + ctx.indented;
if (ctx.align && ctx.type == "}")
return ctx.indented + (state.context.type == (textAfter || "").charAt(0) ? 0 : indentUnit);
}
},
modeProps: {closeBrackets: {triples: '"'}}
});
def(["x-shader/x-vertex", "x-shader/x-fragment"], {
name: "clike",
keywords: words("float int bool void " +
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
"mat2 mat3 mat4 " +
"sampler1D sampler2D sampler3D samplerCube " +
keywords: words("sampler1D sampler2D sampler3D samplerCube " +
"sampler1DShadow sampler2DShadow " +
"const attribute uniform varying " +
"break continue discard return " +
"for while do if else struct " +
"in out inout"),
types: words("float int bool void " +
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
"mat2 mat3 mat4"),
blockKeywords: words("for while do if else struct"),
builtin: words("radians degrees sin cos tan asin acos atan " +
"pow exp log exp2 sqrt inversesqrt " +
@ -446,7 +749,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
"gl_TextureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
"gl_ProjectionMatrixInverseTranspose " +
"gl_ModelViewProjectionMatrixInverseTranspose " +
"gl_TextureMatrixInverseTranspose " +
@ -460,34 +763,173 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
"gl_MaxDrawBuffers"),
indentSwitch: false,
hooks: {"#": cppHook},
modeProps: {fold: ["brace", "include"]}
});
def("text/x-nesc", {
name: "clike",
keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
keywords: words(cKeywords + " as atomic async call command component components configuration event generic " +
"implementation includes interface module new norace nx_struct nx_union post provides " +
"signal task uses abstract extends"),
blockKeywords: words("case do else for if switch while struct"),
atoms: words("null"),
types: cTypes,
blockKeywords: words(cBlockKeywords),
atoms: words("null true false"),
hooks: {"#": cppHook},
modeProps: {fold: ["brace", "include"]}
});
def("text/x-objectivec", {
name: "clike",
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " +
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
atoms: words("YES NO NULL NILL ON OFF"),
keywords: words(cKeywords + " " + objCKeywords),
types: objCTypes,
builtin: words(objCBuiltins),
blockKeywords: words(cBlockKeywords + " @synthesize @try @catch @finally @autoreleasepool @synchronized"),
defKeywords: words(cDefKeywords + " @interface @implementation @protocol @class"),
dontIndentStatements: /^@.*$/,
typeFirstDefinitions: true,
atoms: words("YES NO NULL Nil nil true false nullptr"),
isReservedIdentifier: cIsReservedIdentifier,
hooks: {
"#": cppHook,
"*": pointerHook,
},
modeProps: {fold: ["brace", "include"]}
});
def("text/x-objectivec++", {
name: "clike",
keywords: words(cKeywords + " " + objCKeywords + " " + cppKeywords),
types: objCTypes,
builtin: words(objCBuiltins),
blockKeywords: words(cBlockKeywords + " @synthesize @try @catch @finally @autoreleasepool @synchronized class try catch"),
defKeywords: words(cDefKeywords + " @interface @implementation @protocol @class class namespace"),
dontIndentStatements: /^@.*$|^template$/,
typeFirstDefinitions: true,
atoms: words("YES NO NULL Nil nil true false nullptr"),
isReservedIdentifier: cIsReservedIdentifier,
hooks: {
"#": cppHook,
"*": pointerHook,
"u": cpp11StringHook,
"U": cpp11StringHook,
"L": cpp11StringHook,
"R": cpp11StringHook,
"0": cpp14Literal,
"1": cpp14Literal,
"2": cpp14Literal,
"3": cpp14Literal,
"4": cpp14Literal,
"5": cpp14Literal,
"6": cpp14Literal,
"7": cpp14Literal,
"8": cpp14Literal,
"9": cpp14Literal,
token: function(stream, state, style) {
if (style == "variable" && stream.peek() == "(" &&
(state.prevToken == ";" || state.prevToken == null ||
state.prevToken == "}") &&
cppLooksLikeConstructor(stream.current()))
return "def";
}
},
namespaceSeparator: "::",
modeProps: {fold: ["brace", "include"]}
});
def("text/x-squirrel", {
name: "clike",
keywords: words("base break clone continue const default delete enum extends function in class" +
" foreach local resume return this throw typeof yield constructor instanceof static"),
types: cTypes,
blockKeywords: words("case catch class else for foreach if switch try while"),
defKeywords: words("function local class"),
typeFirstDefinitions: true,
atoms: words("true false null"),
hooks: {"#": cppHook},
modeProps: {fold: ["brace", "include"]}
});
// Ceylon Strings need to deal with interpolation
var stringTokenizer = null;
function tokenCeylonString(type) {
return function(stream, state) {
var escaped = false, next, end = false;
while (!stream.eol()) {
if (!escaped && stream.match('"') &&
(type == "single" || stream.match('""'))) {
end = true;
break;
}
if (!escaped && stream.match('``')) {
stringTokenizer = tokenCeylonString(type);
end = true;
break;
}
next = stream.next();
escaped = type == "single" && !escaped && next == "\\";
}
if (end)
state.tokenize = null;
return "string";
}
}
def("text/x-ceylon", {
name: "clike",
keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
" exists extends finally for function given if import in interface is let module new" +
" nonempty object of out outer package return satisfies super switch then this throw" +
" try value void while"),
types: function(word) {
// In Ceylon all identifiers that start with an uppercase are types
var first = word.charAt(0);
return (first === first.toUpperCase() && first !== first.toLowerCase());
},
blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
defKeywords: words("class dynamic function interface module object package value"),
builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
" native optional sealed see serializable shared suppressWarnings tagged throws variable"),
isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
numberStart: /[\d#$]/,
number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,
multiLineStrings: true,
typeFirstDefinitions: true,
atoms: words("true false null larger smaller equal empty finished"),
indentSwitch: false,
styleDefs: false,
hooks: {
"@": function(stream) {
stream.eatWhile(/[\w\$]/);
return "keyword";
stream.eatWhile(/[\w\$_]/);
return "meta";
},
"#": cppHook
'"': function(stream, state) {
state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
return state.tokenize(stream, state);
},
'`': function(stream, state) {
if (!stringTokenizer || !stream.match('`')) return false;
state.tokenize = stringTokenizer;
stringTokenizer = null;
return state.tokenize(stream, state);
},
"'": function(stream) {
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
return "atom";
},
token: function(_stream, state, style) {
if ((style == "variable" || style == "type") &&
state.prevToken == ".") {
return "variable-2";
}
}
},
modeProps: {fold: "brace"}
modeProps: {
fold: ["brace", "import"],
closeBrackets: {triples: '"'}
}
});
});

View File

@ -12,7 +12,7 @@
<script src="clike.js"></script>
<style>.CodeMirror {border: 2px inset #dee;}</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul>
<li><a href="../../index.html">Home</a>
@ -147,16 +147,36 @@ This is a longer comment
That spans two lines
*/
#import <Test/Test.h>
#import "MyClass.h"
#import <AFramework/AFramework.h>
@import BFrameworkModule;
NS_ENUM(SomeValues) {
aValue = 1;
};
// A Class Extension with some properties
@interface MyClass ()<AProtocol>
@property(atomic, readwrite, assign) NSInteger anInt;
@property(nonatomic, strong, nullable) NSString *aString;
@end
@implementation YourAppDelegate
// This is a one-line comment
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
char myString[] = "This is a C character array";
int test = 5;
return YES;
- (instancetype)initWithString:(NSString *)aStringVar {
if ((self = [super init])) {
aString = aStringVar;
}
return self;
}
- (BOOL)doSomething:(float)progress {
NSString *myString = @"This is a ObjC string %f ";
myString = [[NSString stringWithFormat:myString, progress] stringByAppendingString:self.aString];
return myString.length > 100 ? NO : YES;
}
@end
</textarea></div>
<h2>Java example</h2>
@ -206,6 +226,103 @@ object FilterTest extends App {
}
</textarea></div>
<h2>Kotlin mode</h2>
<div><textarea id="kotlin-code">
package org.wasabi.http
import java.util.concurrent.Executors
import java.net.InetSocketAddress
import org.wasabi.app.AppConfiguration
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.nio.NioServerSocketChannel
import org.wasabi.app.AppServer
public class HttpServer(private val appServer: AppServer) {
val bootstrap: ServerBootstrap
val primaryGroup: NioEventLoopGroup
val workerGroup: NioEventLoopGroup
init {
// Define worker groups
primaryGroup = NioEventLoopGroup()
workerGroup = NioEventLoopGroup()
// Initialize bootstrap of server
bootstrap = ServerBootstrap()
bootstrap.group(primaryGroup, workerGroup)
bootstrap.channel(javaClass<NioServerSocketChannel>())
bootstrap.childHandler(NettyPipelineInitializer(appServer))
}
public fun start(wait: Boolean = true) {
val channel = bootstrap.bind(appServer.configuration.port)?.sync()?.channel()
if (wait) {
channel?.closeFuture()?.sync()
}
}
public fun stop() {
// Shutdown all event loops
primaryGroup.shutdownGracefully()
workerGroup.shutdownGracefully()
// Wait till all threads are terminated
primaryGroup.terminationFuture().sync()
workerGroup.terminationFuture().sync()
}
}
</textarea></div>
<h2>Ceylon mode</h2>
<div><textarea id="ceylon-code">
"Produces the [[stream|Iterable]] that results from repeated
application of the given [[function|next]] to the given
[[first]] element of the stream, until the function first
returns [[finished]]. If the given function never returns
`finished`, the resulting stream is infinite.
For example:
loop(0)(2.plus).takeWhile(10.largerThan)
produces the stream `{ 0, 2, 4, 6, 8 }`."
tagged("Streams")
shared {Element+} loop&lt;Element&gt;(
"The first element of the resulting stream."
Element first)(
"The function that produces the next element of the
stream, given the current element. The function may
return [[finished]] to indicate the end of the
stream."
Element|Finished next(Element element))
=&gt; let (start = first)
object satisfies {Element+} {
first =&gt; start;
empty =&gt; false;
function nextElement(Element element)
=&gt; next(element);
iterator()
=&gt; object satisfies Iterator&lt;Element&gt; {
variable Element|Finished current = start;
shared actual Element|Finished next() {
if (!is Finished result = current) {
current = nextElement(result);
return result;
}
else {
return finished;
}
}
};
};
</textarea></div>
<script>
var cEditor = CodeMirror.fromTextArea(document.getElementById("c-code"), {
lineNumbers: true,
@ -232,6 +349,16 @@ object FilterTest extends App {
matchBrackets: true,
mode: "text/x-scala"
});
var kotlinEditor = CodeMirror.fromTextArea(document.getElementById("kotlin-code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-kotlin"
});
var ceylonEditor = CodeMirror.fromTextArea(document.getElementById("ceylon-code"), {
lineNumbers: true,
matchBrackets: true,
mode: "text/x-ceylon"
});
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
</script>
@ -247,5 +374,7 @@ object FilterTest extends App {
(Java), <code>text/x-csharp</code> (C#),
<code>text/x-objectivec</code> (Objective-C),
<code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
and <code>x-shader/x-fragment</code> (shader programs).</p>
<code>x-shader/x-fragment</code> (shader programs),
<code>text/x-squirrel</code> (Squirrel) and
<code>text/x-ceylon</code> (Ceylon)</p>
</article>

View File

@ -10,7 +10,7 @@
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="clike.js"></script>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul>
<li><a href="../../index.html">Home</a>

View File

@ -0,0 +1,165 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function() {
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-c");
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
MT("indent",
"[type void] [def foo]([type void*] [variable a], [type int] [variable b]) {",
" [type int] [variable c] [operator =] [variable b] [operator +]",
" [number 1];",
" [keyword return] [operator *][variable a];",
"}");
MT("indent_switch",
"[keyword switch] ([variable x]) {",
" [keyword case] [number 10]:",
" [keyword return] [number 20];",
" [keyword default]:",
" [variable printf]([string \"foo %c\"], [variable x]);",
"}");
MT("def",
"[type void] [def foo]() {}",
"[keyword struct] [def bar]{}",
"[keyword enum] [def zot]{}",
"[keyword union] [def ugh]{}",
"[type int] [type *][def baz]() {}");
MT("def_new_line",
"::[variable std]::[variable SomeTerribleType][operator <][variable T][operator >]",
"[def SomeLongMethodNameThatDoesntFitIntoOneLine]([keyword const] [variable MyType][operator &] [variable param]) {}")
MT("double_block",
"[keyword for] (;;)",
" [keyword for] (;;)",
" [variable x][operator ++];",
"[keyword return];");
MT("preprocessor",
"[meta #define FOO 3]",
"[type int] [variable foo];",
"[meta #define BAR\\]",
"[meta 4]",
"[type unsigned] [type int] [variable bar] [operator =] [number 8];",
"[meta #include <baz> ][comment // comment]")
MT("c_underscores",
"[builtin __FOO];",
"[builtin _Complex];",
"[builtin __aName];",
"[variable _aName];");
MT("c_types",
"[type int];",
"[type long];",
"[type char];",
"[type short];",
"[type double];",
"[type float];",
"[type unsigned];",
"[type signed];",
"[type void];",
"[type bool];",
"[type foo_t];",
"[variable foo_T];",
"[variable _t];");
var mode_cpp = CodeMirror.getMode({indentUnit: 2}, "text/x-c++src");
function MTCPP(name) { test.mode(name, mode_cpp, Array.prototype.slice.call(arguments, 1)); }
MTCPP("cpp14_literal",
"[number 10'000];",
"[number 0b10'000];",
"[number 0x10'000];",
"[string '100000'];");
MTCPP("ctor_dtor",
"[def Foo::Foo]() {}",
"[def Foo::~Foo]() {}");
MTCPP("cpp_underscores",
"[builtin __FOO];",
"[builtin _Complex];",
"[builtin __aName];",
"[variable _aName];");
var mode_objc = CodeMirror.getMode({indentUnit: 2}, "text/x-objectivec");
function MTOBJC(name) { test.mode(name, mode_objc, Array.prototype.slice.call(arguments, 1)); }
MTOBJC("objc_underscores",
"[builtin __FOO];",
"[builtin _Complex];",
"[builtin __aName];",
"[variable _aName];");
MTOBJC("objc_interface",
"[keyword @interface] [def foo] {",
" [type int] [variable bar];",
"}",
"[keyword @property] ([keyword atomic], [keyword nullable]) [variable NSString][operator *] [variable a];",
"[keyword @property] ([keyword nonatomic], [keyword assign]) [type int] [variable b];",
"[operator -]([type instancetype])[variable initWithFoo]:([type int])[variable a] " +
"[builtin NS_DESIGNATED_INITIALIZER];",
"[keyword @end]");
MTOBJC("objc_implementation",
"[keyword @implementation] [def foo] {",
" [type int] [variable bar];",
"}",
"[keyword @property] ([keyword readwrite]) [type SEL] [variable a];",
"[operator -]([type instancetype])[variable initWithFoo]:([type int])[variable a] {",
" [keyword if](([keyword self] [operator =] [[[keyword super] [variable init] ]])) {}",
" [keyword return] [keyword self];",
"}",
"[keyword @end]");
MTOBJC("objc_types",
"[type int];",
"[type foo_t];",
"[variable foo_T];",
"[type id];",
"[type SEL];",
"[type instancetype];",
"[type Class];",
"[type Protocol];",
"[type BOOL];"
);
var mode_scala = CodeMirror.getMode({indentUnit: 2}, "text/x-scala");
function MTSCALA(name) { test.mode("scala_" + name, mode_scala, Array.prototype.slice.call(arguments, 1)); }
MTSCALA("nested_comments",
"[comment /*]",
"[comment But wait /* this is a nested comment */ for real]",
"[comment /**** let * me * show * you ****/]",
"[comment ///// let / me / show / you /////]",
"[comment */]");
var mode_java = CodeMirror.getMode({indentUnit: 2}, "text/x-java");
function MTJAVA(name) { test.mode("java_" + name, mode_java, Array.prototype.slice.call(arguments, 1)); }
MTJAVA("types",
"[type byte];",
"[type short];",
"[type int];",
"[type long];",
"[type float];",
"[type double];",
"[type boolean];",
"[type char];",
"[type void];",
"[type Boolean];",
"[type Byte];",
"[type Character];",
"[type Double];",
"[type Float];",
"[type Integer];",
"[type Long];",
"[type Number];",
"[type Object];",
"[type Short];",
"[type String];",
"[type StringBuffer];",
"[type StringBuilder];",
"[type Void];");
})();

File diff suppressed because one or more lines are too long

View File

@ -6,10 +6,12 @@
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<script src="../../addon/edit/closebrackets.js"></script>
<script src="../../addon/edit/matchbrackets.js"></script>
<script src="clojure.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav>
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul>
<li><a href="../../index.html">Home</a>
@ -25,62 +27,67 @@
<article>
<h2>Clojure mode</h2>
<form><textarea id="code" name="code">
; Conway's Game of Life, based on the work of:
;; Laurent Petit https://gist.github.com/1200343
;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life
(ns game-of-life
"Conway's Game of Life, based on the work of
Christophe Grand (http://clj-me.cgrand.net/2011/08/19/conways-game-of-life)
and Laurent Petit (https://gist.github.com/1200343).")
(ns ^{:doc "Conway's Game of Life."}
game-of-life)
;;; Core game of life's algorithm functions
;; Core game of life's algorithm functions
(defn neighbours
"Given a cell's coordinates, returns the coordinates of its neighbours."
(defn neighbors
"Given a cell's coordinates `[x y]`, returns the coordinates of its
neighbors."
[[x y]]
(for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
(for [dx [-1 0 1]
dy (if (zero? dx)
[-1 1]
[-1 0 1])]
[(+ dx x) (+ dy y)]))
(defn step
"Given a set of living cells, computes the new set of living cells."
"Given a set of living `cells`, computes the new set of living cells."
[cells]
(set (for [[cell n] (frequencies (mapcat neighbours cells))
:when (or (= n 3) (and (= n 2) (cells cell)))]
(set (for [[cell n] (frequencies (mapcat neighbors cells))
:when (or (= n 3)
(and (= n 2)
(cells cell)))]
cell)))
;; Utility methods for displaying game on a text terminal
;;; Utility methods for displaying game on a text terminal
(defn print-board
"Prints a board on *out*, representing a step in the game."
[board w h]
(doseq [x (range (inc w)) y (range (inc h))]
(if (= y 0) (print "\n"))
(print (if (board [x y]) "[X]" " . "))))
(defn print-grid
"Prints a `grid` of `w` columns and `h` rows, on *out*, representing a
step in the game."
[grid w h]
(doseq [x (range (inc w))
y (range (inc h))]
(when (= y 0) (println))
(print (if (grid [x y])
"[X]"
" . "))))
(defn display-grids
"Prints a squence of boards on *out*, representing several steps."
(defn print-grids
"Prints a sequence of `grids` of `w` columns and `h` rows on *out*,
representing several steps."
[grids w h]
(doseq [board grids]
(print-board board w h)
(print "\n")))
(doseq [grid grids]
(print-grid grid w h)
(println)))
;; Launches an example board
;;; Launches an example grid
(def
^{:doc "board represents the initial set of living cells"}
board #{[2 1] [2 2] [2 3]})
(def grid
"`grid` represents the initial set of living cells"
#{[2 1] [2 2] [2 3]})
(display-grids (take 3 (iterate step board)) 5 5)
;; Let's play with characters
(println \1 \a \# \\
\" \( \newline
\} \" \space
\tab \return \backspace
\u1000 \uAaAa \u9F9F)
</textarea></form>
(print-grids (take 3 (iterate step grid)) 5 5)</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
autoCloseBrackets: true,
lineNumbers: true,
matchBrackets: true,
mode: 'text/x-clojure'
});
</script>
<p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>

View File

@ -0,0 +1,384 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(function () {
var mode = CodeMirror.getMode({indentUnit: 2}, "clojure");
function MT(name) {
test.mode(name, mode, Array.prototype.slice.call(arguments, 1));
}
MT("atoms",
"[atom false]",
"[atom nil]",
"[atom true]"
);
MT("keywords",
"[atom :foo]",
"[atom ::bar]",
"[atom :foo/bar]",
"[atom :foo.bar/baz]"
);
MT("numbers",
"[number 42] [number +42] [number -421]",
"[number 42N] [number +42N] [number -42N]",
"[number 0.42] [number +0.42] [number -0.42]",
"[number 42M] [number +42M] [number -42M]",
"[number 42.42M] [number +42.42M] [number -42.42M]",
"[number 1/42] [number +1/42] [number -1/42]",
"[number 0x42af] [number +0x42af] [number -0x42af]",
"[number 0x42AF] [number +0x42AF] [number -0x42AF]",
"[number 1e2] [number 1e+2] [number 1e-2]",
"[number +1e2] [number +1e+2] [number +1e-2]",
"[number -1e2] [number -1e+2] [number -1e-2]",
"[number -1.0e2] [number -0.1e+2] [number -1.01e-2]",
"[number 1E2] [number 1E+2] [number 1E-2]",
"[number +1E2] [number +1E+2] [number +1E-2]",
"[number -1E2] [number -1E+2] [number -1E-2]",
"[number -1.0E2] [number -0.1E+2] [number -1.01E-2]",
"[number 2r101010] [number +2r101010] [number -2r101010]",
"[number 2r101010] [number +2r101010] [number -2r101010]",
"[number 8r52] [number +8r52] [number -8r52]",
"[number 36rhello] [number +36rhello] [number -36rhello]",
"[number 36rz] [number +36rz] [number -36rz]",
"[number 36rZ] [number +36rZ] [number -36rZ]",
// invalid numbers
"[error 42foo]",
"[error 42Nfoo]",
"[error 42Mfoo]",
"[error 42.42Mfoo]",
"[error 42.42M!]",
"[error 42!]",
"[error 0x42afm]"
);
MT("characters",
"[string-2 \\1]",
"[string-2 \\a]",
"[string-2 \\a\\b\\c]",
"[string-2 \\#]",
"[string-2 \\\\]",
"[string-2 \\\"]",
"[string-2 \\(]",
"[string-2 \\A]",
"[string-2 \\backspace]",
"[string-2 \\formfeed]",
"[string-2 \\newline]",
"[string-2 \\space]",
"[string-2 \\return]",
"[string-2 \\tab]",
"[string-2 \\u1000]",
"[string-2 \\uAaAa]",
"[string-2 \\u9F9F]",
"[string-2 \\o123]",
"[string-2 \\符]",
"[string-2 \\シ]",
"[string-2 \\ۇ]",
// FIXME
// "[string-2 \\🙂]",
// invalid character literals
"[error \\abc]",
"[error \\a123]",
"[error \\a!]",
"[error \\newlines]",
"[error \\NEWLINE]",
"[error \\u9F9FF]",
"[error \\o1234]"
);
MT("strings",
"[string \"I'm a teapot.\"]",
"[string \"I'm a \\\"teapot\\\".\"]",
"[string \"I'm]", // this is
"[string a]", // a multi-line
"[string teapot.\"]" // string
// TODO unterminated (multi-line) strings?
);
MT("comments",
"[comment ; this is an in-line comment.]",
"[comment ;; this is a line comment.]",
"[keyword comment]",
"[bracket (][comment comment (foo 1 2 3)][bracket )]"
);
MT("reader macro characters",
"[meta #][variable _]",
"[meta #][variable -Inf]",
"[meta ##][variable Inf]",
"[meta ##][variable NaN]",
"[meta @][variable x]",
"[meta ^][bracket {][atom :tag] [variable String][bracket }]",
"[meta `][bracket (][builtin f] [variable x][bracket )]",
"[meta ~][variable foo#]",
"[meta '][number 1]",
"[meta '][atom :foo]",
"[meta '][string \"foo\"]",
"[meta '][variable x]",
"[meta '][bracket (][builtin a] [variable b] [variable c][bracket )]",
"[meta '][bracket [[][variable a] [variable b] [variable c][bracket ]]]",
"[meta '][bracket {][variable a] [number 1] [atom :foo] [number 2] [variable c] [number 3][bracket }]",
"[meta '#][bracket {][variable a] [number 1] [atom :foo][bracket }]"
);
MT("symbols",
"[variable foo!]",
"[variable foo#]",
"[variable foo$]",
"[variable foo&]",
"[variable foo']",
"[variable foo*]",
"[variable foo+]",
"[variable foo-]",
"[variable foo.]",
"[variable foo/bar]",
"[variable foo:bar]",
"[variable foo<]",
"[variable foo=]",
"[variable foo>]",
"[variable foo?]",
"[variable foo_]",
"[variable foo|]",
"[variable foobarBaz]",
"[variable foo¡]",
"[variable 符号]",
"[variable シンボル]",
"[variable ئۇيغۇر]",
"[variable 🙂❤🇺🇸]",
// invalid symbols
"[error 3foo]",
"[error 3+]",
"[error 3|]",
"[error 3_]"
);
MT("numbers and other forms",
"[number 42][bracket (][builtin foo][bracket )]",
"[number 42][bracket [[][variable foo][bracket ]]]",
"[number 42][meta #][bracket {][variable foo][bracket }]",
"[number 42][bracket {][atom :foo] [variable bar][bracket }]",
"[number 42][meta `][variable foo]",
"[number 42][meta ~][variable foo]",
"[number 42][meta #][variable foo]"
);
var specialForms = [".", "catch", "def", "do", "if", "monitor-enter",
"monitor-exit", "new", "quote", "recur", "set!", "throw", "try", "var"];
MT("should highlight special forms as keywords",
typeTokenPairs("keyword", specialForms)
);
var coreSymbols1 = [
"*", "*'", "*1", "*2", "*3", "*agent*", "*allow-unresolved-vars*", "*assert*",
"*clojure-version*", "*command-line-args*", "*compile-files*", "*compile-path*", "*compiler-options*",
"*data-readers*", "*default-data-reader-fn*", "*e", "*err*", "*file*", "*flush-on-newline*", "*fn-loader*",
"*in*", "*math-context*", "*ns*", "*out*", "*print-dup*", "*print-length*", "*print-level*", "*print-meta*",
"*print-namespace-maps*", "*print-readably*", "*read-eval*", "*reader-resolver*", "*source-path*",
"*suppress-read*", "*unchecked-math*", "*use-context-classloader*", "*verbose-defrecords*",
"*warn-on-reflection*", "+", "+'", "-", "-'", "->", "->>", "->ArrayChunk", "->Eduction", "->Vec", "->VecNode",
"->VecSeq", "-cache-protocol-fn", "-reset-methods", "..", "/", "<", "<=", "=", "==", ">", ">=",
"EMPTY-NODE", "Inst", "StackTraceElement->vec", "Throwable->map", "accessor", "aclone", "add-classpath",
"add-watch", "agent", "agent-error", "agent-errors", "aget", "alength", "alias", "all-ns", "alter",
"alter-meta!", "alter-var-root", "amap", "ancestors", "and", "any?", "apply", "areduce", "array-map",
"as->", "aset", "aset-boolean", "aset-byte", "aset-char", "aset-double", "aset-float", "aset-int",
"aset-long", "aset-short", "assert", "assoc", "assoc!", "assoc-in", "associative?", "atom", "await",
"await-for", "await1", "bases", "bean", "bigdec", "bigint", "biginteger", "binding", "bit-and", "bit-and-not",
"bit-clear", "bit-flip", "bit-not", "bit-or", "bit-set", "bit-shift-left", "bit-shift-right", "bit-test",
"bit-xor", "boolean", "boolean-array", "boolean?", "booleans", "bound-fn", "bound-fn*", "bound?",
"bounded-count", "butlast", "byte", "byte-array", "bytes", "bytes?", "case", "cast", "cat", "char",
"char-array", "char-escape-string", "char-name-string", "char?", "chars", "chunk", "chunk-append",
"chunk-buffer", "chunk-cons", "chunk-first", "chunk-next", "chunk-rest", "chunked-seq?", "class", "class?",
"clear-agent-errors", "clojure-version", "coll?", "comment", "commute", "comp", "comparator", "compare",
"compare-and-set!", "compile", "complement", "completing", "concat", "cond", "cond->", "cond->>", "condp",
"conj", "conj!", "cons", "constantly", "construct-proxy", "contains?", "count", "counted?", "create-ns",
"create-struct", "cycle", "dec", "dec'", "decimal?", "declare", "dedupe", "default-data-readers", "definline",
"definterface", "defmacro", "defmethod", "defmulti", "defn", "defn-", "defonce", "defprotocol", "defrecord",
"defstruct", "deftype", "delay", "delay?", "deliver", "denominator", "deref", "derive", "descendants",
"destructure", "disj", "disj!", "dissoc", "dissoc!", "distinct", "distinct?", "doall", "dorun", "doseq",
"dosync", "dotimes", "doto", "double", "double-array", "double?", "doubles", "drop", "drop-last", "drop-while",
"eduction", "empty", "empty?", "ensure", "ensure-reduced", "enumeration-seq", "error-handler", "error-mode",
"eval", "even?", "every-pred", "every?", "ex-data", "ex-info", "extend", "extend-protocol", "extend-type",
"extenders", "extends?", "false?", "ffirst", "file-seq", "filter", "filterv", "find", "find-keyword", "find-ns",
"find-protocol-impl", "find-protocol-method", "find-var", "first", "flatten", "float", "float-array", "float?",
"floats", "flush", "fn", "fn?", "fnext", "fnil", "for", "force", "format", "frequencies", "future", "future-call",
"future-cancel", "future-cancelled?", "future-done?", "future?", "gen-class", "gen-interface", "gensym", "get",
"get-in", "get-method", "get-proxy-class", "get-thread-bindings", "get-validator", "group-by", "halt-when", "hash",
"hash-combine", "hash-map", "hash-ordered-coll", "hash-set", "hash-unordered-coll", "ident?", "identical?",
"identity", "if-let", "if-not", "if-some", "ifn?", "import", "in-ns", "inc", "inc'", "indexed?", "init-proxy",
"inst-ms", "inst-ms*", "inst?", "instance?", "int", "int-array", "int?", "integer?", "interleave", "intern",
"interpose", "into", "into-array", "ints", "io!", "isa?", "iterate", "iterator-seq", "juxt", "keep", "keep-indexed",
"key", "keys", "keyword", "keyword?", "last", "lazy-cat", "lazy-seq", "let", "letfn", "line-seq", "list", "list*",
"list?", "load", "load-file", "load-reader", "load-string", "loaded-libs", "locking", "long", "long-array", "longs",
"loop", "macroexpand", "macroexpand-1", "make-array", "make-hierarchy", "map", "map-entry?", "map-indexed", "map?",
"mapcat", "mapv", "max", "max-key", "memfn", "memoize", "merge", "merge-with", "meta", "method-sig", "methods"];
var coreSymbols2 = [
"min", "min-key", "mix-collection-hash", "mod", "munge", "name", "namespace", "namespace-munge", "nat-int?",
"neg-int?", "neg?", "newline", "next", "nfirst", "nil?", "nnext", "not", "not-any?", "not-empty", "not-every?",
"not=", "ns", "ns-aliases", "ns-imports", "ns-interns", "ns-map", "ns-name", "ns-publics", "ns-refers", "ns-resolve",
"ns-unalias", "ns-unmap", "nth", "nthnext", "nthrest", "num", "number?", "numerator", "object-array", "odd?", "or",
"parents", "partial", "partition", "partition-all", "partition-by", "pcalls", "peek", "persistent!", "pmap", "pop",
"pop!", "pop-thread-bindings", "pos-int?", "pos?", "pr", "pr-str", "prefer-method", "prefers",
"primitives-classnames", "print", "print-ctor", "print-dup", "print-method", "print-simple", "print-str", "printf",
"println", "println-str", "prn", "prn-str", "promise", "proxy", "proxy-call-with-super", "proxy-mappings",
"proxy-name", "proxy-super", "push-thread-bindings", "pvalues", "qualified-ident?", "qualified-keyword?",
"qualified-symbol?", "quot", "rand", "rand-int", "rand-nth", "random-sample", "range", "ratio?", "rational?",
"rationalize", "re-find", "re-groups", "re-matcher", "re-matches", "re-pattern", "re-seq", "read", "read-line",
"read-string", "reader-conditional", "reader-conditional?", "realized?", "record?", "reduce", "reduce-kv", "reduced",
"reduced?", "reductions", "ref", "ref-history-count", "ref-max-history", "ref-min-history", "ref-set", "refer",
"refer-clojure", "reify", "release-pending-sends", "rem", "remove", "remove-all-methods", "remove-method", "remove-ns",
"remove-watch", "repeat", "repeatedly", "replace", "replicate", "require", "reset!", "reset-meta!", "reset-vals!",
"resolve", "rest", "restart-agent", "resultset-seq", "reverse", "reversible?", "rseq", "rsubseq", "run!", "satisfies?",
"second", "select-keys", "send", "send-off", "send-via", "seq", "seq?", "seqable?", "seque", "sequence", "sequential?",
"set", "set-agent-send-executor!", "set-agent-send-off-executor!", "set-error-handler!", "set-error-mode!",
"set-validator!", "set?", "short", "short-array", "shorts", "shuffle", "shutdown-agents", "simple-ident?",
"simple-keyword?", "simple-symbol?", "slurp", "some", "some->", "some->>", "some-fn", "some?", "sort", "sort-by",
"sorted-map", "sorted-map-by", "sorted-set", "sorted-set-by", "sorted?", "special-symbol?", "spit", "split-at",
"split-with", "str", "string?", "struct", "struct-map", "subs", "subseq", "subvec", "supers", "swap!", "swap-vals!",
"symbol", "symbol?", "sync", "tagged-literal", "tagged-literal?", "take", "take-last", "take-nth", "take-while", "test",
"the-ns", "thread-bound?", "time", "to-array", "to-array-2d", "trampoline", "transduce", "transient", "tree-seq",
"true?", "type", "unchecked-add", "unchecked-add-int", "unchecked-byte", "unchecked-char", "unchecked-dec",
"unchecked-dec-int", "unchecked-divide-int", "unchecked-double", "unchecked-float", "unchecked-inc", "unchecked-inc-int",
"unchecked-int", "unchecked-long", "unchecked-multiply", "unchecked-multiply-int", "unchecked-negate",
"unchecked-negate-int", "unchecked-remainder-int", "unchecked-short", "unchecked-subtract", "unchecked-subtract-int",
"underive", "unquote", "unquote-splicing", "unreduced", "unsigned-bit-shift-right", "update", "update-in",
"update-proxy", "uri?", "use", "uuid?", "val", "vals", "var-get", "var-set", "var?", "vary-meta", "vec", "vector",
"vector-of", "vector?", "volatile!", "volatile?", "vreset!", "vswap!", "when", "when-first", "when-let", "when-not",
"when-some", "while", "with-bindings", "with-bindings*", "with-in-str", "with-loading-context", "with-local-vars",
"with-meta", "with-open", "with-out-str", "with-precision", "with-redefs", "with-redefs-fn", "xml-seq", "zero?",
"zipmap"
];
MT("should highlight core symbols as keywords (part 1/2)",
typeTokenPairs("keyword", coreSymbols1)
);
MT("should highlight core symbols as keywords (part 2/2)",
typeTokenPairs("keyword", coreSymbols2)
);
MT("should properly indent forms in list literals",
"[bracket (][builtin foo] [atom :a] [number 1] [atom true] [atom nil][bracket )]",
"",
"[bracket (][builtin foo] [atom :a]",
" [number 1]",
" [atom true]",
" [atom nil][bracket )]",
"",
"[bracket (][builtin foo] [atom :a] [number 1]",
" [atom true]",
" [atom nil][bracket )]",
"",
"[bracket (]",
" [builtin foo]",
" [atom :a]",
" [number 1]",
" [atom true]",
" [atom nil][bracket )]",
"",
"[bracket (][builtin foo] [bracket [[][atom :a][bracket ]]]",
" [number 1]",
" [atom true]",
" [atom nil][bracket )]"
);
MT("should properly indent forms in vector literals",
"[bracket [[][atom :a] [number 1] [atom true] [atom nil][bracket ]]]",
"",
"[bracket [[][atom :a]",
" [number 1]",
" [atom true]",
" [atom nil][bracket ]]]",
"",
"[bracket [[][atom :a] [number 1]",
" [atom true]",
" [atom nil][bracket ]]]",
"",
"[bracket [[]",
" [variable foo]",
" [atom :a]",
" [number 1]",
" [atom true]",
" [atom nil][bracket ]]]"
);
MT("should properly indent forms in map literals",
"[bracket {][atom :a] [atom :a] [atom :b] [number 1] [atom :c] [atom true] [atom :d] [atom nil] [bracket }]",
"",
"[bracket {][atom :a] [atom :a]",
" [atom :b] [number 1]",
" [atom :c] [atom true]",
" [atom :d] [atom nil][bracket }]",
"",
"[bracket {][atom :a]",
" [atom :a]",
" [atom :b]",
" [number 1]",
" [atom :c]",
" [atom true]",
" [atom :d]",
" [atom nil][bracket }]",
"",
"[bracket {]",
" [atom :a] [atom :a]",
" [atom :b] [number 1]",
" [atom :c] [atom true]",
" [atom :d] [atom nil][bracket }]"
);
MT("should properly indent forms in set literals",
"[meta #][bracket {][atom :a] [number 1] [atom true] [atom nil] [bracket }]",
"",
"[meta #][bracket {][atom :a]",
" [number 1]",
" [atom true]",
" [atom nil][bracket }]",
"",
"[meta #][bracket {]",
" [atom :a]",
" [number 1]",
" [atom true]",
" [atom nil][bracket }]"
);
var haveBodyParameter = [
"->", "->>", "as->", "binding", "bound-fn", "case", "catch", "cond",
"cond->", "cond->>", "condp", "def", "definterface", "defmethod", "defn",
"defmacro", "defprotocol", "defrecord", "defstruct", "deftype", "do",
"doseq", "dotimes", "doto", "extend", "extend-protocol", "extend-type",
"fn", "for", "future", "if", "if-let", "if-not", "if-some", "let",
"letfn", "locking", "loop", "ns", "proxy", "reify", "some->", "some->>",
"struct-map", "try", "when", "when-first", "when-let", "when-not",
"when-some", "while", "with-bindings", "with-bindings*", "with-in-str",
"with-loading-context", "with-local-vars", "with-meta", "with-open",
"with-out-str", "with-precision", "with-redefs", "with-redefs-fn"];
function testFormsThatHaveBodyParameter(forms) {
for (var i = 0; i < forms.length; i++) {
MT("should indent body argument of `" + forms[i] + "` by `options.indentUnit` spaces",
"[bracket (][keyword " + forms[i] + "] [variable foo] [variable bar]",
" [variable baz]",
" [variable qux][bracket )]"
);
}
}
testFormsThatHaveBodyParameter(haveBodyParameter);
MT("should indent body argument of `comment` by `options.indentUnit` spaces",
"[bracket (][comment comment foo bar]",
"[comment baz]",
"[comment qux][bracket )]"
);
function typeTokenPairs(type, tokens) {
return "[" + type + " " + tokens.join("] [" + type + " ") + "]";
}
})();

View File

@ -0,0 +1,97 @@
// 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")
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd)
define(["../../lib/codemirror"], mod);
else
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("cmake", function () {
var variable_regex = /({)?[a-zA-Z0-9_]+(})?/;
function tokenString(stream, state) {
var current, prev, found_var = false;
while (!stream.eol() && (current = stream.next()) != state.pending) {
if (current === '$' && prev != '\\' && state.pending == '"') {
found_var = true;
break;
}
prev = current;
}
if (found_var) {
stream.backUp(1);
}
if (current == state.pending) {
state.continueString = false;
} else {
state.continueString = true;
}
return "string";
}
function tokenize(stream, state) {
var ch = stream.next();
// Have we found a variable?
if (ch === '$') {
if (stream.match(variable_regex)) {
return 'variable-2';
}
return 'variable';
}
// Should we still be looking for the end of a string?
if (state.continueString) {
// If so, go through the loop again
stream.backUp(1);
return tokenString(stream, state);
}
// Do we just have a function on our hands?
// In 'cmake_minimum_required (VERSION 2.8.8)', 'cmake_minimum_required' is matched
if (stream.match(/(\s+)?\w+\(/) || stream.match(/(\s+)?\w+\ \(/)) {
stream.backUp(1);
return 'def';
}
if (ch == "#") {
stream.skipToEnd();
return "comment";
}
// Have we found a string?
if (ch == "'" || ch == '"') {
// Store the type (single or double)
state.pending = ch;
// Perform the looping function to find the end
return tokenString(stream, state);
}
if (ch == '(' || ch == ')') {
return 'bracket';
}
if (ch.match(/[0-9]/)) {
return 'number';
}
stream.eatWhile(/[\w-]/);
return null;
}
return {
startState: function () {
var state = {};
state.inDefinition = false;
state.inInclude = false;
state.continueString = false;
state.pending = false;
return state;
},
token: function (stream, state) {
if (stream.eatSpace()) return null;
return tokenize(stream, state);
}
};
});
CodeMirror.defineMIME("text/x-cmake", "cmake");
});

Some files were not shown because too many files have changed in this diff Show More