diff --git a/package.json b/package.json index 274fd5f..0897326 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ ], "author": "yutent", "license": "MIT", - "devDependencies": { + "dependencies": { "autoprefixer": "^7.2.6", "babel-core": "^6.26.3", "babel-plugin-transform-decorators-legacy": "^1.3.4", @@ -32,6 +32,5 @@ "node-sass": "^4.9.0", "postcss": "^6.0.22", "uglify-es": "^3.3.9" - }, - "dependencies": {} + } } diff --git a/src/css/basic-elem.css b/src/css/basic-elem.css new file mode 100644 index 0000000..a7ebba5 --- /dev/null +++ b/src/css/basic-elem.css @@ -0,0 +1 @@ +.do-ui-button{display:inline-block;padding:2px 5px;border:1px solid #ddd;text-align:center;font-size:12px;background:none;cursor:pointer;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.do-ui-button.medium{min-width:100px;height:35px;padding:0 8px;line-height:35px;font-size:15px}.do-ui-button.large{min-width:150px;height:50px;padding:0 13px;line-height:50px;font-size:18px}.do-ui-button.radius-3{border-radius:3px}.do-ui-button.radius-3 [class^="do-icon-"],.do-ui-button.radius-3 [class*=" do-icon-"]{border-radius:3px}.do-ui-button.radius-5{border-radius:5px}.do-ui-button.radius-5 [class^="do-icon-"],.do-ui-button.radius-5 [class*=" do-icon-"]{border-radius:3px}.do-ui-button.teal{border:0;background:#1abc9c;color:#fff}.do-ui-button.teal:hover{background:#48c9b0}.do-ui-button.teal:active{background:#16a085}.do-ui-button.green{border:0;background:#4caf50;color:#fff}.do-ui-button.green:hover{background:#81c784}.do-ui-button.green:active{background:#388e3c}.do-ui-button.blue{border:0;background:#2196f3;color:#fff}.do-ui-button.blue:hover{background:#64b5f6}.do-ui-button.blue:active{background:#1976d2}.do-ui-button.purple{border:0;background:#651fff;color:#fff}.do-ui-button.purple:hover{background:#7c4dff}.do-ui-button.purple:active{background:#6200ea}.do-ui-button.red{border:0;background:#ff5722;color:#fff}.do-ui-button.red:hover{background:#ff7043}.do-ui-button.red:active{background:#e64a19}.do-ui-button.orange{border:0;background:#ff9800;color:#fff}.do-ui-button.orange:hover{background:#ffa726}.do-ui-button.orange:active{background:#f57c00}.do-ui-button.plain{border:0;background:#e7e8eb;color:#546e7a}.do-ui-button.plain:hover{background:#ecf0f1}.do-ui-button.plain:active{background:#d3d5db}.do-ui-button.grey{border:0;background:#546e7a;color:#fff}.do-ui-button.grey:hover{background:#607d8b}.do-ui-button.grey:active{background:#37474f}.do-ui-button.disabled{border-color:#e7e8eb;color:#d3d5db;cursor:not-allowed}.do-ui-button.medium.with-icon,.do-ui-button.large.with-icon{position:relative;padding-left:43px}.do-ui-button.medium.with-icon [class^="do-icon-"],.do-ui-button.medium.with-icon [class*=" do-icon-"],.do-ui-button.large.with-icon [class^="do-icon-"],.do-ui-button.large.with-icon [class*=" do-icon-"]{position:absolute;left:0;top:0;width:35px;font-size:25px;background:rgba(0,0,0,0.1)}.do-ui-button.large.with-icon{padding-left:58px}.do-ui-button.large.with-icon [class^="do-icon-"],.do-ui-button.large.with-icon [class*=" do-icon-"]{width:50px;font-size:35px}.do-ui-input{position:relative;min-height:30px;padding:0 5px;border:1px solid #d3d5db;background:#fff;color:#546e7a;outline:none;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.do-ui-input::-webkit-input-placeholder{color:#d3d5db}.do-ui-input.area{padding:5px}.do-ui-input.radius-3{border-radius:3px}.do-ui-input.radius-5{border-radius:5px}.do-ui-input:focus,.do-ui-input:hover{border-color:#1abc9c}.do-ui-input.alert{border-color:#ff5722;color:#ff5722}.do-ui-input.alert input{color:#ff5722}.do-ui-input.disabled{border-color:transparent;background:#e7e8eb;color:#d3d5db}.do-ui-input.with-icon{display:inline-block;padding:0}.do-ui-input.with-icon input{width:100%;height:100%;min-height:30px;padding:0 30px 0 5px;border:0;background:transparent}.do-ui-input.with-icon [class^="do-icon-"],.do-ui-input.with-icon [class*=" do-icon-"]{position:absolute;right:0;top:0;width:30px;line-height:30px;font-size:22px}.do-ui-select{display:inline-block;min-height:30px;padding:0 30px 0 10px;border:0;border-bottom:1px solid #e7e7e7;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAMAAABV0m3JAAAADFBMVEUAAAD///+Pj4+JiYkxcGihAAAABHRSTlMAABBwqVQF9wAAADNJREFUeNqlzjEOACAMw8DQ/v/PSE5FFhaEx5usdekBuzRVH0RtCqJYELUFrVjQigX/5jdvzgDh9izlMQAAAABJRU5ErkJggg==) no-repeat right 8px;color:#546e7a;outline:none;-webkit-appearance:none;-moz-appearance:none;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.do-ui-select::-ms-expand{display:none}.do-ui-select:focus{border-color:#1abc9c}.do-ui-select.alert{border-color:#ff5722;color:#ff5722}.do-ui-select.disabled{border-color:transparent;background:#e7e8eb;color:#d3d5db}.do-ui-radio,.do-ui-checkbox{display:inline-block;position:relative;width:auto;height:auto;min-height:30px;padding-left:35px;line-height:30px;border-radius:3px;color:#546e7a}.do-ui-radio{padding-left:50px}.do-ui-radio>input{position:absolute;left:10px;top:10px;width:35px;height:10px;border-radius:10px;border:0;background:#d3d5db;-webkit-appearance:none;-moz-appearance:none}.do-ui-radio>input:checked{background:#d3d5db}.do-ui-radio>input:disabled{background:#ecf0f1}.do-ui-radio>input:disabled:checked{background:#d3d5db}.do-ui-radio>input::after{position:absolute;display:block;left:-2px;top:-5px;width:20px;height:20px;border-radius:50%;content:"";background:#ecf0f1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.2);box-shadow:0 1px 2px rgba(0,0,0,0.2)}.do-ui-radio>input:checked::after{left:auto;right:-2px;background:#607d8b}.do-ui-radio>input:checked:disabled::after{background:#d3d5db}.do-ui-radio.green>input:checked{background:#81c784}.do-ui-radio.green>input:checked::after{background:#388e3c}.do-ui-radio.teal>input:checked{background:#81c784}.do-ui-radio.teal>input:checked::after{background:#16a085}.do-ui-radio.blue>input:checked{background:#64b5f6}.do-ui-radio.blue>input:checked::after{background:#1976d2}.do-ui-radio.purple>input:checked{background:#64b5f6}.do-ui-radio.purple>input:checked::after{background:#6200ea}.do-ui-radio.red>input:checked{background:#ff7043}.do-ui-radio.red>input:checked::after{background:#e64a19}.do-ui-radio.orange>input:checked{background:#ffa726}.do-ui-radio.orange>input:checked::after{background:#f57c00}.do-ui-radio.grey>input:checked{background:#607d8b}.do-ui-radio.grey>input:checked::after{background:#37474f}.do-ui-radio.disabled{color:#d3d5db}.do-ui-checkbox>input{position:absolute;left:2px;top:2px;width:26px;height:26px;line-height:22px;border:2px solid #d3d5db;border-radius:3px;text-align:center;font-size:18px;font-family:"ui font" !important;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-appearance:none;-moz-appearance:none}.do-ui-checkbox>input:checked::after{content:"\e60f"}.do-ui-checkbox>input:disabled{border-color:#d3d5db;color:#d3d5db}.do-ui-checkbox.green>input{color:#4caf50 !important;border-color:#4caf50}.do-ui-checkbox.teal>input{color:#1abc9c !important;border-color:#1abc9c}.do-ui-checkbox.purple>input{color:#651fff !important;border-color:#651fff}.do-ui-checkbox.blue>input{color:#2196f3 !important;border-color:#2196f3}.do-ui-checkbox.red>input{color:#ff5722 !important;border-color:#ff5722}.do-ui-checkbox.orange>input{color:#ff9800 !important;border-color:#ff9800}.do-ui-checkbox.grey>input{color:#546e7a !important;border-color:#546e7a}.do-ui-checkbox.disabled{color:#d3d5db}.do-ui-checkbox.with-style{padding-left:5px;padding-right:35px;line-height:26px;border:2px solid #e7e8eb;background:#e7e8eb;text-align:center}.do-ui-checkbox.with-style>input{left:auto;right:0;top:0;line-height:26px;border:0;background:#fff;color:#607d8b}.do-ui-checkbox.with-style>input:disabled{color:#d3d5db !important}.do-ui-checkbox.with-style.green{border-color:#4caf50;background:#4caf50;color:#fff}.do-ui-checkbox.with-style.teal{border-color:#1abc9c;background:#1abc9c;color:#fff}.do-ui-checkbox.with-style.purple{border-color:#651fff;background:#651fff;color:#fff}.do-ui-checkbox.with-style.blue{border-color:#2196f3;background:#2196f3;color:#fff}.do-ui-checkbox.with-style.red{border-color:#ff5722;background:#ff5722;color:#fff}.do-ui-checkbox.with-style.orange{border-color:#ff9800;background:#ff9800;color:#fff}.do-ui-checkbox.with-style.grey{border-color:#546e7a;background:#546e7a;color:#fff}.do-ui-checkbox.with-style.disabled{border-color:#e7e8eb;background:#e7e8eb;color:#d3d5db}.do-ui-quote{display:block;position:relative;min-height:60px;margin:10px 0;padding:15px 5px 5px 50px;border:1px solid #ddd;border-radius:10px;background:#f7f7f7;word-break:break-all}.do-ui-quote::before{position:absolute;left:8px;top:0;font:30px/1.5 "ui font";color:#d3d5db;content:"\e61b"}.do-ui-warn,.do-ui-mark{display:inline-block;position:relative;min-height:40px;margin:5px 0;padding:5px 8px 5px 50px;border:1px solid #ff9800;border-radius:5px;background:#fffbed;color:#f57c00;word-break:break-all}.do-ui-warn p,.do-ui-mark p{margin:0 !important}.do-ui-warn::before,.do-ui-mark::before{position:absolute;left:15px;top:5px;font:20px/1.5 "ui font";color:#ff5722;content:"\e6f6"}.do-ui-mark{border-color:#48c9b0;color:#16a085;background:#edfbf8}.do-ui-mark::before{color:#16a085;content:"\e657"} diff --git a/src/css/basic-elem.scss b/src/css/basic-elem.scss index ff5546a..165f240 100644 --- a/src/css/basic-elem.scss +++ b/src/css/basic-elem.scss @@ -72,31 +72,27 @@ .do-ui-input {position:relative;min-height:30px;padding:0 5px;border:1px solid nth($cp, 3);background:#fff;color:nth($cgr, 1);outline:none;@include ts; - &::-webkit-input-placeholder {color:nth($cp, 3);} - - &.area {padding:5px;} + &::-webkit-input-placeholder {color:nth($cp, 3);} + + &.area {padding:5px;} - &.radius-3 {border-radius:3px;} - &.radius-5 {border-radius:5px;} - - &:focus,&:hover {border-color:nth($ct, 1);} - &.alert {border-color:nth($cr, 1);color:nth($cr, 1); - input {color:nth($cr, 1);} - } - &.disabled {border-color:transparent;background:nth($cp, 1);color:nth($cp, 3)} - - &.with-style {display:inline-block;padding:0; - - input {width:100%;height:100%;min-height:30px;padding:0 30px 0 5px;border: 0;background:transparent;} - - &::after {position:absolute;right:0;top:0;width:35px;height:30px;line-height:30px;text-align:center;font-family:"ui font" !important;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;} - - &.icon-user::after {content:"\e6f4"} - &.icon-pwd::after {content:"\e655"} - &.icon-mail::after {content:"\e66e"} - &.icon-date::after {content:"\e650"} - &.icon-phone::after {content:"\e651"} + &.radius-3 {border-radius:3px;} + &.radius-5 {border-radius:5px;} + + &:focus,&:hover {border-color:nth($ct, 1);} + &.alert {border-color:nth($cr, 1);color:nth($cr, 1); + input {color:nth($cr, 1);} + } + &.disabled {border-color:transparent;background:nth($cp, 1);color:nth($cp, 3)} + + &.with-icon {display:inline-block;padding:0; + + input {width:100%;height:100%;min-height:30px;padding:0 30px 0 5px;border: 0;background:transparent;} + + [class^="do-icon-"], [class*=" do-icon-"] { + position:absolute;right:0;top:0;width:30px;line-height:30px;font-size:22px; } + } } @@ -116,38 +112,38 @@ } .do-ui-radio {padding-left:50px; - >input {position:absolute;left:10px;top:10px;width:35px;height:10px;border-radius:10px;border:0;background:nth($cp, 3);-webkit-appearance:none;-moz-appearance:none; - - &:checked {background:nth($cp, 3);} - &:disabled {background:nth($cp, 2);} - &:disabled:checked {background:nth($cp, 3);} + >input {position:absolute;left:10px;top:10px;width:35px;height:10px;border-radius:10px;border:0;background:nth($cp, 3);-webkit-appearance:none;-moz-appearance:none; + + &:checked {background:nth($cp, 3);} + &:disabled {background:nth($cp, 2);} + &:disabled:checked {background:nth($cp, 3);} - &::after {position:absolute;display:block;left:-2px;top:-5px;width:20px;height:20px;border-radius:50%;content:"";background:nth($cp, 2);box-shadow:0 1px 2px rgba(0,0,0,.2);} - &:checked::after {left:auto;right:-2px;background:nth($cgr, 2);} - &:checked:disabled::after {background:nth($cp, 3);} - } - &.green >input:checked {background:nth($cg, 2); - &::after {background:nth($cg, 3);} - } - &.teal >input:checked {background:nth($cg, 2); - &::after {background:nth($ct, 3);} - } - &.blue >input:checked {background:nth($cb, 2); - &::after {background:nth($cb, 3);} - } - &.purple >input:checked {background:nth($cb, 2); - &::after {background:nth($cpp, 3);} - } - &.red >input:checked {background:nth($cr, 2); - &::after {background:nth($cr, 3);} - } - &.orange >input:checked {background:nth($co, 2); - &::after {background:nth($co, 3);} - } - &.grey >input:checked {background:nth($cgr, 2); - &::after {background:nth($cgr, 3);} - } - &.disabled {color:nth($cp, 3);} + &::after {position:absolute;display:block;left:-2px;top:-5px;width:20px;height:20px;border-radius:50%;content:"";background:nth($cp, 2);box-shadow:0 1px 2px rgba(0,0,0,.2);} + &:checked::after {left:auto;right:-2px;background:nth($cgr, 2);} + &:checked:disabled::after {background:nth($cp, 3);} + } + &.green >input:checked {background:nth($cg, 2); + &::after {background:nth($cg, 3);} + } + &.teal >input:checked {background:nth($cg, 2); + &::after {background:nth($ct, 3);} + } + &.blue >input:checked {background:nth($cb, 2); + &::after {background:nth($cb, 3);} + } + &.purple >input:checked {background:nth($cb, 2); + &::after {background:nth($cpp, 3);} + } + &.red >input:checked {background:nth($cr, 2); + &::after {background:nth($cr, 3);} + } + &.orange >input:checked {background:nth($co, 2); + &::after {background:nth($co, 3);} + } + &.grey >input:checked {background:nth($cgr, 2); + &::after {background:nth($cgr, 3);} + } + &.disabled {color:nth($cp, 3);} } .do-ui-checkbox { >input {position:absolute;left:2px;top:2px;width:26px;height:26px;line-height:22px;border:2px solid nth($cp, 3);border-radius:3px;text-align:center;font-size:18px;font-family:"ui font" !important;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;-webkit-appearance:none;-moz-appearance:none; diff --git a/src/css/reset.css b/src/css/reset.css new file mode 100644 index 0000000..527e48f --- /dev/null +++ b/src/css/reset.css @@ -0,0 +1 @@ +@font-face{font-family:"uifont";src:url("data:application/x-font-woff;charset=utf-8;base64,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") format("woff")}*{margin:0;padding:0;vertical-align:baseline;-webkit-box-sizing:border-box;box-sizing:border-box}::before,::after{-webkit-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section,content{display:block}img{border:0;display:inline-block}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote::before,blockquote::after,q::before,q::after{content:'';content:none}table{border-collapse:collapse;border-spacing:0}a:focus,input,button:focus,input:focus{outline:none}::-moz-focus-inner{border:none;outline:none}[anot],[\:if],do-*{visibility:hidden}.do-fn-cl{*zoom:1}.do-fn-cl::after{content:".";display:block;height:0;clear:both;visibility:hidden;overflow:hidden}.do-fn-clear{clear:both;display:inline}.do-fn-show{display:block}.do-fn-hide{display:none}.do-fn-fl{float:left}.do-fn-fr{float:right}.do-fn-noselect{-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.do-fn-noselect img,.do-fn-noselect a{-webkit-user-drag:none}.do-fn-ell{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.do-st-thin{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.do-st-hand{cursor:pointer}[class^="do-icon-"],[class*=" do-icon-"]{display:inline-block;font-family:"uifont" !important;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.do-icon-info:before{content:"\e673"}.do-icon-bad:before{content:"\e674"}.do-icon-deny:before{content:"\e676"}.do-icon-calendar:before{content:"\e675"}.do-icon-email:before{content:"\e677"}.do-icon-eye:before{content:"\e678"}.do-icon-face:before{content:"\e67c"}.do-icon-fly:before{content:"\e679"}.do-icon-floppy:before{content:"\e67a"}.do-icon-good:before{content:"\e67b"}.do-icon-headset:before{content:"\e67d"}.do-icon-help:before{content:"\e67e"}.do-icon-list:before{content:"\e682"}.do-icon-lock:before{content:"\e683"}.do-icon-menu-left:before{content:"\e684"}.do-icon-menu-right:before{content:"\e685"}.do-icon-minimize:before{content:"\e686"}.do-icon-phone:before{content:"\e688"}.do-icon-picture:before{content:"\e689"}.do-icon-pipe:before{content:"\e68a"}.do-icon-plus:before{content:"\e68b"}.do-icon-quote:before{content:"\e68d"}.do-icon-table:before{content:"\e690"}.do-icon-talk:before{content:"\e691"}.do-icon-time:before{content:"\e692"}.do-icon-download:before{content:"\e694"}.do-icon-upload:before{content:"\e695"}.do-icon-male:before{content:"\e696"}.do-icon-female:before{content:"\e697"}.do-icon-left:before{content:"\e698"}.do-icon-dbl-left:before{content:"\e699"}.do-icon-right:before{content:"\e69a"}.do-icon-dbl-right:before{content:"\e69b"}.do-icon-pin:before{content:"\e69c"}.do-icon-edit:before{content:"\e69d"}.do-icon-home:before{content:"\e69e"}.do-icon-chart:before{content:"\e69f"}.do-icon-folder-close:before{content:"\e6a0"}.do-icon-txt:before{content:"\e6a1"}.do-icon-folder-open:before{content:"\e6a2"}.do-icon-qr:before{content:"\e6a3"}.do-icon-setting:before{content:"\e6a4"}.do-icon-mute:before{content:"\e6a5"}.do-icon-chat:before{content:"\e6a6"}.do-icon-font:before{content:"\e6a7"}.do-icon-unmute:before{content:"\e6a8"}.do-icon-search:before{content:"\e6a9"}.do-icon-sad:before{content:"\e6aa"}.do-icon-trash:before{content:"\e6ab"}.do-icon-happy:before{content:"\e6ac"}.do-icon-share:before{content:"\e6ad"}.do-icon-tag:before{content:"\e6ae"}.do-icon-app2:before{content:"\e6af"}.do-icon-app1:before{content:"\e6b0"}.do-icon-logout:before{content:"\e6b1"}.do-icon-menu-dot:before{content:"\e6b2"}.do-icon-trigon-up:before{content:"\e6b3"}.do-icon-trigon-down:before{content:"\e6b4"}.do-icon-loading:before{content:"\e6b5"}.do-icon-position:before{content:"\e6b6"}.do-icon-warn:before{content:"\e6b7"}.do-icon-bell:before{content:"\e6b8"}.do-icon-close:before{content:"\e6b9"}.do-icon-fire:before{content:"\e6ba"}.do-icon-user:before{content:"\e6bb"}.do-icon-icon-list:before{content:"\e6bc"}.do-icon-star:before{content:"\e6bd"}.do-icon-client:before{content:"\e6be"}.do-icon-maximize:before{content:"\e6bf"}.do-icon-star-full:before{content:"\e6c0"}.do-icon-camera:before{content:"\e6c1"}.do-icon-live:before{content:"\e6c2"}.do-icon-get:before{content:"\e6c3"}.do-icon-wrong:before{content:"\e6c4"} diff --git a/src/css/reset.scss b/src/css/reset.scss index 2806535..7fe56f8 100644 --- a/src/css/reset.scss +++ b/src/css/reset.scss @@ -26,7 +26,7 @@ src: url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'); } * {margin: 0;padding: 0;vertical-align: baseline;box-sizing:border-box;} - +::before,::after {box-sizing:border-box;} /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section,content {display: block;} img {border:0;display:inline-block;} diff --git a/src/js/codemirror/codemirror.js b/src/js/codemirror/codemirror.js index f82f87f..4a9c47e 100644 --- a/src/js/codemirror/codemirror.js +++ b/src/js/codemirror/codemirror.js @@ -1,3969 +1,4514 @@ -define(function(){ - "use strict"; +'use strict' - function CodeMirror(place, givenOptions) { - var options = {}, - defaults = CodeMirror.defaults; - for (var opt in defaults) - if (defaults.hasOwnProperty(opt)) - options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt]; - var input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em"); - input.setAttribute("wrap", "off"); - input.setAttribute("autocorrect", "off"); - input.setAttribute("autocapitalize", "off"); - var inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); - var scrollbarInner = elt("div", null, "CodeMirror-scrollbar-inner"); - var scrollbar = elt("div", [scrollbarInner], "CodeMirror-scrollbar"); - var lineDiv = elt("div"), - selectionDiv = elt("div", null, null, "position: relative; z-index: -1"); - var cursor = elt("pre", "\u00a0", "CodeMirror-cursor"), - widthForcer = elt("pre", "\u00a0", "CodeMirror-cursor", "visibility: hidden"); - var measure = elt("div", null, null, "position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;"); - var lineSpace = elt("div", [measure, cursor, widthForcer, selectionDiv, lineDiv], null, "position: relative; z-index: 0"); - var gutterText = elt("div", null, "CodeMirror-gutter-text"), - gutter = elt("div", [gutterText], "CodeMirror-gutter"); - var mover = elt("div", [gutter, elt("div", [lineSpace], "CodeMirror-lines")], null, "position: relative"); - var sizer = elt("div", [mover], null, "position: relative"); - var scroller = elt("div", [sizer], "CodeMirror-scroll"); - scroller.setAttribute("tabIndex", "-1"); - var wrapper = elt("div", [inputDiv, scrollbar, scroller], "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "")); - if (place.appendChild) place.appendChild(wrapper); - else place(wrapper); - themeChanged(); - keyMapChanged(); - if (ios) input.style.width = "0px"; - if (!webkit) scroller.draggable = true; - lineSpace.style.outline = "none"; - if (options.tabindex != null) input.tabIndex = options.tabindex; - if (options.autofocus) focusInput(); - if (!options.gutter && !options.lineNumbers) gutter.style.display = "none"; - if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute"; - if (mac_geLion) { - scrollbar.style.zIndex = -2; - scrollbar.style.visibility = "hidden"; - } else if (ie_lt8) scrollbar.style.minWidth = "18px"; - var poll = new Delayed(), - highlight = new Delayed(), - blinker; - var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), - frontier = 0, - focused; - loadMode(); - var sel = { - from: { - line: 0, - ch: 0 - }, - to: { - line: 0, - ch: 0 - }, - inverted: false - }; - var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, - draggingText, overwrite = false, - suppressEdits = false, - pasteIncoming = false; - var updateInput, userSelChange, changes, textChanged, selectionChanged, gutterDirty, callbacks; - var displayOffset = 0, - showingFrom = 0, - showingTo = 0, - lastSizeC = 0; - var bracketHighlighted; - var maxLine = getLine(0), - updateMaxLine = false, - maxLineChanged = true; - var pollingFast = false; - var goalColumn = null; +function CodeMirror(place, givenOptions) { + var options = {}, + defaults = CodeMirror.defaults + for (var opt in defaults) + if (defaults.hasOwnProperty(opt)) + options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) + ? givenOptions + : defaults)[opt] + var input = elt( + 'textarea', + null, + null, + 'position: absolute; padding: 0; width: 1px; height: 1em' + ) + input.setAttribute('wrap', 'off') + input.setAttribute('autocorrect', 'off') + input.setAttribute('autocapitalize', 'off') + var inputDiv = elt( + 'div', + [input], + null, + 'overflow: hidden; position: relative; width: 3px; height: 0px;' + ) + var scrollbarInner = elt('div', null, 'CodeMirror-scrollbar-inner') + var scrollbar = elt('div', [scrollbarInner], 'CodeMirror-scrollbar') + var lineDiv = elt('div'), + selectionDiv = elt('div', null, null, 'position: relative; z-index: -1') + var cursor = elt('pre', '\u00a0', 'CodeMirror-cursor'), + widthForcer = elt( + 'pre', + '\u00a0', + 'CodeMirror-cursor', + 'visibility: hidden' + ) + var measure = elt( + 'div', + null, + null, + 'position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;' + ) + var lineSpace = elt( + 'div', + [measure, cursor, widthForcer, selectionDiv, lineDiv], + null, + 'position: relative; z-index: 0' + ) + var gutterText = elt('div', null, 'CodeMirror-gutter-text'), + gutter = elt('div', [gutterText], 'CodeMirror-gutter') + var mover = elt( + 'div', + [gutter, elt('div', [lineSpace], 'CodeMirror-lines')], + null, + 'position: relative' + ) + var sizer = elt('div', [mover], null, 'position: relative') + var scroller = elt('div', [sizer], 'CodeMirror-scroll') + scroller.setAttribute('tabIndex', '-1') + var wrapper = elt( + 'div', + [inputDiv, scrollbar, scroller], + 'CodeMirror' + (options.lineWrapping ? ' CodeMirror-wrap' : '') + ) + if (place.appendChild) place.appendChild(wrapper) + else place(wrapper) + themeChanged() + keyMapChanged() + if (ios) input.style.width = '0px' + if (!webkit) scroller.draggable = true + lineSpace.style.outline = 'none' + if (options.tabindex != null) input.tabIndex = options.tabindex + if (options.autofocus) focusInput() + if (!options.gutter && !options.lineNumbers) gutter.style.display = 'none' + if (khtml) + (inputDiv.style.height = '1px'), (inputDiv.style.position = 'absolute') + if (mac_geLion) { + scrollbar.style.zIndex = -2 + scrollbar.style.visibility = 'hidden' + } else if (ie_lt8) scrollbar.style.minWidth = '18px' + var poll = new Delayed(), + highlight = new Delayed(), + blinker + var mode, + doc = new BranchChunk([new LeafChunk([new Line('')])]), + frontier = 0, + focused + loadMode() + var sel = { + from: { + line: 0, + ch: 0 + }, + to: { + line: 0, + ch: 0 + }, + inverted: false + } + var shiftSelecting, + lastClick, + lastDoubleClick, + lastScrollTop = 0, + draggingText, + overwrite = false, + suppressEdits = false, + pasteIncoming = false + var updateInput, + userSelChange, + changes, + textChanged, + selectionChanged, + gutterDirty, + callbacks + var displayOffset = 0, + showingFrom = 0, + showingTo = 0, + lastSizeC = 0 + var bracketHighlighted + var maxLine = getLine(0), + updateMaxLine = false, + maxLineChanged = true + var pollingFast = false + var goalColumn = null + operation(function() { + setValue(options.value || '') + updateInput = false + })() + var history = new History() + connect(scroller, 'mousedown', operation(onMouseDown)) + connect(scroller, 'dblclick', operation(onDoubleClick)) + connect(lineSpace, 'selectstart', e_preventDefault) + if (!gecko) connect(scroller, 'contextmenu', onContextMenu) + connect(scroller, 'scroll', onScrollMain) + connect(scrollbar, 'scroll', onScrollBar) + connect(scrollbar, 'mousedown', function() { + if (focused) setTimeout(focusInput, 0) + }) + var resizeHandler = connect( + window, + 'resize', + function() { + if (wrapper.parentNode) updateDisplay(true) + else resizeHandler() + }, + true + ) + connect(input, 'keyup', operation(onKeyUp)) + connect(input, 'input', fastPoll) + connect(input, 'keydown', operation(onKeyDown)) + connect(input, 'keypress', operation(onKeyPress)) + connect(input, 'focus', onFocus) + connect(input, 'blur', onBlur) + + function drag_(e) { + if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return + e_stop(e) + } + if (options.dragDrop) { + connect(scroller, 'dragstart', onDragStart) + connect(scroller, 'dragenter', drag_) + connect(scroller, 'dragover', drag_) + connect(scroller, 'drop', operation(onDrop)) + } + connect(scroller, 'paste', function() { + focusInput() + fastPoll() + }) + connect(input, 'paste', function() { + pasteIncoming = true + fastPoll() + }) + connect( + input, + 'cut', + operation(function() { + if (!options.readOnly) replaceSelection('') + }) + ) + if (khtml) + connect(sizer, 'mouseup', function() { + if (document.activeElement == input) input.blur() + focusInput() + }) + var hasFocus + try { + hasFocus = document.activeElement == input + } catch (e) {} + if (hasFocus || options.autofocus) setTimeout(onFocus, 20) + else onBlur() + + function isLine(l) { + return l >= 0 && l < doc.size + } + var __events = {}, + noop = function() {} + var instance = (wrapper.CodeMirror = { + getValue: getValue, + setValue: operation(setValue), + getSelection: getSelection, + replaceSelection: operation(replaceSelection), + focus: function() { + window.focus() + focusInput() + onFocus() + fastPoll() + }, + setOption: function(option, value) { + var oldVal = options[option] + options[option] = value + if (option == 'mode' || option == 'indentUnit') loadMode() + else if (option == 'readOnly' && value == 'nocursor') { + onBlur() + input.blur() + } else if (option == 'readOnly' && !value) { + resetInput(true) + } else if (option == 'theme') themeChanged() + else if (option == 'lineWrapping' && oldVal != value) + operation(wrappingChanged)() + else if (option == 'tabSize') updateDisplay(true) + else if (option == 'keyMap') keyMapChanged() + else if (option == 'tabindex') input.tabIndex = value + if ( + option == 'lineNumbers' || + option == 'gutter' || + option == 'firstLineNumber' || + option == 'theme' || + option == 'lineNumberFormatter' + ) { + gutterChanged() + updateDisplay(true) + } + }, + getOption: function(option) { + return options[option] + }, + getMode: function() { + return mode + }, + undo: operation(undo), + redo: operation(redo), + indentLine: operation(function(n, dir) { + if (typeof dir != 'string') { + if (dir == null) dir = options.smartIndent ? 'smart' : 'prev' + else dir = dir ? 'add' : 'subtract' + } + if (isLine(n)) indentLine(n, dir) + }), + indentSelection: operation(indentSelected), + historySize: function() { + return { + undo: history.done.length, + redo: history.undone.length + } + }, + clearHistory: function() { + history = new History() + }, + setHistory: function(histData) { + history = new History() + history.done = histData.done + history.undone = histData.undone + }, + getHistory: function() { + function cp(arr) { + for (var i = 0, nw = [], nwelt; i < arr.length; ++i) { + nw.push((nwelt = [])) + for (var j = 0, elt = arr[i]; j < elt.length; ++j) { + var old = [], + cur = elt[j] + nwelt.push({ + start: cur.start, + added: cur.added, + old: old + }) + for (var k = 0; k < cur.old.length; ++k) + old.push(hlText(cur.old[k])) + } + } + return nw + } + return { + done: cp(history.done), + undone: cp(history.undone) + } + }, + matchBrackets: operation(function() { + matchBrackets(true) + }), + getTokenAt: operation(function(pos) { + pos = clipPos(pos) + return getLine(pos.line).getTokenAt( + mode, + getStateBefore(pos.line), + options.tabSize, + pos.ch + ) + }), + getStateAfter: function(line) { + line = clipLine(line == null ? doc.size - 1 : line) + return getStateBefore(line + 1) + }, + cursorCoords: function(start, mode) { + if (start == null) start = sel.inverted + return this.charCoords(start ? sel.from : sel.to, mode) + }, + charCoords: function(pos, mode) { + pos = clipPos(pos) + if (mode == 'local') return localCoords(pos, false) + if (mode == 'div') return localCoords(pos, true) + return pageCoords(pos) + }, + coordsChar: function(coords) { + var off = eltOffset(lineSpace) + return coordsChar(coords.x - off.left, coords.y - off.top) + }, + defaultTextHeight: function() { + return textHeight() + }, + markText: operation(markText), + setBookmark: setBookmark, + findMarksAt: findMarksAt, + setMarker: operation(addGutterMarker), + clearMarker: operation(removeGutterMarker), + setLineClass: operation(setLineClass), + hideLine: operation(function(h) { + return setLineHidden(h, true) + }), + showLine: operation(function(h) { + return setLineHidden(h, false) + }), + onDeleteLine: function(line, f) { + if (typeof line == 'number') { + if (!isLine(line)) return null + line = getLine(line) + } + ;(line.handlers || (line.handlers = [])).push(f) + return line + }, + lineInfo: lineInfo, + getViewport: function() { + return { + from: showingFrom, + to: showingTo + } + }, + addWidget: function(pos, node, scroll, vert, horiz) { + pos = localCoords(clipPos(pos)) + var top = pos.yBot, + left = pos.x + node.style.position = 'absolute' + sizer.appendChild(node) + if (vert == 'over') top = pos.y + else if (vert == 'near') { + var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()), + hspace = + Math.max(sizer.clientWidth, lineSpace.clientWidth) - paddingLeft() + if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight) + top = pos.y - node.offsetHeight + if (left + node.offsetWidth > hspace) left = hspace - node.offsetWidth + } + node.style.top = top + paddingTop() + 'px' + node.style.left = node.style.right = '' + if (horiz == 'right') { + left = sizer.clientWidth - node.offsetWidth + node.style.right = '0px' + } else { + if (horiz == 'left') left = 0 + else if (horiz == 'middle') + left = (sizer.clientWidth - node.offsetWidth) / 2 + node.style.left = left + paddingLeft() + 'px' + } + if (scroll) + scrollIntoView( + left, + top, + left + node.offsetWidth, + top + node.offsetHeight + ) + }, + lineCount: function() { + return doc.size + }, + clipPos: clipPos, + getCursor: function(start) { + if (start == null) start = sel.inverted + return copyPos(start ? sel.from : sel.to) + }, + somethingSelected: function() { + return !posEq(sel.from, sel.to) + }, + setCursor: operation(function(line, ch, user) { + if (ch == null && typeof line.line == 'number') + setCursor(line.line, line.ch, user) + else setCursor(line, ch, user) + }), + setSelection: operation(function(from, to, user) { + ;(user + ? setSelectionUser + : setSelection)(clipPos(from), clipPos(to || from)) + }), + getLine: function(line) { + if (isLine(line)) return getLine(line).text + }, + getLineHandle: function(line) { + if (isLine(line)) return getLine(line) + }, + setLine: operation(function(line, text) { + if (isLine(line)) + replaceRange( + text, + { + line: line, + ch: 0 + }, + { + line: line, + ch: getLine(line).text.length + } + ) + }), + removeLine: operation(function(line) { + if (isLine(line)) + replaceRange( + '', + { + line: line, + ch: 0 + }, + clipPos({ + line: line + 1, + ch: 0 + }) + ) + }), + replaceRange: operation(replaceRange), + getRange: function(from, to, lineSep) { + return getRange(clipPos(from), clipPos(to), lineSep) + }, + triggerOnKeyDown: operation(onKeyDown), + execCommand: function(cmd) { + return commands[cmd](instance) + }, + moveH: operation(moveH), + deleteH: operation(deleteH), + moveV: operation(moveV), + toggleOverwrite: function() { + if (overwrite) { + overwrite = false + cursor.className = cursor.className.replace(' CodeMirror-overwrite', '') + } else { + overwrite = true + cursor.className += ' CodeMirror-overwrite' + } + }, + posFromIndex: function(off) { + var lineNo = 0, + ch + doc.iter(0, doc.size, function(line) { + var sz = line.text.length + 1 + if (sz > off) { + ch = off + return true + } + off -= sz + ++lineNo + }) + return clipPos({ + line: lineNo, + ch: ch + }) + }, + indexFromPos: function(coords) { + if (coords.line < 0 || coords.ch < 0) return 0 + var index = coords.ch + doc.iter(0, coords.line, function(line) { + index += line.text.length + 1 + }) + return index + }, + scrollTo: function(x, y) { + if (x != null) scroller.scrollLeft = x + if (y != null) scrollbar.scrollTop = scroller.scrollTop = y + updateDisplay([]) + }, + getScrollInfo: function() { + return { + x: scroller.scrollLeft, + y: scrollbar.scrollTop, + height: scrollbar.scrollHeight, + width: scroller.scrollWidth + } + }, + scrollIntoView: function(pos) { + var coords = localCoords( + pos ? clipPos(pos) : sel.inverted ? sel.from : sel.to + ) + scrollIntoView(coords.x, coords.y, coords.x, coords.yBot) + }, + setSize: function(width, height) { + function interpret(val) { + val = String(val) + return /^\d+$/.test(val) ? val + 'px' : val + } + if (width != null) wrapper.style.width = interpret(width) + if (height != null) scroller.style.height = interpret(height) + instance.refresh() + }, + operation: function(f) { + return operation(f)() + }, + compoundChange: function(f) { + return compoundChange(f) + }, + refresh: function() { + updateDisplay(true, null, lastScrollTop) + if (scrollbar.scrollHeight > lastScrollTop) + scrollbar.scrollTop = lastScrollTop + }, + getInputField: function() { + return input + }, + getWrapperElement: function() { + return wrapper + }, + getScrollerElement: function() { + return scroller + }, + getGutterElement: function() { + return gutter + }, + on: function(name, cb) { + if (!cb || typeof cb !== 'function') return this + if (!__events[name]) { + __events[name] = [cb] + } else { + __events[name].push(cb) + } + return this + } + }) + + function getLine(n) { + return getLineAt(doc, n) + } + + function updateLineHeight(line, height) { + gutterDirty = true + var diff = height - line.height + for (var n = line; n; n = n.parent) n.height += diff + } + + function lineContent(line, wrapAt) { + if (!line.styles) + line.highlight( + mode, + (line.stateAfter = getStateBefore(lineNo(line))), + options.tabSize + ) + return line.getContent(options.tabSize, wrapAt, options.lineWrapping) + } + + function setValue(code) { + var top = { + line: 0, + ch: 0 + } + updateLines( + top, + { + line: doc.size - 1, + ch: getLine(doc.size - 1).text.length + }, + splitLines(code), + top, + top + ) + updateInput = true + } + + function getValue(lineSep) { + var text = [] + doc.iter(0, doc.size, function(line) { + text.push(line.text) + }) + return text.join(lineSep || '\n') + } + + function onScrollBar(e) { + if (Math.abs(scrollbar.scrollTop - lastScrollTop) > 1) { + lastScrollTop = scroller.scrollTop = scrollbar.scrollTop + updateDisplay([]) + } + } + + function onScrollMain(e) { + if (options.fixedGutter && gutter.style.left != scroller.scrollLeft + 'px') + gutter.style.left = scroller.scrollLeft + 'px' + if (Math.abs(scroller.scrollTop - lastScrollTop) > 1) { + lastScrollTop = scroller.scrollTop + if (scrollbar.scrollTop != lastScrollTop) + scrollbar.scrollTop = lastScrollTop + updateDisplay([]) + } + if (options.onScroll) options.onScroll(instance) + } + + function onMouseDown(e) { + setShift(e_prop(e, 'shiftKey')) + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == sizer && n != mover) return + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == gutterText) { + if (options.onGutterClick) + options.onGutterClick( + instance, + indexOf(gutterText.childNodes, n) + showingFrom, + e + ) + return e_preventDefault(e) + } + var start = posFromMouse(e) + switch (e_button(e)) { + case 3: + if (gecko) onContextMenu(e) + return + case 2: + if (start) setCursor(start.line, start.ch, true) + setTimeout(focusInput, 20) + e_preventDefault(e) + return + } + if (!start) { + if (e_target(e) == scroller) e_preventDefault(e) + return + } + if (!focused) onFocus() + var now = +new Date(), + type = 'single' + if ( + lastDoubleClick && + lastDoubleClick.time > now - 400 && + posEq(lastDoubleClick.pos, start) + ) { + type = 'triple' + e_preventDefault(e) + setTimeout(focusInput, 20) + selectLine(start.line) + } else if ( + lastClick && + lastClick.time > now - 400 && + posEq(lastClick.pos, start) + ) { + type = 'double' + lastDoubleClick = { + time: now, + pos: start + } + e_preventDefault(e) + var word = findWordAt(start) + setSelectionUser(word.from, word.to) + } else { + lastClick = { + time: now, + pos: start + } + } + + function dragEnd(e2) { + if (webkit) scroller.draggable = false + draggingText = false + up() + drop() + if ( + Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < + 10 + ) { + e_preventDefault(e2) + setCursor(start.line, start.ch, true) + focusInput() + } + } + var last = start, + going + if ( + options.dragDrop && + dragAndDrop && + !options.readOnly && + !posEq(sel.from, sel.to) && + !posLess(start, sel.from) && + !posLess(sel.to, start) && + type == 'single' + ) { + if (webkit) scroller.draggable = true + var up = connect(document, 'mouseup', operation(dragEnd), true) + var drop = connect(scroller, 'drop', operation(dragEnd), true) + draggingText = true + if (scroller.dragDrop) scroller.dragDrop() + return + } + e_preventDefault(e) + if (type == 'single') setCursor(start.line, start.ch, true) + var startstart = sel.from, + startend = sel.to + + function doSelect(cur) { + if (type == 'single') { + setSelectionUser(start, cur) + } else if (type == 'double') { + var word = findWordAt(cur) + if (posLess(cur, startstart)) setSelectionUser(word.from, startend) + else setSelectionUser(startstart, word.to) + } else if (type == 'triple') { + if (posLess(cur, startstart)) + setSelectionUser( + startend, + clipPos({ + line: cur.line, + ch: 0 + }) + ) + else + setSelectionUser( + startstart, + clipPos({ + line: cur.line + 1, + ch: 0 + }) + ) + } + } + + function extend(e) { + var cur = posFromMouse(e, true) + if (cur && !posEq(cur, last)) { + if (!focused) onFocus() + last = cur + doSelect(cur) + updateInput = false + var visible = visibleLines() + if (cur.line >= visible.to || cur.line < visible.from) + going = setTimeout( + operation(function() { + extend(e) + }), + 150 + ) + } + } + + function done(e) { + clearTimeout(going) + var cur = posFromMouse(e) + if (cur) doSelect(cur) + e_preventDefault(e) + focusInput() + updateInput = true + move() + up() + } + var move = connect( + document, + 'mousemove', + operation(function(e) { + clearTimeout(going) + e_preventDefault(e) + if (!ie && !e_button(e)) done(e) + else extend(e) + }), + true + ) + var up = connect(document, 'mouseup', operation(done), true) + } + + function onDoubleClick(e) { + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == gutterText) return e_preventDefault(e) + e_preventDefault(e) + } + + function onDrop(e) { + if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return + e_preventDefault(e) + var pos = posFromMouse(e, true), + files = e.dataTransfer.files + if (!pos || options.readOnly) return + if (files && files.length && window.FileReader && window.File) { + var n = files.length, + text = Array(n), + read = 0 + var loadFile = function(file, i) { + var reader = new FileReader() + reader.onload = function() { + text[i] = reader.result + if (++read == n) { + pos = clipPos(pos) + operation(function() { + var end = replaceRange(text.join(''), pos, pos) + setSelectionUser(pos, end) + })() + } + } + reader.readAsText(file) + } + for (var i = 0; i < n; ++i) loadFile(files[i], i) + } else { + if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) + return + try { + var text = e.dataTransfer.getData('Text') + if (text) { + compoundChange(function() { + var curFrom = sel.from, + curTo = sel.to + setSelectionUser(pos, pos) + if (draggingText) replaceRange('', curFrom, curTo) + replaceSelection(text) + focusInput() + }) + } + } catch (e) {} + } + } + + function onDragStart(e) { + var txt = getSelection() + e.dataTransfer.setData('Text', txt) + if (e.dataTransfer.setDragImage) + e.dataTransfer.setDragImage(elt('img'), 0, 0) + } + + function doHandleBinding(bound, dropShift) { + if (typeof bound == 'string') { + bound = commands[bound] + if (!bound) return false + } + var prevShift = shiftSelecting + try { + if (options.readOnly) suppressEdits = true + if (dropShift) shiftSelecting = null + bound(instance) + } catch (e) { + if (e != Pass) throw e + return false + } finally { + shiftSelecting = prevShift + suppressEdits = false + } + return true + } + var maybeTransition + + function handleKeyBinding(e) { + var startMap = getKeyMap(options.keyMap), + next = startMap.auto + clearTimeout(maybeTransition) + if (next && !isModifierKey(e)) + maybeTransition = setTimeout(function() { + if (getKeyMap(options.keyMap) == startMap) { + options.keyMap = next.call ? next.call(null, instance) : next + } + }, 50) + var name = keyNames[e_prop(e, 'keyCode')], + handled = false + var flipCtrlCmd = opera && mac + if (name == null || e.altGraphKey) return false + if (e_prop(e, 'altKey')) name = 'Alt-' + name + if (e_prop(e, flipCtrlCmd ? 'metaKey' : 'ctrlKey')) name = 'Ctrl-' + name + if (e_prop(e, flipCtrlCmd ? 'ctrlKey' : 'metaKey')) name = 'Cmd-' + name + var stopped = false + + function stop() { + stopped = true + } + if (e_prop(e, 'shiftKey')) { + handled = + lookupKey( + 'Shift-' + name, + options.extraKeys, + options.keyMap, + function(b) { + return doHandleBinding(b, true) + }, + stop + ) || + lookupKey( + name, + options.extraKeys, + options.keyMap, + function(b) { + if (typeof b == 'string' && /^go[A-Z]/.test(b)) + return doHandleBinding(b) + }, + stop + ) + } else { + handled = lookupKey( + name, + options.extraKeys, + options.keyMap, + doHandleBinding, + stop + ) + } + if (stopped) handled = false + if (handled) { + e_preventDefault(e) + restartBlink() + if (ie_lt9) { + e.oldKeyCode = e.keyCode + e.keyCode = 0 + } + } + return handled + } + + function handleCharBinding(e, ch) { + var handled = lookupKey( + "'" + ch + "'", + options.extraKeys, + options.keyMap, + function(b) { + return doHandleBinding(b, true) + } + ) + if (handled) { + e_preventDefault(e) + restartBlink() + } + return handled + } + var lastStoppedKey = null + + function onKeyDown(e) { + if (!focused) onFocus() + if (ie && e.keyCode == 27) { + e.returnValue = false + } + if (pollingFast) { + if (readInput()) pollingFast = false + } + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return + var code = e_prop(e, 'keyCode') + setShift(code == 16 || e_prop(e, 'shiftKey')) + var handled = handleKeyBinding(e) + if (opera) { + lastStoppedKey = handled ? code : null + if (!handled && code == 88 && e_prop(e, mac ? 'metaKey' : 'ctrlKey')) + replaceSelection('') + } + } + + function onKeyPress(e) { + if (pollingFast) readInput() + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return + var keyCode = e_prop(e, 'keyCode'), + charCode = e_prop(e, 'charCode') + if (opera && keyCode == lastStoppedKey) { + lastStoppedKey = null + e_preventDefault(e) + return + } + if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) + return + var ch = String.fromCharCode(charCode == null ? keyCode : charCode) + if ( + options.electricChars && + mode.electricChars && + options.smartIndent && + !options.readOnly + ) { + if (mode.electricChars.indexOf(ch) > -1) + setTimeout( + operation(function() { + indentLine(sel.to.line, 'smart') + }), + 75 + ) + } + if (handleCharBinding(e, ch)) return + fastPoll() + } + + function onKeyUp(e) { + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return + if (e_prop(e, 'keyCode') == 16) shiftSelecting = null + + if (__events['change']) { + __events['change'].forEach(function(fn) { + fn(instance, getValue()) + }) + } + } + + function onFocus() { + if (options.readOnly == 'nocursor') return + if (!focused) { + if (options.onFocus) options.onFocus(instance) + focused = true + if (scroller.className.search(/\bCodeMirror-focused\b/) == -1) + scroller.className += ' CodeMirror-focused' + } + slowPoll() + restartBlink() + if (__events['focus']) { + __events['focus'].forEach(function(fn) { + fn(instance, getValue()) + }) + } + } + + function onBlur() { + if (focused) { + if (options.onBlur) options.onBlur(instance) + focused = false + if (bracketHighlighted) operation(function() { - setValue(options.value || ""); - updateInput = false; - })(); - var history = new History(); - connect(scroller, "mousedown", operation(onMouseDown)); - connect(scroller, "dblclick", operation(onDoubleClick)); - connect(lineSpace, "selectstart", e_preventDefault); - if (!gecko) connect(scroller, "contextmenu", onContextMenu); - connect(scroller, "scroll", onScrollMain); - connect(scrollbar, "scroll", onScrollBar); - connect(scrollbar, "mousedown", function() { - if (focused) setTimeout(focusInput, 0); - }); - var resizeHandler = connect(window, "resize", function() { - if (wrapper.parentNode) updateDisplay(true); - else resizeHandler(); - }, true); - connect(input, "keyup", operation(onKeyUp)); - connect(input, "input", fastPoll); - connect(input, "keydown", operation(onKeyDown)); - connect(input, "keypress", operation(onKeyPress)); - connect(input, "focus", onFocus); - connect(input, "blur", onBlur); + if (bracketHighlighted) { + bracketHighlighted() + bracketHighlighted = null + } + })() + scroller.className = scroller.className.replace(' CodeMirror-focused', '') + } + clearInterval(blinker) + setTimeout(function() { + if (!focused) shiftSelecting = null + }, 150) + } - function drag_(e) { - if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return; - e_stop(e); + function updateLines(from, to, newText, selFrom, selTo) { + if (suppressEdits) return + var old = [] + doc.iter(from.line, to.line + 1, function(line) { + old.push(newHL(line.text, line.markedSpans)) + }) + if (history) { + history.addChange(from.line, newText.length, old) + while (history.done.length > options.undoDepth) history.done.shift() + } + var lines = updateMarkedSpans( + hlSpans(old[0]), + hlSpans(lst(old)), + from.ch, + to.ch, + newText + ) + updateLinesNoUndo(from, to, lines, selFrom, selTo) + } + + function unredoHelper(from, to) { + if (!from.length) return + var set = from.pop(), + out = [] + for (var i = set.length - 1; i >= 0; i -= 1) { + var change = set[i] + var replaced = [], + end = change.start + change.added + doc.iter(change.start, end, function(line) { + replaced.push(newHL(line.text, line.markedSpans)) + }) + out.push({ + start: change.start, + added: change.old.length, + old: replaced + }) + var pos = { + line: change.start + change.old.length - 1, + ch: editEnd(hlText(lst(replaced)), hlText(lst(change.old))) + } + updateLinesNoUndo( + { + line: change.start, + ch: 0 + }, + { + line: end - 1, + ch: getLine(end - 1).text.length + }, + change.old, + pos, + pos + ) + } + updateInput = true + to.push(out) + } + + function undo() { + unredoHelper(history.done, history.undone) + } + + function redo() { + unredoHelper(history.undone, history.done) + } + + function updateLinesNoUndo(from, to, lines, selFrom, selTo) { + if (suppressEdits) return + var recomputeMaxLength = false, + maxLineLength = maxLine.text.length + if (!options.lineWrapping) + doc.iter(from.line, to.line + 1, function(line) { + if (!line.hidden && line.text.length == maxLineLength) { + recomputeMaxLength = true + return true } - if (options.dragDrop) { - connect(scroller, "dragstart", onDragStart); - connect(scroller, "dragenter", drag_); - connect(scroller, "dragover", drag_); - connect(scroller, "drop", operation(onDrop)); + }) + if (from.line != to.line || lines.length > 1) gutterDirty = true + var nlines = to.line - from.line, + firstLine = getLine(from.line), + lastLine = getLine(to.line) + var lastHL = lst(lines) + if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == '') { + var added = [], + prevLine = null + for (var i = 0, e = lines.length - 1; i < e; ++i) + added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))) + lastLine.update(lastLine.text, hlSpans(lastHL)) + if (nlines) doc.remove(from.line, nlines, callbacks) + if (added.length) doc.insert(from.line, added) + } else if (firstLine == lastLine) { + if (lines.length == 1) { + firstLine.update( + firstLine.text.slice(0, from.ch) + + hlText(lines[0]) + + firstLine.text.slice(to.ch), + hlSpans(lines[0]) + ) + } else { + for (var added = [], i = 1, e = lines.length - 1; i < e; ++i) + added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))) + added.push( + new Line( + hlText(lastHL) + firstLine.text.slice(to.ch), + hlSpans(lastHL) + ) + ) + firstLine.update( + firstLine.text.slice(0, from.ch) + hlText(lines[0]), + hlSpans(lines[0]) + ) + doc.insert(from.line + 1, added) + } + } else if (lines.length == 1) { + firstLine.update( + firstLine.text.slice(0, from.ch) + + hlText(lines[0]) + + lastLine.text.slice(to.ch), + hlSpans(lines[0]) + ) + doc.remove(from.line + 1, nlines, callbacks) + } else { + var added = [] + firstLine.update( + firstLine.text.slice(0, from.ch) + hlText(lines[0]), + hlSpans(lines[0]) + ) + lastLine.update( + hlText(lastHL) + lastLine.text.slice(to.ch), + hlSpans(lastHL) + ) + for (var i = 1, e = lines.length - 1; i < e; ++i) + added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))) + if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks) + doc.insert(from.line + 1, added) + } + if (options.lineWrapping) { + var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3) + doc.iter(from.line, from.line + lines.length, function(line) { + if (line.hidden) return + var guess = Math.ceil(line.text.length / perLine) || 1 + if (guess != line.height) updateLineHeight(line, guess) + }) + } else { + doc.iter(from.line, from.line + lines.length, function(line) { + var l = line.text + if (!line.hidden && l.length > maxLineLength) { + maxLine = line + maxLineLength = l.length + maxLineChanged = true + recomputeMaxLength = false } - connect(scroller, "paste", function() { - focusInput(); - fastPoll(); - }); - connect(input, "paste", function() { - pasteIncoming = true; - fastPoll(); - }); - connect(input, "cut", operation(function() { - if (!options.readOnly) replaceSelection(""); - })); - if (khtml) connect(sizer, "mouseup", function() { - if (document.activeElement == input) input.blur(); - focusInput(); - }); - var hasFocus; - try { - hasFocus = (document.activeElement == input); - } catch (e) {} - if (hasFocus || options.autofocus) setTimeout(onFocus, 20); - else onBlur(); + }) + if (recomputeMaxLength) updateMaxLine = true + } + frontier = Math.min(frontier, from.line) + startWorker(400) + var lendiff = lines.length - nlines - 1 + changes.push({ + from: from.line, + to: to.line + 1, + diff: lendiff + }) + if (options.onChange) { + for (var i = 0; i < lines.length; ++i) + if (typeof lines[i] != 'string') lines[i] = lines[i].text + var changeObj = { + from: from, + to: to, + text: lines + } + if (textChanged) { + for (var cur = textChanged; cur.next; cur = cur.next) {} + cur.next = changeObj + } else textChanged = changeObj + } - function isLine(l) { - return l >= 0 && l < doc.size; + function updateLine(n) { + return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff + } + setSelection( + clipPos(selFrom), + clipPos(selTo), + updateLine(sel.from.line), + updateLine(sel.to.line) + ) + } + + function needsScrollbar() { + var realHeight = doc.height * textHeight() + 2 * paddingTop() + return realHeight * 0.99 > scroller.offsetHeight ? realHeight : false + } + + function updateVerticalScroll(scrollTop) { + var scrollHeight = needsScrollbar() + scrollbar.style.display = scrollHeight ? 'block' : 'none' + if (scrollHeight) { + scrollbarInner.style.height = sizer.style.minHeight = scrollHeight + 'px' + scrollbar.style.height = scroller.clientHeight + 'px' + if (scrollTop != null) { + scrollbar.scrollTop = scroller.scrollTop = scrollTop + if (webkit) + setTimeout(function() { + if (scrollbar.scrollTop != scrollTop) return + scrollbar.scrollTop = scrollTop + (scrollTop ? -1 : 1) + scrollbar.scrollTop = scrollTop + }, 0) + } + } else { + sizer.style.minHeight = '' + } + mover.style.top = displayOffset * textHeight() + 'px' + } + + function computeMaxLength() { + maxLine = getLine(0) + maxLineChanged = true + var maxLineLength = maxLine.text.length + doc.iter(1, doc.size, function(line) { + var l = line.text + if (!line.hidden && l.length > maxLineLength) { + maxLineLength = l.length + maxLine = line + } + }) + updateMaxLine = false + } + + function replaceRange(code, from, to) { + from = clipPos(from) + if (!to) to = from + else to = clipPos(to) + code = splitLines(code) + + function adjustPos(pos) { + if (posLess(pos, from)) return pos + if (!posLess(to, pos)) return end + var line = pos.line + code.length - (to.line - from.line) - 1 + var ch = pos.ch + if (pos.line == to.line) + ch += lst(code).length - (to.ch - (to.line == from.line ? from.ch : 0)) + return { + line: line, + ch: ch + } + } + var end + replaceRange1(code, from, to, function(end1) { + end = end1 + return { + from: adjustPos(sel.from), + to: adjustPos(sel.to) + } + }) + return end + } + + function replaceSelection(code, collapse) { + replaceRange1(splitLines(code), sel.from, sel.to, function(end) { + if (collapse == 'end') + return { + from: end, + to: end } - var __events = {}, noop = function(){}; - var instance = wrapper.CodeMirror = { - getValue: getValue, - setValue: operation(setValue), - getSelection: getSelection, - replaceSelection: operation(replaceSelection), - focus: function() { - window.focus(); - focusInput(); - onFocus(); - fastPoll(); - }, - setOption: function(option, value) { - var oldVal = options[option]; - options[option] = value; - if (option == "mode" || option == "indentUnit") loadMode(); - else if (option == "readOnly" && value == "nocursor") { - onBlur(); - input.blur(); - } else if (option == "readOnly" && !value) { - resetInput(true); - } else if (option == "theme") themeChanged(); - else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)(); - else if (option == "tabSize") updateDisplay(true); - else if (option == "keyMap") keyMapChanged(); - else if (option == "tabindex") input.tabIndex = value; - if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || option == "theme" || option == "lineNumberFormatter") { - gutterChanged(); - updateDisplay(true); - } - }, - getOption: function(option) { - return options[option]; - }, - getMode: function() { - return mode; - }, - undo: operation(undo), - redo: operation(redo), - indentLine: operation(function(n, dir) { - if (typeof dir != "string") { - if (dir == null) dir = options.smartIndent ? "smart" : "prev"; - else dir = dir ? "add" : "subtract"; - } - if (isLine(n)) indentLine(n, dir); - }), - indentSelection: operation(indentSelected), - historySize: function() { - return { - undo: history.done.length, - redo: history.undone.length - }; - }, - clearHistory: function() { - history = new History(); - }, - setHistory: function(histData) { - history = new History(); - history.done = histData.done; - history.undone = histData.undone; - }, - getHistory: function() { - function cp(arr) { - for (var i = 0, nw = [], nwelt; i < arr.length; ++i) { - nw.push(nwelt = []); - for (var j = 0, elt = arr[i]; j < elt.length; ++j) { - var old = [], - cur = elt[j]; - nwelt.push({ - start: cur.start, - added: cur.added, - old: old - }); - for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k])); - } - } - return nw; - } - return { - done: cp(history.done), - undone: cp(history.undone) - }; - }, - matchBrackets: operation(function() { - matchBrackets(true); - }), - getTokenAt: operation(function(pos) { - pos = clipPos(pos); - return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), options.tabSize, pos.ch); - }), - getStateAfter: function(line) { - line = clipLine(line == null ? doc.size - 1 : line); - return getStateBefore(line + 1); - }, - cursorCoords: function(start, mode) { - if (start == null) start = sel.inverted; - return this.charCoords(start ? sel.from : sel.to, mode); - }, - charCoords: function(pos, mode) { - pos = clipPos(pos); - if (mode == "local") return localCoords(pos, false); - if (mode == "div") return localCoords(pos, true); - return pageCoords(pos); - }, - coordsChar: function(coords) { - var off = eltOffset(lineSpace); - return coordsChar(coords.x - off.left, coords.y - off.top); - }, - defaultTextHeight: function() { - return textHeight(); - }, - markText: operation(markText), - setBookmark: setBookmark, - findMarksAt: findMarksAt, - setMarker: operation(addGutterMarker), - clearMarker: operation(removeGutterMarker), - setLineClass: operation(setLineClass), - hideLine: operation(function(h) { - return setLineHidden(h, true); - }), - showLine: operation(function(h) { - return setLineHidden(h, false); - }), - onDeleteLine: function(line, f) { - if (typeof line == "number") { - if (!isLine(line)) return null; - line = getLine(line); - } - (line.handlers || (line.handlers = [])).push(f); - return line; - }, - lineInfo: lineInfo, - getViewport: function() { - return { - from: showingFrom, - to: showingTo - }; - }, - addWidget: function(pos, node, scroll, vert, horiz) { - pos = localCoords(clipPos(pos)); - var top = pos.yBot, - left = pos.x; - node.style.position = "absolute"; - sizer.appendChild(node); - if (vert == "over") top = pos.y; - else if (vert == "near") { - var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()), - hspace = Math.max(sizer.clientWidth, lineSpace.clientWidth) - paddingLeft(); - if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight) - top = pos.y - node.offsetHeight; - if (left + node.offsetWidth > hspace) - left = hspace - node.offsetWidth; - } - node.style.top = (top + paddingTop()) + "px"; - node.style.left = node.style.right = ""; - if (horiz == "right") { - left = sizer.clientWidth - node.offsetWidth; - node.style.right = "0px"; - } else { - if (horiz == "left") left = 0; - else if (horiz == "middle") left = (sizer.clientWidth - node.offsetWidth) / 2; - node.style.left = (left + paddingLeft()) + "px"; - } - if (scroll) - scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight); - }, - lineCount: function() { - return doc.size; - }, - clipPos: clipPos, - getCursor: function(start) { - if (start == null) start = sel.inverted; - return copyPos(start ? sel.from : sel.to); - }, - somethingSelected: function() { - return !posEq(sel.from, sel.to); - }, - setCursor: operation(function(line, ch, user) { - if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user); - else setCursor(line, ch, user); - }), - setSelection: operation(function(from, to, user) { - (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from)); - }), - getLine: function(line) { - if (isLine(line)) return getLine(line).text; - }, - getLineHandle: function(line) { - if (isLine(line)) return getLine(line); - }, - setLine: operation(function(line, text) { - if (isLine(line)) replaceRange(text, { - line: line, - ch: 0 - }, { - line: line, - ch: getLine(line).text.length - }); - }), - removeLine: operation(function(line) { - if (isLine(line)) replaceRange("", { - line: line, - ch: 0 - }, clipPos({ - line: line + 1, - ch: 0 - })); - }), - replaceRange: operation(replaceRange), - getRange: function(from, to, lineSep) { - return getRange(clipPos(from), clipPos(to), lineSep); - }, - triggerOnKeyDown: operation(onKeyDown), - execCommand: function(cmd) { - return commands[cmd](instance); - }, - moveH: operation(moveH), - deleteH: operation(deleteH), - moveV: operation(moveV), - toggleOverwrite: function() { - if (overwrite) { - overwrite = false; - cursor.className = cursor.className.replace(" CodeMirror-overwrite", ""); - } else { - overwrite = true; - cursor.className += " CodeMirror-overwrite"; - } - }, - posFromIndex: function(off) { - var lineNo = 0, - ch; - doc.iter(0, doc.size, function(line) { - var sz = line.text.length + 1; - if (sz > off) { - ch = off; - return true; - } - off -= sz; - ++lineNo; - }); - return clipPos({ - line: lineNo, - ch: ch - }); - }, - indexFromPos: function(coords) { - if (coords.line < 0 || coords.ch < 0) return 0; - var index = coords.ch; - doc.iter(0, coords.line, function(line) { - index += line.text.length + 1; - }); - return index; - }, - scrollTo: function(x, y) { - if (x != null) scroller.scrollLeft = x; - if (y != null) scrollbar.scrollTop = scroller.scrollTop = y; - updateDisplay([]); - }, - getScrollInfo: function() { - return { - x: scroller.scrollLeft, - y: scrollbar.scrollTop, - height: scrollbar.scrollHeight, - width: scroller.scrollWidth - }; - }, - scrollIntoView: function(pos) { - var coords = localCoords(pos ? clipPos(pos) : sel.inverted ? sel.from : sel.to); - scrollIntoView(coords.x, coords.y, coords.x, coords.yBot); - }, - setSize: function(width, height) { - function interpret(val) { - val = String(val); - return /^\d+$/.test(val) ? val + "px" : val; - } - if (width != null) wrapper.style.width = interpret(width); - if (height != null) scroller.style.height = interpret(height); - instance.refresh(); - }, - operation: function(f) { - return operation(f)(); - }, - compoundChange: function(f) { - return compoundChange(f); - }, - refresh: function() { - updateDisplay(true, null, lastScrollTop); - if (scrollbar.scrollHeight > lastScrollTop) - scrollbar.scrollTop = lastScrollTop; - }, - getInputField: function() { - return input; - }, - getWrapperElement: function() { - return wrapper; - }, - getScrollerElement: function() { - return scroller; - }, - getGutterElement: function() { - return gutter; - }, - on: function(name, cb){ - if(!cb || typeof cb !== 'function') return this; - if(!__events[name]){ - __events[name] = [cb] - }else{ - __events[name].push(cb) - } - return this - } - }; - - function getLine(n) { - return getLineAt(doc, n); + else if (collapse == 'start') + return { + from: sel.from, + to: sel.from } - - function updateLineHeight(line, height) { - gutterDirty = true; - var diff = height - line.height; - for (var n = line; n; n = n.parent) n.height += diff; + else + return { + from: sel.from, + to: end } + }) + } - function lineContent(line, wrapAt) { - if (!line.styles) - line.highlight(mode, line.stateAfter = getStateBefore(lineNo(line)), options.tabSize); - return line.getContent(options.tabSize, wrapAt, options.lineWrapping); - } + function replaceRange1(code, from, to, computeSel) { + var endch = code.length == 1 ? code[0].length + from.ch : lst(code).length + var newSel = computeSel({ + line: from.line + code.length - 1, + ch: endch + }) + updateLines(from, to, code, newSel.from, newSel.to) + } - function setValue(code) { - var top = { - line: 0, - ch: 0 - }; - updateLines(top, { - line: doc.size - 1, - ch: getLine(doc.size - 1).text.length - }, splitLines(code), top, top); - updateInput = true; - } + function getRange(from, to, lineSep) { + var l1 = from.line, + l2 = to.line + if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch) + var code = [getLine(l1).text.slice(from.ch)] + doc.iter(l1 + 1, l2, function(line) { + code.push(line.text) + }) + code.push(getLine(l2).text.slice(0, to.ch)) + return code.join(lineSep || '\n') + } - function getValue(lineSep) { - var text = []; - doc.iter(0, doc.size, function(line) { - text.push(line.text); - }); - return text.join(lineSep || "\n"); - } + function getSelection(lineSep) { + return getRange(sel.from, sel.to, lineSep) + } - function onScrollBar(e) { - if (Math.abs(scrollbar.scrollTop - lastScrollTop) > 1) { - lastScrollTop = scroller.scrollTop = scrollbar.scrollTop; - updateDisplay([]); - } - } + function slowPoll() { + if (pollingFast) return + poll.set(options.pollInterval, function() { + readInput() + if (focused) slowPoll() + }) + } - function onScrollMain(e) { - if (options.fixedGutter && gutter.style.left != scroller.scrollLeft + "px") - gutter.style.left = scroller.scrollLeft + "px"; - if (Math.abs(scroller.scrollTop - lastScrollTop) > 1) { - lastScrollTop = scroller.scrollTop; - if (scrollbar.scrollTop != lastScrollTop) - scrollbar.scrollTop = lastScrollTop; - updateDisplay([]); - } - if (options.onScroll) options.onScroll(instance); - } + function fastPoll() { + var missed = false + pollingFast = true - function onMouseDown(e) { - setShift(e_prop(e, "shiftKey")); - for (var n = e_target(e); n != wrapper; n = n.parentNode) - if (n.parentNode == sizer && n != mover) return; - for (var n = e_target(e); n != wrapper; n = n.parentNode) - if (n.parentNode == gutterText) { - if (options.onGutterClick) - options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e); - return e_preventDefault(e); - } - var start = posFromMouse(e); - switch (e_button(e)) { - case 3: - if (gecko) onContextMenu(e); - return; - case 2: - if (start) setCursor(start.line, start.ch, true); - setTimeout(focusInput, 20); - e_preventDefault(e); - return; - } - if (!start) { - if (e_target(e) == scroller) e_preventDefault(e); - return; - } - if (!focused) onFocus(); - var now = +new Date, - type = "single"; - if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { - type = "triple"; - e_preventDefault(e); - setTimeout(focusInput, 20); - selectLine(start.line); - } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) { - type = "double"; - lastDoubleClick = { - time: now, - pos: start - }; - e_preventDefault(e); - var word = findWordAt(start); - setSelectionUser(word.from, word.to); - } else { - lastClick = { - time: now, - pos: start - }; - } + function p() { + var changed = readInput() + if (!changed && !missed) { + missed = true + poll.set(60, p) + } else { + pollingFast = false + slowPoll() + } + } + poll.set(20, p) + } + var prevInput = '' - function dragEnd(e2) { - if (webkit) scroller.draggable = false; - draggingText = false; - up(); - drop(); - if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { - e_preventDefault(e2); - setCursor(start.line, start.ch, true); - focusInput(); - } - } - var last = start, - going; - if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) && !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") { - if (webkit) scroller.draggable = true; - var up = connect(document, "mouseup", operation(dragEnd), true); - var drop = connect(scroller, "drop", operation(dragEnd), true); - draggingText = true; - if (scroller.dragDrop) scroller.dragDrop(); - return; - } - e_preventDefault(e); - if (type == "single") setCursor(start.line, start.ch, true); - var startstart = sel.from, - startend = sel.to; + function readInput() { + if (!focused || hasSelection(input) || options.readOnly) return false + var text = input.value + if (text == prevInput) return false + if (!nestedOperation) startOperation() + shiftSelecting = null + var same = 0, + l = Math.min(prevInput.length, text.length) + while (same < l && prevInput[same] == text[same]) ++same + if (same < prevInput.length) + sel.from = { + line: sel.from.line, + ch: sel.from.ch - (prevInput.length - same) + } + else if (overwrite && posEq(sel.from, sel.to) && !pasteIncoming) + sel.to = { + line: sel.to.line, + ch: Math.min( + getLine(sel.to.line).text.length, + sel.to.ch + (text.length - same) + ) + } + replaceSelection(text.slice(same), 'end') + if (text.length > 1000) { + input.value = prevInput = '' + } else prevInput = text + if (!nestedOperation) endOperation() + pasteIncoming = false + return true + } - function doSelect(cur) { - if (type == "single") { - setSelectionUser(start, cur); - } else if (type == "double") { - var word = findWordAt(cur); - if (posLess(cur, startstart)) setSelectionUser(word.from, startend); - else setSelectionUser(startstart, word.to); - } else if (type == "triple") { - if (posLess(cur, startstart)) setSelectionUser(startend, clipPos({ - line: cur.line, - ch: 0 - })); - else setSelectionUser(startstart, clipPos({ - line: cur.line + 1, - ch: 0 - })); - } - } + function resetInput(user) { + if (!posEq(sel.from, sel.to)) { + prevInput = '' + input.value = getSelection() + if (focused) selectInput(input) + } else if (user) prevInput = input.value = '' + } - function extend(e) { - var cur = posFromMouse(e, true); - if (cur && !posEq(cur, last)) { - if (!focused) onFocus(); - last = cur; - doSelect(cur); - updateInput = false; - var visible = visibleLines(); - if (cur.line >= visible.to || cur.line < visible.from) - going = setTimeout(operation(function() { - extend(e); - }), 150); - } - } + function focusInput() { + if (options.readOnly != 'nocursor') input.focus() + } - function done(e) { - clearTimeout(going); - var cur = posFromMouse(e); - if (cur) doSelect(cur); - e_preventDefault(e); - focusInput(); - updateInput = true; - move(); - up(); - } - var move = connect(document, "mousemove", operation(function(e) { - clearTimeout(going); - e_preventDefault(e); - if (!ie && !e_button(e)) done(e); - else extend(e); - }), true); - var up = connect(document, "mouseup", operation(done), true); - } + function scrollCursorIntoView() { + var coords = calculateCursorCoords() + scrollIntoView(coords.x, coords.y, coords.x, coords.yBot) + if (!focused) return + var box = sizer.getBoundingClientRect(), + doScroll = null + if (coords.y + box.top < 0) doScroll = true + else if ( + coords.y + box.top + textHeight() > + (window.innerHeight || document.documentElement.clientHeight) + ) + doScroll = false + if (doScroll != null) { + var hidden = cursor.style.display == 'none' + if (hidden) { + cursor.style.display = '' + cursor.style.left = coords.x + 'px' + cursor.style.top = coords.y - displayOffset + 'px' + } + cursor.scrollIntoView(doScroll) + if (hidden) cursor.style.display = 'none' + } + } - function onDoubleClick(e) { - for (var n = e_target(e); n != wrapper; n = n.parentNode) - if (n.parentNode == gutterText) return e_preventDefault(e); - e_preventDefault(e); - } + function calculateCursorCoords() { + var cursor = localCoords(sel.inverted ? sel.from : sel.to) + var x = options.lineWrapping + ? Math.min(cursor.x, lineSpace.offsetWidth) + : cursor.x + return { + x: x, + y: cursor.y, + yBot: cursor.yBot + } + } - function onDrop(e) { - if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return; - e_preventDefault(e); - var pos = posFromMouse(e, true), - files = e.dataTransfer.files; - if (!pos || options.readOnly) return; - if (files && files.length && window.FileReader && window.File) { - var n = files.length, - text = Array(n), - read = 0; - var loadFile = function(file, i) { - var reader = new FileReader; - reader.onload = function() { - text[i] = reader.result; - if (++read == n) { - pos = clipPos(pos); - operation(function() { - var end = replaceRange(text.join(""), pos, pos); - setSelectionUser(pos, end); - })(); - } - }; - reader.readAsText(file); - }; - for (var i = 0; i < n; ++i) loadFile(files[i], i); - } else { - if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) return; - try { - var text = e.dataTransfer.getData("Text"); - if (text) { - compoundChange(function() { - var curFrom = sel.from, - curTo = sel.to; - setSelectionUser(pos, pos); - if (draggingText) replaceRange("", curFrom, curTo); - replaceSelection(text); - focusInput(); - }); - } - } catch (e) {} - } - } + function scrollIntoView(x1, y1, x2, y2) { + var scrollPos = calculateScrollPos(x1, y1, x2, y2) + if (scrollPos.scrollLeft != null) { + scroller.scrollLeft = scrollPos.scrollLeft + } + if (scrollPos.scrollTop != null) { + scrollbar.scrollTop = scroller.scrollTop = scrollPos.scrollTop + } + } - function onDragStart(e) { - var txt = getSelection(); - e.dataTransfer.setData("Text", txt); - if (e.dataTransfer.setDragImage) - e.dataTransfer.setDragImage(elt('img'), 0, 0); - } + function calculateScrollPos(x1, y1, x2, y2) { + var pl = paddingLeft(), + pt = paddingTop() + y1 += pt + y2 += pt + x1 += pl + x2 += pl + var screen = scroller.clientHeight, + screentop = scrollbar.scrollTop, + result = {} + var docBottom = needsScrollbar() || Infinity + var atTop = y1 < pt + 10, + atBottom = y2 + pt > docBottom - 10 + if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1) + else if (y2 > screentop + screen) + result.scrollTop = (atBottom ? docBottom : y2) - screen + var screenw = scroller.clientWidth, + screenleft = scroller.scrollLeft + var gutterw = options.fixedGutter ? gutter.clientWidth : 0 + var atLeft = x1 < gutterw + pl + 10 + if (x1 < screenleft + gutterw || atLeft) { + if (atLeft) x1 = 0 + result.scrollLeft = Math.max(0, x1 - 10 - gutterw) + } else if (x2 > screenw + screenleft - 3) { + result.scrollLeft = x2 + 10 - screenw + } + return result + } - function doHandleBinding(bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound]; - if (!bound) return false; - } - var prevShift = shiftSelecting; - try { - if (options.readOnly) suppressEdits = true; - if (dropShift) shiftSelecting = null; - bound(instance); - } catch (e) { - if (e != Pass) throw e; - return false; - } finally { - shiftSelecting = prevShift; - suppressEdits = false; - } - return true; - } - var maybeTransition; + function visibleLines(scrollTop) { + var lh = textHeight(), + top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop() + var fromHeight = Math.max(0, Math.floor(top / lh)) + var toHeight = Math.ceil((top + scroller.clientHeight) / lh) + return { + from: lineAtHeight(doc, fromHeight), + to: lineAtHeight(doc, toHeight) + } + } - function handleKeyBinding(e) { - var startMap = getKeyMap(options.keyMap), - next = startMap.auto; - clearTimeout(maybeTransition); - if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() { - if (getKeyMap(options.keyMap) == startMap) { - options.keyMap = (next.call ? next.call(null, instance) : next); - } - }, 50); - var name = keyNames[e_prop(e, "keyCode")], - handled = false; - var flipCtrlCmd = opera && mac; - if (name == null || e.altGraphKey) return false; - if (e_prop(e, "altKey")) name = "Alt-" + name; - if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name; - if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name; - var stopped = false; - - function stop() { - stopped = true; - } - if (e_prop(e, "shiftKey")) { - handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap, function(b) { - return doHandleBinding(b, true); - }, stop) || lookupKey(name, options.extraKeys, options.keyMap, function(b) { - if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b); - }, stop); - } else { - handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop); - } - if (stopped) handled = false; - if (handled) { - e_preventDefault(e); - restartBlink(); - if (ie_lt9) { - e.oldKeyCode = e.keyCode; - e.keyCode = 0; - } - } - return handled; - } - - function handleCharBinding(e, ch) { - var handled = lookupKey("'" + ch + "'", options.extraKeys, options.keyMap, function(b) { - return doHandleBinding(b, true); - }); - if (handled) { - e_preventDefault(e); - restartBlink(); - } - return handled; - } - var lastStoppedKey = null; - - function onKeyDown(e) { - if (!focused) onFocus(); - if (ie && e.keyCode == 27) { - e.returnValue = false; - } - if (pollingFast) { - if (readInput()) pollingFast = false; - } - if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; - var code = e_prop(e, "keyCode"); - setShift(code == 16 || e_prop(e, "shiftKey")); - var handled = handleKeyBinding(e); - if (opera) { - lastStoppedKey = handled ? code : null; - if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey")) - replaceSelection(""); - } - } - - function onKeyPress(e) { - if (pollingFast) readInput(); - if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; - var keyCode = e_prop(e, "keyCode"), - charCode = e_prop(e, "charCode"); - if (opera && keyCode == lastStoppedKey) { - lastStoppedKey = null; - e_preventDefault(e); - return; - } - if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return; - var ch = String.fromCharCode(charCode == null ? keyCode : charCode); - if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) { - if (mode.electricChars.indexOf(ch) > -1) - setTimeout(operation(function() { - indentLine(sel.to.line, "smart"); - }), 75); - } - if (handleCharBinding(e, ch)) return; - fastPoll(); - } - - function onKeyUp(e) { - if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; - if (e_prop(e, "keyCode") == 16) shiftSelecting = null; - - if(__events['change']){ - __events['change'].forEach(function(fn){ - fn(instance, getValue()) - }) - } - } - - function onFocus() { - if (options.readOnly == "nocursor") return; - if (!focused) { - if (options.onFocus) options.onFocus(instance); - focused = true; - if (scroller.className.search(/\bCodeMirror-focused\b/) == -1) - scroller.className += " CodeMirror-focused"; - } - slowPoll(); - restartBlink(); - if(__events['focus']){ - __events['focus'].forEach(function(fn){ - fn(instance, getValue()) - }) - } - } - - function onBlur() { - if (focused) { - if (options.onBlur) options.onBlur(instance); - focused = false; - if (bracketHighlighted) - operation(function() { - if (bracketHighlighted) { - bracketHighlighted(); - bracketHighlighted = null; - } - })(); - scroller.className = scroller.className.replace(" CodeMirror-focused", ""); - } - clearInterval(blinker); - setTimeout(function() { - if (!focused) shiftSelecting = null; - }, 150); - } - - function updateLines(from, to, newText, selFrom, selTo) { - if (suppressEdits) return; - var old = []; - doc.iter(from.line, to.line + 1, function(line) { - old.push(newHL(line.text, line.markedSpans)); - }); - if (history) { - history.addChange(from.line, newText.length, old); - while (history.done.length > options.undoDepth) history.done.shift(); - } - var lines = updateMarkedSpans(hlSpans(old[0]), hlSpans(lst(old)), from.ch, to.ch, newText); - updateLinesNoUndo(from, to, lines, selFrom, selTo); - } - - function unredoHelper(from, to) { - if (!from.length) return; - var set = from.pop(), - out = []; - for (var i = set.length - 1; i >= 0; i -= 1) { - var change = set[i]; - var replaced = [], - end = change.start + change.added; - doc.iter(change.start, end, function(line) { - replaced.push(newHL(line.text, line.markedSpans)); - }); - out.push({ - start: change.start, - added: change.old.length, - old: replaced - }); - var pos = { - line: change.start + change.old.length - 1, - ch: editEnd(hlText(lst(replaced)), hlText(lst(change.old))) - }; - updateLinesNoUndo({ - line: change.start, - ch: 0 - }, { - line: end - 1, - ch: getLine(end - 1).text.length - }, change.old, pos, pos); - } - updateInput = true; - to.push(out); - } - - function undo() { - unredoHelper(history.done, history.undone); - } - - function redo() { - unredoHelper(history.undone, history.done); - } - - function updateLinesNoUndo(from, to, lines, selFrom, selTo) { - if (suppressEdits) return; - var recomputeMaxLength = false, - maxLineLength = maxLine.text.length; - if (!options.lineWrapping) - doc.iter(from.line, to.line + 1, function(line) { - if (!line.hidden && line.text.length == maxLineLength) { - recomputeMaxLength = true; - return true; - } - }); - if (from.line != to.line || lines.length > 1) gutterDirty = true; - var nlines = to.line - from.line, - firstLine = getLine(from.line), - lastLine = getLine(to.line); - var lastHL = lst(lines); - if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") { - var added = [], - prevLine = null; - for (var i = 0, e = lines.length - 1; i < e; ++i) - added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))); - lastLine.update(lastLine.text, hlSpans(lastHL)); - if (nlines) doc.remove(from.line, nlines, callbacks); - if (added.length) doc.insert(from.line, added); - } else if (firstLine == lastLine) { - if (lines.length == 1) { - firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + firstLine.text.slice(to.ch), hlSpans(lines[0])); - } else { - for (var added = [], i = 1, e = lines.length - 1; i < e; ++i) - added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))); - added.push(new Line(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL))); - firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0])); - doc.insert(from.line + 1, added); - } - } else if (lines.length == 1) { - firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + lastLine.text.slice(to.ch), hlSpans(lines[0])); - doc.remove(from.line + 1, nlines, callbacks); - } else { - var added = []; - firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0])); - lastLine.update(hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL)); - for (var i = 1, e = lines.length - 1; i < e; ++i) - added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))); - if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks); - doc.insert(from.line + 1, added); - } - if (options.lineWrapping) { - var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3); - doc.iter(from.line, from.line + lines.length, function(line) { - if (line.hidden) return; - var guess = Math.ceil(line.text.length / perLine) || 1; - if (guess != line.height) updateLineHeight(line, guess); - }); - } else { - doc.iter(from.line, from.line + lines.length, function(line) { - var l = line.text; - if (!line.hidden && l.length > maxLineLength) { - maxLine = line; - maxLineLength = l.length; - maxLineChanged = true; - recomputeMaxLength = false; - } - }); - if (recomputeMaxLength) updateMaxLine = true; - } - frontier = Math.min(frontier, from.line); - startWorker(400); - var lendiff = lines.length - nlines - 1; - changes.push({ - from: from.line, - to: to.line + 1, - diff: lendiff - }); - if (options.onChange) { - for (var i = 0; i < lines.length; ++i) - if (typeof lines[i] != "string") lines[i] = lines[i].text; - var changeObj = { - from: from, - to: to, - text: lines - }; - if (textChanged) { - for (var cur = textChanged; cur.next; cur = cur.next) {} - cur.next = changeObj; - } else textChanged = changeObj; - } - - function updateLine(n) { - return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff; - } - setSelection(clipPos(selFrom), clipPos(selTo), updateLine(sel.from.line), updateLine(sel.to.line)); - } - - function needsScrollbar() { - var realHeight = doc.height * textHeight() + 2 * paddingTop(); - return realHeight * .99 > scroller.offsetHeight ? realHeight : false; - } - - function updateVerticalScroll(scrollTop) { - var scrollHeight = needsScrollbar(); - scrollbar.style.display = scrollHeight ? "block" : "none"; - if (scrollHeight) { - scrollbarInner.style.height = sizer.style.minHeight = scrollHeight + "px"; - scrollbar.style.height = scroller.clientHeight + "px"; - if (scrollTop != null) { - scrollbar.scrollTop = scroller.scrollTop = scrollTop; - if (webkit) setTimeout(function() { - if (scrollbar.scrollTop != scrollTop) return; - scrollbar.scrollTop = scrollTop + (scrollTop ? -1 : 1); - scrollbar.scrollTop = scrollTop; - }, 0); - } - } else { - sizer.style.minHeight = ""; - } - mover.style.top = displayOffset * textHeight() + "px"; - } - - function computeMaxLength() { - maxLine = getLine(0); - maxLineChanged = true; - var maxLineLength = maxLine.text.length; - doc.iter(1, doc.size, function(line) { - var l = line.text; - if (!line.hidden && l.length > maxLineLength) { - maxLineLength = l.length; - maxLine = line; - } - }); - updateMaxLine = false; - } - - function replaceRange(code, from, to) { - from = clipPos(from); - if (!to) to = from; - else to = clipPos(to); - code = splitLines(code); - - function adjustPos(pos) { - if (posLess(pos, from)) return pos; - if (!posLess(to, pos)) return end; - var line = pos.line + code.length - (to.line - from.line) - 1; - var ch = pos.ch; - if (pos.line == to.line) - ch += lst(code).length - (to.ch - (to.line == from.line ? from.ch : 0)); - return { - line: line, - ch: ch - }; - } - var end; - replaceRange1(code, from, to, function(end1) { - end = end1; - return { - from: adjustPos(sel.from), - to: adjustPos(sel.to) - }; - }); - return end; - } - - function replaceSelection(code, collapse) { - replaceRange1(splitLines(code), sel.from, sel.to, function(end) { - if (collapse == "end") return { - from: end, - to: end - }; - else if (collapse == "start") return { - from: sel.from, - to: sel.from - }; - else return { - from: sel.from, - to: end - }; - }); - } - - function replaceRange1(code, from, to, computeSel) { - var endch = code.length == 1 ? code[0].length + from.ch : lst(code).length; - var newSel = computeSel({ - line: from.line + code.length - 1, - ch: endch - }); - updateLines(from, to, code, newSel.from, newSel.to); - } - - function getRange(from, to, lineSep) { - var l1 = from.line, - l2 = to.line; - if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch); - var code = [getLine(l1).text.slice(from.ch)]; - doc.iter(l1 + 1, l2, function(line) { - code.push(line.text); - }); - code.push(getLine(l2).text.slice(0, to.ch)); - return code.join(lineSep || "\n"); - } - - function getSelection(lineSep) { - return getRange(sel.from, sel.to, lineSep); - } - - function slowPoll() { - if (pollingFast) return; - poll.set(options.pollInterval, function() { - readInput(); - if (focused) slowPoll(); - }); - } - - function fastPoll() { - var missed = false; - pollingFast = true; - - function p() { - var changed = readInput(); - if (!changed && !missed) { - missed = true; - poll.set(60, p); - } else { - pollingFast = false; - slowPoll(); - } - } - poll.set(20, p); - } - var prevInput = ""; - - function readInput() { - if (!focused || hasSelection(input) || options.readOnly) return false; - var text = input.value; - if (text == prevInput) return false; - if (!nestedOperation) startOperation(); - shiftSelecting = null; - var same = 0, - l = Math.min(prevInput.length, text.length); - while (same < l && prevInput[same] == text[same]) ++same; - if (same < prevInput.length) - sel.from = { - line: sel.from.line, - ch: sel.from.ch - (prevInput.length - same) - }; - else if (overwrite && posEq(sel.from, sel.to) && !pasteIncoming) - sel.to = { - line: sel.to.line, - ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same)) - }; - replaceSelection(text.slice(same), "end"); - if (text.length > 1000) { - input.value = prevInput = ""; - } else prevInput = text; - if (!nestedOperation) endOperation(); - pasteIncoming = false; - return true; - } - - function resetInput(user) { - if (!posEq(sel.from, sel.to)) { - prevInput = ""; - input.value = getSelection(); - if (focused) selectInput(input); - } else if (user) prevInput = input.value = ""; - } - - function focusInput() { - if (options.readOnly != "nocursor") input.focus(); - } - - function scrollCursorIntoView() { - var coords = calculateCursorCoords(); - scrollIntoView(coords.x, coords.y, coords.x, coords.yBot); - if (!focused) return; - var box = sizer.getBoundingClientRect(), - doScroll = null; - if (coords.y + box.top < 0) doScroll = true; - else if (coords.y + box.top + textHeight() > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; - if (doScroll != null) { - var hidden = cursor.style.display == "none"; - if (hidden) { - cursor.style.display = ""; - cursor.style.left = coords.x + "px"; - cursor.style.top = (coords.y - displayOffset) + "px"; - } - cursor.scrollIntoView(doScroll); - if (hidden) cursor.style.display = "none"; - } - } - - function calculateCursorCoords() { - var cursor = localCoords(sel.inverted ? sel.from : sel.to); - var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x; - return { - x: x, - y: cursor.y, - yBot: cursor.yBot - }; - } - - function scrollIntoView(x1, y1, x2, y2) { - var scrollPos = calculateScrollPos(x1, y1, x2, y2); - if (scrollPos.scrollLeft != null) { - scroller.scrollLeft = scrollPos.scrollLeft; - } - if (scrollPos.scrollTop != null) { - scrollbar.scrollTop = scroller.scrollTop = scrollPos.scrollTop; - } - } - - function calculateScrollPos(x1, y1, x2, y2) { - var pl = paddingLeft(), - pt = paddingTop(); - y1 += pt; - y2 += pt; - x1 += pl; - x2 += pl; - var screen = scroller.clientHeight, - screentop = scrollbar.scrollTop, - result = {}; - var docBottom = needsScrollbar() || Infinity; - var atTop = y1 < pt + 10, - atBottom = y2 + pt > docBottom - 10; - if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1); - else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen; - var screenw = scroller.clientWidth, - screenleft = scroller.scrollLeft; - var gutterw = options.fixedGutter ? gutter.clientWidth : 0; - var atLeft = x1 < gutterw + pl + 10; - if (x1 < screenleft + gutterw || atLeft) { - if (atLeft) x1 = 0; - result.scrollLeft = Math.max(0, x1 - 10 - gutterw); - } else if (x2 > screenw + screenleft - 3) { - result.scrollLeft = x2 + 10 - screenw; - } - return result; - } - - function visibleLines(scrollTop) { - var lh = textHeight(), - top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop(); - var fromHeight = Math.max(0, Math.floor(top / lh)); - var toHeight = Math.ceil((top + scroller.clientHeight) / lh); - return { - from: lineAtHeight(doc, fromHeight), - to: lineAtHeight(doc, toHeight) - }; - } - - function updateDisplay(changes, suppressCallback, scrollTop) { - if (!scroller.clientWidth) { - showingFrom = showingTo = displayOffset = 0; - return; - } - var visible = visibleLines(scrollTop); - if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) { - updateVerticalScroll(scrollTop); - return; - } - var from = Math.max(visible.from - 100, 0), - to = Math.min(doc.size, visible.to + 100); - if (showingFrom < from && from - showingFrom < 20) from = showingFrom; - if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo); - var intact = changes === true ? [] : computeIntact([{ + function updateDisplay(changes, suppressCallback, scrollTop) { + if (!scroller.clientWidth) { + showingFrom = showingTo = displayOffset = 0 + return + } + var visible = visibleLines(scrollTop) + if ( + changes !== true && + changes.length == 0 && + visible.from > showingFrom && + visible.to < showingTo + ) { + updateVerticalScroll(scrollTop) + return + } + var from = Math.max(visible.from - 100, 0), + to = Math.min(doc.size, visible.to + 100) + if (showingFrom < from && from - showingFrom < 20) from = showingFrom + if (showingTo > to && showingTo - to < 20) + to = Math.min(doc.size, showingTo) + var intact = + changes === true + ? [] + : computeIntact( + [ + { from: showingFrom, to: showingTo, domStart: 0 - }], changes); - var intactLines = 0; - for (var i = 0; i < intact.length; ++i) { - var range = intact[i]; - if (range.from < from) { - range.domStart += (from - range.from); - range.from = from; - } - if (range.to > to) range.to = to; - if (range.from >= range.to) intact.splice(i--, 1); - else intactLines += range.to - range.from; - } - if (intactLines == to - from && from == showingFrom && to == showingTo) { - updateVerticalScroll(scrollTop); - return; - } - intact.sort(function(a, b) { - return a.domStart - b.domStart; - }); - var th = textHeight(), - gutterDisplay = gutter.style.display; - lineDiv.style.display = "none"; - patchDisplay(from, to, intact); - lineDiv.style.display = gutter.style.display = ""; - var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th; - if (different) lastSizeC = scroller.clientHeight + th; - if (from != showingFrom || to != showingTo && options.onViewportChange) - setTimeout(function() { - if (options.onViewportChange) options.onViewportChange(instance, from, to); - }); - showingFrom = from; - showingTo = to; - displayOffset = heightAtLine(doc, from); - startWorker(100); - if (lineDiv.childNodes.length != showingTo - showingFrom) - throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) + " nodes=" + lineDiv.childNodes.length); + } + ], + changes + ) + var intactLines = 0 + for (var i = 0; i < intact.length; ++i) { + var range = intact[i] + if (range.from < from) { + range.domStart += from - range.from + range.from = from + } + if (range.to > to) range.to = to + if (range.from >= range.to) intact.splice(i--, 1) + else intactLines += range.to - range.from + } + if (intactLines == to - from && from == showingFrom && to == showingTo) { + updateVerticalScroll(scrollTop) + return + } + intact.sort(function(a, b) { + return a.domStart - b.domStart + }) + var th = textHeight(), + gutterDisplay = gutter.style.display + lineDiv.style.display = 'none' + patchDisplay(from, to, intact) + lineDiv.style.display = gutter.style.display = '' + var different = + from != showingFrom || + to != showingTo || + lastSizeC != scroller.clientHeight + th + if (different) lastSizeC = scroller.clientHeight + th + if (from != showingFrom || (to != showingTo && options.onViewportChange)) + setTimeout(function() { + if (options.onViewportChange) + options.onViewportChange(instance, from, to) + }) + showingFrom = from + showingTo = to + displayOffset = heightAtLine(doc, from) + startWorker(100) + if (lineDiv.childNodes.length != showingTo - showingFrom) + throw new Error( + 'BAD PATCH! ' + + JSON.stringify(intact) + + ' size=' + + (showingTo - showingFrom) + + ' nodes=' + + lineDiv.childNodes.length + ) - function checkHeights() { - var curNode = lineDiv.firstChild, - heightChanged = false; - doc.iter(showingFrom, showingTo, function(line) { - if (!curNode) return; - if (!line.hidden) { - var height = Math.round(curNode.offsetHeight / th) || 1; - if (line.height != height) { - updateLineHeight(line, height); - gutterDirty = heightChanged = true; - } - } - curNode = curNode.nextSibling; - }); - return heightChanged; - } - if (options.lineWrapping) checkHeights(); - gutter.style.display = gutterDisplay; - if (different || gutterDirty) { - updateGutter() && options.lineWrapping && checkHeights() && updateGutter(); - } - updateVerticalScroll(scrollTop); - updateSelection(); - if (!suppressCallback && options.onUpdate) options.onUpdate(instance); - return true; + function checkHeights() { + var curNode = lineDiv.firstChild, + heightChanged = false + doc.iter(showingFrom, showingTo, function(line) { + if (!curNode) return + if (!line.hidden) { + var height = Math.round(curNode.offsetHeight / th) || 1 + if (line.height != height) { + updateLineHeight(line, height) + gutterDirty = heightChanged = true + } } + curNode = curNode.nextSibling + }) + return heightChanged + } + if (options.lineWrapping) checkHeights() + gutter.style.display = gutterDisplay + if (different || gutterDirty) { + updateGutter() && options.lineWrapping && checkHeights() && updateGutter() + } + updateVerticalScroll(scrollTop) + updateSelection() + if (!suppressCallback && options.onUpdate) options.onUpdate(instance) + return true + } - function computeIntact(intact, changes) { - for (var i = 0, l = changes.length || 0; i < l; ++i) { - var change = changes[i], - intact2 = [], - diff = change.diff || 0; - for (var j = 0, l2 = intact.length; j < l2; ++j) { - var range = intact[j]; - if (change.to <= range.from && change.diff) - intact2.push({ - from: range.from + diff, - to: range.to + diff, - domStart: range.domStart - }); - else if (change.to <= range.from || change.from >= range.to) - intact2.push(range); - else { - if (change.from > range.from) - intact2.push({ - from: range.from, - to: change.from, - domStart: range.domStart - }); - if (change.to < range.to) - intact2.push({ - from: change.to + diff, - to: range.to + diff, - domStart: range.domStart + (change.to - range.from) - }); - } - } - intact = intact2; - } - return intact; + function computeIntact(intact, changes) { + for (var i = 0, l = changes.length || 0; i < l; ++i) { + var change = changes[i], + intact2 = [], + diff = change.diff || 0 + for (var j = 0, l2 = intact.length; j < l2; ++j) { + var range = intact[j] + if (change.to <= range.from && change.diff) + intact2.push({ + from: range.from + diff, + to: range.to + diff, + domStart: range.domStart + }) + else if (change.to <= range.from || change.from >= range.to) + intact2.push(range) + else { + if (change.from > range.from) + intact2.push({ + from: range.from, + to: change.from, + domStart: range.domStart + }) + if (change.to < range.to) + intact2.push({ + from: change.to + diff, + to: range.to + diff, + domStart: range.domStart + (change.to - range.from) + }) } + } + intact = intact2 + } + return intact + } - function patchDisplay(from, to, intact) { - function killNode(node) { - var tmp = node.nextSibling; - node.parentNode.removeChild(node); - return tmp; - } - if (!intact.length) removeChildren(lineDiv); - else { - var domPos = 0, - curNode = lineDiv.firstChild, - n; - for (var i = 0; i < intact.length; ++i) { - var cur = intact[i]; - while (cur.domStart > domPos) { - curNode = killNode(curNode); - domPos++; - } - for (var j = 0, e = cur.to - cur.from; j < e; ++j) { - curNode = curNode.nextSibling; - domPos++; - } - } - while (curNode) curNode = killNode(curNode); - } - var nextIntact = intact.shift(), - curNode = lineDiv.firstChild, - j = from; - doc.iter(from, to, function(line) { - if (nextIntact && nextIntact.to == j) nextIntact = intact.shift(); - if (!nextIntact || nextIntact.from > j) { - if (line.hidden) var lineElement = elt("pre"); - else { - var lineElement = lineContent(line); - if (line.className) lineElement.className = line.className; - if (line.bgClassName) { - var pre = elt("pre", "\u00a0", line.bgClassName, "position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2"); - lineElement = elt("div", [pre, lineElement], null, "position: relative"); - } - } - lineDiv.insertBefore(lineElement, curNode); - } else { - curNode = curNode.nextSibling; - } - ++j; - }); + function patchDisplay(from, to, intact) { + function killNode(node) { + var tmp = node.nextSibling + node.parentNode.removeChild(node) + return tmp + } + if (!intact.length) removeChildren(lineDiv) + else { + var domPos = 0, + curNode = lineDiv.firstChild, + n + for (var i = 0; i < intact.length; ++i) { + var cur = intact[i] + while (cur.domStart > domPos) { + curNode = killNode(curNode) + domPos++ } - - function updateGutter() { - if (!options.gutter && !options.lineNumbers) return; - var hText = mover.offsetHeight, - hEditor = scroller.clientHeight; - gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px"; - var fragment = document.createDocumentFragment(), - i = showingFrom, - normalNode; - doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) { - if (line.hidden) { - fragment.appendChild(elt("pre")); - } else { - var marker = line.gutterMarker; - var text = options.lineNumbers ? options.lineNumberFormatter(i + options.firstLineNumber) : null; - if (marker && marker.text) - text = marker.text.replace("%N%", text != null ? text : ""); - else if (text == null) - text = "\u00a0"; - var markerElement = fragment.appendChild(elt("pre", null, marker && marker.style)); - markerElement.innerHTML = text; - for (var j = 1; j < line.height; ++j) { - markerElement.appendChild(elt("br")); - markerElement.appendChild(document.createTextNode("\u00a0")); - } - if (!marker) normalNode = i; - } - ++i; - }); - gutter.style.display = "none"; - removeChildrenAndAdd(gutterText, fragment); - if (normalNode != null && options.lineNumbers) { - var node = gutterText.childNodes[normalNode - showingFrom]; - var minwidth = String(doc.size).length, - val = eltText(node.firstChild), - pad = ""; - while (val.length + pad.length < minwidth) pad += "\u00a0"; - if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild); - } - gutter.style.display = ""; - var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2; - lineSpace.style.marginLeft = gutter.offsetWidth + "px"; - gutterDirty = false; - return resized; + for (var j = 0, e = cur.to - cur.from; j < e; ++j) { + curNode = curNode.nextSibling + domPos++ } - - function updateSelection() { - var collapsed = posEq(sel.from, sel.to); - var fromPos = localCoords(sel.from, true); - var toPos = collapsed ? fromPos : localCoords(sel.to, true); - var headPos = sel.inverted ? fromPos : toPos, - th = textHeight(); - var wrapOff = eltOffset(wrapper), - lineOff = eltOffset(lineDiv); - inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + "px"; - inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + "px"; - if (collapsed) { - cursor.style.top = headPos.y + "px"; - cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + "px"; - cursor.style.display = ""; - selectionDiv.style.display = "none"; - } else { - var sameLine = fromPos.y == toPos.y, - fragment = document.createDocumentFragment(); - var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth; - var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight; - var add = function(left, top, right, height) { - var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px" : "right: " + right + "px"; - fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + "px; top: " + top + "px; " + rstyle + "; height: " + height + "px")); - }; - if (sel.from.ch && fromPos.y >= 0) { - var right = sameLine ? clientWidth - toPos.x : 0; - add(fromPos.x, fromPos.y, right, th); - } - var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0)); - var middleHeight = Math.min(toPos.y, clientHeight) - middleStart; - if (middleHeight > 0.2 * th) - add(0, middleStart, 0, middleHeight); - if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th) - add(0, toPos.y, clientWidth - toPos.x, th); - removeChildrenAndAdd(selectionDiv, fragment); - cursor.style.display = "none"; - selectionDiv.style.display = ""; - } + } + while (curNode) curNode = killNode(curNode) + } + var nextIntact = intact.shift(), + curNode = lineDiv.firstChild, + j = from + doc.iter(from, to, function(line) { + if (nextIntact && nextIntact.to == j) nextIntact = intact.shift() + if (!nextIntact || nextIntact.from > j) { + if (line.hidden) var lineElement = elt('pre') + else { + var lineElement = lineContent(line) + if (line.className) lineElement.className = line.className + if (line.bgClassName) { + var pre = elt( + 'pre', + '\u00a0', + line.bgClassName, + 'position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2' + ) + lineElement = elt( + 'div', + [pre, lineElement], + null, + 'position: relative' + ) + } } + lineDiv.insertBefore(lineElement, curNode) + } else { + curNode = curNode.nextSibling + } + ++j + }) + } - function setShift(val) { - if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from); - else shiftSelecting = null; + function updateGutter() { + if (!options.gutter && !options.lineNumbers) return + var hText = mover.offsetHeight, + hEditor = scroller.clientHeight + gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + 'px' + var fragment = document.createDocumentFragment(), + i = showingFrom, + normalNode + doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) { + if (line.hidden) { + fragment.appendChild(elt('pre')) + } else { + var marker = line.gutterMarker + var text = options.lineNumbers + ? options.lineNumberFormatter(i + options.firstLineNumber) + : null + if (marker && marker.text) + text = marker.text.replace('%N%', text != null ? text : '') + else if (text == null) text = '\u00a0' + var markerElement = fragment.appendChild( + elt('pre', null, marker && marker.style) + ) + markerElement.innerHTML = text + for (var j = 1; j < line.height; ++j) { + markerElement.appendChild(elt('br')) + markerElement.appendChild(document.createTextNode('\u00a0')) } + if (!marker) normalNode = i + } + ++i + }) + gutter.style.display = 'none' + removeChildrenAndAdd(gutterText, fragment) + if (normalNode != null && options.lineNumbers) { + var node = gutterText.childNodes[normalNode - showingFrom] + var minwidth = String(doc.size).length, + val = eltText(node.firstChild), + pad = '' + while (val.length + pad.length < minwidth) pad += '\u00a0' + if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild) + } + gutter.style.display = '' + var resized = + Math.abs( + (parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth + ) > 2 + lineSpace.style.marginLeft = gutter.offsetWidth + 'px' + gutterDirty = false + return resized + } - function setSelectionUser(from, to) { - var sh = shiftSelecting && clipPos(shiftSelecting); - if (sh) { - if (posLess(sh, from)) from = sh; - else if (posLess(to, sh)) to = sh; - } - setSelection(from, to); - userSelChange = true; - } + function updateSelection() { + var collapsed = posEq(sel.from, sel.to) + var fromPos = localCoords(sel.from, true) + var toPos = collapsed ? fromPos : localCoords(sel.to, true) + var headPos = sel.inverted ? fromPos : toPos, + th = textHeight() + var wrapOff = eltOffset(wrapper), + lineOff = eltOffset(lineDiv) + inputDiv.style.top = + Math.max( + 0, + Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top) + ) + 'px' + inputDiv.style.left = + Math.max( + 0, + Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left) + ) + 'px' + if (collapsed) { + cursor.style.top = headPos.y + 'px' + cursor.style.left = + (options.lineWrapping + ? Math.min(headPos.x, lineSpace.offsetWidth) + : headPos.x) + 'px' + cursor.style.display = '' + selectionDiv.style.display = 'none' + } else { + var sameLine = fromPos.y == toPos.y, + fragment = document.createDocumentFragment() + var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth + var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight + var add = function(left, top, right, height) { + var rstyle = quirksMode + ? 'width: ' + + (!right ? clientWidth : clientWidth - right - left) + + 'px' + : 'right: ' + right + 'px' + fragment.appendChild( + elt( + 'div', + null, + 'CodeMirror-selected', + 'position: absolute; left: ' + + left + + 'px; top: ' + + top + + 'px; ' + + rstyle + + '; height: ' + + height + + 'px' + ) + ) + } + if (sel.from.ch && fromPos.y >= 0) { + var right = sameLine ? clientWidth - toPos.x : 0 + add(fromPos.x, fromPos.y, right, th) + } + var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0)) + var middleHeight = Math.min(toPos.y, clientHeight) - middleStart + if (middleHeight > 0.2 * th) add(0, middleStart, 0, middleHeight) + if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - 0.5 * th) + add(0, toPos.y, clientWidth - toPos.x, th) + removeChildrenAndAdd(selectionDiv, fragment) + cursor.style.display = 'none' + selectionDiv.style.display = '' + } + } - function setSelection(from, to, oldFrom, oldTo) { - goalColumn = null; - if (oldFrom == null) { - oldFrom = sel.from.line; - oldTo = sel.to.line; - } - if (posEq(sel.from, from) && posEq(sel.to, to)) return; - if (posLess(to, from)) { - var tmp = to; - to = from; - from = tmp; - } - if (from.line != oldFrom) { - var from1 = skipHidden(from, oldFrom, sel.from.ch); - if (!from1) setLineHidden(from.line, false); - else from = from1; - } - if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch); - if (posEq(from, to)) sel.inverted = false; - else if (posEq(from, sel.to)) sel.inverted = false; - else if (posEq(to, sel.from)) sel.inverted = true; - if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) { - var head = sel.inverted ? from : to; - if (head.line != sel.from.line && sel.from.line < doc.size) { - var oldLine = getLine(sel.from.line); - if (/^\s+$/.test(oldLine.text)) - setTimeout(operation(function() { - if (oldLine.parent && /^\s+$/.test(oldLine.text)) { - var no = lineNo(oldLine); - replaceRange("", { - line: no, - ch: 0 - }, { - line: no, - ch: oldLine.text.length - }); - } - }, 10)); - } - } - sel.from = from; - sel.to = to; - selectionChanged = true; - } + function setShift(val) { + if (val) + shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from) + else shiftSelecting = null + } - function skipHidden(pos, oldLine, oldCh) { - function getNonHidden(dir) { - var lNo = pos.line + dir, - end = dir == 1 ? doc.size : -1; - while (lNo != end) { - var line = getLine(lNo); - if (!line.hidden) { - var ch = pos.ch; - if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length; - return { - line: lNo, - ch: ch - }; - } - lNo += dir; - } - } - var line = getLine(pos.line); - var toEnd = pos.ch == line.text.length && pos.ch != oldCh; - if (!line.hidden) return pos; - if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1); - else return getNonHidden(-1) || getNonHidden(1); - } + function setSelectionUser(from, to) { + var sh = shiftSelecting && clipPos(shiftSelecting) + if (sh) { + if (posLess(sh, from)) from = sh + else if (posLess(to, sh)) to = sh + } + setSelection(from, to) + userSelChange = true + } - function setCursor(line, ch, user) { - var pos = clipPos({ - line: line, - ch: ch || 0 - }); - (user ? setSelectionUser : setSelection)(pos, pos); - } - - function clipLine(n) { - return Math.max(0, Math.min(n, doc.size - 1)); - } - - function clipPos(pos) { - if (pos.line < 0) return { - line: 0, - ch: 0 - }; - if (pos.line >= doc.size) return { - line: doc.size - 1, - ch: getLine(doc.size - 1).text.length - }; - var ch = pos.ch, - linelen = getLine(pos.line).text.length; - if (ch == null || ch > linelen) return { - line: pos.line, - ch: linelen - }; - else if (ch < 0) return { - line: pos.line, - ch: 0 - }; - else return pos; - } - - function findPosH(dir, unit) { - var end = sel.inverted ? sel.from : sel.to, - line = end.line, - ch = end.ch; - var lineObj = getLine(line); - - function findNextLine() { - for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) { - var lo = getLine(l); - if (!lo.hidden) { - line = l; - lineObj = lo; - return true; - } - } - } - - function moveOnce(boundToLine) { - if (ch == (dir < 0 ? 0 : lineObj.text.length)) { - if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0; - else return false; - } else ch += dir; - return true; - } - if (unit == "char") moveOnce(); - else if (unit == "column") moveOnce(true); - else if (unit == "word") { - var sawWord = false; - for (;;) { - if (dir < 0) - if (!moveOnce()) break; - if (isWordChar(lineObj.text.charAt(ch))) sawWord = true; - else if (sawWord) { - if (dir < 0) { - dir = 1; - moveOnce(); - } - break; - } - if (dir > 0) - if (!moveOnce()) break; - } - } - return { - line: line, - ch: ch - }; - } - - function moveH(dir, unit) { - var pos = dir < 0 ? sel.from : sel.to; - if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit); - setCursor(pos.line, pos.ch, true); - } - - function deleteH(dir, unit) { - if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to); - else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to); - else replaceRange("", sel.from, findPosH(dir, unit)); - userSelChange = true; - } - - function moveV(dir, unit) { - var dist = 0, - pos = localCoords(sel.inverted ? sel.from : sel.to, true); - if (goalColumn != null) pos.x = goalColumn; - if (unit == "page") { - var screen = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight); - var target = coordsChar(pos.x, pos.y + screen * dir); - } else if (unit == "line") { - var th = textHeight(); - var target = coordsChar(pos.x, pos.y + .5 * th + dir * th); - } - if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y; - setCursor(target.line, target.ch, true); - goalColumn = pos.x; - } - - function findWordAt(pos) { - var line = getLine(pos.line).text; - var start = pos.ch, - end = pos.ch; - if (line) { - if (pos.after === false || end == line.length) --start; - else ++end; - var startChar = line.charAt(start); - var check = isWordChar(startChar) ? isWordChar : /\s/.test(startChar) ? function(ch) { - return /\s/.test(ch); - } : function(ch) { - return !/\s/.test(ch) && isWordChar(ch); - }; - while (start > 0 && check(line.charAt(start - 1))) --start; - while (end < line.length && check(line.charAt(end))) ++end; - } - return { - from: { - line: pos.line, - ch: start - }, - to: { - line: pos.line, - ch: end - } - }; - } - - function selectLine(line) { - setSelectionUser({ - line: line, - ch: 0 - }, clipPos({ - line: line + 1, - ch: 0 - })); - } - - function indentSelected(mode) { - if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode); - var e = sel.to.line - (sel.to.ch ? 0 : 1); - for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode); - } - - function indentLine(n, how) { - if (!how) how = "add"; - if (how == "smart") { - if (!mode.indent) how = "prev"; - else var state = getStateBefore(n); - } - var line = getLine(n), - curSpace = line.indentation(options.tabSize), - curSpaceString = line.text.match(/^\s*/)[0], - indentation; - if (how == "smart") { - indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text); - if (indentation == Pass) how = "prev"; - } - if (how == "prev") { - if (n) indentation = getLine(n - 1).indentation(options.tabSize); - else indentation = 0; - } else if (how == "add") indentation = curSpace + options.indentUnit; - else if (how == "subtract") indentation = curSpace - options.indentUnit; - indentation = Math.max(0, indentation); - var diff = indentation - curSpace; - var indentString = "", - pos = 0; - if (options.indentWithTabs) - for (var i = Math.floor(indentation / options.tabSize); i; --i) { - pos += options.tabSize; - indentString += "\t"; - } - if (pos < indentation) indentString += spaceStr(indentation - pos); - if (indentString != curSpaceString) - replaceRange(indentString, { - line: n, + function setSelection(from, to, oldFrom, oldTo) { + goalColumn = null + if (oldFrom == null) { + oldFrom = sel.from.line + oldTo = sel.to.line + } + if (posEq(sel.from, from) && posEq(sel.to, to)) return + if (posLess(to, from)) { + var tmp = to + to = from + from = tmp + } + if (from.line != oldFrom) { + var from1 = skipHidden(from, oldFrom, sel.from.ch) + if (!from1) setLineHidden(from.line, false) + else from = from1 + } + if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch) + if (posEq(from, to)) sel.inverted = false + else if (posEq(from, sel.to)) sel.inverted = false + else if (posEq(to, sel.from)) sel.inverted = true + if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) { + var head = sel.inverted ? from : to + if (head.line != sel.from.line && sel.from.line < doc.size) { + var oldLine = getLine(sel.from.line) + if (/^\s+$/.test(oldLine.text)) + setTimeout( + operation(function() { + if (oldLine.parent && /^\s+$/.test(oldLine.text)) { + var no = lineNo(oldLine) + replaceRange( + '', + { + line: no, ch: 0 - }, { - line: n, - ch: curSpaceString.length - }); - line.stateAfter = null; - } + }, + { + line: no, + ch: oldLine.text.length + } + ) + } + }, 10) + ) + } + } + sel.from = from + sel.to = to + selectionChanged = true + } - function loadMode() { - mode = CodeMirror.getMode(options, options.mode); - doc.iter(0, doc.size, function(line) { - line.stateAfter = null; - }); - frontier = 0; - startWorker(100); + function skipHidden(pos, oldLine, oldCh) { + function getNonHidden(dir) { + var lNo = pos.line + dir, + end = dir == 1 ? doc.size : -1 + while (lNo != end) { + var line = getLine(lNo) + if (!line.hidden) { + var ch = pos.ch + if (toEnd || ch > oldCh || ch > line.text.length) + ch = line.text.length + return { + line: lNo, + ch: ch + } } + lNo += dir + } + } + var line = getLine(pos.line) + var toEnd = pos.ch == line.text.length && pos.ch != oldCh + if (!line.hidden) return pos + if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1) + else return getNonHidden(-1) || getNonHidden(1) + } - function gutterChanged() { - var visible = options.gutter || options.lineNumbers; - gutter.style.display = visible ? "" : "none"; - if (visible) gutterDirty = true; - else lineDiv.parentNode.style.marginLeft = 0; + function setCursor(line, ch, user) { + var pos = clipPos({ + line: line, + ch: ch || 0 + }) + ;(user ? setSelectionUser : setSelection)(pos, pos) + } + + function clipLine(n) { + return Math.max(0, Math.min(n, doc.size - 1)) + } + + function clipPos(pos) { + if (pos.line < 0) + return { + line: 0, + ch: 0 + } + if (pos.line >= doc.size) + return { + line: doc.size - 1, + ch: getLine(doc.size - 1).text.length + } + var ch = pos.ch, + linelen = getLine(pos.line).text.length + if (ch == null || ch > linelen) + return { + line: pos.line, + ch: linelen + } + else if (ch < 0) + return { + line: pos.line, + ch: 0 + } + else return pos + } + + function findPosH(dir, unit) { + var end = sel.inverted ? sel.from : sel.to, + line = end.line, + ch = end.ch + var lineObj = getLine(line) + + function findNextLine() { + for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) { + var lo = getLine(l) + if (!lo.hidden) { + line = l + lineObj = lo + return true } + } + } - function wrappingChanged(from, to) { - if (options.lineWrapping) { - wrapper.className += " CodeMirror-wrap"; - var perLine = scroller.clientWidth / charWidth() - 3; - doc.iter(0, doc.size, function(line) { - if (line.hidden) return; - var guess = Math.ceil(line.text.length / perLine) || 1; - if (guess != 1) updateLineHeight(line, guess); - }); - lineSpace.style.minWidth = widthForcer.style.left = ""; - } else { - wrapper.className = wrapper.className.replace(" CodeMirror-wrap", ""); - computeMaxLength(); - doc.iter(0, doc.size, function(line) { - if (line.height != 1 && !line.hidden) updateLineHeight(line, 1); - }); + function moveOnce(boundToLine) { + if (ch == (dir < 0 ? 0 : lineObj.text.length)) { + if (!boundToLine && findNextLine()) + ch = dir < 0 ? lineObj.text.length : 0 + else return false + } else ch += dir + return true + } + if (unit == 'char') moveOnce() + else if (unit == 'column') moveOnce(true) + else if (unit == 'word') { + var sawWord = false + for (;;) { + if (dir < 0) if (!moveOnce()) break + if (isWordChar(lineObj.text.charAt(ch))) sawWord = true + else if (sawWord) { + if (dir < 0) { + dir = 1 + moveOnce() + } + break + } + if (dir > 0) if (!moveOnce()) break + } + } + return { + line: line, + ch: ch + } + } + + function moveH(dir, unit) { + var pos = dir < 0 ? sel.from : sel.to + if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit) + setCursor(pos.line, pos.ch, true) + } + + function deleteH(dir, unit) { + if (!posEq(sel.from, sel.to)) replaceRange('', sel.from, sel.to) + else if (dir < 0) replaceRange('', findPosH(dir, unit), sel.to) + else replaceRange('', sel.from, findPosH(dir, unit)) + userSelChange = true + } + + function moveV(dir, unit) { + var dist = 0, + pos = localCoords(sel.inverted ? sel.from : sel.to, true) + if (goalColumn != null) pos.x = goalColumn + if (unit == 'page') { + var screen = Math.min( + scroller.clientHeight, + window.innerHeight || document.documentElement.clientHeight + ) + var target = coordsChar(pos.x, pos.y + screen * dir) + } else if (unit == 'line') { + var th = textHeight() + var target = coordsChar(pos.x, pos.y + 0.5 * th + dir * th) + } + if (unit == 'page') + scrollbar.scrollTop += localCoords(target, true).y - pos.y + setCursor(target.line, target.ch, true) + goalColumn = pos.x + } + + function findWordAt(pos) { + var line = getLine(pos.line).text + var start = pos.ch, + end = pos.ch + if (line) { + if (pos.after === false || end == line.length) --start + else ++end + var startChar = line.charAt(start) + var check = isWordChar(startChar) + ? isWordChar + : /\s/.test(startChar) + ? function(ch) { + return /\s/.test(ch) } - changes.push({ - from: 0, - to: doc.size - }); - } - - function themeChanged() { - scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") + - options.theme.replace(/(^|\s)\s*/g, " cm-s-"); - } - - function keyMapChanged() { - var style = keyMap[options.keyMap].style; - wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + - (style ? " cm-keymap-" + style : ""); - } - - function TextMarker(type, style) { - this.lines = []; - this.type = type; - if (style) this.style = style; - } - TextMarker.prototype.clear = operation(function() { - var min, max; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (span.from != null) min = lineNo(line); - if (span.to != null) max = lineNo(line); - line.markedSpans = removeMarkedSpan(line.markedSpans, span); + : function(ch) { + return !/\s/.test(ch) && isWordChar(ch) } - if (min != null) changes.push({ - from: min, - to: max + 1 - }); - this.lines.length = 0; - this.explicitlyCleared = true; - }); - TextMarker.prototype.find = function() { - var from, to; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (span.from != null || span.to != null) { - var found = lineNo(line); - if (span.from != null) from = { - line: found, - ch: span.from - }; - if (span.to != null) to = { - line: found, - ch: span.to - }; - } - } - if (this.type == "bookmark") return from; - return from && { - from: from, - to: to - }; - }; + while (start > 0 && check(line.charAt(start - 1))) --start + while (end < line.length && check(line.charAt(end))) ++end + } + return { + from: { + line: pos.line, + ch: start + }, + to: { + line: pos.line, + ch: end + } + } + } - function markText(from, to, className, options) { - from = clipPos(from); - to = clipPos(to); - var marker = new TextMarker("range", className); - if (options) - for (var opt in options) - if (options.hasOwnProperty(opt)) - marker[opt] = options[opt]; - var curLine = from.line; - doc.iter(curLine, to.line + 1, function(line) { - var span = { - from: curLine == from.line ? from.ch : null, - to: curLine == to.line ? to.ch : null, - marker: marker - }; - line.markedSpans = (line.markedSpans || []).concat([span]); - marker.lines.push(line); - ++curLine; - }); - changes.push({ - from: from.line, - to: to.line + 1 - }); - return marker; + function selectLine(line) { + setSelectionUser( + { + line: line, + ch: 0 + }, + clipPos({ + line: line + 1, + ch: 0 + }) + ) + } + + function indentSelected(mode) { + if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode) + var e = sel.to.line - (sel.to.ch ? 0 : 1) + for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode) + } + + function indentLine(n, how) { + if (!how) how = 'add' + if (how == 'smart') { + if (!mode.indent) how = 'prev' + else var state = getStateBefore(n) + } + var line = getLine(n), + curSpace = line.indentation(options.tabSize), + curSpaceString = line.text.match(/^\s*/)[0], + indentation + if (how == 'smart') { + indentation = mode.indent( + state, + line.text.slice(curSpaceString.length), + line.text + ) + if (indentation == Pass) how = 'prev' + } + if (how == 'prev') { + if (n) indentation = getLine(n - 1).indentation(options.tabSize) + else indentation = 0 + } else if (how == 'add') indentation = curSpace + options.indentUnit + else if (how == 'subtract') indentation = curSpace - options.indentUnit + indentation = Math.max(0, indentation) + var diff = indentation - curSpace + var indentString = '', + pos = 0 + if (options.indentWithTabs) + for (var i = Math.floor(indentation / options.tabSize); i; --i) { + pos += options.tabSize + indentString += '\t' + } + if (pos < indentation) indentString += spaceStr(indentation - pos) + if (indentString != curSpaceString) + replaceRange( + indentString, + { + line: n, + ch: 0 + }, + { + line: n, + ch: curSpaceString.length } + ) + line.stateAfter = null + } - function setBookmark(pos) { - pos = clipPos(pos); - var marker = new TextMarker("bookmark"), - line = getLine(pos.line); - history.addChange(pos.line, 1, [newHL(line.text, line.markedSpans)], true); - var span = { - from: pos.ch, - to: pos.ch, - marker: marker - }; - line.markedSpans = (line.markedSpans || []).concat([span]); - marker.lines.push(line); - return marker; + function loadMode() { + mode = CodeMirror.getMode(options, options.mode) + doc.iter(0, doc.size, function(line) { + line.stateAfter = null + }) + frontier = 0 + startWorker(100) + } + + function gutterChanged() { + var visible = options.gutter || options.lineNumbers + gutter.style.display = visible ? '' : 'none' + if (visible) gutterDirty = true + else lineDiv.parentNode.style.marginLeft = 0 + } + + function wrappingChanged(from, to) { + if (options.lineWrapping) { + wrapper.className += ' CodeMirror-wrap' + var perLine = scroller.clientWidth / charWidth() - 3 + doc.iter(0, doc.size, function(line) { + if (line.hidden) return + var guess = Math.ceil(line.text.length / perLine) || 1 + if (guess != 1) updateLineHeight(line, guess) + }) + lineSpace.style.minWidth = widthForcer.style.left = '' + } else { + wrapper.className = wrapper.className.replace(' CodeMirror-wrap', '') + computeMaxLength() + doc.iter(0, doc.size, function(line) { + if (line.height != 1 && !line.hidden) updateLineHeight(line, 1) + }) + } + changes.push({ + from: 0, + to: doc.size + }) + } + + function themeChanged() { + scroller.className = + scroller.className.replace(/\s*cm-s-\S+/g, '') + + options.theme.replace(/(^|\s)\s*/g, ' cm-s-') + } + + function keyMapChanged() { + var style = keyMap[options.keyMap].style + wrapper.className = + wrapper.className.replace(/\s*cm-keymap-\S+/g, '') + + (style ? ' cm-keymap-' + style : '') + } + + function TextMarker(type, style) { + this.lines = [] + this.type = type + if (style) this.style = style + } + TextMarker.prototype.clear = operation(function() { + var min, max + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i] + var span = getMarkedSpanFor(line.markedSpans, this) + if (span.from != null) min = lineNo(line) + if (span.to != null) max = lineNo(line) + line.markedSpans = removeMarkedSpan(line.markedSpans, span) + } + if (min != null) + changes.push({ + from: min, + to: max + 1 + }) + this.lines.length = 0 + this.explicitlyCleared = true + }) + TextMarker.prototype.find = function() { + var from, to + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i] + var span = getMarkedSpanFor(line.markedSpans, this) + if (span.from != null || span.to != null) { + var found = lineNo(line) + if (span.from != null) + from = { + line: found, + ch: span.from + } + if (span.to != null) + to = { + line: found, + ch: span.to + } + } + } + if (this.type == 'bookmark') return from + return ( + from && { + from: from, + to: to + } + ) + } + + function markText(from, to, className, options) { + from = clipPos(from) + to = clipPos(to) + var marker = new TextMarker('range', className) + if (options) + for (var opt in options) + if (options.hasOwnProperty(opt)) marker[opt] = options[opt] + var curLine = from.line + doc.iter(curLine, to.line + 1, function(line) { + var span = { + from: curLine == from.line ? from.ch : null, + to: curLine == to.line ? to.ch : null, + marker: marker + } + line.markedSpans = (line.markedSpans || []).concat([span]) + marker.lines.push(line) + ++curLine + }) + changes.push({ + from: from.line, + to: to.line + 1 + }) + return marker + } + + function setBookmark(pos) { + pos = clipPos(pos) + var marker = new TextMarker('bookmark'), + line = getLine(pos.line) + history.addChange(pos.line, 1, [newHL(line.text, line.markedSpans)], true) + var span = { + from: pos.ch, + to: pos.ch, + marker: marker + } + line.markedSpans = (line.markedSpans || []).concat([span]) + marker.lines.push(line) + return marker + } + + function findMarksAt(pos) { + pos = clipPos(pos) + var markers = [], + spans = getLine(pos.line).markedSpans + if (spans) + for (var i = 0; i < spans.length; ++i) { + var span = spans[i] + if ( + (span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch) + ) + markers.push(span.marker) + } + return markers + } + + function addGutterMarker(line, text, className) { + if (typeof line == 'number') line = getLine(clipLine(line)) + line.gutterMarker = { + text: text, + style: className + } + gutterDirty = true + return line + } + + function removeGutterMarker(line) { + if (typeof line == 'number') line = getLine(clipLine(line)) + line.gutterMarker = null + gutterDirty = true + } + + function changeLine(handle, op) { + var no = handle, + line = handle + if (typeof handle == 'number') line = getLine(clipLine(handle)) + else no = lineNo(handle) + if (no == null) return null + if (op(line, no)) + changes.push({ + from: no, + to: no + 1 + }) + else return null + return line + } + + function setLineClass(handle, className, bgClassName) { + return changeLine(handle, function(line) { + if (line.className != className || line.bgClassName != bgClassName) { + line.className = className + line.bgClassName = bgClassName + return true + } + }) + } + + function setLineHidden(handle, hidden) { + return changeLine(handle, function(line, no) { + if (line.hidden != hidden) { + line.hidden = hidden + if (!options.lineWrapping) { + if (hidden && line.text.length == maxLine.text.length) { + updateMaxLine = true + } else if (!hidden && line.text.length > maxLine.text.length) { + maxLine = line + updateMaxLine = false + } } - - function findMarksAt(pos) { - pos = clipPos(pos); - var markers = [], - spans = getLine(pos.line).markedSpans; - if (spans) - for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if ((span.from == null || span.from <= pos.ch) && (span.to == null || span.to >= pos.ch)) - markers.push(span.marker); - } - return markers; + updateLineHeight(line, hidden ? 0 : 1) + var fline = sel.from.line, + tline = sel.to.line + if (hidden && (fline == no || tline == no)) { + var from = + fline == no + ? skipHidden( + { + line: fline, + ch: 0 + }, + fline, + 0 + ) + : sel.from + var to = + tline == no + ? skipHidden( + { + line: tline, + ch: 0 + }, + tline, + 0 + ) + : sel.to + if (!to) return + setSelection(from, to) } + return (gutterDirty = true) + } + }) + } - function addGutterMarker(line, text, className) { - if (typeof line == "number") line = getLine(clipLine(line)); - line.gutterMarker = { - text: text, - style: className - }; - gutterDirty = true; - return line; + function lineInfo(line) { + if (typeof line == 'number') { + if (!isLine(line)) return null + var n = line + line = getLine(line) + if (!line) return null + } else { + var n = lineNo(line) + if (n == null) return null + } + var marker = line.gutterMarker + return { + line: n, + handle: line, + text: line.text, + markerText: marker && marker.text, + markerClass: marker && marker.style, + lineClass: line.className, + bgClass: line.bgClassName + } + } + + function measureLine(line, ch) { + if (ch == 0) + return { + top: 0, + left: 0 + } + var pre = lineContent(line, ch) + removeChildrenAndAdd(measure, pre) + var anchor = pre.anchor + var top = anchor.offsetTop, + left = anchor.offsetLeft + if (ie && top == 0 && left == 0) { + var backup = elt('span', 'x') + anchor.parentNode.insertBefore(backup, anchor.nextSibling) + top = backup.offsetTop + } + return { + top: top, + left: left + } + } + + function localCoords(pos, inLineWrap) { + var x, + lh = textHeight(), + y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0)) + if (pos.ch == 0) x = 0 + else { + var sp = measureLine(getLine(pos.line), pos.ch) + x = sp.left + if (options.lineWrapping) y += Math.max(0, sp.top) + } + return { + x: x, + y: y, + yBot: y + lh + } + } + + function coordsChar(x, y) { + var th = textHeight(), + cw = charWidth(), + heightPos = displayOffset + Math.floor(y / th) + if (heightPos < 0) + return { + line: 0, + ch: 0 + } + var lineNo = lineAtHeight(doc, heightPos) + if (lineNo >= doc.size) + return { + line: doc.size - 1, + ch: getLine(doc.size - 1).text.length + } + var lineObj = getLine(lineNo), + text = lineObj.text + var tw = options.lineWrapping, + innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0 + if (x <= 0 && innerOff == 0) + return { + line: lineNo, + ch: 0 + } + var wrongLine = false + + function getX(len) { + var sp = measureLine(lineObj, len) + if (tw) { + var off = Math.round(sp.top / th) + wrongLine = off != innerOff + return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth) + } + return sp.left + } + var from = 0, + fromX = 0, + to = text.length, + toX + var estimated = Math.min( + to, + Math.ceil((x + innerOff * scroller.clientWidth * 0.9) / cw) + ) + for (;;) { + var estX = getX(estimated) + if (estX <= x && estimated < to) + estimated = Math.min(to, Math.ceil(estimated * 1.2)) + else { + toX = estX + to = estimated + break + } + } + if (x > toX) + return { + line: lineNo, + ch: to + } + estimated = Math.floor(to * 0.8) + estX = getX(estimated) + if (estX < x) { + from = estimated + fromX = estX + } + for (;;) { + if (to - from <= 1) { + var after = x - fromX < toX - x + return { + line: lineNo, + ch: after ? from : to, + after: after } + } + var middle = Math.ceil((from + to) / 2), + middleX = getX(middle) + if (middleX > x) { + to = middle + toX = middleX + if (wrongLine) toX += 1000 + } else { + from = middle + fromX = middleX + } + } + } - function removeGutterMarker(line) { - if (typeof line == "number") line = getLine(clipLine(line)); - line.gutterMarker = null; - gutterDirty = true; + function pageCoords(pos) { + var local = localCoords(pos, true), + off = eltOffset(lineSpace) + return { + x: off.left + local.x, + y: off.top + local.y, + yBot: off.top + local.yBot + } + } + var cachedHeight, cachedHeightFor, measurePre + + function textHeight() { + if (measurePre == null) { + measurePre = elt('pre') + for (var i = 0; i < 49; ++i) { + measurePre.appendChild(document.createTextNode('x')) + measurePre.appendChild(elt('br')) + } + measurePre.appendChild(document.createTextNode('x')) + } + var offsetHeight = lineDiv.clientHeight + if (offsetHeight == cachedHeightFor) return cachedHeight + cachedHeightFor = offsetHeight + removeChildrenAndAdd(measure, measurePre.cloneNode(true)) + cachedHeight = measure.firstChild.offsetHeight / 50 || 1 + removeChildren(measure) + return cachedHeight + } + var cachedWidth, + cachedWidthFor = 0 + + function charWidth() { + if (scroller.clientWidth == cachedWidthFor) return cachedWidth + cachedWidthFor = scroller.clientWidth + var anchor = elt('span', 'x') + var pre = elt('pre', [anchor]) + removeChildrenAndAdd(measure, pre) + return (cachedWidth = anchor.offsetWidth || 10) + } + + function paddingTop() { + return lineSpace.offsetTop + } + + function paddingLeft() { + return lineSpace.offsetLeft + } + + function posFromMouse(e, liberal) { + var offW = eltOffset(scroller, true), + x, + y + try { + x = e.clientX + y = e.clientY + } catch (e) { + return null + } + if ( + !liberal && + (x - offW.left > scroller.clientWidth || + y - offW.top > scroller.clientHeight) + ) + return null + var offL = eltOffset(lineSpace, true) + return coordsChar(x - offL.left, y - offL.top) + } + var detectingSelectAll + + function onContextMenu(e) { + var pos = posFromMouse(e), + scrollPos = scrollbar.scrollTop + if (!pos || opera) return + if ( + posEq(sel.from, sel.to) || + posLess(pos, sel.from) || + !posLess(pos, sel.to) + ) + operation(setCursor)(pos.line, pos.ch) + var oldCSS = input.style.cssText + inputDiv.style.position = 'absolute' + input.style.cssText = + 'position: fixed; width: 30px; height: 30px; top: ' + + (e.clientY - 5) + + 'px; left: ' + + (e.clientX - 5) + + 'px; z-index: 1000; background: white; ' + + 'border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);' + focusInput() + resetInput(true) + if (posEq(sel.from, sel.to)) input.value = prevInput = ' ' + + function rehide() { + inputDiv.style.position = 'relative' + input.style.cssText = oldCSS + if (ie_lt9) scrollbar.scrollTop = scrollPos + slowPoll() + if (input.selectionStart != null) { + clearTimeout(detectingSelectAll) + var extval = (input.value = + ' ' + (posEq(sel.from, sel.to) ? '' : input.value)), + i = 0 + prevInput = ' ' + input.selectionStart = 1 + input.selectionEnd = extval.length + detectingSelectAll = setTimeout(function poll() { + if (prevInput == ' ' && input.selectionStart == 0) + operation(commands.selectAll)(instance) + else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500) + else resetInput() + }, 200) + } + } + if (gecko) { + e_stop(e) + var mouseup = connect( + window, + 'mouseup', + function() { + mouseup() + setTimeout(rehide, 20) + }, + true + ) + } else { + setTimeout(rehide, 50) + } + } + + function restartBlink() { + clearInterval(blinker) + var on = true + cursor.style.visibility = '' + blinker = setInterval(function() { + cursor.style.visibility = (on = !on) ? '' : 'hidden' + }, options.cursorBlinkRate) + } + var matching = { + '(': ')>', + ')': '(<', + '[': ']>', + ']': '[<', + '{': '}>', + '}': '{<' + } + + function matchBrackets(autoclear) { + var head = sel.inverted ? sel.from : sel.to, + line = getLine(head.line), + pos = head.ch - 1 + var match = + (pos >= 0 && matching[line.text.charAt(pos)]) || + matching[line.text.charAt(++pos)] + if (!match) return + var ch = match.charAt(0), + forward = match.charAt(1) == '>', + d = forward ? 1 : -1, + st = line.styles + for (var off = pos + 1, i = 0, e = st.length; i < e; i += 2) + if ((off -= st[i].length) <= 0) { + var style = st[i + 1] + break + } + var stack = [line.text.charAt(pos)], + re = /[(){}[\]]/ + + function scan(line, from, to) { + if (!line.text) return + var st = line.styles, + pos = forward ? 0 : line.text.length - 1, + cur + for ( + var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; + i != e; + i += 2 * d + ) { + var text = st[i] + if (st[i + 1] != style) { + pos += d * text.length + continue } - - function changeLine(handle, op) { - var no = handle, - line = handle; - if (typeof handle == "number") line = getLine(clipLine(handle)); - else no = lineNo(handle); - if (no == null) return null; - if (op(line, no)) changes.push({ - from: no, - to: no + 1 - }); - else return null; - return line; - } - - function setLineClass(handle, className, bgClassName) { - return changeLine(handle, function(line) { - if (line.className != className || line.bgClassName != bgClassName) { - line.className = className; - line.bgClassName = bgClassName; - return true; - } - }); - } - - function setLineHidden(handle, hidden) { - return changeLine(handle, function(line, no) { - if (line.hidden != hidden) { - line.hidden = hidden; - if (!options.lineWrapping) { - if (hidden && line.text.length == maxLine.text.length) { - updateMaxLine = true; - } else if (!hidden && line.text.length > maxLine.text.length) { - maxLine = line; - updateMaxLine = false; - } - } - updateLineHeight(line, hidden ? 0 : 1); - var fline = sel.from.line, - tline = sel.to.line; - if (hidden && (fline == no || tline == no)) { - var from = fline == no ? skipHidden({ - line: fline, - ch: 0 - }, fline, 0) : sel.from; - var to = tline == no ? skipHidden({ - line: tline, - ch: 0 - }, tline, 0) : sel.to; - if (!to) return; - setSelection(from, to); - } - return (gutterDirty = true); - } - }); - } - - function lineInfo(line) { - if (typeof line == "number") { - if (!isLine(line)) return null; - var n = line; - line = getLine(line); - if (!line) return null; - } else { - var n = lineNo(line); - if (n == null) return null; - } - var marker = line.gutterMarker; - return { - line: n, - handle: line, - text: line.text, - markerText: marker && marker.text, - markerClass: marker && marker.style, - lineClass: line.className, - bgClass: line.bgClassName - }; - } - - function measureLine(line, ch) { - if (ch == 0) return { - top: 0, - left: 0 - }; - var pre = lineContent(line, ch); - removeChildrenAndAdd(measure, pre); - var anchor = pre.anchor; - var top = anchor.offsetTop, - left = anchor.offsetLeft; - if (ie && top == 0 && left == 0) { - var backup = elt("span", "x"); - anchor.parentNode.insertBefore(backup, anchor.nextSibling); - top = backup.offsetTop; - } - return { - top: top, - left: left - }; - } - - function localCoords(pos, inLineWrap) { - var x, lh = textHeight(), - y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0)); - if (pos.ch == 0) x = 0; - else { - var sp = measureLine(getLine(pos.line), pos.ch); - x = sp.left; - if (options.lineWrapping) y += Math.max(0, sp.top); - } - return { - x: x, - y: y, - yBot: y + lh - }; - } - - function coordsChar(x, y) { - var th = textHeight(), - cw = charWidth(), - heightPos = displayOffset + Math.floor(y / th); - if (heightPos < 0) return { - line: 0, - ch: 0 - }; - var lineNo = lineAtHeight(doc, heightPos); - if (lineNo >= doc.size) return { - line: doc.size - 1, - ch: getLine(doc.size - 1).text.length - }; - var lineObj = getLine(lineNo), - text = lineObj.text; - var tw = options.lineWrapping, - innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0; - if (x <= 0 && innerOff == 0) return { - line: lineNo, - ch: 0 - }; - var wrongLine = false; - - function getX(len) { - var sp = measureLine(lineObj, len); - if (tw) { - var off = Math.round(sp.top / th); - wrongLine = off != innerOff; - return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth); - } - return sp.left; - } - var from = 0, - fromX = 0, - to = text.length, - toX; - var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw)); - for (;;) { - var estX = getX(estimated); - if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2)); - else { - toX = estX; - to = estimated; - break; - } - } - if (x > toX) return { - line: lineNo, - ch: to - }; - estimated = Math.floor(to * 0.8); - estX = getX(estimated); - if (estX < x) { - from = estimated; - fromX = estX; - } - for (;;) { - if (to - from <= 1) { - var after = x - fromX < toX - x; - return { - line: lineNo, - ch: after ? from : to, - after: after - }; - } - var middle = Math.ceil((from + to) / 2), - middleX = getX(middle); - if (middleX > x) { - to = middle; - toX = middleX; - if (wrongLine) toX += 1000; - } else { - from = middle; - fromX = middleX; - } - } - } - - function pageCoords(pos) { - var local = localCoords(pos, true), - off = eltOffset(lineSpace); - return { - x: off.left + local.x, - y: off.top + local.y, - yBot: off.top + local.yBot - }; - } - var cachedHeight, cachedHeightFor, measurePre; - - function textHeight() { - if (measurePre == null) { - measurePre = elt("pre"); - for (var i = 0; i < 49; ++i) { - measurePre.appendChild(document.createTextNode("x")); - measurePre.appendChild(elt("br")); - } - measurePre.appendChild(document.createTextNode("x")); - } - var offsetHeight = lineDiv.clientHeight; - if (offsetHeight == cachedHeightFor) return cachedHeight; - cachedHeightFor = offsetHeight; - removeChildrenAndAdd(measure, measurePre.cloneNode(true)); - cachedHeight = measure.firstChild.offsetHeight / 50 || 1; - removeChildren(measure); - return cachedHeight; - } - var cachedWidth, cachedWidthFor = 0; - - function charWidth() { - if (scroller.clientWidth == cachedWidthFor) return cachedWidth; - cachedWidthFor = scroller.clientWidth; - var anchor = elt("span", "x"); - var pre = elt("pre", [anchor]); - removeChildrenAndAdd(measure, pre); - return (cachedWidth = anchor.offsetWidth || 10); - } - - function paddingTop() { - return lineSpace.offsetTop; - } - - function paddingLeft() { - return lineSpace.offsetLeft; - } - - function posFromMouse(e, liberal) { - var offW = eltOffset(scroller, true), - x, y; - try { - x = e.clientX; - y = e.clientY; - } catch (e) { - return null; - } - if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight)) - return null; - var offL = eltOffset(lineSpace, true); - return coordsChar(x - offL.left, y - offL.top); - } - var detectingSelectAll; - - function onContextMenu(e) { - var pos = posFromMouse(e), - scrollPos = scrollbar.scrollTop; - if (!pos || opera) return; - if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) - operation(setCursor)(pos.line, pos.ch); - var oldCSS = input.style.cssText; - inputDiv.style.position = "absolute"; - input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " + "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; - focusInput(); - resetInput(true); - if (posEq(sel.from, sel.to)) input.value = prevInput = " "; - - function rehide() { - inputDiv.style.position = "relative"; - input.style.cssText = oldCSS; - if (ie_lt9) scrollbar.scrollTop = scrollPos; - slowPoll(); - if (input.selectionStart != null) { - clearTimeout(detectingSelectAll); - var extval = input.value = " " + (posEq(sel.from, sel.to) ? "" : input.value), - i = 0; - prevInput = " "; - input.selectionStart = 1; - input.selectionEnd = extval.length; - detectingSelectAll = setTimeout(function poll() { - if (prevInput == " " && input.selectionStart == 0) - operation(commands.selectAll)(instance); - else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); - else resetInput(); - }, 200); - } - } - if (gecko) { - e_stop(e); - var mouseup = connect(window, "mouseup", function() { - mouseup(); - setTimeout(rehide, 20); - }, true); - } else { - setTimeout(rehide, 50); - } - } - - function restartBlink() { - clearInterval(blinker); - var on = true; - cursor.style.visibility = ""; - blinker = setInterval(function() { - cursor.style.visibility = (on = !on) ? "" : "hidden"; - }, options.cursorBlinkRate); - } - var matching = { - "(": ")>", - ")": "(<", - "[": "]>", - "]": "[<", - "{": "}>", - "}": "{<" - }; - - function matchBrackets(autoclear) { - var head = sel.inverted ? sel.from : sel.to, - line = getLine(head.line), - pos = head.ch - 1; - var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; - if (!match) return; - var ch = match.charAt(0), - forward = match.charAt(1) == ">", - d = forward ? 1 : -1, - st = line.styles; - for (var off = pos + 1, i = 0, e = st.length; i < e; i += 2) - if ((off -= st[i].length) <= 0) { - var style = st[i + 1]; - break; - } - var stack = [line.text.charAt(pos)], - re = /[(){}[\]]/; - - function scan(line, from, to) { - if (!line.text) return; - var st = line.styles, - pos = forward ? 0 : line.text.length - 1, - cur; - for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2 * d) { - var text = st[i]; - if (st[i + 1] != style) { - pos += d * text.length; - continue; - } - for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos += d) { - if (pos >= from && pos < to && re.test(cur = text.charAt(j))) { - var match = matching[cur]; - if (match.charAt(1) == ">" == forward) stack.push(cur); - else if (stack.pop() != match.charAt(0)) return { - pos: pos, - match: false - }; - else if (!stack.length) return { - pos: pos, - match: true - }; - } - } - } - } - for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i += d) { - var line = getLine(i), - first = i == head.line; - var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length); - if (found) break; - } - if (!found) found = { - pos: null, + for ( + var j = forward ? 0 : text.length - 1, + te = forward ? text.length : -1; + j != te; + j += d, pos += d + ) { + if (pos >= from && pos < to && re.test((cur = text.charAt(j)))) { + var match = matching[cur] + if ((match.charAt(1) == '>') == forward) stack.push(cur) + else if (stack.pop() != match.charAt(0)) + return { + pos: pos, match: false - }; - var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; - var one = markText({ - line: head.line, - ch: pos - }, { - line: head.line, - ch: pos + 1 - }, style), - two = found.pos != null && markText({ - line: i, - ch: found.pos - }, { - line: i, - ch: found.pos + 1 - }, style); - var clear = operation(function() { - one.clear(); - two && two.clear(); - }); - if (autoclear) setTimeout(clear, 800); - else bracketHighlighted = clear; + } + else if (!stack.length) + return { + pos: pos, + match: true + } + } } - - function findStartLine(n) { - var minindent, minline; - for (var search = n, lim = n - 40; search > lim; --search) { - if (search == 0) return 0; - var line = getLine(search - 1); - if (line.stateAfter) return search; - var indented = line.indentation(options.tabSize); - if (minline == null || minindent > indented) { - minline = search - 1; - minindent = indented; - } - } - return minline; - } - - function getStateBefore(n) { - var pos = findStartLine(n), - state = pos && getLine(pos - 1).stateAfter; - if (!state) state = startState(mode); - else state = copyState(mode, state); - doc.iter(pos, n, function(line) { - line.process(mode, state, options.tabSize); - line.stateAfter = (pos == n - 1 || pos % 5 == 0) ? copyState(mode, state) : null; - }); - return state; - } - - function highlightWorker() { - if (frontier >= showingTo) return; - var end = +new Date + options.workTime, - state = copyState(mode, getStateBefore(frontier)); - var startFrontier = frontier; - doc.iter(frontier, showingTo, function(line) { - if (frontier >= showingFrom) { - line.highlight(mode, state, options.tabSize); - line.stateAfter = copyState(mode, state); - } else { - line.process(mode, state, options.tabSize); - line.stateAfter = frontier % 5 == 0 ? copyState(mode, state) : null; - } - ++frontier; - if (+new Date > end) { - startWorker(options.workDelay); - return true; - } - }); - if (showingTo > startFrontier && frontier >= showingFrom) - operation(function() { - changes.push({ - from: startFrontier, - to: frontier - }); - })(); - } - - function startWorker(time) { - if (frontier < showingTo) - highlight.set(time, highlightWorker); - } - - function startOperation() { - updateInput = userSelChange = textChanged = null; - changes = []; - selectionChanged = false; - callbacks = []; - } - - function endOperation() { - if (updateMaxLine) computeMaxLength(); - if (maxLineChanged && !options.lineWrapping) { - var cursorWidth = widthForcer.offsetWidth, - left = measureLine(maxLine, maxLine.text.length).left; - if (!ie_lt8) { - widthForcer.style.left = left + "px"; - lineSpace.style.minWidth = (left + cursorWidth) + "px"; - } - maxLineChanged = false; - } - var newScrollPos, updated; - if (selectionChanged) { - var coords = calculateCursorCoords(); - newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot); - } - if (changes.length || newScrollPos && newScrollPos.scrollTop != null) - updated = updateDisplay(changes, true, newScrollPos && newScrollPos.scrollTop); - if (!updated) { - if (selectionChanged) updateSelection(); - if (gutterDirty) updateGutter(); - } - if (newScrollPos) scrollCursorIntoView(); - if (selectionChanged) restartBlink(); - if (focused && (updateInput === true || (updateInput !== false && selectionChanged))) - resetInput(userSelChange); - if (selectionChanged && options.matchBrackets) - setTimeout(operation(function() { - if (bracketHighlighted) { - bracketHighlighted(); - bracketHighlighted = null; - } - if (posEq(sel.from, sel.to)) matchBrackets(false); - }), 20); - var sc = selectionChanged, - cbs = callbacks; - if (textChanged && options.onChange && instance) - options.onChange(instance, textChanged); - if (sc && options.onCursorActivity) - options.onCursorActivity(instance); - for (var i = 0; i < cbs.length; ++i) cbs[i](instance); - if (updated && options.onUpdate) options.onUpdate(instance); - } - var nestedOperation = 0; - - function operation(f) { - return function() { - if (!nestedOperation++) startOperation(); - try { - var result = f.apply(this, arguments); - } finally { - if (!--nestedOperation) endOperation(); - } - return result; - }; - } - - function compoundChange(f) { - history.startCompound(); - try { - return f(); - } finally { - history.endCompound(); - } - } - for (var ext in extensions) - if (extensions.propertyIsEnumerable(ext) && !instance.propertyIsEnumerable(ext)) - instance[ext] = extensions[ext]; - for (var i = 0; i < initHooks.length; ++i) initHooks[i](instance); - return instance; + } } - CodeMirror.defaults = { - value: "", - mode: null, - theme: "default", - indentUnit: 2, - indentWithTabs: false, - smartIndent: true, - tabSize: 4, - keyMap: "default", - extraKeys: null, - electricChars: true, - autoClearEmptyLines: false, - onKeyEvent: null, - onDragEvent: null, - lineWrapping: false, - lineNumbers: false, - gutter: false, - fixedGutter: false, - firstLineNumber: 1, - readOnly: false, - dragDrop: true, - onChange: null, - onCursorActivity: null, - onViewportChange: null, - onGutterClick: null, - onUpdate: null, - onFocus: null, - onBlur: null, - onScroll: null, - matchBrackets: false, - cursorBlinkRate: 530, - workTime: 100, - workDelay: 200, - pollInterval: 100, - undoDepth: 40, - tabindex: null, - autofocus: null, - lineNumberFormatter: function(integer) { - return integer; + for ( + var i = head.line, + e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); + i != e; + i += d + ) { + var line = getLine(i), + first = i == head.line + var found = scan( + line, + first && forward ? pos + 1 : 0, + first && !forward ? pos : line.text.length + ) + if (found) break + } + if (!found) + found = { + pos: null, + match: false + } + var style = found.match + ? 'CodeMirror-matchingbracket' + : 'CodeMirror-nonmatchingbracket' + var one = markText( + { + line: head.line, + ch: pos + }, + { + line: head.line, + ch: pos + 1 + }, + style + ), + two = + found.pos != null && + markText( + { + line: i, + ch: found.pos + }, + { + line: i, + ch: found.pos + 1 + }, + style + ) + var clear = operation(function() { + one.clear() + two && two.clear() + }) + if (autoclear) setTimeout(clear, 800) + else bracketHighlighted = clear + } + + function findStartLine(n) { + var minindent, minline + for (var search = n, lim = n - 40; search > lim; --search) { + if (search == 0) return 0 + var line = getLine(search - 1) + if (line.stateAfter) return search + var indented = line.indentation(options.tabSize) + if (minline == null || minindent > indented) { + minline = search - 1 + minindent = indented + } + } + return minline + } + + function getStateBefore(n) { + var pos = findStartLine(n), + state = pos && getLine(pos - 1).stateAfter + if (!state) state = startState(mode) + else state = copyState(mode, state) + doc.iter(pos, n, function(line) { + line.process(mode, state, options.tabSize) + line.stateAfter = + pos == n - 1 || pos % 5 == 0 ? copyState(mode, state) : null + }) + return state + } + + function highlightWorker() { + if (frontier >= showingTo) return + var end = +new Date() + options.workTime, + state = copyState(mode, getStateBefore(frontier)) + var startFrontier = frontier + doc.iter(frontier, showingTo, function(line) { + if (frontier >= showingFrom) { + line.highlight(mode, state, options.tabSize) + line.stateAfter = copyState(mode, state) + } else { + line.process(mode, state, options.tabSize) + line.stateAfter = frontier % 5 == 0 ? copyState(mode, state) : null + } + ++frontier + if (+new Date() > end) { + startWorker(options.workDelay) + return true + } + }) + if (showingTo > startFrontier && frontier >= showingFrom) + operation(function() { + changes.push({ + from: startFrontier, + to: frontier + }) + })() + } + + function startWorker(time) { + if (frontier < showingTo) highlight.set(time, highlightWorker) + } + + function startOperation() { + updateInput = userSelChange = textChanged = null + changes = [] + selectionChanged = false + callbacks = [] + } + + function endOperation() { + if (updateMaxLine) computeMaxLength() + if (maxLineChanged && !options.lineWrapping) { + var cursorWidth = widthForcer.offsetWidth, + left = measureLine(maxLine, maxLine.text.length).left + if (!ie_lt8) { + widthForcer.style.left = left + 'px' + lineSpace.style.minWidth = left + cursorWidth + 'px' + } + maxLineChanged = false + } + var newScrollPos, updated + if (selectionChanged) { + var coords = calculateCursorCoords() + newScrollPos = calculateScrollPos( + coords.x, + coords.y, + coords.x, + coords.yBot + ) + } + if (changes.length || (newScrollPos && newScrollPos.scrollTop != null)) + updated = updateDisplay( + changes, + true, + newScrollPos && newScrollPos.scrollTop + ) + if (!updated) { + if (selectionChanged) updateSelection() + if (gutterDirty) updateGutter() + } + if (newScrollPos) scrollCursorIntoView() + if (selectionChanged) restartBlink() + if ( + focused && + (updateInput === true || (updateInput !== false && selectionChanged)) + ) + resetInput(userSelChange) + if (selectionChanged && options.matchBrackets) + setTimeout( + operation(function() { + if (bracketHighlighted) { + bracketHighlighted() + bracketHighlighted = null + } + if (posEq(sel.from, sel.to)) matchBrackets(false) + }), + 20 + ) + var sc = selectionChanged, + cbs = callbacks + if (textChanged && options.onChange && instance) + options.onChange(instance, textChanged) + if (sc && options.onCursorActivity) options.onCursorActivity(instance) + for (var i = 0; i < cbs.length; ++i) cbs[i](instance) + if (updated && options.onUpdate) options.onUpdate(instance) + } + var nestedOperation = 0 + + function operation(f) { + return function() { + if (!nestedOperation++) startOperation() + try { + var result = f.apply(this, arguments) + } finally { + if (!--nestedOperation) endOperation() + } + return result + } + } + + function compoundChange(f) { + history.startCompound() + try { + return f() + } finally { + history.endCompound() + } + } + for (var ext in extensions) + if ( + extensions.propertyIsEnumerable(ext) && + !instance.propertyIsEnumerable(ext) + ) + instance[ext] = extensions[ext] + for (var i = 0; i < initHooks.length; ++i) initHooks[i](instance) + return instance +} +CodeMirror.defaults = { + value: '', + mode: null, + theme: 'default', + indentUnit: 2, + indentWithTabs: false, + smartIndent: true, + tabSize: 4, + keyMap: 'default', + extraKeys: null, + electricChars: true, + autoClearEmptyLines: false, + onKeyEvent: null, + onDragEvent: null, + lineWrapping: false, + lineNumbers: false, + gutter: false, + fixedGutter: false, + firstLineNumber: 1, + readOnly: false, + dragDrop: true, + onChange: null, + onCursorActivity: null, + onViewportChange: null, + onGutterClick: null, + onUpdate: null, + onFocus: null, + onBlur: null, + onScroll: null, + matchBrackets: false, + cursorBlinkRate: 530, + workTime: 100, + workDelay: 200, + pollInterval: 100, + undoDepth: 40, + tabindex: null, + autofocus: null, + lineNumberFormatter: function(integer) { + return integer + } +} +var ios = + /AppleWebKit/.test(navigator.userAgent) && + /Mobile\/\w+/.test(navigator.userAgent) +var mac = ios || /Mac/.test(navigator.platform) +var win = /Win/.test(navigator.platform) +var modes = (CodeMirror.modes = {}), + mimeModes = (CodeMirror.mimeModes = {}) +CodeMirror.defineMode = function(name, mode) { + if (!CodeMirror.defaults.mode && name != 'null') + CodeMirror.defaults.mode = name + if (arguments.length > 2) { + mode.dependencies = [] + for (var i = 2; i < arguments.length; ++i) + mode.dependencies.push(arguments[i]) + } + 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 (typeof spec == 'string' && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) + return CodeMirror.resolveMode('application/xml') + if (typeof spec == 'string') + return { + name: spec + } + else + return ( + spec || { + name: 'null' + } + ) +} +CodeMirror.getMode = function(options, spec) { + var spec = CodeMirror.resolveMode(spec) + var mfactory = modes[spec.name] + if (!mfactory) return CodeMirror.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)) modeObj[prop] = exts[prop] + } + modeObj.name = spec.name + return modeObj +} +CodeMirror.listModes = function() { + var list = [] + for (var m in modes) if (modes.propertyIsEnumerable(m)) list.push(m) + return list +} +CodeMirror.listMIMEs = function() { + var list = [] + for (var m in mimeModes) + if (mimeModes.propertyIsEnumerable(m)) + list.push({ + mime: m, + mode: mimeModes[m] + }) + return list +} +var extensions = (CodeMirror.extensions = {}) +CodeMirror.defineExtension = function(name, func) { + extensions[name] = func +} +var initHooks = [] +CodeMirror.defineInitHook = function(f) { + initHooks.push(f) +} +var modeExtensions = (CodeMirror.modeExtensions = {}) +CodeMirror.extendMode = function(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) + ? modeExtensions[mode] + : (modeExtensions[mode] = {}) + for (var prop in properties) + if (properties.hasOwnProperty(prop)) exts[prop] = properties[prop] +} +var commands = (CodeMirror.commands = { + selectAll: function(cm) { + cm.setSelection( + { + line: 0, + ch: 0 + }, + { + line: cm.lineCount() - 1 + } + ) + }, + killLine: function(cm) { + var from = cm.getCursor(true), + to = cm.getCursor(false), + sel = !posEq(from, to) + if (!sel && cm.getLine(from.line).length == from.ch) + cm.replaceRange('', from, { + line: from.line + 1, + ch: 0 + }) + else + cm.replaceRange( + '', + from, + sel + ? to + : { + line: from.line + } + ) + }, + deleteLine: function(cm) { + var l = cm.getCursor().line + cm.replaceRange( + '', + { + line: l, + ch: 0 + }, + { + line: l + } + ) + }, + undo: function(cm) { + cm.undo() + }, + redo: function(cm) { + cm.redo() + }, + goDocStart: function(cm) { + cm.setCursor(0, 0, true) + }, + goDocEnd: function(cm) { + cm.setSelection( + { + line: cm.lineCount() - 1 + }, + null, + true + ) + }, + goLineStart: function(cm) { + cm.setCursor(cm.getCursor().line, 0, true) + }, + goLineStartSmart: function(cm) { + var cur = cm.getCursor() + var text = cm.getLine(cur.line), + firstNonWS = Math.max(0, text.search(/\S/)) + cm.setCursor( + cur.line, + cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, + true + ) + }, + goLineEnd: function(cm) { + cm.setSelection( + { + line: cm.getCursor().line + }, + null, + true + ) + }, + goLineUp: function(cm) { + cm.moveV(-1, 'line') + }, + goLineDown: function(cm) { + cm.moveV(1, 'line') + }, + goPageUp: function(cm) { + cm.moveV(-1, 'page') + }, + goPageDown: function(cm) { + cm.moveV(1, 'page') + }, + goCharLeft: function(cm) { + cm.moveH(-1, 'char') + }, + goCharRight: function(cm) { + cm.moveH(1, 'char') + }, + goColumnLeft: function(cm) { + cm.moveH(-1, 'column') + }, + goColumnRight: function(cm) { + cm.moveH(1, 'column') + }, + goWordLeft: function(cm) { + cm.moveH(-1, 'word') + }, + goWordRight: function(cm) { + cm.moveH(1, 'word') + }, + delCharLeft: function(cm) { + cm.deleteH(-1, 'char') + }, + delCharRight: function(cm) { + cm.deleteH(1, 'char') + }, + delWordLeft: function(cm) { + cm.deleteH(-1, 'word') + }, + delWordRight: function(cm) { + cm.deleteH(1, 'word') + }, + indentAuto: function(cm) { + cm.indentSelection('smart') + }, + indentMore: function(cm) { + cm.indentSelection('add') + }, + indentLess: function(cm) { + cm.indentSelection('subtract') + }, + insertTab: function(cm) { + cm.replaceSelection('\t', 'end') + }, + defaultTab: function(cm) { + if (cm.somethingSelected()) cm.indentSelection('add') + else cm.replaceSelection('\t', 'end') + }, + transposeChars: function(cm) { + var cur = cm.getCursor(), + line = cm.getLine(cur.line) + if (cur.ch > 0 && cur.ch < line.length - 1) + cm.replaceRange( + line.charAt(cur.ch) + line.charAt(cur.ch - 1), + { + line: cur.line, + ch: cur.ch - 1 + }, + { + line: cur.line, + ch: cur.ch + 1 } - }; - var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent); - var mac = ios || /Mac/.test(navigator.platform); - var win = /Win/.test(navigator.platform); - var modes = CodeMirror.modes = {}, - mimeModes = CodeMirror.mimeModes = {}; - CodeMirror.defineMode = function(name, mode) { - if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; - if (arguments.length > 2) { - mode.dependencies = []; - for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); + ) + }, + newlineAndIndent: function(cm) { + cm.replaceSelection('\n', 'end') + cm.indentLine(cm.getCursor().line) + }, + toggleOverwrite: function(cm) { + cm.toggleOverwrite() + } +}) +var keyMap = (CodeMirror.keyMap = {}) +keyMap.basic = { + Left: 'goCharLeft', + Right: 'goCharRight', + Up: 'goLineUp', + Down: 'goLineDown', + End: 'goLineEnd', + Home: 'goLineStartSmart', + PageUp: 'goPageUp', + PageDown: 'goPageDown', + Delete: 'delCharRight', + Backspace: 'delCharLeft', + Tab: 'defaultTab', + 'Shift-Tab': 'indentAuto', + Enter: 'newlineAndIndent', + Insert: 'toggleOverwrite' +} +keyMap.pcDefault = { + 'Ctrl-A': 'selectAll', + 'Ctrl-D': 'deleteLine', + 'Ctrl-Z': 'undo', + 'Shift-Ctrl-Z': 'redo', + 'Ctrl-Y': 'redo', + 'Ctrl-Home': 'goDocStart', + 'Alt-Up': 'goDocStart', + 'Ctrl-End': 'goDocEnd', + 'Ctrl-Down': 'goDocEnd', + 'Ctrl-Left': 'goWordLeft', + 'Ctrl-Right': 'goWordRight', + 'Alt-Left': 'goLineStart', + 'Alt-Right': 'goLineEnd', + 'Ctrl-Backspace': 'delWordLeft', + 'Ctrl-Delete': 'delWordRight', + 'Ctrl-S': 'save', + 'Ctrl-F': 'find', + 'Ctrl-G': 'findNext', + 'Shift-Ctrl-G': 'findPrev', + 'Shift-Ctrl-F': 'replace', + 'Shift-Ctrl-R': 'replaceAll', + 'Ctrl-[': 'indentLess', + 'Ctrl-]': 'indentMore', + fallthrough: 'basic' +} +keyMap.macDefault = { + 'Cmd-A': 'selectAll', + 'Cmd-D': 'deleteLine', + 'Cmd-Z': 'undo', + 'Shift-Cmd-Z': 'redo', + 'Cmd-Y': 'redo', + 'Cmd-Up': 'goDocStart', + 'Cmd-End': 'goDocEnd', + 'Cmd-Down': 'goDocEnd', + 'Alt-Left': 'goWordLeft', + 'Alt-Right': 'goWordRight', + 'Cmd-Left': 'goLineStart', + 'Cmd-Right': 'goLineEnd', + 'Alt-Backspace': 'delWordLeft', + 'Ctrl-Alt-Backspace': 'delWordRight', + 'Alt-Delete': 'delWordRight', + 'Cmd-S': 'save', + 'Cmd-F': 'find', + 'Cmd-G': 'findNext', + 'Shift-Cmd-G': 'findPrev', + 'Cmd-Alt-F': 'replace', + 'Shift-Cmd-Alt-F': 'replaceAll', + 'Cmd-[': 'indentLess', + 'Cmd-]': 'indentMore', + fallthrough: ['basic', 'emacsy'] +} +keyMap['default'] = mac ? keyMap.macDefault : keyMap.pcDefault +keyMap.emacsy = { + 'Ctrl-F': 'goCharRight', + 'Ctrl-B': 'goCharLeft', + 'Ctrl-P': 'goLineUp', + 'Ctrl-N': 'goLineDown', + 'Alt-F': 'goWordRight', + 'Alt-B': 'goWordLeft', + 'Ctrl-A': 'goLineStart', + 'Ctrl-E': 'goLineEnd', + 'Ctrl-V': 'goPageDown', + 'Shift-Ctrl-V': 'goPageUp', + 'Ctrl-D': 'delCharRight', + 'Ctrl-H': 'delCharLeft', + 'Alt-D': 'delWordRight', + 'Alt-Backspace': 'delWordLeft', + 'Ctrl-K': 'killLine', + 'Ctrl-T': 'transposeChars' +} + +function getKeyMap(val) { + if (typeof val == 'string') return keyMap[val] + else return val +} + +function lookupKey(name, extraMap, map, handle, stop) { + function lookup(map) { + map = getKeyMap(map) + var found = map[name] + if (found === false) { + if (stop) stop() + return true + } + if (found != null && handle(found)) return true + if (map.nofallthrough) { + if (stop) stop() + return true + } + var fallthrough = map.fallthrough + if (fallthrough == null) return false + if (Object.prototype.toString.call(fallthrough) != '[object Array]') + return lookup(fallthrough) + for (var i = 0, e = fallthrough.length; i < e; ++i) { + if (lookup(fallthrough[i])) return true + } + return false + } + if (extraMap && lookup(extraMap)) return true + return lookup(map) +} + +function isModifierKey(event) { + var name = keyNames[e_prop(event, 'keyCode')] + return name == 'Ctrl' || name == 'Alt' || name == 'Shift' || name == 'Mod' +} +CodeMirror.isModifierKey = isModifierKey +CodeMirror.fromTextArea = function(textarea, options) { + if (!options) options = {} + options.value = textarea.value + if (!options.tabindex && textarea.tabindex) + options.tabindex = textarea.tabindex + if (options.autofocus == null) { + var hasFocus = document.body + try { + hasFocus = document.activeElement + } catch (e) {} + options.autofocus = + hasFocus == textarea || + (textarea.getAttribute('autofocus') != null && hasFocus == document.body) + } + + function save() { + textarea.value = instance.getValue() + } + if (textarea.form) { + var rmSubmit = connect(textarea.form, 'submit', save, true) + var realSubmit = textarea.form.submit + textarea.form.submit = function wrappedSubmit() { + save() + textarea.form.submit = realSubmit + textarea.form.submit() + textarea.form.submit = wrappedSubmit + } + } + textarea.style.display = 'none' + var instance = CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling) + }, options) + instance.save = save + instance.getTextArea = function() { + return textarea + } + instance.toTextArea = function() { + save() + textarea.parentNode.removeChild(instance.getWrapperElement()) + textarea.style.display = '' + if (textarea.form) { + rmSubmit() + if (typeof textarea.form.submit == 'function') + textarea.form.submit = realSubmit + } + } + return instance +} +var gecko = /gecko\/\d{7}/i.test(navigator.userAgent) +var ie = /MSIE \d/.test(navigator.userAgent) +var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent) +var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent) +var quirksMode = ie && document.documentMode == 5 +var webkit = /WebKit\//.test(navigator.userAgent) +var chrome = /Chrome\//.test(navigator.userAgent) +var opera = /Opera\//.test(navigator.userAgent) +var safari = /Apple Computer/.test(navigator.vendor) +var khtml = /KHTML\//.test(navigator.userAgent) +var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent) + +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 +} +CodeMirror.copyState = copyState + +function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true +} +CodeMirror.startState = startState +CodeMirror.innerMode = function(mode, state) { + while (mode.innerMode) { + var info = mode.innerMode(state) + state = info.state + mode = info.mode + } + return ( + info || { + mode: mode, + state: state + } + ) +} + +function StringStream(string, tabSize) { + this.pos = this.start = 0 + this.string = string + this.tabSize = tabSize || 8 +} +StringStream.prototype = { + eol: function() { + return this.pos >= this.string.length + }, + sol: function() { + return this.pos == 0 + }, + peek: function() { + return this.string.charAt(this.pos) || undefined + }, + 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 countColumn(this.string, this.start, this.tabSize) + }, + indentation: function() { + return countColumn(this.string, null, this.tabSize) + }, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == 'string') { + var cased = function(str) { + return caseInsensitive ? str.toLowerCase() : str + } + if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { + 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 + } + }, + current: function() { + return this.string.slice(this.start, this.pos) + } +} +CodeMirror.StringStream = StringStream + +function MarkedSpan(from, to, marker) { + this.from = from + this.to = to + this.marker = marker +} + +function getMarkedSpanFor(spans, marker) { + if (spans) + for (var i = 0; i < spans.length; ++i) { + var span = spans[i] + if (span.marker == marker) return span + } +} + +function removeMarkedSpan(spans, span) { + var r + for (var i = 0; i < spans.length; ++i) + if (spans[i] != span) (r || (r = [])).push(spans[i]) + return r +} + +function markedSpansBefore(old, startCh, endCh) { + if (old) + for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], + marker = span.marker + var startsBefore = + span.from == null || + (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh) + if ( + startsBefore || + (marker.type == 'bookmark' && + span.from == startCh && + span.from != endCh) + ) { + var endsAfter = + span.to == null || + (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) + ;(nw || (nw = [])).push({ + from: span.from, + to: endsAfter ? null : span.to, + marker: marker + }) + } + } + return nw +} + +function markedSpansAfter(old, endCh) { + if (old) + for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], + marker = span.marker + var endsAfter = + span.to == null || + (marker.inclusiveRight ? span.to >= endCh : span.to > endCh) + if (endsAfter || (marker.type == 'bookmark' && span.from == endCh)) { + var startsBefore = + span.from == null || + (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) + ;(nw || (nw = [])).push({ + from: startsBefore ? null : span.from - endCh, + to: span.to == null ? null : span.to - endCh, + marker: marker + }) + } + } + return nw +} + +function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) { + if (!oldFirst && !oldLast) return newText + var first = markedSpansBefore(oldFirst, startCh) + var last = markedSpansAfter(oldLast, endCh) + var sameLine = newText.length == 1, + offset = lst(newText).length + (sameLine ? startCh : 0) + if (first) { + for (var i = 0; i < first.length; ++i) { + var span = first[i] + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker) + if (!found) span.to = startCh + else if (sameLine) span.to = found.to == null ? null : found.to + offset + } + } + } + if (last) { + for (var i = 0; i < last.length; ++i) { + var span = last[i] + if (span.to != null) span.to += offset + if (span.from == null) { + var found = getMarkedSpanFor(first, span.marker) + if (!found) { + span.from = offset + if (sameLine) (first || (first = [])).push(span) } - 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 (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) - return CodeMirror.resolveMode("application/xml"); - if (typeof spec == "string") return { - name: spec - }; - else return spec || { - name: "null" - }; - }; - CodeMirror.getMode = function(options, spec) { - var spec = CodeMirror.resolveMode(spec); - var mfactory = modes[spec.name]; - if (!mfactory) return CodeMirror.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)) modeObj[prop] = exts[prop]; + } else { + span.from += offset + if (sameLine) (first || (first = [])).push(span) + } + } + } + var newMarkers = [newHL(newText[0], first)] + if (!sameLine) { + var gap = newText.length - 2, + gapMarkers + if (gap > 0 && first) + for (var i = 0; i < first.length; ++i) + if (first[i].to == null) + (gapMarkers || (gapMarkers = [])).push({ + from: null, + to: null, + marker: first[i].marker + }) + for (var i = 0; i < gap; ++i) + newMarkers.push(newHL(newText[i + 1], gapMarkers)) + newMarkers.push(newHL(lst(newText), last)) + } + return newMarkers +} + +function hlText(val) { + return typeof val == 'string' ? val : val.text +} + +function hlSpans(val) { + if (typeof val == 'string') return null + var spans = val.markedSpans, + out = null + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { + if (!out) out = spans.slice(0, i) + } else if (out) out.push(spans[i]) + } + return !out ? spans : out.length ? out : null +} + +function newHL(text, spans) { + return spans + ? { + text: text, + markedSpans: spans + } + : text +} + +function detachMarkedSpans(line) { + var spans = line.markedSpans + if (!spans) return + for (var i = 0; i < spans.length; ++i) { + var lines = spans[i].marker.lines + var ix = indexOf(lines, line) + lines.splice(ix, 1) + } + line.markedSpans = null +} + +function attachMarkedSpans(line, spans) { + if (!spans) return + for (var i = 0; i < spans.length; ++i) + var marker = spans[i].marker.lines.push(line) + line.markedSpans = spans +} +var eolSpanContent = ' ' +if (gecko || (ie && !ie_lt8)) eolSpanContent = '\u200b' +else if (opera) eolSpanContent = '' + +function Line(text, markedSpans) { + this.text = text + this.height = 1 + attachMarkedSpans(this, markedSpans) +} +Line.prototype = { + update: function(text, markedSpans) { + this.text = text + this.stateAfter = this.styles = null + detachMarkedSpans(this) + attachMarkedSpans(this, markedSpans) + }, + highlight: function(mode, state, tabSize) { + var stream = new StringStream(this.text, tabSize), + st = this.styles || (this.styles = []) + var pos = (st.length = 0) + if (this.text == '' && mode.blankLine) mode.blankLine(state) + while (!stream.eol()) { + var style = mode.token(stream, state), + substr = stream.current() + stream.start = stream.pos + if (pos && st[pos - 1] == style) { + st[pos - 2] += substr + } else if (substr) { + st[pos++] = substr + st[pos++] = style + } + if (stream.pos > 5000) { + st[pos++] = this.text.slice(stream.pos) + st[pos++] = null + break + } + } + }, + process: function(mode, state, tabSize) { + var stream = new StringStream(this.text, tabSize) + if (this.text == '' && mode.blankLine) mode.blankLine(state) + while (!stream.eol() && stream.pos <= 5000) { + mode.token(stream, state) + stream.start = stream.pos + } + }, + getTokenAt: function(mode, state, tabSize, ch) { + var txt = this.text, + stream = new StringStream(txt, tabSize) + while (stream.pos < ch && !stream.eol()) { + stream.start = stream.pos + var style = mode.token(stream, state) + } + return { + start: stream.start, + end: stream.pos, + string: stream.current(), + className: style || null, + state: state + } + }, + indentation: function(tabSize) { + return countColumn(this.text, null, tabSize) + }, + getContent: function(tabSize, wrapAt, compensateForWrapping) { + var first = true, + col = 0, + specials = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g + var pre = elt('pre') + + function span_(html, text, style) { + if (!text) return + if (first && ie && text.charAt(0) == ' ') text = '\u00a0' + text.slice(1) + first = false + if (!specials.test(text)) { + col += text.length + var content = document.createTextNode(text) + } else { + var content = document.createDocumentFragment(), + pos = 0 + while (true) { + specials.lastIndex = pos + var m = specials.exec(text) + var skipped = m ? m.index - pos : text.length - pos + if (skipped) { + content.appendChild( + document.createTextNode(text.slice(pos, pos + skipped)) + ) + col += skipped + } + if (!m) break + pos += skipped + 1 + if (m[0] == '\t') { + var tabWidth = tabSize - col % tabSize + content.appendChild(elt('span', spaceStr(tabWidth), 'cm-tab')) + col += tabWidth + } else { + var token = elt('span', '\u2022', 'cm-invalidchar') + token.title = '\\u' + m[0].charCodeAt(0).toString(16) + content.appendChild(token) + col += 1 + } } - modeObj.name = spec.name; - return modeObj; - }; - CodeMirror.listModes = function() { - var list = []; - for (var m in modes) - if (modes.propertyIsEnumerable(m)) list.push(m); - return list; - }; - CodeMirror.listMIMEs = function() { - var list = []; - for (var m in mimeModes) - if (mimeModes.propertyIsEnumerable(m)) list.push({ - mime: m, - mode: mimeModes[m] - }); - return list; - }; - var extensions = CodeMirror.extensions = {}; - CodeMirror.defineExtension = function(name, func) { - extensions[name] = func; - }; - var initHooks = []; - CodeMirror.defineInitHook = function(f) { - initHooks.push(f); - }; - var modeExtensions = CodeMirror.modeExtensions = {}; - CodeMirror.extendMode = function(mode, properties) { - var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); - for (var prop in properties) - if (properties.hasOwnProperty(prop)) - exts[prop] = properties[prop]; - }; - var commands = CodeMirror.commands = { - selectAll: function(cm) { - cm.setSelection({ - line: 0, - ch: 0 - }, { - line: cm.lineCount() - 1 - }); - }, - killLine: function(cm) { - var from = cm.getCursor(true), - to = cm.getCursor(false), - sel = !posEq(from, to); - if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, { - line: from.line + 1, - ch: 0 - }); - else cm.replaceRange("", from, sel ? to : { - line: from.line - }); - }, - deleteLine: function(cm) { - var l = cm.getCursor().line; - cm.replaceRange("", { - line: l, - ch: 0 - }, { - line: l - }); - }, - undo: function(cm) { - cm.undo(); - }, - redo: function(cm) { - cm.redo(); - }, - goDocStart: function(cm) { - cm.setCursor(0, 0, true); - }, - goDocEnd: function(cm) { - cm.setSelection({ - line: cm.lineCount() - 1 - }, null, true); - }, - goLineStart: function(cm) { - cm.setCursor(cm.getCursor().line, 0, true); - }, - goLineStartSmart: function(cm) { - var cur = cm.getCursor(); - var text = cm.getLine(cur.line), - firstNonWS = Math.max(0, text.search(/\S/)); - cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true); - }, - goLineEnd: function(cm) { - cm.setSelection({ - line: cm.getCursor().line - }, null, true); - }, - goLineUp: function(cm) { - cm.moveV(-1, "line"); - }, - goLineDown: function(cm) { - cm.moveV(1, "line"); - }, - goPageUp: function(cm) { - cm.moveV(-1, "page"); - }, - goPageDown: function(cm) { - cm.moveV(1, "page"); - }, - goCharLeft: function(cm) { - cm.moveH(-1, "char"); - }, - goCharRight: function(cm) { - cm.moveH(1, "char"); - }, - goColumnLeft: function(cm) { - cm.moveH(-1, "column"); - }, - goColumnRight: function(cm) { - cm.moveH(1, "column"); - }, - goWordLeft: function(cm) { - cm.moveH(-1, "word"); - }, - goWordRight: function(cm) { - cm.moveH(1, "word"); - }, - delCharLeft: function(cm) { - cm.deleteH(-1, "char"); - }, - delCharRight: function(cm) { - cm.deleteH(1, "char"); - }, - delWordLeft: function(cm) { - cm.deleteH(-1, "word"); - }, - delWordRight: function(cm) { - cm.deleteH(1, "word"); - }, - indentAuto: function(cm) { - cm.indentSelection("smart"); - }, - indentMore: function(cm) { - cm.indentSelection("add"); - }, - indentLess: function(cm) { - cm.indentSelection("subtract"); - }, - insertTab: function(cm) { - cm.replaceSelection("\t", "end"); - }, - defaultTab: function(cm) { - if (cm.somethingSelected()) cm.indentSelection("add"); - else cm.replaceSelection("\t", "end"); - }, - transposeChars: function(cm) { - var cur = cm.getCursor(), - line = cm.getLine(cur.line); - if (cur.ch > 0 && cur.ch < line.length - 1) - cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), { - line: cur.line, - ch: cur.ch - 1 - }, { - line: cur.line, - ch: cur.ch + 1 - }); - }, - newlineAndIndent: function(cm) { - cm.replaceSelection("\n", "end"); - cm.indentLine(cm.getCursor().line); - }, - toggleOverwrite: function(cm) { - cm.toggleOverwrite(); - } - }; - var keyMap = CodeMirror.keyMap = {}; - keyMap.basic = { - "Left": "goCharLeft", - "Right": "goCharRight", - "Up": "goLineUp", - "Down": "goLineDown", - "End": "goLineEnd", - "Home": "goLineStartSmart", - "PageUp": "goPageUp", - "PageDown": "goPageDown", - "Delete": "delCharRight", - "Backspace": "delCharLeft", - "Tab": "defaultTab", - "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", - "Insert": "toggleOverwrite" - }; - keyMap.pcDefault = { - "Ctrl-A": "selectAll", - "Ctrl-D": "deleteLine", - "Ctrl-Z": "undo", - "Shift-Ctrl-Z": "redo", - "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", - "Alt-Up": "goDocStart", - "Ctrl-End": "goDocEnd", - "Ctrl-Down": "goDocEnd", - "Ctrl-Left": "goWordLeft", - "Ctrl-Right": "goWordRight", - "Alt-Left": "goLineStart", - "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delWordLeft", - "Ctrl-Delete": "delWordRight", - "Ctrl-S": "save", - "Ctrl-F": "find", - "Ctrl-G": "findNext", - "Shift-Ctrl-G": "findPrev", - "Shift-Ctrl-F": "replace", - "Shift-Ctrl-R": "replaceAll", - "Ctrl-[": "indentLess", - "Ctrl-]": "indentMore", - fallthrough: "basic" - }; - keyMap.macDefault = { - "Cmd-A": "selectAll", - "Cmd-D": "deleteLine", - "Cmd-Z": "undo", - "Shift-Cmd-Z": "redo", - "Cmd-Y": "redo", - "Cmd-Up": "goDocStart", - "Cmd-End": "goDocEnd", - "Cmd-Down": "goDocEnd", - "Alt-Left": "goWordLeft", - "Alt-Right": "goWordRight", - "Cmd-Left": "goLineStart", - "Cmd-Right": "goLineEnd", - "Alt-Backspace": "delWordLeft", - "Ctrl-Alt-Backspace": "delWordRight", - "Alt-Delete": "delWordRight", - "Cmd-S": "save", - "Cmd-F": "find", - "Cmd-G": "findNext", - "Shift-Cmd-G": "findPrev", - "Cmd-Alt-F": "replace", - "Shift-Cmd-Alt-F": "replaceAll", - "Cmd-[": "indentLess", - "Cmd-]": "indentMore", - fallthrough: ["basic", "emacsy"] - }; - keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; - keyMap.emacsy = { - "Ctrl-F": "goCharRight", - "Ctrl-B": "goCharLeft", - "Ctrl-P": "goLineUp", - "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", - "Alt-B": "goWordLeft", - "Ctrl-A": "goLineStart", - "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", - "Shift-Ctrl-V": "goPageUp", - "Ctrl-D": "delCharRight", - "Ctrl-H": "delCharLeft", - "Alt-D": "delWordRight", - "Alt-Backspace": "delWordLeft", - "Ctrl-K": "killLine", - "Ctrl-T": "transposeChars" - }; - - function getKeyMap(val) { - if (typeof val == "string") return keyMap[val]; - else return val; + } + if (style) html.appendChild(elt('span', [content], style)) + else html.appendChild(content) } - - function lookupKey(name, extraMap, map, handle, stop) { - function lookup(map) { - map = getKeyMap(map); - var found = map[name]; - if (found === false) { - if (stop) stop(); - return true; + var span = span_ + if (wrapAt != null) { + var outPos = 0, + anchor = (pre.anchor = elt('span')) + span = function(html, text, style) { + var l = text.length + if (wrapAt >= outPos && wrapAt < outPos + l) { + var cut = wrapAt - outPos + if (cut) { + span_(html, text.slice(0, cut), style) + if (compensateForWrapping) { + var view = text.slice(cut - 1, cut + 1) + if (spanAffectsWrapping.test(view)) html.appendChild(elt('wbr')) + else if (!ie_lt8 && /\w\w/.test(view)) + html.appendChild(document.createTextNode('\u200d')) } - if (found != null && handle(found)) return true; - if (map.nofallthrough) { - if (stop) stop(); - return true; - } - var fallthrough = map.fallthrough; - if (fallthrough == null) return false; - if (Object.prototype.toString.call(fallthrough) != "[object Array]") - return lookup(fallthrough); - for (var i = 0, e = fallthrough.length; i < e; ++i) { - if (lookup(fallthrough[i])) return true; - } - return false; - } - if (extraMap && lookup(extraMap)) return true; - return lookup(map); - } - - function isModifierKey(event) { - var name = keyNames[e_prop(event, "keyCode")]; - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; - } - CodeMirror.isModifierKey = isModifierKey; - CodeMirror.fromTextArea = function(textarea, options) { - if (!options) options = {}; - options.value = textarea.value; - if (!options.tabindex && textarea.tabindex) - options.tabindex = textarea.tabindex; - if (options.autofocus == null) { - var hasFocus = document.body; - try { - hasFocus = document.activeElement; - } catch (e) {} - options.autofocus = hasFocus == textarea || textarea.getAttribute("autofocus") != null && hasFocus == document.body; - } - - function save() { - textarea.value = instance.getValue(); - } - if (textarea.form) { - var rmSubmit = connect(textarea.form, "submit", save, true); - var realSubmit = textarea.form.submit; - textarea.form.submit = function wrappedSubmit() { - save(); - textarea.form.submit = realSubmit; - textarea.form.submit(); - textarea.form.submit = wrappedSubmit; - }; - } - textarea.style.display = "none"; - var instance = CodeMirror(function(node) { - textarea.parentNode.insertBefore(node, textarea.nextSibling); - }, options); - instance.save = save; - instance.getTextArea = function() { - return textarea; - }; - instance.toTextArea = function() { - save(); - textarea.parentNode.removeChild(instance.getWrapperElement()); - textarea.style.display = ""; - if (textarea.form) { - rmSubmit(); - if (typeof textarea.form.submit == "function") - textarea.form.submit = realSubmit; - } - }; - return instance; - }; - var gecko = /gecko\/\d{7}/i.test(navigator.userAgent); - var ie = /MSIE \d/.test(navigator.userAgent); - var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); - var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent); - var quirksMode = ie && document.documentMode == 5; - var webkit = /WebKit\//.test(navigator.userAgent); - var chrome = /Chrome\//.test(navigator.userAgent); - var opera = /Opera\//.test(navigator.userAgent); - var safari = /Apple Computer/.test(navigator.vendor); - var khtml = /KHTML\//.test(navigator.userAgent); - var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent); - - 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; - } - CodeMirror.copyState = copyState; - - function startState(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true; - } - CodeMirror.startState = startState; - CodeMirror.innerMode = function(mode, state) { - while (mode.innerMode) { - var info = mode.innerMode(state); - state = info.state; - mode = info.mode; - } - return info || { - mode: mode, - state: state - }; - }; - - function StringStream(string, tabSize) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - } - StringStream.prototype = { - eol: function() { - return this.pos >= this.string.length; - }, - sol: function() { - return this.pos == 0; - }, - peek: function() { - return this.string.charAt(this.pos) || undefined; - }, - 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 countColumn(this.string, this.start, this.tabSize); - }, - indentation: function() { - return countColumn(this.string, null, this.tabSize); - }, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function(str) { - return caseInsensitive ? str.toLowerCase() : str; - }; - if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { - 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; - } - }, - current: function() { - return this.string.slice(this.start, this.pos); - } - }; - CodeMirror.StringStream = StringStream; - - function MarkedSpan(from, to, marker) { - this.from = from; - this.to = to; - this.marker = marker; - } - - function getMarkedSpanFor(spans, marker) { - if (spans) - for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.marker == marker) return span; - } - } - - function removeMarkedSpan(spans, span) { - var r; - for (var i = 0; i < spans.length; ++i) - if (spans[i] != span)(r || (r = [])).push(spans[i]); - return r; - } - - function markedSpansBefore(old, startCh, endCh) { - if (old) - for (var i = 0, nw; i < old.length; ++i) { - var span = old[i], - marker = span.marker; - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); - if (startsBefore || marker.type == "bookmark" && span.from == startCh && span.from != endCh) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); - (nw || (nw = [])).push({ - from: span.from, - to: endsAfter ? null : span.to, - marker: marker - }); - } - } - return nw; - } - - function markedSpansAfter(old, endCh) { - if (old) - for (var i = 0, nw; i < old.length; ++i) { - var span = old[i], - marker = span.marker; - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); - if (endsAfter || marker.type == "bookmark" && span.from == endCh) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); - (nw || (nw = [])).push({ - from: startsBefore ? null : span.from - endCh, - to: span.to == null ? null : span.to - endCh, - marker: marker - }); - } - } - return nw; - } - - function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) { - if (!oldFirst && !oldLast) return newText; - var first = markedSpansBefore(oldFirst, startCh); - var last = markedSpansAfter(oldLast, endCh); - var sameLine = newText.length == 1, - offset = lst(newText).length + (sameLine ? startCh : 0); - if (first) { - for (var i = 0; i < first.length; ++i) { - var span = first[i]; - if (span.to == null) { - var found = getMarkedSpanFor(last, span.marker); - if (!found) span.to = startCh; - else if (sameLine) span.to = found.to == null ? null : found.to + offset; - } - } - } - if (last) { - for (var i = 0; i < last.length; ++i) { - var span = last[i]; - if (span.to != null) span.to += offset; - if (span.from == null) { - var found = getMarkedSpanFor(first, span.marker); - if (!found) { - span.from = offset; - if (sameLine)(first || (first = [])).push(span); - } - } else { - span.from += offset; - if (sameLine)(first || (first = [])).push(span); - } - } - } - var newMarkers = [newHL(newText[0], first)]; - if (!sameLine) { - var gap = newText.length - 2, - gapMarkers; - if (gap > 0 && first) - for (var i = 0; i < first.length; ++i) - if (first[i].to == null) - (gapMarkers || (gapMarkers = [])).push({ - from: null, - to: null, - marker: first[i].marker - }); - for (var i = 0; i < gap; ++i) - newMarkers.push(newHL(newText[i + 1], gapMarkers)); - newMarkers.push(newHL(lst(newText), last)); - } - return newMarkers; - } - - function hlText(val) { - return typeof val == "string" ? val : val.text; - } - - function hlSpans(val) { - if (typeof val == "string") return null; - var spans = val.markedSpans, - out = null; - for (var i = 0; i < spans.length; ++i) { - if (spans[i].marker.explicitlyCleared) { - if (!out) out = spans.slice(0, i); - } else if (out) out.push(spans[i]); - } - return !out ? spans : out.length ? out : null; - } - - function newHL(text, spans) { - return spans ? { - text: text, - markedSpans: spans - } : text; - } - - function detachMarkedSpans(line) { - var spans = line.markedSpans; - if (!spans) return; - for (var i = 0; i < spans.length; ++i) { - var lines = spans[i].marker.lines; - var ix = indexOf(lines, line); - lines.splice(ix, 1); - } - line.markedSpans = null; - } - - function attachMarkedSpans(line, spans) { - if (!spans) return; - for (var i = 0; i < spans.length; ++i) - var marker = spans[i].marker.lines.push(line); - line.markedSpans = spans; - } - var eolSpanContent = " "; - if (gecko || (ie && !ie_lt8)) eolSpanContent = "\u200b"; - else if (opera) eolSpanContent = ""; - - function Line(text, markedSpans) { - this.text = text; - this.height = 1; - attachMarkedSpans(this, markedSpans); - } - Line.prototype = { - update: function(text, markedSpans) { - this.text = text; - this.stateAfter = this.styles = null; - detachMarkedSpans(this); - attachMarkedSpans(this, markedSpans); - }, - highlight: function(mode, state, tabSize) { - var stream = new StringStream(this.text, tabSize), - st = this.styles || (this.styles = []); - var pos = st.length = 0; - if (this.text == "" && mode.blankLine) mode.blankLine(state); - while (!stream.eol()) { - var style = mode.token(stream, state), - substr = stream.current(); - stream.start = stream.pos; - if (pos && st[pos - 1] == style) { - st[pos - 2] += substr; - } else if (substr) { - st[pos++] = substr; - st[pos++] = style; - } - if (stream.pos > 5000) { - st[pos++] = this.text.slice(stream.pos); - st[pos++] = null; - break; - } - } - }, - process: function(mode, state, tabSize) { - var stream = new StringStream(this.text, tabSize); - if (this.text == "" && mode.blankLine) mode.blankLine(state); - while (!stream.eol() && stream.pos <= 5000) { - mode.token(stream, state); - stream.start = stream.pos; - } - }, - getTokenAt: function(mode, state, tabSize, ch) { - var txt = this.text, - stream = new StringStream(txt, tabSize); - while (stream.pos < ch && !stream.eol()) { - stream.start = stream.pos; - var style = mode.token(stream, state); - } - return { - start: stream.start, - end: stream.pos, - string: stream.current(), - className: style || null, - state: state - }; - }, - indentation: function(tabSize) { - return countColumn(this.text, null, tabSize); - }, - getContent: function(tabSize, wrapAt, compensateForWrapping) { - var first = true, - col = 0, - specials = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g; - var pre = elt("pre"); - - function span_(html, text, style) { - if (!text) return; - if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1); - first = false; - if (!specials.test(text)) { - col += text.length; - var content = document.createTextNode(text); - } else { - var content = document.createDocumentFragment(), - pos = 0; - while (true) { - specials.lastIndex = pos; - var m = specials.exec(text); - var skipped = m ? m.index - pos : text.length - pos; - if (skipped) { - content.appendChild(document.createTextNode(text.slice(pos, pos + skipped))); - col += skipped; - } - if (!m) break; - pos += skipped + 1; - if (m[0] == "\t") { - var tabWidth = tabSize - col % tabSize; - content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); - col += tabWidth; - } else { - var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + m[0].charCodeAt(0).toString(16); - content.appendChild(token); - col += 1; - } - } - } - if (style) html.appendChild(elt("span", [content], style)); - else html.appendChild(content); - } - var span = span_; - if (wrapAt != null) { - var outPos = 0, - anchor = pre.anchor = elt("span"); - span = function(html, text, style) { - var l = text.length; - if (wrapAt >= outPos && wrapAt < outPos + l) { - var cut = wrapAt - outPos; - if (cut) { - span_(html, text.slice(0, cut), style); - if (compensateForWrapping) { - var view = text.slice(cut - 1, cut + 1); - if (spanAffectsWrapping.test(view)) html.appendChild(elt("wbr")); - else if (!ie_lt8 && /\w\w/.test(view)) html.appendChild(document.createTextNode("\u200d")); - } - } - html.appendChild(anchor); - span_(anchor, opera ? text.slice(cut, cut + 1) : text.slice(cut), style); - if (opera) span_(html, text.slice(cut + 1), style); - wrapAt--; - outPos += l; - } else { - outPos += l; - span_(html, text, style); - if (outPos == wrapAt && outPos == len) { - setTextContent(anchor, eolSpanContent); - html.appendChild(anchor); - } else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function() {}; - } - }; - } - var st = this.styles, - allText = this.text, - marked = this.markedSpans; - var len = allText.length; - - function styleToClass(style) { - if (!style) return null; - return "cm-" + style.replace(/ +/g, " cm-"); - } - if (!allText && wrapAt == null) { - span(pre, " "); - } else if (!marked || !marked.length) { - for (var i = 0, ch = 0; ch < len; i += 2) { - var str = st[i], - style = st[i + 1], - l = str.length; - if (ch + l > len) str = str.slice(0, len - ch); - ch += l; - span(pre, str, styleToClass(style)); - } - } else { - marked.sort(function(a, b) { - return a.from - b.from; - }); - var pos = 0, - i = 0, - text = "", - style, sg = 0; - var nextChange = marked[0].from || 0, - marks = [], - markpos = 0; - var advanceMarks = function() { - var m; - while (markpos < marked.length && ((m = marked[markpos]).from == pos || m.from == null)) { - if (m.marker.type == "range") marks.push(m); - ++markpos; - } - nextChange = markpos < marked.length ? marked[markpos].from : Infinity; - for (var i = 0; i < marks.length; ++i) { - var to = marks[i].to; - if (to == null) to = Infinity; - if (to == pos) marks.splice(i--, 1); - else nextChange = Math.min(to, nextChange); - } - }; - var m = 0; - while (pos < len) { - if (nextChange == pos) advanceMarks(); - var upto = Math.min(len, nextChange); - while (true) { - if (text) { - var end = pos + text.length; - var appliedStyle = style; - for (var j = 0; j < marks.length; ++j) { - var mark = marks[j]; - appliedStyle = (appliedStyle ? appliedStyle + " " : "") + mark.marker.style; - if (mark.marker.endStyle && mark.to === Math.min(end, upto)) appliedStyle += " " + mark.marker.endStyle; - if (mark.marker.startStyle && mark.from === pos) appliedStyle += " " + mark.marker.startStyle; - } - span(pre, end > upto ? text.slice(0, upto - pos) : text, appliedStyle); - if (end >= upto) { - text = text.slice(upto - pos); - pos = upto; - break; - } - pos = end; - } - text = st[i++]; - style = styleToClass(st[i++]); - } - } - } - return pre; - }, - cleanUp: function() { - this.parent = null; - detachMarkedSpans(this); - } - }; - - function LeafChunk(lines) { - this.lines = lines; - this.parent = null; - for (var i = 0, e = lines.length, height = 0; i < e; ++i) { - lines[i].parent = this; - height += lines[i].height; - } - this.height = height; - } - LeafChunk.prototype = { - chunkSize: function() { - return this.lines.length; - }, - remove: function(at, n, callbacks) { - for (var i = at, e = at + n; i < e; ++i) { - var line = this.lines[i]; - this.height -= line.height; - line.cleanUp(); - if (line.handlers) - for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]); - } - this.lines.splice(at, n); - }, - collapse: function(lines) { - lines.splice.apply(lines, [lines.length, 0].concat(this.lines)); - }, - insertHeight: function(at, lines, height) { - this.height += height; - this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); - for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this; - }, - iterN: function(at, n, op) { - for (var e = at + n; at < e; ++at) - if (op(this.lines[at])) return true; - } - }; - - function BranchChunk(children) { - this.children = children; - var size = 0, - height = 0; - for (var i = 0, e = children.length; i < e; ++i) { - var ch = children[i]; - size += ch.chunkSize(); - height += ch.height; - ch.parent = this; - } - this.size = size; - this.height = height; - this.parent = null; - } - BranchChunk.prototype = { - chunkSize: function() { - return this.size; - }, - remove: function(at, n, callbacks) { - this.size -= n; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], - sz = child.chunkSize(); - if (at < sz) { - var rm = Math.min(n, sz - at), - oldHeight = child.height; - child.remove(at, rm, callbacks); - this.height -= oldHeight - child.height; - if (sz == rm) { - this.children.splice(i--, 1); - child.parent = null; - } - if ((n -= rm) == 0) break; - at = 0; - } else at -= sz; - } - if (this.size - n < 25) { - var lines = []; - this.collapse(lines); - this.children = [new LeafChunk(lines)]; - this.children[0].parent = this; - } - }, - collapse: function(lines) { - for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines); - }, - insert: function(at, lines) { - var height = 0; - for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height; - this.insertHeight(at, lines, height); - }, - insertHeight: function(at, lines, height) { - this.size += lines.length; - this.height += height; - for (var i = 0, e = this.children.length; i < e; ++i) { - var child = this.children[i], - sz = child.chunkSize(); - if (at <= sz) { - child.insertHeight(at, lines, height); - if (child.lines && child.lines.length > 50) { - while (child.lines.length > 50) { - var spilled = child.lines.splice(child.lines.length - 25, 25); - var newleaf = new LeafChunk(spilled); - child.height -= newleaf.height; - this.children.splice(i + 1, 0, newleaf); - newleaf.parent = this; - } - this.maybeSpill(); - } - break; - } - at -= sz; - } - }, - maybeSpill: function() { - if (this.children.length <= 10) return; - var me = this; - do { - var spilled = me.children.splice(me.children.length - 5, 5); - var sibling = new BranchChunk(spilled); - if (!me.parent) { - var copy = new BranchChunk(me.children); - copy.parent = me; - me.children = [copy, sibling]; - me = copy; - } else { - me.size -= sibling.size; - me.height -= sibling.height; - var myIndex = indexOf(me.parent.children, me); - me.parent.children.splice(myIndex + 1, 0, sibling); - } - sibling.parent = me.parent; - } while (me.children.length > 10); - me.parent.maybeSpill(); - }, - iter: function(from, to, op) { - this.iterN(from, to - from, op); - }, - iterN: function(at, n, op) { - for (var i = 0, e = this.children.length; i < e; ++i) { - var child = this.children[i], - sz = child.chunkSize(); - if (at < sz) { - var used = Math.min(n, sz - at); - if (child.iterN(at, used, op)) return true; - if ((n -= used) == 0) break; - at = 0; - } else at -= sz; - } - } - }; - - function getLineAt(chunk, n) { - while (!chunk.lines) { - for (var i = 0;; ++i) { - var child = chunk.children[i], - sz = child.chunkSize(); - if (n < sz) { - chunk = child; - break; - } - n -= sz; - } - } - return chunk.lines[n]; - } - - function lineNo(line) { - if (line.parent == null) return null; - var cur = line.parent, - no = indexOf(cur.lines, line); - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0, e = chunk.children.length;; ++i) { - if (chunk.children[i] == cur) break; - no += chunk.children[i].chunkSize(); - } - } - return no; - } - - function lineAtHeight(chunk, h) { - var n = 0; - outer: do { - for (var i = 0, e = chunk.children.length; i < e; ++i) { - var child = chunk.children[i], - ch = child.height; - if (h < ch) { - chunk = child; - continue outer; - } - h -= ch; - n += child.chunkSize(); - } - return n; - } while (!chunk.lines); - for (var i = 0, e = chunk.lines.length; i < e; ++i) { - var line = chunk.lines[i], - lh = line.height; - if (h < lh) break; - h -= lh; - } - return n + i; - } - - function heightAtLine(chunk, n) { - var h = 0; - outer: do { - for (var i = 0, e = chunk.children.length; i < e; ++i) { - var child = chunk.children[i], - sz = child.chunkSize(); - if (n < sz) { - chunk = child; - continue outer; - } - n -= sz; - h += child.height; - } - return h; - } while (!chunk.lines); - for (var i = 0; i < n; ++i) h += chunk.lines[i].height; - return h; - } - - function History() { - this.time = 0; - this.done = []; - this.undone = []; - this.compound = 0; - this.closed = false; - } - History.prototype = { - addChange: function(start, added, old) { - this.undone.length = 0; - var time = +new Date, - cur = lst(this.done), - last = cur && lst(cur); - var dtime = time - this.time; - if (cur && !this.closed && this.compound) { - cur.push({ - start: start, - added: added, - old: old - }); - } else if (dtime > 400 || !last || this.closed || last.start > start + old.length || last.start + last.added < start) { - this.done.push([{ - start: start, - added: added, - old: old - }]); - this.closed = false; - } else { - var startBefore = Math.max(0, last.start - start), - endAfter = Math.max(0, (start + old.length) - (last.start + last.added)); - for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]); - for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]); - if (startBefore) last.start = start; - last.added += added - (old.length - startBefore - endAfter); - } - this.time = time; - }, - startCompound: function() { - if (!this.compound++) this.closed = true; - }, - endCompound: function() { - if (!--this.compound) this.closed = true; - } - }; - - function stopMethod() { - e_stop(this); - } - - function addStop(event) { - if (!event.stop) event.stop = stopMethod; - return event; - } - - function e_preventDefault(e) { - if (e.preventDefault) e.preventDefault(); - else e.returnValue = false; - } - - function e_stopPropagation(e) { - if (e.stopPropagation) e.stopPropagation(); - else e.cancelBubble = true; - } - - function e_stop(e) { - e_preventDefault(e); - e_stopPropagation(e); - } - CodeMirror.e_stop = e_stop; - CodeMirror.e_preventDefault = e_preventDefault; - CodeMirror.e_stopPropagation = e_stopPropagation; - - function e_target(e) { - return e.target || e.srcElement; - } - - function e_button(e) { - var b = e.which; - if (b == null) { - if (e.button & 1) b = 1; - else if (e.button & 2) b = 3; - else if (e.button & 4) b = 2; - } - if (mac && e.ctrlKey && b == 1) b = 3; - return b; - } - - function e_prop(e, prop) { - var overridden = e.override && e.override.hasOwnProperty(prop); - return overridden ? e.override[prop] : e[prop]; - } - - function connect(node, type, handler, disconnect) { - if (typeof node.addEventListener == "function") { - node.addEventListener(type, handler, false); - if (disconnect) return function() { - node.removeEventListener(type, handler, false); - }; + } + html.appendChild(anchor) + span_( + anchor, + opera ? text.slice(cut, cut + 1) : text.slice(cut), + style + ) + if (opera) span_(html, text.slice(cut + 1), style) + wrapAt-- + outPos += l } else { - var wrapHandler = function(event) { - handler(event || window.event); - }; - node.attachEvent("on" + type, wrapHandler); - if (disconnect) return function() { - node.detachEvent("on" + type, wrapHandler); - }; + outPos += l + span_(html, text, style) + if (outPos == wrapAt && outPos == len) { + setTextContent(anchor, eolSpanContent) + html.appendChild(anchor) + } else if (outPos > wrapAt + 10 && /\s/.test(text)) + span = function() {} } + } } - CodeMirror.connect = connect; + var st = this.styles, + allText = this.text, + marked = this.markedSpans + var len = allText.length - function Delayed() { - this.id = null; + function styleToClass(style) { + if (!style) return null + return 'cm-' + style.replace(/ +/g, ' cm-') } - Delayed.prototype = { - set: function(ms, f) { - clearTimeout(this.id); - this.id = setTimeout(f, ms); + if (!allText && wrapAt == null) { + span(pre, ' ') + } else if (!marked || !marked.length) { + for (var i = 0, ch = 0; ch < len; i += 2) { + var str = st[i], + style = st[i + 1], + l = str.length + if (ch + l > len) str = str.slice(0, len - ch) + ch += l + span(pre, str, styleToClass(style)) + } + } else { + marked.sort(function(a, b) { + return a.from - b.from + }) + var pos = 0, + i = 0, + text = '', + style, + sg = 0 + var nextChange = marked[0].from || 0, + marks = [], + markpos = 0 + var advanceMarks = function() { + var m + while ( + markpos < marked.length && + ((m = marked[markpos]).from == pos || m.from == null) + ) { + if (m.marker.type == 'range') marks.push(m) + ++markpos } - }; - var Pass = CodeMirror.Pass = { - toString: function() { - return "CodeMirror.Pass"; + nextChange = markpos < marked.length ? marked[markpos].from : Infinity + for (var i = 0; i < marks.length; ++i) { + var to = marks[i].to + if (to == null) to = Infinity + if (to == pos) marks.splice(i--, 1) + else nextChange = Math.min(to, nextChange) } - }; - var dragAndDrop = function() { - if (ie_lt9) return false; - var div = elt('div'); - return "draggable" in div || "dragDrop" in div; - }(); - var lineSep = function() { - var te = elt("textarea"); - te.value = "foo\nbar"; - if (te.value.indexOf("\r") > -1) return "\r\n"; - return "\n"; - }(); - var spanAffectsWrapping = /^$/; - if (gecko) spanAffectsWrapping = /$'/; - else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/; - else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/; - - function countColumn(string, end, tabSize) { - if (end == null) { - end = string.search(/[^\s\u00a0]/); - if (end == -1) end = string.length; - } - for (var i = 0, n = 0; i < end; ++i) { - if (string.charAt(i) == "\t") n += tabSize - (n % tabSize); - else ++n; - } - return n; - } - - function eltOffset(node, screen) { - try { - var box = node.getBoundingClientRect(); - box = { - top: box.top, - left: box.left - }; - } catch (e) { - box = { - top: 0, - left: 0 - }; - } - if (!screen) { - if (window.pageYOffset == null) { - var t = document.documentElement || document.body.parentNode; - if (t.scrollTop == null) t = document.body; - box.top += t.scrollTop; - box.left += t.scrollLeft; - } else { - box.top += window.pageYOffset; - box.left += window.pageXOffset; + } + var m = 0 + while (pos < len) { + if (nextChange == pos) advanceMarks() + var upto = Math.min(len, nextChange) + while (true) { + if (text) { + var end = pos + text.length + var appliedStyle = style + for (var j = 0; j < marks.length; ++j) { + var mark = marks[j] + appliedStyle = + (appliedStyle ? appliedStyle + ' ' : '') + mark.marker.style + if (mark.marker.endStyle && mark.to === Math.min(end, upto)) + appliedStyle += ' ' + mark.marker.endStyle + if (mark.marker.startStyle && mark.from === pos) + appliedStyle += ' ' + mark.marker.startStyle } + span( + pre, + end > upto ? text.slice(0, upto - pos) : text, + appliedStyle + ) + if (end >= upto) { + text = text.slice(upto - pos) + pos = upto + break + } + pos = end + } + text = st[i++] + style = styleToClass(st[i++]) } - return box; + } } + return pre + }, + cleanUp: function() { + this.parent = null + detachMarkedSpans(this) + } +} - function eltText(node) { - return node.textContent || node.innerText || node.nodeValue || ""; +function LeafChunk(lines) { + this.lines = lines + this.parent = null + for (var i = 0, e = lines.length, height = 0; i < e; ++i) { + lines[i].parent = this + height += lines[i].height + } + this.height = height +} +LeafChunk.prototype = { + chunkSize: function() { + return this.lines.length + }, + remove: function(at, n, callbacks) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i] + this.height -= line.height + line.cleanUp() + if (line.handlers) + for (var j = 0; j < line.handlers.length; ++j) + callbacks.push(line.handlers[j]) } - var spaceStrs = [""]; + this.lines.splice(at, n) + }, + collapse: function(lines) { + lines.splice.apply(lines, [lines.length, 0].concat(this.lines)) + }, + insertHeight: function(at, lines, height) { + this.height += height + this.lines = this.lines + .slice(0, at) + .concat(lines) + .concat(this.lines.slice(at)) + for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this + }, + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) if (op(this.lines[at])) return true + } +} - function spaceStr(n) { - while (spaceStrs.length <= n) - spaceStrs.push(lst(spaceStrs) + " "); - return spaceStrs[n]; +function BranchChunk(children) { + this.children = children + var size = 0, + height = 0 + for (var i = 0, e = children.length; i < e; ++i) { + var ch = children[i] + size += ch.chunkSize() + height += ch.height + ch.parent = this + } + this.size = size + this.height = height + this.parent = null +} +BranchChunk.prototype = { + chunkSize: function() { + return this.size + }, + remove: function(at, n, callbacks) { + this.size -= n + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], + sz = child.chunkSize() + if (at < sz) { + var rm = Math.min(n, sz - at), + oldHeight = child.height + child.remove(at, rm, callbacks) + this.height -= oldHeight - child.height + if (sz == rm) { + this.children.splice(i--, 1) + child.parent = null + } + if ((n -= rm) == 0) break + at = 0 + } else at -= sz } + if (this.size - n < 25) { + var lines = [] + this.collapse(lines) + this.children = [new LeafChunk(lines)] + this.children[0].parent = this + } + }, + collapse: function(lines) { + for (var i = 0, e = this.children.length; i < e; ++i) + this.children[i].collapse(lines) + }, + insert: function(at, lines) { + var height = 0 + for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height + this.insertHeight(at, lines, height) + }, + insertHeight: function(at, lines, height) { + this.size += lines.length + this.height += height + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], + sz = child.chunkSize() + if (at <= sz) { + child.insertHeight(at, lines, height) + if (child.lines && child.lines.length > 50) { + while (child.lines.length > 50) { + var spilled = child.lines.splice(child.lines.length - 25, 25) + var newleaf = new LeafChunk(spilled) + child.height -= newleaf.height + this.children.splice(i + 1, 0, newleaf) + newleaf.parent = this + } + this.maybeSpill() + } + break + } + at -= sz + } + }, + maybeSpill: function() { + if (this.children.length <= 10) return + var me = this + do { + var spilled = me.children.splice(me.children.length - 5, 5) + var sibling = new BranchChunk(spilled) + if (!me.parent) { + var copy = new BranchChunk(me.children) + copy.parent = me + me.children = [copy, sibling] + me = copy + } else { + me.size -= sibling.size + me.height -= sibling.height + var myIndex = indexOf(me.parent.children, me) + me.parent.children.splice(myIndex + 1, 0, sibling) + } + sibling.parent = me.parent + } while (me.children.length > 10) + me.parent.maybeSpill() + }, + iter: function(from, to, op) { + this.iterN(from, to - from, op) + }, + iterN: function(at, n, op) { + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], + sz = child.chunkSize() + if (at < sz) { + var used = Math.min(n, sz - at) + if (child.iterN(at, used, op)) return true + if ((n -= used) == 0) break + at = 0 + } else at -= sz + } + } +} - function lst(arr) { - return arr[arr.length - 1]; +function getLineAt(chunk, n) { + while (!chunk.lines) { + for (var i = 0; ; ++i) { + var child = chunk.children[i], + sz = child.chunkSize() + if (n < sz) { + chunk = child + break + } + n -= sz } + } + return chunk.lines[n] +} - function selectInput(node) { - if (ios) { - node.selectionStart = 0; - node.selectionEnd = node.value.length; - } else node.select(); +function lineNo(line) { + if (line.parent == null) return null + var cur = line.parent, + no = indexOf(cur.lines, line) + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0, e = chunk.children.length; ; ++i) { + if (chunk.children[i] == cur) break + no += chunk.children[i].chunkSize() } + } + return no +} - function posEq(a, b) { - return a.line == b.line && a.ch == b.ch; +function lineAtHeight(chunk, h) { + var n = 0 + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], + ch = child.height + if (h < ch) { + chunk = child + continue outer + } + h -= ch + n += child.chunkSize() } + return n + } while (!chunk.lines) + for (var i = 0, e = chunk.lines.length; i < e; ++i) { + var line = chunk.lines[i], + lh = line.height + if (h < lh) break + h -= lh + } + return n + i +} - function posLess(a, b) { - return a.line < b.line || (a.line == b.line && a.ch < b.ch); +function heightAtLine(chunk, n) { + var h = 0 + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], + sz = child.chunkSize() + if (n < sz) { + chunk = child + continue outer + } + n -= sz + h += child.height } + return h + } while (!chunk.lines) + for (var i = 0; i < n; ++i) h += chunk.lines[i].height + return h +} - function copyPos(x) { - return { - line: x.line, - ch: x.ch - }; +function History() { + this.time = 0 + this.done = [] + this.undone = [] + this.compound = 0 + this.closed = false +} +History.prototype = { + addChange: function(start, added, old) { + this.undone.length = 0 + var time = +new Date(), + cur = lst(this.done), + last = cur && lst(cur) + var dtime = time - this.time + if (cur && !this.closed && this.compound) { + cur.push({ + start: start, + added: added, + old: old + }) + } else if ( + dtime > 400 || + !last || + this.closed || + last.start > start + old.length || + last.start + last.added < start + ) { + this.done.push([ + { + start: start, + added: added, + old: old + } + ]) + this.closed = false + } else { + var startBefore = Math.max(0, last.start - start), + endAfter = Math.max(0, start + old.length - (last.start + last.added)) + for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]) + for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]) + if (startBefore) last.start = start + last.added += added - (old.length - startBefore - endAfter) } + this.time = time + }, + startCompound: function() { + if (!this.compound++) this.closed = true + }, + endCompound: function() { + if (!--this.compound) this.closed = true + } +} - function elt(tag, content, className, style) { - var e = document.createElement(tag); - if (className) e.className = className; - if (style) e.style.cssText = style; - if (typeof content == "string") setTextContent(e, content); - else if (content) - for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); - return e; - } +function stopMethod() { + e_stop(this) +} - function removeChildren(e) { - e.innerHTML = ""; - return e; - } +function addStop(event) { + if (!event.stop) event.stop = stopMethod + return event +} - function removeChildrenAndAdd(parent, e) { - removeChildren(parent).appendChild(e); - } +function e_preventDefault(e) { + if (e.preventDefault) e.preventDefault() + else e.returnValue = false +} - function setTextContent(e, str) { - if (ie_lt9) { - e.innerHTML = ""; - e.appendChild(document.createTextNode(str)); - } else e.textContent = str; - } +function e_stopPropagation(e) { + if (e.stopPropagation) e.stopPropagation() + else e.cancelBubble = true +} - function editEnd(from, to) { - if (!to) return 0; - if (!from) return to.length; - for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j) - if (from.charAt(i) != to.charAt(j)) break; - return j + 1; - } +function e_stop(e) { + e_preventDefault(e) + e_stopPropagation(e) +} +CodeMirror.e_stop = e_stop +CodeMirror.e_preventDefault = e_preventDefault +CodeMirror.e_stopPropagation = e_stopPropagation - function indexOf(collection, elt) { - if (collection.indexOf) return collection.indexOf(elt); - for (var i = 0, e = collection.length; i < e; ++i) - if (collection[i] == elt) return i; - return -1; - } - var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/; +function e_target(e) { + return e.target || e.srcElement +} - function isWordChar(ch) { - return /\w/.test(ch) || ch > "\x80" && (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); +function e_button(e) { + var b = e.which + if (b == null) { + if (e.button & 1) b = 1 + else if (e.button & 2) b = 3 + else if (e.button & 4) b = 2 + } + if (mac && e.ctrlKey && b == 1) b = 3 + return b +} + +function e_prop(e, prop) { + var overridden = e.override && e.override.hasOwnProperty(prop) + return overridden ? e.override[prop] : e[prop] +} + +function connect(node, type, handler, disconnect) { + if (typeof node.addEventListener == 'function') { + node.addEventListener(type, handler, false) + if (disconnect) + return function() { + node.removeEventListener(type, handler, false) + } + } else { + var wrapHandler = function(event) { + handler(event || window.event) } - var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { + node.attachEvent('on' + type, wrapHandler) + if (disconnect) + return function() { + node.detachEvent('on' + type, wrapHandler) + } + } +} +CodeMirror.connect = connect + +function Delayed() { + this.id = null +} +Delayed.prototype = { + set: function(ms, f) { + clearTimeout(this.id) + this.id = setTimeout(f, ms) + } +} +var Pass = (CodeMirror.Pass = { + toString: function() { + return 'CodeMirror.Pass' + } +}) +var dragAndDrop = (function() { + if (ie_lt9) return false + var div = elt('div') + return 'draggable' in div || 'dragDrop' in div +})() +var lineSep = (function() { + var te = elt('textarea') + te.value = 'foo\nbar' + if (te.value.indexOf('\r') > -1) return '\r\n' + return '\n' +})() +var spanAffectsWrapping = /^$/ +if (gecko) spanAffectsWrapping = /$'/ +else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/ +else if (chrome) + spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/ + +function countColumn(string, end, tabSize) { + if (end == null) { + end = string.search(/[^\s\u00a0]/) + if (end == -1) end = string.length + } + for (var i = 0, n = 0; i < end; ++i) { + if (string.charAt(i) == '\t') n += tabSize - n % tabSize + else ++n + } + return n +} + +function eltOffset(node, screen) { + try { + var box = node.getBoundingClientRect() + box = { + top: box.top, + left: box.left + } + } catch (e) { + box = { + top: 0, + left: 0 + } + } + if (!screen) { + if (window.pageYOffset == null) { + var t = document.documentElement || document.body.parentNode + if (t.scrollTop == null) t = document.body + box.top += t.scrollTop + box.left += t.scrollLeft + } else { + box.top += window.pageYOffset + box.left += window.pageXOffset + } + } + return box +} + +function eltText(node) { + return node.textContent || node.innerText || node.nodeValue || '' +} +var spaceStrs = [''] + +function spaceStr(n) { + while (spaceStrs.length <= n) spaceStrs.push(lst(spaceStrs) + ' ') + return spaceStrs[n] +} + +function lst(arr) { + return arr[arr.length - 1] +} + +function selectInput(node) { + if (ios) { + node.selectionStart = 0 + node.selectionEnd = node.value.length + } else node.select() +} + +function posEq(a, b) { + return a.line == b.line && a.ch == b.ch +} + +function posLess(a, b) { + return a.line < b.line || (a.line == b.line && a.ch < b.ch) +} + +function copyPos(x) { + return { + line: x.line, + ch: x.ch + } +} + +function elt(tag, content, className, style) { + var e = document.createElement(tag) + if (className) e.className = className + if (style) e.style.cssText = style + if (typeof content == 'string') setTextContent(e, content) + else if (content) + for (var i = 0; i < content.length; ++i) e.appendChild(content[i]) + return e +} + +function removeChildren(e) { + e.innerHTML = '' + return e +} + +function removeChildrenAndAdd(parent, e) { + removeChildren(parent).appendChild(e) +} + +function setTextContent(e, str) { + if (ie_lt9) { + e.innerHTML = '' + e.appendChild(document.createTextNode(str)) + } else e.textContent = str +} + +function editEnd(from, to) { + if (!to) return 0 + if (!from) return to.length + for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j) + if (from.charAt(i) != to.charAt(j)) break + return j + 1 +} + +function indexOf(collection, elt) { + if (collection.indexOf) return collection.indexOf(elt) + for (var i = 0, e = collection.length; i < e; ++i) + if (collection[i] == elt) return i + return -1 +} +var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/ + +function isWordChar(ch) { + return ( + /\w/.test(ch) || + (ch > '\x80' && + (ch.toUpperCase() != ch.toLowerCase() || + nonASCIISingleCaseWordChar.test(ch))) + ) +} +var splitLines = + '\n\nb'.split(/\n/).length != 3 + ? function(string) { var pos = 0, - result = [], - l = string.length; + result = [], + l = string.length while (pos <= l) { - var nl = string.indexOf("\n", pos); - if (nl == -1) nl = string.length; - var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); - var rt = line.indexOf("\r"); - if (rt != -1) { - result.push(line.slice(0, rt)); - pos += rt + 1; - } else { - result.push(line); - pos = nl + 1; - } + var nl = string.indexOf('\n', pos) + if (nl == -1) nl = string.length + var line = string.slice( + pos, + string.charAt(nl - 1) == '\r' ? nl - 1 : nl + ) + var rt = line.indexOf('\r') + if (rt != -1) { + result.push(line.slice(0, rt)) + pos += rt + 1 + } else { + result.push(line) + pos = nl + 1 + } } - return result; - } : function(string) { - return string.split(/\r\n?|\n/); - }; - CodeMirror.splitLines = splitLines; - var hasSelection = window.getSelection ? function(te) { - try { - return te.selectionStart != te.selectionEnd; - } catch (e) { - return false; - } - } : function(te) { - try { - var range = te.ownerDocument.selection.createRange(); - } catch (e) {} - if (!range || range.parentElement() != te) return false; - return range.compareEndPoints("StartToEnd", range) != 0; - }; - CodeMirror.defineMode("null", function() { - return { - token: function(stream) { - stream.skipToEnd(); - } - }; - }); - CodeMirror.defineMIME("text/plain", "null"); - var keyNames = { - 3: "Enter", - 8: "Backspace", - 9: "Tab", - 13: "Enter", - 16: "Shift", - 17: "Ctrl", - 18: "Alt", - 19: "Pause", - 20: "CapsLock", - 27: "Esc", - 32: "Space", - 33: "PageUp", - 34: "PageDown", - 35: "End", - 36: "Home", - 37: "Left", - 38: "Up", - 39: "Right", - 40: "Down", - 44: "PrintScrn", - 45: "Insert", - 46: "Delete", - 59: ";", - 91: "Mod", - 92: "Mod", - 93: "Mod", - 109: "-", - 107: "=", - 127: "Delete", - 186: ";", - 187: "=", - 188: ",", - 189: "-", - 190: ".", - 191: "/", - 192: "`", - 219: "[", - 220: "\\", - 221: "]", - 222: "'", - 63276: "PageUp", - 63277: "PageDown", - 63275: "End", - 63273: "Home", - 63234: "Left", - 63232: "Up", - 63235: "Right", - 63233: "Down", - 63302: "Insert", - 63272: "Delete" - }; - CodeMirror.keyNames = keyNames; - (function() { - for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); - for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); - for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; - })(); - CodeMirror.version = "2.36"; - return CodeMirror; -}) \ No newline at end of file + return result + } + : function(string) { + return string.split(/\r\n?|\n/) + } +CodeMirror.splitLines = splitLines +var hasSelection = window.getSelection + ? function(te) { + try { + return te.selectionStart != te.selectionEnd + } catch (e) { + return false + } + } + : function(te) { + try { + var range = te.ownerDocument.selection.createRange() + } catch (e) {} + if (!range || range.parentElement() != te) return false + return range.compareEndPoints('StartToEnd', range) != 0 + } +CodeMirror.defineMode('null', function() { + return { + token: function(stream) { + stream.skipToEnd() + } + } +}) +CodeMirror.defineMIME('text/plain', 'null') +var keyNames = { + 3: 'Enter', + 8: 'Backspace', + 9: 'Tab', + 13: 'Enter', + 16: 'Shift', + 17: 'Ctrl', + 18: 'Alt', + 19: 'Pause', + 20: 'CapsLock', + 27: 'Esc', + 32: 'Space', + 33: 'PageUp', + 34: 'PageDown', + 35: 'End', + 36: 'Home', + 37: 'Left', + 38: 'Up', + 39: 'Right', + 40: 'Down', + 44: 'PrintScrn', + 45: 'Insert', + 46: 'Delete', + 59: ';', + 91: 'Mod', + 92: 'Mod', + 93: 'Mod', + 109: '-', + 107: '=', + 127: 'Delete', + 186: ';', + 187: '=', + 188: ',', + 189: '-', + 190: '.', + 191: '/', + 192: '`', + 219: '[', + 220: '\\', + 221: ']', + 222: "'", + 63276: 'PageUp', + 63277: 'PageDown', + 63275: 'End', + 63273: 'Home', + 63234: 'Left', + 63232: 'Up', + 63235: 'Right', + 63233: 'Down', + 63302: 'Insert', + 63272: 'Delete' +} +CodeMirror.keyNames = keyNames +;(function() { + for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i) + for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i) + for (var i = 1; i <= 12; i++) + keyNames[i + 111] = keyNames[i + 63235] = 'F' + i +})() +CodeMirror.version = '2.36' +export default CodeMirror diff --git a/src/js/codemirror/htmlmixed.js b/src/js/codemirror/htmlmixed.js index 5452d58..e297ec6 100644 --- a/src/js/codemirror/htmlmixed.js +++ b/src/js/codemirror/htmlmixed.js @@ -1,1213 +1,2122 @@ -define(["./codemirror", 'css!./theme-dark'], function(CodeMirror) { - CodeMirror.defineMode("htmlmixed", function(config) { - var htmlMode = CodeMirror.getMode(config, { - name: "xml", - htmlMode: true - }); - var jsMode = CodeMirror.getMode(config, "javascript"); - var cssMode = CodeMirror.getMode(config, "css"); +import CodeMirror from './codemirror' +import './theme-dark.scss' - function html(stream, state) { - var style = htmlMode.token(stream, state.htmlState); - if (style == "tag" && stream.current() == ">" && state.htmlState.context) { - if (/^script$/i.test(state.htmlState.context.tagName)) { - state.token = javascript; - state.localState = jsMode.startState(htmlMode.indent(state.htmlState, "")); - } else if (/^style$/i.test(state.htmlState.context.tagName)) { - state.token = css; - state.localState = cssMode.startState(htmlMode.indent(state.htmlState, "")); - } - } - return style; - } +CodeMirror.defineMode( + 'htmlmixed', + function(config) { + var htmlMode = CodeMirror.getMode(config, { + name: 'xml', + htmlMode: true + }) + var jsMode = CodeMirror.getMode(config, 'javascript') + var cssMode = CodeMirror.getMode(config, 'css') - function maybeBackup(stream, pat, style) { - var cur = stream.current(); - var close = cur.search(pat), - m; - if (close > -1) stream.backUp(cur.length - close); - else if (m = cur.match(/<\/?$/)) { - stream.backUp(cur.length); - if (!stream.match(pat, false)) stream.match(cur[0]); - } - return style; + function html(stream, state) { + var style = htmlMode.token(stream, state.htmlState) + if ( + style == 'tag' && + stream.current() == '>' && + state.htmlState.context + ) { + if (/^script$/i.test(state.htmlState.context.tagName)) { + state.token = javascript + state.localState = jsMode.startState( + htmlMode.indent(state.htmlState, '') + ) + } else if (/^style$/i.test(state.htmlState.context.tagName)) { + state.token = css + state.localState = cssMode.startState( + htmlMode.indent(state.htmlState, '') + ) } + } + return style + } - function javascript(stream, state) { - if (stream.match(/^<\/\s*script\s*>/i, false)) { - state.token = html; - state.localState = null; - return html(stream, state); - } - return maybeBackup(stream, /<\/\s*script\s*>/, jsMode.token(stream, state.localState)); - } + function maybeBackup(stream, pat, style) { + var cur = stream.current() + var close = cur.search(pat), + m + if (close > -1) stream.backUp(cur.length - close) + else if ((m = cur.match(/<\/?$/))) { + stream.backUp(cur.length) + if (!stream.match(pat, false)) stream.match(cur[0]) + } + return style + } - function css(stream, state) { - if (stream.match(/^<\/\s*style\s*>/i, false)) { - state.token = html; - state.localState = null; - return html(stream, state); - } - return maybeBackup(stream, /<\/\s*style\s*>/, cssMode.token(stream, state.localState)); - } + function javascript(stream, state) { + if (stream.match(/^<\/\s*script\s*>/i, false)) { + state.token = html + state.localState = null + return html(stream, state) + } + return maybeBackup( + stream, + /<\/\s*script\s*>/, + jsMode.token(stream, state.localState) + ) + } + + function css(stream, state) { + if (stream.match(/^<\/\s*style\s*>/i, false)) { + state.token = html + state.localState = null + return html(stream, state) + } + return maybeBackup( + stream, + /<\/\s*style\s*>/, + cssMode.token(stream, state.localState) + ) + } + return { + startState: function() { + var state = htmlMode.startState() return { - startState: function() { - var state = htmlMode.startState(); - return { - token: html, - localState: null, - mode: "html", - htmlState: state - }; - }, - copyState: function(state) { - if (state.localState) - var local = CodeMirror.copyState(state.token == css ? cssMode : jsMode, state.localState); - return { - token: state.token, - localState: local, - mode: state.mode, - htmlState: CodeMirror.copyState(htmlMode, state.htmlState) - }; - }, - token: function(stream, state) { - return state.token(stream, state); - }, - indent: function(state, textAfter) { - if (state.token == html || /^\s*<\//.test(textAfter)) - return htmlMode.indent(state.htmlState, textAfter); - else if (state.token == javascript) - return jsMode.indent(state.localState, textAfter); - else - return cssMode.indent(state.localState, textAfter); - }, - electricChars: "/{}:", - innerMode: function(state) { - var mode = state.token == html ? htmlMode : state.token == javascript ? jsMode : cssMode; - return { - state: state.localState || state.htmlState, - mode: mode - }; - } - }; - }, "xml", "javascript", "css"); - CodeMirror.defineMIME("text/html", "htmlmixed"); - - CodeMirror.defineMode("css", function(config) { - var indentUnit = config.indentUnit, - type; - var atMediaTypes = keySet(["all", "aural", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "embossed"]); - var atMediaFeatures = keySet(["width", "min-width", "max-width", "height", "min-height", "max-height", "device-width", "min-device-width", "max-device-width", "device-height", "min-device-height", "max-device-height", "aspect-ratio", "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio", "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color", "max-color", "color-index", "min-color-index", "max-color-index", "monochrome", "min-monochrome", "max-monochrome", "resolution", "min-resolution", "max-resolution", "scan", "grid"]); - var propertyKeywords = keySet(["align-content", "align-items", "align-self", "alignment-adjust", "alignment-baseline", "anchor-point", "animation", "animation-delay", "animation-direction", "animation-duration", "animation-iteration-count", "animation-name", "animation-play-state", "animation-timing-function", "appearance", "azimuth", "backface-visibility", "background", "background-attachment", "background-clip", "background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "baseline-shift", "binding", "bleed", "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target", "border", "border-bottom", "border-bottom-color", "border-bottom-left-radius", "border-bottom-right-radius", "border-bottom-style", "border-bottom-width", "border-collapse", "border-color", "border-image", "border-image-outset", "border-image-repeat", "border-image-slice", "border-image-source", "border-image-width", "border-left", "border-left-color", "border-left-style", "border-left-width", "border-radius", "border-right", "border-right-color", "border-right-style", "border-right-width", "border-spacing", "border-style", "border-top", "border-top-color", "border-top-left-radius", "border-top-right-radius", "border-top-style", "border-top-width", "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing", "break-after", "break-before", "break-inside", "caption-side", "clear", "clip", "color", "color-profile", "column-count", "column-fill", "column-gap", "column-rule", "column-rule-color", "column-rule-style", "column-rule-width", "column-span", "column-width", "columns", "content", "counter-increment", "counter-reset", "crop", "cue", "cue-after", "cue-before", "cursor", "direction", "display", "dominant-baseline", "drop-initial-after-adjust", "drop-initial-after-align", "drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size", "drop-initial-value", "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", "float", "float-offset", "font", "font-feature-settings", "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-synthesis", "font-variant", "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", "font-variant-position", "font-weight", "grid-cell", "grid-column", "grid-column-align", "grid-column-sizing", "grid-column-span", "grid-columns", "grid-flow", "grid-row", "grid-row-align", "grid-row-sizing", "grid-row-span", "grid-rows", "grid-template", "hanging-punctuation", "height", "hyphens", "icon", "image-orientation", "image-rendering", "image-resolution", "inline-box-align", "justify-content", "left", "letter-spacing", "line-break", "line-height", "line-stacking", "line-stacking-ruby", "line-stacking-shift", "line-stacking-strategy", "list-style", "list-style-image", "list-style-position", "list-style-type", "margin", "margin-bottom", "margin-left", "margin-right", "margin-top", "marker-offset", "marks", "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed", "marquee-style", "max-height", "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", "nav-left", "nav-right", "nav-up", "opacity", "order", "orphans", "outline", "outline-color", "outline-offset", "outline-style", "outline-width", "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", "page", "page-break-after", "page-break-before", "page-break-inside", "page-policy", "pause", "pause-after", "pause-before", "perspective", "perspective-origin", "pitch", "pitch-range", "play-during", "position", "presentation-level", "punctuation-trim", "quotes", "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", "ruby-position", "ruby-span", "size", "speak", "speak-as", "speak-header", "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", "tab-size", "table-layout", "target", "target-name", "target-new", "target-position", "text-align", "text-align-last", "text-decoration", "text-decoration-color", "text-decoration-line", "text-decoration-skip", "text-decoration-style", "text-emphasis", "text-emphasis-color", "text-emphasis-position", "text-emphasis-style", "text-height", "text-indent", "text-justify", "text-outline", "text-shadow", "text-space-collapse", "text-transform", "text-underline-position", "text-wrap", "top", "transform", "transform-origin", "transform-style", "transition", "transition-delay", "transition-duration", "transition-property", "transition-timing-function", "unicode-bidi", "vertical-align", "visibility", "voice-balance", "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", "voice-volume", "volume", "white-space", "widows", "width", "word-break", "word-spacing", "word-wrap", "z-index"]); - var colorKeywords = keySet(["black", "silver", "gray", "white", "maroon", "red", "purple", "fuchsia", "green", "lime", "olive", "yellow", "navy", "blue", "teal", "aqua"]); - var valueKeywords = keySet(["above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll", "alternate", "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", "arabic-indic", "armenian", "asterisks", "auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", "both", "bottom", "break-all", "break-word", "button", "button-bevel", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", "cjk-earthly-branch", "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote", "col-resize", "collapse", "compact", "condensed", "contain", "content", "content-box", "context-menu", "continuous", "copy", "cover", "crop", "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", "decimal-leading-zero", "default", "default-button", "destination-atop", "destination-in", "destination-out", "destination-over", "devanagari", "disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", "element", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er", "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et", "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "forwards", "from", "geometricPrecision", "georgian", "graytext", "groove", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "help", "hidden", "hide", "higher", "highlight", "highlighttext", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore", "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "kannada", "katakana", "katakana-iroha", "khmer", "landscape", "lao", "large", "larger", "left", "level", "lighter", "line-through", "linear", "lines", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", "lower-roman", "lowercase", "ltr", "malayalam", "match", "media-controls-background", "media-current-time-display", "media-fullscreen-button", "media-mute-button", "media-play-button", "media-return-to-realtime-button", "media-rewind-button", "media-seek-back-button", "media-seek-forward-button", "media-slider", "media-sliderthumb", "media-time-remaining-display", "media-volume-slider", "media-volume-slider-container", "media-volume-sliderthumb", "medium", "menu", "menulist", "menulist-button", "menulist-text", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", "mix", "mongolian", "monospace", "move", "multiple", "myanmar", "n-resize", "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote", "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset", "outside", "overlay", "overline", "padding", "padding-box", "painted", "paused", "persian", "plus-darker", "plus-lighter", "pointer", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button", "radio", "read-only", "read-write", "read-write-plaintext-only", "relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba", "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", "s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield", "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", "searchfield-results-decoration", "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", "single", "skip-white-space", "slide", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", "small", "small-caps", "small-caption", "smaller", "solid", "somali", "source-atop", "source-in", "source-out", "source-over", "space", "square", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "subpixel-antialiased", "super", "sw-resize", "table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row", "table-row-group", "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top", "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal", "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider", "window", "windowframe", "windowtext", "x-large", "x-small", "xor", "xx-large", "xx-small", "yellow"]); - - function keySet(array) { - var keys = {}; - for (var i = 0; i < array.length; ++i) keys[array[i]] = true; - return keys; - } - - function ret(style, tp) { - type = tp; - return style; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == "@") { - stream.eatWhile(/[\w\\\-]/); - return ret("def", stream.current()); - } else if (ch == "/" && stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } else if (ch == "<" && stream.eat("!")) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } else if (ch == "=") ret(null, "compare"); - else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (ch == "#") { - stream.eatWhile(/[\w\\\-]/); - return ret("atom", "hash"); - } else if (ch == "!") { - stream.match(/^\s*\w*/); - return ret("keyword", "important"); - } else if (/\d/.test(ch)) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } else if (ch === "-") { - if (/\d/.test(stream.peek())) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } else if (stream.match(/^[^-]+-/)) { - return ret("meta", type); - } - } else if (/[,+>*\/]/.test(ch)) { - return ret(null, "select-op"); - } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { - return ret("qualifier", type); - } else if (ch == ":") { - return ret("operator", ch); - } else if (/[;{}\[\]\(\)]/.test(ch)) { - return ret(null, ch); - } else { - stream.eatWhile(/[\w\\\-]/); - return ret("property", "variable"); - } - } - - function tokenCComment(stream, state) { - var maybeEnd = false, - ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenSGMLComment(stream, state) { - var dashes = 0, - ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = tokenBase; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, - ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) - break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; + token: html, + localState: null, + mode: 'html', + htmlState: state } + }, + copyState: function(state) { + if (state.localState) + var local = CodeMirror.copyState( + state.token == css ? cssMode : jsMode, + state.localState + ) return { - startState: function(base) { - return { - tokenize: tokenBase, - baseIndent: base || 0, - stack: [] - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - var context = state.stack[state.stack.length - 1]; - if (style == "property") { - if (context == "propertyValue") { - if (valueKeywords[stream.current()]) { - style = "string-2"; - } else if (colorKeywords[stream.current()]) { - style = "keyword"; - } else { - style = "variable-2"; - } - } else if (context == "rule") { - if (!propertyKeywords[stream.current()]) { - style += " error"; - } - } else if (!context || context == "@media{") { - style = "tag"; - } else if (context == "@media") { - if (atMediaTypes[stream.current()]) { - style = "attribute"; - } else if (/^(only|not)$/i.test(stream.current())) { - style = "keyword"; - } else if (stream.current().toLowerCase() == "and") { - style = "error"; - } else if (atMediaFeatures[stream.current()]) { - style = "error"; - } else { - style = "attribute error"; - } - } else if (context == "@mediaType") { - if (atMediaTypes[stream.current()]) { - style = "attribute"; - } else if (stream.current().toLowerCase() == "and") { - style = "operator"; - } else if (/^(only|not)$/i.test(stream.current())) { - style = "error"; - } else if (atMediaFeatures[stream.current()]) { - style = "error"; - } else { - style = "error"; - } - } else if (context == "@mediaType(") { - if (propertyKeywords[stream.current()]) {} else if (atMediaTypes[stream.current()]) { - style = "error"; - } else if (stream.current().toLowerCase() == "and") { - style = "operator"; - } else if (/^(only|not)$/i.test(stream.current())) { - style = "error"; - } else { - style += " error"; - } - } else { - style = "error"; - } - } else if (style == "atom") { - if (!context || context == "@media{") { - style = "builtin"; - } else if (context == "propertyValue") { - if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { - style += " error"; - } - } else { - style = "error"; - } - } else if (context == "@media" && type == "{") { - style = "error"; - } - if (type == "{") { - if (context == "@media" || context == "@mediaType") { - state.stack.pop(); - state.stack[state.stack.length - 1] = "@media{"; - } else state.stack.push("rule"); - } else if (type == "}") { - state.stack.pop(); - if (context == "propertyValue") state.stack.pop(); - } else if (type == "@media") state.stack.push("@media"); - else if (context == "@media" && /\b(keyword|attribute)\b/.test(style)) - state.stack.push("@mediaType"); - else if (context == "@mediaType" && stream.current() == ",") state.stack.pop(); - else if (context == "@mediaType" && type == "(") state.stack.push("@mediaType("); - else if (context == "@mediaType(" && type == ")") state.stack.pop(); - else if (context == "rule" && type == ":") state.stack.push("propertyValue"); - else if (context == "propertyValue" && type == ";") state.stack.pop(); - return style; - }, - indent: function(state, textAfter) { - var n = state.stack.length; - if (/^\}/.test(textAfter)) - n -= state.stack[state.stack.length - 1] == "propertyValue" ? 2 : 1; - return state.baseIndent + n * indentUnit; - }, - electricChars: "}" - }; - }); - CodeMirror.defineMIME("text/css", "css"); - - CodeMirror.defineMode("javascript", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var jsonMode = parserConfig.json; - var isTS = parserConfig.typescript; - var keywords = function() { - function kw(type) { - return { - type: type, - style: "keyword" - }; - } - var A = kw("keyword a"), - B = kw("keyword b"), - C = kw("keyword c"); - var operator = kw("operator"), - atom = { - type: "atom", - style: "atom" - }; - var jsKeywords = { - "if": A, - "while": A, - "with": A, - "else": B, - "async": B, - "await": B, - "*": B, - "yield": B, - "do": B, - "try": B, - "finally": B, - "return": C, - "break": C, - "continue": C, - "new": C, - "delete": C, - "throw": C, - "var": kw("var"), - "const": kw("var"), - "let": kw("var"), - "function": kw("function"), - "require": kw("function"), - "interface": kw("interface"), - "class": kw("class"), - "extends": kw("extends"), - "constructor": kw("constructor"), - "public": kw("public"), - "private": kw("private"), - "protected": kw("protected"), - "static": kw("static"), - "super": kw("super"), - "catch": kw("catch"), - "for": kw("for"), - "switch": kw("switch"), - "case": kw("case"), - "default": kw("default"), - "in": operator, - "typeof": operator, - "instanceof": operator, - "true": atom, - "false": atom, - "null": atom, - "undefined": atom, - "NaN": atom, - "Infinity": atom - }; - if (isTS) { - var type = { - type: "variable", - style: "variable-3" - }; - var tsKeywords = { - "interface": kw("interface"), - "class": kw("class"), - "extends": kw("extends"), - "constructor": kw("constructor"), - "public": kw("public"), - "private": kw("private"), - "protected": kw("protected"), - "static": kw("static"), - "super": kw("super"), - "string": type, - "number": type, - "bool": type, - "any": type - }; - for (var attr in tsKeywords) { - jsKeywords[attr] = tsKeywords[attr]; - } - } - return jsKeywords; - }(); - var isOperatorChar = /[+\-*&%=<>!?|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function nextUntilUnescaped(stream, end) { - var escaped = false, - next; - while ((next = stream.next()) != null) { - if (next == end && !escaped) - return false; - escaped = !escaped && next == "\\"; - } - return escaped; - } - var type, content; - - function ret(tp, style, cont) { - type = tp; - content = cont; - return style; - } - - function jsTokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") - return chain(stream, state, jsTokenString(ch)); - else if (/[\[\]{}\(\),;\:\.]/.test(ch)) - return ret(ch); - else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) { - stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, jsTokenComment); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } else if (state.lastType == "operator" || state.lastType == "keyword c" || /^[\[{}\(,;:]$/.test(state.lastType)) { - nextUntilUnescaped(stream, "/"); - stream.eatWhile(/[gimy]/); - return ret("regexp", "string-2"); - } else { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - } else if (ch == "#") { - stream.skipToEnd(); - return ret("error", "error"); - } else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } else { - stream.eatWhile(/[\w\$_]/); - var word = stream.current(), - known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.lastType != ".") ? ret(known.type, known.style, word) : ret("variable", "variable", word); - } - } - - function jsTokenString(quote) { - return function(stream, state) { - if (!nextUntilUnescaped(stream, quote)) - state.tokenize = jsTokenBase; - return ret("string", "string"); - }; - } - - function jsTokenComment(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = jsTokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - var atomicTypes = { - "atom": true, - "number": true, - "variable": true, - "string": true, - "regexp": true - }; - - function JSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - } - - function parseJS(state, style, type, content, stream) { - var cc = state.cc; - cx.state = state; - cx.stream = stream; - cx.marked = null, cx.cc = cc; - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - while (true) { - var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; - if (combinator(type, content)) { - while (cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - var cx = { - state: null, - column: null, - marked: null, - cc: null - }; - - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - - function cont() { - pass.apply(null, arguments); - return true; - } - - function register(varname) { - var state = cx.state; - if (state.context) { - cx.marked = "def"; - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return; - state.localVars = { - name: varname, - next: state.localVars - }; - } - } - var defaultVars = { - name: "this", - next: { - name: "arguments" - } - }; - - function pushcontext() { - cx.state.context = { - prev: cx.state.context, - vars: cx.state.localVars - }; - cx.state.localVars = defaultVars; - } - - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - - function pushlex(type, info) { - var result = function() { - var state = cx.state; - state.lexical = new JSLexical(state.indented, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - return function expecting(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(arguments.callee); - }; - } - - function statement(type) { - if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), block, poplex); - if (type == ";") return cont(); - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), poplex, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), statement, poplex, popcontext); - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - - function expression(type) { - if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator); - if (type == "function") return cont(functiondef); - if (type == "keyword c") return cont(maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator); - if (type == "operator") return cont(expression); - if (type == "[") return cont(pushlex("]"), commasep(expression, "]"), poplex, maybeoperator); - if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); - return cont(); - } - - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - - function maybeoperator(type, value) { - if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator); - if (type == "operator" && value == "?") return cont(expression, expect(":"), expression); - if (type == ";") return; - if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); - if (type == ".") return cont(property, maybeoperator); - if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); - } - - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperator, expect(";"), poplex); - } - - function property(type) { - if (type == "variable") { - cx.marked = "property"; - return cont(); - } - } - - function objprop(type) { - if (type == "variable") cx.marked = "property"; - if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression); - } - - function commasep(what, end) { - function proceed(type) { - if (type == ",") return cont(what, proceed); - if (type == end) return cont(); - return cont(expect(end)); - } - return function commaSeparated(type) { - if (type == end) return cont(); - else return pass(what, proceed); - }; - } - - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - - function maybetype(type) { - if (type == ":") return cont(typedef); - return pass(); - } - - function typedef(type) { - if (type == "variable") { - cx.marked = "variable-3"; - return cont(); - } - return pass(); - } - - function vardef1(type, value) { - if (type == "variable") { - register(value); - return isTS ? cont(maybetype, vardef2) : cont(vardef2); - } - return pass(); - } - - function vardef2(type, value) { - if (value == "=") return cont(expression, vardef2); - if (type == ",") return cont(vardef1); - } - - function forspec1(type) { - if (type == "var") return cont(vardef1, expect(";"), forspec2); - if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybein); - return cont(forspec2); - } - - function formaybein(type, value) { - if (value == "in") return cont(expression); - return cont(maybeoperator, forspec2); - } - - function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in") return cont(expression); - return cont(expression, expect(";"), forspec3); - } - - function forspec3(type) { - if (type != ")") cont(expression); - } - - function functiondef(type, value) { - if (type == "variable") { - register(value); - return cont(functiondef); - } - if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext); - } - - function funarg(type, value) { - if (type == "variable") { - register(value); - return isTS ? cont(maybetype) : cont(); - } + token: state.token, + localState: local, + mode: state.mode, + htmlState: CodeMirror.copyState(htmlMode, state.htmlState) } + }, + token: function(stream, state) { + return state.token(stream, state) + }, + indent: function(state, textAfter) { + if (state.token == html || /^\s*<\//.test(textAfter)) + return htmlMode.indent(state.htmlState, textAfter) + else if (state.token == javascript) + return jsMode.indent(state.localState, textAfter) + else return cssMode.indent(state.localState, textAfter) + }, + electricChars: '/{}:', + innerMode: function(state) { + var mode = + state.token == html + ? htmlMode + : state.token == javascript ? jsMode : cssMode return { - startState: function(basecolumn) { - return { - tokenize: jsTokenBase, - lastType: null, - cc: [], - lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - context: parserConfig.localVars && { - vars: parserConfig.localVars - }, - indented: 0 - }; - }, - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.lastType = type; - return parseJS(state, style, type, content, stream); - }, - indent: function(state, textAfter) { - if (state.tokenize == jsTokenComment) return CodeMirror.Pass; - if (state.tokenize != jsTokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), - lexical = state.lexical; - if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; - var type = lexical.type, - closing = firstChar == type; - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0); - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "form") return lexical.indented + indentUnit; - else if (type == "stat") - return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? indentUnit : 0); - else if (lexical.info == "switch" && !closing) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - electricChars: ":{}", - jsonMode: jsonMode - }; - }); - CodeMirror.defineMIME("text/javascript", "javascript"); - CodeMirror.defineMIME("application/json", { - name: "javascript", - json: true - }); - CodeMirror.defineMIME("text/typescript", { - name: "javascript", - typescript: true - }); - CodeMirror.defineMIME("application/typescript", { - name: "javascript", - typescript: true - }); - - CodeMirror.defineMode("xml", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var Kludges = parserConfig.htmlMode ? { - autoSelfClosers: { - 'area': true, - 'base': true, - 'br': true, - 'col': true, - 'command': true, - 'embed': true, - 'frame': true, - 'hr': true, - 'img': true, - 'input': true, - 'keygen': true, - 'link': true, - 'meta': true, - 'param': true, - 'source': true, - 'track': true, - 'wbr': true - }, - implicitlyClosed: { - 'dd': true, - 'li': true, - 'optgroup': true, - 'option': true, - 'p': true, - 'rp': true, - 'rt': true, - 'tbody': true, - 'td': true, - 'tfoot': true, - 'th': true, - 'tr': true - }, - contextGrabbers: { - 'dd': { - 'dd': true, - 'dt': true - }, - 'dt': { - 'dd': true, - 'dt': true - }, - 'li': { - 'li': true - }, - 'option': { - 'option': true, - 'optgroup': true - }, - 'optgroup': { - 'optgroup': true - }, - 'p': { - 'address': true, - 'article': true, - 'aside': true, - 'blockquote': true, - 'dir': true, - 'div': true, - 'dl': true, - 'fieldset': true, - 'footer': true, - 'form': true, - 'h1': true, - 'h2': true, - 'h3': true, - 'h4': true, - 'h5': true, - 'h6': true, - 'header': true, - 'hgroup': true, - 'hr': true, - 'menu': true, - 'nav': true, - 'ol': true, - 'p': true, - 'pre': true, - 'section': true, - 'table': true, - 'ul': true - }, - 'rp': { - 'rp': true, - 'rt': true - }, - 'rt': { - 'rp': true, - 'rt': true - }, - 'tbody': { - 'tbody': true, - 'tfoot': true - }, - 'td': { - 'td': true, - 'th': true - }, - 'tfoot': { - 'tbody': true - }, - 'th': { - 'td': true, - 'th': true - }, - 'thead': { - 'tbody': true, - 'tfoot': true - }, - 'tr': { - 'tr': true - } - }, - doNotIndent: { - "pre": true - }, - allowUnquoted: true, - allowMissing: true - } : { - autoSelfClosers: {}, - implicitlyClosed: {}, - contextGrabbers: {}, - doNotIndent: {}, - allowUnquoted: false, - allowMissing: false - }; - var alignCDATA = parserConfig.alignCDATA; - var tagName, type; - - function inText(stream, state) { - function chain(parser) { - state.tokenize = parser; - return parser(stream, state); - } - var ch = stream.next(); - if (ch == "<") { - if (stream.eat("!")) { - if (stream.eat("[")) { - if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); - else return null; - } else if (stream.match("--")) return chain(inBlock("comment", "-->")); - else if (stream.match("DOCTYPE", true, true)) { - stream.eatWhile(/[\w\._\-]/); - return chain(doctype(1)); - } else return null; - } else if (stream.eat("?")) { - stream.eatWhile(/[\w\._\-]/); - state.tokenize = inBlock("meta", "?>"); - return "meta"; - } else { - var isClose = stream.eat("/"); - tagName = ""; - var c; - while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; - if (!tagName) return "error"; - type = isClose ? "closeTag" : "openTag"; - state.tokenize = inTag; - return "tag"; - } - } else if (ch == "&") { - var ok; - if (stream.eat("#")) { - if (stream.eat("x")) { - ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); - } else { - ok = stream.eatWhile(/[\d]/) && stream.eat(";"); - } - } else { - ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); - } - return ok ? "atom" : "error"; - } else { - stream.eatWhile(/[^&<]/); - return null; - } + state: state.localState || state.htmlState, + mode: mode } + } + } + }, + 'xml', + 'javascript', + 'css' +) +CodeMirror.defineMIME('text/html', 'htmlmixed') - function inTag(stream, state) { - var ch = stream.next(); - if (ch == ">" || (ch == "/" && stream.eat(">"))) { - state.tokenize = inText; - type = ch == ">" ? "endTag" : "selfcloseTag"; - return "tag"; - } else if (ch == "=") { - type = "equals"; - return null; - } else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - return state.tokenize(stream, state); - } else { - stream.eatWhile(/[^\s\u00a0=<>\"\']/); - return "word"; - } - } +CodeMirror.defineMode('css', function(config) { + var indentUnit = config.indentUnit, + type + var atMediaTypes = keySet([ + 'all', + 'aural', + 'braille', + 'handheld', + 'print', + 'projection', + 'screen', + 'tty', + 'tv', + 'embossed' + ]) + var atMediaFeatures = keySet([ + 'width', + 'min-width', + 'max-width', + 'height', + 'min-height', + 'max-height', + 'device-width', + 'min-device-width', + 'max-device-width', + 'device-height', + 'min-device-height', + 'max-device-height', + 'aspect-ratio', + 'min-aspect-ratio', + 'max-aspect-ratio', + 'device-aspect-ratio', + 'min-device-aspect-ratio', + 'max-device-aspect-ratio', + 'color', + 'min-color', + 'max-color', + 'color-index', + 'min-color-index', + 'max-color-index', + 'monochrome', + 'min-monochrome', + 'max-monochrome', + 'resolution', + 'min-resolution', + 'max-resolution', + 'scan', + 'grid' + ]) + var propertyKeywords = keySet([ + 'align-content', + 'align-items', + 'align-self', + 'alignment-adjust', + 'alignment-baseline', + 'anchor-point', + 'animation', + 'animation-delay', + 'animation-direction', + 'animation-duration', + 'animation-iteration-count', + 'animation-name', + 'animation-play-state', + 'animation-timing-function', + 'appearance', + 'azimuth', + 'backface-visibility', + 'background', + 'background-attachment', + 'background-clip', + 'background-color', + 'background-image', + 'background-origin', + 'background-position', + 'background-repeat', + 'background-size', + 'baseline-shift', + 'binding', + 'bleed', + 'bookmark-label', + 'bookmark-level', + 'bookmark-state', + 'bookmark-target', + 'border', + 'border-bottom', + 'border-bottom-color', + 'border-bottom-left-radius', + 'border-bottom-right-radius', + 'border-bottom-style', + 'border-bottom-width', + 'border-collapse', + 'border-color', + 'border-image', + 'border-image-outset', + 'border-image-repeat', + 'border-image-slice', + 'border-image-source', + 'border-image-width', + 'border-left', + 'border-left-color', + 'border-left-style', + 'border-left-width', + 'border-radius', + 'border-right', + 'border-right-color', + 'border-right-style', + 'border-right-width', + 'border-spacing', + 'border-style', + 'border-top', + 'border-top-color', + 'border-top-left-radius', + 'border-top-right-radius', + 'border-top-style', + 'border-top-width', + 'border-width', + 'bottom', + 'box-decoration-break', + 'box-shadow', + 'box-sizing', + 'break-after', + 'break-before', + 'break-inside', + 'caption-side', + 'clear', + 'clip', + 'color', + 'color-profile', + 'column-count', + 'column-fill', + 'column-gap', + 'column-rule', + 'column-rule-color', + 'column-rule-style', + 'column-rule-width', + 'column-span', + 'column-width', + 'columns', + 'content', + 'counter-increment', + 'counter-reset', + 'crop', + 'cue', + 'cue-after', + 'cue-before', + 'cursor', + 'direction', + 'display', + 'dominant-baseline', + 'drop-initial-after-adjust', + 'drop-initial-after-align', + 'drop-initial-before-adjust', + 'drop-initial-before-align', + 'drop-initial-size', + 'drop-initial-value', + 'elevation', + 'empty-cells', + 'fit', + 'fit-position', + 'flex', + 'flex-basis', + 'flex-direction', + 'flex-flow', + 'flex-grow', + 'flex-shrink', + 'flex-wrap', + 'float', + 'float-offset', + 'font', + 'font-feature-settings', + 'font-family', + 'font-kerning', + 'font-language-override', + 'font-size', + 'font-size-adjust', + 'font-stretch', + 'font-style', + 'font-synthesis', + 'font-variant', + 'font-variant-alternates', + 'font-variant-caps', + 'font-variant-east-asian', + 'font-variant-ligatures', + 'font-variant-numeric', + 'font-variant-position', + 'font-weight', + 'grid-cell', + 'grid-column', + 'grid-column-align', + 'grid-column-sizing', + 'grid-column-span', + 'grid-columns', + 'grid-flow', + 'grid-row', + 'grid-row-align', + 'grid-row-sizing', + 'grid-row-span', + 'grid-rows', + 'grid-template', + 'hanging-punctuation', + 'height', + 'hyphens', + 'icon', + 'image-orientation', + 'image-rendering', + 'image-resolution', + 'inline-box-align', + 'justify-content', + 'left', + 'letter-spacing', + 'line-break', + 'line-height', + 'line-stacking', + 'line-stacking-ruby', + 'line-stacking-shift', + 'line-stacking-strategy', + 'list-style', + 'list-style-image', + 'list-style-position', + 'list-style-type', + 'margin', + 'margin-bottom', + 'margin-left', + 'margin-right', + 'margin-top', + 'marker-offset', + 'marks', + 'marquee-direction', + 'marquee-loop', + 'marquee-play-count', + 'marquee-speed', + 'marquee-style', + 'max-height', + 'max-width', + 'min-height', + 'min-width', + 'move-to', + 'nav-down', + 'nav-index', + 'nav-left', + 'nav-right', + 'nav-up', + 'opacity', + 'order', + 'orphans', + 'outline', + 'outline-color', + 'outline-offset', + 'outline-style', + 'outline-width', + 'overflow', + 'overflow-style', + 'overflow-wrap', + 'overflow-x', + 'overflow-y', + 'padding', + 'padding-bottom', + 'padding-left', + 'padding-right', + 'padding-top', + 'page', + 'page-break-after', + 'page-break-before', + 'page-break-inside', + 'page-policy', + 'pause', + 'pause-after', + 'pause-before', + 'perspective', + 'perspective-origin', + 'pitch', + 'pitch-range', + 'play-during', + 'position', + 'presentation-level', + 'punctuation-trim', + 'quotes', + 'rendering-intent', + 'resize', + 'rest', + 'rest-after', + 'rest-before', + 'richness', + 'right', + 'rotation', + 'rotation-point', + 'ruby-align', + 'ruby-overhang', + 'ruby-position', + 'ruby-span', + 'size', + 'speak', + 'speak-as', + 'speak-header', + 'speak-numeral', + 'speak-punctuation', + 'speech-rate', + 'stress', + 'string-set', + 'tab-size', + 'table-layout', + 'target', + 'target-name', + 'target-new', + 'target-position', + 'text-align', + 'text-align-last', + 'text-decoration', + 'text-decoration-color', + 'text-decoration-line', + 'text-decoration-skip', + 'text-decoration-style', + 'text-emphasis', + 'text-emphasis-color', + 'text-emphasis-position', + 'text-emphasis-style', + 'text-height', + 'text-indent', + 'text-justify', + 'text-outline', + 'text-shadow', + 'text-space-collapse', + 'text-transform', + 'text-underline-position', + 'text-wrap', + 'top', + 'transform', + 'transform-origin', + 'transform-style', + 'transition', + 'transition-delay', + 'transition-duration', + 'transition-property', + 'transition-timing-function', + 'unicode-bidi', + 'vertical-align', + 'visibility', + 'voice-balance', + 'voice-duration', + 'voice-family', + 'voice-pitch', + 'voice-range', + 'voice-rate', + 'voice-stress', + 'voice-volume', + 'volume', + 'white-space', + 'widows', + 'width', + 'word-break', + 'word-spacing', + 'word-wrap', + 'z-index' + ]) + var colorKeywords = keySet([ + 'black', + 'silver', + 'gray', + 'white', + 'maroon', + 'red', + 'purple', + 'fuchsia', + 'green', + 'lime', + 'olive', + 'yellow', + 'navy', + 'blue', + 'teal', + 'aqua' + ]) + var valueKeywords = keySet([ + 'above', + 'absolute', + 'activeborder', + 'activecaption', + 'afar', + 'after-white-space', + 'ahead', + 'alias', + 'all', + 'all-scroll', + 'alternate', + 'always', + 'amharic', + 'amharic-abegede', + 'antialiased', + 'appworkspace', + 'arabic-indic', + 'armenian', + 'asterisks', + 'auto', + 'avoid', + 'background', + 'backwards', + 'baseline', + 'below', + 'bidi-override', + 'binary', + 'bengali', + 'blink', + 'block', + 'block-axis', + 'bold', + 'bolder', + 'border', + 'border-box', + 'both', + 'bottom', + 'break-all', + 'break-word', + 'button', + 'button-bevel', + 'buttonface', + 'buttonhighlight', + 'buttonshadow', + 'buttontext', + 'cambodian', + 'capitalize', + 'caps-lock-indicator', + 'caption', + 'captiontext', + 'caret', + 'cell', + 'center', + 'checkbox', + 'circle', + 'cjk-earthly-branch', + 'cjk-heavenly-stem', + 'cjk-ideographic', + 'clear', + 'clip', + 'close-quote', + 'col-resize', + 'collapse', + 'compact', + 'condensed', + 'contain', + 'content', + 'content-box', + 'context-menu', + 'continuous', + 'copy', + 'cover', + 'crop', + 'cross', + 'crosshair', + 'currentcolor', + 'cursive', + 'dashed', + 'decimal', + 'decimal-leading-zero', + 'default', + 'default-button', + 'destination-atop', + 'destination-in', + 'destination-out', + 'destination-over', + 'devanagari', + 'disc', + 'discard', + 'document', + 'dot-dash', + 'dot-dot-dash', + 'dotted', + 'double', + 'down', + 'e-resize', + 'ease', + 'ease-in', + 'ease-in-out', + 'ease-out', + 'element', + 'ellipsis', + 'embed', + 'end', + 'ethiopic', + 'ethiopic-abegede', + 'ethiopic-abegede-am-et', + 'ethiopic-abegede-gez', + 'ethiopic-abegede-ti-er', + 'ethiopic-abegede-ti-et', + 'ethiopic-halehame-aa-er', + 'ethiopic-halehame-aa-et', + 'ethiopic-halehame-am-et', + 'ethiopic-halehame-gez', + 'ethiopic-halehame-om-et', + 'ethiopic-halehame-sid-et', + 'ethiopic-halehame-so-et', + 'ethiopic-halehame-ti-er', + 'ethiopic-halehame-ti-et', + 'ethiopic-halehame-tig', + 'ew-resize', + 'expanded', + 'extra-condensed', + 'extra-expanded', + 'fantasy', + 'fast', + 'fill', + 'fixed', + 'flat', + 'footnotes', + 'forwards', + 'from', + 'geometricPrecision', + 'georgian', + 'graytext', + 'groove', + 'gujarati', + 'gurmukhi', + 'hand', + 'hangul', + 'hangul-consonant', + 'hebrew', + 'help', + 'hidden', + 'hide', + 'higher', + 'highlight', + 'highlighttext', + 'hiragana', + 'hiragana-iroha', + 'horizontal', + 'hsl', + 'hsla', + 'icon', + 'ignore', + 'inactiveborder', + 'inactivecaption', + 'inactivecaptiontext', + 'infinite', + 'infobackground', + 'infotext', + 'inherit', + 'initial', + 'inline', + 'inline-axis', + 'inline-block', + 'inline-table', + 'inset', + 'inside', + 'intrinsic', + 'invert', + 'italic', + 'justify', + 'kannada', + 'katakana', + 'katakana-iroha', + 'khmer', + 'landscape', + 'lao', + 'large', + 'larger', + 'left', + 'level', + 'lighter', + 'line-through', + 'linear', + 'lines', + 'list-item', + 'listbox', + 'listitem', + 'local', + 'logical', + 'loud', + 'lower', + 'lower-alpha', + 'lower-armenian', + 'lower-greek', + 'lower-hexadecimal', + 'lower-latin', + 'lower-norwegian', + 'lower-roman', + 'lowercase', + 'ltr', + 'malayalam', + 'match', + 'media-controls-background', + 'media-current-time-display', + 'media-fullscreen-button', + 'media-mute-button', + 'media-play-button', + 'media-return-to-realtime-button', + 'media-rewind-button', + 'media-seek-back-button', + 'media-seek-forward-button', + 'media-slider', + 'media-sliderthumb', + 'media-time-remaining-display', + 'media-volume-slider', + 'media-volume-slider-container', + 'media-volume-sliderthumb', + 'medium', + 'menu', + 'menulist', + 'menulist-button', + 'menulist-text', + 'menulist-textfield', + 'menutext', + 'message-box', + 'middle', + 'min-intrinsic', + 'mix', + 'mongolian', + 'monospace', + 'move', + 'multiple', + 'myanmar', + 'n-resize', + 'narrower', + 'navy', + 'ne-resize', + 'nesw-resize', + 'no-close-quote', + 'no-drop', + 'no-open-quote', + 'no-repeat', + 'none', + 'normal', + 'not-allowed', + 'nowrap', + 'ns-resize', + 'nw-resize', + 'nwse-resize', + 'oblique', + 'octal', + 'open-quote', + 'optimizeLegibility', + 'optimizeSpeed', + 'oriya', + 'oromo', + 'outset', + 'outside', + 'overlay', + 'overline', + 'padding', + 'padding-box', + 'painted', + 'paused', + 'persian', + 'plus-darker', + 'plus-lighter', + 'pointer', + 'portrait', + 'pre', + 'pre-line', + 'pre-wrap', + 'preserve-3d', + 'progress', + 'push-button', + 'radio', + 'read-only', + 'read-write', + 'read-write-plaintext-only', + 'relative', + 'repeat', + 'repeat-x', + 'repeat-y', + 'reset', + 'reverse', + 'rgb', + 'rgba', + 'ridge', + 'right', + 'round', + 'row-resize', + 'rtl', + 'run-in', + 'running', + 's-resize', + 'sans-serif', + 'scroll', + 'scrollbar', + 'se-resize', + 'searchfield', + 'searchfield-cancel-button', + 'searchfield-decoration', + 'searchfield-results-button', + 'searchfield-results-decoration', + 'semi-condensed', + 'semi-expanded', + 'separate', + 'serif', + 'show', + 'sidama', + 'single', + 'skip-white-space', + 'slide', + 'slider-horizontal', + 'slider-vertical', + 'sliderthumb-horizontal', + 'sliderthumb-vertical', + 'slow', + 'small', + 'small-caps', + 'small-caption', + 'smaller', + 'solid', + 'somali', + 'source-atop', + 'source-in', + 'source-out', + 'source-over', + 'space', + 'square', + 'square-button', + 'start', + 'static', + 'status-bar', + 'stretch', + 'stroke', + 'sub', + 'subpixel-antialiased', + 'super', + 'sw-resize', + 'table', + 'table-caption', + 'table-cell', + 'table-column', + 'table-column-group', + 'table-footer-group', + 'table-header-group', + 'table-row', + 'table-row-group', + 'telugu', + 'text', + 'text-bottom', + 'text-top', + 'textarea', + 'textfield', + 'thai', + 'thick', + 'thin', + 'threeddarkshadow', + 'threedface', + 'threedhighlight', + 'threedlightshadow', + 'threedshadow', + 'tibetan', + 'tigre', + 'tigrinya-er', + 'tigrinya-er-abegede', + 'tigrinya-et', + 'tigrinya-et-abegede', + 'to', + 'top', + 'transparent', + 'ultra-condensed', + 'ultra-expanded', + 'underline', + 'up', + 'upper-alpha', + 'upper-armenian', + 'upper-greek', + 'upper-hexadecimal', + 'upper-latin', + 'upper-norwegian', + 'upper-roman', + 'uppercase', + 'urdu', + 'url', + 'vertical', + 'vertical-text', + 'visible', + 'visibleFill', + 'visiblePainted', + 'visibleStroke', + 'visual', + 'w-resize', + 'wait', + 'wave', + 'white', + 'wider', + 'window', + 'windowframe', + 'windowtext', + 'x-large', + 'x-small', + 'xor', + 'xx-large', + 'xx-small', + 'yellow' + ]) - function inAttribute(quote) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inTag; - break; - } - } - return "string"; - }; - } + function keySet(array) { + var keys = {} + for (var i = 0; i < array.length; ++i) keys[array[i]] = true + return keys + } - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - return style; - }; - } + function ret(style, tp) { + type = tp + return style + } - function doctype(depth) { - return function(stream, state) { - var ch; - while ((ch = stream.next()) != null) { - if (ch == "<") { - state.tokenize = doctype(depth + 1); - return state.tokenize(stream, state); - } else if (ch == ">") { - if (depth == 1) { - state.tokenize = inText; - break; - } else { - state.tokenize = doctype(depth - 1); - return state.tokenize(stream, state); - } - } - } - return "meta"; - }; - } - var curState, setStyle; + function tokenBase(stream, state) { + var ch = stream.next() + if (ch == '@') { + stream.eatWhile(/[\w\\\-]/) + return ret('def', stream.current()) + } else if (ch == '/' && stream.eat('*')) { + state.tokenize = tokenCComment + return tokenCComment(stream, state) + } else if (ch == '<' && stream.eat('!')) { + state.tokenize = tokenSGMLComment + return tokenSGMLComment(stream, state) + } else if (ch == '=') ret(null, 'compare') + else if ((ch == '~' || ch == '|') && stream.eat('=')) + return ret(null, 'compare') + else if (ch == '"' || ch == "'") { + state.tokenize = tokenString(ch) + return state.tokenize(stream, state) + } else if (ch == '#') { + stream.eatWhile(/[\w\\\-]/) + return ret('atom', 'hash') + } else if (ch == '!') { + stream.match(/^\s*\w*/) + return ret('keyword', 'important') + } else if (/\d/.test(ch)) { + stream.eatWhile(/[\w.%]/) + return ret('number', 'unit') + } else if (ch === '-') { + if (/\d/.test(stream.peek())) { + stream.eatWhile(/[\w.%]/) + return ret('number', 'unit') + } else if (stream.match(/^[^-]+-/)) { + return ret('meta', type) + } + } else if (/[,+>*\/]/.test(ch)) { + return ret(null, 'select-op') + } else if (ch == '.' && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { + return ret('qualifier', type) + } else if (ch == ':') { + return ret('operator', ch) + } else if (/[;{}\[\]\(\)]/.test(ch)) { + return ret(null, ch) + } else { + stream.eatWhile(/[\w\\\-]/) + return ret('property', 'variable') + } + } - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); - } + function tokenCComment(stream, state) { + var maybeEnd = false, + ch + while ((ch = stream.next()) != null) { + if (maybeEnd && ch == '/') { + state.tokenize = tokenBase + break + } + maybeEnd = ch == '*' + } + return ret('comment', 'comment') + } - function cont() { - pass.apply(null, arguments); - return true; - } + function tokenSGMLComment(stream, state) { + var dashes = 0, + ch + while ((ch = stream.next()) != null) { + if (dashes >= 2 && ch == '>') { + state.tokenize = tokenBase + break + } + dashes = ch == '-' ? dashes + 1 : 0 + } + return ret('comment', 'comment') + } - function pushContext(tagName, startOfLine) { - var noIndent = Kludges.doNotIndent.hasOwnProperty(tagName) || (curState.context && curState.context.noIndent); - curState.context = { - prev: curState.context, - tagName: tagName, - indent: curState.indented, - startOfLine: startOfLine, - noIndent: noIndent - }; + function tokenString(quote) { + return function(stream, state) { + var escaped = false, + ch + while ((ch = stream.next()) != null) { + if (ch == quote && !escaped) break + escaped = !escaped && ch == '\\' + } + if (!escaped) state.tokenize = tokenBase + return ret('string', 'string') + } + } + return { + startState: function(base) { + return { + tokenize: tokenBase, + baseIndent: base || 0, + stack: [] + } + }, + token: function(stream, state) { + if (stream.eatSpace()) return null + var style = state.tokenize(stream, state) + var context = state.stack[state.stack.length - 1] + if (style == 'property') { + if (context == 'propertyValue') { + if (valueKeywords[stream.current()]) { + style = 'string-2' + } else if (colorKeywords[stream.current()]) { + style = 'keyword' + } else { + style = 'variable-2' + } + } else if (context == 'rule') { + if (!propertyKeywords[stream.current()]) { + style += ' error' + } + } else if (!context || context == '@media{') { + style = 'tag' + } else if (context == '@media') { + if (atMediaTypes[stream.current()]) { + style = 'attribute' + } else if (/^(only|not)$/i.test(stream.current())) { + style = 'keyword' + } else if (stream.current().toLowerCase() == 'and') { + style = 'error' + } else if (atMediaFeatures[stream.current()]) { + style = 'error' + } else { + style = 'attribute error' + } + } else if (context == '@mediaType') { + if (atMediaTypes[stream.current()]) { + style = 'attribute' + } else if (stream.current().toLowerCase() == 'and') { + style = 'operator' + } else if (/^(only|not)$/i.test(stream.current())) { + style = 'error' + } else if (atMediaFeatures[stream.current()]) { + style = 'error' + } else { + style = 'error' + } + } else if (context == '@mediaType(') { + if (propertyKeywords[stream.current()]) { + } else if (atMediaTypes[stream.current()]) { + style = 'error' + } else if (stream.current().toLowerCase() == 'and') { + style = 'operator' + } else if (/^(only|not)$/i.test(stream.current())) { + style = 'error' + } else { + style += ' error' + } + } else { + style = 'error' } + } else if (style == 'atom') { + if (!context || context == '@media{') { + style = 'builtin' + } else if (context == 'propertyValue') { + if (!/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) { + style += ' error' + } + } else { + style = 'error' + } + } else if (context == '@media' && type == '{') { + style = 'error' + } + if (type == '{') { + if (context == '@media' || context == '@mediaType') { + state.stack.pop() + state.stack[state.stack.length - 1] = '@media{' + } else state.stack.push('rule') + } else if (type == '}') { + state.stack.pop() + if (context == 'propertyValue') state.stack.pop() + } else if (type == '@media') state.stack.push('@media') + else if (context == '@media' && /\b(keyword|attribute)\b/.test(style)) + state.stack.push('@mediaType') + else if (context == '@mediaType' && stream.current() == ',') + state.stack.pop() + else if (context == '@mediaType' && type == '(') + state.stack.push('@mediaType(') + else if (context == '@mediaType(' && type == ')') state.stack.pop() + else if (context == 'rule' && type == ':') + state.stack.push('propertyValue') + else if (context == 'propertyValue' && type == ';') state.stack.pop() + return style + }, + indent: function(state, textAfter) { + var n = state.stack.length + if (/^\}/.test(textAfter)) + n -= state.stack[state.stack.length - 1] == 'propertyValue' ? 2 : 1 + return state.baseIndent + n * indentUnit + }, + electricChars: '}' + } +}) +CodeMirror.defineMIME('text/css', 'css') - function popContext() { - if (curState.context) curState.context = curState.context.prev; - } +CodeMirror.defineMode('javascript', function(config, parserConfig) { + var indentUnit = config.indentUnit + var jsonMode = parserConfig.json + var isTS = parserConfig.typescript + var keywords = (function() { + function kw(type) { + return { + type: type, + style: 'keyword' + } + } + var A = kw('keyword a'), + B = kw('keyword b'), + C = kw('keyword c') + var operator = kw('operator'), + atom = { + type: 'atom', + style: 'atom' + } + var jsKeywords = { + if: A, + while: A, + with: A, + else: B, + async: B, + await: B, + '*': B, + yield: B, + do: B, + try: B, + finally: B, + return: C, + break: C, + continue: C, + new: C, + delete: C, + throw: C, + var: kw('var'), + const: kw('var'), + let: kw('var'), + function: kw('function'), + require: kw('function'), + interface: kw('interface'), + class: kw('class'), + extends: kw('extends'), + constructor: kw('constructor'), + public: kw('public'), + private: kw('private'), + protected: kw('protected'), + static: kw('static'), + super: kw('super'), + catch: kw('catch'), + for: kw('for'), + switch: kw('switch'), + case: kw('case'), + default: kw('default'), + in: operator, + typeof: operator, + instanceof: operator, + true: atom, + false: atom, + null: atom, + undefined: atom, + NaN: atom, + Infinity: atom + } + if (isTS) { + var type = { + type: 'variable', + style: 'variable-3' + } + var tsKeywords = { + interface: kw('interface'), + class: kw('class'), + extends: kw('extends'), + constructor: kw('constructor'), + public: kw('public'), + private: kw('private'), + protected: kw('protected'), + static: kw('static'), + super: kw('super'), + string: type, + number: type, + bool: type, + any: type + } + for (var attr in tsKeywords) { + jsKeywords[attr] = tsKeywords[attr] + } + } + return jsKeywords + })() + var isOperatorChar = /[+\-*&%=<>!?|]/ - function element(type) { - if (type == "openTag") { - curState.tagName = tagName; - return cont(attributes, endtag(curState.startOfLine)); - } else if (type == "closeTag") { - var err = false; - if (curState.context) { - if (curState.context.tagName != tagName) { - if (Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())) { - popContext(); - } - err = !curState.context || curState.context.tagName != tagName; - } - } else { - err = true; - } - if (err) setStyle = "error"; - return cont(endclosetag(err)); - } - return cont(); - } + function chain(stream, state, f) { + state.tokenize = f + return f(stream, state) + } - function endtag(startOfLine) { - return function(type) { - if (type == "selfcloseTag" || (type == "endTag" && Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))) { - maybePopContext(curState.tagName.toLowerCase()); - return cont(); - } - if (type == "endTag") { - maybePopContext(curState.tagName.toLowerCase()); - pushContext(curState.tagName, startOfLine); - return cont(); - } - return cont(); - }; - } + function nextUntilUnescaped(stream, end) { + var escaped = false, + next + while ((next = stream.next()) != null) { + if (next == end && !escaped) return false + escaped = !escaped && next == '\\' + } + return escaped + } + var type, content - function endclosetag(err) { - return function(type) { - if (err) setStyle = "error"; - if (type == "endTag") { - popContext(); - return cont(); - } - setStyle = "error"; - return cont(arguments.callee); - }; - } + function ret(tp, style, cont) { + type = tp + content = cont + return style + } - function maybePopContext(nextTagName) { - var parentTagName; - while (true) { - if (!curState.context) { - return; - } - parentTagName = curState.context.tagName.toLowerCase(); - if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) || !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { - return; - } - popContext(); - } - } + function jsTokenBase(stream, state) { + var ch = stream.next() + if (ch == '"' || ch == "'") return chain(stream, state, jsTokenString(ch)) + else if (/[\[\]{}\(\),;\:\.]/.test(ch)) return ret(ch) + else if (ch == '0' && stream.eat(/x/i)) { + stream.eatWhile(/[\da-f]/i) + return ret('number', 'number') + } else if (/\d/.test(ch) || (ch == '-' && stream.eat(/\d/))) { + stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/) + return ret('number', 'number') + } else if (ch == '/') { + if (stream.eat('*')) { + return chain(stream, state, jsTokenComment) + } else if (stream.eat('/')) { + stream.skipToEnd() + return ret('comment', 'comment') + } else if ( + state.lastType == 'operator' || + state.lastType == 'keyword c' || + /^[\[{}\(,;:]$/.test(state.lastType) + ) { + nextUntilUnescaped(stream, '/') + stream.eatWhile(/[gimy]/) + return ret('regexp', 'string-2') + } else { + stream.eatWhile(isOperatorChar) + return ret('operator', null, stream.current()) + } + } else if (ch == '#') { + stream.skipToEnd() + return ret('error', 'error') + } else if (isOperatorChar.test(ch)) { + stream.eatWhile(isOperatorChar) + return ret('operator', null, stream.current()) + } else { + stream.eatWhile(/[\w\$_]/) + var word = stream.current(), + known = keywords.propertyIsEnumerable(word) && keywords[word] + return known && state.lastType != '.' + ? ret(known.type, known.style, word) + : ret('variable', 'variable', word) + } + } - function attributes(type) { - if (type == "word") { - setStyle = "attribute"; - return cont(attribute, attributes); - } - if (type == "endTag" || type == "selfcloseTag") return pass(); - setStyle = "error"; - return cont(attributes); - } + function jsTokenString(quote) { + return function(stream, state) { + if (!nextUntilUnescaped(stream, quote)) state.tokenize = jsTokenBase + return ret('string', 'string') + } + } - function attribute(type) { - if (type == "equals") return cont(attvalue, attributes); - if (!Kludges.allowMissing) setStyle = "error"; - else if (type == "word") setStyle = "attribute"; - return (type == "endTag" || type == "selfcloseTag") ? pass() : cont(); - } + function jsTokenComment(stream, state) { + var maybeEnd = false, + ch + while ((ch = stream.next())) { + if (ch == '/' && maybeEnd) { + state.tokenize = jsTokenBase + break + } + maybeEnd = ch == '*' + } + return ret('comment', 'comment') + } + var atomicTypes = { + atom: true, + number: true, + variable: true, + string: true, + regexp: true + } - function attvalue(type) { - if (type == "string") return cont(attvaluemaybe); - if (type == "word" && Kludges.allowUnquoted) { - setStyle = "string"; - return cont(); - } - setStyle = "error"; - return (type == "endTag" || type == "selfCloseTag") ? pass() : cont(); - } + function JSLexical(indented, column, type, align, prev, info) { + this.indented = indented + this.column = column + this.type = type + this.prev = prev + this.info = info + if (align != null) this.align = align + } - function attvaluemaybe(type) { - if (type == "string") return cont(attvaluemaybe); - else return pass(); + function inScope(state, varname) { + for (var v = state.localVars; v; v = v.next) + if (v.name == varname) return true + } + + function parseJS(state, style, type, content, stream) { + var cc = state.cc + cx.state = state + cx.stream = stream + ;(cx.marked = null), (cx.cc = cc) + if (!state.lexical.hasOwnProperty('align')) state.lexical.align = true + while (true) { + var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement + if (combinator(type, content)) { + while (cc.length && cc[cc.length - 1].lex) cc.pop()() + if (cx.marked) return cx.marked + if (type == 'variable' && inScope(state, content)) return 'variable-2' + return style + } + } + } + var cx = { + state: null, + column: null, + marked: null, + cc: null + } + + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]) + } + + function cont() { + pass.apply(null, arguments) + return true + } + + function register(varname) { + var state = cx.state + if (state.context) { + cx.marked = 'def' + for (var v = state.localVars; v; v = v.next) if (v.name == varname) return + state.localVars = { + name: varname, + next: state.localVars + } + } + } + var defaultVars = { + name: 'this', + next: { + name: 'arguments' + } + } + + function pushcontext() { + cx.state.context = { + prev: cx.state.context, + vars: cx.state.localVars + } + cx.state.localVars = defaultVars + } + + function popcontext() { + cx.state.localVars = cx.state.context.vars + cx.state.context = cx.state.context.prev + } + + function pushlex(type, info) { + var result = function() { + var state = cx.state + state.lexical = new JSLexical( + state.indented, + cx.stream.column(), + type, + null, + state.lexical, + info + ) + } + result.lex = true + return result + } + + function poplex() { + var state = cx.state + if (state.lexical.prev) { + if (state.lexical.type == ')') state.indented = state.lexical.indented + state.lexical = state.lexical.prev + } + } + poplex.lex = true + + function expect(wanted) { + return function expecting(type) { + if (type == wanted) return cont() + else if (wanted == ';') return pass() + else return cont(arguments.callee) + } + } + + function statement(type) { + if (type == 'var') + return cont(pushlex('vardef'), vardef1, expect(';'), poplex) + if (type == 'keyword a') + return cont(pushlex('form'), expression, statement, poplex) + if (type == 'keyword b') return cont(pushlex('form'), statement, poplex) + if (type == '{') return cont(pushlex('}'), block, poplex) + if (type == ';') return cont() + if (type == 'function') return cont(functiondef) + if (type == 'for') + return cont( + pushlex('form'), + expect('('), + pushlex(')'), + forspec1, + expect(')'), + poplex, + statement, + poplex + ) + if (type == 'variable') return cont(pushlex('stat'), maybelabel) + if (type == 'switch') + return cont( + pushlex('form'), + expression, + pushlex('}', 'switch'), + expect('{'), + block, + poplex, + poplex + ) + if (type == 'case') return cont(expression, expect(':')) + if (type == 'default') return cont(expect(':')) + if (type == 'catch') + return cont( + pushlex('form'), + pushcontext, + expect('('), + funarg, + expect(')'), + statement, + poplex, + popcontext + ) + return pass(pushlex('stat'), expression, expect(';'), poplex) + } + + function expression(type) { + if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator) + if (type == 'function') return cont(functiondef) + if (type == 'keyword c') return cont(maybeexpression) + if (type == '(') + return cont( + pushlex(')'), + maybeexpression, + expect(')'), + poplex, + maybeoperator + ) + if (type == 'operator') return cont(expression) + if (type == '[') + return cont( + pushlex(']'), + commasep(expression, ']'), + poplex, + maybeoperator + ) + if (type == '{') + return cont(pushlex('}'), commasep(objprop, '}'), poplex, maybeoperator) + return cont() + } + + function maybeexpression(type) { + if (type.match(/[;\}\)\],]/)) return pass() + return pass(expression) + } + + function maybeoperator(type, value) { + if (type == 'operator' && /\+\+|--/.test(value)) return cont(maybeoperator) + if (type == 'operator' && value == '?') + return cont(expression, expect(':'), expression) + if (type == ';') return + if (type == '(') + return cont( + pushlex(')'), + commasep(expression, ')'), + poplex, + maybeoperator + ) + if (type == '.') return cont(property, maybeoperator) + if (type == '[') + return cont(pushlex(']'), expression, expect(']'), poplex, maybeoperator) + } + + function maybelabel(type) { + if (type == ':') return cont(poplex, statement) + return pass(maybeoperator, expect(';'), poplex) + } + + function property(type) { + if (type == 'variable') { + cx.marked = 'property' + return cont() + } + } + + function objprop(type) { + if (type == 'variable') cx.marked = 'property' + if (atomicTypes.hasOwnProperty(type)) return cont(expect(':'), expression) + } + + function commasep(what, end) { + function proceed(type) { + if (type == ',') return cont(what, proceed) + if (type == end) return cont() + return cont(expect(end)) + } + return function commaSeparated(type) { + if (type == end) return cont() + else return pass(what, proceed) + } + } + + function block(type) { + if (type == '}') return cont() + return pass(statement, block) + } + + function maybetype(type) { + if (type == ':') return cont(typedef) + return pass() + } + + function typedef(type) { + if (type == 'variable') { + cx.marked = 'variable-3' + return cont() + } + return pass() + } + + function vardef1(type, value) { + if (type == 'variable') { + register(value) + return isTS ? cont(maybetype, vardef2) : cont(vardef2) + } + return pass() + } + + function vardef2(type, value) { + if (value == '=') return cont(expression, vardef2) + if (type == ',') return cont(vardef1) + } + + function forspec1(type) { + if (type == 'var') return cont(vardef1, expect(';'), forspec2) + if (type == ';') return cont(forspec2) + if (type == 'variable') return cont(formaybein) + return cont(forspec2) + } + + function formaybein(type, value) { + if (value == 'in') return cont(expression) + return cont(maybeoperator, forspec2) + } + + function forspec2(type, value) { + if (type == ';') return cont(forspec3) + if (value == 'in') return cont(expression) + return cont(expression, expect(';'), forspec3) + } + + function forspec3(type) { + if (type != ')') cont(expression) + } + + function functiondef(type, value) { + if (type == 'variable') { + register(value) + return cont(functiondef) + } + if (type == '(') + return cont( + pushlex(')'), + pushcontext, + commasep(funarg, ')'), + poplex, + statement, + popcontext + ) + } + + function funarg(type, value) { + if (type == 'variable') { + register(value) + return isTS ? cont(maybetype) : cont() + } + } + return { + startState: function(basecolumn) { + return { + tokenize: jsTokenBase, + lastType: null, + cc: [], + lexical: new JSLexical( + (basecolumn || 0) - indentUnit, + 0, + 'block', + false + ), + localVars: parserConfig.localVars, + context: parserConfig.localVars && { + vars: parserConfig.localVars + }, + indented: 0 + } + }, + token: function(stream, state) { + if (stream.sol()) { + if (!state.lexical.hasOwnProperty('align')) state.lexical.align = false + state.indented = stream.indentation() + } + if (stream.eatSpace()) return null + var style = state.tokenize(stream, state) + if (type == 'comment') return style + state.lastType = type + return parseJS(state, style, type, content, stream) + }, + indent: function(state, textAfter) { + if (state.tokenize == jsTokenComment) return CodeMirror.Pass + if (state.tokenize != jsTokenBase) return 0 + var firstChar = textAfter && textAfter.charAt(0), + lexical = state.lexical + if (lexical.type == 'stat' && firstChar == '}') lexical = lexical.prev + var type = lexical.type, + closing = firstChar == type + if (type == 'vardef') + return ( + lexical.indented + + (state.lastType == 'operator' || state.lastType == ',' ? 4 : 0) + ) + else if (type == 'form' && firstChar == '{') return lexical.indented + else if (type == 'form') return lexical.indented + indentUnit + else if (type == 'stat') + return ( + lexical.indented + + (state.lastType == 'operator' || state.lastType == ',' + ? indentUnit + : 0) + ) + else if (lexical.info == 'switch' && !closing) + return ( + lexical.indented + + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit) + ) + else if (lexical.align) return lexical.column + (closing ? 0 : 1) + else return lexical.indented + (closing ? 0 : indentUnit) + }, + electricChars: ':{}', + jsonMode: jsonMode + } +}) +CodeMirror.defineMIME('text/javascript', 'javascript') +CodeMirror.defineMIME('application/json', { + name: 'javascript', + json: true +}) +CodeMirror.defineMIME('text/typescript', { + name: 'javascript', + typescript: true +}) +CodeMirror.defineMIME('application/typescript', { + name: 'javascript', + typescript: true +}) + +CodeMirror.defineMode('xml', function(config, parserConfig) { + var indentUnit = config.indentUnit + var Kludges = parserConfig.htmlMode + ? { + autoSelfClosers: { + area: true, + base: true, + br: true, + col: true, + command: true, + embed: true, + frame: true, + hr: true, + img: true, + input: true, + keygen: true, + link: true, + meta: true, + param: true, + source: true, + track: true, + wbr: true + }, + implicitlyClosed: { + dd: true, + li: true, + optgroup: true, + option: true, + p: true, + rp: true, + rt: true, + tbody: true, + td: true, + tfoot: true, + th: true, + tr: true + }, + contextGrabbers: { + dd: { + dd: true, + dt: true + }, + dt: { + dd: true, + dt: true + }, + li: { + li: true + }, + option: { + option: true, + optgroup: true + }, + optgroup: { + optgroup: true + }, + p: { + address: true, + article: true, + aside: true, + blockquote: true, + dir: true, + div: true, + dl: true, + fieldset: true, + footer: true, + form: true, + h1: true, + h2: true, + h3: true, + h4: true, + h5: true, + h6: true, + header: true, + hgroup: true, + hr: true, + menu: true, + nav: true, + ol: true, + p: true, + pre: true, + section: true, + table: true, + ul: true + }, + rp: { + rp: true, + rt: true + }, + rt: { + rp: true, + rt: true + }, + tbody: { + tbody: true, + tfoot: true + }, + td: { + td: true, + th: true + }, + tfoot: { + tbody: true + }, + th: { + td: true, + th: true + }, + thead: { + tbody: true, + tfoot: true + }, + tr: { + tr: true + } + }, + doNotIndent: { + pre: true + }, + allowUnquoted: true, + allowMissing: true + } + : { + autoSelfClosers: {}, + implicitlyClosed: {}, + contextGrabbers: {}, + doNotIndent: {}, + allowUnquoted: false, + allowMissing: false + } + var alignCDATA = parserConfig.alignCDATA + var tagName, type + + function inText(stream, state) { + function chain(parser) { + state.tokenize = parser + return parser(stream, state) + } + var ch = stream.next() + if (ch == '<') { + if (stream.eat('!')) { + if (stream.eat('[')) { + if (stream.match('CDATA[')) return chain(inBlock('atom', ']]>')) + else return null + } else if (stream.match('--')) return chain(inBlock('comment', '-->')) + else if (stream.match('DOCTYPE', true, true)) { + stream.eatWhile(/[\w\._\-]/) + return chain(doctype(1)) + } else return null + } else if (stream.eat('?')) { + stream.eatWhile(/[\w\._\-]/) + state.tokenize = inBlock('meta', '?>') + return 'meta' + } else { + var isClose = stream.eat('/') + tagName = '' + var c + while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c + if (!tagName) return 'error' + type = isClose ? 'closeTag' : 'openTag' + state.tokenize = inTag + return 'tag' + } + } else if (ch == '&') { + var ok + if (stream.eat('#')) { + if (stream.eat('x')) { + ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(';') + } else { + ok = stream.eatWhile(/[\d]/) && stream.eat(';') } - return { - startState: function() { - return { - tokenize: inText, - cc: [], - indented: 0, - startOfLine: true, - tagName: null, - context: null - }; - }, - token: function(stream, state) { - if (stream.sol()) { - state.startOfLine = true; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - setStyle = type = tagName = null; - var style = state.tokenize(stream, state); - state.type = type; - if ((style || type) && style != "comment") { - curState = state; - while (true) { - var comb = state.cc.pop() || element; - if (comb(type || style)) break; - } - } - state.startOfLine = false; - return setStyle || style; - }, - indent: function(state, textAfter, fullLine) { - var context = state.context; - if ((state.tokenize != inTag && state.tokenize != inText) || context && context.noIndent) - return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; - if (alignCDATA && /' || (ch == '/' && stream.eat('>'))) { + state.tokenize = inText + type = ch == '>' ? 'endTag' : 'selfcloseTag' + return 'tag' + } else if (ch == '=') { + type = 'equals' + return null + } else if (/[\'\"]/.test(ch)) { + state.tokenize = inAttribute(ch) + return state.tokenize(stream, state) + } else { + stream.eatWhile(/[^\s\u00a0=<>\"\']/) + return 'word' + } + } + + function inAttribute(quote) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.next() == quote) { + state.tokenize = inTag + break + } + } + return 'string' + } + } + + function inBlock(style, terminator) { + return function(stream, state) { + while (!stream.eol()) { + if (stream.match(terminator)) { + state.tokenize = inText + break + } + stream.next() + } + return style + } + } + + function doctype(depth) { + return function(stream, state) { + var ch + while ((ch = stream.next()) != null) { + if (ch == '<') { + state.tokenize = doctype(depth + 1) + return state.tokenize(stream, state) + } else if (ch == '>') { + if (depth == 1) { + state.tokenize = inText + break + } else { + state.tokenize = doctype(depth - 1) + return state.tokenize(stream, state) + } + } + } + return 'meta' + } + } + var curState, setStyle + + function pass() { + for (var i = arguments.length - 1; i >= 0; i--) + curState.cc.push(arguments[i]) + } + + function cont() { + pass.apply(null, arguments) + return true + } + + function pushContext(tagName, startOfLine) { + var noIndent = + Kludges.doNotIndent.hasOwnProperty(tagName) || + (curState.context && curState.context.noIndent) + curState.context = { + prev: curState.context, + tagName: tagName, + indent: curState.indented, + startOfLine: startOfLine, + noIndent: noIndent + } + } + + function popContext() { + if (curState.context) curState.context = curState.context.prev + } + + function element(type) { + if (type == 'openTag') { + curState.tagName = tagName + return cont(attributes, endtag(curState.startOfLine)) + } else if (type == 'closeTag') { + var err = false + if (curState.context) { + if (curState.context.tagName != tagName) { + if ( + Kludges.implicitlyClosed.hasOwnProperty( + curState.context.tagName.toLowerCase() + ) + ) { + popContext() + } + err = !curState.context || curState.context.tagName != tagName + } + } else { + err = true + } + if (err) setStyle = 'error' + return cont(endclosetag(err)) + } + return cont() + } + + function endtag(startOfLine) { + return function(type) { + if ( + type == 'selfcloseTag' || + (type == 'endTag' && + Kludges.autoSelfClosers.hasOwnProperty( + curState.tagName.toLowerCase() + )) + ) { + maybePopContext(curState.tagName.toLowerCase()) + return cont() + } + if (type == 'endTag') { + maybePopContext(curState.tagName.toLowerCase()) + pushContext(curState.tagName, startOfLine) + return cont() + } + return cont() + } + } + + function endclosetag(err) { + return function(type) { + if (err) setStyle = 'error' + if (type == 'endTag') { + popContext() + return cont() + } + setStyle = 'error' + return cont(arguments.callee) + } + } + + function maybePopContext(nextTagName) { + var parentTagName + while (true) { + if (!curState.context) { + return + } + parentTagName = curState.context.tagName.toLowerCase() + if ( + !Kludges.contextGrabbers.hasOwnProperty(parentTagName) || + !Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName) + ) { + return + } + popContext() + } + } + + function attributes(type) { + if (type == 'word') { + setStyle = 'attribute' + return cont(attribute, attributes) + } + if (type == 'endTag' || type == 'selfcloseTag') return pass() + setStyle = 'error' + return cont(attributes) + } + + function attribute(type) { + if (type == 'equals') return cont(attvalue, attributes) + if (!Kludges.allowMissing) setStyle = 'error' + else if (type == 'word') setStyle = 'attribute' + return type == 'endTag' || type == 'selfcloseTag' ? pass() : cont() + } + + function attvalue(type) { + if (type == 'string') return cont(attvaluemaybe) + if (type == 'word' && Kludges.allowUnquoted) { + setStyle = 'string' + return cont() + } + setStyle = 'error' + return type == 'endTag' || type == 'selfCloseTag' ? pass() : cont() + } + + function attvaluemaybe(type) { + if (type == 'string') return cont(attvaluemaybe) + else return pass() + } + return { + startState: function() { + return { + tokenize: inText, + cc: [], + indented: 0, + startOfLine: true, + tagName: null, + context: null + } + }, + token: function(stream, state) { + if (stream.sol()) { + state.startOfLine = true + state.indented = stream.indentation() + } + if (stream.eatSpace()) return null + setStyle = type = tagName = null + var style = state.tokenize(stream, state) + state.type = type + if ((style || type) && style != 'comment') { + curState = state + while (true) { + var comb = state.cc.pop() || element + if (comb(type || style)) break + } + } + state.startOfLine = false + return setStyle || style + }, + indent: function(state, textAfter, fullLine) { + var context = state.context + if ( + (state.tokenize != inTag && state.tokenize != inText) || + (context && context.noIndent) + ) + return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0 + if (alignCDATA && / { + if (it.__checked__) { + this.checkedItems[it[this.props.id]] = it.$model + } + }) if (typeof this.props.created === 'function') { this.props.created(this) }