diff --git a/.gitignore b/.gitignore index 7b99fd1..4609d10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .DS_Store ._.DS_Store node_modules +dist +dist-electron diff --git a/README.md b/README.md index 53e171a..f91d2de 100644 --- a/README.md +++ b/README.md @@ -84,20 +84,33 @@ This is a list of all the **options** you can set up: ![](http://patriciogonzalezvivo.com/images/glslEditor/debugger.gif) -## Electron Version -When developing use this to automatically reload Electron on every change +## Browser Version +Runs glslEditor in your favourite Browser™ ```bash -npm run dev +npm run browser ``` -For use just do: +or ```bash -npm run start +yarn browser ``` +## Electron Version +Runs glslEditor in [electron](https://www.electronjs.org/) +When developing use this to automatically reload Electron on every change + +```bash +npm run electron +``` + +or + +```bash +yarn electron +``` ## TODOs diff --git a/build/glslEditor.css b/build/glslEditor.css deleted file mode 100644 index 58724e1..0000000 --- a/build/glslEditor.css +++ /dev/null @@ -1,2 +0,0 @@ -@charset 'utf-8';.CodeMirror{font-family:monospace;height:300px;color:black}.CodeMirror-lines{padding:4px 0}.CodeMirror pre{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:white}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:black}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-animate-fat-cursor{width:auto;border:0;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-ruler{border-left:1px solid #ccc;position:absolute}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error{color:#f00}.cm-invalidchar{color:#f00}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0f0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#f22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:white}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:none;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;margin-bottom:-30px;*zoom:1;*display:inline}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper{-webkit-user-select:none;-ms-user-select:none;user-select:none}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre{border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent}.CodeMirror-wrap pre{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;overflow:auto}.CodeMirror-code{outline:none}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background:#ffa;background:rgba(255,255,0,.4)}.CodeMirror span{*vertical-align:text-bottom}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:none}.CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.CodeMirror-dialog button{font-size:70%}.CodeMirror-foldmarker{color:blue;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.CodeMirror-foldgutter{width:.7em}.CodeMirror-foldgutter-open,.CodeMirror-foldgutter-folded{cursor:pointer}.CodeMirror-foldgutter-open:after{content:"\25BE"}.CodeMirror-foldgutter-folded:after{content:"\25B8"}.CodeMirror-hints{position:absolute;z-index:10;overflow:hidden;list-style:none;margin:0;padding:2px;box-shadow:2px 3px 5px rgba(0,0,0,.2);border-radius:3px;border:1px solid silver;background:white;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;max-width:19em;overflow:hidden;white-space:pre;color:black;cursor:pointer}li.CodeMirror-hint-active{background:#08f;color:white}.cm-s-ambiance .cm-header{color:blue}.cm-s-ambiance .cm-quote{color:#24c2c7}.cm-s-ambiance .cm-keyword{color:#cda869}.cm-s-ambiance .cm-atom{color:#cf7ea9}.cm-s-ambiance .cm-number{color:#78cf8a}.cm-s-ambiance .cm-def{color:#aac6e3}.cm-s-ambiance .cm-variable{color:#ffb795}.cm-s-ambiance .cm-variable-2{color:#eed1b3}.cm-s-ambiance .cm-variable-3{color:#faded3}.cm-s-ambiance .cm-property{color:#eed1b3}.cm-s-ambiance .cm-operator{color:#fa8d6a}.cm-s-ambiance .cm-comment{color:#555;font-style:italic}.cm-s-ambiance .cm-string{color:#8f9d6a}.cm-s-ambiance .cm-string-2{color:#9d937c}.cm-s-ambiance .cm-meta{color:#d2a8a1}.cm-s-ambiance .cm-qualifier{color:yellow}.cm-s-ambiance .cm-builtin{color:#99c}.cm-s-ambiance .cm-bracket{color:#24c2c7}.cm-s-ambiance .cm-tag{color:#fee4ff}.cm-s-ambiance .cm-attribute{color:#9b859d}.cm-s-ambiance .cm-hr{color:pink}.cm-s-ambiance .cm-link{color:#f4c20b}.cm-s-ambiance .cm-special{color:#ff9d00}.cm-s-ambiance .cm-error{color:#af2018}.cm-s-ambiance .CodeMirror-matchingbracket{color:#0f0}.cm-s-ambiance .CodeMirror-nonmatchingbracket{color:#f22}.cm-s-ambiance div.CodeMirror-selected{background:rgba(255,255,255,.15)}.cm-s-ambiance.CodeMirror-focused div.CodeMirror-selected{background:rgba(255,255,255,.1)}.cm-s-ambiance .CodeMirror-line::selection,.cm-s-ambiance .CodeMirror-line>span::selection,.cm-s-ambiance .CodeMirror-line>span>span::selection{background:rgba(255,255,255,.1)}.cm-s-ambiance .CodeMirror-line::-moz-selection,.cm-s-ambiance .CodeMirror-line>span::-moz-selection,.cm-s-ambiance .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,.1)}.cm-s-ambiance.CodeMirror{line-height:1.4em;color:#e6e1dc;background-color:#202020;box-shadow:inset 0 0 10px black}.cm-s-ambiance .CodeMirror-gutters{background:#3d3d3d;border-right:1px solid #4d4d4d;box-shadow:0 10px 20px black}.cm-s-ambiance .CodeMirror-linenumber{text-shadow:0 1px 1px #4d4d4d;color:#111;padding:0 5px}.cm-s-ambiance .CodeMirror-guttermarker{color:#aaa}.cm-s-ambiance .CodeMirror-guttermarker-subtle{color:#111}.cm-s-ambiance .CodeMirror-cursor{border-left:1px solid #7991e8}.cm-s-ambiance .CodeMirror-activeline-background{background:none repeat scroll 0 0 rgba(255,255,255,.031)}.cm-s-ambiance.CodeMirror,.cm-s-ambiance .CodeMirror-gutters{background-image:url(data:image/png;base64,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)}.cm-s-base16-dark.CodeMirror{background:#151515;color:#e0e0e0}.cm-s-base16-dark div.CodeMirror-selected{background:#303030}.cm-s-base16-dark .CodeMirror-line::selection,.cm-s-base16-dark .CodeMirror-line>span::selection,.cm-s-base16-dark .CodeMirror-line>span>span::selection{background:rgba(48,48,48,.99)}.cm-s-base16-dark .CodeMirror-line::-moz-selection,.cm-s-base16-dark .CodeMirror-line>span::-moz-selection,.cm-s-base16-dark .CodeMirror-line>span>span::-moz-selection{background:rgba(48,48,48,.99)}.cm-s-base16-dark .CodeMirror-gutters{background:#151515;border-right:0}.cm-s-base16-dark .CodeMirror-guttermarker{color:#ac4142}.cm-s-base16-dark .CodeMirror-guttermarker-subtle{color:#505050}.cm-s-base16-dark .CodeMirror-linenumber{color:#505050}.cm-s-base16-dark .CodeMirror-cursor{border-left:1px solid #b0b0b0}.cm-s-base16-dark span.cm-comment{color:#8f5536}.cm-s-base16-dark span.cm-atom{color:#aa759f}.cm-s-base16-dark span.cm-number{color:#aa759f}.cm-s-base16-dark span.cm-property,.cm-s-base16-dark span.cm-attribute{color:#90a959}.cm-s-base16-dark span.cm-keyword{color:#ac4142}.cm-s-base16-dark span.cm-string{color:#f4bf75}.cm-s-base16-dark span.cm-variable{color:#90a959}.cm-s-base16-dark span.cm-variable-2{color:#6a9fb5}.cm-s-base16-dark span.cm-def{color:#d28445}.cm-s-base16-dark span.cm-bracket{color:#e0e0e0}.cm-s-base16-dark span.cm-tag{color:#ac4142}.cm-s-base16-dark span.cm-link{color:#aa759f}.cm-s-base16-dark span.cm-error{background:#ac4142;color:#b0b0b0}.cm-s-base16-dark .CodeMirror-activeline-background{background:#202020}.cm-s-base16-dark .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-base16-light.CodeMirror{background:#f5f5f5;color:#202020}.cm-s-base16-light div.CodeMirror-selected{background:#e0e0e0}.cm-s-base16-light .CodeMirror-line::selection,.cm-s-base16-light .CodeMirror-line>span::selection,.cm-s-base16-light .CodeMirror-line>span>span::selection{background:#e0e0e0}.cm-s-base16-light .CodeMirror-line::-moz-selection,.cm-s-base16-light .CodeMirror-line>span::-moz-selection,.cm-s-base16-light .CodeMirror-line>span>span::-moz-selection{background:#e0e0e0}.cm-s-base16-light .CodeMirror-gutters{background:#f5f5f5;border-right:0}.cm-s-base16-light .CodeMirror-guttermarker{color:#ac4142}.cm-s-base16-light .CodeMirror-guttermarker-subtle{color:#b0b0b0}.cm-s-base16-light .CodeMirror-linenumber{color:#b0b0b0}.cm-s-base16-light .CodeMirror-cursor{border-left:1px solid #505050}.cm-s-base16-light span.cm-comment{color:#8f5536}.cm-s-base16-light span.cm-atom{color:#aa759f}.cm-s-base16-light span.cm-number{color:#aa759f}.cm-s-base16-light span.cm-property,.cm-s-base16-light span.cm-attribute{color:#90a959}.cm-s-base16-light span.cm-keyword{color:#ac4142}.cm-s-base16-light span.cm-string{color:#f4bf75}.cm-s-base16-light span.cm-variable{color:#90a959}.cm-s-base16-light span.cm-variable-2{color:#6a9fb5}.cm-s-base16-light span.cm-def{color:#d28445}.cm-s-base16-light span.cm-bracket{color:#202020}.cm-s-base16-light span.cm-tag{color:#ac4142}.cm-s-base16-light span.cm-link{color:#aa759f}.cm-s-base16-light span.cm-error{background:#ac4142;color:#505050}.cm-s-base16-light .CodeMirror-activeline-background{background:#dddcdc}.cm-s-base16-light .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-dracula.CodeMirror,.cm-s-dracula .CodeMirror-gutters{background-color:#282a36!important;color:#f8f8f2!important;border:none}.cm-s-dracula .CodeMirror-gutters{color:#282a36}.cm-s-dracula .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-dracula .CodeMirror-linenumber{color:#6d8a88}.cm-s-dracula.CodeMirror-focused div.CodeMirror-selected{background:rgba(255,255,255,.1)}.cm-s-dracula .CodeMirror-line::selection,.cm-s-dracula .CodeMirror-line>span::selection,.cm-s-dracula .CodeMirror-line>span>span::selection{background:rgba(255,255,255,.1)}.cm-s-dracula .CodeMirror-line::-moz-selection,.cm-s-dracula .CodeMirror-line>span::-moz-selection,.cm-s-dracula .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,.1)}.cm-s-dracula span.cm-comment{color:#6272a4}.cm-s-dracula span.cm-string,.cm-s-dracula span.cm-string-2{color:#f1fa8c}.cm-s-dracula span.cm-number{color:#bd93f9}.cm-s-dracula span.cm-variable{color:#50fa7b}.cm-s-dracula span.cm-variable-2{color:white}.cm-s-dracula span.cm-def{color:#ffb86c}.cm-s-dracula span.cm-keyword{color:#ff79c6}.cm-s-dracula span.cm-operator{color:#ff79c6}.cm-s-dracula span.cm-keyword{color:#ff79c6}.cm-s-dracula span.cm-atom{color:#bd93f9}.cm-s-dracula span.cm-meta{color:#f8f8f2}.cm-s-dracula span.cm-tag{color:#ff79c6}.cm-s-dracula span.cm-attribute{color:#50fa7b}.cm-s-dracula span.cm-qualifier{color:#50fa7b}.cm-s-dracula span.cm-property{color:#66d9ef}.cm-s-dracula span.cm-builtin{color:#50fa7b}.cm-s-dracula span.cm-variable-3{color:#50fa7b}.cm-s-dracula .CodeMirror-activeline-background{background:rgba(255,255,255,.1)}.cm-s-dracula .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-eclipse span.cm-meta{color:#ff1717}.cm-s-eclipse span.cm-keyword{line-height:1em;font-weight:700;color:#7f0055}.cm-s-eclipse span.cm-atom{color:#219}.cm-s-eclipse span.cm-number{color:#164}.cm-s-eclipse span.cm-def{color:#00f}.cm-s-eclipse span.cm-variable{color:black}.cm-s-eclipse span.cm-variable-2{color:#0000c0}.cm-s-eclipse span.cm-variable-3{color:#0000c0}.cm-s-eclipse span.cm-property{color:black}.cm-s-eclipse span.cm-operator{color:black}.cm-s-eclipse span.cm-comment{color:#3f7f5f}.cm-s-eclipse span.cm-string{color:#2a00ff}.cm-s-eclipse span.cm-string-2{color:#f50}.cm-s-eclipse span.cm-qualifier{color:#555}.cm-s-eclipse span.cm-builtin{color:#30a}.cm-s-eclipse span.cm-bracket{color:#cc7}.cm-s-eclipse span.cm-tag{color:#170}.cm-s-eclipse span.cm-attribute{color:#00c}.cm-s-eclipse span.cm-link{color:#219}.cm-s-eclipse span.cm-error{color:#f00}.cm-s-eclipse .CodeMirror-activeline-background{background:#e8f2ff}.cm-s-eclipse .CodeMirror-matchingbracket{outline:1px solid grey;color:black!important}.cm-s-elegant span.cm-number,.cm-s-elegant span.cm-string,.cm-s-elegant span.cm-atom{color:#762}.cm-s-elegant span.cm-comment{color:#262;font-style:italic;line-height:1em}.cm-s-elegant span.cm-meta{color:#555;font-style:italic;line-height:1em}.cm-s-elegant span.cm-variable{color:black}.cm-s-elegant span.cm-variable-2{color:#b11}.cm-s-elegant span.cm-qualifier{color:#555}.cm-s-elegant span.cm-keyword{color:#730}.cm-s-elegant span.cm-builtin{color:#30a}.cm-s-elegant span.cm-link{color:#762}.cm-s-elegant span.cm-error{background-color:#fdd}.cm-s-elegant .CodeMirror-activeline-background{background:#e8f2ff}.cm-s-elegant .CodeMirror-matchingbracket{outline:1px solid grey;color:black!important}.cm-s-icecoder{color:#666;background:#141612}.cm-s-icecoder span.cm-keyword{color:#eee;font-weight:700}.cm-s-icecoder span.cm-atom{color:#e1c76e}.cm-s-icecoder span.cm-number{color:#6cb5d9}.cm-s-icecoder span.cm-def{color:#b9ca4a}.cm-s-icecoder span.cm-variable{color:#6cb5d9}.cm-s-icecoder span.cm-variable-2{color:#cc1e5c}.cm-s-icecoder span.cm-variable-3{color:#f9602c}.cm-s-icecoder span.cm-property{color:#eee}.cm-s-icecoder span.cm-operator{color:#9179bb}.cm-s-icecoder span.cm-comment{color:#97a3aa}.cm-s-icecoder span.cm-string{color:#b9ca4a}.cm-s-icecoder span.cm-string-2{color:#6cb5d9}.cm-s-icecoder span.cm-meta{color:#555}.cm-s-icecoder span.cm-qualifier{color:#555}.cm-s-icecoder span.cm-builtin{color:#214e7b}.cm-s-icecoder span.cm-bracket{color:#cc7}.cm-s-icecoder span.cm-tag{color:#e8e8e8}.cm-s-icecoder span.cm-attribute{color:#099}.cm-s-icecoder span.cm-header{color:#6a0d6a}.cm-s-icecoder span.cm-quote{color:#186718}.cm-s-icecoder span.cm-hr{color:#888}.cm-s-icecoder span.cm-link{color:#e1c76e}.cm-s-icecoder span.cm-error{color:#d00}.cm-s-icecoder .CodeMirror-cursor{border-left:1px solid white}.cm-s-icecoder div.CodeMirror-selected{color:#fff;background:#037}.cm-s-icecoder .CodeMirror-gutters{background:#141612;min-width:41px;border-right:0}.cm-s-icecoder .CodeMirror-linenumber{color:#555;cursor:default}.cm-s-icecoder .CodeMirror-matchingbracket{border:1px solid grey;color:black!important}.cm-s-icecoder .CodeMirror-activeline-background{background:#000}.cm-s-lesser-dark{line-height:1.3em}.cm-s-lesser-dark.CodeMirror{background:#262626;color:#ebefe7;text-shadow:0 -1px 1px #262626}.cm-s-lesser-dark div.CodeMirror-selected{background:#45443b}.cm-s-lesser-dark .CodeMirror-line::selection,.cm-s-lesser-dark .CodeMirror-line>span::selection,.cm-s-lesser-dark .CodeMirror-line>span>span::selection{background:rgba(69,68,59,.99)}.cm-s-lesser-dark .CodeMirror-line::-moz-selection,.cm-s-lesser-dark .CodeMirror-line>span::-moz-selection,.cm-s-lesser-dark .CodeMirror-line>span>span::-moz-selection{background:rgba(69,68,59,.99)}.cm-s-lesser-dark .CodeMirror-cursor{border-left:1px solid white}.cm-s-lesser-dark pre{padding:0 8px}.cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket{color:#7efc7e}.cm-s-lesser-dark .CodeMirror-gutters{background:#262626;border-right:1px solid #aaa}.cm-s-lesser-dark .CodeMirror-guttermarker{color:#599eff}.cm-s-lesser-dark .CodeMirror-guttermarker-subtle{color:#777}.cm-s-lesser-dark .CodeMirror-linenumber{color:#777}.cm-s-lesser-dark span.cm-header{color:#a0a}.cm-s-lesser-dark span.cm-quote{color:#090}.cm-s-lesser-dark span.cm-keyword{color:#599eff}.cm-s-lesser-dark span.cm-atom{color:#c2b470}.cm-s-lesser-dark span.cm-number{color:#b35e4d}.cm-s-lesser-dark span.cm-def{color:white}.cm-s-lesser-dark span.cm-variable{color:#d9bf8c}.cm-s-lesser-dark span.cm-variable-2{color:#669199}.cm-s-lesser-dark span.cm-variable-3{color:white}.cm-s-lesser-dark span.cm-property{color:#92a75c}.cm-s-lesser-dark span.cm-operator{color:#92a75c}.cm-s-lesser-dark span.cm-comment{color:#666}.cm-s-lesser-dark span.cm-string{color:#bcd279}.cm-s-lesser-dark span.cm-string-2{color:#f50}.cm-s-lesser-dark span.cm-meta{color:#738c73}.cm-s-lesser-dark span.cm-qualifier{color:#555}.cm-s-lesser-dark span.cm-builtin{color:#ff9e59}.cm-s-lesser-dark span.cm-bracket{color:#ebefe7}.cm-s-lesser-dark span.cm-tag{color:#669199}.cm-s-lesser-dark span.cm-attribute{color:#00c}.cm-s-lesser-dark span.cm-hr{color:#999}.cm-s-lesser-dark span.cm-link{color:#00c}.cm-s-lesser-dark span.cm-error{color:#9d1e15}.cm-s-lesser-dark .CodeMirror-activeline-background{background:#3c3a3a}.cm-s-lesser-dark .CodeMirror-matchingbracket{outline:1px solid grey;color:white!important}.cm-s-material{background-color:#263238;color:#e9eded}.cm-s-material .CodeMirror-gutters{background:#263238;color:#537f7e;border:none}.cm-s-material .CodeMirror-guttermarker,.cm-s-material .CodeMirror-guttermarker-subtle,.cm-s-material .CodeMirror-linenumber{color:#537f7e}.cm-s-material .CodeMirror-cursor{border-left:1px solid #f8f8f0}.cm-s-material div.CodeMirror-selected{background:rgba(255,255,255,.15)}.cm-s-material.CodeMirror-focused div.CodeMirror-selected{background:rgba(255,255,255,.1)}.cm-s-material .CodeMirror-line::selection,.cm-s-material .CodeMirror-line>span::selection,.cm-s-material .CodeMirror-line>span>span::selection{background:rgba(255,255,255,.1)}.cm-s-material .CodeMirror-line::-moz-selection,.cm-s-material .CodeMirror-line>span::-moz-selection,.cm-s-material .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,.1)}.cm-s-material .CodeMirror-activeline-background{background:transparent}.cm-s-material .cm-keyword{color:#c792ea}.cm-s-material .cm-operator{color:#e9eded}.cm-s-material .cm-variable-2{color:#80cbc4}.cm-s-material .cm-variable-3{color:#82b1ff}.cm-s-material .cm-builtin{color:#decb6b}.cm-s-material .cm-atom{color:#f77669}.cm-s-material .cm-number{color:#f77669}.cm-s-material .cm-def{color:#e9eded}.cm-s-material .cm-error{color:#fff;background-color:#ec5f67}.cm-s-material .cm-string{color:#c3e88d}.cm-s-material .cm-string-2{color:#80cbc4}.cm-s-material .cm-comment{color:#546e7a}.cm-s-material .cm-variable{color:#82b1ff}.cm-s-material .cm-tag{color:#80cbc4}.cm-s-material .cm-meta{color:#80cbc4}.cm-s-material .cm-attribute{color:#ffcb6b}.cm-s-material .cm-property{color:#80cbae}.cm-s-material .cm-qualifier{color:#decb6b}.cm-s-material .cm-variable-3{color:#decb6b}.cm-s-material .cm-tag{color:#ff5370}.cm-s-material .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-mdn-like.CodeMirror{color:#999;background-color:#fff}.cm-s-mdn-like div.CodeMirror-selected{background:#cfc}.cm-s-mdn-like .CodeMirror-line::selection,.cm-s-mdn-like .CodeMirror-line>span::selection,.cm-s-mdn-like .CodeMirror-line>span>span::selection{background:#cfc}.cm-s-mdn-like .CodeMirror-line::-moz-selection,.cm-s-mdn-like .CodeMirror-line>span::-moz-selection,.cm-s-mdn-like .CodeMirror-line>span>span::-moz-selection{background:#cfc}.cm-s-mdn-like .CodeMirror-gutters{background:#f8f8f8;border-left:6px solid rgba(0,83,159,.65);color:#333}.cm-s-mdn-like .CodeMirror-linenumber{color:#aaa;padding-left:8px}.cm-s-mdn-like .CodeMirror-cursor{border-left:2px solid #222}.cm-s-mdn-like .cm-keyword{color:#6262ff}.cm-s-mdn-like .cm-atom{color:#F90}.cm-s-mdn-like .cm-number{color:#ca7841}.cm-s-mdn-like .cm-def{color:#8da6ce}.cm-s-mdn-like span.cm-variable-2,.cm-s-mdn-like span.cm-tag{color:#690}.cm-s-mdn-like span.cm-variable-3,.cm-s-mdn-like span.cm-def{color:#07a}.cm-s-mdn-like .cm-variable{color:#07a}.cm-s-mdn-like .cm-property{color:#905}.cm-s-mdn-like .cm-qualifier{color:#690}.cm-s-mdn-like .cm-operator{color:#cda869}.cm-s-mdn-like .cm-comment{color:#777;font-weight:400}.cm-s-mdn-like .cm-string{color:#07a;font-style:italic}.cm-s-mdn-like .cm-string-2{color:#bd6b18}.cm-s-mdn-like .cm-meta{color:#000}.cm-s-mdn-like .cm-builtin{color:#9b7536}.cm-s-mdn-like .cm-tag{color:#997643}.cm-s-mdn-like .cm-attribute{color:#d6bb6d}.cm-s-mdn-like .cm-header{color:#ff6400}.cm-s-mdn-like .cm-hr{color:#aeaeae}.cm-s-mdn-like .cm-link{color:#ad9361;font-style:italic;text-decoration:none}.cm-s-mdn-like .cm-error{border-bottom:1px solid red}div.cm-s-mdn-like .CodeMirror-activeline-background{background:#efefff}div.cm-s-mdn-like span.CodeMirror-matchingbracket{outline:1px solid grey;color:inherit}.cm-s-mdn-like.CodeMirror{background-image:url(data:image/png;base64,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)}.cm-s-midnight span.CodeMirror-matchhighlight{background:#494949}.cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight{background:#314d67!important}.cm-s-midnight .CodeMirror-activeline-background{background:#253540}.cm-s-midnight.CodeMirror{background:#0f192a;color:#d1edff}.cm-s-midnight.CodeMirror{border-top:1px solid black;border-bottom:1px solid black}.cm-s-midnight div.CodeMirror-selected{background:#314d67}.cm-s-midnight .CodeMirror-line::selection,.cm-s-midnight .CodeMirror-line>span::selection,.cm-s-midnight .CodeMirror-line>span>span::selection{background:rgba(49,77,103,.99)}.cm-s-midnight .CodeMirror-line::-moz-selection,.cm-s-midnight .CodeMirror-line>span::-moz-selection,.cm-s-midnight .CodeMirror-line>span>span::-moz-selection{background:rgba(49,77,103,.99)}.cm-s-midnight .CodeMirror-gutters{background:#0f192a;border-right:1px solid}.cm-s-midnight .CodeMirror-guttermarker{color:white}.cm-s-midnight .CodeMirror-guttermarker-subtle{color:#d0d0d0}.cm-s-midnight .CodeMirror-linenumber{color:#d0d0d0}.cm-s-midnight .CodeMirror-cursor{border-left:1px solid #f8f8f0}.cm-s-midnight span.cm-comment{color:#428bdd}.cm-s-midnight span.cm-atom{color:#ae81ff}.cm-s-midnight span.cm-number{color:#d1edff}.cm-s-midnight span.cm-property,.cm-s-midnight span.cm-attribute{color:#a6e22e}.cm-s-midnight span.cm-keyword{color:#e83737}.cm-s-midnight span.cm-string{color:#1dc116}.cm-s-midnight span.cm-variable{color:#ffaa3e}.cm-s-midnight span.cm-variable-2{color:#ffaa3e}.cm-s-midnight span.cm-def{color:#4DD}.cm-s-midnight span.cm-bracket{color:#d1edff}.cm-s-midnight span.cm-tag{color:#449}.cm-s-midnight span.cm-link{color:#ae81ff}.cm-s-midnight span.cm-error{background:#f92672;color:#f8f8f0}.cm-s-midnight .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-monokai.CodeMirror{background:#272822;color:#f8f8f2}.cm-s-monokai div.CodeMirror-selected{background:#49483e}.cm-s-monokai .CodeMirror-line::selection,.cm-s-monokai .CodeMirror-line>span::selection,.cm-s-monokai .CodeMirror-line>span>span::selection{background:rgba(73,72,62,.99)}.cm-s-monokai .CodeMirror-line::-moz-selection,.cm-s-monokai .CodeMirror-line>span::-moz-selection,.cm-s-monokai .CodeMirror-line>span>span::-moz-selection{background:rgba(73,72,62,.99)}.cm-s-monokai .CodeMirror-gutters{background:#272822;border-right:0}.cm-s-monokai .CodeMirror-guttermarker{color:white}.cm-s-monokai .CodeMirror-guttermarker-subtle{color:#d0d0d0}.cm-s-monokai .CodeMirror-linenumber{color:#d0d0d0}.cm-s-monokai .CodeMirror-cursor{border-left:1px solid #f8f8f0}.cm-s-monokai span.cm-comment{color:#75715e}.cm-s-monokai span.cm-atom{color:#ae81ff}.cm-s-monokai span.cm-number{color:#ae81ff}.cm-s-monokai span.cm-property,.cm-s-monokai span.cm-attribute{color:#a6e22e}.cm-s-monokai span.cm-keyword{color:#f92672}.cm-s-monokai span.cm-string{color:#e6db74}.cm-s-monokai span.cm-variable{color:#f8f8f2}.cm-s-monokai span.cm-variable-2{color:#9effff}.cm-s-monokai span.cm-variable-3{color:#66d9ef}.cm-s-monokai span.cm-def{color:#fd971f}.cm-s-monokai span.cm-bracket{color:#f8f8f2}.cm-s-monokai span.cm-tag{color:#f92672}.cm-s-monokai span.cm-header{color:#ae81ff}.cm-s-monokai span.cm-link{color:#ae81ff}.cm-s-monokai span.cm-error{background:#f92672;color:#f8f8f0}.cm-s-monokai .CodeMirror-activeline-background{background:#373831}.cm-s-monokai .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-neat span.cm-comment{color:#a86}.cm-s-neat span.cm-keyword{line-height:1em;font-weight:700;color:blue}.cm-s-neat span.cm-string{color:#a22}.cm-s-neat span.cm-builtin{line-height:1em;font-weight:700;color:#077}.cm-s-neat span.cm-special{line-height:1em;font-weight:700;color:#0aa}.cm-s-neat span.cm-variable{color:black}.cm-s-neat span.cm-number,.cm-s-neat span.cm-atom{color:#3a3}.cm-s-neat span.cm-meta{color:#555}.cm-s-neat span.cm-link{color:#3a3}.cm-s-neat .CodeMirror-activeline-background{background:#e8f2ff}.cm-s-neat .CodeMirror-matchingbracket{outline:1px solid grey;color:black!important}.cm-s-neo.CodeMirror{background-color:#fff;color:#2e383c;line-height:1.4375}.cm-s-neo .cm-comment{color:#75787b}.cm-s-neo .cm-keyword,.cm-s-neo .cm-property{color:#1d75b3}.cm-s-neo .cm-atom,.cm-s-neo .cm-number{color:#75438a}.cm-s-neo .cm-node,.cm-s-neo .cm-tag{color:#9c3328}.cm-s-neo .cm-string{color:#b35e14}.cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier{color:#047d65}.cm-s-neo pre{padding:0}.cm-s-neo .CodeMirror-gutters{border:none;border-right:10px solid transparent;background-color:transparent}.cm-s-neo .CodeMirror-linenumber{padding:0;color:#e0e2e5}.cm-s-neo .CodeMirror-guttermarker{color:#1d75b3}.cm-s-neo .CodeMirror-guttermarker-subtle{color:#e0e2e5}.cm-s-neo .CodeMirror-cursor{width:auto;border:0;background:rgba(155,157,162,.37);z-index:1}.cm-s-pastel-on-dark.CodeMirror{background:#2c2827;color:#8f938f;line-height:1.5;font-size:14px}.cm-s-pastel-on-dark div.CodeMirror-selected{background:rgba(221,240,255,.2)}.cm-s-pastel-on-dark .CodeMirror-line::selection,.cm-s-pastel-on-dark .CodeMirror-line>span::selection,.cm-s-pastel-on-dark .CodeMirror-line>span>span::selection{background:rgba(221,240,255,.2)}.cm-s-pastel-on-dark .CodeMirror-line::-moz-selection,.cm-s-pastel-on-dark .CodeMirror-line>span::-moz-selection,.cm-s-pastel-on-dark .CodeMirror-line>span>span::-moz-selection{background:rgba(221,240,255,.2)}.cm-s-pastel-on-dark .CodeMirror-gutters{background:#34302f;border-right:0;padding:0 3px}.cm-s-pastel-on-dark .CodeMirror-guttermarker{color:white}.cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle{color:#8f938f}.cm-s-pastel-on-dark .CodeMirror-linenumber{color:#8f938f}.cm-s-pastel-on-dark .CodeMirror-cursor{border-left:1px solid #a7a7a7}.cm-s-pastel-on-dark span.cm-comment{color:#a6c6ff}.cm-s-pastel-on-dark span.cm-atom{color:#de8e30}.cm-s-pastel-on-dark span.cm-number{color:#ccc}.cm-s-pastel-on-dark span.cm-property{color:#8f938f}.cm-s-pastel-on-dark span.cm-attribute{color:#a6e22e}.cm-s-pastel-on-dark span.cm-keyword{color:#aeb2f8}.cm-s-pastel-on-dark span.cm-string{color:#66a968}.cm-s-pastel-on-dark span.cm-variable{color:#aeb2f8}.cm-s-pastel-on-dark span.cm-variable-2{color:#bebf55}.cm-s-pastel-on-dark span.cm-variable-3{color:#de8e30}.cm-s-pastel-on-dark span.cm-def{color:#757ad8}.cm-s-pastel-on-dark span.cm-bracket{color:#f8f8f2}.cm-s-pastel-on-dark span.cm-tag{color:#c1c144}.cm-s-pastel-on-dark span.cm-link{color:#ae81ff}.cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin{color:#c1c144}.cm-s-pastel-on-dark span.cm-error{background:#757ad8;color:#f8f8f0}.cm-s-pastel-on-dark .CodeMirror-activeline-background{background:rgba(255,255,255,.031)}.cm-s-pastel-on-dark .CodeMirror-matchingbracket{border:1px solid rgba(255,255,255,.25);color:#8f938f!important;margin:-1px -1px 0}.cm-s-railscasts.CodeMirror{background:#2b2b2b;color:#f4f1ed}.cm-s-railscasts div.CodeMirror-selected{background:#272935!important}.cm-s-railscasts .CodeMirror-gutters{background:#2b2b2b;border-right:0}.cm-s-railscasts .CodeMirror-linenumber{color:#5a647e}.cm-s-railscasts .CodeMirror-cursor{border-left:1px solid #d4cfc9!important}.cm-s-railscasts span.cm-comment{color:#bc9458}.cm-s-railscasts span.cm-atom{color:#b6b3eb}.cm-s-railscasts span.cm-number{color:#b6b3eb}.cm-s-railscasts span.cm-property,.cm-s-railscasts span.cm-attribute{color:#a5c261}.cm-s-railscasts span.cm-keyword{color:#da4939}.cm-s-railscasts span.cm-string{color:#ffc66d}.cm-s-railscasts span.cm-variable{color:#a5c261}.cm-s-railscasts span.cm-variable-2{color:#6d9cbe}.cm-s-railscasts span.cm-def{color:#cc7833}.cm-s-railscasts span.cm-error{background:#da4939;color:#d4cfc9}.cm-s-railscasts span.cm-bracket{color:#f4f1ed}.cm-s-railscasts span.cm-tag{color:#da4939}.cm-s-railscasts span.cm-link{color:#b6b3eb}.cm-s-railscasts .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-railscasts .CodeMirror-activeline-background{background:#303040}.cm-s-seti.CodeMirror{background-color:#151718!important;color:#cfd2d1!important;border:none}.cm-s-seti .CodeMirror-gutters{color:#404b53;background-color:#0e1112;border:none}.cm-s-seti .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-seti .CodeMirror-linenumber{color:#6d8a88}.cm-s-seti.CodeMirror-focused div.CodeMirror-selected{background:rgba(255,255,255,.1)}.cm-s-seti .CodeMirror-line::selection,.cm-s-seti .CodeMirror-line>span::selection,.cm-s-seti .CodeMirror-line>span>span::selection{background:rgba(255,255,255,.1)}.cm-s-seti .CodeMirror-line::-moz-selection,.cm-s-seti .CodeMirror-line>span::-moz-selection,.cm-s-seti .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,.1)}.cm-s-seti span.cm-comment{color:#41535b}.cm-s-seti span.cm-string,.cm-s-seti span.cm-string-2{color:#55b5db}.cm-s-seti span.cm-number{color:#cd3f45}.cm-s-seti span.cm-variable{color:#55b5db}.cm-s-seti span.cm-variable-2{color:#a074c4}.cm-s-seti span.cm-def{color:#55b5db}.cm-s-seti span.cm-keyword{color:#ff79c6}.cm-s-seti span.cm-operator{color:#9fca56}.cm-s-seti span.cm-keyword{color:#e6cd69}.cm-s-seti span.cm-atom{color:#cd3f45}.cm-s-seti span.cm-meta{color:#55b5db}.cm-s-seti span.cm-tag{color:#55b5db}.cm-s-seti span.cm-attribute{color:#9fca56}.cm-s-seti span.cm-qualifier{color:#9fca56}.cm-s-seti span.cm-property{color:#a074c4}.cm-s-seti span.cm-variable-3{color:#9fca56}.cm-s-seti span.cm-builtin{color:#9fca56}.cm-s-seti .CodeMirror-activeline-background{background:#101213}.cm-s-seti .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.solarized.base03{color:#002b36}.solarized.base02{color:#073642}.solarized.base01{color:#586e75}.solarized.base00{color:#657b83}.solarized.base0{color:#839496}.solarized.base1{color:#93a1a1}.solarized.base2{color:#eee8d5}.solarized.base3{color:#fdf6e3}.solarized.solar-yellow{color:#b58900}.solarized.solar-orange{color:#cb4b16}.solarized.solar-red{color:#dc322f}.solarized.solar-magenta{color:#d33682}.solarized.solar-violet{color:#6c71c4}.solarized.solar-blue{color:#268bd2}.solarized.solar-cyan{color:#2aa198}.solarized.solar-green{color:#859900}.cm-s-solarized{line-height:1.45em;color-profile:sRGB;rendering-intent:auto}.cm-s-solarized.cm-s-dark{color:#839496;background-color:#002b36;text-shadow:#002b36 0 1px}.cm-s-solarized.cm-s-light{background-color:#fdf6e3;color:#657b83;text-shadow:#eee8d5 0 1px}.cm-s-solarized .CodeMirror-widget{text-shadow:none}.cm-s-solarized .cm-header{color:#586e75}.cm-s-solarized .cm-quote{color:#93a1a1}.cm-s-solarized .cm-keyword{color:#cb4b16}.cm-s-solarized .cm-atom{color:#d33682}.cm-s-solarized .cm-number{color:#d33682}.cm-s-solarized .cm-def{color:#2aa198}.cm-s-solarized .cm-variable{color:#839496}.cm-s-solarized .cm-variable-2{color:#b58900}.cm-s-solarized .cm-variable-3{color:#6c71c4}.cm-s-solarized .cm-property{color:#2aa198}.cm-s-solarized .cm-operator{color:#6c71c4}.cm-s-solarized .cm-comment{color:#586e75;font-style:italic}.cm-s-solarized .cm-string{color:#859900}.cm-s-solarized .cm-string-2{color:#b58900}.cm-s-solarized .cm-meta{color:#859900}.cm-s-solarized .cm-qualifier{color:#b58900}.cm-s-solarized .cm-builtin{color:#d33682}.cm-s-solarized .cm-bracket{color:#cb4b16}.cm-s-solarized .CodeMirror-matchingbracket{color:#859900}.cm-s-solarized .CodeMirror-nonmatchingbracket{color:#dc322f}.cm-s-solarized .cm-tag{color:#93a1a1}.cm-s-solarized .cm-attribute{color:#2aa198}.cm-s-solarized .cm-hr{color:transparent;border-top:1px solid #586e75;display:block}.cm-s-solarized .cm-link{color:#93a1a1;cursor:pointer}.cm-s-solarized .cm-special{color:#6c71c4}.cm-s-solarized .cm-em{color:#999;text-decoration:underline;-webkit-text-decoration-style:dotted;text-decoration-style:dotted}.cm-s-solarized .cm-strong{color:#eee}.cm-s-solarized .cm-error,.cm-s-solarized .cm-invalidchar{color:#586e75;border-bottom:1px dotted #dc322f}.cm-s-solarized.cm-s-dark div.CodeMirror-selected{background:#073642}.cm-s-solarized.cm-s-dark.CodeMirror ::selection{background:rgba(7,54,66,.99)}.cm-s-solarized.cm-s-dark .CodeMirror-line::-moz-selection,.cm-s-dark .CodeMirror-line>span::-moz-selection,.cm-s-dark .CodeMirror-line>span>span::-moz-selection{background:rgba(7,54,66,.99)}.cm-s-solarized.cm-s-light div.CodeMirror-selected{background:#eee8d5}.cm-s-solarized.cm-s-light .CodeMirror-line::selection,.cm-s-light .CodeMirror-line>span::selection,.cm-s-light .CodeMirror-line>span>span::selection{background:#eee8d5}.cm-s-solarized.cm-s-light .CodeMirror-line::-moz-selection,.cm-s-ligh .CodeMirror-line>span::-moz-selection,.cm-s-ligh .CodeMirror-line>span>span::-moz-selection{background:#eee8d5}.cm-s-solarized.CodeMirror{box-shadow:inset 7px 0 12px -6px #000}.cm-s-solarized .CodeMirror-gutters{border-right:1px solid}.cm-s-solarized.cm-s-dark .CodeMirror-gutters{background-color:#002b36;border-color:#00232c}.cm-s-solarized.cm-s-dark .CodeMirror-linenumber{text-shadow:#021014 0 -1px}.cm-s-solarized.cm-s-light .CodeMirror-gutters{background-color:#fdf6e3;border-color:#eee8d5}.cm-s-solarized .CodeMirror-linenumber{color:#586e75;padding:0 5px}.cm-s-solarized .CodeMirror-guttermarker-subtle{color:#586e75}.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker{color:#ddd}.cm-s-solarized.cm-s-light .CodeMirror-guttermarker{color:#cb4b16}.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text{color:#586e75}.cm-s-solarized .CodeMirror-cursor{border-left:1px solid #819090}.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background{background:rgba(255,255,255,.1)}.cm-s-solarized.cm-s-light .CodeMirror-activeline-background{background:rgba(0,0,0,.1)}.cm-s-tomorrow-night-bright.CodeMirror{background:#000;color:#eaeaea}.cm-s-tomorrow-night-bright div.CodeMirror-selected{background:#424242}.cm-s-tomorrow-night-bright .CodeMirror-gutters{background:#000;border-right:0}.cm-s-tomorrow-night-bright .CodeMirror-guttermarker{color:#e78c45}.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle{color:#777}.cm-s-tomorrow-night-bright .CodeMirror-linenumber{color:#424242}.cm-s-tomorrow-night-bright .CodeMirror-cursor{border-left:1px solid #6a6a6a}.cm-s-tomorrow-night-bright span.cm-comment{color:#d27b53}.cm-s-tomorrow-night-bright span.cm-atom{color:#a16a94}.cm-s-tomorrow-night-bright span.cm-number{color:#a16a94}.cm-s-tomorrow-night-bright span.cm-property,.cm-s-tomorrow-night-bright span.cm-attribute{color:#9c9}.cm-s-tomorrow-night-bright span.cm-keyword{color:#d54e53}.cm-s-tomorrow-night-bright span.cm-string{color:#e7c547}.cm-s-tomorrow-night-bright span.cm-variable{color:#b9ca4a}.cm-s-tomorrow-night-bright span.cm-variable-2{color:#7aa6da}.cm-s-tomorrow-night-bright span.cm-def{color:#e78c45}.cm-s-tomorrow-night-bright span.cm-bracket{color:#eaeaea}.cm-s-tomorrow-night-bright span.cm-tag{color:#d54e53}.cm-s-tomorrow-night-bright span.cm-link{color:#a16a94}.cm-s-tomorrow-night-bright span.cm-error{background:#d54e53;color:#6a6a6a}.cm-s-tomorrow-night-bright .CodeMirror-activeline-background{background:#2a2a2a}.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-tomorrow-night-eighties.CodeMirror{background:#000;color:#ccc}.cm-s-tomorrow-night-eighties div.CodeMirror-selected{background:#2d2d2d}.cm-s-tomorrow-night-eighties .CodeMirror-line::selection,.cm-s-tomorrow-night-eighties .CodeMirror-line>span::selection,.cm-s-tomorrow-night-eighties .CodeMirror-line>span>span::selection{background:rgba(45,45,45,.99)}.cm-s-tomorrow-night-eighties .CodeMirror-line::-moz-selection,.cm-s-tomorrow-night-eighties .CodeMirror-line>span::-moz-selection,.cm-s-tomorrow-night-eighties .CodeMirror-line>span>span::-moz-selection{background:rgba(45,45,45,.99)}.cm-s-tomorrow-night-eighties .CodeMirror-gutters{background:#000;border-right:0}.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker{color:#f2777a}.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle{color:#777}.cm-s-tomorrow-night-eighties .CodeMirror-linenumber{color:#515151}.cm-s-tomorrow-night-eighties .CodeMirror-cursor{border-left:1px solid #6a6a6a}.cm-s-tomorrow-night-eighties span.cm-comment{color:#d27b53}.cm-s-tomorrow-night-eighties span.cm-atom{color:#a16a94}.cm-s-tomorrow-night-eighties span.cm-number{color:#a16a94}.cm-s-tomorrow-night-eighties span.cm-property,.cm-s-tomorrow-night-eighties span.cm-attribute{color:#9c9}.cm-s-tomorrow-night-eighties span.cm-keyword{color:#f2777a}.cm-s-tomorrow-night-eighties span.cm-string{color:#fc6}.cm-s-tomorrow-night-eighties span.cm-variable{color:#9c9}.cm-s-tomorrow-night-eighties span.cm-variable-2{color:#69c}.cm-s-tomorrow-night-eighties span.cm-def{color:#f99157}.cm-s-tomorrow-night-eighties span.cm-bracket{color:#ccc}.cm-s-tomorrow-night-eighties span.cm-tag{color:#f2777a}.cm-s-tomorrow-night-eighties span.cm-link{color:#a16a94}.cm-s-tomorrow-night-eighties span.cm-error{background:#f2777a;color:#6a6a6a}.cm-s-tomorrow-night-eighties .CodeMirror-activeline-background{background:#343600}.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket{text-decoration:underline;color:white!important}.cm-s-ttcn .cm-quote{color:#090}.cm-s-ttcn .cm-negative{color:#d44}.cm-s-ttcn .cm-positive{color:#292}.cm-s-ttcn .cm-header,.cm-strong{font-weight:700}.cm-s-ttcn .cm-em{font-style:italic}.cm-s-ttcn .cm-link{text-decoration:underline}.cm-s-ttcn .cm-strikethrough{text-decoration:line-through}.cm-s-ttcn .cm-header{color:#00f;font-weight:700}.cm-s-ttcn .cm-atom{color:#219}.cm-s-ttcn .cm-attribute{color:#00c}.cm-s-ttcn .cm-bracket{color:#997}.cm-s-ttcn .cm-comment{color:#333}.cm-s-ttcn .cm-def{color:#00f}.cm-s-ttcn .cm-em{font-style:italic}.cm-s-ttcn .cm-error{color:#f00}.cm-s-ttcn .cm-hr{color:#999}.cm-s-ttcn .cm-invalidchar{color:#f00}.cm-s-ttcn .cm-keyword{font-weight:700}.cm-s-ttcn .cm-link{color:#00c;text-decoration:underline}.cm-s-ttcn .cm-meta{color:#555}.cm-s-ttcn .cm-negative{color:#d44}.cm-s-ttcn .cm-positive{color:#292}.cm-s-ttcn .cm-qualifier{color:#555}.cm-s-ttcn .cm-strikethrough{text-decoration:line-through}.cm-s-ttcn .cm-string{color:#006400}.cm-s-ttcn .cm-string-2{color:#f50}.cm-s-ttcn .cm-strong{font-weight:700}.cm-s-ttcn .cm-tag{color:#170}.cm-s-ttcn .cm-variable{color:#8b2252}.cm-s-ttcn .cm-variable-2{color:#05a}.cm-s-ttcn .cm-variable-3{color:#085}.cm-s-ttcn .cm-invalidchar{color:#f00}.cm-s-ttcn .cm-accessTypes,.cm-s-ttcn .cm-compareTypes{color:#27408b}.cm-s-ttcn .cm-cmipVerbs{color:#8b2252}.cm-s-ttcn .cm-modifier{color:#d2691e}.cm-s-ttcn .cm-status{color:#8b4545}.cm-s-ttcn .cm-storage{color:#a020f0}.cm-s-ttcn .cm-tags{color:#006400}.cm-s-ttcn .cm-externalCommands{color:#8b4545;font-weight:700}.cm-s-ttcn .cm-fileNCtrlMaskOptions,.cm-s-ttcn .cm-sectionTitle{color:#2e8b57;font-weight:700}.cm-s-ttcn .cm-booleanConsts,.cm-s-ttcn .cm-otherConsts,.cm-s-ttcn .cm-verdictConsts{color:#006400}.cm-s-ttcn .cm-configOps,.cm-s-ttcn .cm-functionOps,.cm-s-ttcn .cm-portOps,.cm-s-ttcn .cm-sutOps,.cm-s-ttcn .cm-timerOps,.cm-s-ttcn .cm-verdictOps{color:#00f}.cm-s-ttcn .cm-preprocessor,.cm-s-ttcn .cm-templateMatch,.cm-s-ttcn .cm-ttcn3Macros{color:#27408b}.cm-s-ttcn .cm-types{color:#a52a2a;font-weight:700}.cm-s-ttcn .cm-visibilityModifiers{font-weight:700}.cm-s-yeti.CodeMirror{background-color:#eceae8!important;color:#d1c9c0!important;border:none}.cm-s-yeti .CodeMirror-gutters{color:#adaba6;background-color:#e5e1db;border:none}.cm-s-yeti .CodeMirror-cursor{border-left:solid thin #d1c9c0}.cm-s-yeti .CodeMirror-linenumber{color:#adaba6}.cm-s-yeti.CodeMirror-focused div.CodeMirror-selected{background:#dcd8d2}.cm-s-yeti .CodeMirror-line::selection,.cm-s-yeti .CodeMirror-line>span::selection,.cm-s-yeti .CodeMirror-line>span>span::selection{background:#dcd8d2}.cm-s-yeti .CodeMirror-line::-moz-selection,.cm-s-yeti .CodeMirror-line>span::-moz-selection,.cm-s-yeti .CodeMirror-line>span>span::-moz-selection{background:#dcd8d2}.cm-s-yeti span.cm-comment{color:#d4c8be}.cm-s-yeti span.cm-string,.cm-s-yeti span.cm-string-2{color:#96c0d8}.cm-s-yeti span.cm-number{color:#a074c4}.cm-s-yeti span.cm-variable{color:#55b5db}.cm-s-yeti span.cm-variable-2{color:#a074c4}.cm-s-yeti span.cm-def{color:#55b5db}.cm-s-yeti span.cm-operator{color:#9fb96e}.cm-s-yeti span.cm-keyword{color:#9fb96e}.cm-s-yeti span.cm-atom{color:#a074c4}.cm-s-yeti span.cm-meta{color:#96c0d8}.cm-s-yeti span.cm-tag{color:#96c0d8}.cm-s-yeti span.cm-attribute{color:#9fb96e}.cm-s-yeti span.cm-qualifier{color:#96c0d8}.cm-s-yeti span.cm-property{color:#a074c4}.cm-s-yeti span.cm-builtin{color:#a074c4}.cm-s-yeti span.cm-variable-3{color:#96c0d8}.cm-s-yeti .CodeMirror-activeline-background{background:#e7e4e0}.cm-s-yeti .CodeMirror-matchingbracket{text-decoration:underline}.ge_menu_bar{position:fixed;width:100%;margin:0;z-index:300;color:#eefafa;background-color:#2f302b;font-family:Helvetica,Geneva,sans-serif;font-weight:400}.ge_menu{display:inline-block;margin:16px 32px 16px 16px;letter-spacing:.2em;font-size:14px}.ge_menu .material-icons{font-size:18px;vertical-align:bottom;display:inline-block;margin-right:4px}.ge_menu--hidden{display:none}.ge_menu_button{cursor:pointer;background:none;display:block;border:none;border-radius:4px;padding:0;font:inherit;color:inherit;outline:none;text-align:left;letter-spacing:.05em!important}.ge_menu_highlight{width:24px;color:#fff}.ge_menu_disabled{width:24px;color:#777}.ge_menu_button:hover{color:#b3e5fc}.ge_sub_menu .ge_menu_button{width:100%}.ge_sub_menu_button{height:35px;cursor:pointer;background:none;border:none;padding:0;font:inherit;color:inherit;text-align:left;-webkit-user-select:none;-ms-user-select:none;user-select:none}.ge_sub_menu_button::selection{background:transparent;color:inherit}.ge_sub_menu_button::-moz-selection{background:transparent;color:inherit}.ge_sub_menu_button:hover{color:#b3e5fc}.ge_sub_menu{padding:4px 12px;font-family:Helvetica,Geneva,sans-serif;font-weight:300;font-size:14px}.ge_menu_icon{display:inline-block;width:48px}.ge_panel{cursor:pointer;color:#eefafa;background-color:#2f302b;font-family:Helvetica,Geneva,sans-serif;font-weight:100;margin:0;padding-top:5px;z-index:300;border-bottom:solid 1px #444}li.ge_panel_tab{cursor:pointer;list-style-type:none;background-color:#2f302b;color:#777;display:inline-block;text-align:center;padding:8px 16px;margin-bottom:8px;letter-spacing:.05em;font-face:monospace;font-size:14px}li.ge_panel_tab_active{cursor:pointer;border-radius:4px;list-style-type:none;display:inline-block;text-align:center;padding:8px 16px;margin-bottom:8px;letter-spacing:.05em;font-size:14px}li.ge_panel_tab:hover{color:#b3e5fc}a.ge_panel_tab_close{cursor:pointer;font-size:12px;margin-left:10px;font-weight:100}.CodeMirror{font-family:Source Code Pro,monospace;font-size:14px;line-height:1.4;height:auto;z-index:100}.CodeMirror-linenumbers{padding:0 8px;font-family:Helvetica,Geneva,sans-serif}.CodeMirror-linenumber.CodeMirror-gutter-elt{color:#546e7a}.CodeMirror pre{padding:0 8px}.CodeMirror-vscrollbar{visibility:hidden}.ge_editor{background-color:#272823}.ge_editor-unfocus{opacity:.5;filter:blur(1px);background-color:#272823}.CodeMirror{margin-top:12px}.ge_canvas_container{position:fixed;right:0;margin:0;padding:0;transition:top .25s ease;z-index:200}.ge_canvas{margin:0;padding:0;z-index:200}.ge_control{margin:0;padding:0;position:absolute;width:100%;bottom:16px;opacity:1;transition:opacity .3s;z-index:200}.ge_control_panel{padding:8px;border-radius:4px;text-align:center;position:absolute;right:0;left:0;bottom:0;margin:auto;width:120px;background-color:rgba(0,0,0,.5);font-size:18px!important;opacity:1;transition:opacity .3s;z-index:200}.ge_contol li{margin:0;padding:0;list-style-type:none}.ge_control_hidden{opacity:0}.ge_control_element{background-color:transparent;color:#eefafa;font-family:Helvetica,Geneva,sans-serif;font-weight:300;display:inline;-webkit-user-select:none;-ms-user-select:none;user-select:none}.ge_control_element_button{display:inline-block;margin:0 8px;width:24px;height:24px;cursor:pointer;background:none;border:none;padding:0;font:inherit;color:inherit;text-align:center;vertical-align:middle;font-size:14px;overflow:hidden;outline:none;-webkit-user-select:none;-ms-user-select:none;user-select:none}.ge_control_element_button::selection{background:transparent;color:inherit}.ge_control_element_button::-moz-selection{background:transparent;color:inherit}.ge_control_element_button:hover{color:#b3e5fc}.ghostdom{background:#999;opacity:.2;position:absolute;right:0;margin:0;padding:0;transition:all .25s ease-in-out;z-index:199}.ge_picker_modal{box-sizing:border-box;position:absolute;padding:0;overflow:hidden;box-shadow:0 0 0 5px rgba(0,0,0,.2),0 4px 8px 0 rgba(0,0,0,.25);-webkit-user-select:none;-ms-user-select:none;user-select:none;z-index:1000}.ge_picker_modal *{box-sizing:border-box}.ge_picker_canvas{width:100%;height:100%;cursor:crosshair}.ge_colorpicker_patch{position:absolute;left:0;top:0;width:100%;height:50px}.ge_colorpicker_hsv-map{position:relative;height:200px;width:100%;top:50px}.ge_colorpicker_disc-cover{opacity:0;background-color:#000;position:absolute;top:0;left:0;width:200px;height:200px;border-radius:50%;cursor:crosshair}.ge_colorpicker_disc-cover:after{content:'';background-color:transparent;position:absolute;top:-1px;left:-1px;width:202px;height:202px;border:3px solid #2e3033;border-radius:50%;opacity:1;pointer-events:none;box-sizing:border-box}.ge_colorpicker_bar-bg,.ge_colorpicker_bar-white{position:absolute;right:0;top:0;width:25px;height:200px}.ge_colorpicker_bar-white{background-color:#fff}.ge_colorpicker_disc-cursor{position:absolute;border:1px solid #eee;border-radius:50%;width:9px;height:9px;margin:-5px;cursor:crosshair}.ge_colorpicker_dark .ge_colorpicker_disc-cursor{border-color:#333}.ge_colorpicker_bar-luminance{position:absolute;right:0;top:0}.ge_colorpicker_bar-cursors{position:absolute;right:0;width:25px;top:0;height:200px;overflow:hidden}.ge_colorpicker_bar-cursor-left,.ge_colorpicker_bar-cursor-right{position:absolute;width:0;height:0;border:4px solid transparent;margin-top:-4px}.ge_colorpicker_bar-cursor-left{left:0;border-left:4px solid #eee}.ge_colorpicker_bar-cursor-right{right:0;border-right:4px solid #eee}.ge_colorpicker_dark .ge_colorpicker_bar-cursor-left{border-left-color:#333}.ge_colorpicker_dark .ge_colorpicker_bar-cursor-right{border-right-color:#333}.ge_colorpicker_link-button{position:absolute;bottom:5px;left:5px;color:#85ccc4;font-family:Helvetica,Arial,sans-serif;font-size:20px;font-weight:100;cursor:pointer}.ge_modal{box-sizing:border-box;position:absolute;z-index:1000;-webkit-user-select:none;-ms-user-select:none;user-select:none;box-shadow:0 0 0 5px rgba(0,0,0,.2),0 4px 8px 0 rgba(0,0,0,.25);font-family:Helvetica,Geneva,sans-serif;font-weight:100}.ge_export_modal{overflow:hidden;color:#eefafa;background-color:#2f302b;box-shadow:0 5px 5px 5px rgba(0,0,0,.2),0 5px 0 0 rgba(0,0,0,.25);-webkit-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;margin:0;padding-right:10px;padding-left:10px;padding-top:5px;padding-bottom:5px;list-style-type:none}.ge_tooltip_modal{padding:10px;padding-top:0;padding-bottom:0;background-color:#2e3033;font-size:14px}.ge_tooltip_modal a{text-decoration:none;color:#b3e5fc}.ge_tooltip_modal p{color:#c0c6c6;margin:6px}.ge-error,.ge-warning{position:relative;font-family:Source Code Pro,monospace;padding-left:3em;padding-right:10px}.ge-error-icon,.ge-warning-icon{position:absolute;left:0;width:3em;text-align:center}.ge-error{background:#be1a20;color:white}.ge-warning{background:#fc0;color:black}.ge_assing_marker{margin-left:-15px;color:#b3e5fc;font-size:10px}.ge_assing_marker_faster{color:green;background-color:green}.ge_assing_marker_pct{position:absolute;top:0;left:-17px;height:100%;z-index:-1;background-color:#555}.ge_assing_marker_slower{background-color:red}.ge_assing_marker:hover{color:white}.ge_assing_marker_on{margin-left:-15px;color:white}.ge_export_icon{position:relative;float:right;right:8px;bottom:40px;width:32px;height:28px;border-radius:16px;padding-top:4px;-webkit-user-select:none;-ms-user-select:none;user-select:none;z-index:300;text-align:center;vertical-align:bottom;background-color:rgba(0,0,0,.5);font-size:18px!important;color:#eefafa;cursor:pointer}.ge_export_icon:hover{color:#b3e5fc} -/*# sourceMappingURL=glslEditor.css.map */ diff --git a/build/glslEditor.css.map b/build/glslEditor.css.map deleted file mode 100644 index fa00163..0000000 --- a/build/glslEditor.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["glslEditor.css","../../node_modules/codemirror/lib/codemirror.css","../../node_modules/codemirror/addon/dialog/dialog.css","../../node_modules/codemirror/addon/fold/foldgutter.css","../../node_modules/codemirror/addon/hint/show-hint.css","../../node_modules/codemirror/theme/ambiance.css","../../node_modules/codemirror/theme/base16-dark.css","../../node_modules/codemirror/theme/base16-light.css","../../node_modules/codemirror/theme/dracula.css","../../node_modules/codemirror/theme/eclipse.css","../../node_modules/codemirror/theme/elegant.css","../../node_modules/codemirror/theme/icecoder.css","../../node_modules/codemirror/theme/lesser-dark.css","../../node_modules/codemirror/theme/material.css","../../node_modules/codemirror/theme/mdn-like.css","../../node_modules/codemirror/theme/midnight.css","../../node_modules/codemirror/theme/monokai.css","../../node_modules/codemirror/theme/neat.css","../../node_modules/codemirror/theme/neo.css","../../node_modules/codemirror/theme/pastel-on-dark.css","../../node_modules/codemirror/theme/railscasts.css","../../node_modules/codemirror/theme/seti.css","../../node_modules/codemirror/theme/solarized.css","../../node_modules/codemirror/theme/tomorrow-night-bright.css","../../node_modules/codemirror/theme/tomorrow-night-eighties.css","../../node_modules/codemirror/theme/ttcn.css","../../node_modules/codemirror/theme/yeti.css","_menu.css","_panel.css","_editor.css","_shader.css","_pickers.css","_modals.css","_errors.css","_debugger.css","_icons.css"],"names":[],"mappings":"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","file":"glslEditor.css","sourcesContent":["@charset 'utf-8';\n\n/* VARIABLES */\n\n:root {\n --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;\n /* -- font-family: 'Montserrat'; */\n --editor-font-family: 'Source Code Pro', monospace;\n --ui-base-color: #2f302b;\n --ui-component-color: #2e3033;\n --ui-element-color: #3a3c40;\n --ui-active-color: #171e22;\n --ui-highlight-color: #B3E5FC;\n --ui-component-text-color: #eefafa;\n --ui-link-text-color: #e1eeee;\n --ui-subtext-color: #c0c6c6;\n --ui-border-color: #999ca0;\n --modal-shadow: 0 0 0 5px rgba(0,0,0,0.2), 0 4px 8px 0 rgba(0,0,0,0.25);\n\n /* Z-INDEX SCALE */\n --z-editor: 100;\n --z-shader-ghost: 199;\n --z-shader: 200;\n --z-divider: 250;\n --z-menu: 300;\n --z-helpers: 1000;\n}\n\n/* Native Codemirror */\n@import 'codemirror/lib/codemirror.css';\n@import 'codemirror/addon/dialog/dialog.css';\n@import 'codemirror/addon/fold/foldgutter.css';\n@import 'codemirror/addon/hint/show-hint.css';\n\n/* Themes */\n@import 'codemirror/theme/ambiance.css';\n@import 'codemirror/theme/base16-dark.css';\n@import 'codemirror/theme/base16-light.css';\n@import 'codemirror/theme/dracula.css';\n@import 'codemirror/theme/eclipse.css';\n@import 'codemirror/theme/elegant.css';\n@import 'codemirror/theme/icecoder.css';\n@import 'codemirror/theme/lesser-dark.css';\n@import 'codemirror/theme/material.css';\n@import 'codemirror/theme/mdn-like.css';\n@import 'codemirror/theme/midnight.css';\n@import 'codemirror/theme/monokai.css';\n@import 'codemirror/theme/neat.css';\n@import 'codemirror/theme/neo.css';\n@import 'codemirror/theme/pastel-on-dark.css';\n@import 'codemirror/theme/railscasts.css';\n@import 'codemirror/theme/seti.css';\n@import 'codemirror/theme/solarized.css';\n@import 'codemirror/theme/tomorrow-night-bright.css';\n@import 'codemirror/theme/tomorrow-night-eighties.css';\n@import 'codemirror/theme/ttcn.css';\n@import 'codemirror/theme/yeti.css';\n\n/* Elements */\n@import '_menu';\n@import '_panel';\n@import '_editor';\n@import '_shader';\n\n@import '_pickers';\n@import '_modals';\n@import '_errors';\n@import '_debugger';\n@import '_icons';\n","/* BASICS */\n\n.CodeMirror {\n /* Set height, width, borders, and global font properties here */\n font-family: monospace;\n height: 300px;\n color: black;\n}\n\n/* PADDING */\n\n.CodeMirror-lines {\n padding: 4px 0; /* Vertical padding around content */\n}\n.CodeMirror pre {\n padding: 0 4px; /* Horizontal padding of content */\n}\n\n.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n background-color: white; /* The little square between H and V scrollbars */\n}\n\n/* GUTTER */\n\n.CodeMirror-gutters {\n border-right: 1px solid #ddd;\n background-color: #f7f7f7;\n white-space: nowrap;\n}\n.CodeMirror-linenumbers {}\n.CodeMirror-linenumber {\n padding: 0 3px 0 5px;\n min-width: 20px;\n text-align: right;\n color: #999;\n white-space: nowrap;\n}\n\n.CodeMirror-guttermarker { color: black; }\n.CodeMirror-guttermarker-subtle { color: #999; }\n\n/* CURSOR */\n\n.CodeMirror-cursor {\n border-left: 1px solid black;\n border-right: none;\n width: 0;\n}\n/* Shown when moving in bi-directional text */\n.CodeMirror div.CodeMirror-secondarycursor {\n border-left: 1px solid silver;\n}\n.cm-fat-cursor .CodeMirror-cursor {\n width: auto;\n border: 0;\n background: #7e7;\n}\n.cm-fat-cursor div.CodeMirror-cursors {\n z-index: 1;\n}\n\n.cm-animate-fat-cursor {\n width: auto;\n border: 0;\n -webkit-animation: blink 1.06s steps(1) infinite;\n -moz-animation: blink 1.06s steps(1) infinite;\n animation: blink 1.06s steps(1) infinite;\n background-color: #7e7;\n}\n@-moz-keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n@-webkit-keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n@keyframes blink {\n 0% {}\n 50% { background-color: transparent; }\n 100% {}\n}\n\n/* Can style cursor different in overwrite (non-insert) mode */\n.CodeMirror-overwrite .CodeMirror-cursor {}\n\n.cm-tab { display: inline-block; text-decoration: inherit; }\n\n.CodeMirror-ruler {\n border-left: 1px solid #ccc;\n position: absolute;\n}\n\n/* DEFAULT THEME */\n\n.cm-s-default .cm-header {color: blue;}\n.cm-s-default .cm-quote {color: #090;}\n.cm-negative {color: #d44;}\n.cm-positive {color: #292;}\n.cm-header, .cm-strong {font-weight: bold;}\n.cm-em {font-style: italic;}\n.cm-link {text-decoration: underline;}\n.cm-strikethrough {text-decoration: line-through;}\n\n.cm-s-default .cm-keyword {color: #708;}\n.cm-s-default .cm-atom {color: #219;}\n.cm-s-default .cm-number {color: #164;}\n.cm-s-default .cm-def {color: #00f;}\n.cm-s-default .cm-variable,\n.cm-s-default .cm-punctuation,\n.cm-s-default .cm-property,\n.cm-s-default .cm-operator {}\n.cm-s-default .cm-variable-2 {color: #05a;}\n.cm-s-default .cm-variable-3 {color: #085;}\n.cm-s-default .cm-comment {color: #a50;}\n.cm-s-default .cm-string {color: #a11;}\n.cm-s-default .cm-string-2 {color: #f50;}\n.cm-s-default .cm-meta {color: #555;}\n.cm-s-default .cm-qualifier {color: #555;}\n.cm-s-default .cm-builtin {color: #30a;}\n.cm-s-default .cm-bracket {color: #997;}\n.cm-s-default .cm-tag {color: #170;}\n.cm-s-default .cm-attribute {color: #00c;}\n.cm-s-default .cm-hr {color: #999;}\n.cm-s-default .cm-link {color: #00c;}\n\n.cm-s-default .cm-error {color: #f00;}\n.cm-invalidchar {color: #f00;}\n\n.CodeMirror-composing { border-bottom: 2px solid; }\n\n/* Default styles for common addons */\n\ndiv.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}\ndiv.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}\n.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }\n.CodeMirror-activeline-background {background: #e8f2ff;}\n\n/* STOP */\n\n/* The rest of this file contains styles related to the mechanics of\n the editor. You probably shouldn't touch them. */\n\n.CodeMirror {\n position: relative;\n overflow: hidden;\n background: white;\n}\n\n.CodeMirror-scroll {\n overflow: scroll !important; /* Things will break if this is overridden */\n /* 30px is the magic margin used to hide the element's real scrollbars */\n /* See overflow: hidden in .CodeMirror */\n margin-bottom: -30px; margin-right: -30px;\n padding-bottom: 30px;\n height: 100%;\n outline: none; /* Prevent dragging from highlighting the element */\n position: relative;\n}\n.CodeMirror-sizer {\n position: relative;\n border-right: 30px solid transparent;\n}\n\n/* The fake, visible scrollbars. Used to force redraw during scrolling\n before actuall scrolling happens, thus preventing shaking and\n flickering artifacts. */\n.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {\n position: absolute;\n z-index: 6;\n display: none;\n}\n.CodeMirror-vscrollbar {\n right: 0; top: 0;\n overflow-x: hidden;\n overflow-y: scroll;\n}\n.CodeMirror-hscrollbar {\n bottom: 0; left: 0;\n overflow-y: hidden;\n overflow-x: scroll;\n}\n.CodeMirror-scrollbar-filler {\n right: 0; bottom: 0;\n}\n.CodeMirror-gutter-filler {\n left: 0; bottom: 0;\n}\n\n.CodeMirror-gutters {\n position: absolute; left: 0; top: 0;\n z-index: 3;\n}\n.CodeMirror-gutter {\n white-space: normal;\n height: 100%;\n display: inline-block;\n margin-bottom: -30px;\n /* Hack to make IE7 behave */\n *zoom:1;\n *display:inline;\n}\n.CodeMirror-gutter-wrapper {\n position: absolute;\n z-index: 4;\n background: none !important;\n border: none !important;\n}\n.CodeMirror-gutter-background {\n position: absolute;\n top: 0; bottom: 0;\n z-index: 4;\n}\n.CodeMirror-gutter-elt {\n position: absolute;\n cursor: default;\n z-index: 4;\n}\n.CodeMirror-gutter-wrapper {\n -webkit-user-select: none;\n -moz-user-select: none;\n user-select: none;\n}\n\n.CodeMirror-lines {\n cursor: text;\n min-height: 1px; /* prevents collapsing before first draw */\n}\n.CodeMirror pre {\n /* Reset some styles that the rest of the page might have set */\n -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;\n border-width: 0;\n background: transparent;\n font-family: inherit;\n font-size: inherit;\n margin: 0;\n white-space: pre;\n word-wrap: normal;\n line-height: inherit;\n color: inherit;\n z-index: 2;\n position: relative;\n overflow: visible;\n -webkit-tap-highlight-color: transparent;\n}\n.CodeMirror-wrap pre {\n word-wrap: break-word;\n white-space: pre-wrap;\n word-break: normal;\n}\n\n.CodeMirror-linebackground {\n position: absolute;\n left: 0; right: 0; top: 0; bottom: 0;\n z-index: 0;\n}\n\n.CodeMirror-linewidget {\n position: relative;\n z-index: 2;\n overflow: auto;\n}\n\n.CodeMirror-widget {}\n\n.CodeMirror-code {\n outline: none;\n}\n\n/* Force content-box sizing for the elements where we expect it */\n.CodeMirror-scroll,\n.CodeMirror-sizer,\n.CodeMirror-gutter,\n.CodeMirror-gutters,\n.CodeMirror-linenumber {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n}\n\n.CodeMirror-measure {\n position: absolute;\n width: 100%;\n height: 0;\n overflow: hidden;\n visibility: hidden;\n}\n\n.CodeMirror-cursor { position: absolute; }\n.CodeMirror-measure pre { position: static; }\n\ndiv.CodeMirror-cursors {\n visibility: hidden;\n position: relative;\n z-index: 3;\n}\ndiv.CodeMirror-dragcursors {\n visibility: visible;\n}\n\n.CodeMirror-focused div.CodeMirror-cursors {\n visibility: visible;\n}\n\n.CodeMirror-selected { background: #d9d9d9; }\n.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }\n.CodeMirror-crosshair { cursor: crosshair; }\n.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }\n.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }\n\n.cm-searching {\n background: #ffa;\n background: rgba(255, 255, 0, .4);\n}\n\n/* IE7 hack to prevent it from returning funny offsetTops on the spans */\n.CodeMirror span { *vertical-align: text-bottom; }\n\n/* Used to force a border model for a node */\n.cm-force-border { padding-right: .1px; }\n\n@media print {\n /* Hide the cursor when printing */\n .CodeMirror div.CodeMirror-cursors {\n visibility: hidden;\n }\n}\n\n/* See issue #2901 */\n.cm-tab-wrap-hack:after { content: ''; }\n\n/* Help users use markselection to safely style text background */\nspan.CodeMirror-selectedtext { background: none; }\n",".CodeMirror-dialog {\n position: absolute;\n left: 0; right: 0;\n background: inherit;\n z-index: 15;\n padding: .1em .8em;\n overflow: hidden;\n color: inherit;\n}\n\n.CodeMirror-dialog-top {\n border-bottom: 1px solid #eee;\n top: 0;\n}\n\n.CodeMirror-dialog-bottom {\n border-top: 1px solid #eee;\n bottom: 0;\n}\n\n.CodeMirror-dialog input {\n border: none;\n outline: none;\n background: transparent;\n width: 20em;\n color: inherit;\n font-family: monospace;\n}\n\n.CodeMirror-dialog button {\n font-size: 70%;\n}\n",".CodeMirror-foldmarker {\n color: blue;\n text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;\n font-family: arial;\n line-height: .3;\n cursor: pointer;\n}\n.CodeMirror-foldgutter {\n width: .7em;\n}\n.CodeMirror-foldgutter-open,\n.CodeMirror-foldgutter-folded {\n cursor: pointer;\n}\n.CodeMirror-foldgutter-open:after {\n content: \"\\25BE\";\n}\n.CodeMirror-foldgutter-folded:after {\n content: \"\\25B8\";\n}\n",".CodeMirror-hints {\n position: absolute;\n z-index: 10;\n overflow: hidden;\n list-style: none;\n\n margin: 0;\n padding: 2px;\n\n -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n box-shadow: 2px 3px 5px rgba(0,0,0,.2);\n border-radius: 3px;\n border: 1px solid silver;\n\n background: white;\n font-size: 90%;\n font-family: monospace;\n\n max-height: 20em;\n overflow-y: auto;\n}\n\n.CodeMirror-hint {\n margin: 0;\n padding: 0 4px;\n border-radius: 2px;\n max-width: 19em;\n overflow: hidden;\n white-space: pre;\n color: black;\n cursor: pointer;\n}\n\nli.CodeMirror-hint-active {\n background: #08f;\n color: white;\n}\n","/* ambiance theme for codemirror */\n\n/* Color scheme */\n\n.cm-s-ambiance .cm-header { color: blue; }\n.cm-s-ambiance .cm-quote { color: #24C2C7; }\n\n.cm-s-ambiance .cm-keyword { color: #cda869; }\n.cm-s-ambiance .cm-atom { color: #CF7EA9; }\n.cm-s-ambiance .cm-number { color: #78CF8A; }\n.cm-s-ambiance .cm-def { color: #aac6e3; }\n.cm-s-ambiance .cm-variable { color: #ffb795; }\n.cm-s-ambiance .cm-variable-2 { color: #eed1b3; }\n.cm-s-ambiance .cm-variable-3 { color: #faded3; }\n.cm-s-ambiance .cm-property { color: #eed1b3; }\n.cm-s-ambiance .cm-operator { color: #fa8d6a; }\n.cm-s-ambiance .cm-comment { color: #555; font-style:italic; }\n.cm-s-ambiance .cm-string { color: #8f9d6a; }\n.cm-s-ambiance .cm-string-2 { color: #9d937c; }\n.cm-s-ambiance .cm-meta { color: #D2A8A1; }\n.cm-s-ambiance .cm-qualifier { color: yellow; }\n.cm-s-ambiance .cm-builtin { color: #9999cc; }\n.cm-s-ambiance .cm-bracket { color: #24C2C7; }\n.cm-s-ambiance .cm-tag { color: #fee4ff; }\n.cm-s-ambiance .cm-attribute { color: #9B859D; }\n.cm-s-ambiance .cm-hr { color: pink; }\n.cm-s-ambiance .cm-link { color: #F4C20B; }\n.cm-s-ambiance .cm-special { color: #FF9D00; }\n.cm-s-ambiance .cm-error { color: #AF2018; }\n\n.cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; }\n.cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; }\n\n.cm-s-ambiance div.CodeMirror-selected { background: rgba(255, 255, 255, 0.15); }\n.cm-s-ambiance.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }\n.cm-s-ambiance .CodeMirror-line::selection, .cm-s-ambiance .CodeMirror-line > span::selection, .cm-s-ambiance .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }\n.cm-s-ambiance .CodeMirror-line::-moz-selection, .cm-s-ambiance .CodeMirror-line > span::-moz-selection, .cm-s-ambiance .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }\n\n/* Editor styling */\n\n.cm-s-ambiance.CodeMirror {\n line-height: 1.40em;\n color: #E6E1DC;\n background-color: #202020;\n -webkit-box-shadow: inset 0 0 10px black;\n -moz-box-shadow: inset 0 0 10px black;\n box-shadow: inset 0 0 10px black;\n}\n\n.cm-s-ambiance .CodeMirror-gutters {\n background: #3D3D3D;\n border-right: 1px solid #4D4D4D;\n box-shadow: 0 10px 20px black;\n}\n\n.cm-s-ambiance .CodeMirror-linenumber {\n text-shadow: 0px 1px 1px #4d4d4d;\n color: #111;\n padding: 0 5px;\n}\n\n.cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; }\n.cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; }\n\n.cm-s-ambiance .CodeMirror-cursor { border-left: 1px solid #7991E8; }\n\n.cm-s-ambiance .CodeMirror-activeline-background {\n background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031);\n}\n\n.cm-s-ambiance.CodeMirror,\n.cm-s-ambiance .CodeMirror-gutters {\n background-image: url(\"data:image/png;base64,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\");\n}\n","/*\n\n Name: Base16 Default Dark\n Author: Chris Kempson (http://chriskempson.com)\n\n CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)\n Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)\n\n*/\n\n.cm-s-base16-dark.CodeMirror { background: #151515; color: #e0e0e0; }\n.cm-s-base16-dark div.CodeMirror-selected { background: #303030; }\n.cm-s-base16-dark .CodeMirror-line::selection, .cm-s-base16-dark .CodeMirror-line > span::selection, .cm-s-base16-dark .CodeMirror-line > span > span::selection { background: rgba(48, 48, 48, .99); }\n.cm-s-base16-dark .CodeMirror-line::-moz-selection, .cm-s-base16-dark .CodeMirror-line > span::-moz-selection, .cm-s-base16-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(48, 48, 48, .99); }\n.cm-s-base16-dark .CodeMirror-gutters { background: #151515; border-right: 0px; }\n.cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; }\n.cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; }\n.cm-s-base16-dark .CodeMirror-linenumber { color: #505050; }\n.cm-s-base16-dark .CodeMirror-cursor { border-left: 1px solid #b0b0b0; }\n\n.cm-s-base16-dark span.cm-comment { color: #8f5536; }\n.cm-s-base16-dark span.cm-atom { color: #aa759f; }\n.cm-s-base16-dark span.cm-number { color: #aa759f; }\n\n.cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute { color: #90a959; }\n.cm-s-base16-dark span.cm-keyword { color: #ac4142; }\n.cm-s-base16-dark span.cm-string { color: #f4bf75; }\n\n.cm-s-base16-dark span.cm-variable { color: #90a959; }\n.cm-s-base16-dark span.cm-variable-2 { color: #6a9fb5; }\n.cm-s-base16-dark span.cm-def { color: #d28445; }\n.cm-s-base16-dark span.cm-bracket { color: #e0e0e0; }\n.cm-s-base16-dark span.cm-tag { color: #ac4142; }\n.cm-s-base16-dark span.cm-link { color: #aa759f; }\n.cm-s-base16-dark span.cm-error { background: #ac4142; color: #b0b0b0; }\n\n.cm-s-base16-dark .CodeMirror-activeline-background { background: #202020; }\n.cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n","/*\n\n Name: Base16 Default Light\n Author: Chris Kempson (http://chriskempson.com)\n\n CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)\n Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)\n\n*/\n\n.cm-s-base16-light.CodeMirror { background: #f5f5f5; color: #202020; }\n.cm-s-base16-light div.CodeMirror-selected { background: #e0e0e0; }\n.cm-s-base16-light .CodeMirror-line::selection, .cm-s-base16-light .CodeMirror-line > span::selection, .cm-s-base16-light .CodeMirror-line > span > span::selection { background: #e0e0e0; }\n.cm-s-base16-light .CodeMirror-line::-moz-selection, .cm-s-base16-light .CodeMirror-line > span::-moz-selection, .cm-s-base16-light .CodeMirror-line > span > span::-moz-selection { background: #e0e0e0; }\n.cm-s-base16-light .CodeMirror-gutters { background: #f5f5f5; border-right: 0px; }\n.cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; }\n.cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; }\n.cm-s-base16-light .CodeMirror-linenumber { color: #b0b0b0; }\n.cm-s-base16-light .CodeMirror-cursor { border-left: 1px solid #505050; }\n\n.cm-s-base16-light span.cm-comment { color: #8f5536; }\n.cm-s-base16-light span.cm-atom { color: #aa759f; }\n.cm-s-base16-light span.cm-number { color: #aa759f; }\n\n.cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute { color: #90a959; }\n.cm-s-base16-light span.cm-keyword { color: #ac4142; }\n.cm-s-base16-light span.cm-string { color: #f4bf75; }\n\n.cm-s-base16-light span.cm-variable { color: #90a959; }\n.cm-s-base16-light span.cm-variable-2 { color: #6a9fb5; }\n.cm-s-base16-light span.cm-def { color: #d28445; }\n.cm-s-base16-light span.cm-bracket { color: #202020; }\n.cm-s-base16-light span.cm-tag { color: #ac4142; }\n.cm-s-base16-light span.cm-link { color: #aa759f; }\n.cm-s-base16-light span.cm-error { background: #ac4142; color: #505050; }\n\n.cm-s-base16-light .CodeMirror-activeline-background { background: #DDDCDC; }\n.cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n","/*\n\n Name: dracula\n Author: Michael Kaminsky (http://github.com/mkaminsky11)\n\n Original dracula color scheme by Zeno Rocha (https://github.com/zenorocha/dracula-theme)\n\n*/\n\n\n.cm-s-dracula.CodeMirror, .cm-s-dracula .CodeMirror-gutters {\n background-color: #282a36 !important;\n color: #f8f8f2 !important;\n border: none;\n}\n.cm-s-dracula .CodeMirror-gutters { color: #282a36; }\n.cm-s-dracula .CodeMirror-cursor { border-left: solid thin #f8f8f0; }\n.cm-s-dracula .CodeMirror-linenumber { color: #6D8A88; }\n.cm-s-dracula.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }\n.cm-s-dracula .CodeMirror-line::selection, .cm-s-dracula .CodeMirror-line > span::selection, .cm-s-dracula .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }\n.cm-s-dracula .CodeMirror-line::-moz-selection, .cm-s-dracula .CodeMirror-line > span::-moz-selection, .cm-s-dracula .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }\n.cm-s-dracula span.cm-comment { color: #6272a4; }\n.cm-s-dracula span.cm-string, .cm-s-dracula span.cm-string-2 { color: #f1fa8c; }\n.cm-s-dracula span.cm-number { color: #bd93f9; }\n.cm-s-dracula span.cm-variable { color: #50fa7b; }\n.cm-s-dracula span.cm-variable-2 { color: white; }\n.cm-s-dracula span.cm-def { color: #ffb86c; }\n.cm-s-dracula span.cm-keyword { color: #ff79c6; }\n.cm-s-dracula span.cm-operator { color: #ff79c6; }\n.cm-s-dracula span.cm-keyword { color: #ff79c6; }\n.cm-s-dracula span.cm-atom { color: #bd93f9; }\n.cm-s-dracula span.cm-meta { color: #f8f8f2; }\n.cm-s-dracula span.cm-tag { color: #ff79c6; }\n.cm-s-dracula span.cm-attribute { color: #50fa7b; }\n.cm-s-dracula span.cm-qualifier { color: #50fa7b; }\n.cm-s-dracula span.cm-property { color: #66d9ef; }\n.cm-s-dracula span.cm-builtin { color: #50fa7b; }\n.cm-s-dracula span.cm-variable-3 { color: #50fa7b; }\n\n.cm-s-dracula .CodeMirror-activeline-background { background: rgba(255,255,255,0.1); }\n.cm-s-dracula .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n",".cm-s-eclipse span.cm-meta { color: #FF1717; }\n.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }\n.cm-s-eclipse span.cm-atom { color: #219; }\n.cm-s-eclipse span.cm-number { color: #164; }\n.cm-s-eclipse span.cm-def { color: #00f; }\n.cm-s-eclipse span.cm-variable { color: black; }\n.cm-s-eclipse span.cm-variable-2 { color: #0000C0; }\n.cm-s-eclipse span.cm-variable-3 { color: #0000C0; }\n.cm-s-eclipse span.cm-property { color: black; }\n.cm-s-eclipse span.cm-operator { color: black; }\n.cm-s-eclipse span.cm-comment { color: #3F7F5F; }\n.cm-s-eclipse span.cm-string { color: #2A00FF; }\n.cm-s-eclipse span.cm-string-2 { color: #f50; }\n.cm-s-eclipse span.cm-qualifier { color: #555; }\n.cm-s-eclipse span.cm-builtin { color: #30a; }\n.cm-s-eclipse span.cm-bracket { color: #cc7; }\n.cm-s-eclipse span.cm-tag { color: #170; }\n.cm-s-eclipse span.cm-attribute { color: #00c; }\n.cm-s-eclipse span.cm-link { color: #219; }\n.cm-s-eclipse span.cm-error { color: #f00; }\n\n.cm-s-eclipse .CodeMirror-activeline-background { background: #e8f2ff; }\n.cm-s-eclipse .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }\n",".cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom { color: #762; }\n.cm-s-elegant span.cm-comment { color: #262; font-style: italic; line-height: 1em; }\n.cm-s-elegant span.cm-meta { color: #555; font-style: italic; line-height: 1em; }\n.cm-s-elegant span.cm-variable { color: black; }\n.cm-s-elegant span.cm-variable-2 { color: #b11; }\n.cm-s-elegant span.cm-qualifier { color: #555; }\n.cm-s-elegant span.cm-keyword { color: #730; }\n.cm-s-elegant span.cm-builtin { color: #30a; }\n.cm-s-elegant span.cm-link { color: #762; }\n.cm-s-elegant span.cm-error { background-color: #fdd; }\n\n.cm-s-elegant .CodeMirror-activeline-background { background: #e8f2ff; }\n.cm-s-elegant .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }\n","/*\nICEcoder default theme by Matt Pass, used in code editor available at https://icecoder.net\n*/\n\n.cm-s-icecoder { color: #666; background: #141612; }\n\n.cm-s-icecoder span.cm-keyword { color: #eee; font-weight:bold; } /* off-white 1 */\n.cm-s-icecoder span.cm-atom { color: #e1c76e; } /* yellow */\n.cm-s-icecoder span.cm-number { color: #6cb5d9; } /* blue */\n.cm-s-icecoder span.cm-def { color: #b9ca4a; } /* green */\n\n.cm-s-icecoder span.cm-variable { color: #6cb5d9; } /* blue */\n.cm-s-icecoder span.cm-variable-2 { color: #cc1e5c; } /* pink */\n.cm-s-icecoder span.cm-variable-3 { color: #f9602c; } /* orange */\n\n.cm-s-icecoder span.cm-property { color: #eee; } /* off-white 1 */\n.cm-s-icecoder span.cm-operator { color: #9179bb; } /* purple */\n.cm-s-icecoder span.cm-comment { color: #97a3aa; } /* grey-blue */\n\n.cm-s-icecoder span.cm-string { color: #b9ca4a; } /* green */\n.cm-s-icecoder span.cm-string-2 { color: #6cb5d9; } /* blue */\n\n.cm-s-icecoder span.cm-meta { color: #555; } /* grey */\n\n.cm-s-icecoder span.cm-qualifier { color: #555; } /* grey */\n.cm-s-icecoder span.cm-builtin { color: #214e7b; } /* bright blue */\n.cm-s-icecoder span.cm-bracket { color: #cc7; } /* grey-yellow */\n\n.cm-s-icecoder span.cm-tag { color: #e8e8e8; } /* off-white 2 */\n.cm-s-icecoder span.cm-attribute { color: #099; } /* teal */\n\n.cm-s-icecoder span.cm-header { color: #6a0d6a; } /* purple-pink */\n.cm-s-icecoder span.cm-quote { color: #186718; } /* dark green */\n.cm-s-icecoder span.cm-hr { color: #888; } /* mid-grey */\n.cm-s-icecoder span.cm-link { color: #e1c76e; } /* yellow */\n.cm-s-icecoder span.cm-error { color: #d00; } /* red */\n\n.cm-s-icecoder .CodeMirror-cursor { border-left: 1px solid white; }\n.cm-s-icecoder div.CodeMirror-selected { color: #fff; background: #037; }\n.cm-s-icecoder .CodeMirror-gutters { background: #141612; min-width: 41px; border-right: 0; }\n.cm-s-icecoder .CodeMirror-linenumber { color: #555; cursor: default; }\n.cm-s-icecoder .CodeMirror-matchingbracket { border: 1px solid grey; color: black !important; }\n.cm-s-icecoder .CodeMirror-activeline-background { background: #000; }","/*\nhttp://lesscss.org/ dark theme\nPorted to CodeMirror by Peter Kroon\n*/\n.cm-s-lesser-dark {\n line-height: 1.3em;\n}\n.cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }\n.cm-s-lesser-dark div.CodeMirror-selected { background: #45443B; } /* 33322B*/\n.cm-s-lesser-dark .CodeMirror-line::selection, .cm-s-lesser-dark .CodeMirror-line > span::selection, .cm-s-lesser-dark .CodeMirror-line > span > span::selection { background: rgba(69, 68, 59, .99); }\n.cm-s-lesser-dark .CodeMirror-line::-moz-selection, .cm-s-lesser-dark .CodeMirror-line > span::-moz-selection, .cm-s-lesser-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(69, 68, 59, .99); }\n.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white; }\n.cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/\n\n.cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/\n\n.cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; }\n.cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; }\n.cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; }\n.cm-s-lesser-dark .CodeMirror-linenumber { color: #777; }\n\n.cm-s-lesser-dark span.cm-header { color: #a0a; }\n.cm-s-lesser-dark span.cm-quote { color: #090; }\n.cm-s-lesser-dark span.cm-keyword { color: #599eff; }\n.cm-s-lesser-dark span.cm-atom { color: #C2B470; }\n.cm-s-lesser-dark span.cm-number { color: #B35E4D; }\n.cm-s-lesser-dark span.cm-def { color: white; }\n.cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }\n.cm-s-lesser-dark span.cm-variable-2 { color: #669199; }\n.cm-s-lesser-dark span.cm-variable-3 { color: white; }\n.cm-s-lesser-dark span.cm-property { color: #92A75C; }\n.cm-s-lesser-dark span.cm-operator { color: #92A75C; }\n.cm-s-lesser-dark span.cm-comment { color: #666; }\n.cm-s-lesser-dark span.cm-string { color: #BCD279; }\n.cm-s-lesser-dark span.cm-string-2 { color: #f50; }\n.cm-s-lesser-dark span.cm-meta { color: #738C73; }\n.cm-s-lesser-dark span.cm-qualifier { color: #555; }\n.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }\n.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }\n.cm-s-lesser-dark span.cm-tag { color: #669199; }\n.cm-s-lesser-dark span.cm-attribute { color: #00c; }\n.cm-s-lesser-dark span.cm-hr { color: #999; }\n.cm-s-lesser-dark span.cm-link { color: #00c; }\n.cm-s-lesser-dark span.cm-error { color: #9d1e15; }\n\n.cm-s-lesser-dark .CodeMirror-activeline-background { background: #3C3A3A; }\n.cm-s-lesser-dark .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }\n","/*\n\n Name: material\n Author: Michael Kaminsky (http://github.com/mkaminsky11)\n\n Original material color scheme by Mattia Astorino (https://github.com/equinusocio/material-theme)\n\n*/\n\n.cm-s-material {\n background-color: #263238;\n color: rgba(233, 237, 237, 1);\n}\n.cm-s-material .CodeMirror-gutters {\n background: #263238;\n color: rgb(83,127,126);\n border: none;\n}\n.cm-s-material .CodeMirror-guttermarker, .cm-s-material .CodeMirror-guttermarker-subtle, .cm-s-material .CodeMirror-linenumber { color: rgb(83,127,126); }\n.cm-s-material .CodeMirror-cursor { border-left: 1px solid #f8f8f0; }\n.cm-s-material div.CodeMirror-selected { background: rgba(255, 255, 255, 0.15); }\n.cm-s-material.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }\n.cm-s-material .CodeMirror-line::selection, .cm-s-material .CodeMirror-line > span::selection, .cm-s-material .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }\n.cm-s-material .CodeMirror-line::-moz-selection, .cm-s-material .CodeMirror-line > span::-moz-selection, .cm-s-material .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }\n\n.cm-s-material .CodeMirror-activeline-background { background: rgba(0, 0, 0, 0); }\n.cm-s-material .cm-keyword { color: rgba(199, 146, 234, 1); }\n.cm-s-material .cm-operator { color: rgba(233, 237, 237, 1); }\n.cm-s-material .cm-variable-2 { color: #80CBC4; }\n.cm-s-material .cm-variable-3 { color: #82B1FF; }\n.cm-s-material .cm-builtin { color: #DECB6B; }\n.cm-s-material .cm-atom { color: #F77669; }\n.cm-s-material .cm-number { color: #F77669; }\n.cm-s-material .cm-def { color: rgba(233, 237, 237, 1); }\n.cm-s-material .cm-error {\n color: rgba(255, 255, 255, 1.0);\n background-color: #EC5F67;\n}\n.cm-s-material .cm-string { color: #C3E88D; }\n.cm-s-material .cm-string-2 { color: #80CBC4; }\n.cm-s-material .cm-comment { color: #546E7A; }\n.cm-s-material .cm-variable { color: #82B1FF; }\n.cm-s-material .cm-tag { color: #80CBC4; }\n.cm-s-material .cm-meta { color: #80CBC4; }\n.cm-s-material .cm-attribute { color: #FFCB6B; }\n.cm-s-material .cm-property { color: #80CBAE; }\n.cm-s-material .cm-qualifier { color: #DECB6B; }\n.cm-s-material .cm-variable-3 { color: #DECB6B; }\n.cm-s-material .cm-tag { color: rgba(255, 83, 112, 1); }\n.cm-s-material .CodeMirror-matchingbracket {\n text-decoration: underline;\n color: white !important;\n}\n","/*\n MDN-LIKE Theme - Mozilla\n Ported to CodeMirror by Peter Kroon \n Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues\n GitHub: @peterkroon\n\n The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation\n\n*/\n.cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; }\n.cm-s-mdn-like div.CodeMirror-selected { background: #cfc; }\n.cm-s-mdn-like .CodeMirror-line::selection, .cm-s-mdn-like .CodeMirror-line > span::selection, .cm-s-mdn-like .CodeMirror-line > span > span::selection { background: #cfc; }\n.cm-s-mdn-like .CodeMirror-line::-moz-selection, .cm-s-mdn-like .CodeMirror-line > span::-moz-selection, .cm-s-mdn-like .CodeMirror-line > span > span::-moz-selection { background: #cfc; }\n\n.cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; }\n.cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; padding-left: 8px; }\n.cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; }\n\n.cm-s-mdn-like .cm-keyword { color: #6262FF; }\n.cm-s-mdn-like .cm-atom { color: #F90; }\n.cm-s-mdn-like .cm-number { color: #ca7841; }\n.cm-s-mdn-like .cm-def { color: #8DA6CE; }\n.cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; }\n.cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; }\n\n.cm-s-mdn-like .cm-variable { color: #07a; }\n.cm-s-mdn-like .cm-property { color: #905; }\n.cm-s-mdn-like .cm-qualifier { color: #690; }\n\n.cm-s-mdn-like .cm-operator { color: #cda869; }\n.cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; }\n.cm-s-mdn-like .cm-string { color:#07a; font-style:italic; }\n.cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/\n.cm-s-mdn-like .cm-meta { color: #000; } /*?*/\n.cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/\n.cm-s-mdn-like .cm-tag { color: #997643; }\n.cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/\n.cm-s-mdn-like .cm-header { color: #FF6400; }\n.cm-s-mdn-like .cm-hr { color: #AEAEAE; }\n.cm-s-mdn-like .cm-link { color:#ad9361; font-style:italic; text-decoration:none; }\n.cm-s-mdn-like .cm-error { border-bottom: 1px solid red; }\n\ndiv.cm-s-mdn-like .CodeMirror-activeline-background { background: #efefff; }\ndiv.cm-s-mdn-like span.CodeMirror-matchingbracket { outline:1px solid grey; color: inherit; }\n\n.cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,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); }\n","/* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */\n\n/**/\n.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; }\n.cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; }\n\n/**/\n.cm-s-midnight .CodeMirror-activeline-background { background: #253540; }\n\n.cm-s-midnight.CodeMirror {\n background: #0F192A;\n color: #D1EDFF;\n}\n\n.cm-s-midnight.CodeMirror { border-top: 1px solid black; border-bottom: 1px solid black; }\n\n.cm-s-midnight div.CodeMirror-selected { background: #314D67; }\n.cm-s-midnight .CodeMirror-line::selection, .cm-s-midnight .CodeMirror-line > span::selection, .cm-s-midnight .CodeMirror-line > span > span::selection { background: rgba(49, 77, 103, .99); }\n.cm-s-midnight .CodeMirror-line::-moz-selection, .cm-s-midnight .CodeMirror-line > span::-moz-selection, .cm-s-midnight .CodeMirror-line > span > span::-moz-selection { background: rgba(49, 77, 103, .99); }\n.cm-s-midnight .CodeMirror-gutters { background: #0F192A; border-right: 1px solid; }\n.cm-s-midnight .CodeMirror-guttermarker { color: white; }\n.cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; }\n.cm-s-midnight .CodeMirror-linenumber { color: #D0D0D0; }\n.cm-s-midnight .CodeMirror-cursor { border-left: 1px solid #F8F8F0; }\n\n.cm-s-midnight span.cm-comment { color: #428BDD; }\n.cm-s-midnight span.cm-atom { color: #AE81FF; }\n.cm-s-midnight span.cm-number { color: #D1EDFF; }\n\n.cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute { color: #A6E22E; }\n.cm-s-midnight span.cm-keyword { color: #E83737; }\n.cm-s-midnight span.cm-string { color: #1DC116; }\n\n.cm-s-midnight span.cm-variable { color: #FFAA3E; }\n.cm-s-midnight span.cm-variable-2 { color: #FFAA3E; }\n.cm-s-midnight span.cm-def { color: #4DD; }\n.cm-s-midnight span.cm-bracket { color: #D1EDFF; }\n.cm-s-midnight span.cm-tag { color: #449; }\n.cm-s-midnight span.cm-link { color: #AE81FF; }\n.cm-s-midnight span.cm-error { background: #F92672; color: #F8F8F0; }\n\n.cm-s-midnight .CodeMirror-matchingbracket {\n text-decoration: underline;\n color: white !important;\n}\n","/* Based on Sublime Text's Monokai theme */\n\n.cm-s-monokai.CodeMirror { background: #272822; color: #f8f8f2; }\n.cm-s-monokai div.CodeMirror-selected { background: #49483E; }\n.cm-s-monokai .CodeMirror-line::selection, .cm-s-monokai .CodeMirror-line > span::selection, .cm-s-monokai .CodeMirror-line > span > span::selection { background: rgba(73, 72, 62, .99); }\n.cm-s-monokai .CodeMirror-line::-moz-selection, .cm-s-monokai .CodeMirror-line > span::-moz-selection, .cm-s-monokai .CodeMirror-line > span > span::-moz-selection { background: rgba(73, 72, 62, .99); }\n.cm-s-monokai .CodeMirror-gutters { background: #272822; border-right: 0px; }\n.cm-s-monokai .CodeMirror-guttermarker { color: white; }\n.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; }\n.cm-s-monokai .CodeMirror-linenumber { color: #d0d0d0; }\n.cm-s-monokai .CodeMirror-cursor { border-left: 1px solid #f8f8f0; }\n\n.cm-s-monokai span.cm-comment { color: #75715e; }\n.cm-s-monokai span.cm-atom { color: #ae81ff; }\n.cm-s-monokai span.cm-number { color: #ae81ff; }\n\n.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute { color: #a6e22e; }\n.cm-s-monokai span.cm-keyword { color: #f92672; }\n.cm-s-monokai span.cm-string { color: #e6db74; }\n\n.cm-s-monokai span.cm-variable { color: #f8f8f2; }\n.cm-s-monokai span.cm-variable-2 { color: #9effff; }\n.cm-s-monokai span.cm-variable-3 { color: #66d9ef; }\n.cm-s-monokai span.cm-def { color: #fd971f; }\n.cm-s-monokai span.cm-bracket { color: #f8f8f2; }\n.cm-s-monokai span.cm-tag { color: #f92672; }\n.cm-s-monokai span.cm-header { color: #ae81ff; }\n.cm-s-monokai span.cm-link { color: #ae81ff; }\n.cm-s-monokai span.cm-error { background: #f92672; color: #f8f8f0; }\n\n.cm-s-monokai .CodeMirror-activeline-background { background: #373831; }\n.cm-s-monokai .CodeMirror-matchingbracket {\n text-decoration: underline;\n color: white !important;\n}\n",".cm-s-neat span.cm-comment { color: #a86; }\n.cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }\n.cm-s-neat span.cm-string { color: #a22; }\n.cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }\n.cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }\n.cm-s-neat span.cm-variable { color: black; }\n.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }\n.cm-s-neat span.cm-meta { color: #555; }\n.cm-s-neat span.cm-link { color: #3a3; }\n\n.cm-s-neat .CodeMirror-activeline-background { background: #e8f2ff; }\n.cm-s-neat .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }\n","/* neo theme for codemirror */\n\n/* Color scheme */\n\n.cm-s-neo.CodeMirror {\n background-color:#ffffff;\n color:#2e383c;\n line-height:1.4375;\n}\n.cm-s-neo .cm-comment { color:#75787b; }\n.cm-s-neo .cm-keyword, .cm-s-neo .cm-property { color:#1d75b3; }\n.cm-s-neo .cm-atom,.cm-s-neo .cm-number { color:#75438a; }\n.cm-s-neo .cm-node,.cm-s-neo .cm-tag { color:#9c3328; }\n.cm-s-neo .cm-string { color:#b35e14; }\n.cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier { color:#047d65; }\n\n\n/* Editor styling */\n\n.cm-s-neo pre {\n padding:0;\n}\n\n.cm-s-neo .CodeMirror-gutters {\n border:none;\n border-right:10px solid transparent;\n background-color:transparent;\n}\n\n.cm-s-neo .CodeMirror-linenumber {\n padding:0;\n color:#e0e2e5;\n}\n\n.cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; }\n.cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; }\n\n.cm-s-neo .CodeMirror-cursor {\n width: auto;\n border: 0;\n background: rgba(155,157,162,0.37);\n z-index: 1;\n}\n","/**\n * Pastel On Dark theme ported from ACE editor\n * @license MIT\n * @copyright AtomicPages LLC 2014\n * @author Dennis Thompson, AtomicPages LLC\n * @version 1.1\n * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme\n */\n\n.cm-s-pastel-on-dark.CodeMirror {\n\tbackground: #2c2827;\n\tcolor: #8F938F;\n\tline-height: 1.5;\n\tfont-size: 14px;\n}\n.cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2); }\n.cm-s-pastel-on-dark .CodeMirror-line::selection, .cm-s-pastel-on-dark .CodeMirror-line > span::selection, .cm-s-pastel-on-dark .CodeMirror-line > span > span::selection { background: rgba(221,240,255,0.2); }\n.cm-s-pastel-on-dark .CodeMirror-line::-moz-selection, .cm-s-pastel-on-dark .CodeMirror-line > span::-moz-selection, .cm-s-pastel-on-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(221,240,255,0.2); }\n\n.cm-s-pastel-on-dark .CodeMirror-gutters {\n\tbackground: #34302f;\n\tborder-right: 0px;\n\tpadding: 0 3px;\n}\n.cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; }\n.cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; }\n.cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; }\n.cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7; }\n.cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; }\n.cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; }\n.cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; }\n.cm-s-pastel-on-dark span.cm-property { color: #8F938F; }\n.cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; }\n.cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; }\n.cm-s-pastel-on-dark span.cm-string { color: #66A968; }\n.cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; }\n.cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; }\n.cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; }\n.cm-s-pastel-on-dark span.cm-def { color: #757aD8; }\n.cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; }\n.cm-s-pastel-on-dark span.cm-tag { color: #C1C144; }\n.cm-s-pastel-on-dark span.cm-link { color: #ae81ff; }\n.cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; }\n.cm-s-pastel-on-dark span.cm-error {\n\tbackground: #757aD8;\n\tcolor: #f8f8f0;\n}\n.cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031); }\n.cm-s-pastel-on-dark .CodeMirror-matchingbracket {\n\tborder: 1px solid rgba(255,255,255,0.25);\n\tcolor: #8F938F !important;\n\tmargin: -1px -1px 0 -1px;\n}\n","/*\n\n Name: Railscasts\n Author: Ryan Bates (http://railscasts.com)\n\n CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)\n Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)\n\n*/\n\n.cm-s-railscasts.CodeMirror {background: #2b2b2b; color: #f4f1ed;}\n.cm-s-railscasts div.CodeMirror-selected {background: #272935 !important;}\n.cm-s-railscasts .CodeMirror-gutters {background: #2b2b2b; border-right: 0px;}\n.cm-s-railscasts .CodeMirror-linenumber {color: #5a647e;}\n.cm-s-railscasts .CodeMirror-cursor {border-left: 1px solid #d4cfc9 !important;}\n\n.cm-s-railscasts span.cm-comment {color: #bc9458;}\n.cm-s-railscasts span.cm-atom {color: #b6b3eb;}\n.cm-s-railscasts span.cm-number {color: #b6b3eb;}\n\n.cm-s-railscasts span.cm-property, .cm-s-railscasts span.cm-attribute {color: #a5c261;}\n.cm-s-railscasts span.cm-keyword {color: #da4939;}\n.cm-s-railscasts span.cm-string {color: #ffc66d;}\n\n.cm-s-railscasts span.cm-variable {color: #a5c261;}\n.cm-s-railscasts span.cm-variable-2 {color: #6d9cbe;}\n.cm-s-railscasts span.cm-def {color: #cc7833;}\n.cm-s-railscasts span.cm-error {background: #da4939; color: #d4cfc9;}\n.cm-s-railscasts span.cm-bracket {color: #f4f1ed;}\n.cm-s-railscasts span.cm-tag {color: #da4939;}\n.cm-s-railscasts span.cm-link {color: #b6b3eb;}\n\n.cm-s-railscasts .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}\n.cm-s-railscasts .CodeMirror-activeline-background { background: #303040; }\n","/*\n\n Name: seti\n Author: Michael Kaminsky (http://github.com/mkaminsky11)\n\n Original seti color scheme by Jesse Weed (https://github.com/jesseweed/seti-syntax)\n\n*/\n\n\n.cm-s-seti.CodeMirror {\n background-color: #151718 !important;\n color: #CFD2D1 !important;\n border: none;\n}\n.cm-s-seti .CodeMirror-gutters {\n color: #404b53;\n background-color: #0E1112;\n border: none;\n}\n.cm-s-seti .CodeMirror-cursor { border-left: solid thin #f8f8f0; }\n.cm-s-seti .CodeMirror-linenumber { color: #6D8A88; }\n.cm-s-seti.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }\n.cm-s-seti .CodeMirror-line::selection, .cm-s-seti .CodeMirror-line > span::selection, .cm-s-seti .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }\n.cm-s-seti .CodeMirror-line::-moz-selection, .cm-s-seti .CodeMirror-line > span::-moz-selection, .cm-s-seti .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }\n.cm-s-seti span.cm-comment { color: #41535b; }\n.cm-s-seti span.cm-string, .cm-s-seti span.cm-string-2 { color: #55b5db; }\n.cm-s-seti span.cm-number { color: #cd3f45; }\n.cm-s-seti span.cm-variable { color: #55b5db; }\n.cm-s-seti span.cm-variable-2 { color: #a074c4; }\n.cm-s-seti span.cm-def { color: #55b5db; }\n.cm-s-seti span.cm-keyword { color: #ff79c6; }\n.cm-s-seti span.cm-operator { color: #9fca56; }\n.cm-s-seti span.cm-keyword { color: #e6cd69; }\n.cm-s-seti span.cm-atom { color: #cd3f45; }\n.cm-s-seti span.cm-meta { color: #55b5db; }\n.cm-s-seti span.cm-tag { color: #55b5db; }\n.cm-s-seti span.cm-attribute { color: #9fca56; }\n.cm-s-seti span.cm-qualifier { color: #9fca56; }\n.cm-s-seti span.cm-property { color: #a074c4; }\n.cm-s-seti span.cm-variable-3 { color: #9fca56; }\n.cm-s-seti span.cm-builtin { color: #9fca56; }\n.cm-s-seti .CodeMirror-activeline-background { background: #101213; }\n.cm-s-seti .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n","/*\nSolarized theme for code-mirror\nhttp://ethanschoonover.com/solarized\n*/\n\n/*\nSolarized color pallet\nhttp://ethanschoonover.com/solarized/img/solarized-palette.png\n*/\n\n.solarized.base03 { color: #002b36; }\n.solarized.base02 { color: #073642; }\n.solarized.base01 { color: #586e75; }\n.solarized.base00 { color: #657b83; }\n.solarized.base0 { color: #839496; }\n.solarized.base1 { color: #93a1a1; }\n.solarized.base2 { color: #eee8d5; }\n.solarized.base3 { color: #fdf6e3; }\n.solarized.solar-yellow { color: #b58900; }\n.solarized.solar-orange { color: #cb4b16; }\n.solarized.solar-red { color: #dc322f; }\n.solarized.solar-magenta { color: #d33682; }\n.solarized.solar-violet { color: #6c71c4; }\n.solarized.solar-blue { color: #268bd2; }\n.solarized.solar-cyan { color: #2aa198; }\n.solarized.solar-green { color: #859900; }\n\n/* Color scheme for code-mirror */\n\n.cm-s-solarized {\n line-height: 1.45em;\n color-profile: sRGB;\n rendering-intent: auto;\n}\n.cm-s-solarized.cm-s-dark {\n color: #839496;\n background-color: #002b36;\n text-shadow: #002b36 0 1px;\n}\n.cm-s-solarized.cm-s-light {\n background-color: #fdf6e3;\n color: #657b83;\n text-shadow: #eee8d5 0 1px;\n}\n\n.cm-s-solarized .CodeMirror-widget {\n text-shadow: none;\n}\n\n.cm-s-solarized .cm-header { color: #586e75; }\n.cm-s-solarized .cm-quote { color: #93a1a1; }\n\n.cm-s-solarized .cm-keyword { color: #cb4b16; }\n.cm-s-solarized .cm-atom { color: #d33682; }\n.cm-s-solarized .cm-number { color: #d33682; }\n.cm-s-solarized .cm-def { color: #2aa198; }\n\n.cm-s-solarized .cm-variable { color: #839496; }\n.cm-s-solarized .cm-variable-2 { color: #b58900; }\n.cm-s-solarized .cm-variable-3 { color: #6c71c4; }\n\n.cm-s-solarized .cm-property { color: #2aa198; }\n.cm-s-solarized .cm-operator { color: #6c71c4; }\n\n.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; }\n\n.cm-s-solarized .cm-string { color: #859900; }\n.cm-s-solarized .cm-string-2 { color: #b58900; }\n\n.cm-s-solarized .cm-meta { color: #859900; }\n.cm-s-solarized .cm-qualifier { color: #b58900; }\n.cm-s-solarized .cm-builtin { color: #d33682; }\n.cm-s-solarized .cm-bracket { color: #cb4b16; }\n.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; }\n.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; }\n.cm-s-solarized .cm-tag { color: #93a1a1; }\n.cm-s-solarized .cm-attribute { color: #2aa198; }\n.cm-s-solarized .cm-hr {\n color: transparent;\n border-top: 1px solid #586e75;\n display: block;\n}\n.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; }\n.cm-s-solarized .cm-special { color: #6c71c4; }\n.cm-s-solarized .cm-em {\n color: #999;\n text-decoration: underline;\n text-decoration-style: dotted;\n}\n.cm-s-solarized .cm-strong { color: #eee; }\n.cm-s-solarized .cm-error,\n.cm-s-solarized .cm-invalidchar {\n color: #586e75;\n border-bottom: 1px dotted #dc322f;\n}\n\n.cm-s-solarized.cm-s-dark div.CodeMirror-selected { background: #073642; }\n.cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); }\n.cm-s-solarized.cm-s-dark .CodeMirror-line::-moz-selection, .cm-s-dark .CodeMirror-line > span::-moz-selection, .cm-s-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(7, 54, 66, 0.99); }\n\n.cm-s-solarized.cm-s-light div.CodeMirror-selected { background: #eee8d5; }\n.cm-s-solarized.cm-s-light .CodeMirror-line::selection, .cm-s-light .CodeMirror-line > span::selection, .cm-s-light .CodeMirror-line > span > span::selection { background: #eee8d5; }\n.cm-s-solarized.cm-s-light .CodeMirror-line::-moz-selection, .cm-s-ligh .CodeMirror-line > span::-moz-selection, .cm-s-ligh .CodeMirror-line > span > span::-moz-selection { background: #eee8d5; }\n\n/* Editor styling */\n\n\n\n/* Little shadow on the view-port of the buffer view */\n.cm-s-solarized.CodeMirror {\n -moz-box-shadow: inset 7px 0 12px -6px #000;\n -webkit-box-shadow: inset 7px 0 12px -6px #000;\n box-shadow: inset 7px 0 12px -6px #000;\n}\n\n/* Gutter border and some shadow from it */\n.cm-s-solarized .CodeMirror-gutters {\n border-right: 1px solid;\n}\n\n/* Gutter colors and line number styling based of color scheme (dark / light) */\n\n/* Dark */\n.cm-s-solarized.cm-s-dark .CodeMirror-gutters {\n background-color: #002b36;\n border-color: #00232c;\n}\n\n.cm-s-solarized.cm-s-dark .CodeMirror-linenumber {\n text-shadow: #021014 0 -1px;\n}\n\n/* Light */\n.cm-s-solarized.cm-s-light .CodeMirror-gutters {\n background-color: #fdf6e3;\n border-color: #eee8d5;\n}\n\n/* Common */\n.cm-s-solarized .CodeMirror-linenumber {\n color: #586e75;\n padding: 0 5px;\n}\n.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }\n.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; }\n.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; }\n\n.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text {\n color: #586e75;\n}\n\n.cm-s-solarized .CodeMirror-cursor { border-left: 1px solid #819090; }\n\n/*\nActive line. Negative margin compensates left padding of the text in the\nview-port\n*/\n.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {\n background: rgba(255, 255, 255, 0.10);\n}\n.cm-s-solarized.cm-s-light .CodeMirror-activeline-background {\n background: rgba(0, 0, 0, 0.10);\n}\n","/*\n\n Name: Tomorrow Night - Bright\n Author: Chris Kempson\n\n Port done by Gerard Braad \n\n*/\n\n.cm-s-tomorrow-night-bright.CodeMirror { background: #000000; color: #eaeaea; }\n.cm-s-tomorrow-night-bright div.CodeMirror-selected { background: #424242; }\n.cm-s-tomorrow-night-bright .CodeMirror-gutters { background: #000000; border-right: 0px; }\n.cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; }\n.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; }\n.cm-s-tomorrow-night-bright .CodeMirror-linenumber { color: #424242; }\n.cm-s-tomorrow-night-bright .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }\n\n.cm-s-tomorrow-night-bright span.cm-comment { color: #d27b53; }\n.cm-s-tomorrow-night-bright span.cm-atom { color: #a16a94; }\n.cm-s-tomorrow-night-bright span.cm-number { color: #a16a94; }\n\n.cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute { color: #99cc99; }\n.cm-s-tomorrow-night-bright span.cm-keyword { color: #d54e53; }\n.cm-s-tomorrow-night-bright span.cm-string { color: #e7c547; }\n\n.cm-s-tomorrow-night-bright span.cm-variable { color: #b9ca4a; }\n.cm-s-tomorrow-night-bright span.cm-variable-2 { color: #7aa6da; }\n.cm-s-tomorrow-night-bright span.cm-def { color: #e78c45; }\n.cm-s-tomorrow-night-bright span.cm-bracket { color: #eaeaea; }\n.cm-s-tomorrow-night-bright span.cm-tag { color: #d54e53; }\n.cm-s-tomorrow-night-bright span.cm-link { color: #a16a94; }\n.cm-s-tomorrow-night-bright span.cm-error { background: #d54e53; color: #6A6A6A; }\n\n.cm-s-tomorrow-night-bright .CodeMirror-activeline-background { background: #2a2a2a; }\n.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n","/*\n\n Name: Tomorrow Night - Eighties\n Author: Chris Kempson\n\n CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)\n Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)\n\n*/\n\n.cm-s-tomorrow-night-eighties.CodeMirror { background: #000000; color: #CCCCCC; }\n.cm-s-tomorrow-night-eighties div.CodeMirror-selected { background: #2D2D2D; }\n.cm-s-tomorrow-night-eighties .CodeMirror-line::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::selection { background: rgba(45, 45, 45, 0.99); }\n.cm-s-tomorrow-night-eighties .CodeMirror-line::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::-moz-selection { background: rgba(45, 45, 45, 0.99); }\n.cm-s-tomorrow-night-eighties .CodeMirror-gutters { background: #000000; border-right: 0px; }\n.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; }\n.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; }\n.cm-s-tomorrow-night-eighties .CodeMirror-linenumber { color: #515151; }\n.cm-s-tomorrow-night-eighties .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }\n\n.cm-s-tomorrow-night-eighties span.cm-comment { color: #d27b53; }\n.cm-s-tomorrow-night-eighties span.cm-atom { color: #a16a94; }\n.cm-s-tomorrow-night-eighties span.cm-number { color: #a16a94; }\n\n.cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute { color: #99cc99; }\n.cm-s-tomorrow-night-eighties span.cm-keyword { color: #f2777a; }\n.cm-s-tomorrow-night-eighties span.cm-string { color: #ffcc66; }\n\n.cm-s-tomorrow-night-eighties span.cm-variable { color: #99cc99; }\n.cm-s-tomorrow-night-eighties span.cm-variable-2 { color: #6699cc; }\n.cm-s-tomorrow-night-eighties span.cm-def { color: #f99157; }\n.cm-s-tomorrow-night-eighties span.cm-bracket { color: #CCCCCC; }\n.cm-s-tomorrow-night-eighties span.cm-tag { color: #f2777a; }\n.cm-s-tomorrow-night-eighties span.cm-link { color: #a16a94; }\n.cm-s-tomorrow-night-eighties span.cm-error { background: #f2777a; color: #6A6A6A; }\n\n.cm-s-tomorrow-night-eighties .CodeMirror-activeline-background { background: #343600; }\n.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }\n",".cm-s-ttcn .cm-quote { color: #090; }\n.cm-s-ttcn .cm-negative { color: #d44; }\n.cm-s-ttcn .cm-positive { color: #292; }\n.cm-s-ttcn .cm-header, .cm-strong { font-weight: bold; }\n.cm-s-ttcn .cm-em { font-style: italic; }\n.cm-s-ttcn .cm-link { text-decoration: underline; }\n.cm-s-ttcn .cm-strikethrough { text-decoration: line-through; }\n.cm-s-ttcn .cm-header { color: #00f; font-weight: bold; }\n\n.cm-s-ttcn .cm-atom { color: #219; }\n.cm-s-ttcn .cm-attribute { color: #00c; }\n.cm-s-ttcn .cm-bracket { color: #997; }\n.cm-s-ttcn .cm-comment { color: #333333; }\n.cm-s-ttcn .cm-def { color: #00f; }\n.cm-s-ttcn .cm-em { font-style: italic; }\n.cm-s-ttcn .cm-error { color: #f00; }\n.cm-s-ttcn .cm-hr { color: #999; }\n.cm-s-ttcn .cm-invalidchar { color: #f00; }\n.cm-s-ttcn .cm-keyword { font-weight:bold; }\n.cm-s-ttcn .cm-link { color: #00c; text-decoration: underline; }\n.cm-s-ttcn .cm-meta { color: #555; }\n.cm-s-ttcn .cm-negative { color: #d44; }\n.cm-s-ttcn .cm-positive { color: #292; }\n.cm-s-ttcn .cm-qualifier { color: #555; }\n.cm-s-ttcn .cm-strikethrough { text-decoration: line-through; }\n.cm-s-ttcn .cm-string { color: #006400; }\n.cm-s-ttcn .cm-string-2 { color: #f50; }\n.cm-s-ttcn .cm-strong { font-weight: bold; }\n.cm-s-ttcn .cm-tag { color: #170; }\n.cm-s-ttcn .cm-variable { color: #8B2252; }\n.cm-s-ttcn .cm-variable-2 { color: #05a; }\n.cm-s-ttcn .cm-variable-3 { color: #085; }\n\n.cm-s-ttcn .cm-invalidchar { color: #f00; }\n\n/* ASN */\n.cm-s-ttcn .cm-accessTypes,\n.cm-s-ttcn .cm-compareTypes { color: #27408B; }\n.cm-s-ttcn .cm-cmipVerbs { color: #8B2252; }\n.cm-s-ttcn .cm-modifier { color:#D2691E; }\n.cm-s-ttcn .cm-status { color:#8B4545; }\n.cm-s-ttcn .cm-storage { color:#A020F0; }\n.cm-s-ttcn .cm-tags { color:#006400; }\n\n/* CFG */\n.cm-s-ttcn .cm-externalCommands { color: #8B4545; font-weight:bold; }\n.cm-s-ttcn .cm-fileNCtrlMaskOptions,\n.cm-s-ttcn .cm-sectionTitle { color: #2E8B57; font-weight:bold; }\n\n/* TTCN */\n.cm-s-ttcn .cm-booleanConsts,\n.cm-s-ttcn .cm-otherConsts,\n.cm-s-ttcn .cm-verdictConsts { color: #006400; }\n.cm-s-ttcn .cm-configOps,\n.cm-s-ttcn .cm-functionOps,\n.cm-s-ttcn .cm-portOps,\n.cm-s-ttcn .cm-sutOps,\n.cm-s-ttcn .cm-timerOps,\n.cm-s-ttcn .cm-verdictOps { color: #0000FF; }\n.cm-s-ttcn .cm-preprocessor,\n.cm-s-ttcn .cm-templateMatch,\n.cm-s-ttcn .cm-ttcn3Macros { color: #27408B; }\n.cm-s-ttcn .cm-types { color: #A52A2A; font-weight:bold; }\n.cm-s-ttcn .cm-visibilityModifiers { font-weight:bold; }\n","/*\n\n Name: yeti\n Author: Michael Kaminsky (http://github.com/mkaminsky11)\n\n Original yeti color scheme by Jesse Weed (https://github.com/jesseweed/yeti-syntax)\n\n*/\n\n\n.cm-s-yeti.CodeMirror {\n background-color: #ECEAE8 !important;\n color: #d1c9c0 !important;\n border: none;\n}\n\n.cm-s-yeti .CodeMirror-gutters {\n color: #adaba6;\n background-color: #E5E1DB;\n border: none;\n}\n.cm-s-yeti .CodeMirror-cursor { border-left: solid thin #d1c9c0; }\n.cm-s-yeti .CodeMirror-linenumber { color: #adaba6; }\n.cm-s-yeti.CodeMirror-focused div.CodeMirror-selected { background: #DCD8D2; }\n.cm-s-yeti .CodeMirror-line::selection, .cm-s-yeti .CodeMirror-line > span::selection, .cm-s-yeti .CodeMirror-line > span > span::selection { background: #DCD8D2; }\n.cm-s-yeti .CodeMirror-line::-moz-selection, .cm-s-yeti .CodeMirror-line > span::-moz-selection, .cm-s-yeti .CodeMirror-line > span > span::-moz-selection { background: #DCD8D2; }\n.cm-s-yeti span.cm-comment { color: #d4c8be; }\n.cm-s-yeti span.cm-string, .cm-s-yeti span.cm-string-2 { color: #96c0d8; }\n.cm-s-yeti span.cm-number { color: #a074c4; }\n.cm-s-yeti span.cm-variable { color: #55b5db; }\n.cm-s-yeti span.cm-variable-2 { color: #a074c4; }\n.cm-s-yeti span.cm-def { color: #55b5db; }\n.cm-s-yeti span.cm-operator { color: #9fb96e; }\n.cm-s-yeti span.cm-keyword { color: #9fb96e; }\n.cm-s-yeti span.cm-atom { color: #a074c4; }\n.cm-s-yeti span.cm-meta { color: #96c0d8; }\n.cm-s-yeti span.cm-tag { color: #96c0d8; }\n.cm-s-yeti span.cm-attribute { color: #9fb96e; }\n.cm-s-yeti span.cm-qualifier { color: #96c0d8; }\n.cm-s-yeti span.cm-property { color: #a074c4; }\n.cm-s-yeti span.cm-builtin { color: #a074c4; }\n.cm-s-yeti span.cm-variable-3 { color: #96c0d8; }\n.cm-s-yeti .CodeMirror-activeline-background { background: #E7E4E0; }\n.cm-s-yeti .CodeMirror-matchingbracket { text-decoration: underline; }\n","/* MENU */\n\n.ge_menu_bar {\n position: fixed;\n width: 100%;\n margin: 0px;\n z-index: var(--z-menu);\n color: var(--ui-component-text-color);\n background-color: var(--ui-base-color);\n font-family: Helvetica, Geneva, sans-serif;\n font-weight: 400;\n}\n\n.ge_menu {\n display: inline-block;\n margin: 16px 32px 16px 16px;\n letter-spacing: 0.2em;\n font-size: 14px;\n}\n\n.ge_menu .material-icons {\n font-size: 18px;\n vertical-align: bottom;\n display: inline-block;\n margin-right: 4px;\n}\n\n.ge_menu--hidden {\n display: none;\n}\n\n.ge_menu_button {\n cursor: pointer;\n background: none;\n display: block;\n border: none;\n border-radius: 4px;\n padding: 0;\n font: inherit;\n color: inherit;\n outline: none;\n text-align: left;\n letter-spacing: 0.05em !important;\n}\n\n.ge_menu_highlight {\n width: 24px;\n color: #FFFFFF;\n}\n\n.ge_menu_disabled {\n width: 24px;\n color: #777777;\n}\n\n.ge_menu_button:hover {\n color: var(--ui-highlight-color);\n}\n\n.ge_sub_menu .ge_menu_button {\n width: 100%;\n}\n\n.ge_sub_menu_button {\n height: 35px;\n cursor: pointer;\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n color: inherit;\n text-align: left;\n\n -moz-user-select: -moz-none;\n -khtml-user-select: none;\n -webkit-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n\n.ge_sub_menu_button::selection { background: transparent;color:inherit; }\n.ge_sub_menu_button::-moz-selection { background: transparent;color:inherit; }\n.ge_sub_menu_button:hover { color: var(--ui-highlight-color); }\n\n.ge_sub_menu {\n padding: 4px 12px 4px 12px;\n font-family: Helvetica, Geneva, sans-serif;\n font-weight: 300;\n font-size: 14px;\n}\n\n.ge_menu_icon {\n display: inline-block;\n width: 48px;\n}\n",".ge_panel {\n cursor: pointer;\n color: var(--ui-component-text-color);\n background-color: var(--ui-base-color);\n font-family: Helvetica, Geneva, sans-serif;\n font-weight: 100;\n margin: 0px;\n padding-top: 5px;\n z-index: var(--z-menu);\n border-bottom: solid 1px #444444;\n}\n\nli.ge_panel_tab {\n cursor: pointer;\n list-style-type: none;\n background-color: var(--ui-base-color);\n color: #777777;\n display: inline-block;\n text-align: center;\n padding: 8px 16px 8px 16px;\n margin-bottom: 8px;\n letter-spacing: 0.05em;\n font-face: monospace;\n font-size: 14px;\n}\n\nli.ge_panel_tab_active {\n cursor: pointer;\n //background-color: var(--ui-active-color);\n border-radius: 4px;\n list-style-type: none;\n display: inline-block;\n text-align: center;\n padding: 8px 16px 8px 16px;\n margin-bottom: 8px;\n letter-spacing: 0.05em;\n font-size: 14px;\n}\n\nli.ge_panel_tab:hover {\n color: var(--ui-highlight-color);\n}\n\na.ge_panel_tab_close {\n cursor: pointer;\n font-size: 12px;\n margin-left: 10px;\n font-weight: 100;\n}\n","/* EDITOR */\n\n.CodeMirror {\n font-family: var(--editor-font-family);\n font-size: 14px;\n line-height: 1.4;\n height: auto;\n z-index: var(--z-editor);\n}\n\n.CodeMirror-linenumbers {\n padding: 0 8px;\n font-family: Helvetica, Geneva, sans-serif;\n}\n\n.CodeMirror-linenumber.CodeMirror-gutter-elt {\n color: #546E7A;\n}\n\n/* Slightly more padding around the text content */\n.CodeMirror pre {\n padding: 0 8px;\n}\n\n.CodeMirror-vscrollbar {\n\tvisibility: hidden;\n}\n\n.ge_editor {\n background-color: #272823;\n}\n\n.ge_editor-unfocus {\n opacity: .5;\n filter: blur(1px);\n background-color: #272823;\n}\n\n.CodeMirror {\n margin-top: 12px;\n}\n","/* CANVAS */\n\n.ge_canvas_container {\n position: fixed;\n right: 0px;\n margin: 0px;\n padding: 0px;\n transition: top 0.25s ease;\n z-index: var(--z-shader);\n}\n\n.ge_canvas {\n margin: 0px;\n padding: 0px;\n z-index: var(--z-shader);\n}\n\n.ge_control {\n margin: 0px;\n padding: 0px;\n position: absolute;\n width: 100%;\n bottom: 16px;\n\n opacity: 1;\n -webkit-transition: opacity .3s;\n -moz-transition: opacity .3s;\n transition: opacity .3s;\n z-index: var(--z-shader);\n}\n\n.ge_control_panel {\n padding: 8px;\n border-radius: 4px;\n text-align: center;\n position: absolute;\n right: 0;\n left: 0;\n bottom: 0;\n margin: auto;\n width: 120px;\n background-color: rgba(0,0,0,.5);\n font-size: 18px !important;\n opacity: 1;\n -webkit-transition: opacity .3s;\n -moz-transition: opacity .3s;\n transition: opacity .3s;\n z-index: var(--z-shader);\n}\n\n\n\n.ge_contol li {\n margin: 0;\n padding: 0;\n list-style-type: none;\n}\n\n.ge_control_hidden {\n /*display: none;*/\n opacity: 0;\n}\n\n.ge_control_element {\n\tbackground-color: rgba(0,0,0,0);\n\tcolor: var(--ui-component-text-color);\n font-family: Helvetica, Geneva, sans-serif;\n font-weight: 300;\n\tdisplay: inline;\n\t-moz-user-select: -moz-none;\n\t-khtml-user-select: none;\n\t-webkit-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n\n.ge_control_element_button {\n display: inline-block;\n\tmargin: 0px 8px 0px 8px;\n width: 24px;\n height: 24px;\n cursor: pointer;\n background: none;\n border: none;\n padding: 0;\n font: inherit;\n color: inherit;\n text-align: center;\n vertical-align: middle;\n font-size: 14px;\n overflow: hidden;\n outline: none;\n //border: solid 1px rgba(255, 255, 255, 0.8);\n //border-radius: 4px;\n -moz-user-select: -moz-none;\n \t-khtml-user-select: none;\n \t-webkit-user-select: none;\n \t-ms-user-select: none;\n \tuser-select: none;\n}\n\n.ge_control_element_button::selection { background: transparent;color:inherit; }\n.ge_control_element_button::-moz-selection { background: transparent;color:inherit; }\n\n.ge_control_element_button:hover {\n color: var(--ui-highlight-color);\n}\n\n.ghostdom {\n\tbackground: #999;\n\topacity: 0.2;\n\n\tposition: absolute;\n\tright: 0px;\n\tmargin: 0;\n\tpadding: 0;\n\n\t-webkit-transition: all 0.25s ease-in-out;\n\t-moz-transition: all 0.25s ease-in-out;\n\t-ms-transition: all 0.25s ease-in-out;\n\t-o-transition: all 0.25s ease-in-out;\n\ttransition: all 0.25s ease-in-out;\n\n\tz-index: var(--z-shader-ghost);\n}\n",".ge_picker_modal {\n box-sizing: border-box;\n position: absolute;\n padding: 0px;\n /*background-color: var(--ui-component-color);*/\n overflow: hidden;\n box-shadow: var(--modal-shadow);\n user-select: none;\n z-index: var(--z-helpers); /* z-index will be modified by Greensock Draggable when dragging */\n}\n\n.ge_picker_modal * {\n box-sizing: border-box;\n}\n\n.ge_picker_canvas {\n width: 100%;\n height: 100%;\n cursor: crosshair;\n}\n\n.ge_colorpicker_patch {\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 50px;\n}\n\n.ge_colorpicker_hsv-map {\n position: relative;\n height: 200px;\n width: 100%;\n top: 50px;\n}\n\n.ge_colorpicker_disc-cover {\n opacity: 0;\n background-color: #000;\n position: absolute;\n top: 0;\n left: 0;\n width: 200px;\n height: 200px;\n border-radius: 50%;\n cursor: crosshair;\n}\n\n.ge_colorpicker_disc-cover::after {\n content: '';\n background-color: transparent;\n position: absolute;\n top: -1px;\n left: -1px;\n width: 202px;\n height: 202px;\n border: 3px solid var(--ui-component-color);\n border-radius: 50%;\n opacity: 1;\n pointer-events: none;\n box-sizing: border-box;\n}\n\n.ge_colorpicker_bar-bg,\n.ge_colorpicker_bar-white {\n position: absolute;\n right: 0;\n top: 0;\n width: 25px;\n height: 200px;\n}\n\n.ge_colorpicker_bar-white {\n background-color: #fff;\n}\n\n.ge_colorpicker_disc-cursor {\n position: absolute;\n border: 1px solid #eee;\n border-radius: 50%;\n width: 9px;\n height: 9px;\n margin: -5px;\n cursor: crosshair;\n}\n\n.ge_colorpicker_dark .ge_colorpicker_disc-cursor {\n border-color: #333;\n}\n\n/*.ge_colorpicker_no-cursor,\n.ge_colorpicker_no-cursor .ge_colorpicker_patch,\n.ge_colorpicker_no-cursor .ge_colorpicker_disc-cursor,\n.ge_colorpicker_no-cursor .ge_colorpicker_disc-cover {\n cursor: none;\n}*/\n\n.ge_colorpicker_bar-luminance {\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.ge_colorpicker_bar-cursors {\n position: absolute;\n right: 0;\n width: 25px;\n top: 0;\n height: 200px;\n overflow: hidden;\n}\n.ge_colorpicker_bar-cursor-left,\n.ge_colorpicker_bar-cursor-right {\n position: absolute;\n width: 0;\n height: 0;\n border: 4px solid transparent;\n margin-top: -4px;\n}\n.ge_colorpicker_bar-cursor-left {\n left: 0;\n border-left: 4px solid #eee;\n}\n.ge_colorpicker_bar-cursor-right {\n right: 0;\n border-right: 4px solid #eee;\n}\n\n.ge_colorpicker_dark .ge_colorpicker_bar-cursor-left {\n border-left-color: #333;\n}\n.ge_colorpicker_dark .ge_colorpicker_bar-cursor-right {\n border-right-color: #333;\n}\n\n.ge_colorpicker_link-button {\n position: absolute;\n bottom: 5px;\n left: 5px;\n color: #85CCC4; /*white;*/\n font-family: Helvetica, Arial, sans-serif;;\n font-size: 20px;\n font-weight: 100;\n cursor: pointer;\n}\n\n",".ge_modal {\n box-sizing: border-box;\n position: absolute;\n z-index: var(--z-helpers); /* z-index will be modified by Greensock Draggable when dragging */\n user-select: none;\n box-shadow: var(--modal-shadow);\n font-family: Helvetica, Geneva, sans-serif;\n font-weight: 100;\n}\n\n.ge_export_modal {\n overflow: hidden;\n color: var(--ui-component-text-color);\n background-color: var(--ui-base-color);\n /*box-shadow: var(--modal-shadow);*/\n box-shadow: 0 5px 5px 5px rgba(0,0,0,.2),0 5px 0px 0px rgba(0,0,0,.25);\n user-select: none;\n cursor: pointer;\n margin: 0px;\n padding-right: 10px;\n padding-left: 10px;\n padding-top: 5px;\n padding-bottom: 5px;\n list-style-type: none;\n}\n\n.ge_tooltip_modal {\n padding: 10px;\n padding-top: 0px;\n padding-bottom: 0px;\n background-color: var(--ui-component-color);\n font-size: 14px;\n}\n\n.ge_tooltip_modal a {\n text-decoration: none;\n color: var(--ui-highlight-color);\n}\n\n.ge_tooltip_modal p {\n color: var(--ui-subtext-color);\n margin: 6px;\n}","\n.ge-error,\n.ge-warning {\n position: relative;\n font-family: var(--editor-font-family);\n padding-left: 3em; /* Theoretically, aligns error text to the first tab stop */\n padding-right: 10px;\n}\n\n.ge-error-icon,\n.ge-warning-icon {\n position: absolute;\n left: 0;\n /*top: 3px;*/\n width: 3em; /* Centers the icon within the first tab stop */\n text-align: center;\n}\n\n.ge-error {\n background: #be1a20;\n color: white;\n}\n\n.ge-warning {\n background: #ffcc00;\n color: black;\n}",".ge_assing_marker {\n margin-left: -15px;\n\tcolor: var(--ui-highlight-color);\n font-size: 10px;\n /*transform: translate(0,50%);*/\n}\n\n.ge_assing_marker_faster {\n color: green;\n background-color: green;\n}\n\n.ge_assing_marker_pct {\n position: absolute;\n top: 0px;\n left: -17px;\n height: 100%;\n z-index: -1;\n background-color: #555;\n}\n\n.ge_assing_marker_slower {\n background-color: red;\n}\n\n.ge_assing_marker:hover {\n color: white;\n}\n\n.ge_assing_marker_on {\n margin-left: -15px;\n color: white;\n}\n\n",".ge_export_icon {\n position: relative;\n float: right;\n right: 8px;\n bottom: 40px;\n width: 32px;\n height: 28px;\n border-radius:16px;\n padding-top:4px;\n /*box-shadow: var(--modal-shadow);*/\n user-select: none;\n z-index: var(--z-menu);\n text-align:center;\n vertical-align: bottom;\n background-color: rgba(0,0,0,.5);\n font-size: 18px !important;\n color: var(--ui-component-text-color);\n cursor: pointer;\n}\n\n.ge_export_icon:hover {\n color: var(--ui-highlight-color);\n}\n"]} \ No newline at end of file diff --git a/build/glslEditor.js b/build/glslEditor.js deleted file mode 100644 index f800564..0000000 --- a/build/glslEditor.js +++ /dev/null @@ -1,22948 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.GlslEditor = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; i--) { - var from = ranges[i].from(), to = ranges[i].to(); - if (from.line >= minLine) continue; - if (to.line >= minLine) to = Pos(minLine, 0); - minLine = from.line; - if (mode == null) { - if (cm.uncomment(from, to, options)) mode = "un"; - else { cm.lineComment(from, to, options); mode = "line"; } - } else if (mode == "un") { - cm.uncomment(from, to, options); - } else { - cm.lineComment(from, to, options); - } - } - }); - - CodeMirror.defineExtension("lineComment", function(from, to, options) { - if (!options) options = noOptions; - var self = this, mode = self.getModeAt(from); - var commentString = options.lineComment || mode.lineComment; - if (!commentString) { - if (options.blockCommentStart || mode.blockCommentStart) { - options.fullLines = true; - self.blockComment(from, to, options); - } - return; - } - var firstLine = self.getLine(from.line); - if (firstLine == null) return; - var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1); - var pad = options.padding == null ? " " : options.padding; - var blankLines = options.commentBlankLines || from.line == to.line; - - self.operation(function() { - if (options.indent) { - var baseString = null; - for (var i = from.line; i < end; ++i) { - var line = self.getLine(i); - var whitespace = line.slice(0, firstNonWS(line)); - if (baseString == null || baseString.length > whitespace.length) { - baseString = whitespace; - } - } - for (var i = from.line; i < end; ++i) { - var line = self.getLine(i), cut = baseString.length; - if (!blankLines && !nonWS.test(line)) continue; - if (line.slice(0, cut) != baseString) cut = firstNonWS(line); - self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut)); - } - } else { - for (var i = from.line; i < end; ++i) { - if (blankLines || nonWS.test(self.getLine(i))) - self.replaceRange(commentString + pad, Pos(i, 0)); - } - } - }); - }); - - CodeMirror.defineExtension("blockComment", function(from, to, options) { - if (!options) options = noOptions; - var self = this, mode = self.getModeAt(from); - var startString = options.blockCommentStart || mode.blockCommentStart; - var endString = options.blockCommentEnd || mode.blockCommentEnd; - if (!startString || !endString) { - if ((options.lineComment || mode.lineComment) && options.fullLines != false) - self.lineComment(from, to, options); - return; - } - - var end = Math.min(to.line, self.lastLine()); - if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end; - - var pad = options.padding == null ? " " : options.padding; - if (from.line > end) return; - - self.operation(function() { - if (options.fullLines != false) { - var lastLineHasText = nonWS.test(self.getLine(end)); - self.replaceRange(pad + endString, Pos(end)); - self.replaceRange(startString + pad, Pos(from.line, 0)); - var lead = options.blockCommentLead || mode.blockCommentLead; - if (lead != null) for (var i = from.line + 1; i <= end; ++i) - if (i != end || lastLineHasText) - self.replaceRange(lead + pad, Pos(i, 0)); - } else { - self.replaceRange(endString, to); - self.replaceRange(startString, from); - } - }); - }); - - CodeMirror.defineExtension("uncomment", function(from, to, options) { - if (!options) options = noOptions; - var self = this, mode = self.getModeAt(from); - var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end); - - // Try finding line comments - var lineString = options.lineComment || mode.lineComment, lines = []; - var pad = options.padding == null ? " " : options.padding, didSomething; - lineComment: { - if (!lineString) break lineComment; - for (var i = start; i <= end; ++i) { - var line = self.getLine(i); - var found = line.indexOf(lineString); - if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1; - if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment; - if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment; - lines.push(line); - } - self.operation(function() { - for (var i = start; i <= end; ++i) { - var line = lines[i - start]; - var pos = line.indexOf(lineString), endPos = pos + lineString.length; - if (pos < 0) continue; - if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length; - didSomething = true; - self.replaceRange("", Pos(i, pos), Pos(i, endPos)); - } - }); - if (didSomething) return true; - } - - // Try block comments - var startString = options.blockCommentStart || mode.blockCommentStart; - var endString = options.blockCommentEnd || mode.blockCommentEnd; - if (!startString || !endString) return false; - var lead = options.blockCommentLead || mode.blockCommentLead; - var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end); - var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString); - if (close == -1 && start != end) { - endLine = self.getLine(--end); - close = endLine.lastIndexOf(endString); - } - if (open == -1 || close == -1 || - !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) || - !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1)))) - return false; - - // Avoid killing block comments completely outside the selection. - // Positions of the last startString before the start of the selection, and the first endString after it. - var lastStart = startLine.lastIndexOf(startString, from.ch); - var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length); - if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false; - // Positions of the first endString after the end of the selection, and the last startString before it. - firstEnd = endLine.indexOf(endString, to.ch); - var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch); - lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart; - if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false; - - self.operation(function() { - self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)), - Pos(end, close + endString.length)); - var openEnd = open + startString.length; - if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length; - self.replaceRange("", Pos(start, open), Pos(start, openEnd)); - if (lead) for (var i = start + 1; i <= end; ++i) { - var line = self.getLine(i), found = line.indexOf(lead); - if (found == -1 || nonWS.test(line.slice(0, found))) continue; - var foundEnd = found + lead.length; - if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length; - self.replaceRange("", Pos(i, found), Pos(i, foundEnd)); - } - }); - return true; - }); -}); - -},{"../../lib/codemirror":30}],16:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Open simple dialogs on top of an editor. Relies on dialog.css. - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - function dialogDiv(cm, template, bottom) { - var wrap = cm.getWrapperElement(); - var dialog; - dialog = wrap.appendChild(document.createElement("div")); - if (bottom) - dialog.className = "CodeMirror-dialog CodeMirror-dialog-bottom"; - else - dialog.className = "CodeMirror-dialog CodeMirror-dialog-top"; - - if (typeof template == "string") { - dialog.innerHTML = template; - } else { // Assuming it's a detached DOM element. - dialog.appendChild(template); - } - return dialog; - } - - function closeNotification(cm, newVal) { - if (cm.state.currentNotificationClose) - cm.state.currentNotificationClose(); - cm.state.currentNotificationClose = newVal; - } - - CodeMirror.defineExtension("openDialog", function(template, callback, options) { - if (!options) options = {}; - - closeNotification(this, null); - - var dialog = dialogDiv(this, template, options.bottom); - var closed = false, me = this; - function close(newVal) { - if (typeof newVal == 'string') { - inp.value = newVal; - } else { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - - if (options.onClose) options.onClose(dialog); - } - } - - var inp = dialog.getElementsByTagName("input")[0], button; - if (inp) { - if (options.value) { - inp.value = options.value; - if (options.selectValueOnOpen !== false) { - inp.select(); - } - } - - if (options.onInput) - CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); - if (options.onKeyUp) - CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); - - CodeMirror.on(inp, "keydown", function(e) { - if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } - if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { - inp.blur(); - CodeMirror.e_stop(e); - close(); - } - if (e.keyCode == 13) callback(inp.value, e); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); - - inp.focus(); - } else if (button = dialog.getElementsByTagName("button")[0]) { - CodeMirror.on(button, "click", function() { - close(); - me.focus(); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); - - button.focus(); - } - return close; - }); - - CodeMirror.defineExtension("openConfirm", function(template, callbacks, options) { - closeNotification(this, null); - var dialog = dialogDiv(this, template, options && options.bottom); - var buttons = dialog.getElementsByTagName("button"); - var closed = false, me = this, blurring = 1; - function close() { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - } - buttons[0].focus(); - for (var i = 0; i < buttons.length; ++i) { - var b = buttons[i]; - (function(callback) { - CodeMirror.on(b, "click", function(e) { - CodeMirror.e_preventDefault(e); - close(); - if (callback) callback(me); - }); - })(callbacks[i]); - CodeMirror.on(b, "blur", function() { - --blurring; - setTimeout(function() { if (blurring <= 0) close(); }, 200); - }); - CodeMirror.on(b, "focus", function() { ++blurring; }); - } - }); - - /* - * openNotification - * Opens a notification, that can be closed with an optional timer - * (default 5000ms timer) and always closes on click. - * - * If a notification is opened while another is opened, it will close the - * currently opened one and open the new one immediately. - */ - CodeMirror.defineExtension("openNotification", function(template, options) { - closeNotification(this, close); - var dialog = dialogDiv(this, template, options && options.bottom); - var closed = false, doneTimer; - var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; - - function close() { - if (closed) return; - closed = true; - clearTimeout(doneTimer); - dialog.parentNode.removeChild(dialog); - } - - CodeMirror.on(dialog, 'click', function(e) { - CodeMirror.e_preventDefault(e); - close(); - }); - - if (duration) - doneTimer = setTimeout(close, duration); - - return close; - }); -}); - -},{"../../lib/codemirror":30}],17:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - CodeMirror.defineExtension("addPanel", function(node, options) { - options = options || {}; - - if (!this.state.panels) initPanels(this); - - var info = this.state.panels; - var wrapper = info.wrapper; - var cmWrapper = this.getWrapperElement(); - - if (options.after instanceof Panel && !options.after.cleared) { - wrapper.insertBefore(node, options.before.node.nextSibling); - } else if (options.before instanceof Panel && !options.before.cleared) { - wrapper.insertBefore(node, options.before.node); - } else if (options.replace instanceof Panel && !options.replace.cleared) { - wrapper.insertBefore(node, options.replace.node); - options.replace.clear(); - } else if (options.position == "bottom") { - wrapper.appendChild(node); - } else if (options.position == "before-bottom") { - wrapper.insertBefore(node, cmWrapper.nextSibling); - } else if (options.position == "after-top") { - wrapper.insertBefore(node, cmWrapper); - } else { - wrapper.insertBefore(node, wrapper.firstChild); - } - - var height = (options && options.height) || node.offsetHeight; - this._setSize(null, info.heightLeft -= height); - info.panels++; - return new Panel(this, node, options, height); - }); - - function Panel(cm, node, options, height) { - this.cm = cm; - this.node = node; - this.options = options; - this.height = height; - this.cleared = false; - } - - Panel.prototype.clear = function() { - if (this.cleared) return; - this.cleared = true; - var info = this.cm.state.panels; - this.cm._setSize(null, info.heightLeft += this.height); - info.wrapper.removeChild(this.node); - if (--info.panels == 0) removePanels(this.cm); - }; - - Panel.prototype.changed = function(height) { - var newHeight = height == null ? this.node.offsetHeight : height; - var info = this.cm.state.panels; - this.cm._setSize(null, info.height += (newHeight - this.height)); - this.height = newHeight; - }; - - function initPanels(cm) { - var wrap = cm.getWrapperElement(); - var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle; - var height = parseInt(style.height); - var info = cm.state.panels = { - setHeight: wrap.style.height, - heightLeft: height, - panels: 0, - wrapper: document.createElement("div") - }; - wrap.parentNode.insertBefore(info.wrapper, wrap); - var hasFocus = cm.hasFocus(); - info.wrapper.appendChild(wrap); - if (hasFocus) cm.focus(); - - cm._setSize = cm.setSize; - if (height != null) cm.setSize = function(width, newHeight) { - if (newHeight == null) return this._setSize(width, newHeight); - info.setHeight = newHeight; - if (typeof newHeight != "number") { - var px = /^(\d+\.?\d*)px$/.exec(newHeight); - if (px) { - newHeight = Number(px[1]); - } else { - info.wrapper.style.height = newHeight; - newHeight = info.wrapper.offsetHeight; - info.wrapper.style.height = ""; - } - } - cm._setSize(width, info.heightLeft += (newHeight - height)); - height = newHeight; - }; - } - - function removePanels(cm) { - var info = cm.state.panels; - cm.state.panels = null; - - var wrap = cm.getWrapperElement(); - info.wrapper.parentNode.replaceChild(wrap, info.wrapper); - wrap.style.height = info.setHeight; - cm.setSize = cm._setSize; - cm.setSize(); - } -}); - -},{"../../lib/codemirror":30}],18:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineOption("rulers", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - clearRulers(cm); - cm.off("refresh", refreshRulers); - } - if (val && val.length) { - setRulers(cm); - cm.on("refresh", refreshRulers); - } - }); - - function clearRulers(cm) { - for (var i = cm.display.lineSpace.childNodes.length - 1; i >= 0; i--) { - var node = cm.display.lineSpace.childNodes[i]; - if (/(^|\s)CodeMirror-ruler($|\s)/.test(node.className)) - node.parentNode.removeChild(node); - } - } - - function setRulers(cm) { - var val = cm.getOption("rulers"); - var cw = cm.defaultCharWidth(); - var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left; - var minH = cm.display.scroller.offsetHeight + 30; - for (var i = 0; i < val.length; i++) { - var elt = document.createElement("div"); - elt.className = "CodeMirror-ruler"; - var col, conf = val[i]; - if (typeof conf == "number") { - col = conf; - } else { - col = conf.column; - if (conf.className) elt.className += " " + conf.className; - if (conf.color) elt.style.borderColor = conf.color; - if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle; - if (conf.width) elt.style.borderLeftWidth = conf.width; - } - elt.style.left = (left + col * cw) + "px"; - elt.style.top = "-50px"; - elt.style.bottom = "-20px"; - elt.style.minHeight = minH + "px"; - cm.display.lineSpace.insertBefore(elt, cm.display.cursorDiv); - } - } - - function refreshRulers(cm) { - clearRulers(cm); - setRulers(cm); - } -}); - -},{"../../lib/codemirror":30}],19:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - var defaults = { - pairs: "()[]{}''\"\"", - triples: "", - explode: "[]{}" - }; - - var Pos = CodeMirror.Pos; - - CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - cm.removeKeyMap(keyMap); - cm.state.closeBrackets = null; - } - if (val) { - cm.state.closeBrackets = val; - cm.addKeyMap(keyMap); - } - }); - - function getOption(conf, name) { - if (name == "pairs" && typeof conf == "string") return conf; - if (typeof conf == "object" && conf[name] != null) return conf[name]; - return defaults[name]; - } - - var bind = defaults.pairs + "`"; - var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; - for (var i = 0; i < bind.length; i++) - keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i)); - - function handler(ch) { - return function(cm) { return handleChar(cm, ch); }; - } - - function getConfig(cm) { - var deflt = cm.state.closeBrackets; - if (!deflt) return null; - var mode = cm.getModeAt(cm.getCursor()); - return mode.closeBrackets || deflt; - } - - function handleBackspace(cm) { - var conf = getConfig(cm); - if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; - - var pairs = getOption(conf, "pairs"); - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var around = charsAround(cm, ranges[i].head); - if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass; - } - for (var i = ranges.length - 1; i >= 0; i--) { - var cur = ranges[i].head; - cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1)); - } - } - - function handleEnter(cm) { - var conf = getConfig(cm); - var explode = conf && getOption(conf, "explode"); - if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass; - - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) return CodeMirror.Pass; - var around = charsAround(cm, ranges[i].head); - if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass; - } - cm.operation(function() { - cm.replaceSelection("\n\n", null); - cm.execCommand("goCharLeft"); - ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var line = ranges[i].head.line; - cm.indentLine(line, null, true); - cm.indentLine(line + 1, null, true); - } - }); - } - - function contractSelection(sel) { - var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0; - return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)), - head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))}; - } - - function handleChar(cm, ch) { - var conf = getConfig(cm); - if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass; - - var pairs = getOption(conf, "pairs"); - var pos = pairs.indexOf(ch); - if (pos == -1) return CodeMirror.Pass; - var triples = getOption(conf, "triples"); - - var identical = pairs.charAt(pos + 1) == ch; - var ranges = cm.listSelections(); - var opening = pos % 2 == 0; - - var type, next; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], cur = range.head, curType; - var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1)); - if (opening && !range.empty()) { - curType = "surround"; - } else if ((identical || !opening) && next == ch) { - if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch) - curType = "skipThree"; - else - curType = "skip"; - } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 && - cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch && - (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) { - curType = "addFour"; - } else if (identical) { - if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both"; - else return CodeMirror.Pass; - } else if (opening && (cm.getLine(cur.line).length == cur.ch || - isClosingBracket(next, pairs) || - /\s/.test(next))) { - curType = "both"; - } else { - return CodeMirror.Pass; - } - if (!type) type = curType; - else if (type != curType) return CodeMirror.Pass; - } - - var left = pos % 2 ? pairs.charAt(pos - 1) : ch; - var right = pos % 2 ? ch : pairs.charAt(pos + 1); - cm.operation(function() { - if (type == "skip") { - cm.execCommand("goCharRight"); - } else if (type == "skipThree") { - for (var i = 0; i < 3; i++) - cm.execCommand("goCharRight"); - } else if (type == "surround") { - var sels = cm.getSelections(); - for (var i = 0; i < sels.length; i++) - sels[i] = left + sels[i] + right; - cm.replaceSelections(sels, "around"); - sels = cm.listSelections().slice(); - for (var i = 0; i < sels.length; i++) - sels[i] = contractSelection(sels[i]); - cm.setSelections(sels); - } else if (type == "both") { - cm.replaceSelection(left + right, null); - cm.triggerElectric(left + right); - cm.execCommand("goCharLeft"); - } else if (type == "addFour") { - cm.replaceSelection(left + left + left + left, "before"); - cm.execCommand("goCharRight"); - } - }); - } - - function isClosingBracket(ch, pairs) { - var pos = pairs.lastIndexOf(ch); - return pos > -1 && pos % 2 == 1; - } - - function charsAround(cm, pos) { - var str = cm.getRange(Pos(pos.line, pos.ch - 1), - Pos(pos.line, pos.ch + 1)); - return str.length == 2 ? str : null; - } - - // Project the token type that will exists after the given char is - // typed, and use it to determine whether it would cause the start - // of a string token. - function enteringString(cm, pos, ch) { - var line = cm.getLine(pos.line); - var token = cm.getTokenAt(pos); - if (/\bstring2?\b/.test(token.type)) return false; - var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4); - stream.pos = stream.start = token.start; - for (;;) { - var type1 = cm.getMode().token(stream, token.state); - if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1); - stream.start = stream.pos; - } - } -}); - -},{"../../lib/codemirror":30}],20:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - var ie_lt8 = /MSIE \d/.test(navigator.userAgent) && - (document.documentMode == null || document.documentMode < 8); - - var Pos = CodeMirror.Pos; - - var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; - - function findMatchingBracket(cm, where, strict, config) { - var line = cm.getLineHandle(where.line), pos = where.ch - 1; - var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; - if (!match) return null; - var dir = match.charAt(1) == ">" ? 1 : -1; - if (strict && (dir > 0) != (pos == where.ch)) return null; - var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); - - var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); - if (found == null) return null; - return {from: Pos(where.line, pos), to: found && found.pos, - match: found && found.ch == match.charAt(0), forward: dir > 0}; - } - - // bracketRegex is used to specify which type of bracket to scan - // should be a regexp, e.g. /[[\]]/ - // - // Note: If "where" is on an open bracket, then this bracket is ignored. - // - // Returns false when no bracket was found, null when it reached - // maxScanLines and gave up - function scanForBracket(cm, where, dir, style, config) { - var maxScanLen = (config && config.maxScanLineLength) || 10000; - var maxScanLines = (config && config.maxScanLines) || 1000; - - var stack = []; - var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/; - var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1) - : Math.max(cm.firstLine() - 1, where.line - maxScanLines); - for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) { - var line = cm.getLine(lineNo); - if (!line) continue; - var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1; - if (line.length > maxScanLen) continue; - if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0); - for (; pos != end; pos += dir) { - var ch = line.charAt(pos); - if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) { - var match = matching[ch]; - if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch); - else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch}; - else stack.pop(); - } - } - } - return lineNo - dir == (dir > 0 ? cm.lastLine() : cm.firstLine()) ? false : null; - } - - function matchBrackets(cm, autoclear, config) { - // Disable brace matching in long lines, since it'll cause hugely slow updates - var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; - var marks = [], ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); - if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { - var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; - marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); - if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen) - marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style})); - } - } - - if (marks.length) { - // Kludge to work around the IE bug from issue #1193, where text - // input stops going to the textare whever this fires. - if (ie_lt8 && cm.state.focused) cm.focus(); - - var clear = function() { - cm.operation(function() { - for (var i = 0; i < marks.length; i++) marks[i].clear(); - }); - }; - if (autoclear) setTimeout(clear, 800); - else return clear; - } - } - - var currentlyHighlighted = null; - function doMatchBrackets(cm) { - cm.operation(function() { - if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} - currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); - }); - } - - CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) - cm.off("cursorActivity", doMatchBrackets); - if (val) { - cm.state.matchBrackets = typeof val == "object" ? val : {}; - cm.on("cursorActivity", doMatchBrackets); - } - }); - - CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); - CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){ - return findMatchingBracket(this, pos, strict, config); - }); - CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ - return scanForBracket(this, pos, dir, style, config); - }); -}); - -},{"../../lib/codemirror":30}],21:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function doFold(cm, pos, options, force) { - if (options && options.call) { - var finder = options; - options = null; - } else { - var finder = getOption(cm, options, "rangeFinder"); - } - if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0); - var minSize = getOption(cm, options, "minFoldSize"); - - function getRange(allowFolded) { - var range = finder(cm, pos); - if (!range || range.to.line - range.from.line < minSize) return null; - var marks = cm.findMarksAt(range.from); - for (var i = 0; i < marks.length; ++i) { - if (marks[i].__isFold && force !== "fold") { - if (!allowFolded) return null; - range.cleared = true; - marks[i].clear(); - } - } - return range; - } - - var range = getRange(true); - if (getOption(cm, options, "scanUp")) while (!range && pos.line > cm.firstLine()) { - pos = CodeMirror.Pos(pos.line - 1, 0); - range = getRange(false); - } - if (!range || range.cleared || force === "unfold") return; - - var myWidget = makeWidget(cm, options); - CodeMirror.on(myWidget, "mousedown", function(e) { - myRange.clear(); - CodeMirror.e_preventDefault(e); - }); - var myRange = cm.markText(range.from, range.to, { - replacedWith: myWidget, - clearOnEnter: true, - __isFold: true - }); - myRange.on("clear", function(from, to) { - CodeMirror.signal(cm, "unfold", cm, from, to); - }); - CodeMirror.signal(cm, "fold", cm, range.from, range.to); - } - - function makeWidget(cm, options) { - var widget = getOption(cm, options, "widget"); - if (typeof widget == "string") { - var text = document.createTextNode(widget); - widget = document.createElement("span"); - widget.appendChild(text); - widget.className = "CodeMirror-foldmarker"; - } - return widget; - } - - // Clumsy backwards-compatible interface - CodeMirror.newFoldFunction = function(rangeFinder, widget) { - return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); }; - }; - - // New-style interface - CodeMirror.defineExtension("foldCode", function(pos, options, force) { - doFold(this, pos, options, force); - }); - - CodeMirror.defineExtension("isFolded", function(pos) { - var marks = this.findMarksAt(pos); - for (var i = 0; i < marks.length; ++i) - if (marks[i].__isFold) return true; - }); - - CodeMirror.commands.toggleFold = function(cm) { - cm.foldCode(cm.getCursor()); - }; - CodeMirror.commands.fold = function(cm) { - cm.foldCode(cm.getCursor(), null, "fold"); - }; - CodeMirror.commands.unfold = function(cm) { - cm.foldCode(cm.getCursor(), null, "unfold"); - }; - CodeMirror.commands.foldAll = function(cm) { - cm.operation(function() { - for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) - cm.foldCode(CodeMirror.Pos(i, 0), null, "fold"); - }); - }; - CodeMirror.commands.unfoldAll = function(cm) { - cm.operation(function() { - for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++) - cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold"); - }); - }; - - CodeMirror.registerHelper("fold", "combine", function() { - var funcs = Array.prototype.slice.call(arguments, 0); - return function(cm, start) { - for (var i = 0; i < funcs.length; ++i) { - var found = funcs[i](cm, start); - if (found) return found; - } - }; - }); - - CodeMirror.registerHelper("fold", "auto", function(cm, start) { - var helpers = cm.getHelpers(start, "fold"); - for (var i = 0; i < helpers.length; i++) { - var cur = helpers[i](cm, start); - if (cur) return cur; - } - }); - - var defaultOptions = { - rangeFinder: CodeMirror.fold.auto, - widget: "\u2194", - minFoldSize: 0, - scanUp: false - }; - - CodeMirror.defineOption("foldOptions", null); - - function getOption(cm, options, name) { - if (options && options[name] !== undefined) - return options[name]; - var editorOptions = cm.options.foldOptions; - if (editorOptions && editorOptions[name] !== undefined) - return editorOptions[name]; - return defaultOptions[name]; - } - - CodeMirror.defineExtension("foldOption", function(options, name) { - return getOption(this, options, name); - }); -}); - -},{"../../lib/codemirror":30}],22:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror"), _dereq_("./foldcode")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "./foldcode"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineOption("foldGutter", false, function(cm, val, old) { - if (old && old != CodeMirror.Init) { - cm.clearGutter(cm.state.foldGutter.options.gutter); - cm.state.foldGutter = null; - cm.off("gutterClick", onGutterClick); - cm.off("change", onChange); - cm.off("viewportChange", onViewportChange); - cm.off("fold", onFold); - cm.off("unfold", onFold); - cm.off("swapDoc", updateInViewport); - } - if (val) { - cm.state.foldGutter = new State(parseOptions(val)); - updateInViewport(cm); - cm.on("gutterClick", onGutterClick); - cm.on("change", onChange); - cm.on("viewportChange", onViewportChange); - cm.on("fold", onFold); - cm.on("unfold", onFold); - cm.on("swapDoc", updateInViewport); - } - }); - - var Pos = CodeMirror.Pos; - - function State(options) { - this.options = options; - this.from = this.to = 0; - } - - function parseOptions(opts) { - if (opts === true) opts = {}; - if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter"; - if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open"; - if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded"; - return opts; - } - - function isFolded(cm, line) { - var marks = cm.findMarksAt(Pos(line)); - for (var i = 0; i < marks.length; ++i) - if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i]; - } - - function marker(spec) { - if (typeof spec == "string") { - var elt = document.createElement("div"); - elt.className = spec + " CodeMirror-guttermarker-subtle"; - return elt; - } else { - return spec.cloneNode(true); - } - } - - function updateFoldInfo(cm, from, to) { - var opts = cm.state.foldGutter.options, cur = from; - var minSize = cm.foldOption(opts, "minFoldSize"); - var func = cm.foldOption(opts, "rangeFinder"); - cm.eachLine(from, to, function(line) { - var mark = null; - if (isFolded(cm, cur)) { - mark = marker(opts.indicatorFolded); - } else { - var pos = Pos(cur, 0); - var range = func && func(cm, pos); - if (range && range.to.line - range.from.line >= minSize) - mark = marker(opts.indicatorOpen); - } - cm.setGutterMarker(line, opts.gutter, mark); - ++cur; - }); - } - - function updateInViewport(cm) { - var vp = cm.getViewport(), state = cm.state.foldGutter; - if (!state) return; - cm.operation(function() { - updateFoldInfo(cm, vp.from, vp.to); - }); - state.from = vp.from; state.to = vp.to; - } - - function onGutterClick(cm, line, gutter) { - var state = cm.state.foldGutter; - if (!state) return; - var opts = state.options; - if (gutter != opts.gutter) return; - var folded = isFolded(cm, line); - if (folded) folded.clear(); - else cm.foldCode(Pos(line, 0), opts.rangeFinder); - } - - function onChange(cm) { - var state = cm.state.foldGutter; - if (!state) return; - var opts = state.options; - state.from = state.to = 0; - clearTimeout(state.changeUpdate); - state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600); - } - - function onViewportChange(cm) { - var state = cm.state.foldGutter; - if (!state) return; - var opts = state.options; - clearTimeout(state.changeUpdate); - state.changeUpdate = setTimeout(function() { - var vp = cm.getViewport(); - if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) { - updateInViewport(cm); - } else { - cm.operation(function() { - if (vp.from < state.from) { - updateFoldInfo(cm, vp.from, state.from); - state.from = vp.from; - } - if (vp.to > state.to) { - updateFoldInfo(cm, state.to, vp.to); - state.to = vp.to; - } - }); - } - }, opts.updateViewportTimeSpan || 400); - } - - function onFold(cm, from) { - var state = cm.state.foldGutter; - if (!state) return; - var line = from.line; - if (line >= state.from && line < state.to) - updateFoldInfo(cm, line, line + 1); - } -}); - -},{"../../lib/codemirror":30,"./foldcode":21}],23:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.registerHelper("fold", "indent", function(cm, start) { - var tabSize = cm.getOption("tabSize"), firstLine = cm.getLine(start.line); - if (!/\S/.test(firstLine)) return; - var getIndent = function(line) { - return CodeMirror.countColumn(line, null, tabSize); - }; - var myIndent = getIndent(firstLine); - var lastLineInFold = null; - // Go through lines until we find a line that definitely doesn't belong in - // the block we're folding, or to the end. - for (var i = start.line + 1, end = cm.lastLine(); i <= end; ++i) { - var curLine = cm.getLine(i); - var curIndent = getIndent(curLine); - if (curIndent > myIndent) { - // Lines with a greater indent are considered part of the block. - lastLineInFold = i; - } else if (!/\S/.test(curLine)) { - // Empty lines might be breaks within the block we're trying to fold. - } else { - // A non-empty line at an indent equal to or less than ours marks the - // start of another block. - break; - } - } - if (lastLineInFold) return { - from: CodeMirror.Pos(start.line, firstLine.length), - to: CodeMirror.Pos(lastLineInFold, cm.getLine(lastLineInFold).length) - }; -}); - -}); - -},{"../../lib/codemirror":30}],24:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - var Pos = CodeMirror.Pos; - - function forEach(arr, f) { - for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]); - } - - function arrayContains(arr, item) { - if (!Array.prototype.indexOf) { - var i = arr.length; - while (i--) { - if (arr[i] === item) { - return true; - } - } - return false; - } - return arr.indexOf(item) != -1; - } - - function scriptHint(editor, keywords, getToken, options) { - // Find the token at the cursor - var cur = editor.getCursor(), token = getToken(editor, cur); - if (/\b(?:string|comment)\b/.test(token.type)) return; - token.state = CodeMirror.innerMode(editor.getMode(), token.state).state; - - // If it's not a 'word-style' token, ignore the token. - if (!/^[\w$_]*$/.test(token.string)) { - token = {start: cur.ch, end: cur.ch, string: "", state: token.state, - type: token.string == "." ? "property" : null}; - } else if (token.end > cur.ch) { - token.end = cur.ch; - token.string = token.string.slice(0, cur.ch - token.start); - } - - var tprop = token; - // If it is a property, find out what it is a property of. - while (tprop.type == "property") { - tprop = getToken(editor, Pos(cur.line, tprop.start)); - if (tprop.string != ".") return; - tprop = getToken(editor, Pos(cur.line, tprop.start)); - if (!context) var context = []; - context.push(tprop); - } - return {list: getCompletions(token, context, keywords, options), - from: Pos(cur.line, token.start), - to: Pos(cur.line, token.end)}; - } - - function javascriptHint(editor, options) { - return scriptHint(editor, javascriptKeywords, - function (e, cur) {return e.getTokenAt(cur);}, - options); - }; - CodeMirror.registerHelper("hint", "javascript", javascriptHint); - - function getCoffeeScriptToken(editor, cur) { - // This getToken, it is for coffeescript, imitates the behavior of - // getTokenAt method in javascript.js, that is, returning "property" - // type and treat "." as indepenent token. - var token = editor.getTokenAt(cur); - if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') { - token.end = token.start; - token.string = '.'; - token.type = "property"; - } - else if (/^\.[\w$_]*$/.test(token.string)) { - token.type = "property"; - token.start++; - token.string = token.string.replace(/\./, ''); - } - return token; - } - - function coffeescriptHint(editor, options) { - return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options); - } - CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint); - - var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " + - "toUpperCase toLowerCase split concat match replace search").split(" "); - var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " + - "lastIndexOf every some filter forEach map reduce reduceRight ").split(" "); - var funcProps = "prototype apply call bind".split(" "); - var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " + - "if in instanceof new null return switch throw true try typeof var void while with").split(" "); - var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " + - "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" "); - - function getCompletions(token, context, keywords, options) { - var found = [], start = token.string, global = options && options.globalScope || window; - function maybeAdd(str) { - if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str); - } - function gatherCompletions(obj) { - if (typeof obj == "string") forEach(stringProps, maybeAdd); - else if (obj instanceof Array) forEach(arrayProps, maybeAdd); - else if (obj instanceof Function) forEach(funcProps, maybeAdd); - for (var name in obj) maybeAdd(name); - } - - if (context && context.length) { - // If this is a property, see if it belongs to some object we can - // find in the current environment. - var obj = context.pop(), base; - if (obj.type && obj.type.indexOf("variable") === 0) { - if (options && options.additionalContext) - base = options.additionalContext[obj.string]; - if (!options || options.useGlobalScope !== false) - base = base || global[obj.string]; - } else if (obj.type == "string") { - base = ""; - } else if (obj.type == "atom") { - base = 1; - } else if (obj.type == "function") { - if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') && - (typeof global.jQuery == 'function')) - base = global.jQuery(); - else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function')) - base = global._(); - } - while (base != null && context.length) - base = base[context.pop().string]; - if (base != null) gatherCompletions(base); - } else { - // If not, just look in the global object and any local scope - // (reading into JS mode internals to get at the local and global variables) - for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); - for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name); - if (!options || options.useGlobalScope !== false) - gatherCompletions(global); - forEach(keywords, maybeAdd); - } - return found; - } -}); - -},{"../../lib/codemirror":30}],25:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var HINT_ELEMENT_CLASS = "CodeMirror-hint"; - var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active"; - - // This is the old interface, kept around for now to stay - // backwards-compatible. - CodeMirror.showHint = function(cm, getHints, options) { - if (!getHints) return cm.showHint(options); - if (options && options.async) getHints.async = true; - var newOpts = {hint: getHints}; - if (options) for (var prop in options) newOpts[prop] = options[prop]; - return cm.showHint(newOpts); - }; - - CodeMirror.defineExtension("showHint", function(options) { - options = parseOptions(this, this.getCursor("start"), options); - var selections = this.listSelections() - if (selections.length > 1) return; - // By default, don't allow completion when something is selected. - // A hint function can have a `supportsSelection` property to - // indicate that it can handle selections. - if (this.somethingSelected()) { - if (!options.hint.supportsSelection) return; - // Don't try with cross-line selections - for (var i = 0; i < selections.length; i++) - if (selections[i].head.line != selections[i].anchor.line) return; - } - - if (this.state.completionActive) this.state.completionActive.close(); - var completion = this.state.completionActive = new Completion(this, options); - if (!completion.options.hint) return; - - CodeMirror.signal(this, "startCompletion", this); - completion.update(true); - }); - - function Completion(cm, options) { - this.cm = cm; - this.options = options; - this.widget = null; - this.debounce = 0; - this.tick = 0; - this.startPos = this.cm.getCursor("start"); - this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length; - - var self = this; - cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); }); - } - - var requestAnimationFrame = window.requestAnimationFrame || function(fn) { - return setTimeout(fn, 1000/60); - }; - var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout; - - Completion.prototype = { - close: function() { - if (!this.active()) return; - this.cm.state.completionActive = null; - this.tick = null; - this.cm.off("cursorActivity", this.activityFunc); - - if (this.widget && this.data) CodeMirror.signal(this.data, "close"); - if (this.widget) this.widget.close(); - CodeMirror.signal(this.cm, "endCompletion", this.cm); - }, - - active: function() { - return this.cm.state.completionActive == this; - }, - - pick: function(data, i) { - var completion = data.list[i]; - if (completion.hint) completion.hint(this.cm, data, completion); - else this.cm.replaceRange(getText(completion), completion.from || data.from, - completion.to || data.to, "complete"); - CodeMirror.signal(data, "pick", completion); - this.close(); - }, - - cursorActivity: function() { - if (this.debounce) { - cancelAnimationFrame(this.debounce); - this.debounce = 0; - } - - var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line); - if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch || - pos.ch < this.startPos.ch || this.cm.somethingSelected() || - (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) { - this.close(); - } else { - var self = this; - this.debounce = requestAnimationFrame(function() {self.update();}); - if (this.widget) this.widget.disable(); - } - }, - - update: function(first) { - if (this.tick == null) return; - if (!this.options.hint.async) { - this.finishUpdate(this.options.hint(this.cm, this.options), first); - } else { - var myTick = ++this.tick, self = this; - this.options.hint(this.cm, function(data) { - if (self.tick == myTick) self.finishUpdate(data, first); - }, this.options); - } - }, - - finishUpdate: function(data, first) { - if (this.data) CodeMirror.signal(this.data, "update"); - if (data && this.data && CodeMirror.cmpPos(data.from, this.data.from)) data = null; - this.data = data; - - var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle); - if (this.widget) this.widget.close(); - if (data && data.list.length) { - if (picked && data.list.length == 1) { - this.pick(data, 0); - } else { - this.widget = new Widget(this, data); - CodeMirror.signal(data, "shown"); - } - } - } - }; - - function parseOptions(cm, pos, options) { - var editor = cm.options.hintOptions; - var out = {}; - for (var prop in defaultOptions) out[prop] = defaultOptions[prop]; - if (editor) for (var prop in editor) - if (editor[prop] !== undefined) out[prop] = editor[prop]; - if (options) for (var prop in options) - if (options[prop] !== undefined) out[prop] = options[prop]; - if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos) - return out; - } - - function getText(completion) { - if (typeof completion == "string") return completion; - else return completion.text; - } - - function buildKeyMap(completion, handle) { - var baseMap = { - Up: function() {handle.moveFocus(-1);}, - Down: function() {handle.moveFocus(1);}, - PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);}, - PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);}, - Home: function() {handle.setFocus(0);}, - End: function() {handle.setFocus(handle.length - 1);}, - Enter: handle.pick, - Tab: handle.pick, - Esc: handle.close - }; - var custom = completion.options.customKeys; - var ourMap = custom ? {} : baseMap; - function addBinding(key, val) { - var bound; - if (typeof val != "string") - bound = function(cm) { return val(cm, handle); }; - // This mechanism is deprecated - else if (baseMap.hasOwnProperty(val)) - bound = baseMap[val]; - else - bound = val; - ourMap[key] = bound; - } - if (custom) - for (var key in custom) if (custom.hasOwnProperty(key)) - addBinding(key, custom[key]); - var extra = completion.options.extraKeys; - if (extra) - for (var key in extra) if (extra.hasOwnProperty(key)) - addBinding(key, extra[key]); - return ourMap; - } - - function getHintElement(hintsElement, el) { - while (el && el != hintsElement) { - if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el; - el = el.parentNode; - } - } - - function Widget(completion, data) { - this.completion = completion; - this.data = data; - this.picked = false; - var widget = this, cm = completion.cm; - - var hints = this.hints = document.createElement("ul"); - hints.className = "CodeMirror-hints"; - this.selectedHint = data.selectedHint || 0; - - var completions = data.list; - for (var i = 0; i < completions.length; ++i) { - var elt = hints.appendChild(document.createElement("li")), cur = completions[i]; - var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS); - if (cur.className != null) className = cur.className + " " + className; - elt.className = className; - if (cur.render) cur.render(elt, data, cur); - else elt.appendChild(document.createTextNode(cur.displayText || getText(cur))); - elt.hintId = i; - } - - var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null); - var left = pos.left, top = pos.bottom, below = true; - hints.style.left = left + "px"; - hints.style.top = top + "px"; - // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor. - var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth); - var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight); - (completion.options.container || document.body).appendChild(hints); - var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH; - if (overlapY > 0) { - var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top); - if (curTop - height > 0) { // Fits above cursor - hints.style.top = (top = pos.top - height) + "px"; - below = false; - } else if (height > winH) { - hints.style.height = (winH - 5) + "px"; - hints.style.top = (top = pos.bottom - box.top) + "px"; - var cursor = cm.getCursor(); - if (data.from.ch != cursor.ch) { - pos = cm.cursorCoords(cursor); - hints.style.left = (left = pos.left) + "px"; - box = hints.getBoundingClientRect(); - } - } - } - var overlapX = box.right - winW; - if (overlapX > 0) { - if (box.right - box.left > winW) { - hints.style.width = (winW - 5) + "px"; - overlapX -= (box.right - box.left) - winW; - } - hints.style.left = (left = pos.left - overlapX) + "px"; - } - - cm.addKeyMap(this.keyMap = buildKeyMap(completion, { - moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); }, - setFocus: function(n) { widget.changeActive(n); }, - menuSize: function() { return widget.screenAmount(); }, - length: completions.length, - close: function() { completion.close(); }, - pick: function() { widget.pick(); }, - data: data - })); - - if (completion.options.closeOnUnfocus) { - var closingOnBlur; - cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); }); - cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); }); - } - - var startScroll = cm.getScrollInfo(); - cm.on("scroll", this.onScroll = function() { - var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect(); - var newTop = top + startScroll.top - curScroll.top; - var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop); - if (!below) point += hints.offsetHeight; - if (point <= editor.top || point >= editor.bottom) return completion.close(); - hints.style.top = newTop + "px"; - hints.style.left = (left + startScroll.left - curScroll.left) + "px"; - }); - - CodeMirror.on(hints, "dblclick", function(e) { - var t = getHintElement(hints, e.target || e.srcElement); - if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();} - }); - - CodeMirror.on(hints, "click", function(e) { - var t = getHintElement(hints, e.target || e.srcElement); - if (t && t.hintId != null) { - widget.changeActive(t.hintId); - if (completion.options.completeOnSingleClick) widget.pick(); - } - }); - - CodeMirror.on(hints, "mousedown", function() { - setTimeout(function(){cm.focus();}, 20); - }); - - CodeMirror.signal(data, "select", completions[0], hints.firstChild); - return true; - } - - Widget.prototype = { - close: function() { - if (this.completion.widget != this) return; - this.completion.widget = null; - this.hints.parentNode.removeChild(this.hints); - this.completion.cm.removeKeyMap(this.keyMap); - - var cm = this.completion.cm; - if (this.completion.options.closeOnUnfocus) { - cm.off("blur", this.onBlur); - cm.off("focus", this.onFocus); - } - cm.off("scroll", this.onScroll); - }, - - disable: function() { - this.completion.cm.removeKeyMap(this.keyMap); - var widget = this; - this.keyMap = {Enter: function() { widget.picked = true; }}; - this.completion.cm.addKeyMap(this.keyMap); - }, - - pick: function() { - this.completion.pick(this.data, this.selectedHint); - }, - - changeActive: function(i, avoidWrap) { - if (i >= this.data.list.length) - i = avoidWrap ? this.data.list.length - 1 : 0; - else if (i < 0) - i = avoidWrap ? 0 : this.data.list.length - 1; - if (this.selectedHint == i) return; - var node = this.hints.childNodes[this.selectedHint]; - node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); - node = this.hints.childNodes[this.selectedHint = i]; - node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; - if (node.offsetTop < this.hints.scrollTop) - this.hints.scrollTop = node.offsetTop - 3; - else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight) - this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3; - CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node); - }, - - screenAmount: function() { - return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1; - } - }; - - function applicableHelpers(cm, helpers) { - if (!cm.somethingSelected()) return helpers - var result = [] - for (var i = 0; i < helpers.length; i++) - if (helpers[i].supportsSelection) result.push(helpers[i]) - return result - } - - function resolveAutoHints(cm, pos) { - var helpers = cm.getHelpers(pos, "hint"), words - if (helpers.length) { - var async = false, resolved - for (var i = 0; i < helpers.length; i++) if (helpers[i].async) async = true - if (async) { - resolved = function(cm, callback, options) { - var app = applicableHelpers(cm, helpers) - function run(i, result) { - if (i == app.length) return callback(null) - var helper = app[i] - if (helper.async) { - helper(cm, function(result) { - if (result) callback(result) - else run(i + 1) - }, options) - } else { - var result = helper(cm, options) - if (result) callback(result) - else run(i + 1) - } - } - run(0) - } - resolved.async = true - } else { - resolved = function(cm, options) { - var app = applicableHelpers(cm, helpers) - for (var i = 0; i < app.length; i++) { - var cur = app[i](cm, options) - if (cur && cur.list.length) return cur - } - } - } - resolved.supportsSelection = true - return resolved - } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) { - return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) } - } else if (CodeMirror.hint.anyword) { - return function(cm, options) { return CodeMirror.hint.anyword(cm, options) } - } else { - return function() {} - } - } - - CodeMirror.registerHelper("hint", "auto", { - resolve: resolveAutoHints - }); - - CodeMirror.registerHelper("hint", "fromList", function(cm, options) { - var cur = cm.getCursor(), token = cm.getTokenAt(cur); - var to = CodeMirror.Pos(cur.line, token.end); - if (token.string && /\w/.test(token.string[token.string.length - 1])) { - var term = token.string, from = CodeMirror.Pos(cur.line, token.start); - } else { - var term = "", from = to; - } - var found = []; - for (var i = 0; i < options.words.length; i++) { - var word = options.words[i]; - if (word.slice(0, term.length) == term) - found.push(word); - } - - if (found.length) return {list: found, from: from, to: to}; - }); - - CodeMirror.commands.autocomplete = CodeMirror.showHint; - - var defaultOptions = { - hint: CodeMirror.hint.auto, - completeSingle: true, - alignWithWord: true, - closeCharacters: /[\s()\[\]{};:>,]/, - closeOnUnfocus: true, - completeOnSingleClick: false, - container: null, - customKeys: null, - extraKeys: null - }; - - CodeMirror.defineOption("hintOptions", null); -}); - -},{"../../lib/codemirror":30}],26:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Define search commands. Depends on dialog.js or another -// implementation of the openDialog method. - -// Replace works a little oddly -- it will do the replace on the next -// Ctrl-G (or whatever is bound to findNext) press. You prevent a -// replace by making sure the match is no longer selected when hitting -// Ctrl-G. - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror"), _dereq_("./searchcursor"), _dereq_("../dialog/dialog")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function searchOverlay(query, caseInsensitive) { - if (typeof query == "string") - query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g"); - else if (!query.global) - query = new RegExp(query.source, query.ignoreCase ? "gi" : "g"); - - return {token: function(stream) { - query.lastIndex = stream.pos; - var match = query.exec(stream.string); - if (match && match.index == stream.pos) { - stream.pos += match[0].length; - return "searching"; - } else if (match) { - stream.pos = match.index; - } else { - stream.skipToEnd(); - } - }}; - } - - function SearchState() { - this.posFrom = this.posTo = this.lastQuery = this.query = null; - this.overlay = null; - } - - function getSearchState(cm) { - return cm.state.search || (cm.state.search = new SearchState()); - } - - function queryCaseInsensitive(query) { - return typeof query == "string" && query == query.toLowerCase(); - } - - function getSearchCursor(cm, query, pos) { - // Heuristic: if the query string is all lowercase, do a case insensitive search. - return cm.getSearchCursor(query, pos, queryCaseInsensitive(query)); - } - - function persistentDialog(cm, text, deflt, f) { - cm.openDialog(text, f, { - value: deflt, - selectValueOnOpen: true, - closeOnEnter: false, - onClose: function() { clearSearch(cm); } - }); - } - - function dialog(cm, text, shortText, deflt, f) { - if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true}); - else f(prompt(shortText, deflt)); - } - - function confirmDialog(cm, text, shortText, fs) { - if (cm.openConfirm) cm.openConfirm(text, fs); - else if (confirm(shortText)) fs[0](); - } - - function parseString(string) { - return string.replace(/\\(.)/g, function(_, ch) { - if (ch == "n") return "\n" - if (ch == "r") return "\r" - return ch - }) - } - - function parseQuery(query) { - var isRE = query.match(/^\/(.*)\/([a-z]*)$/); - if (isRE) { - try { query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1 ? "" : "i"); } - catch(e) {} // Not a regular expression after all, do a string search - } else { - query = parseString(query) - } - if (typeof query == "string" ? query == "" : query.test("")) - query = /x^/; - return query; - } - - var queryDialog = - 'Search: (Use /re/ syntax for regexp search)'; - - function startSearch(cm, state, query) { - state.queryText = query; - state.query = parseQuery(query); - cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query)); - state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query)); - cm.addOverlay(state.overlay); - if (cm.showMatchesOnScrollbar) { - if (state.annotate) { state.annotate.clear(); state.annotate = null; } - state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query)); - } - } - - function doSearch(cm, rev, persistent) { - var state = getSearchState(cm); - if (state.query) return findNext(cm, rev); - var q = cm.getSelection() || state.lastQuery; - if (persistent && cm.openDialog) { - var hiding = null - persistentDialog(cm, queryDialog, q, function(query, event) { - CodeMirror.e_stop(event); - if (!query) return; - if (query != state.queryText) startSearch(cm, state, query); - if (hiding) hiding.style.opacity = 1 - findNext(cm, event.shiftKey, function(_, to) { - var dialog - if (to.line < 3 && document.querySelector && - (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) && - dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top) - (hiding = dialog).style.opacity = .4 - }) - }); - } else { - dialog(cm, queryDialog, "Search for:", q, function(query) { - if (query && !state.query) cm.operation(function() { - startSearch(cm, state, query); - state.posFrom = state.posTo = cm.getCursor(); - findNext(cm, rev); - }); - }); - } - } - - function findNext(cm, rev, callback) {cm.operation(function() { - var state = getSearchState(cm); - var cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo); - if (!cursor.find(rev)) { - cursor = getSearchCursor(cm, state.query, rev ? CodeMirror.Pos(cm.lastLine()) : CodeMirror.Pos(cm.firstLine(), 0)); - if (!cursor.find(rev)) return; - } - cm.setSelection(cursor.from(), cursor.to()); - cm.scrollIntoView({from: cursor.from(), to: cursor.to()}, 20); - state.posFrom = cursor.from(); state.posTo = cursor.to(); - if (callback) callback(cursor.from(), cursor.to()) - });} - - function clearSearch(cm) {cm.operation(function() { - var state = getSearchState(cm); - state.lastQuery = state.query; - if (!state.query) return; - state.query = state.queryText = null; - cm.removeOverlay(state.overlay); - if (state.annotate) { state.annotate.clear(); state.annotate = null; } - });} - - var replaceQueryDialog = - ' (Use /re/ syntax for regexp search)'; - var replacementQueryDialog = 'With: '; - var doReplaceConfirm = "Replace? "; - - function replaceAll(cm, query, text) { - cm.operation(function() { - for (var cursor = getSearchCursor(cm, query); cursor.findNext();) { - if (typeof query != "string") { - var match = cm.getRange(cursor.from(), cursor.to()).match(query); - cursor.replace(text.replace(/\$(\d)/g, function(_, i) {return match[i];})); - } else cursor.replace(text); - } - }); - } - - function replace(cm, all) { - if (cm.getOption("readOnly")) return; - var query = cm.getSelection() || getSearchState(cm).lastQuery; - var dialogText = all ? "Replace all:" : "Replace:" - dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) { - if (!query) return; - query = parseQuery(query); - dialog(cm, replacementQueryDialog, "Replace with:", "", function(text) { - text = parseString(text) - if (all) { - replaceAll(cm, query, text) - } else { - clearSearch(cm); - var cursor = getSearchCursor(cm, query, cm.getCursor()); - var advance = function() { - var start = cursor.from(), match; - if (!(match = cursor.findNext())) { - cursor = getSearchCursor(cm, query); - if (!(match = cursor.findNext()) || - (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; - } - cm.setSelection(cursor.from(), cursor.to()); - cm.scrollIntoView({from: cursor.from(), to: cursor.to()}); - confirmDialog(cm, doReplaceConfirm, "Replace?", - [function() {doReplace(match);}, advance, - function() {replaceAll(cm, query, text)}]); - }; - var doReplace = function(match) { - cursor.replace(typeof query == "string" ? text : - text.replace(/\$(\d)/g, function(_, i) {return match[i];})); - advance(); - }; - advance(); - } - }); - }); - } - - CodeMirror.commands.find = function(cm) {clearSearch(cm); doSearch(cm);}; - CodeMirror.commands.findPersistent = function(cm) {clearSearch(cm); doSearch(cm, false, true);}; - CodeMirror.commands.findNext = doSearch; - CodeMirror.commands.findPrev = function(cm) {doSearch(cm, true);}; - CodeMirror.commands.clearSearch = clearSearch; - CodeMirror.commands.replace = replace; - CodeMirror.commands.replaceAll = function(cm) {replace(cm, true);}; -}); - -},{"../../lib/codemirror":30,"../dialog/dialog":16,"./searchcursor":27}],27:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - var Pos = CodeMirror.Pos; - - function SearchCursor(doc, query, pos, caseFold) { - this.atOccurrence = false; this.doc = doc; - if (caseFold == null && typeof query == "string") caseFold = false; - - pos = pos ? doc.clipPos(pos) : Pos(0, 0); - this.pos = {from: pos, to: pos}; - - // The matches method is filled in based on the type of query. - // It takes a position and a direction, and returns an object - // describing the next occurrence of the query, or null if no - // more matches were found. - if (typeof query != "string") { // Regexp match - if (!query.global) query = new RegExp(query.source, query.ignoreCase ? "ig" : "g"); - this.matches = function(reverse, pos) { - if (reverse) { - query.lastIndex = 0; - var line = doc.getLine(pos.line).slice(0, pos.ch), cutOff = 0, match, start; - for (;;) { - query.lastIndex = cutOff; - var newMatch = query.exec(line); - if (!newMatch) break; - match = newMatch; - start = match.index; - cutOff = match.index + (match[0].length || 1); - if (cutOff == line.length) break; - } - var matchLen = (match && match[0].length) || 0; - if (!matchLen) { - if (start == 0 && line.length == 0) {match = undefined;} - else if (start != doc.getLine(pos.line).length) { - matchLen++; - } - } - } else { - query.lastIndex = pos.ch; - var line = doc.getLine(pos.line), match = query.exec(line); - var matchLen = (match && match[0].length) || 0; - var start = match && match.index; - if (start + matchLen != line.length && !matchLen) matchLen = 1; - } - if (match && matchLen) - return {from: Pos(pos.line, start), - to: Pos(pos.line, start + matchLen), - match: match}; - }; - } else { // String query - var origQuery = query; - if (caseFold) query = query.toLowerCase(); - var fold = caseFold ? function(str){return str.toLowerCase();} : function(str){return str;}; - var target = query.split("\n"); - // Different methods for single-line and multi-line queries - if (target.length == 1) { - if (!query.length) { - // Empty string would match anything and never progress, so - // we define it to match nothing instead. - this.matches = function() {}; - } else { - this.matches = function(reverse, pos) { - if (reverse) { - var orig = doc.getLine(pos.line).slice(0, pos.ch), line = fold(orig); - var match = line.lastIndexOf(query); - if (match > -1) { - match = adjustPos(orig, line, match); - return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)}; - } - } else { - var orig = doc.getLine(pos.line).slice(pos.ch), line = fold(orig); - var match = line.indexOf(query); - if (match > -1) { - match = adjustPos(orig, line, match) + pos.ch; - return {from: Pos(pos.line, match), to: Pos(pos.line, match + origQuery.length)}; - } - } - }; - } - } else { - var origTarget = origQuery.split("\n"); - this.matches = function(reverse, pos) { - var last = target.length - 1; - if (reverse) { - if (pos.line - (target.length - 1) < doc.firstLine()) return; - if (fold(doc.getLine(pos.line).slice(0, origTarget[last].length)) != target[target.length - 1]) return; - var to = Pos(pos.line, origTarget[last].length); - for (var ln = pos.line - 1, i = last - 1; i >= 1; --i, --ln) - if (target[i] != fold(doc.getLine(ln))) return; - var line = doc.getLine(ln), cut = line.length - origTarget[0].length; - if (fold(line.slice(cut)) != target[0]) return; - return {from: Pos(ln, cut), to: to}; - } else { - if (pos.line + (target.length - 1) > doc.lastLine()) return; - var line = doc.getLine(pos.line), cut = line.length - origTarget[0].length; - if (fold(line.slice(cut)) != target[0]) return; - var from = Pos(pos.line, cut); - for (var ln = pos.line + 1, i = 1; i < last; ++i, ++ln) - if (target[i] != fold(doc.getLine(ln))) return; - if (fold(doc.getLine(ln).slice(0, origTarget[last].length)) != target[last]) return; - return {from: from, to: Pos(ln, origTarget[last].length)}; - } - }; - } - } - } - - SearchCursor.prototype = { - findNext: function() {return this.find(false);}, - findPrevious: function() {return this.find(true);}, - - find: function(reverse) { - var self = this, pos = this.doc.clipPos(reverse ? this.pos.from : this.pos.to); - function savePosAndFail(line) { - var pos = Pos(line, 0); - self.pos = {from: pos, to: pos}; - self.atOccurrence = false; - return false; - } - - for (;;) { - if (this.pos = this.matches(reverse, pos)) { - this.atOccurrence = true; - return this.pos.match || true; - } - if (reverse) { - if (!pos.line) return savePosAndFail(0); - pos = Pos(pos.line-1, this.doc.getLine(pos.line-1).length); - } - else { - var maxLine = this.doc.lineCount(); - if (pos.line == maxLine - 1) return savePosAndFail(maxLine); - pos = Pos(pos.line + 1, 0); - } - } - }, - - from: function() {if (this.atOccurrence) return this.pos.from;}, - to: function() {if (this.atOccurrence) return this.pos.to;}, - - replace: function(newText, origin) { - if (!this.atOccurrence) return; - var lines = CodeMirror.splitLines(newText); - this.doc.replaceRange(lines, this.pos.from, this.pos.to, origin); - this.pos.to = Pos(this.pos.from.line + lines.length - 1, - lines[lines.length - 1].length + (lines.length == 1 ? this.pos.from.ch : 0)); - } - }; - - // Maps a position in a case-folded line back to a position in the original line - // (compensating for codepoints increasing in number during folding) - function adjustPos(orig, folded, pos) { - if (orig.length == folded.length) return pos; - for (var pos1 = Math.min(pos, orig.length);;) { - var len1 = orig.slice(0, pos1).toLowerCase().length; - if (len1 < pos) ++pos1; - else if (len1 > pos) --pos1; - else return pos1; - } - } - - CodeMirror.defineExtension("getSearchCursor", function(query, pos, caseFold) { - return new SearchCursor(this.doc, query, pos, caseFold); - }); - CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) { - return new SearchCursor(this, query, pos, caseFold); - }); - - CodeMirror.defineExtension("selectMatches", function(query, caseFold) { - var ranges = []; - var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold); - while (cur.findNext()) { - if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break; - ranges.push({anchor: cur.from(), head: cur.to()}); - } - if (ranges.length) - this.setSelections(ranges, 0); - }); -}); - -},{"../../lib/codemirror":30}],28:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var Pos = CodeMirror.Pos; - - function findParagraph(cm, pos, options) { - var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart"); - for (var start = pos.line, first = cm.firstLine(); start > first; --start) { - var line = cm.getLine(start); - if (startRE && startRE.test(line)) break; - if (!/\S/.test(line)) { ++start; break; } - } - var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd"); - for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) { - var line = cm.getLine(end); - if (endRE && endRE.test(line)) { ++end; break; } - if (!/\S/.test(line)) break; - } - return {from: start, to: end}; - } - - function findBreakPoint(text, column, wrapOn, killTrailingSpace) { - for (var at = column; at > 0; --at) - if (wrapOn.test(text.slice(at - 1, at + 1))) break; - for (var first = true;; first = false) { - var endOfText = at; - if (killTrailingSpace) - while (text.charAt(endOfText - 1) == " ") --endOfText; - if (endOfText == 0 && first) at = column; - else return {from: endOfText, to: at}; - } - } - - function wrapRange(cm, from, to, options) { - from = cm.clipPos(from); to = cm.clipPos(to); - var column = options.column || 80; - var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/; - var killTrailing = options.killTrailingSpace !== false; - var changes = [], curLine = "", curNo = from.line; - var lines = cm.getRange(from, to, false); - if (!lines.length) return null; - var leadingSpace = lines[0].match(/^[ \t]*/)[0]; - - for (var i = 0; i < lines.length; ++i) { - var text = lines[i], oldLen = curLine.length, spaceInserted = 0; - if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) { - curLine += " "; - spaceInserted = 1; - } - var spaceTrimmed = ""; - if (i) { - spaceTrimmed = text.match(/^\s*/)[0]; - text = text.slice(spaceTrimmed.length); - } - curLine += text; - if (i) { - var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed && - findBreakPoint(curLine, column, wrapOn, killTrailing); - // If this isn't broken, or is broken at a different point, remove old break - if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) { - changes.push({text: [spaceInserted ? " " : ""], - from: Pos(curNo, oldLen), - to: Pos(curNo + 1, spaceTrimmed.length)}); - } else { - curLine = leadingSpace + text; - ++curNo; - } - } - while (curLine.length > column) { - var bp = findBreakPoint(curLine, column, wrapOn, killTrailing); - changes.push({text: ["", leadingSpace], - from: Pos(curNo, bp.from), - to: Pos(curNo, bp.to)}); - curLine = leadingSpace + curLine.slice(bp.to); - ++curNo; - } - } - if (changes.length) cm.operation(function() { - for (var i = 0; i < changes.length; ++i) { - var change = changes[i]; - if (change.text || CodeMirror.cmpPos(change.from, change.to)) - cm.replaceRange(change.text, change.from, change.to); - } - }); - return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null; - } - - CodeMirror.defineExtension("wrapParagraph", function(pos, options) { - options = options || {}; - if (!pos) pos = this.getCursor(); - var para = findParagraph(this, pos, options); - return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options); - }); - - CodeMirror.commands.wrapLines = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(), at = cm.lastLine() + 1; - for (var i = ranges.length - 1; i >= 0; i--) { - var range = ranges[i], span; - if (range.empty()) { - var para = findParagraph(cm, range.head, {}); - span = {from: Pos(para.from, 0), to: Pos(para.to - 1)}; - } else { - span = {from: range.from(), to: range.to()}; - } - if (span.to.line >= at) continue; - at = span.from.line; - wrapRange(cm, span.from, span.to, {}); - } - }); - }; - - CodeMirror.defineExtension("wrapRange", function(from, to, options) { - return wrapRange(this, from, to, options || {}); - }); - - CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) { - options = options || {}; - var cm = this, paras = []; - for (var line = from.line; line <= to.line;) { - var para = findParagraph(cm, Pos(line, 0), options); - paras.push(para); - line = para.to; - } - var madeChange = false; - if (paras.length) cm.operation(function() { - for (var i = paras.length - 1; i >= 0; --i) - madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options); - }); - return madeChange; - }); -}); - -},{"../../lib/codemirror":30}],29:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// A rough approximation of Sublime Text's keybindings -// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../lib/codemirror"), _dereq_("../addon/search/searchcursor"), _dereq_("../addon/edit/matchbrackets")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var map = CodeMirror.keyMap.sublime = {fallthrough: "default"}; - var cmds = CodeMirror.commands; - var Pos = CodeMirror.Pos; - var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault; - var ctrl = mac ? "Cmd-" : "Ctrl-"; - - // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that. - function findPosSubword(doc, start, dir) { - if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1)); - var line = doc.getLine(start.line); - if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0)); - var state = "start", type; - for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) { - var next = line.charAt(dir < 0 ? pos - 1 : pos); - var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o"; - if (cat == "w" && next.toUpperCase() == next) cat = "W"; - if (state == "start") { - if (cat != "o") { state = "in"; type = cat; } - } else if (state == "in") { - if (type != cat) { - if (type == "w" && cat == "W" && dir < 0) pos--; - if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; } - break; - } - } - } - return Pos(start.line, pos); - } - - function moveSubword(cm, dir) { - cm.extendSelectionsBy(function(range) { - if (cm.display.shift || cm.doc.extend || range.empty()) - return findPosSubword(cm.doc, range.head, dir); - else - return dir < 0 ? range.from() : range.to(); - }); - } - - cmds[map["Alt-Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); }; - cmds[map["Alt-Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); }; - - var scrollLineCombo = mac ? "Ctrl-Alt-" : "Ctrl-"; - - cmds[map[scrollLineCombo + "Up"] = "scrollLineUp"] = function(cm) { - var info = cm.getScrollInfo(); - if (!cm.somethingSelected()) { - var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local"); - if (cm.getCursor().line >= visibleBottomLine) - cm.execCommand("goLineUp"); - } - cm.scrollTo(null, info.top - cm.defaultTextHeight()); - }; - cmds[map[scrollLineCombo + "Down"] = "scrollLineDown"] = function(cm) { - var info = cm.getScrollInfo(); - if (!cm.somethingSelected()) { - var visibleTopLine = cm.lineAtHeight(info.top, "local")+1; - if (cm.getCursor().line <= visibleTopLine) - cm.execCommand("goLineDown"); - } - cm.scrollTo(null, info.top + cm.defaultTextHeight()); - }; - - cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) { - var ranges = cm.listSelections(), lineRanges = []; - for (var i = 0; i < ranges.length; i++) { - var from = ranges[i].from(), to = ranges[i].to(); - for (var line = from.line; line <= to.line; ++line) - if (!(to.line > from.line && line == to.line && to.ch == 0)) - lineRanges.push({anchor: line == from.line ? from : Pos(line, 0), - head: line == to.line ? to : Pos(line)}); - } - cm.setSelections(lineRanges, 0); - }; - - map["Shift-Tab"] = "indentLess"; - - cmds[map["Esc"] = "singleSelectionTop"] = function(cm) { - var range = cm.listSelections()[0]; - cm.setSelection(range.anchor, range.head, {scroll: false}); - }; - - cmds[map[ctrl + "L"] = "selectLine"] = function(cm) { - var ranges = cm.listSelections(), extended = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - extended.push({anchor: Pos(range.from().line, 0), - head: Pos(range.to().line + 1, 0)}); - } - cm.setSelections(extended); - }; - - map["Shift-" + ctrl + "K"] = "deleteLine"; - - function insertLine(cm, above) { - cm.operation(function() { - var len = cm.listSelections().length, newSelection = [], last = -1; - for (var i = 0; i < len; i++) { - var head = cm.listSelections()[i].head; - if (head.line <= last) continue; - var at = Pos(head.line + (above ? 0 : 1), 0); - cm.replaceRange("\n", at, null, "+insertLine"); - cm.indentLine(at.line, null, true); - newSelection.push({head: at, anchor: at}); - last = head.line + 1; - } - cm.setSelections(newSelection); - }); - } - - cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { insertLine(cm, false); }; - - cmds[map["Shift-" + ctrl + "Enter"] = "insertLineBefore"] = function(cm) { insertLine(cm, true); }; - - function wordAt(cm, pos) { - var start = pos.ch, end = start, line = cm.getLine(pos.line); - while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start; - while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end; - return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)}; - } - - cmds[map[ctrl + "D"] = "selectNextOccurrence"] = function(cm) { - var from = cm.getCursor("from"), to = cm.getCursor("to"); - var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel; - if (CodeMirror.cmpPos(from, to) == 0) { - var word = wordAt(cm, from); - if (!word.word) return; - cm.setSelection(word.from, word.to); - fullWord = true; - } else { - var text = cm.getRange(from, to); - var query = fullWord ? new RegExp("\\b" + text + "\\b") : text; - var cur = cm.getSearchCursor(query, to); - if (cur.findNext()) { - cm.addSelection(cur.from(), cur.to()); - } else { - cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); - if (cur.findNext()) - cm.addSelection(cur.from(), cur.to()); - } - } - if (fullWord) - cm.state.sublimeFindFullWord = cm.doc.sel; - }; - - var mirror = "(){}[]"; - function selectBetweenBrackets(cm) { - var pos = cm.getCursor(), opening = cm.scanForBracket(pos, -1); - if (!opening) return; - for (;;) { - var closing = cm.scanForBracket(pos, 1); - if (!closing) return; - if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) { - cm.setSelection(Pos(opening.pos.line, opening.pos.ch + 1), closing.pos, false); - return true; - } - pos = Pos(closing.pos.line, closing.pos.ch + 1); - } - } - - cmds[map["Shift-" + ctrl + "Space"] = "selectScope"] = function(cm) { - selectBetweenBrackets(cm) || cm.execCommand("selectAll"); - }; - cmds[map["Shift-" + ctrl + "M"] = "selectBetweenBrackets"] = function(cm) { - if (!selectBetweenBrackets(cm)) return CodeMirror.Pass; - }; - - cmds[map[ctrl + "M"] = "goToBracket"] = function(cm) { - cm.extendSelectionsBy(function(range) { - var next = cm.scanForBracket(range.head, 1); - if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos; - var prev = cm.scanForBracket(range.head, -1); - return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head; - }); - }; - - var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-"; - - cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) { - var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], from = range.from().line - 1, to = range.to().line; - newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch), - head: Pos(range.head.line - 1, range.head.ch)}); - if (range.to().ch == 0 && !range.empty()) --to; - if (from > at) linesToMove.push(from, to); - else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; - at = to; - } - cm.operation(function() { - for (var i = 0; i < linesToMove.length; i += 2) { - var from = linesToMove[i], to = linesToMove[i + 1]; - var line = cm.getLine(from); - cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); - if (to > cm.lastLine()) - cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine"); - else - cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); - } - cm.setSelections(newSels); - cm.scrollIntoView(); - }); - }; - - cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) { - var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1; - for (var i = ranges.length - 1; i >= 0; i--) { - var range = ranges[i], from = range.to().line + 1, to = range.from().line; - if (range.to().ch == 0 && !range.empty()) from--; - if (from < at) linesToMove.push(from, to); - else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; - at = to; - } - cm.operation(function() { - for (var i = linesToMove.length - 2; i >= 0; i -= 2) { - var from = linesToMove[i], to = linesToMove[i + 1]; - var line = cm.getLine(from); - if (from == cm.lastLine()) - cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine"); - else - cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); - cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); - } - cm.scrollIntoView(); - }); - }; - - map[ctrl + "/"] = function(cm) { - cm.toggleComment({ indent: true }); - } - - cmds[map[ctrl + "J"] = "joinLines"] = function(cm) { - var ranges = cm.listSelections(), joined = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], from = range.from(); - var start = from.line, end = range.to().line; - while (i < ranges.length - 1 && ranges[i + 1].from().line == end) - end = ranges[++i].to().line; - joined.push({start: start, end: end, anchor: !range.empty() && from}); - } - cm.operation(function() { - var offset = 0, ranges = []; - for (var i = 0; i < joined.length; i++) { - var obj = joined[i]; - var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head; - for (var line = obj.start; line <= obj.end; line++) { - var actual = line - offset; - if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1); - if (actual < cm.lastLine()) { - cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length)); - ++offset; - } - } - ranges.push({anchor: anchor || head, head: head}); - } - cm.setSelections(ranges, 0); - }); - }; - - cmds[map["Shift-" + ctrl + "D"] = "duplicateLine"] = function(cm) { - cm.operation(function() { - var rangeCount = cm.listSelections().length; - for (var i = 0; i < rangeCount; i++) { - var range = cm.listSelections()[i]; - if (range.empty()) - cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0)); - else - cm.replaceRange(cm.getRange(range.from(), range.to()), range.from()); - } - cm.scrollIntoView(); - }); - }; - - map[ctrl + "T"] = "transposeChars"; - - function sortLines(cm, caseSensitive) { - var ranges = cm.listSelections(), toSort = [], selected; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.empty()) continue; - var from = range.from().line, to = range.to().line; - while (i < ranges.length - 1 && ranges[i + 1].from().line == to) - to = range[++i].to().line; - toSort.push(from, to); - } - if (toSort.length) selected = true; - else toSort.push(cm.firstLine(), cm.lastLine()); - - cm.operation(function() { - var ranges = []; - for (var i = 0; i < toSort.length; i += 2) { - var from = toSort[i], to = toSort[i + 1]; - var start = Pos(from, 0), end = Pos(to); - var lines = cm.getRange(start, end, false); - if (caseSensitive) - lines.sort(); - else - lines.sort(function(a, b) { - var au = a.toUpperCase(), bu = b.toUpperCase(); - if (au != bu) { a = au; b = bu; } - return a < b ? -1 : a == b ? 0 : 1; - }); - cm.replaceRange(lines, start, end); - if (selected) ranges.push({anchor: start, head: end}); - } - if (selected) cm.setSelections(ranges, 0); - }); - } - - cmds[map["F9"] = "sortLines"] = function(cm) { sortLines(cm, true); }; - cmds[map[ctrl + "F9"] = "sortLinesInsensitive"] = function(cm) { sortLines(cm, false); }; - - cmds[map["F2"] = "nextBookmark"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) while (marks.length) { - var current = marks.shift(); - var found = current.find(); - if (found) { - marks.push(current); - return cm.setSelection(found.from, found.to); - } - } - }; - - cmds[map["Shift-F2"] = "prevBookmark"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) while (marks.length) { - marks.unshift(marks.pop()); - var found = marks[marks.length - 1].find(); - if (!found) - marks.pop(); - else - return cm.setSelection(found.from, found.to); - } - }; - - cmds[map[ctrl + "F2"] = "toggleBookmark"] = function(cm) { - var ranges = cm.listSelections(); - var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []); - for (var i = 0; i < ranges.length; i++) { - var from = ranges[i].from(), to = ranges[i].to(); - var found = cm.findMarks(from, to); - for (var j = 0; j < found.length; j++) { - if (found[j].sublimeBookmark) { - found[j].clear(); - for (var k = 0; k < marks.length; k++) - if (marks[k] == found[j]) - marks.splice(k--, 1); - break; - } - } - if (j == found.length) - marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false})); - } - }; - - cmds[map["Shift-" + ctrl + "F2"] = "clearBookmarks"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear(); - marks.length = 0; - }; - - cmds[map["Alt-F2"] = "selectBookmarks"] = function(cm) { - var marks = cm.state.sublimeBookmarks, ranges = []; - if (marks) for (var i = 0; i < marks.length; i++) { - var found = marks[i].find(); - if (!found) - marks.splice(i--, 0); - else - ranges.push({anchor: found.from, head: found.to}); - } - if (ranges.length) - cm.setSelections(ranges, 0); - }; - - map["Alt-Q"] = "wrapLines"; - - var cK = ctrl + "K "; - - function modifyWordOrSelection(cm, mod) { - cm.operation(function() { - var ranges = cm.listSelections(), indices = [], replacements = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.empty()) { indices.push(i); replacements.push(""); } - else replacements.push(mod(cm.getRange(range.from(), range.to()))); - } - cm.replaceSelections(replacements, "around", "case"); - for (var i = indices.length - 1, at; i >= 0; i--) { - var range = ranges[indices[i]]; - if (at && CodeMirror.cmpPos(range.head, at) > 0) continue; - var word = wordAt(cm, range.head); - at = word.from; - cm.replaceRange(mod(word.word), word.from, word.to); - } - }); - } - - map[cK + ctrl + "Backspace"] = "delLineLeft"; - - cmds[map["Backspace"] = "smartBackspace"] = function(cm) { - if (cm.somethingSelected()) return CodeMirror.Pass; - - var cursor = cm.getCursor(); - var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor); - var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize")); - var indentUnit = cm.getOption("indentUnit"); - - if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) { - var prevIndent = new Pos(cursor.line, - CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit)); - - // If no smart delete is happening (due to tab sizing) just do a regular delete - if (prevIndent.ch == cursor.ch) return CodeMirror.Pass; - - return cm.replaceRange("", prevIndent, cursor, "+delete"); - } else { - return CodeMirror.Pass; - } - }; - - cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = ranges.length - 1; i >= 0; i--) - cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete"); - cm.scrollIntoView(); - }); - }; - - cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) { - modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); }); - }; - cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) { - modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); }); - }; - - cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) { - if (cm.state.sublimeMark) cm.state.sublimeMark.clear(); - cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); - }; - cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) cm.setSelection(cm.getCursor(), found); - }; - cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) { - var from = cm.getCursor(), to = found; - if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; } - cm.state.sublimeKilled = cm.getRange(from, to); - cm.replaceRange("", from, to); - } - }; - cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) { - cm.state.sublimeMark.clear(); - cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); - cm.setCursor(found); - } - }; - cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) { - if (cm.state.sublimeKilled != null) - cm.replaceSelection(cm.state.sublimeKilled, null, "paste"); - }; - - map[cK + ctrl + "G"] = "clearBookmarks"; - cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) { - var pos = cm.cursorCoords(null, "local"); - cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2); - }; - - cmds[map["Shift-Alt-Up"] = "selectLinesUpward"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.head.line > cm.firstLine()) - cm.addSelection(Pos(range.head.line - 1, range.head.ch)); - } - }); - }; - cmds[map["Shift-Alt-Down"] = "selectLinesDownward"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.head.line < cm.lastLine()) - cm.addSelection(Pos(range.head.line + 1, range.head.ch)); - } - }); - }; - - function getTarget(cm) { - var from = cm.getCursor("from"), to = cm.getCursor("to"); - if (CodeMirror.cmpPos(from, to) == 0) { - var word = wordAt(cm, from); - if (!word.word) return; - from = word.from; - to = word.to; - } - return {from: from, to: to, query: cm.getRange(from, to), word: word}; - } - - function findAndGoTo(cm, forward) { - var target = getTarget(cm); - if (!target) return; - var query = target.query; - var cur = cm.getSearchCursor(query, forward ? target.to : target.from); - - if (forward ? cur.findNext() : cur.findPrevious()) { - cm.setSelection(cur.from(), cur.to()); - } else { - cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0) - : cm.clipPos(Pos(cm.lastLine()))); - if (forward ? cur.findNext() : cur.findPrevious()) - cm.setSelection(cur.from(), cur.to()); - else if (target.word) - cm.setSelection(target.from, target.to); - } - }; - cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); }; - cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); }; - cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) { - var target = getTarget(cm); - if (!target) return; - var cur = cm.getSearchCursor(target.query); - var matches = []; - var primaryIndex = -1; - while (cur.findNext()) { - matches.push({anchor: cur.from(), head: cur.to()}); - if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch) - primaryIndex++; - } - cm.setSelections(matches, primaryIndex); - }; - - map["Shift-" + ctrl + "["] = "fold"; - map["Shift-" + ctrl + "]"] = "unfold"; - map[cK + ctrl + "0"] = map[cK + ctrl + "j"] = "unfoldAll"; - - map[ctrl + "I"] = "findIncremental"; - map["Shift-" + ctrl + "I"] = "findIncrementalReverse"; - map[ctrl + "H"] = "replace"; - map["F3"] = "findNext"; - map["Shift-F3"] = "findPrev"; - - CodeMirror.normalizeKeyMap(map); -}); - -},{"../addon/edit/matchbrackets":20,"../addon/search/searchcursor":27,"../lib/codemirror":30}],30:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// This is CodeMirror (http://codemirror.net), a code editor -// implemented in JavaScript on top of the browser's DOM. -// -// You can find some technical background for some of the code below -// at http://marijnhaverbeke.nl/blog/#cm-internals . - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - module.exports = mod(); - else if (typeof define == "function" && define.amd) // AMD - return define([], mod); - else // Plain browser env - this.CodeMirror = mod(); -})(function() { - "use strict"; - - // BROWSER SNIFFING - - // Kludges for bugs and behavior differences that can't be feature - // detected are enabled based on userAgent etc sniffing. - var userAgent = navigator.userAgent; - var platform = navigator.platform; - - var gecko = /gecko\/\d/i.test(userAgent); - var ie_upto10 = /MSIE \d/.test(userAgent); - var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); - var ie = ie_upto10 || ie_11up; - var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]); - var webkit = /WebKit\//.test(userAgent); - var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); - var chrome = /Chrome\//.test(userAgent); - var presto = /Opera\//.test(userAgent); - var safari = /Apple Computer/.test(navigator.vendor); - var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); - var phantom = /PhantomJS/.test(userAgent); - - var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); - // This is woefully incomplete. Suggestions for alternative methods welcome. - var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); - var mac = ios || /Mac/.test(platform); - var windows = /win/i.test(platform); - - var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); - if (presto_version) presto_version = Number(presto_version[1]); - if (presto_version && presto_version >= 15) { presto = false; webkit = true; } - // Some browsers use the wrong event properties to signal cmd/ctrl on OS X - var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); - var captureRightClick = gecko || (ie && ie_version >= 9); - - // Optimize some code when these features are not used. - var sawReadOnlySpans = false, sawCollapsedSpans = false; - - // EDITOR CONSTRUCTOR - - // A CodeMirror instance represents an editor. This is the object - // that user code is usually dealing with. - - function CodeMirror(place, options) { - if (!(this instanceof CodeMirror)) return new CodeMirror(place, options); - - this.options = options = options ? copyObj(options) : {}; - // Determine effective options based on given values and defaults. - copyObj(defaults, options, false); - setGuttersForLineNumbers(options); - - var doc = options.value; - if (typeof doc == "string") doc = new Doc(doc, options.mode, null, options.lineSeparator); - this.doc = doc; - - var input = new CodeMirror.inputStyles[options.inputStyle](this); - var display = this.display = new Display(place, doc, input); - display.wrapper.CodeMirror = this; - updateGutters(this); - themeChanged(this); - if (options.lineWrapping) - this.display.wrapper.className += " CodeMirror-wrap"; - if (options.autofocus && !mobile) display.input.focus(); - initScrollbars(this); - - this.state = { - keyMaps: [], // stores maps added by addKeyMap - overlays: [], // highlighting overlays, as added by addOverlay - modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info - overwrite: false, - delayingBlurEvent: false, - focused: false, - suppressEdits: false, // used to disable editing during key handlers when in readOnly mode - pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll - selectingText: false, - draggingText: false, - highlight: new Delayed(), // stores highlight worker timeout - keySeq: null, // Unfinished key sequence - specialChars: null - }; - - var cm = this; - - // Override magic textarea content restore that IE sometimes does - // on our hidden textarea on reload - if (ie && ie_version < 11) setTimeout(function() { cm.display.input.reset(true); }, 20); - - registerEventHandlers(this); - ensureGlobalHandlers(); - - startOperation(this); - this.curOp.forceUpdate = true; - attachDoc(this, doc); - - if ((options.autofocus && !mobile) || cm.hasFocus()) - setTimeout(bind(onFocus, this), 20); - else - onBlur(this); - - for (var opt in optionHandlers) if (optionHandlers.hasOwnProperty(opt)) - optionHandlers[opt](this, options[opt], Init); - maybeUpdateLineNumberWidth(this); - if (options.finishInit) options.finishInit(this); - for (var i = 0; i < initHooks.length; ++i) initHooks[i](this); - endOperation(this); - // Suppress optimizelegibility in Webkit, since it breaks text - // measuring on line wrapping boundaries. - if (webkit && options.lineWrapping && - getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") - display.lineDiv.style.textRendering = "auto"; - } - - // DISPLAY CONSTRUCTOR - - // The display handles the DOM integration, both for input reading - // and content drawing. It holds references to DOM nodes and - // display-related state. - - function Display(place, doc, input) { - var d = this; - this.input = input; - - // Covers bottom-right square when both scrollbars are present. - d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); - d.scrollbarFiller.setAttribute("cm-not-content", "true"); - // Covers bottom of gutter when coverGutterNextToScrollbar is on - // and h scrollbar is present. - d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); - d.gutterFiller.setAttribute("cm-not-content", "true"); - // Will contain the actual code, positioned to cover the viewport. - d.lineDiv = elt("div", null, "CodeMirror-code"); - // Elements are added to these to represent selection and cursors. - d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); - d.cursorDiv = elt("div", null, "CodeMirror-cursors"); - // A visibility: hidden element used to find the size of things. - d.measure = elt("div", null, "CodeMirror-measure"); - // When lines outside of the viewport are measured, they are drawn in this. - d.lineMeasure = elt("div", null, "CodeMirror-measure"); - // Wraps everything that needs to exist inside the vertically-padded coordinate system - d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], - null, "position: relative; outline: none"); - // Moved around its parent to cover visible view. - d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative"); - // Set to the height of the document, allowing scrolling. - d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); - d.sizerWidth = null; - // Behavior of elts with overflow: auto and padding is - // inconsistent across browsers. This is used to ensure the - // scrollable area is big enough. - d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); - // Will contain the gutters, if any. - d.gutters = elt("div", null, "CodeMirror-gutters"); - d.lineGutter = null; - // Actual scrollable element. - d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); - d.scroller.setAttribute("tabIndex", "-1"); - // The element in which the editor lives. - d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); - - // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) - if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } - if (!webkit && !(gecko && mobile)) d.scroller.draggable = true; - - if (place) { - if (place.appendChild) place.appendChild(d.wrapper); - else place(d.wrapper); - } - - // Current rendered range (may be bigger than the view window). - d.viewFrom = d.viewTo = doc.first; - d.reportedViewFrom = d.reportedViewTo = doc.first; - // Information about the rendered lines. - d.view = []; - d.renderedView = null; - // Holds info about a single rendered line when it was rendered - // for measurement, while not in view. - d.externalMeasured = null; - // Empty space (in pixels) above the view - d.viewOffset = 0; - d.lastWrapHeight = d.lastWrapWidth = 0; - d.updateLineNumbers = null; - - d.nativeBarWidth = d.barHeight = d.barWidth = 0; - d.scrollbarsClipped = false; - - // Used to only resize the line number gutter when necessary (when - // the amount of lines crosses a boundary that makes its width change) - d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; - // Set to true when a non-horizontal-scrolling line widget is - // added. As an optimization, line widget aligning is skipped when - // this is false. - d.alignWidgets = false; - - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - d.maxLine = null; - d.maxLineLength = 0; - d.maxLineChanged = false; - - // Used for measuring wheel scrolling granularity - d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; - - // True when shift is held down. - d.shift = false; - - // Used to track whether anything happened since the context menu - // was opened. - d.selForContextMenu = null; - - d.activeTouch = null; - - input.init(d); - } - - // STATE UPDATES - - // Used to get the editor into a consistent state again when options change. - - function loadMode(cm) { - cm.doc.mode = CodeMirror.getMode(cm.options, cm.doc.modeOption); - resetModeState(cm); - } - - function resetModeState(cm) { - cm.doc.iter(function(line) { - if (line.stateAfter) line.stateAfter = null; - if (line.styles) line.styles = null; - }); - cm.doc.frontier = cm.doc.first; - startWorker(cm, 100); - cm.state.modeGen++; - if (cm.curOp) regChange(cm); - } - - function wrappingChanged(cm) { - if (cm.options.lineWrapping) { - addClass(cm.display.wrapper, "CodeMirror-wrap"); - cm.display.sizer.style.minWidth = ""; - cm.display.sizerWidth = null; - } else { - rmClass(cm.display.wrapper, "CodeMirror-wrap"); - findMaxLine(cm); - } - estimateLineHeights(cm); - regChange(cm); - clearCaches(cm); - setTimeout(function(){updateScrollbars(cm);}, 100); - } - - // Returns a function that estimates the height of a line, to use as - // first approximation until the line becomes visible (and is thus - // properly measurable). - function estimateHeight(cm) { - var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; - var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); - return function(line) { - if (lineIsHidden(cm.doc, line)) return 0; - - var widgetsHeight = 0; - if (line.widgets) for (var i = 0; i < line.widgets.length; i++) { - if (line.widgets[i].height) widgetsHeight += line.widgets[i].height; - } - - if (wrapping) - return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th; - else - return widgetsHeight + th; - }; - } - - function estimateLineHeights(cm) { - var doc = cm.doc, est = estimateHeight(cm); - doc.iter(function(line) { - var estHeight = est(line); - if (estHeight != line.height) updateLineHeight(line, estHeight); - }); - } - - function themeChanged(cm) { - cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + - cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); - clearCaches(cm); - } - - function guttersChanged(cm) { - updateGutters(cm); - regChange(cm); - setTimeout(function(){alignHorizontally(cm);}, 20); - } - - // Rebuild the gutter elements, ensure the margin to the left of the - // code matches their width. - function updateGutters(cm) { - var gutters = cm.display.gutters, specs = cm.options.gutters; - removeChildren(gutters); - for (var i = 0; i < specs.length; ++i) { - var gutterClass = specs[i]; - var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)); - if (gutterClass == "CodeMirror-linenumbers") { - cm.display.lineGutter = gElt; - gElt.style.width = (cm.display.lineNumWidth || 1) + "px"; - } - } - gutters.style.display = i ? "" : "none"; - updateGutterSpace(cm); - } - - function updateGutterSpace(cm) { - var width = cm.display.gutters.offsetWidth; - cm.display.sizer.style.marginLeft = width + "px"; - } - - // Compute the character length of a line, taking into account - // collapsed ranges (see markText) that might hide parts, and join - // other lines onto it. - function lineLength(line) { - if (line.height == 0) return 0; - var len = line.text.length, merged, cur = line; - while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(0, true); - cur = found.from.line; - len += found.from.ch - found.to.ch; - } - cur = line; - while (merged = collapsedSpanAtEnd(cur)) { - var found = merged.find(0, true); - len -= cur.text.length - found.from.ch; - cur = found.to.line; - len += cur.text.length - found.to.ch; - } - return len; - } - - // Find the longest line in the document. - function findMaxLine(cm) { - var d = cm.display, doc = cm.doc; - d.maxLine = getLine(doc, doc.first); - d.maxLineLength = lineLength(d.maxLine); - d.maxLineChanged = true; - doc.iter(function(line) { - var len = lineLength(line); - if (len > d.maxLineLength) { - d.maxLineLength = len; - d.maxLine = line; - } - }); - } - - // Make sure the gutters options contains the element - // "CodeMirror-linenumbers" when the lineNumbers option is true. - function setGuttersForLineNumbers(options) { - var found = indexOf(options.gutters, "CodeMirror-linenumbers"); - if (found == -1 && options.lineNumbers) { - options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]); - } else if (found > -1 && !options.lineNumbers) { - options.gutters = options.gutters.slice(0); - options.gutters.splice(found, 1); - } - } - - // SCROLLBARS - - // Prepare DOM reads needed to update the scrollbars. Done in one - // shot to minimize update/measure roundtrips. - function measureForScrollbars(cm) { - var d = cm.display, gutterW = d.gutters.offsetWidth; - var docH = Math.round(cm.doc.height + paddingVert(cm.display)); - return { - clientHeight: d.scroller.clientHeight, - viewHeight: d.wrapper.clientHeight, - scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, - viewWidth: d.wrapper.clientWidth, - barLeft: cm.options.fixedGutter ? gutterW : 0, - docHeight: docH, - scrollHeight: docH + scrollGap(cm) + d.barHeight, - nativeBarWidth: d.nativeBarWidth, - gutterWidth: gutterW - }; - } - - function NativeScrollbars(place, scroll, cm) { - this.cm = cm; - var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); - var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); - place(vert); place(horiz); - - on(vert, "scroll", function() { - if (vert.clientHeight) scroll(vert.scrollTop, "vertical"); - }); - on(horiz, "scroll", function() { - if (horiz.clientWidth) scroll(horiz.scrollLeft, "horizontal"); - }); - - this.checkedOverlay = false; - // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). - if (ie && ie_version < 8) this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; - } - - NativeScrollbars.prototype = copyObj({ - update: function(measure) { - var needsH = measure.scrollWidth > measure.clientWidth + 1; - var needsV = measure.scrollHeight > measure.clientHeight + 1; - var sWidth = measure.nativeBarWidth; - - if (needsV) { - this.vert.style.display = "block"; - this.vert.style.bottom = needsH ? sWidth + "px" : "0"; - var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); - // A bug in IE8 can cause this value to be negative, so guard it. - this.vert.firstChild.style.height = - Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; - } else { - this.vert.style.display = ""; - this.vert.firstChild.style.height = "0"; - } - - if (needsH) { - this.horiz.style.display = "block"; - this.horiz.style.right = needsV ? sWidth + "px" : "0"; - this.horiz.style.left = measure.barLeft + "px"; - var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); - this.horiz.firstChild.style.width = - (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; - } else { - this.horiz.style.display = ""; - this.horiz.firstChild.style.width = "0"; - } - - if (!this.checkedOverlay && measure.clientHeight > 0) { - if (sWidth == 0) this.overlayHack(); - this.checkedOverlay = true; - } - - return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}; - }, - setScrollLeft: function(pos) { - if (this.horiz.scrollLeft != pos) this.horiz.scrollLeft = pos; - }, - setScrollTop: function(pos) { - if (this.vert.scrollTop != pos) this.vert.scrollTop = pos; - }, - overlayHack: function() { - var w = mac && !mac_geMountainLion ? "12px" : "18px"; - this.horiz.style.minHeight = this.vert.style.minWidth = w; - var self = this; - var barMouseDown = function(e) { - if (e_target(e) != self.vert && e_target(e) != self.horiz) - operation(self.cm, onMouseDown)(e); - }; - on(this.vert, "mousedown", barMouseDown); - on(this.horiz, "mousedown", barMouseDown); - }, - clear: function() { - var parent = this.horiz.parentNode; - parent.removeChild(this.horiz); - parent.removeChild(this.vert); - } - }, NativeScrollbars.prototype); - - function NullScrollbars() {} - - NullScrollbars.prototype = copyObj({ - update: function() { return {bottom: 0, right: 0}; }, - setScrollLeft: function() {}, - setScrollTop: function() {}, - clear: function() {} - }, NullScrollbars.prototype); - - CodeMirror.scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; - - function initScrollbars(cm) { - if (cm.display.scrollbars) { - cm.display.scrollbars.clear(); - if (cm.display.scrollbars.addClass) - rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); - } - - cm.display.scrollbars = new CodeMirror.scrollbarModel[cm.options.scrollbarStyle](function(node) { - cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); - // Prevent clicks in the scrollbars from killing focus - on(node, "mousedown", function() { - if (cm.state.focused) setTimeout(function() { cm.display.input.focus(); }, 0); - }); - node.setAttribute("cm-not-content", "true"); - }, function(pos, axis) { - if (axis == "horizontal") setScrollLeft(cm, pos); - else setScrollTop(cm, pos); - }, cm); - if (cm.display.scrollbars.addClass) - addClass(cm.display.wrapper, cm.display.scrollbars.addClass); - } - - function updateScrollbars(cm, measure) { - if (!measure) measure = measureForScrollbars(cm); - var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; - updateScrollbarsInner(cm, measure); - for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { - if (startWidth != cm.display.barWidth && cm.options.lineWrapping) - updateHeightsInViewport(cm); - updateScrollbarsInner(cm, measureForScrollbars(cm)); - startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; - } - } - - // Re-synchronize the fake scrollbars with the actual size of the - // content. - function updateScrollbarsInner(cm, measure) { - var d = cm.display; - var sizes = d.scrollbars.update(measure); - - d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; - d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; - - if (sizes.right && sizes.bottom) { - d.scrollbarFiller.style.display = "block"; - d.scrollbarFiller.style.height = sizes.bottom + "px"; - d.scrollbarFiller.style.width = sizes.right + "px"; - } else d.scrollbarFiller.style.display = ""; - if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { - d.gutterFiller.style.display = "block"; - d.gutterFiller.style.height = sizes.bottom + "px"; - d.gutterFiller.style.width = measure.gutterWidth + "px"; - } else d.gutterFiller.style.display = ""; - } - - // Compute the lines that are visible in a given viewport (defaults - // the the current scroll position). viewport may contain top, - // height, and ensure (see op.scrollToPos) properties. - function visibleLines(display, doc, viewport) { - var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; - top = Math.floor(top - paddingTop(display)); - var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; - - var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); - // Ensure is a {from: {line, ch}, to: {line, ch}} object, and - // forces those lines into the viewport (if possible). - if (viewport && viewport.ensure) { - var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; - if (ensureFrom < from) { - from = ensureFrom; - to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); - } else if (Math.min(ensureTo, doc.lastLine()) >= to) { - from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); - to = ensureTo; - } - } - return {from: from, to: Math.max(to, from + 1)}; - } - - // LINE NUMBERS - - // Re-align line numbers and gutter marks to compensate for - // horizontal scrolling. - function alignHorizontally(cm) { - var display = cm.display, view = display.view; - if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) return; - var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; - var gutterW = display.gutters.offsetWidth, left = comp + "px"; - for (var i = 0; i < view.length; i++) if (!view[i].hidden) { - if (cm.options.fixedGutter && view[i].gutter) - view[i].gutter.style.left = left; - var align = view[i].alignable; - if (align) for (var j = 0; j < align.length; j++) - align[j].style.left = left; - } - if (cm.options.fixedGutter) - display.gutters.style.left = (comp + gutterW) + "px"; - } - - // Used to ensure that the line number gutter is still the right - // size for the current document size. Returns true when an update - // is needed. - function maybeUpdateLineNumberWidth(cm) { - if (!cm.options.lineNumbers) return false; - var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; - if (last.length != display.lineNumChars) { - var test = display.measure.appendChild(elt("div", [elt("div", last)], - "CodeMirror-linenumber CodeMirror-gutter-elt")); - var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; - display.lineGutter.style.width = ""; - display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; - display.lineNumWidth = display.lineNumInnerWidth + padding; - display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; - display.lineGutter.style.width = display.lineNumWidth + "px"; - updateGutterSpace(cm); - return true; - } - return false; - } - - function lineNumberFor(options, i) { - return String(options.lineNumberFormatter(i + options.firstLineNumber)); - } - - // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, - // but using getBoundingClientRect to get a sub-pixel-accurate - // result. - function compensateForHScroll(display) { - return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left; - } - - // DISPLAY DRAWING - - function DisplayUpdate(cm, viewport, force) { - var display = cm.display; - - this.viewport = viewport; - // Store some values that we'll need later (but don't want to force a relayout for) - this.visible = visibleLines(display, cm.doc, viewport); - this.editorIsHidden = !display.wrapper.offsetWidth; - this.wrapperHeight = display.wrapper.clientHeight; - this.wrapperWidth = display.wrapper.clientWidth; - this.oldDisplayWidth = displayWidth(cm); - this.force = force; - this.dims = getDimensions(cm); - this.events = []; - } - - DisplayUpdate.prototype.signal = function(emitter, type) { - if (hasHandler(emitter, type)) - this.events.push(arguments); - }; - DisplayUpdate.prototype.finish = function() { - for (var i = 0; i < this.events.length; i++) - signal.apply(null, this.events[i]); - }; - - function maybeClipScrollbars(cm) { - var display = cm.display; - if (!display.scrollbarsClipped && display.scroller.offsetWidth) { - display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; - display.heightForcer.style.height = scrollGap(cm) + "px"; - display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; - display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; - display.scrollbarsClipped = true; - } - } - - // Does the actual updating of the line display. Bails out - // (returning false) when there is nothing to be done and forced is - // false. - function updateDisplayIfNeeded(cm, update) { - var display = cm.display, doc = cm.doc; - - if (update.editorIsHidden) { - resetView(cm); - return false; - } - - // Bail out if the visible area is already rendered and nothing changed. - if (!update.force && - update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && - display.renderedView == display.view && countDirtyView(cm) == 0) - return false; - - if (maybeUpdateLineNumberWidth(cm)) { - resetView(cm); - update.dims = getDimensions(cm); - } - - // Compute a suitable new viewport (from & to) - var end = doc.first + doc.size; - var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); - var to = Math.min(end, update.visible.to + cm.options.viewportMargin); - if (display.viewFrom < from && from - display.viewFrom < 20) from = Math.max(doc.first, display.viewFrom); - if (display.viewTo > to && display.viewTo - to < 20) to = Math.min(end, display.viewTo); - if (sawCollapsedSpans) { - from = visualLineNo(cm.doc, from); - to = visualLineEndNo(cm.doc, to); - } - - var different = from != display.viewFrom || to != display.viewTo || - display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; - adjustView(cm, from, to); - - display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); - // Position the mover div to align with the current scroll position - cm.display.mover.style.top = display.viewOffset + "px"; - - var toUpdate = countDirtyView(cm); - if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) - return false; - - // For big changes, we hide the enclosing element during the - // update, since that speeds up the operations on most browsers. - var focused = activeElt(); - if (toUpdate > 4) display.lineDiv.style.display = "none"; - patchDisplay(cm, display.updateLineNumbers, update.dims); - if (toUpdate > 4) display.lineDiv.style.display = ""; - display.renderedView = display.view; - // There might have been a widget with a focused element that got - // hidden or updated, if so re-focus it. - if (focused && activeElt() != focused && focused.offsetHeight) focused.focus(); - - // Prevent selection and cursors from interfering with the scroll - // width and height. - removeChildren(display.cursorDiv); - removeChildren(display.selectionDiv); - display.gutters.style.height = display.sizer.style.minHeight = 0; - - if (different) { - display.lastWrapHeight = update.wrapperHeight; - display.lastWrapWidth = update.wrapperWidth; - startWorker(cm, 400); - } - - display.updateLineNumbers = null; - - return true; - } - - function postUpdateDisplay(cm, update) { - var viewport = update.viewport; - for (var first = true;; first = false) { - if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { - // Clip forced viewport to actual scrollable area. - if (viewport && viewport.top != null) - viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; - // Updated line heights might result in the drawn area not - // actually covering the viewport. Keep looping until it does. - update.visible = visibleLines(cm.display, cm.doc, viewport); - if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) - break; - } - if (!updateDisplayIfNeeded(cm, update)) break; - updateHeightsInViewport(cm); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - setDocumentHeight(cm, barMeasure); - updateScrollbars(cm, barMeasure); - } - - update.signal(cm, "update", cm); - if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { - update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); - cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; - } - } - - function updateDisplaySimple(cm, viewport) { - var update = new DisplayUpdate(cm, viewport); - if (updateDisplayIfNeeded(cm, update)) { - updateHeightsInViewport(cm); - postUpdateDisplay(cm, update); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - setDocumentHeight(cm, barMeasure); - updateScrollbars(cm, barMeasure); - update.finish(); - } - } - - function setDocumentHeight(cm, measure) { - cm.display.sizer.style.minHeight = measure.docHeight + "px"; - var total = measure.docHeight + cm.display.barHeight; - cm.display.heightForcer.style.top = total + "px"; - cm.display.gutters.style.height = Math.max(total + scrollGap(cm), measure.clientHeight) + "px"; - } - - // Read the actual heights of the rendered lines, and update their - // stored heights to match. - function updateHeightsInViewport(cm) { - var display = cm.display; - var prevBottom = display.lineDiv.offsetTop; - for (var i = 0; i < display.view.length; i++) { - var cur = display.view[i], height; - if (cur.hidden) continue; - if (ie && ie_version < 8) { - var bot = cur.node.offsetTop + cur.node.offsetHeight; - height = bot - prevBottom; - prevBottom = bot; - } else { - var box = cur.node.getBoundingClientRect(); - height = box.bottom - box.top; - } - var diff = cur.line.height - height; - if (height < 2) height = textHeight(display); - if (diff > .001 || diff < -.001) { - updateLineHeight(cur.line, height); - updateWidgetHeight(cur.line); - if (cur.rest) for (var j = 0; j < cur.rest.length; j++) - updateWidgetHeight(cur.rest[j]); - } - } - } - - // Read and store the height of line widgets associated with the - // given line. - function updateWidgetHeight(line) { - if (line.widgets) for (var i = 0; i < line.widgets.length; ++i) - line.widgets[i].height = line.widgets[i].node.offsetHeight; - } - - // Do a bulk-read of the DOM positions and sizes needed to draw the - // view, so that we don't interleave reading and writing to the DOM. - function getDimensions(cm) { - var d = cm.display, left = {}, width = {}; - var gutterLeft = d.gutters.clientLeft; - for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { - left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft; - width[cm.options.gutters[i]] = n.clientWidth; - } - return {fixedPos: compensateForHScroll(d), - gutterTotalWidth: d.gutters.offsetWidth, - gutterLeft: left, - gutterWidth: width, - wrapperWidth: d.wrapper.clientWidth}; - } - - // Sync the actual display DOM structure with display.view, removing - // nodes for lines that are no longer in view, and creating the ones - // that are not there yet, and updating the ones that are out of - // date. - function patchDisplay(cm, updateNumbersFrom, dims) { - var display = cm.display, lineNumbers = cm.options.lineNumbers; - var container = display.lineDiv, cur = container.firstChild; - - function rm(node) { - var next = node.nextSibling; - // Works around a throw-scroll bug in OS X Webkit - if (webkit && mac && cm.display.currentWheelTarget == node) - node.style.display = "none"; - else - node.parentNode.removeChild(node); - return next; - } - - var view = display.view, lineN = display.viewFrom; - // Loop over the elements in the view, syncing cur (the DOM nodes - // in display.lineDiv) with the view as we go. - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (lineView.hidden) { - } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet - var node = buildLineElement(cm, lineView, lineN, dims); - container.insertBefore(node, cur); - } else { // Already drawn - while (cur != lineView.node) cur = rm(cur); - var updateNumber = lineNumbers && updateNumbersFrom != null && - updateNumbersFrom <= lineN && lineView.lineNumber; - if (lineView.changes) { - if (indexOf(lineView.changes, "gutter") > -1) updateNumber = false; - updateLineForChanges(cm, lineView, lineN, dims); - } - if (updateNumber) { - removeChildren(lineView.lineNumber); - lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); - } - cur = lineView.node.nextSibling; - } - lineN += lineView.size; - } - while (cur) cur = rm(cur); - } - - // When an aspect of a line changes, a string is added to - // lineView.changes. This updates the relevant part of the line's - // DOM structure. - function updateLineForChanges(cm, lineView, lineN, dims) { - for (var j = 0; j < lineView.changes.length; j++) { - var type = lineView.changes[j]; - if (type == "text") updateLineText(cm, lineView); - else if (type == "gutter") updateLineGutter(cm, lineView, lineN, dims); - else if (type == "class") updateLineClasses(lineView); - else if (type == "widget") updateLineWidgets(cm, lineView, dims); - } - lineView.changes = null; - } - - // Lines with gutter elements, widgets or a background class need to - // be wrapped, and have the extra elements added to the wrapper div - function ensureLineWrapped(lineView) { - if (lineView.node == lineView.text) { - lineView.node = elt("div", null, null, "position: relative"); - if (lineView.text.parentNode) - lineView.text.parentNode.replaceChild(lineView.node, lineView.text); - lineView.node.appendChild(lineView.text); - if (ie && ie_version < 8) lineView.node.style.zIndex = 2; - } - return lineView.node; - } - - function updateLineBackground(lineView) { - var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; - if (cls) cls += " CodeMirror-linebackground"; - if (lineView.background) { - if (cls) lineView.background.className = cls; - else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } - } else if (cls) { - var wrap = ensureLineWrapped(lineView); - lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); - } - } - - // Wrapper around buildLineContent which will reuse the structure - // in display.externalMeasured when possible. - function getLineContent(cm, lineView) { - var ext = cm.display.externalMeasured; - if (ext && ext.line == lineView.line) { - cm.display.externalMeasured = null; - lineView.measure = ext.measure; - return ext.built; - } - return buildLineContent(cm, lineView); - } - - // Redraw the line's text. Interacts with the background and text - // classes because the mode may output tokens that influence these - // classes. - function updateLineText(cm, lineView) { - var cls = lineView.text.className; - var built = getLineContent(cm, lineView); - if (lineView.text == lineView.node) lineView.node = built.pre; - lineView.text.parentNode.replaceChild(built.pre, lineView.text); - lineView.text = built.pre; - if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { - lineView.bgClass = built.bgClass; - lineView.textClass = built.textClass; - updateLineClasses(lineView); - } else if (cls) { - lineView.text.className = cls; - } - } - - function updateLineClasses(lineView) { - updateLineBackground(lineView); - if (lineView.line.wrapClass) - ensureLineWrapped(lineView).className = lineView.line.wrapClass; - else if (lineView.node != lineView.text) - lineView.node.className = ""; - var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; - lineView.text.className = textClass || ""; - } - - function updateLineGutter(cm, lineView, lineN, dims) { - if (lineView.gutter) { - lineView.node.removeChild(lineView.gutter); - lineView.gutter = null; - } - if (lineView.gutterBackground) { - lineView.node.removeChild(lineView.gutterBackground); - lineView.gutterBackground = null; - } - if (lineView.line.gutterClass) { - var wrap = ensureLineWrapped(lineView); - lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, - "left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + - "px; width: " + dims.gutterTotalWidth + "px"); - wrap.insertBefore(lineView.gutterBackground, lineView.text); - } - var markers = lineView.line.gutterMarkers; - if (cm.options.lineNumbers || markers) { - var wrap = ensureLineWrapped(lineView); - var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", "left: " + - (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"); - cm.display.input.setUneditable(gutterWrap); - wrap.insertBefore(gutterWrap, lineView.text); - if (lineView.line.gutterClass) - gutterWrap.className += " " + lineView.line.gutterClass; - if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) - lineView.lineNumber = gutterWrap.appendChild( - elt("div", lineNumberFor(cm.options, lineN), - "CodeMirror-linenumber CodeMirror-gutter-elt", - "left: " + dims.gutterLeft["CodeMirror-linenumbers"] + "px; width: " - + cm.display.lineNumInnerWidth + "px")); - if (markers) for (var k = 0; k < cm.options.gutters.length; ++k) { - var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]; - if (found) - gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", "left: " + - dims.gutterLeft[id] + "px; width: " + dims.gutterWidth[id] + "px")); - } - } - } - - function updateLineWidgets(cm, lineView, dims) { - if (lineView.alignable) lineView.alignable = null; - for (var node = lineView.node.firstChild, next; node; node = next) { - var next = node.nextSibling; - if (node.className == "CodeMirror-linewidget") - lineView.node.removeChild(node); - } - insertLineWidgets(cm, lineView, dims); - } - - // Build a line's DOM representation from scratch - function buildLineElement(cm, lineView, lineN, dims) { - var built = getLineContent(cm, lineView); - lineView.text = lineView.node = built.pre; - if (built.bgClass) lineView.bgClass = built.bgClass; - if (built.textClass) lineView.textClass = built.textClass; - - updateLineClasses(lineView); - updateLineGutter(cm, lineView, lineN, dims); - insertLineWidgets(cm, lineView, dims); - return lineView.node; - } - - // A lineView may contain multiple logical lines (when merged by - // collapsed spans). The widgets for all of them need to be drawn. - function insertLineWidgets(cm, lineView, dims) { - insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); - if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) - insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); - } - - function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { - if (!line.widgets) return; - var wrap = ensureLineWrapped(lineView); - for (var i = 0, ws = line.widgets; i < ws.length; ++i) { - var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget"); - if (!widget.handleMouseEvents) node.setAttribute("cm-ignore-events", "true"); - positionLineWidget(widget, node, lineView, dims); - cm.display.input.setUneditable(node); - if (allowAbove && widget.above) - wrap.insertBefore(node, lineView.gutter || lineView.text); - else - wrap.appendChild(node); - signalLater(widget, "redraw"); - } - } - - function positionLineWidget(widget, node, lineView, dims) { - if (widget.noHScroll) { - (lineView.alignable || (lineView.alignable = [])).push(node); - var width = dims.wrapperWidth; - node.style.left = dims.fixedPos + "px"; - if (!widget.coverGutter) { - width -= dims.gutterTotalWidth; - node.style.paddingLeft = dims.gutterTotalWidth + "px"; - } - node.style.width = width + "px"; - } - if (widget.coverGutter) { - node.style.zIndex = 5; - node.style.position = "relative"; - if (!widget.noHScroll) node.style.marginLeft = -dims.gutterTotalWidth + "px"; - } - } - - // POSITION OBJECT - - // A Pos instance represents a position within the text. - var Pos = CodeMirror.Pos = function(line, ch) { - if (!(this instanceof Pos)) return new Pos(line, ch); - this.line = line; this.ch = ch; - }; - - // Compare two positions, return 0 if they are the same, a negative - // number when a is less, and a positive number otherwise. - var cmp = CodeMirror.cmpPos = function(a, b) { return a.line - b.line || a.ch - b.ch; }; - - function copyPos(x) {return Pos(x.line, x.ch);} - function maxPos(a, b) { return cmp(a, b) < 0 ? b : a; } - function minPos(a, b) { return cmp(a, b) < 0 ? a : b; } - - // INPUT HANDLING - - function ensureFocus(cm) { - if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); } - } - - function isReadOnly(cm) { - return cm.options.readOnly || cm.doc.cantEdit; - } - - // This will be set to an array of strings when copying, so that, - // when pasting, we know what kind of selections the copied text - // was made out of. - var lastCopied = null; - - function applyTextInput(cm, inserted, deleted, sel, origin) { - var doc = cm.doc; - cm.display.shift = false; - if (!sel) sel = doc.sel; - - var paste = cm.state.pasteIncoming || origin == "paste"; - var textLines = doc.splitLines(inserted), multiPaste = null; - // When pasing N lines into N selections, insert one line per selection - if (paste && sel.ranges.length > 1) { - if (lastCopied && lastCopied.join("\n") == inserted) { - if (sel.ranges.length % lastCopied.length == 0) { - multiPaste = []; - for (var i = 0; i < lastCopied.length; i++) - multiPaste.push(doc.splitLines(lastCopied[i])); - } - } else if (textLines.length == sel.ranges.length) { - multiPaste = map(textLines, function(l) { return [l]; }); - } - } - - // Normal behavior is to insert the new text into every selection - for (var i = sel.ranges.length - 1; i >= 0; i--) { - var range = sel.ranges[i]; - var from = range.from(), to = range.to(); - if (range.empty()) { - if (deleted && deleted > 0) // Handle deletion - from = Pos(from.line, from.ch - deleted); - else if (cm.state.overwrite && !paste) // Handle overwrite - to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); - } - var updateInput = cm.curOp.updateInput; - var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i % multiPaste.length] : textLines, - origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}; - makeChange(cm.doc, changeEvent); - signalLater(cm, "inputRead", cm, changeEvent); - } - if (inserted && !paste) - triggerElectric(cm, inserted); - - ensureCursorVisible(cm); - cm.curOp.updateInput = updateInput; - cm.curOp.typing = true; - cm.state.pasteIncoming = cm.state.cutIncoming = false; - } - - function handlePaste(e, cm) { - var pasted = e.clipboardData && e.clipboardData.getData("text/plain"); - if (pasted) { - e.preventDefault(); - if (!isReadOnly(cm) && !cm.options.disableInput) - runInOp(cm, function() { applyTextInput(cm, pasted, 0, null, "paste"); }); - return true; - } - } - - function triggerElectric(cm, inserted) { - // When an 'electric' character is inserted, immediately trigger a reindent - if (!cm.options.electricChars || !cm.options.smartIndent) return; - var sel = cm.doc.sel; - - for (var i = sel.ranges.length - 1; i >= 0; i--) { - var range = sel.ranges[i]; - if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) continue; - var mode = cm.getModeAt(range.head); - var indented = false; - if (mode.electricChars) { - for (var j = 0; j < mode.electricChars.length; j++) - if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { - indented = indentLine(cm, range.head.line, "smart"); - break; - } - } else if (mode.electricInput) { - if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) - indented = indentLine(cm, range.head.line, "smart"); - } - if (indented) signalLater(cm, "electricInput", cm, range.head.line); - } - } - - function copyableRanges(cm) { - var text = [], ranges = []; - for (var i = 0; i < cm.doc.sel.ranges.length; i++) { - var line = cm.doc.sel.ranges[i].head.line; - var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; - ranges.push(lineRange); - text.push(cm.getRange(lineRange.anchor, lineRange.head)); - } - return {text: text, ranges: ranges}; - } - - function disableBrowserMagic(field) { - field.setAttribute("autocorrect", "off"); - field.setAttribute("autocapitalize", "off"); - field.setAttribute("spellcheck", "false"); - } - - // TEXTAREA INPUT STYLE - - function TextareaInput(cm) { - this.cm = cm; - // See input.poll and input.reset - this.prevInput = ""; - - // Flag that indicates whether we expect input to appear real soon - // now (after some event like 'keypress' or 'input') and are - // polling intensively. - this.pollingFast = false; - // Self-resetting timeout for the poller - this.polling = new Delayed(); - // Tracks when input.reset has punted to just putting a short - // string into the textarea instead of the full selection. - this.inaccurateSelection = false; - // Used to work around IE issue with selection being forgotten when focus moves away from textarea - this.hasSelection = false; - this.composing = null; - }; - - function hiddenTextarea() { - var te = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em; outline: none"); - var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); - // The textarea is kept positioned near the cursor to prevent the - // fact that it'll be scrolled into view on input from scrolling - // our fake cursor out of view. On webkit, when wrap=off, paste is - // very slow. So make the area wide instead. - if (webkit) te.style.width = "1000px"; - else te.setAttribute("wrap", "off"); - // If border: 0; -- iOS fails to open keyboard (issue #1287) - if (ios) te.style.border = "1px solid black"; - disableBrowserMagic(te); - return div; - } - - TextareaInput.prototype = copyObj({ - init: function(display) { - var input = this, cm = this.cm; - - // Wraps and hides input textarea - var div = this.wrapper = hiddenTextarea(); - // The semihidden textarea that is focused when the editor is - // focused, and receives input. - var te = this.textarea = div.firstChild; - display.wrapper.insertBefore(div, display.wrapper.firstChild); - - // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) - if (ios) te.style.width = "0px"; - - on(te, "input", function() { - if (ie && ie_version >= 9 && input.hasSelection) input.hasSelection = null; - input.poll(); - }); - - on(te, "paste", function(e) { - if (handlePaste(e, cm)) return true; - - cm.state.pasteIncoming = true; - input.fastPoll(); - }); - - function prepareCopyCut(e) { - if (cm.somethingSelected()) { - lastCopied = cm.getSelections(); - if (input.inaccurateSelection) { - input.prevInput = ""; - input.inaccurateSelection = false; - te.value = lastCopied.join("\n"); - selectInput(te); - } - } else if (!cm.options.lineWiseCopyCut) { - return; - } else { - var ranges = copyableRanges(cm); - lastCopied = ranges.text; - if (e.type == "cut") { - cm.setSelections(ranges.ranges, null, sel_dontScroll); - } else { - input.prevInput = ""; - te.value = ranges.text.join("\n"); - selectInput(te); - } - } - if (e.type == "cut") cm.state.cutIncoming = true; - } - on(te, "cut", prepareCopyCut); - on(te, "copy", prepareCopyCut); - - on(display.scroller, "paste", function(e) { - if (eventInWidget(display, e)) return; - cm.state.pasteIncoming = true; - input.focus(); - }); - - // Prevent normal selection in the editor (we handle our own) - on(display.lineSpace, "selectstart", function(e) { - if (!eventInWidget(display, e)) e_preventDefault(e); - }); - - on(te, "compositionstart", function() { - var start = cm.getCursor("from"); - if (input.composing) input.composing.range.clear() - input.composing = { - start: start, - range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) - }; - }); - on(te, "compositionend", function() { - if (input.composing) { - input.poll(); - input.composing.range.clear(); - input.composing = null; - } - }); - }, - - prepareSelection: function() { - // Redraw the selection and/or cursor - var cm = this.cm, display = cm.display, doc = cm.doc; - var result = prepareSelection(cm); - - // Move the hidden textarea near the cursor to prevent scrolling artifacts - if (cm.options.moveInputWithCursor) { - var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); - var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); - result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, - headPos.top + lineOff.top - wrapOff.top)); - result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, - headPos.left + lineOff.left - wrapOff.left)); - } - - return result; - }, - - showSelection: function(drawn) { - var cm = this.cm, display = cm.display; - removeChildrenAndAdd(display.cursorDiv, drawn.cursors); - removeChildrenAndAdd(display.selectionDiv, drawn.selection); - if (drawn.teTop != null) { - this.wrapper.style.top = drawn.teTop + "px"; - this.wrapper.style.left = drawn.teLeft + "px"; - } - }, - - // Reset the input to correspond to the selection (or to be empty, - // when not typing and nothing is selected) - reset: function(typing) { - if (this.contextMenuPending) return; - var minimal, selected, cm = this.cm, doc = cm.doc; - if (cm.somethingSelected()) { - this.prevInput = ""; - var range = doc.sel.primary(); - minimal = hasCopyEvent && - (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000); - var content = minimal ? "-" : selected || cm.getSelection(); - this.textarea.value = content; - if (cm.state.focused) selectInput(this.textarea); - if (ie && ie_version >= 9) this.hasSelection = content; - } else if (!typing) { - this.prevInput = this.textarea.value = ""; - if (ie && ie_version >= 9) this.hasSelection = null; - } - this.inaccurateSelection = minimal; - }, - - getField: function() { return this.textarea; }, - - supportsTouch: function() { return false; }, - - focus: function() { - if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { - try { this.textarea.focus(); } - catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM - } - }, - - blur: function() { this.textarea.blur(); }, - - resetPosition: function() { - this.wrapper.style.top = this.wrapper.style.left = 0; - }, - - receivedFocus: function() { this.slowPoll(); }, - - // Poll for input changes, using the normal rate of polling. This - // runs as long as the editor is focused. - slowPoll: function() { - var input = this; - if (input.pollingFast) return; - input.polling.set(this.cm.options.pollInterval, function() { - input.poll(); - if (input.cm.state.focused) input.slowPoll(); - }); - }, - - // When an event has just come in that is likely to add or change - // something in the input textarea, we poll faster, to ensure that - // the change appears on the screen quickly. - fastPoll: function() { - var missed = false, input = this; - input.pollingFast = true; - function p() { - var changed = input.poll(); - if (!changed && !missed) {missed = true; input.polling.set(60, p);} - else {input.pollingFast = false; input.slowPoll();} - } - input.polling.set(20, p); - }, - - // Read input from the textarea, and update the document to match. - // When something is selected, it is present in the textarea, and - // selected (unless it is huge, in which case a placeholder is - // used). When nothing is selected, the cursor sits after previously - // seen text (can be empty), which is stored in prevInput (we must - // not reset the textarea when typing, because that breaks IME). - poll: function() { - var cm = this.cm, input = this.textarea, prevInput = this.prevInput; - // Since this is called a *lot*, try to bail out as cheaply as - // possible when it is clear that nothing happened. hasSelection - // will be the case when there is a lot of text in the textarea, - // in which case reading its value would be expensive. - if (this.contextMenuPending || !cm.state.focused || - (hasSelection(input) && !prevInput && !this.composing) || - isReadOnly(cm) || cm.options.disableInput || cm.state.keySeq) - return false; - - var text = input.value; - // If nothing changed, bail. - if (text == prevInput && !cm.somethingSelected()) return false; - // Work around nonsensical selection resetting in IE9/10, and - // inexplicable appearance of private area unicode characters on - // some key combos in Mac (#2689). - if (ie && ie_version >= 9 && this.hasSelection === text || - mac && /[\uf700-\uf7ff]/.test(text)) { - cm.display.input.reset(); - return false; - } - - if (cm.doc.sel == cm.display.selForContextMenu) { - var first = text.charCodeAt(0); - if (first == 0x200b && !prevInput) prevInput = "\u200b"; - if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo"); } - } - // Find the part of the input that is actually new - var same = 0, l = Math.min(prevInput.length, text.length); - while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) ++same; - - var self = this; - runInOp(cm, function() { - applyTextInput(cm, text.slice(same), prevInput.length - same, - null, self.composing ? "*compose" : null); - - // Don't leave long text in the textarea, since it makes further polling slow - if (text.length > 1000 || text.indexOf("\n") > -1) input.value = self.prevInput = ""; - else self.prevInput = text; - - if (self.composing) { - self.composing.range.clear(); - self.composing.range = cm.markText(self.composing.start, cm.getCursor("to"), - {className: "CodeMirror-composing"}); - } - }); - return true; - }, - - ensurePolled: function() { - if (this.pollingFast && this.poll()) this.pollingFast = false; - }, - - onKeyPress: function() { - if (ie && ie_version >= 9) this.hasSelection = null; - this.fastPoll(); - }, - - onContextMenu: function(e) { - var input = this, cm = input.cm, display = cm.display, te = input.textarea; - var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; - if (!pos || presto) return; // Opera is difficult. - - // Reset the current text selection only if the click is done outside of the selection - // and 'resetSelectionOnContextMenu' option is true. - var reset = cm.options.resetSelectionOnContextMenu; - if (reset && cm.doc.sel.contains(pos) == -1) - operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); - - var oldCSS = te.style.cssText; - input.wrapper.style.position = "absolute"; - te.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + - "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: " + - (ie ? "rgba(255, 255, 255, .05)" : "transparent") + - "; outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; - if (webkit) var oldScrollY = window.scrollY; // Work around Chrome issue (#2712) - display.input.focus(); - if (webkit) window.scrollTo(null, oldScrollY); - display.input.reset(); - // Adds "Select all" to context menu in FF - if (!cm.somethingSelected()) te.value = input.prevInput = " "; - input.contextMenuPending = true; - display.selForContextMenu = cm.doc.sel; - clearTimeout(display.detectingSelectAll); - - // Select-all will be greyed out if there's nothing to select, so - // this adds a zero-width space so that we can later check whether - // it got selected. - function prepareSelectAllHack() { - if (te.selectionStart != null) { - var selected = cm.somethingSelected(); - var extval = "\u200b" + (selected ? te.value : ""); - te.value = "\u21da"; // Used to catch context-menu undo - te.value = extval; - input.prevInput = selected ? "" : "\u200b"; - te.selectionStart = 1; te.selectionEnd = extval.length; - // Re-set this, in case some other handler touched the - // selection in the meantime. - display.selForContextMenu = cm.doc.sel; - } - } - function rehide() { - input.contextMenuPending = false; - input.wrapper.style.position = "relative"; - te.style.cssText = oldCSS; - if (ie && ie_version < 9) display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); - - // Try to detect the user choosing select-all - if (te.selectionStart != null) { - if (!ie || (ie && ie_version < 9)) prepareSelectAllHack(); - var i = 0, poll = function() { - if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && - te.selectionEnd > 0 && input.prevInput == "\u200b") - operation(cm, commands.selectAll)(cm); - else if (i++ < 10) display.detectingSelectAll = setTimeout(poll, 500); - else display.input.reset(); - }; - display.detectingSelectAll = setTimeout(poll, 200); - } - } - - if (ie && ie_version >= 9) prepareSelectAllHack(); - if (captureRightClick) { - e_stop(e); - var mouseup = function() { - off(window, "mouseup", mouseup); - setTimeout(rehide, 20); - }; - on(window, "mouseup", mouseup); - } else { - setTimeout(rehide, 50); - } - }, - - readOnlyChanged: function(val) { - if (!val) this.reset(); - }, - - setUneditable: nothing, - - needsContentAttribute: false - }, TextareaInput.prototype); - - // CONTENTEDITABLE INPUT STYLE - - function ContentEditableInput(cm) { - this.cm = cm; - this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; - this.polling = new Delayed(); - this.gracePeriod = false; - } - - ContentEditableInput.prototype = copyObj({ - init: function(display) { - var input = this, cm = input.cm; - var div = input.div = display.lineDiv; - disableBrowserMagic(div); - - on(div, "paste", function(e) { handlePaste(e, cm); }) - - on(div, "compositionstart", function(e) { - var data = e.data; - input.composing = {sel: cm.doc.sel, data: data, startData: data}; - if (!data) return; - var prim = cm.doc.sel.primary(); - var line = cm.getLine(prim.head.line); - var found = line.indexOf(data, Math.max(0, prim.head.ch - data.length)); - if (found > -1 && found <= prim.head.ch) - input.composing.sel = simpleSelection(Pos(prim.head.line, found), - Pos(prim.head.line, found + data.length)); - }); - on(div, "compositionupdate", function(e) { - input.composing.data = e.data; - }); - on(div, "compositionend", function(e) { - var ours = input.composing; - if (!ours) return; - if (e.data != ours.startData && !/\u200b/.test(e.data)) - ours.data = e.data; - // Need a small delay to prevent other code (input event, - // selection polling) from doing damage when fired right after - // compositionend. - setTimeout(function() { - if (!ours.handled) - input.applyComposition(ours); - if (input.composing == ours) - input.composing = null; - }, 50); - }); - - on(div, "touchstart", function() { - input.forceCompositionEnd(); - }); - - on(div, "input", function() { - if (input.composing) return; - if (isReadOnly(cm) || !input.pollContent()) - runInOp(input.cm, function() {regChange(cm);}); - }); - - function onCopyCut(e) { - if (cm.somethingSelected()) { - lastCopied = cm.getSelections(); - if (e.type == "cut") cm.replaceSelection("", null, "cut"); - } else if (!cm.options.lineWiseCopyCut) { - return; - } else { - var ranges = copyableRanges(cm); - lastCopied = ranges.text; - if (e.type == "cut") { - cm.operation(function() { - cm.setSelections(ranges.ranges, 0, sel_dontScroll); - cm.replaceSelection("", null, "cut"); - }); - } - } - // iOS exposes the clipboard API, but seems to discard content inserted into it - if (e.clipboardData && !ios) { - e.preventDefault(); - e.clipboardData.clearData(); - e.clipboardData.setData("text/plain", lastCopied.join("\n")); - } else { - // Old-fashioned briefly-focus-a-textarea hack - var kludge = hiddenTextarea(), te = kludge.firstChild; - cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); - te.value = lastCopied.join("\n"); - var hadFocus = document.activeElement; - selectInput(te); - setTimeout(function() { - cm.display.lineSpace.removeChild(kludge); - hadFocus.focus(); - }, 50); - } - } - on(div, "copy", onCopyCut); - on(div, "cut", onCopyCut); - }, - - prepareSelection: function() { - var result = prepareSelection(this.cm, false); - result.focus = this.cm.state.focused; - return result; - }, - - showSelection: function(info) { - if (!info || !this.cm.display.view.length) return; - if (info.focus) this.showPrimarySelection(); - this.showMultipleSelections(info); - }, - - showPrimarySelection: function() { - var sel = window.getSelection(), prim = this.cm.doc.sel.primary(); - var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset); - var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset); - if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && - cmp(minPos(curAnchor, curFocus), prim.from()) == 0 && - cmp(maxPos(curAnchor, curFocus), prim.to()) == 0) - return; - - var start = posToDOM(this.cm, prim.from()); - var end = posToDOM(this.cm, prim.to()); - if (!start && !end) return; - - var view = this.cm.display.view; - var old = sel.rangeCount && sel.getRangeAt(0); - if (!start) { - start = {node: view[0].measure.map[2], offset: 0}; - } else if (!end) { // FIXME dangerously hacky - var measure = view[view.length - 1].measure; - var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; - end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; - } - - try { var rng = range(start.node, start.offset, end.offset, end.node); } - catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible - if (rng) { - sel.removeAllRanges(); - sel.addRange(rng); - if (old && sel.anchorNode == null) sel.addRange(old); - else if (gecko) this.startGracePeriod(); - } - this.rememberSelection(); - }, - - startGracePeriod: function() { - var input = this; - clearTimeout(this.gracePeriod); - this.gracePeriod = setTimeout(function() { - input.gracePeriod = false; - if (input.selectionChanged()) - input.cm.operation(function() { input.cm.curOp.selectionChanged = true; }); - }, 20); - }, - - showMultipleSelections: function(info) { - removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); - removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); - }, - - rememberSelection: function() { - var sel = window.getSelection(); - this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; - this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; - }, - - selectionInEditor: function() { - var sel = window.getSelection(); - if (!sel.rangeCount) return false; - var node = sel.getRangeAt(0).commonAncestorContainer; - return contains(this.div, node); - }, - - focus: function() { - if (this.cm.options.readOnly != "nocursor") this.div.focus(); - }, - blur: function() { this.div.blur(); }, - getField: function() { return this.div; }, - - supportsTouch: function() { return true; }, - - receivedFocus: function() { - var input = this; - if (this.selectionInEditor()) - this.pollSelection(); - else - runInOp(this.cm, function() { input.cm.curOp.selectionChanged = true; }); - - function poll() { - if (input.cm.state.focused) { - input.pollSelection(); - input.polling.set(input.cm.options.pollInterval, poll); - } - } - this.polling.set(this.cm.options.pollInterval, poll); - }, - - selectionChanged: function() { - var sel = window.getSelection(); - return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || - sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset; - }, - - pollSelection: function() { - if (!this.composing && !this.gracePeriod && this.selectionChanged()) { - var sel = window.getSelection(), cm = this.cm; - this.rememberSelection(); - var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); - var head = domToPos(cm, sel.focusNode, sel.focusOffset); - if (anchor && head) runInOp(cm, function() { - setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); - if (anchor.bad || head.bad) cm.curOp.selectionChanged = true; - }); - } - }, - - pollContent: function() { - var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); - var from = sel.from(), to = sel.to(); - if (from.line < display.viewFrom || to.line > display.viewTo - 1) return false; - - var fromIndex; - if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { - var fromLine = lineNo(display.view[0].line); - var fromNode = display.view[0].node; - } else { - var fromLine = lineNo(display.view[fromIndex].line); - var fromNode = display.view[fromIndex - 1].node.nextSibling; - } - var toIndex = findViewIndex(cm, to.line); - if (toIndex == display.view.length - 1) { - var toLine = display.viewTo - 1; - var toNode = display.lineDiv.lastChild; - } else { - var toLine = lineNo(display.view[toIndex + 1].line) - 1; - var toNode = display.view[toIndex + 1].node.previousSibling; - } - - var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); - var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); - while (newText.length > 1 && oldText.length > 1) { - if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } - else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } - else break; - } - - var cutFront = 0, cutEnd = 0; - var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); - while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) - ++cutFront; - var newBot = lst(newText), oldBot = lst(oldText); - var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), - oldBot.length - (oldText.length == 1 ? cutFront : 0)); - while (cutEnd < maxCutEnd && - newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) - ++cutEnd; - - newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd); - newText[0] = newText[0].slice(cutFront); - - var chFrom = Pos(fromLine, cutFront); - var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); - if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { - replaceRange(cm.doc, newText, chFrom, chTo, "+input"); - return true; - } - }, - - ensurePolled: function() { - this.forceCompositionEnd(); - }, - reset: function() { - this.forceCompositionEnd(); - }, - forceCompositionEnd: function() { - if (!this.composing || this.composing.handled) return; - this.applyComposition(this.composing); - this.composing.handled = true; - this.div.blur(); - this.div.focus(); - }, - applyComposition: function(composing) { - if (isReadOnly(this.cm)) - operation(this.cm, regChange)(this.cm) - else if (composing.data && composing.data != composing.startData) - operation(this.cm, applyTextInput)(this.cm, composing.data, 0, composing.sel); - }, - - setUneditable: function(node) { - node.contentEditable = "false" - }, - - onKeyPress: function(e) { - e.preventDefault(); - if (!isReadOnly(this.cm)) - operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); - }, - - readOnlyChanged: function(val) { - this.div.contentEditable = String(val != "nocursor") - }, - - onContextMenu: nothing, - resetPosition: nothing, - - needsContentAttribute: true - }, ContentEditableInput.prototype); - - function posToDOM(cm, pos) { - var view = findViewForLine(cm, pos.line); - if (!view || view.hidden) return null; - var line = getLine(cm.doc, pos.line); - var info = mapFromLineView(view, line, pos.line); - - var order = getOrder(line), side = "left"; - if (order) { - var partPos = getBidiPartAt(order, pos.ch); - side = partPos % 2 ? "right" : "left"; - } - var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); - result.offset = result.collapse == "right" ? result.end : result.start; - return result; - } - - function badPos(pos, bad) { if (bad) pos.bad = true; return pos; } - - function domToPos(cm, node, offset) { - var lineNode; - if (node == cm.display.lineDiv) { - lineNode = cm.display.lineDiv.childNodes[offset]; - if (!lineNode) return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true); - node = null; offset = 0; - } else { - for (lineNode = node;; lineNode = lineNode.parentNode) { - if (!lineNode || lineNode == cm.display.lineDiv) return null; - if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) break; - } - } - for (var i = 0; i < cm.display.view.length; i++) { - var lineView = cm.display.view[i]; - if (lineView.node == lineNode) - return locateNodeInLineView(lineView, node, offset); - } - } - - function locateNodeInLineView(lineView, node, offset) { - var wrapper = lineView.text.firstChild, bad = false; - if (!node || !contains(wrapper, node)) return badPos(Pos(lineNo(lineView.line), 0), true); - if (node == wrapper) { - bad = true; - node = wrapper.childNodes[offset]; - offset = 0; - if (!node) { - var line = lineView.rest ? lst(lineView.rest) : lineView.line; - return badPos(Pos(lineNo(line), line.text.length), bad); - } - } - - var textNode = node.nodeType == 3 ? node : null, topNode = node; - if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { - textNode = node.firstChild; - if (offset) offset = textNode.nodeValue.length; - } - while (topNode.parentNode != wrapper) topNode = topNode.parentNode; - var measure = lineView.measure, maps = measure.maps; - - function find(textNode, topNode, offset) { - for (var i = -1; i < (maps ? maps.length : 0); i++) { - var map = i < 0 ? measure.map : maps[i]; - for (var j = 0; j < map.length; j += 3) { - var curNode = map[j + 2]; - if (curNode == textNode || curNode == topNode) { - var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); - var ch = map[j] + offset; - if (offset < 0 || curNode != textNode) ch = map[j + (offset ? 1 : 0)]; - return Pos(line, ch); - } - } - } - } - var found = find(textNode, topNode, offset); - if (found) return badPos(found, bad); - - // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems - for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { - found = find(after, after.firstChild, 0); - if (found) - return badPos(Pos(found.line, found.ch - dist), bad); - else - dist += after.textContent.length; - } - for (var before = topNode.previousSibling, dist = offset; before; before = before.previousSibling) { - found = find(before, before.firstChild, -1); - if (found) - return badPos(Pos(found.line, found.ch + dist), bad); - else - dist += after.textContent.length; - } - } - - function domTextBetween(cm, from, to, fromLine, toLine) { - var text = "", closing = false, lineSep = cm.doc.lineSeparator(); - function recognizeMarker(id) { return function(marker) { return marker.id == id; }; } - function walk(node) { - if (node.nodeType == 1) { - var cmText = node.getAttribute("cm-text"); - if (cmText != null) { - if (cmText == "") cmText = node.textContent.replace(/\u200b/g, ""); - text += cmText; - return; - } - var markerID = node.getAttribute("cm-marker"), range; - if (markerID) { - var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); - if (found.length && (range = found[0].find())) - text += getBetween(cm.doc, range.from, range.to).join(lineSep); - return; - } - if (node.getAttribute("contenteditable") == "false") return; - for (var i = 0; i < node.childNodes.length; i++) - walk(node.childNodes[i]); - if (/^(pre|div|p)$/i.test(node.nodeName)) - closing = true; - } else if (node.nodeType == 3) { - var val = node.nodeValue; - if (!val) return; - if (closing) { - text += lineSep; - closing = false; - } - text += val; - } - } - for (;;) { - walk(from); - if (from == to) break; - from = from.nextSibling; - } - return text; - } - - CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; - - // SELECTION / CURSOR - - // Selection objects are immutable. A new one is created every time - // the selection changes. A selection is one or more non-overlapping - // (and non-touching) ranges, sorted, and an integer that indicates - // which one is the primary selection (the one that's scrolled into - // view, that getCursor returns, etc). - function Selection(ranges, primIndex) { - this.ranges = ranges; - this.primIndex = primIndex; - } - - Selection.prototype = { - primary: function() { return this.ranges[this.primIndex]; }, - equals: function(other) { - if (other == this) return true; - if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) return false; - for (var i = 0; i < this.ranges.length; i++) { - var here = this.ranges[i], there = other.ranges[i]; - if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) return false; - } - return true; - }, - deepCopy: function() { - for (var out = [], i = 0; i < this.ranges.length; i++) - out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); - return new Selection(out, this.primIndex); - }, - somethingSelected: function() { - for (var i = 0; i < this.ranges.length; i++) - if (!this.ranges[i].empty()) return true; - return false; - }, - contains: function(pos, end) { - if (!end) end = pos; - for (var i = 0; i < this.ranges.length; i++) { - var range = this.ranges[i]; - if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) - return i; - } - return -1; - } - }; - - function Range(anchor, head) { - this.anchor = anchor; this.head = head; - } - - Range.prototype = { - from: function() { return minPos(this.anchor, this.head); }, - to: function() { return maxPos(this.anchor, this.head); }, - empty: function() { - return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch; - } - }; - - // Take an unsorted, potentially overlapping set of ranges, and - // build a selection out of it. 'Consumes' ranges array (modifying - // it). - function normalizeSelection(ranges, primIndex) { - var prim = ranges[primIndex]; - ranges.sort(function(a, b) { return cmp(a.from(), b.from()); }); - primIndex = indexOf(ranges, prim); - for (var i = 1; i < ranges.length; i++) { - var cur = ranges[i], prev = ranges[i - 1]; - if (cmp(prev.to(), cur.from()) >= 0) { - var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); - var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; - if (i <= primIndex) --primIndex; - ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); - } - } - return new Selection(ranges, primIndex); - } - - function simpleSelection(anchor, head) { - return new Selection([new Range(anchor, head || anchor)], 0); - } - - // Most of the external API clips given positions to make sure they - // actually exist within the document. - function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1));} - function clipPos(doc, pos) { - if (pos.line < doc.first) return Pos(doc.first, 0); - var last = doc.first + doc.size - 1; - if (pos.line > last) return Pos(last, getLine(doc, last).text.length); - return clipToLen(pos, getLine(doc, pos.line).text.length); - } - function clipToLen(pos, linelen) { - var ch = pos.ch; - if (ch == null || ch > linelen) return Pos(pos.line, linelen); - else if (ch < 0) return Pos(pos.line, 0); - else return pos; - } - function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size;} - function clipPosArray(doc, array) { - for (var out = [], i = 0; i < array.length; i++) out[i] = clipPos(doc, array[i]); - return out; - } - - // SELECTION UPDATES - - // The 'scroll' parameter given to many of these indicated whether - // the new cursor position should be scrolled into view after - // modifying the selection. - - // If shift is held or the extend flag is set, extends a range to - // include a given position (and optionally a second position). - // Otherwise, simply returns the range between the given positions. - // Used for cursor motion and such. - function extendRange(doc, range, head, other) { - if (doc.cm && doc.cm.display.shift || doc.extend) { - var anchor = range.anchor; - if (other) { - var posBefore = cmp(head, anchor) < 0; - if (posBefore != (cmp(other, anchor) < 0)) { - anchor = head; - head = other; - } else if (posBefore != (cmp(head, other) < 0)) { - head = other; - } - } - return new Range(anchor, head); - } else { - return new Range(other || head, head); - } - } - - // Extend the primary selection range, discard the rest. - function extendSelection(doc, head, other, options) { - setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options); - } - - // Extend all selections (pos is an array of selections with length - // equal the number of selections) - function extendSelections(doc, heads, options) { - for (var out = [], i = 0; i < doc.sel.ranges.length; i++) - out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null); - var newSel = normalizeSelection(out, doc.sel.primIndex); - setSelection(doc, newSel, options); - } - - // Updates a single range in the selection. - function replaceOneSelection(doc, i, range, options) { - var ranges = doc.sel.ranges.slice(0); - ranges[i] = range; - setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options); - } - - // Reset the selection to a single range. - function setSimpleSelection(doc, anchor, head, options) { - setSelection(doc, simpleSelection(anchor, head), options); - } - - // Give beforeSelectionChange handlers a change to influence a - // selection update. - function filterSelectionChange(doc, sel) { - var obj = { - ranges: sel.ranges, - update: function(ranges) { - this.ranges = []; - for (var i = 0; i < ranges.length; i++) - this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), - clipPos(doc, ranges[i].head)); - } - }; - signal(doc, "beforeSelectionChange", doc, obj); - if (doc.cm) signal(doc.cm, "beforeSelectionChange", doc.cm, obj); - if (obj.ranges != sel.ranges) return normalizeSelection(obj.ranges, obj.ranges.length - 1); - else return sel; - } - - function setSelectionReplaceHistory(doc, sel, options) { - var done = doc.history.done, last = lst(done); - if (last && last.ranges) { - done[done.length - 1] = sel; - setSelectionNoUndo(doc, sel, options); - } else { - setSelection(doc, sel, options); - } - } - - // Set a new selection. - function setSelection(doc, sel, options) { - setSelectionNoUndo(doc, sel, options); - addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); - } - - function setSelectionNoUndo(doc, sel, options) { - if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) - sel = filterSelectionChange(doc, sel); - - var bias = options && options.bias || - (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); - setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); - - if (!(options && options.scroll === false) && doc.cm) - ensureCursorVisible(doc.cm); - } - - function setSelectionInner(doc, sel) { - if (sel.equals(doc.sel)) return; - - doc.sel = sel; - - if (doc.cm) { - doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true; - signalCursorActivity(doc.cm); - } - signalLater(doc, "cursorActivity", doc); - } - - // Verify that the selection does not partially select any atomic - // marked ranges. - function reCheckSelection(doc) { - setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll); - } - - // Return a selection that does not partially select any atomic - // ranges. - function skipAtomicInSelection(doc, sel, bias, mayClear) { - var out; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - var newAnchor = skipAtomic(doc, range.anchor, bias, mayClear); - var newHead = skipAtomic(doc, range.head, bias, mayClear); - if (out || newAnchor != range.anchor || newHead != range.head) { - if (!out) out = sel.ranges.slice(0, i); - out[i] = new Range(newAnchor, newHead); - } - } - return out ? normalizeSelection(out, sel.primIndex) : sel; - } - - // Ensure a given position is not inside an atomic range. - function skipAtomic(doc, pos, bias, mayClear) { - var flipped = false, curPos = pos; - var dir = bias || 1; - doc.cantEdit = false; - search: for (;;) { - var line = getLine(doc, curPos.line); - if (line.markedSpans) { - for (var i = 0; i < line.markedSpans.length; ++i) { - var sp = line.markedSpans[i], m = sp.marker; - if ((sp.from == null || (m.inclusiveLeft ? sp.from <= curPos.ch : sp.from < curPos.ch)) && - (sp.to == null || (m.inclusiveRight ? sp.to >= curPos.ch : sp.to > curPos.ch))) { - if (mayClear) { - signal(m, "beforeCursorEnter"); - if (m.explicitlyCleared) { - if (!line.markedSpans) break; - else {--i; continue;} - } - } - if (!m.atomic) continue; - var newPos = m.find(dir < 0 ? -1 : 1); - if (cmp(newPos, curPos) == 0) { - newPos.ch += dir; - if (newPos.ch < 0) { - if (newPos.line > doc.first) newPos = clipPos(doc, Pos(newPos.line - 1)); - else newPos = null; - } else if (newPos.ch > line.text.length) { - if (newPos.line < doc.first + doc.size - 1) newPos = Pos(newPos.line + 1, 0); - else newPos = null; - } - if (!newPos) { - if (flipped) { - // Driven in a corner -- no valid cursor position found at all - // -- try again *with* clearing, if we didn't already - if (!mayClear) return skipAtomic(doc, pos, bias, true); - // Otherwise, turn off editing until further notice, and return the start of the doc - doc.cantEdit = true; - return Pos(doc.first, 0); - } - flipped = true; newPos = pos; dir = -dir; - } - } - curPos = newPos; - continue search; - } - } - } - return curPos; - } - } - - // SELECTION DRAWING - - function updateSelection(cm) { - cm.display.input.showSelection(cm.display.input.prepareSelection()); - } - - function prepareSelection(cm, primary) { - var doc = cm.doc, result = {}; - var curFragment = result.cursors = document.createDocumentFragment(); - var selFragment = result.selection = document.createDocumentFragment(); - - for (var i = 0; i < doc.sel.ranges.length; i++) { - if (primary === false && i == doc.sel.primIndex) continue; - var range = doc.sel.ranges[i]; - var collapsed = range.empty(); - if (collapsed || cm.options.showCursorWhenSelecting) - drawSelectionCursor(cm, range.head, curFragment); - if (!collapsed) - drawSelectionRange(cm, range, selFragment); - } - return result; - } - - // Draws a cursor for the given range - function drawSelectionCursor(cm, head, output) { - var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); - - var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); - cursor.style.left = pos.left + "px"; - cursor.style.top = pos.top + "px"; - cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; - - if (pos.other) { - // Secondary cursor, shown when on a 'jump' in bi-directional text - var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); - otherCursor.style.display = ""; - otherCursor.style.left = pos.other.left + "px"; - otherCursor.style.top = pos.other.top + "px"; - otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; - } - } - - // Draws the given range as a highlighted selection - function drawSelectionRange(cm, range, output) { - var display = cm.display, doc = cm.doc; - var fragment = document.createDocumentFragment(); - var padding = paddingH(cm.display), leftSide = padding.left; - var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; - - function add(left, top, width, bottom) { - if (top < 0) top = 0; - top = Math.round(top); - bottom = Math.round(bottom); - fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + - "px; top: " + top + "px; width: " + (width == null ? rightSide - left : width) + - "px; height: " + (bottom - top) + "px")); - } - - function drawForLine(line, fromArg, toArg) { - var lineObj = getLine(doc, line); - var lineLen = lineObj.text.length; - var start, end; - function coords(ch, bias) { - return charCoords(cm, Pos(line, ch), "div", lineObj, bias); - } - - iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function(from, to, dir) { - var leftPos = coords(from, "left"), rightPos, left, right; - if (from == to) { - rightPos = leftPos; - left = right = leftPos.left; - } else { - rightPos = coords(to - 1, "right"); - if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp; } - left = leftPos.left; - right = rightPos.right; - } - if (fromArg == null && from == 0) left = leftSide; - if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part - add(left, leftPos.top, null, leftPos.bottom); - left = leftSide; - if (leftPos.bottom < rightPos.top) add(left, leftPos.bottom, null, rightPos.top); - } - if (toArg == null && to == lineLen) right = rightSide; - if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) - start = leftPos; - if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) - end = rightPos; - if (left < leftSide + 1) left = leftSide; - add(left, rightPos.top, right - left, rightPos.bottom); - }); - return {start: start, end: end}; - } - - var sFrom = range.from(), sTo = range.to(); - if (sFrom.line == sTo.line) { - drawForLine(sFrom.line, sFrom.ch, sTo.ch); - } else { - var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); - var singleVLine = visualLine(fromLine) == visualLine(toLine); - var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; - var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; - if (singleVLine) { - if (leftEnd.top < rightStart.top - 2) { - add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); - add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); - } else { - add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); - } - } - if (leftEnd.bottom < rightStart.top) - add(leftSide, leftEnd.bottom, null, rightStart.top); - } - - output.appendChild(fragment); - } - - // Cursor-blinking - function restartBlink(cm) { - if (!cm.state.focused) return; - var display = cm.display; - clearInterval(display.blinker); - var on = true; - display.cursorDiv.style.visibility = ""; - if (cm.options.cursorBlinkRate > 0) - display.blinker = setInterval(function() { - display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; - }, cm.options.cursorBlinkRate); - else if (cm.options.cursorBlinkRate < 0) - display.cursorDiv.style.visibility = "hidden"; - } - - // HIGHLIGHT WORKER - - function startWorker(cm, time) { - if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo) - cm.state.highlight.set(time, bind(highlightWorker, cm)); - } - - function highlightWorker(cm) { - var doc = cm.doc; - if (doc.frontier < doc.first) doc.frontier = doc.first; - if (doc.frontier >= cm.display.viewTo) return; - var end = +new Date + cm.options.workTime; - var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)); - var changedLines = []; - - doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function(line) { - if (doc.frontier >= cm.display.viewFrom) { // Visible - var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength; - var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true); - line.styles = highlighted.styles; - var oldCls = line.styleClasses, newCls = highlighted.classes; - if (newCls) line.styleClasses = newCls; - else if (oldCls) line.styleClasses = null; - var ischange = !oldStyles || oldStyles.length != line.styles.length || - oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); - for (var i = 0; !ischange && i < oldStyles.length; ++i) ischange = oldStyles[i] != line.styles[i]; - if (ischange) changedLines.push(doc.frontier); - line.stateAfter = tooLong ? state : copyState(doc.mode, state); - } else { - if (line.text.length <= cm.options.maxHighlightLength) - processLine(cm, line.text, state); - line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null; - } - ++doc.frontier; - if (+new Date > end) { - startWorker(cm, cm.options.workDelay); - return true; - } - }); - if (changedLines.length) runInOp(cm, function() { - for (var i = 0; i < changedLines.length; i++) - regLineChange(cm, changedLines[i], "text"); - }); - } - - // Finds the line to start with when starting a parse. Tries to - // find a line with a stateAfter, so that it can start with a - // valid state. If that fails, it returns the line with the - // smallest indentation, which tends to need the least context to - // parse correctly. - function findStartLine(cm, n, precise) { - var minindent, minline, doc = cm.doc; - var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); - for (var search = n; search > lim; --search) { - if (search <= doc.first) return doc.first; - var line = getLine(doc, search - 1); - if (line.stateAfter && (!precise || search <= doc.frontier)) return search; - var indented = countColumn(line.text, null, cm.options.tabSize); - if (minline == null || minindent > indented) { - minline = search - 1; - minindent = indented; - } - } - return minline; - } - - function getStateBefore(cm, n, precise) { - var doc = cm.doc, display = cm.display; - if (!doc.mode.startState) return true; - var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter; - if (!state) state = startState(doc.mode); - else state = copyState(doc.mode, state); - doc.iter(pos, n, function(line) { - processLine(cm, line.text, state); - var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo; - line.stateAfter = save ? copyState(doc.mode, state) : null; - ++pos; - }); - if (precise) doc.frontier = pos; - return state; - } - - // POSITION MEASUREMENT - - function paddingTop(display) {return display.lineSpace.offsetTop;} - function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight;} - function paddingH(display) { - if (display.cachedPaddingH) return display.cachedPaddingH; - var e = removeChildrenAndAdd(display.measure, elt("pre", "x")); - var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; - var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; - if (!isNaN(data.left) && !isNaN(data.right)) display.cachedPaddingH = data; - return data; - } - - function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth; } - function displayWidth(cm) { - return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth; - } - function displayHeight(cm) { - return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight; - } - - // Ensure the lineView.wrapping.heights array is populated. This is - // an array of bottom offsets for the lines that make up a drawn - // line. When lineWrapping is on, there might be more than one - // height. - function ensureLineHeights(cm, lineView, rect) { - var wrapping = cm.options.lineWrapping; - var curWidth = wrapping && displayWidth(cm); - if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { - var heights = lineView.measure.heights = []; - if (wrapping) { - lineView.measure.width = curWidth; - var rects = lineView.text.firstChild.getClientRects(); - for (var i = 0; i < rects.length - 1; i++) { - var cur = rects[i], next = rects[i + 1]; - if (Math.abs(cur.bottom - next.bottom) > 2) - heights.push((cur.bottom + next.top) / 2 - rect.top); - } - } - heights.push(rect.bottom - rect.top); - } - } - - // Find a line map (mapping character offsets to text nodes) and a - // measurement cache for the given line number. (A line view might - // contain multiple lines when collapsed ranges are present.) - function mapFromLineView(lineView, line, lineN) { - if (lineView.line == line) - return {map: lineView.measure.map, cache: lineView.measure.cache}; - for (var i = 0; i < lineView.rest.length; i++) - if (lineView.rest[i] == line) - return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]}; - for (var i = 0; i < lineView.rest.length; i++) - if (lineNo(lineView.rest[i]) > lineN) - return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i], before: true}; - } - - // Render a line into the hidden node display.externalMeasured. Used - // when measurement is needed for a line that's not in the viewport. - function updateExternalMeasurement(cm, line) { - line = visualLine(line); - var lineN = lineNo(line); - var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); - view.lineN = lineN; - var built = view.built = buildLineContent(cm, view); - view.text = built.pre; - removeChildrenAndAdd(cm.display.lineMeasure, built.pre); - return view; - } - - // Get a {top, bottom, left, right} box (in line-local coordinates) - // for a given character. - function measureChar(cm, line, ch, bias) { - return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias); - } - - // Find a line view that corresponds to the given line number. - function findViewForLine(cm, lineN) { - if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) - return cm.display.view[findViewIndex(cm, lineN)]; - var ext = cm.display.externalMeasured; - if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) - return ext; - } - - // Measurement can be split in two steps, the set-up work that - // applies to the whole line, and the measurement of the actual - // character. Functions like coordsChar, that need to do a lot of - // measurements in a row, can thus ensure that the set-up work is - // only done once. - function prepareMeasureForLine(cm, line) { - var lineN = lineNo(line); - var view = findViewForLine(cm, lineN); - if (view && !view.text) { - view = null; - } else if (view && view.changes) { - updateLineForChanges(cm, view, lineN, getDimensions(cm)); - cm.curOp.forceUpdate = true; - } - if (!view) - view = updateExternalMeasurement(cm, line); - - var info = mapFromLineView(view, line, lineN); - return { - line: line, view: view, rect: null, - map: info.map, cache: info.cache, before: info.before, - hasHeights: false - }; - } - - // Given a prepared measurement object, measures the position of an - // actual character (or fetches it from the cache). - function measureCharPrepared(cm, prepared, ch, bias, varHeight) { - if (prepared.before) ch = -1; - var key = ch + (bias || ""), found; - if (prepared.cache.hasOwnProperty(key)) { - found = prepared.cache[key]; - } else { - if (!prepared.rect) - prepared.rect = prepared.view.text.getBoundingClientRect(); - if (!prepared.hasHeights) { - ensureLineHeights(cm, prepared.view, prepared.rect); - prepared.hasHeights = true; - } - found = measureCharInner(cm, prepared, ch, bias); - if (!found.bogus) prepared.cache[key] = found; - } - return {left: found.left, right: found.right, - top: varHeight ? found.rtop : found.top, - bottom: varHeight ? found.rbottom : found.bottom}; - } - - var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; - - function nodeAndOffsetInLineMap(map, ch, bias) { - var node, start, end, collapse; - // First, search the line map for the text node corresponding to, - // or closest to, the target character. - for (var i = 0; i < map.length; i += 3) { - var mStart = map[i], mEnd = map[i + 1]; - if (ch < mStart) { - start = 0; end = 1; - collapse = "left"; - } else if (ch < mEnd) { - start = ch - mStart; - end = start + 1; - } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { - end = mEnd - mStart; - start = end - 1; - if (ch >= mEnd) collapse = "right"; - } - if (start != null) { - node = map[i + 2]; - if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) - collapse = bias; - if (bias == "left" && start == 0) - while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { - node = map[(i -= 3) + 2]; - collapse = "left"; - } - if (bias == "right" && start == mEnd - mStart) - while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { - node = map[(i += 3) + 2]; - collapse = "right"; - } - break; - } - } - return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}; - } - - function measureCharInner(cm, prepared, ch, bias) { - var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); - var node = place.node, start = place.start, end = place.end, collapse = place.collapse; - - var rect; - if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. - for (var i = 0; i < 4; i++) { // Retry a maximum of 4 times when nonsense rectangles are returned - while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) --start; - while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) ++end; - if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) { - rect = node.parentNode.getBoundingClientRect(); - } else if (ie && cm.options.lineWrapping) { - var rects = range(node, start, end).getClientRects(); - if (rects.length) - rect = rects[bias == "right" ? rects.length - 1 : 0]; - else - rect = nullRect; - } else { - rect = range(node, start, end).getBoundingClientRect() || nullRect; - } - if (rect.left || rect.right || start == 0) break; - end = start; - start = start - 1; - collapse = "right"; - } - if (ie && ie_version < 11) rect = maybeUpdateRectForZooming(cm.display.measure, rect); - } else { // If it is a widget, simply get the box for the whole widget. - if (start > 0) collapse = bias = "right"; - var rects; - if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) - rect = rects[bias == "right" ? rects.length - 1 : 0]; - else - rect = node.getBoundingClientRect(); - } - if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { - var rSpan = node.parentNode.getClientRects()[0]; - if (rSpan) - rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; - else - rect = nullRect; - } - - var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; - var mid = (rtop + rbot) / 2; - var heights = prepared.view.measure.heights; - for (var i = 0; i < heights.length - 1; i++) - if (mid < heights[i]) break; - var top = i ? heights[i - 1] : 0, bot = heights[i]; - var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, - right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, - top: top, bottom: bot}; - if (!rect.left && !rect.right) result.bogus = true; - if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } - - return result; - } - - // Work around problem with bounding client rects on ranges being - // returned incorrectly when zoomed on IE10 and below. - function maybeUpdateRectForZooming(measure, rect) { - if (!window.screen || screen.logicalXDPI == null || - screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) - return rect; - var scaleX = screen.logicalXDPI / screen.deviceXDPI; - var scaleY = screen.logicalYDPI / screen.deviceYDPI; - return {left: rect.left * scaleX, right: rect.right * scaleX, - top: rect.top * scaleY, bottom: rect.bottom * scaleY}; - } - - function clearLineMeasurementCacheFor(lineView) { - if (lineView.measure) { - lineView.measure.cache = {}; - lineView.measure.heights = null; - if (lineView.rest) for (var i = 0; i < lineView.rest.length; i++) - lineView.measure.caches[i] = {}; - } - } - - function clearLineMeasurementCache(cm) { - cm.display.externalMeasure = null; - removeChildren(cm.display.lineMeasure); - for (var i = 0; i < cm.display.view.length; i++) - clearLineMeasurementCacheFor(cm.display.view[i]); - } - - function clearCaches(cm) { - clearLineMeasurementCache(cm); - cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; - if (!cm.options.lineWrapping) cm.display.maxLineChanged = true; - cm.display.lineNumChars = null; - } - - function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft; } - function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop; } - - // Converts a {top, bottom, left, right} box from line-local - // coordinates into another coordinate system. Context may be one of - // "line", "div" (display.lineDiv), "local"/null (editor), "window", - // or "page". - function intoCoordSystem(cm, lineObj, rect, context) { - if (lineObj.widgets) for (var i = 0; i < lineObj.widgets.length; ++i) if (lineObj.widgets[i].above) { - var size = widgetHeight(lineObj.widgets[i]); - rect.top += size; rect.bottom += size; - } - if (context == "line") return rect; - if (!context) context = "local"; - var yOff = heightAtLine(lineObj); - if (context == "local") yOff += paddingTop(cm.display); - else yOff -= cm.display.viewOffset; - if (context == "page" || context == "window") { - var lOff = cm.display.lineSpace.getBoundingClientRect(); - yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); - var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); - rect.left += xOff; rect.right += xOff; - } - rect.top += yOff; rect.bottom += yOff; - return rect; - } - - // Coverts a box from "div" coords to another coordinate system. - // Context may be "window", "page", "div", or "local"/null. - function fromCoordSystem(cm, coords, context) { - if (context == "div") return coords; - var left = coords.left, top = coords.top; - // First move into "page" coordinate system - if (context == "page") { - left -= pageScrollX(); - top -= pageScrollY(); - } else if (context == "local" || !context) { - var localBox = cm.display.sizer.getBoundingClientRect(); - left += localBox.left; - top += localBox.top; - } - - var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); - return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}; - } - - function charCoords(cm, pos, context, lineObj, bias) { - if (!lineObj) lineObj = getLine(cm.doc, pos.line); - return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context); - } - - // Returns a box for a given cursor position, which may have an - // 'other' property containing the position of the secondary cursor - // on a bidi boundary. - function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { - lineObj = lineObj || getLine(cm.doc, pos.line); - if (!preparedMeasure) preparedMeasure = prepareMeasureForLine(cm, lineObj); - function get(ch, right) { - var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); - if (right) m.left = m.right; else m.right = m.left; - return intoCoordSystem(cm, lineObj, m, context); - } - function getBidi(ch, partPos) { - var part = order[partPos], right = part.level % 2; - if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { - part = order[--partPos]; - ch = bidiRight(part) - (part.level % 2 ? 0 : 1); - right = true; - } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { - part = order[++partPos]; - ch = bidiLeft(part) - part.level % 2; - right = false; - } - if (right && ch == part.to && ch > part.from) return get(ch - 1); - return get(ch, right); - } - var order = getOrder(lineObj), ch = pos.ch; - if (!order) return get(ch); - var partPos = getBidiPartAt(order, ch); - var val = getBidi(ch, partPos); - if (bidiOther != null) val.other = getBidi(ch, bidiOther); - return val; - } - - // Used to cheaply estimate the coordinates for a position. Used for - // intermediate scroll updates. - function estimateCoords(cm, pos) { - var left = 0, pos = clipPos(cm.doc, pos); - if (!cm.options.lineWrapping) left = charWidth(cm.display) * pos.ch; - var lineObj = getLine(cm.doc, pos.line); - var top = heightAtLine(lineObj) + paddingTop(cm.display); - return {left: left, right: left, top: top, bottom: top + lineObj.height}; - } - - // Positions returned by coordsChar contain some extra information. - // xRel is the relative x position of the input coordinates compared - // to the found position (so xRel > 0 means the coordinates are to - // the right of the character position, for example). When outside - // is true, that means the coordinates lie outside the line's - // vertical range. - function PosWithInfo(line, ch, outside, xRel) { - var pos = Pos(line, ch); - pos.xRel = xRel; - if (outside) pos.outside = true; - return pos; - } - - // Compute the character position closest to the given coordinates. - // Input must be lineSpace-local ("div" coordinate system). - function coordsChar(cm, x, y) { - var doc = cm.doc; - y += cm.display.viewOffset; - if (y < 0) return PosWithInfo(doc.first, 0, true, -1); - var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; - if (lineN > last) - return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1); - if (x < 0) x = 0; - - var lineObj = getLine(doc, lineN); - for (;;) { - var found = coordsCharInner(cm, lineObj, lineN, x, y); - var merged = collapsedSpanAtEnd(lineObj); - var mergedPos = merged && merged.find(0, true); - if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) - lineN = lineNo(lineObj = mergedPos.to.line); - else - return found; - } - } - - function coordsCharInner(cm, lineObj, lineNo, x, y) { - var innerOff = y - heightAtLine(lineObj); - var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth; - var preparedMeasure = prepareMeasureForLine(cm, lineObj); - - function getX(ch) { - var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure); - wrongLine = true; - if (innerOff > sp.bottom) return sp.left - adjust; - else if (innerOff < sp.top) return sp.left + adjust; - else wrongLine = false; - return sp.left; - } - - var bidi = getOrder(lineObj), dist = lineObj.text.length; - var from = lineLeft(lineObj), to = lineRight(lineObj); - var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine; - - if (x > toX) return PosWithInfo(lineNo, to, toOutside, 1); - // Do a binary search between these bounds. - for (;;) { - if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { - var ch = x < fromX || x - fromX <= toX - x ? from : to; - var xDiff = x - (ch == from ? fromX : toX); - while (isExtendingChar(lineObj.text.charAt(ch))) ++ch; - var pos = PosWithInfo(lineNo, ch, ch == from ? fromOutside : toOutside, - xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0); - return pos; - } - var step = Math.ceil(dist / 2), middle = from + step; - if (bidi) { - middle = from; - for (var i = 0; i < step; ++i) middle = moveVisually(lineObj, middle, 1); - } - var middleX = getX(middle); - if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) toX += 1000; dist = step;} - else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step;} - } - } - - var measureText; - // Compute the default text height. - function textHeight(display) { - if (display.cachedTextHeight != null) return display.cachedTextHeight; - if (measureText == null) { - measureText = elt("pre"); - // Measure a bunch of lines, for browsers that compute - // fractional heights. - for (var i = 0; i < 49; ++i) { - measureText.appendChild(document.createTextNode("x")); - measureText.appendChild(elt("br")); - } - measureText.appendChild(document.createTextNode("x")); - } - removeChildrenAndAdd(display.measure, measureText); - var height = measureText.offsetHeight / 50; - if (height > 3) display.cachedTextHeight = height; - removeChildren(display.measure); - return height || 1; - } - - // Compute the default character width. - function charWidth(display) { - if (display.cachedCharWidth != null) return display.cachedCharWidth; - var anchor = elt("span", "xxxxxxxxxx"); - var pre = elt("pre", [anchor]); - removeChildrenAndAdd(display.measure, pre); - var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; - if (width > 2) display.cachedCharWidth = width; - return width || 10; - } - - // OPERATIONS - - // Operations are used to wrap a series of changes to the editor - // state in such a way that each change won't have to update the - // cursor and display (which would be awkward, slow, and - // error-prone). Instead, display updates are batched and then all - // combined and executed at once. - - var operationGroup = null; - - var nextOpId = 0; - // Start a new operation. - function startOperation(cm) { - cm.curOp = { - cm: cm, - viewChanged: false, // Flag that indicates that lines might need to be redrawn - startHeight: cm.doc.height, // Used to detect need to update scrollbar - forceUpdate: false, // Used to force a redraw - updateInput: null, // Whether to reset the input textarea - typing: false, // Whether this reset should be careful to leave existing text (for compositing) - changeObjs: null, // Accumulated changes, for firing change events - cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on - cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already - selectionChanged: false, // Whether the selection needs to be redrawn - updateMaxLine: false, // Set when the widest line needs to be determined anew - scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet - scrollToPos: null, // Used to scroll to a specific position - focus: false, - id: ++nextOpId // Unique ID - }; - if (operationGroup) { - operationGroup.ops.push(cm.curOp); - } else { - cm.curOp.ownsGroup = operationGroup = { - ops: [cm.curOp], - delayedCallbacks: [] - }; - } - } - - function fireCallbacksForOps(group) { - // Calls delayed callbacks and cursorActivity handlers until no - // new ones appear - var callbacks = group.delayedCallbacks, i = 0; - do { - for (; i < callbacks.length; i++) - callbacks[i].call(null); - for (var j = 0; j < group.ops.length; j++) { - var op = group.ops[j]; - if (op.cursorActivityHandlers) - while (op.cursorActivityCalled < op.cursorActivityHandlers.length) - op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); - } - } while (i < callbacks.length); - } - - // Finish an operation, updating the display and signalling delayed events - function endOperation(cm) { - var op = cm.curOp, group = op.ownsGroup; - if (!group) return; - - try { fireCallbacksForOps(group); } - finally { - operationGroup = null; - for (var i = 0; i < group.ops.length; i++) - group.ops[i].cm.curOp = null; - endOperations(group); - } - } - - // The DOM updates done when an operation finishes are batched so - // that the minimum number of relayouts are required. - function endOperations(group) { - var ops = group.ops; - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_R1(ops[i]); - for (var i = 0; i < ops.length; i++) // Write DOM (maybe) - endOperation_W1(ops[i]); - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_R2(ops[i]); - for (var i = 0; i < ops.length; i++) // Write DOM (maybe) - endOperation_W2(ops[i]); - for (var i = 0; i < ops.length; i++) // Read DOM - endOperation_finish(ops[i]); - } - - function endOperation_R1(op) { - var cm = op.cm, display = cm.display; - maybeClipScrollbars(cm); - if (op.updateMaxLine) findMaxLine(cm); - - op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || - op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || - op.scrollToPos.to.line >= display.viewTo) || - display.maxLineChanged && cm.options.lineWrapping; - op.update = op.mustUpdate && - new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); - } - - function endOperation_W1(op) { - op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); - } - - function endOperation_R2(op) { - var cm = op.cm, display = cm.display; - if (op.updatedDisplay) updateHeightsInViewport(cm); - - op.barMeasure = measureForScrollbars(cm); - - // If the max line changed since it was last measured, measure it, - // and ensure the document's width matches it. - // updateDisplay_W2 will use these properties to do the actual resizing - if (display.maxLineChanged && !cm.options.lineWrapping) { - op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; - cm.display.sizerWidth = op.adjustWidthTo; - op.barMeasure.scrollWidth = - Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); - op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); - } - - if (op.updatedDisplay || op.selectionChanged) - op.preparedSelection = display.input.prepareSelection(); - } - - function endOperation_W2(op) { - var cm = op.cm; - - if (op.adjustWidthTo != null) { - cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; - if (op.maxScrollLeft < cm.doc.scrollLeft) - setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); - cm.display.maxLineChanged = false; - } - - if (op.preparedSelection) - cm.display.input.showSelection(op.preparedSelection); - if (op.updatedDisplay) - setDocumentHeight(cm, op.barMeasure); - if (op.updatedDisplay || op.startHeight != cm.doc.height) - updateScrollbars(cm, op.barMeasure); - - if (op.selectionChanged) restartBlink(cm); - - if (cm.state.focused && op.updateInput) - cm.display.input.reset(op.typing); - if (op.focus && op.focus == activeElt()) ensureFocus(op.cm); - } - - function endOperation_finish(op) { - var cm = op.cm, display = cm.display, doc = cm.doc; - - if (op.updatedDisplay) postUpdateDisplay(cm, op.update); - - // Abort mouse wheel delta measurement, when scrolling explicitly - if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) - display.wheelStartX = display.wheelStartY = null; - - // Propagate the scroll position to the actual DOM scroller - if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { - doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)); - display.scrollbars.setScrollTop(doc.scrollTop); - display.scroller.scrollTop = doc.scrollTop; - } - if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { - doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - displayWidth(cm), op.scrollLeft)); - display.scrollbars.setScrollLeft(doc.scrollLeft); - display.scroller.scrollLeft = doc.scrollLeft; - alignHorizontally(cm); - } - // If we need to scroll a specific position into view, do so. - if (op.scrollToPos) { - var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), - clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); - if (op.scrollToPos.isCursor && cm.state.focused) maybeScrollWindow(cm, coords); - } - - // Fire events for markers that are hidden/unidden by editing or - // undoing - var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; - if (hidden) for (var i = 0; i < hidden.length; ++i) - if (!hidden[i].lines.length) signal(hidden[i], "hide"); - if (unhidden) for (var i = 0; i < unhidden.length; ++i) - if (unhidden[i].lines.length) signal(unhidden[i], "unhide"); - - if (display.wrapper.offsetHeight) - doc.scrollTop = cm.display.scroller.scrollTop; - - // Fire change events, and delayed event handlers - if (op.changeObjs) - signal(cm, "changes", cm, op.changeObjs); - if (op.update) - op.update.finish(); - } - - // Run the given function in an operation - function runInOp(cm, f) { - if (cm.curOp) return f(); - startOperation(cm); - try { return f(); } - finally { endOperation(cm); } - } - // Wraps a function in an operation. Returns the wrapped function. - function operation(cm, f) { - return function() { - if (cm.curOp) return f.apply(cm, arguments); - startOperation(cm); - try { return f.apply(cm, arguments); } - finally { endOperation(cm); } - }; - } - // Used to add methods to editor and doc instances, wrapping them in - // operations. - function methodOp(f) { - return function() { - if (this.curOp) return f.apply(this, arguments); - startOperation(this); - try { return f.apply(this, arguments); } - finally { endOperation(this); } - }; - } - function docMethodOp(f) { - return function() { - var cm = this.cm; - if (!cm || cm.curOp) return f.apply(this, arguments); - startOperation(cm); - try { return f.apply(this, arguments); } - finally { endOperation(cm); } - }; - } - - // VIEW TRACKING - - // These objects are used to represent the visible (currently drawn) - // part of the document. A LineView may correspond to multiple - // logical lines, if those are connected by collapsed ranges. - function LineView(doc, line, lineN) { - // The starting line - this.line = line; - // Continuing lines, if any - this.rest = visualLineContinued(line); - // Number of logical lines in this visual line - this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; - this.node = this.text = null; - this.hidden = lineIsHidden(doc, line); - } - - // Create a range of LineView objects for the given lines. - function buildViewArray(cm, from, to) { - var array = [], nextPos; - for (var pos = from; pos < to; pos = nextPos) { - var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); - nextPos = pos + view.size; - array.push(view); - } - return array; - } - - // Updates the display.view data structure for a given change to the - // document. From and to are in pre-change coordinates. Lendiff is - // the amount of lines added or subtracted by the change. This is - // used for changes that span multiple lines, or change the way - // lines are divided into visual lines. regLineChange (below) - // registers single-line changes. - function regChange(cm, from, to, lendiff) { - if (from == null) from = cm.doc.first; - if (to == null) to = cm.doc.first + cm.doc.size; - if (!lendiff) lendiff = 0; - - var display = cm.display; - if (lendiff && to < display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers > from)) - display.updateLineNumbers = from; - - cm.curOp.viewChanged = true; - - if (from >= display.viewTo) { // Change after - if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) - resetView(cm); - } else if (to <= display.viewFrom) { // Change before - if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { - resetView(cm); - } else { - display.viewFrom += lendiff; - display.viewTo += lendiff; - } - } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap - resetView(cm); - } else if (from <= display.viewFrom) { // Top overlap - var cut = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cut) { - display.view = display.view.slice(cut.index); - display.viewFrom = cut.lineN; - display.viewTo += lendiff; - } else { - resetView(cm); - } - } else if (to >= display.viewTo) { // Bottom overlap - var cut = viewCuttingPoint(cm, from, from, -1); - if (cut) { - display.view = display.view.slice(0, cut.index); - display.viewTo = cut.lineN; - } else { - resetView(cm); - } - } else { // Gap in the middle - var cutTop = viewCuttingPoint(cm, from, from, -1); - var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cutTop && cutBot) { - display.view = display.view.slice(0, cutTop.index) - .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) - .concat(display.view.slice(cutBot.index)); - display.viewTo += lendiff; - } else { - resetView(cm); - } - } - - var ext = display.externalMeasured; - if (ext) { - if (to < ext.lineN) - ext.lineN += lendiff; - else if (from < ext.lineN + ext.size) - display.externalMeasured = null; - } - } - - // Register a change to a single line. Type must be one of "text", - // "gutter", "class", "widget" - function regLineChange(cm, line, type) { - cm.curOp.viewChanged = true; - var display = cm.display, ext = cm.display.externalMeasured; - if (ext && line >= ext.lineN && line < ext.lineN + ext.size) - display.externalMeasured = null; - - if (line < display.viewFrom || line >= display.viewTo) return; - var lineView = display.view[findViewIndex(cm, line)]; - if (lineView.node == null) return; - var arr = lineView.changes || (lineView.changes = []); - if (indexOf(arr, type) == -1) arr.push(type); - } - - // Clear the view. - function resetView(cm) { - cm.display.viewFrom = cm.display.viewTo = cm.doc.first; - cm.display.view = []; - cm.display.viewOffset = 0; - } - - // Find the view element corresponding to a given line. Return null - // when the line isn't visible. - function findViewIndex(cm, n) { - if (n >= cm.display.viewTo) return null; - n -= cm.display.viewFrom; - if (n < 0) return null; - var view = cm.display.view; - for (var i = 0; i < view.length; i++) { - n -= view[i].size; - if (n < 0) return i; - } - } - - function viewCuttingPoint(cm, oldN, newN, dir) { - var index = findViewIndex(cm, oldN), diff, view = cm.display.view; - if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) - return {index: index, lineN: newN}; - for (var i = 0, n = cm.display.viewFrom; i < index; i++) - n += view[i].size; - if (n != oldN) { - if (dir > 0) { - if (index == view.length - 1) return null; - diff = (n + view[index].size) - oldN; - index++; - } else { - diff = n - oldN; - } - oldN += diff; newN += diff; - } - while (visualLineNo(cm.doc, newN) != newN) { - if (index == (dir < 0 ? 0 : view.length - 1)) return null; - newN += dir * view[index - (dir < 0 ? 1 : 0)].size; - index += dir; - } - return {index: index, lineN: newN}; - } - - // Force the view to cover a given range, adding empty view element - // or clipping off existing ones as needed. - function adjustView(cm, from, to) { - var display = cm.display, view = display.view; - if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { - display.view = buildViewArray(cm, from, to); - display.viewFrom = from; - } else { - if (display.viewFrom > from) - display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); - else if (display.viewFrom < from) - display.view = display.view.slice(findViewIndex(cm, from)); - display.viewFrom = from; - if (display.viewTo < to) - display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); - else if (display.viewTo > to) - display.view = display.view.slice(0, findViewIndex(cm, to)); - } - display.viewTo = to; - } - - // Count the number of lines in the view whose DOM representation is - // out of date (or nonexistent). - function countDirtyView(cm) { - var view = cm.display.view, dirty = 0; - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (!lineView.hidden && (!lineView.node || lineView.changes)) ++dirty; - } - return dirty; - } - - // EVENT HANDLERS - - // Attach the necessary event handlers when initializing the editor - function registerEventHandlers(cm) { - var d = cm.display; - on(d.scroller, "mousedown", operation(cm, onMouseDown)); - // Older IE's will not fire a second mousedown for a double click - if (ie && ie_version < 11) - on(d.scroller, "dblclick", operation(cm, function(e) { - if (signalDOMEvent(cm, e)) return; - var pos = posFromMouse(cm, e); - if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) return; - e_preventDefault(e); - var word = cm.findWordAt(pos); - extendSelection(cm.doc, word.anchor, word.head); - })); - else - on(d.scroller, "dblclick", function(e) { signalDOMEvent(cm, e) || e_preventDefault(e); }); - // Some browsers fire contextmenu *after* opening the menu, at - // which point we can't mess with it anymore. Context menu is - // handled in onMouseDown for these browsers. - if (!captureRightClick) on(d.scroller, "contextmenu", function(e) {onContextMenu(cm, e);}); - - // Used to suppress mouse event handling when a touch happens - var touchFinished, prevTouch = {end: 0}; - function finishTouch() { - if (d.activeTouch) { - touchFinished = setTimeout(function() {d.activeTouch = null;}, 1000); - prevTouch = d.activeTouch; - prevTouch.end = +new Date; - } - }; - function isMouseLikeTouchEvent(e) { - if (e.touches.length != 1) return false; - var touch = e.touches[0]; - return touch.radiusX <= 1 && touch.radiusY <= 1; - } - function farAway(touch, other) { - if (other.left == null) return true; - var dx = other.left - touch.left, dy = other.top - touch.top; - return dx * dx + dy * dy > 20 * 20; - } - on(d.scroller, "touchstart", function(e) { - if (!isMouseLikeTouchEvent(e)) { - clearTimeout(touchFinished); - var now = +new Date; - d.activeTouch = {start: now, moved: false, - prev: now - prevTouch.end <= 300 ? prevTouch : null}; - if (e.touches.length == 1) { - d.activeTouch.left = e.touches[0].pageX; - d.activeTouch.top = e.touches[0].pageY; - } - } - }); - on(d.scroller, "touchmove", function() { - if (d.activeTouch) d.activeTouch.moved = true; - }); - on(d.scroller, "touchend", function(e) { - var touch = d.activeTouch; - if (touch && !eventInWidget(d, e) && touch.left != null && - !touch.moved && new Date - touch.start < 300) { - var pos = cm.coordsChar(d.activeTouch, "page"), range; - if (!touch.prev || farAway(touch, touch.prev)) // Single tap - range = new Range(pos, pos); - else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap - range = cm.findWordAt(pos); - else // Triple tap - range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); - cm.setSelection(range.anchor, range.head); - cm.focus(); - e_preventDefault(e); - } - finishTouch(); - }); - on(d.scroller, "touchcancel", finishTouch); - - // Sync scrolling between fake scrollbars and real scrollable - // area, ensure viewport is updated when scrolling. - on(d.scroller, "scroll", function() { - if (d.scroller.clientHeight) { - setScrollTop(cm, d.scroller.scrollTop); - setScrollLeft(cm, d.scroller.scrollLeft, true); - signal(cm, "scroll", cm); - } - }); - - // Listen to wheel events in order to try and update the viewport on time. - on(d.scroller, "mousewheel", function(e){onScrollWheel(cm, e);}); - on(d.scroller, "DOMMouseScroll", function(e){onScrollWheel(cm, e);}); - - // Prevent wrapper from ever scrolling - on(d.wrapper, "scroll", function() { d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); - - d.dragFunctions = { - enter: function(e) {if (!signalDOMEvent(cm, e)) e_stop(e);}, - over: function(e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, - start: function(e){onDragStart(cm, e);}, - drop: operation(cm, onDrop), - leave: function() {clearDragCursor(cm);} - }; - - var inp = d.input.getField(); - on(inp, "keyup", function(e) { onKeyUp.call(cm, e); }); - on(inp, "keydown", operation(cm, onKeyDown)); - on(inp, "keypress", operation(cm, onKeyPress)); - on(inp, "focus", bind(onFocus, cm)); - on(inp, "blur", bind(onBlur, cm)); - } - - function dragDropChanged(cm, value, old) { - var wasOn = old && old != CodeMirror.Init; - if (!value != !wasOn) { - var funcs = cm.display.dragFunctions; - var toggle = value ? on : off; - toggle(cm.display.scroller, "dragstart", funcs.start); - toggle(cm.display.scroller, "dragenter", funcs.enter); - toggle(cm.display.scroller, "dragover", funcs.over); - toggle(cm.display.scroller, "dragleave", funcs.leave); - toggle(cm.display.scroller, "drop", funcs.drop); - } - } - - // Called when the window resizes - function onResize(cm) { - var d = cm.display; - if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) - return; - // Might be a text scaling operation, clear size caches. - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - d.scrollbarsClipped = false; - cm.setSize(); - } - - // MOUSE EVENTS - - // Return true when the given mouse event happened in a widget - function eventInWidget(display, e) { - for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { - if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || - (n.parentNode == display.sizer && n != display.mover)) - return true; - } - } - - // Given a mouse event, find the corresponding position. If liberal - // is false, it checks whether a gutter or scrollbar was clicked, - // and returns null if it was. forRect is used by rectangular - // selections, and tries to estimate a character position even for - // coordinates beyond the right of the text. - function posFromMouse(cm, e, liberal, forRect) { - var display = cm.display; - if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") return null; - - var x, y, space = display.lineSpace.getBoundingClientRect(); - // Fails unpredictably on IE[67] when mouse is dragged around quickly. - try { x = e.clientX - space.left; y = e.clientY - space.top; } - catch (e) { return null; } - var coords = coordsChar(cm, x, y), line; - if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { - var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; - coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); - } - return coords; - } - - // A mouse down can be a single click, double click, triple click, - // start of selection drag, start of text drag, new cursor - // (ctrl-click), rectangle drag (alt-drag), or xwin - // middle-click-paste. Or it might be a click on something we should - // not interfere with, such as a scrollbar or widget. - function onMouseDown(e) { - var cm = this, display = cm.display; - if (display.activeTouch && display.input.supportsTouch() || signalDOMEvent(cm, e)) return; - display.shift = e.shiftKey; - - if (eventInWidget(display, e)) { - if (!webkit) { - // Briefly turn off draggability, to allow widgets to do - // normal dragging things. - display.scroller.draggable = false; - setTimeout(function(){display.scroller.draggable = true;}, 100); - } - return; - } - if (clickInGutter(cm, e)) return; - var start = posFromMouse(cm, e); - window.focus(); - - switch (e_button(e)) { - case 1: - // #3261: make sure, that we're not starting a second selection - if (cm.state.selectingText) - cm.state.selectingText(e); - else if (start) - leftButtonDown(cm, e, start); - else if (e_target(e) == display.scroller) - e_preventDefault(e); - break; - case 2: - if (webkit) cm.state.lastMiddleDown = +new Date; - if (start) extendSelection(cm.doc, start); - setTimeout(function() {display.input.focus();}, 20); - e_preventDefault(e); - break; - case 3: - if (captureRightClick) onContextMenu(cm, e); - else delayBlurEvent(cm); - break; - } - } - - var lastClick, lastDoubleClick; - function leftButtonDown(cm, e, start) { - if (ie) setTimeout(bind(ensureFocus, cm), 0); - else cm.curOp.focus = activeElt(); - - var now = +new Date, type; - if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) { - type = "triple"; - } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) { - type = "double"; - lastDoubleClick = {time: now, pos: start}; - } else { - type = "single"; - lastClick = {time: now, pos: start}; - } - - var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained; - if (cm.options.dragDrop && dragAndDrop && !isReadOnly(cm) && - type == "single" && (contained = sel.contains(start)) > -1 && - (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) && - (cmp(contained.to(), start) > 0 || start.xRel < 0)) - leftButtonStartDrag(cm, e, start, modifier); - else - leftButtonSelect(cm, e, start, type, modifier); - } - - // Start a text drag. When it ends, see if any dragging actually - // happen, and treat as a click if it didn't. - function leftButtonStartDrag(cm, e, start, modifier) { - var display = cm.display, startTime = +new Date; - var dragEnd = operation(cm, function(e2) { - if (webkit) display.scroller.draggable = false; - cm.state.draggingText = false; - off(document, "mouseup", dragEnd); - off(display.scroller, "drop", dragEnd); - if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { - e_preventDefault(e2); - if (!modifier && +new Date - 200 < startTime) - extendSelection(cm.doc, start); - // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) - if (webkit || ie && ie_version == 9) - setTimeout(function() {document.body.focus(); display.input.focus();}, 20); - else - display.input.focus(); - } - }); - // Let the drag handler handle this. - if (webkit) display.scroller.draggable = true; - cm.state.draggingText = dragEnd; - // IE's approach to draggable - if (display.scroller.dragDrop) display.scroller.dragDrop(); - on(document, "mouseup", dragEnd); - on(display.scroller, "drop", dragEnd); - } - - // Normal selection, as opposed to text dragging. - function leftButtonSelect(cm, e, start, type, addNew) { - var display = cm.display, doc = cm.doc; - e_preventDefault(e); - - var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; - if (addNew && !e.shiftKey) { - ourIndex = doc.sel.contains(start); - if (ourIndex > -1) - ourRange = ranges[ourIndex]; - else - ourRange = new Range(start, start); - } else { - ourRange = doc.sel.primary(); - ourIndex = doc.sel.primIndex; - } - - if (e.altKey) { - type = "rect"; - if (!addNew) ourRange = new Range(start, start); - start = posFromMouse(cm, e, true, true); - ourIndex = -1; - } else if (type == "double") { - var word = cm.findWordAt(start); - if (cm.display.shift || doc.extend) - ourRange = extendRange(doc, ourRange, word.anchor, word.head); - else - ourRange = word; - } else if (type == "triple") { - var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))); - if (cm.display.shift || doc.extend) - ourRange = extendRange(doc, ourRange, line.anchor, line.head); - else - ourRange = line; - } else { - ourRange = extendRange(doc, ourRange, start); - } - - if (!addNew) { - ourIndex = 0; - setSelection(doc, new Selection([ourRange], 0), sel_mouse); - startSel = doc.sel; - } else if (ourIndex == -1) { - ourIndex = ranges.length; - setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), - {scroll: false, origin: "*mouse"}); - } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) { - setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), - {scroll: false, origin: "*mouse"}); - startSel = doc.sel; - } else { - replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); - } - - var lastPos = start; - function extendTo(pos) { - if (cmp(lastPos, pos) == 0) return; - lastPos = pos; - - if (type == "rect") { - var ranges = [], tabSize = cm.options.tabSize; - var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); - var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); - var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); - for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); - line <= end; line++) { - var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); - if (left == right) - ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); - else if (text.length > leftPos) - ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); - } - if (!ranges.length) ranges.push(new Range(start, start)); - setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), - {origin: "*mouse", scroll: false}); - cm.scrollIntoView(pos); - } else { - var oldRange = ourRange; - var anchor = oldRange.anchor, head = pos; - if (type != "single") { - if (type == "double") - var range = cm.findWordAt(pos); - else - var range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))); - if (cmp(range.anchor, anchor) > 0) { - head = range.head; - anchor = minPos(oldRange.from(), range.anchor); - } else { - head = range.anchor; - anchor = maxPos(oldRange.to(), range.head); - } - } - var ranges = startSel.ranges.slice(0); - ranges[ourIndex] = new Range(clipPos(doc, anchor), head); - setSelection(doc, normalizeSelection(ranges, ourIndex), sel_mouse); - } - } - - var editorSize = display.wrapper.getBoundingClientRect(); - // Used to ensure timeout re-tries don't fire when another extend - // happened in the meantime (clearTimeout isn't reliable -- at - // least on Chrome, the timeouts still happen even when cleared, - // if the clear happens after their scheduled firing time). - var counter = 0; - - function extend(e) { - var curCount = ++counter; - var cur = posFromMouse(cm, e, true, type == "rect"); - if (!cur) return; - if (cmp(cur, lastPos) != 0) { - cm.curOp.focus = activeElt(); - extendTo(cur); - var visible = visibleLines(display, doc); - if (cur.line >= visible.to || cur.line < visible.from) - setTimeout(operation(cm, function(){if (counter == curCount) extend(e);}), 150); - } else { - var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; - if (outside) setTimeout(operation(cm, function() { - if (counter != curCount) return; - display.scroller.scrollTop += outside; - extend(e); - }), 50); - } - } - - function done(e) { - cm.state.selectingText = false; - counter = Infinity; - e_preventDefault(e); - display.input.focus(); - off(document, "mousemove", move); - off(document, "mouseup", up); - doc.history.lastSelOrigin = null; - } - - var move = operation(cm, function(e) { - if (!e_button(e)) done(e); - else extend(e); - }); - var up = operation(cm, done); - cm.state.selectingText = up; - on(document, "mousemove", move); - on(document, "mouseup", up); - } - - // Determines whether an event happened in the gutter, and fires the - // handlers for the corresponding event. - function gutterEvent(cm, e, type, prevent, signalfn) { - try { var mX = e.clientX, mY = e.clientY; } - catch(e) { return false; } - if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) return false; - if (prevent) e_preventDefault(e); - - var display = cm.display; - var lineBox = display.lineDiv.getBoundingClientRect(); - - if (mY > lineBox.bottom || !hasHandler(cm, type)) return e_defaultPrevented(e); - mY -= lineBox.top - display.viewOffset; - - for (var i = 0; i < cm.options.gutters.length; ++i) { - var g = display.gutters.childNodes[i]; - if (g && g.getBoundingClientRect().right >= mX) { - var line = lineAtHeight(cm.doc, mY); - var gutter = cm.options.gutters[i]; - signalfn(cm, type, cm, line, gutter, e); - return e_defaultPrevented(e); - } - } - } - - function clickInGutter(cm, e) { - return gutterEvent(cm, e, "gutterClick", true, signalLater); - } - - // Kludge to work around strange IE behavior where it'll sometimes - // re-fire a series of drag-related events right after the drop (#1551) - var lastDrop = 0; - - function onDrop(e) { - var cm = this; - clearDragCursor(cm); - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) - return; - e_preventDefault(e); - if (ie) lastDrop = +new Date; - var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; - if (!pos || isReadOnly(cm)) return; - // Might be a file drop, in which case we simply extract the text - // and insert it. - if (files && files.length && window.FileReader && window.File) { - var n = files.length, text = Array(n), read = 0; - var loadFile = function(file, i) { - if (cm.options.allowDropFileTypes && - indexOf(cm.options.allowDropFileTypes, file.type) == -1) - return; - - var reader = new FileReader; - reader.onload = operation(cm, function() { - var content = reader.result; - if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) content = ""; - text[i] = content; - if (++read == n) { - pos = clipPos(cm.doc, pos); - var change = {from: pos, to: pos, - text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), - origin: "paste"}; - makeChange(cm.doc, change); - setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); - } - }); - reader.readAsText(file); - }; - for (var i = 0; i < n; ++i) loadFile(files[i], i); - } else { // Normal drop - // Don't do a replace if the drop happened inside of the selected text. - if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { - cm.state.draggingText(e); - // Ensure the editor is re-focused - setTimeout(function() {cm.display.input.focus();}, 20); - return; - } - try { - var text = e.dataTransfer.getData("Text"); - if (text) { - if (cm.state.draggingText && !(mac ? e.altKey : e.ctrlKey)) - var selected = cm.listSelections(); - setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); - if (selected) for (var i = 0; i < selected.length; ++i) - replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag"); - cm.replaceSelection(text, "around", "paste"); - cm.display.input.focus(); - } - } - catch(e){} - } - } - - function onDragStart(cm, e) { - if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return; } - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) return; - - e.dataTransfer.setData("Text", cm.getSelection()); - - // Use dummy image instead of default browsers image. - // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. - if (e.dataTransfer.setDragImage && !safari) { - var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); - img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; - if (presto) { - img.width = img.height = 1; - cm.display.wrapper.appendChild(img); - // Force a relayout, or Opera won't use our image for some obscure reason - img._top = img.offsetTop; - } - e.dataTransfer.setDragImage(img, 0, 0); - if (presto) img.parentNode.removeChild(img); - } - } - - function onDragOver(cm, e) { - var pos = posFromMouse(cm, e); - if (!pos) return; - var frag = document.createDocumentFragment(); - drawSelectionCursor(cm, pos, frag); - if (!cm.display.dragCursor) { - cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); - cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); - } - removeChildrenAndAdd(cm.display.dragCursor, frag); - } - - function clearDragCursor(cm) { - if (cm.display.dragCursor) { - cm.display.lineSpace.removeChild(cm.display.dragCursor); - cm.display.dragCursor = null; - } - } - - // SCROLL EVENTS - - // Sync the scrollable area and scrollbars, ensure the viewport - // covers the visible area. - function setScrollTop(cm, val) { - if (Math.abs(cm.doc.scrollTop - val) < 2) return; - cm.doc.scrollTop = val; - if (!gecko) updateDisplaySimple(cm, {top: val}); - if (cm.display.scroller.scrollTop != val) cm.display.scroller.scrollTop = val; - cm.display.scrollbars.setScrollTop(val); - if (gecko) updateDisplaySimple(cm); - startWorker(cm, 100); - } - // Sync scroller and scrollbar, ensure the gutter elements are - // aligned. - function setScrollLeft(cm, val, isScroller) { - if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) return; - val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); - cm.doc.scrollLeft = val; - alignHorizontally(cm); - if (cm.display.scroller.scrollLeft != val) cm.display.scroller.scrollLeft = val; - cm.display.scrollbars.setScrollLeft(val); - } - - // Since the delta values reported on mouse wheel events are - // unstandardized between browsers and even browser versions, and - // generally horribly unpredictable, this code starts by measuring - // the scroll effect that the first few mouse wheel events have, - // and, from that, detects the way it can convert deltas to pixel - // offsets afterwards. - // - // The reason we want to know the amount a wheel event will scroll - // is that it gives us a chance to update the display before the - // actual scrolling happens, reducing flickering. - - var wheelSamples = 0, wheelPixelsPerUnit = null; - // Fill in a browser-detected starting value on browsers where we - // know one. These don't have to be accurate -- the result of them - // being wrong would just be a slight flicker on the first wheel - // scroll (if it is large enough). - if (ie) wheelPixelsPerUnit = -.53; - else if (gecko) wheelPixelsPerUnit = 15; - else if (chrome) wheelPixelsPerUnit = -.7; - else if (safari) wheelPixelsPerUnit = -1/3; - - var wheelEventDelta = function(e) { - var dx = e.wheelDeltaX, dy = e.wheelDeltaY; - if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) dx = e.detail; - if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) dy = e.detail; - else if (dy == null) dy = e.wheelDelta; - return {x: dx, y: dy}; - }; - CodeMirror.wheelEventPixels = function(e) { - var delta = wheelEventDelta(e); - delta.x *= wheelPixelsPerUnit; - delta.y *= wheelPixelsPerUnit; - return delta; - }; - - function onScrollWheel(cm, e) { - var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; - - var display = cm.display, scroll = display.scroller; - // Quit if there's nothing to scroll here - var canScrollX = scroll.scrollWidth > scroll.clientWidth; - var canScrollY = scroll.scrollHeight > scroll.clientHeight; - if (!(dx && canScrollX || dy && canScrollY)) return; - - // Webkit browsers on OS X abort momentum scrolls when the target - // of the scroll event is removed from the scrollable element. - // This hack (see related code in patchDisplay) makes sure the - // element is kept around. - if (dy && mac && webkit) { - outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { - for (var i = 0; i < view.length; i++) { - if (view[i].node == cur) { - cm.display.currentWheelTarget = cur; - break outer; - } - } - } - } - - // On some browsers, horizontal scrolling will cause redraws to - // happen before the gutter has been realigned, causing it to - // wriggle around in a most unseemly way. When we have an - // estimated pixels/delta value, we just handle horizontal - // scrolling entirely here. It'll be slightly off from native, but - // better than glitching out. - if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { - if (dy && canScrollY) - setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))); - setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))); - // Only prevent default scrolling if vertical scrolling is - // actually possible. Otherwise, it causes vertical scroll - // jitter on OSX trackpads when deltaX is small and deltaY - // is large (issue #3579) - if (!dy || (dy && canScrollY)) - e_preventDefault(e); - display.wheelStartX = null; // Abort measurement, if in progress - return; - } - - // 'Project' the visible viewport to cover the area that is being - // scrolled into view (if we know enough to estimate it). - if (dy && wheelPixelsPerUnit != null) { - var pixels = dy * wheelPixelsPerUnit; - var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; - if (pixels < 0) top = Math.max(0, top + pixels - 50); - else bot = Math.min(cm.doc.height, bot + pixels + 50); - updateDisplaySimple(cm, {top: top, bottom: bot}); - } - - if (wheelSamples < 20) { - if (display.wheelStartX == null) { - display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; - display.wheelDX = dx; display.wheelDY = dy; - setTimeout(function() { - if (display.wheelStartX == null) return; - var movedX = scroll.scrollLeft - display.wheelStartX; - var movedY = scroll.scrollTop - display.wheelStartY; - var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || - (movedX && display.wheelDX && movedX / display.wheelDX); - display.wheelStartX = display.wheelStartY = null; - if (!sample) return; - wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); - ++wheelSamples; - }, 200); - } else { - display.wheelDX += dx; display.wheelDY += dy; - } - } - } - - // KEY EVENTS - - // Run a handler that was bound to a key. - function doHandleBinding(cm, bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound]; - if (!bound) return false; - } - // Ensure previous input has been read, so that the handler sees a - // consistent view of the document - cm.display.input.ensurePolled(); - var prevShift = cm.display.shift, done = false; - try { - if (isReadOnly(cm)) cm.state.suppressEdits = true; - if (dropShift) cm.display.shift = false; - done = bound(cm) != Pass; - } finally { - cm.display.shift = prevShift; - cm.state.suppressEdits = false; - } - return done; - } - - function lookupKeyForEditor(cm, name, handle) { - for (var i = 0; i < cm.state.keyMaps.length; i++) { - var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); - if (result) return result; - } - return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) - || lookupKey(name, cm.options.keyMap, handle, cm); - } - - var stopSeq = new Delayed; - function dispatchKey(cm, name, e, handle) { - var seq = cm.state.keySeq; - if (seq) { - if (isModifierKey(name)) return "handled"; - stopSeq.set(50, function() { - if (cm.state.keySeq == seq) { - cm.state.keySeq = null; - cm.display.input.reset(); - } - }); - name = seq + " " + name; - } - var result = lookupKeyForEditor(cm, name, handle); - - if (result == "multi") - cm.state.keySeq = name; - if (result == "handled") - signalLater(cm, "keyHandled", cm, name, e); - - if (result == "handled" || result == "multi") { - e_preventDefault(e); - restartBlink(cm); - } - - if (seq && !result && /\'$/.test(name)) { - e_preventDefault(e); - return true; - } - return !!result; - } - - // Handle a key from the keydown event. - function handleKeyBinding(cm, e) { - var name = keyName(e, true); - if (!name) return false; - - if (e.shiftKey && !cm.state.keySeq) { - // First try to resolve full name (including 'Shift-'). Failing - // that, see if there is a cursor-motion command (starting with - // 'go') bound to the keyname without 'Shift-'. - return dispatchKey(cm, "Shift-" + name, e, function(b) {return doHandleBinding(cm, b, true);}) - || dispatchKey(cm, name, e, function(b) { - if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) - return doHandleBinding(cm, b); - }); - } else { - return dispatchKey(cm, name, e, function(b) { return doHandleBinding(cm, b); }); - } - } - - // Handle a key from the keypress event - function handleCharBinding(cm, e, ch) { - return dispatchKey(cm, "'" + ch + "'", e, - function(b) { return doHandleBinding(cm, b, true); }); - } - - var lastStoppedKey = null; - function onKeyDown(e) { - var cm = this; - cm.curOp.focus = activeElt(); - if (signalDOMEvent(cm, e)) return; - // IE does strange things with escape. - if (ie && ie_version < 11 && e.keyCode == 27) e.returnValue = false; - var code = e.keyCode; - cm.display.shift = code == 16 || e.shiftKey; - var handled = handleKeyBinding(cm, e); - if (presto) { - lastStoppedKey = handled ? code : null; - // Opera has no cut event... we try to at least catch the key combo - if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) - cm.replaceSelection("", null, "cut"); - } - - // Turn mouse into crosshair when Alt is held on Mac. - if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) - showCrossHair(cm); - } - - function showCrossHair(cm) { - var lineDiv = cm.display.lineDiv; - addClass(lineDiv, "CodeMirror-crosshair"); - - function up(e) { - if (e.keyCode == 18 || !e.altKey) { - rmClass(lineDiv, "CodeMirror-crosshair"); - off(document, "keyup", up); - off(document, "mouseover", up); - } - } - on(document, "keyup", up); - on(document, "mouseover", up); - } - - function onKeyUp(e) { - if (e.keyCode == 16) this.doc.sel.shift = false; - signalDOMEvent(this, e); - } - - function onKeyPress(e) { - var cm = this; - if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) return; - var keyCode = e.keyCode, charCode = e.charCode; - if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} - if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) return; - var ch = String.fromCharCode(charCode == null ? keyCode : charCode); - if (handleCharBinding(cm, e, ch)) return; - cm.display.input.onKeyPress(e); - } - - // FOCUS/BLUR EVENTS - - function delayBlurEvent(cm) { - cm.state.delayingBlurEvent = true; - setTimeout(function() { - if (cm.state.delayingBlurEvent) { - cm.state.delayingBlurEvent = false; - onBlur(cm); - } - }, 100); - } - - function onFocus(cm) { - if (cm.state.delayingBlurEvent) cm.state.delayingBlurEvent = false; - - if (cm.options.readOnly == "nocursor") return; - if (!cm.state.focused) { - signal(cm, "focus", cm); - cm.state.focused = true; - addClass(cm.display.wrapper, "CodeMirror-focused"); - // This test prevents this from firing when a context - // menu is closed (since the input reset would kill the - // select-all detection hack) - if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { - cm.display.input.reset(); - if (webkit) setTimeout(function() { cm.display.input.reset(true); }, 20); // Issue #1730 - } - cm.display.input.receivedFocus(); - } - restartBlink(cm); - } - function onBlur(cm) { - if (cm.state.delayingBlurEvent) return; - - if (cm.state.focused) { - signal(cm, "blur", cm); - cm.state.focused = false; - rmClass(cm.display.wrapper, "CodeMirror-focused"); - } - clearInterval(cm.display.blinker); - setTimeout(function() {if (!cm.state.focused) cm.display.shift = false;}, 150); - } - - // CONTEXT MENU HANDLING - - // To make the context menu work, we need to briefly unhide the - // textarea (making it as unobtrusive as possible) to let the - // right-click take effect on it. - function onContextMenu(cm, e) { - if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) return; - if (signalDOMEvent(cm, e, "contextmenu")) return; - cm.display.input.onContextMenu(e); - } - - function contextMenuInGutter(cm, e) { - if (!hasHandler(cm, "gutterContextMenu")) return false; - return gutterEvent(cm, e, "gutterContextMenu", false, signal); - } - - // UPDATING - - // Compute the position of the end of a change (its 'to' property - // refers to the pre-change end). - var changeEnd = CodeMirror.changeEnd = function(change) { - if (!change.text) return change.to; - return Pos(change.from.line + change.text.length - 1, - lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)); - }; - - // Adjust a position to refer to the post-change position of the - // same text, or the end of the change if the change covers it. - function adjustForChange(pos, change) { - if (cmp(pos, change.from) < 0) return pos; - if (cmp(pos, change.to) <= 0) return changeEnd(change); - - var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; - if (pos.line == change.to.line) ch += changeEnd(change).ch - change.to.ch; - return Pos(line, ch); - } - - function computeSelAfterChange(doc, change) { - var out = []; - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - out.push(new Range(adjustForChange(range.anchor, change), - adjustForChange(range.head, change))); - } - return normalizeSelection(out, doc.sel.primIndex); - } - - function offsetPos(pos, old, nw) { - if (pos.line == old.line) - return Pos(nw.line, pos.ch - old.ch + nw.ch); - else - return Pos(nw.line + (pos.line - old.line), pos.ch); - } - - // Used by replaceSelections to allow moving the selection to the - // start or around the replaced test. Hint may be "start" or "around". - function computeReplacedSel(doc, changes, hint) { - var out = []; - var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; - for (var i = 0; i < changes.length; i++) { - var change = changes[i]; - var from = offsetPos(change.from, oldPrev, newPrev); - var to = offsetPos(changeEnd(change), oldPrev, newPrev); - oldPrev = change.to; - newPrev = to; - if (hint == "around") { - var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; - out[i] = new Range(inv ? to : from, inv ? from : to); - } else { - out[i] = new Range(from, from); - } - } - return new Selection(out, doc.sel.primIndex); - } - - // Allow "beforeChange" event handlers to influence a change - function filterChange(doc, change, update) { - var obj = { - canceled: false, - from: change.from, - to: change.to, - text: change.text, - origin: change.origin, - cancel: function() { this.canceled = true; } - }; - if (update) obj.update = function(from, to, text, origin) { - if (from) this.from = clipPos(doc, from); - if (to) this.to = clipPos(doc, to); - if (text) this.text = text; - if (origin !== undefined) this.origin = origin; - }; - signal(doc, "beforeChange", doc, obj); - if (doc.cm) signal(doc.cm, "beforeChange", doc.cm, obj); - - if (obj.canceled) return null; - return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}; - } - - // Apply a change to a document, and add it to the document's - // history, and propagating it to all linked documents. - function makeChange(doc, change, ignoreReadOnly) { - if (doc.cm) { - if (!doc.cm.curOp) return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly); - if (doc.cm.state.suppressEdits) return; - } - - if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { - change = filterChange(doc, change, true); - if (!change) return; - } - - // Possibly split or suppress the update based on the presence - // of read-only spans in its range. - var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); - if (split) { - for (var i = split.length - 1; i >= 0; --i) - makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}); - } else { - makeChangeInner(doc, change); - } - } - - function makeChangeInner(doc, change) { - if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) return; - var selAfter = computeSelAfterChange(doc, change); - addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); - - makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); - var rebased = []; - - linkedDocs(doc, function(doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); - }); - } - - // Revert a change stored in a document's history. - function makeChangeFromHistory(doc, type, allowSelectionOnly) { - if (doc.cm && doc.cm.state.suppressEdits) return; - - var hist = doc.history, event, selAfter = doc.sel; - var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; - - // Verify that there is a useable event (so that ctrl-z won't - // needlessly clear selection events) - for (var i = 0; i < source.length; i++) { - event = source[i]; - if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) - break; - } - if (i == source.length) return; - hist.lastOrigin = hist.lastSelOrigin = null; - - for (;;) { - event = source.pop(); - if (event.ranges) { - pushSelectionToHistory(event, dest); - if (allowSelectionOnly && !event.equals(doc.sel)) { - setSelection(doc, event, {clearRedo: false}); - return; - } - selAfter = event; - } - else break; - } - - // Build up a reverse change object to add to the opposite history - // stack (redo when undoing, and vice versa). - var antiChanges = []; - pushSelectionToHistory(selAfter, dest); - dest.push({changes: antiChanges, generation: hist.generation}); - hist.generation = event.generation || ++hist.maxGeneration; - - var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); - - for (var i = event.changes.length - 1; i >= 0; --i) { - var change = event.changes[i]; - change.origin = type; - if (filter && !filterChange(doc, change, false)) { - source.length = 0; - return; - } - - antiChanges.push(historyChangeFromChange(doc, change)); - - var after = i ? computeSelAfterChange(doc, change) : lst(source); - makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); - if (!i && doc.cm) doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); - var rebased = []; - - // Propagate to the linked documents - linkedDocs(doc, function(doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); - }); - } - } - - // Sub-views need their line numbers shifted when text is added - // above or below them in the parent document. - function shiftDoc(doc, distance) { - if (distance == 0) return; - doc.first += distance; - doc.sel = new Selection(map(doc.sel.ranges, function(range) { - return new Range(Pos(range.anchor.line + distance, range.anchor.ch), - Pos(range.head.line + distance, range.head.ch)); - }), doc.sel.primIndex); - if (doc.cm) { - regChange(doc.cm, doc.first, doc.first - distance, distance); - for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) - regLineChange(doc.cm, l, "gutter"); - } - } - - // More lower-level change function, handling only a single document - // (not linked ones). - function makeChangeSingleDoc(doc, change, selAfter, spans) { - if (doc.cm && !doc.cm.curOp) - return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans); - - if (change.to.line < doc.first) { - shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); - return; - } - if (change.from.line > doc.lastLine()) return; - - // Clip the change to the size of this doc - if (change.from.line < doc.first) { - var shift = change.text.length - 1 - (doc.first - change.from.line); - shiftDoc(doc, shift); - change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), - text: [lst(change.text)], origin: change.origin}; - } - var last = doc.lastLine(); - if (change.to.line > last) { - change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), - text: [change.text[0]], origin: change.origin}; - } - - change.removed = getBetween(doc, change.from, change.to); - - if (!selAfter) selAfter = computeSelAfterChange(doc, change); - if (doc.cm) makeChangeSingleDocInEditor(doc.cm, change, spans); - else updateDoc(doc, change, spans); - setSelectionNoUndo(doc, selAfter, sel_dontScroll); - } - - // Handle the interaction of a change to a document with the editor - // that this document is part of. - function makeChangeSingleDocInEditor(cm, change, spans) { - var doc = cm.doc, display = cm.display, from = change.from, to = change.to; - - var recomputeMaxLength = false, checkWidthStart = from.line; - if (!cm.options.lineWrapping) { - checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); - doc.iter(checkWidthStart, to.line + 1, function(line) { - if (line == display.maxLine) { - recomputeMaxLength = true; - return true; - } - }); - } - - if (doc.sel.contains(change.from, change.to) > -1) - signalCursorActivity(cm); - - updateDoc(doc, change, spans, estimateHeight(cm)); - - if (!cm.options.lineWrapping) { - doc.iter(checkWidthStart, from.line + change.text.length, function(line) { - var len = lineLength(line); - if (len > display.maxLineLength) { - display.maxLine = line; - display.maxLineLength = len; - display.maxLineChanged = true; - recomputeMaxLength = false; - } - }); - if (recomputeMaxLength) cm.curOp.updateMaxLine = true; - } - - // Adjust frontier, schedule worker - doc.frontier = Math.min(doc.frontier, from.line); - startWorker(cm, 400); - - var lendiff = change.text.length - (to.line - from.line) - 1; - // Remember that these lines changed, for updating the display - if (change.full) - regChange(cm); - else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) - regLineChange(cm, from.line, "text"); - else - regChange(cm, from.line, to.line + 1, lendiff); - - var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); - if (changeHandler || changesHandler) { - var obj = { - from: from, to: to, - text: change.text, - removed: change.removed, - origin: change.origin - }; - if (changeHandler) signalLater(cm, "change", cm, obj); - if (changesHandler) (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); - } - cm.display.selForContextMenu = null; - } - - function replaceRange(doc, code, from, to, origin) { - if (!to) to = from; - if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp; } - if (typeof code == "string") code = doc.splitLines(code); - makeChange(doc, {from: from, to: to, text: code, origin: origin}); - } - - // SCROLLING THINGS INTO VIEW - - // If an editor sits on the top or bottom of the window, partially - // scrolled out of view, this ensures that the cursor is visible. - function maybeScrollWindow(cm, coords) { - if (signalDOMEvent(cm, "scrollCursorIntoView")) return; - - var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; - if (coords.top + box.top < 0) doScroll = true; - else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; - if (doScroll != null && !phantom) { - var scrollNode = elt("div", "\u200b", null, "position: absolute; top: " + - (coords.top - display.viewOffset - paddingTop(cm.display)) + "px; height: " + - (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px; left: " + - coords.left + "px; width: 2px;"); - cm.display.lineSpace.appendChild(scrollNode); - scrollNode.scrollIntoView(doScroll); - cm.display.lineSpace.removeChild(scrollNode); - } - } - - // Scroll a given position into view (immediately), verifying that - // it actually became visible (as line heights are accurately - // measured, the position of something may 'drift' during drawing). - function scrollPosIntoView(cm, pos, end, margin) { - if (margin == null) margin = 0; - for (var limit = 0; limit < 5; limit++) { - var changed = false, coords = cursorCoords(cm, pos); - var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); - var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), - Math.min(coords.top, endCoords.top) - margin, - Math.max(coords.left, endCoords.left), - Math.max(coords.bottom, endCoords.bottom) + margin); - var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; - if (scrollPos.scrollTop != null) { - setScrollTop(cm, scrollPos.scrollTop); - if (Math.abs(cm.doc.scrollTop - startTop) > 1) changed = true; - } - if (scrollPos.scrollLeft != null) { - setScrollLeft(cm, scrollPos.scrollLeft); - if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) changed = true; - } - if (!changed) break; - } - return coords; - } - - // Scroll a given set of coordinates into view (immediately). - function scrollIntoView(cm, x1, y1, x2, y2) { - var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2); - if (scrollPos.scrollTop != null) setScrollTop(cm, scrollPos.scrollTop); - if (scrollPos.scrollLeft != null) setScrollLeft(cm, scrollPos.scrollLeft); - } - - // Calculate a new scroll position needed to scroll the given - // rectangle into view. Returns an object with scrollTop and - // scrollLeft properties. When these are undefined, the - // vertical/horizontal position does not need to be adjusted. - function calculateScrollPos(cm, x1, y1, x2, y2) { - var display = cm.display, snapMargin = textHeight(cm.display); - if (y1 < 0) y1 = 0; - var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; - var screen = displayHeight(cm), result = {}; - if (y2 - y1 > screen) y2 = y1 + screen; - var docBottom = cm.doc.height + paddingVert(display); - var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin; - if (y1 < screentop) { - result.scrollTop = atTop ? 0 : y1; - } else if (y2 > screentop + screen) { - var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen); - if (newTop != screentop) result.scrollTop = newTop; - } - - var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft; - var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0); - var tooWide = x2 - x1 > screenw; - if (tooWide) x2 = x1 + screenw; - if (x1 < 10) - result.scrollLeft = 0; - else if (x1 < screenleft) - result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)); - else if (x2 > screenw + screenleft - 3) - result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw; - return result; - } - - // Store a relative adjustment to the scroll position in the current - // operation (to be applied when the operation finishes). - function addToScrollPos(cm, left, top) { - if (left != null || top != null) resolveScrollToPos(cm); - if (left != null) - cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left; - if (top != null) - cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; - } - - // Make sure that at the end of the operation the current cursor is - // shown. - function ensureCursorVisible(cm) { - resolveScrollToPos(cm); - var cur = cm.getCursor(), from = cur, to = cur; - if (!cm.options.lineWrapping) { - from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur; - to = Pos(cur.line, cur.ch + 1); - } - cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}; - } - - // When an operation has its scrollToPos property set, and another - // scroll action is applied before the end of the operation, this - // 'simulates' scrolling that position into view in a cheap way, so - // that the effect of intermediate scroll commands is not ignored. - function resolveScrollToPos(cm) { - var range = cm.curOp.scrollToPos; - if (range) { - cm.curOp.scrollToPos = null; - var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); - var sPos = calculateScrollPos(cm, Math.min(from.left, to.left), - Math.min(from.top, to.top) - range.margin, - Math.max(from.right, to.right), - Math.max(from.bottom, to.bottom) + range.margin); - cm.scrollTo(sPos.scrollLeft, sPos.scrollTop); - } - } - - // API UTILITIES - - // Indent the given line. The how parameter can be "smart", - // "add"/null, "subtract", or "prev". When aggressive is false - // (typically set to true for forced single-line indents), empty - // lines are not indented, and places where the mode returns Pass - // are left alone. - function indentLine(cm, n, how, aggressive) { - var doc = cm.doc, state; - if (how == null) how = "add"; - if (how == "smart") { - // Fall back to "prev" when the mode doesn't have an indentation - // method. - if (!doc.mode.indent) how = "prev"; - else state = getStateBefore(cm, n); - } - - var tabSize = cm.options.tabSize; - var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); - if (line.stateAfter) line.stateAfter = null; - var curSpaceString = line.text.match(/^\s*/)[0], indentation; - if (!aggressive && !/\S/.test(line.text)) { - indentation = 0; - how = "not"; - } else if (how == "smart") { - indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); - if (indentation == Pass || indentation > 150) { - if (!aggressive) return; - how = "prev"; - } - } - if (how == "prev") { - if (n > doc.first) indentation = countColumn(getLine(doc, n-1).text, null, tabSize); - else indentation = 0; - } else if (how == "add") { - indentation = curSpace + cm.options.indentUnit; - } else if (how == "subtract") { - indentation = curSpace - cm.options.indentUnit; - } else if (typeof how == "number") { - indentation = curSpace + how; - } - indentation = Math.max(0, indentation); - - var indentString = "", pos = 0; - if (cm.options.indentWithTabs) - for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} - if (pos < indentation) indentString += spaceStr(indentation - pos); - - if (indentString != curSpaceString) { - replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); - line.stateAfter = null; - return true; - } else { - // Ensure that, if the cursor was in the whitespace at the start - // of the line, it is moved to the end of that space. - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - if (range.head.line == n && range.head.ch < curSpaceString.length) { - var pos = Pos(n, curSpaceString.length); - replaceOneSelection(doc, i, new Range(pos, pos)); - break; - } - } - } - } - - // Utility for applying a change to a line by handle or number, - // returning the number and optionally registering the line as - // changed. - function changeLine(doc, handle, changeType, op) { - var no = handle, line = handle; - if (typeof handle == "number") line = getLine(doc, clipLine(doc, handle)); - else no = lineNo(handle); - if (no == null) return null; - if (op(line, no) && doc.cm) regLineChange(doc.cm, no, changeType); - return line; - } - - // Helper for deleting text near the selection(s), used to implement - // backspace, delete, and similar functionality. - function deleteNearSelection(cm, compute) { - var ranges = cm.doc.sel.ranges, kill = []; - // Build up a set of ranges to kill first, merging overlapping - // ranges. - for (var i = 0; i < ranges.length; i++) { - var toKill = compute(ranges[i]); - while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { - var replaced = kill.pop(); - if (cmp(replaced.from, toKill.from) < 0) { - toKill.from = replaced.from; - break; - } - } - kill.push(toKill); - } - // Next, remove those actual ranges. - runInOp(cm, function() { - for (var i = kill.length - 1; i >= 0; i--) - replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); - ensureCursorVisible(cm); - }); - } - - // Used for horizontal relative motion. Dir is -1 or 1 (left or - // right), unit can be "char", "column" (like char, but doesn't - // cross line boundaries), "word" (across next word), or "group" (to - // the start of next group of word or non-word-non-whitespace - // chars). The visually param controls whether, in right-to-left - // text, direction 1 means to move towards the next index in the - // string, or towards the character to the right of the current - // position. The resulting position will have a hitSide=true - // property if it reached the end of the document. - function findPosH(doc, pos, dir, unit, visually) { - var line = pos.line, ch = pos.ch, origDir = dir; - var lineObj = getLine(doc, line); - var possible = true; - function findNextLine() { - var l = line + dir; - if (l < doc.first || l >= doc.first + doc.size) return (possible = false); - line = l; - return lineObj = getLine(doc, l); - } - function moveOnce(boundToLine) { - var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true); - if (next == null) { - if (!boundToLine && findNextLine()) { - if (visually) ch = (dir < 0 ? lineRight : lineLeft)(lineObj); - else ch = dir < 0 ? lineObj.text.length : 0; - } else return (possible = false); - } else ch = next; - return true; - } - - if (unit == "char") moveOnce(); - else if (unit == "column") moveOnce(true); - else if (unit == "word" || unit == "group") { - var sawType = null, group = unit == "group"; - var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); - for (var first = true;; first = false) { - if (dir < 0 && !moveOnce(!first)) break; - var cur = lineObj.text.charAt(ch) || "\n"; - var type = isWordChar(cur, helper) ? "w" - : group && cur == "\n" ? "n" - : !group || /\s/.test(cur) ? null - : "p"; - if (group && !first && !type) type = "s"; - if (sawType && sawType != type) { - if (dir < 0) {dir = 1; moveOnce();} - break; - } - - if (type) sawType = type; - if (dir > 0 && !moveOnce(!first)) break; - } - } - var result = skipAtomic(doc, Pos(line, ch), origDir, true); - if (!possible) result.hitSide = true; - return result; - } - - // For relative vertical movement. Dir may be -1 or 1. Unit can be - // "page" or "line". The resulting position will have a hitSide=true - // property if it reached the end of the document. - function findPosV(cm, pos, dir, unit) { - var doc = cm.doc, x = pos.left, y; - if (unit == "page") { - var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); - y = pos.top + dir * (pageSize - (dir < 0 ? 1.5 : .5) * textHeight(cm.display)); - } else if (unit == "line") { - y = dir > 0 ? pos.bottom + 3 : pos.top - 3; - } - for (;;) { - var target = coordsChar(cm, x, y); - if (!target.outside) break; - if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break; } - y += dir * 5; - } - return target; - } - - // EDITOR METHODS - - // The publicly visible API. Note that methodOp(f) means - // 'wrap f in an operation, performed on its `this` parameter'. - - // This is not the complete set of editor methods. Most of the - // methods defined on the Doc type are also injected into - // CodeMirror.prototype, for backwards compatibility and - // convenience. - - CodeMirror.prototype = { - constructor: CodeMirror, - focus: function(){window.focus(); this.display.input.focus();}, - - setOption: function(option, value) { - var options = this.options, old = options[option]; - if (options[option] == value && option != "mode") return; - options[option] = value; - if (optionHandlers.hasOwnProperty(option)) - operation(this, optionHandlers[option])(this, value, old); - }, - - getOption: function(option) {return this.options[option];}, - getDoc: function() {return this.doc;}, - - addKeyMap: function(map, bottom) { - this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); - }, - removeKeyMap: function(map) { - var maps = this.state.keyMaps; - for (var i = 0; i < maps.length; ++i) - if (maps[i] == map || maps[i].name == map) { - maps.splice(i, 1); - return true; - } - }, - - addOverlay: methodOp(function(spec, options) { - var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); - if (mode.startState) throw new Error("Overlays may not be stateful."); - this.state.overlays.push({mode: mode, modeSpec: spec, opaque: options && options.opaque}); - this.state.modeGen++; - regChange(this); - }), - removeOverlay: methodOp(function(spec) { - var overlays = this.state.overlays; - for (var i = 0; i < overlays.length; ++i) { - var cur = overlays[i].modeSpec; - if (cur == spec || typeof spec == "string" && cur.name == spec) { - overlays.splice(i, 1); - this.state.modeGen++; - regChange(this); - return; - } - } - }), - - indentLine: methodOp(function(n, dir, aggressive) { - if (typeof dir != "string" && typeof dir != "number") { - if (dir == null) dir = this.options.smartIndent ? "smart" : "prev"; - else dir = dir ? "add" : "subtract"; - } - if (isLine(this.doc, n)) indentLine(this, n, dir, aggressive); - }), - indentSelection: methodOp(function(how) { - var ranges = this.doc.sel.ranges, end = -1; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (!range.empty()) { - var from = range.from(), to = range.to(); - var start = Math.max(end, from.line); - end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; - for (var j = start; j < end; ++j) - indentLine(this, j, how); - var newRanges = this.doc.sel.ranges; - if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) - replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); - } else if (range.head.line > end) { - indentLine(this, range.head.line, how, true); - end = range.head.line; - if (i == this.doc.sel.primIndex) ensureCursorVisible(this); - } - } - }), - - // Fetch the parser token for a given character. Useful for hacks - // that want to inspect the mode state (say, for completion). - getTokenAt: function(pos, precise) { - return takeToken(this, pos, precise); - }, - - getLineTokens: function(line, precise) { - return takeToken(this, Pos(line), precise, true); - }, - - getTokenTypeAt: function(pos) { - pos = clipPos(this.doc, pos); - var styles = getLineStyles(this, getLine(this.doc, pos.line)); - var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; - var type; - if (ch == 0) type = styles[2]; - else for (;;) { - var mid = (before + after) >> 1; - if ((mid ? styles[mid * 2 - 1] : 0) >= ch) after = mid; - else if (styles[mid * 2 + 1] < ch) before = mid + 1; - else { type = styles[mid * 2 + 2]; break; } - } - var cut = type ? type.indexOf("cm-overlay ") : -1; - return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1); - }, - - getModeAt: function(pos) { - var mode = this.doc.mode; - if (!mode.innerMode) return mode; - return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode; - }, - - getHelper: function(pos, type) { - return this.getHelpers(pos, type)[0]; - }, - - getHelpers: function(pos, type) { - var found = []; - if (!helpers.hasOwnProperty(type)) return found; - var help = helpers[type], mode = this.getModeAt(pos); - if (typeof mode[type] == "string") { - if (help[mode[type]]) found.push(help[mode[type]]); - } else if (mode[type]) { - for (var i = 0; i < mode[type].length; i++) { - var val = help[mode[type][i]]; - if (val) found.push(val); - } - } else if (mode.helperType && help[mode.helperType]) { - found.push(help[mode.helperType]); - } else if (help[mode.name]) { - found.push(help[mode.name]); - } - for (var i = 0; i < help._global.length; i++) { - var cur = help._global[i]; - if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) - found.push(cur.val); - } - return found; - }, - - getStateAfter: function(line, precise) { - var doc = this.doc; - line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); - return getStateBefore(this, line + 1, precise); - }, - - cursorCoords: function(start, mode) { - var pos, range = this.doc.sel.primary(); - if (start == null) pos = range.head; - else if (typeof start == "object") pos = clipPos(this.doc, start); - else pos = start ? range.from() : range.to(); - return cursorCoords(this, pos, mode || "page"); - }, - - charCoords: function(pos, mode) { - return charCoords(this, clipPos(this.doc, pos), mode || "page"); - }, - - coordsChar: function(coords, mode) { - coords = fromCoordSystem(this, coords, mode || "page"); - return coordsChar(this, coords.left, coords.top); - }, - - lineAtHeight: function(height, mode) { - height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; - return lineAtHeight(this.doc, height + this.display.viewOffset); - }, - heightAtLine: function(line, mode) { - var end = false, lineObj; - if (typeof line == "number") { - var last = this.doc.first + this.doc.size - 1; - if (line < this.doc.first) line = this.doc.first; - else if (line > last) { line = last; end = true; } - lineObj = getLine(this.doc, line); - } else { - lineObj = line; - } - return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page").top + - (end ? this.doc.height - heightAtLine(lineObj) : 0); - }, - - defaultTextHeight: function() { return textHeight(this.display); }, - defaultCharWidth: function() { return charWidth(this.display); }, - - setGutterMarker: methodOp(function(line, gutterID, value) { - return changeLine(this.doc, line, "gutter", function(line) { - var markers = line.gutterMarkers || (line.gutterMarkers = {}); - markers[gutterID] = value; - if (!value && isEmpty(markers)) line.gutterMarkers = null; - return true; - }); - }), - - clearGutter: methodOp(function(gutterID) { - var cm = this, doc = cm.doc, i = doc.first; - doc.iter(function(line) { - if (line.gutterMarkers && line.gutterMarkers[gutterID]) { - line.gutterMarkers[gutterID] = null; - regLineChange(cm, i, "gutter"); - if (isEmpty(line.gutterMarkers)) line.gutterMarkers = null; - } - ++i; - }); - }), - - lineInfo: function(line) { - if (typeof line == "number") { - if (!isLine(this.doc, line)) return null; - var n = line; - line = getLine(this.doc, line); - if (!line) return null; - } else { - var n = lineNo(line); - if (n == null) return null; - } - return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, - textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, - widgets: line.widgets}; - }, - - getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo};}, - - addWidget: function(pos, node, scroll, vert, horiz) { - var display = this.display; - pos = cursorCoords(this, clipPos(this.doc, pos)); - var top = pos.bottom, left = pos.left; - node.style.position = "absolute"; - node.setAttribute("cm-ignore-events", "true"); - this.display.input.setUneditable(node); - display.sizer.appendChild(node); - if (vert == "over") { - top = pos.top; - } else if (vert == "above" || vert == "near") { - var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), - hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); - // Default to positioning above (if specified and possible); otherwise default to positioning below - if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) - top = pos.top - node.offsetHeight; - else if (pos.bottom + node.offsetHeight <= vspace) - top = pos.bottom; - if (left + node.offsetWidth > hspace) - left = hspace - node.offsetWidth; - } - node.style.top = top + "px"; - node.style.left = node.style.right = ""; - if (horiz == "right") { - left = display.sizer.clientWidth - node.offsetWidth; - node.style.right = "0px"; - } else { - if (horiz == "left") left = 0; - else if (horiz == "middle") left = (display.sizer.clientWidth - node.offsetWidth) / 2; - node.style.left = left + "px"; - } - if (scroll) - scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight); - }, - - triggerOnKeyDown: methodOp(onKeyDown), - triggerOnKeyPress: methodOp(onKeyPress), - triggerOnKeyUp: onKeyUp, - - execCommand: function(cmd) { - if (commands.hasOwnProperty(cmd)) - return commands[cmd].call(null, this); - }, - - triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), - - findPosH: function(from, amount, unit, visually) { - var dir = 1; - if (amount < 0) { dir = -1; amount = -amount; } - for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { - cur = findPosH(this.doc, cur, dir, unit, visually); - if (cur.hitSide) break; - } - return cur; - }, - - moveH: methodOp(function(dir, unit) { - var cm = this; - cm.extendSelectionsBy(function(range) { - if (cm.display.shift || cm.doc.extend || range.empty()) - return findPosH(cm.doc, range.head, dir, unit, cm.options.rtlMoveVisually); - else - return dir < 0 ? range.from() : range.to(); - }, sel_move); - }), - - deleteH: methodOp(function(dir, unit) { - var sel = this.doc.sel, doc = this.doc; - if (sel.somethingSelected()) - doc.replaceSelection("", null, "+delete"); - else - deleteNearSelection(this, function(range) { - var other = findPosH(doc, range.head, dir, unit, false); - return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}; - }); - }), - - findPosV: function(from, amount, unit, goalColumn) { - var dir = 1, x = goalColumn; - if (amount < 0) { dir = -1; amount = -amount; } - for (var i = 0, cur = clipPos(this.doc, from); i < amount; ++i) { - var coords = cursorCoords(this, cur, "div"); - if (x == null) x = coords.left; - else coords.left = x; - cur = findPosV(this, coords, dir, unit); - if (cur.hitSide) break; - } - return cur; - }, - - moveV: methodOp(function(dir, unit) { - var cm = this, doc = this.doc, goals = []; - var collapse = !cm.display.shift && !doc.extend && doc.sel.somethingSelected(); - doc.extendSelectionsBy(function(range) { - if (collapse) - return dir < 0 ? range.from() : range.to(); - var headPos = cursorCoords(cm, range.head, "div"); - if (range.goalColumn != null) headPos.left = range.goalColumn; - goals.push(headPos.left); - var pos = findPosV(cm, headPos, dir, unit); - if (unit == "page" && range == doc.sel.primary()) - addToScrollPos(cm, null, charCoords(cm, pos, "div").top - headPos.top); - return pos; - }, sel_move); - if (goals.length) for (var i = 0; i < doc.sel.ranges.length; i++) - doc.sel.ranges[i].goalColumn = goals[i]; - }), - - // Find the word at the given position (as returned by coordsChar). - findWordAt: function(pos) { - var doc = this.doc, line = getLine(doc, pos.line).text; - var start = pos.ch, end = pos.ch; - if (line) { - var helper = this.getHelper(pos, "wordChars"); - if ((pos.xRel < 0 || end == line.length) && start) --start; else ++end; - var startChar = line.charAt(start); - var check = isWordChar(startChar, helper) - ? function(ch) { return isWordChar(ch, helper); } - : /\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 new Range(Pos(pos.line, start), Pos(pos.line, end)); - }, - - toggleOverwrite: function(value) { - if (value != null && value == this.state.overwrite) return; - if (this.state.overwrite = !this.state.overwrite) - addClass(this.display.cursorDiv, "CodeMirror-overwrite"); - else - rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); - - signal(this, "overwriteToggle", this, this.state.overwrite); - }, - hasFocus: function() { return this.display.input.getField() == activeElt(); }, - - scrollTo: methodOp(function(x, y) { - if (x != null || y != null) resolveScrollToPos(this); - if (x != null) this.curOp.scrollLeft = x; - if (y != null) this.curOp.scrollTop = y; - }), - getScrollInfo: function() { - var scroller = this.display.scroller; - return {left: scroller.scrollLeft, top: scroller.scrollTop, - height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, - width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, - clientHeight: displayHeight(this), clientWidth: displayWidth(this)}; - }, - - scrollIntoView: methodOp(function(range, margin) { - if (range == null) { - range = {from: this.doc.sel.primary().head, to: null}; - if (margin == null) margin = this.options.cursorScrollMargin; - } else if (typeof range == "number") { - range = {from: Pos(range, 0), to: null}; - } else if (range.from == null) { - range = {from: range, to: null}; - } - if (!range.to) range.to = range.from; - range.margin = margin || 0; - - if (range.from.line != null) { - resolveScrollToPos(this); - this.curOp.scrollToPos = range; - } else { - var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left), - Math.min(range.from.top, range.to.top) - range.margin, - Math.max(range.from.right, range.to.right), - Math.max(range.from.bottom, range.to.bottom) + range.margin); - this.scrollTo(sPos.scrollLeft, sPos.scrollTop); - } - }), - - setSize: methodOp(function(width, height) { - var cm = this; - function interpret(val) { - return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; - } - if (width != null) cm.display.wrapper.style.width = interpret(width); - if (height != null) cm.display.wrapper.style.height = interpret(height); - if (cm.options.lineWrapping) clearLineMeasurementCache(this); - var lineNo = cm.display.viewFrom; - cm.doc.iter(lineNo, cm.display.viewTo, function(line) { - if (line.widgets) for (var i = 0; i < line.widgets.length; i++) - if (line.widgets[i].noHScroll) { regLineChange(cm, lineNo, "widget"); break; } - ++lineNo; - }); - cm.curOp.forceUpdate = true; - signal(cm, "refresh", this); - }), - - operation: function(f){return runInOp(this, f);}, - - refresh: methodOp(function() { - var oldHeight = this.display.cachedTextHeight; - regChange(this); - this.curOp.forceUpdate = true; - clearCaches(this); - this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop); - updateGutterSpace(this); - if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) - estimateLineHeights(this); - signal(this, "refresh", this); - }), - - swapDoc: methodOp(function(doc) { - var old = this.doc; - old.cm = null; - attachDoc(this, doc); - clearCaches(this); - this.display.input.reset(); - this.scrollTo(doc.scrollLeft, doc.scrollTop); - this.curOp.forceScroll = true; - signalLater(this, "swapDoc", this, old); - return old; - }), - - getInputField: function(){return this.display.input.getField();}, - getWrapperElement: function(){return this.display.wrapper;}, - getScrollerElement: function(){return this.display.scroller;}, - getGutterElement: function(){return this.display.gutters;} - }; - eventMixin(CodeMirror); - - // OPTION DEFAULTS - - // The default configuration options. - var defaults = CodeMirror.defaults = {}; - // Functions to run when options are changed. - var optionHandlers = CodeMirror.optionHandlers = {}; - - function option(name, deflt, handle, notOnInit) { - CodeMirror.defaults[name] = deflt; - if (handle) optionHandlers[name] = - notOnInit ? function(cm, val, old) {if (old != Init) handle(cm, val, old);} : handle; - } - - // Passed to option handlers when there is no old value. - var Init = CodeMirror.Init = {toString: function(){return "CodeMirror.Init";}}; - - // These two are, on init, called from the constructor because they - // have to be initialized before the editor can start at all. - option("value", "", function(cm, val) { - cm.setValue(val); - }, true); - option("mode", null, function(cm, val) { - cm.doc.modeOption = val; - loadMode(cm); - }, true); - - option("indentUnit", 2, loadMode, true); - option("indentWithTabs", false); - option("smartIndent", true); - option("tabSize", 4, function(cm) { - resetModeState(cm); - clearCaches(cm); - regChange(cm); - }, true); - option("lineSeparator", null, function(cm, val) { - cm.doc.lineSep = val; - if (!val) return; - var newBreaks = [], lineNo = cm.doc.first; - cm.doc.iter(function(line) { - for (var pos = 0;;) { - var found = line.text.indexOf(val, pos); - if (found == -1) break; - pos = found + val.length; - newBreaks.push(Pos(lineNo, found)); - } - lineNo++; - }); - for (var i = newBreaks.length - 1; i >= 0; i--) - replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) - }); - option("specialChars", /[\t\u0000-\u0019\u00ad\u200b-\u200f\u2028\u2029\ufeff]/g, function(cm, val, old) { - cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); - if (old != CodeMirror.Init) cm.refresh(); - }); - option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function(cm) {cm.refresh();}, true); - option("electricChars", true); - option("inputStyle", mobile ? "contenteditable" : "textarea", function() { - throw new Error("inputStyle can not (yet) be changed in a running editor"); // FIXME - }, true); - option("rtlMoveVisually", !windows); - option("wholeLineUpdateBefore", true); - - option("theme", "default", function(cm) { - themeChanged(cm); - guttersChanged(cm); - }, true); - option("keyMap", "default", function(cm, val, old) { - var next = getKeyMap(val); - var prev = old != CodeMirror.Init && getKeyMap(old); - if (prev && prev.detach) prev.detach(cm, next); - if (next.attach) next.attach(cm, prev || null); - }); - option("extraKeys", null); - - option("lineWrapping", false, wrappingChanged, true); - option("gutters", [], function(cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); - }, true); - option("fixedGutter", true, function(cm, val) { - cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; - cm.refresh(); - }, true); - option("coverGutterNextToScrollbar", false, function(cm) {updateScrollbars(cm);}, true); - option("scrollbarStyle", "native", function(cm) { - initScrollbars(cm); - updateScrollbars(cm); - cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); - cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); - }, true); - option("lineNumbers", false, function(cm) { - setGuttersForLineNumbers(cm.options); - guttersChanged(cm); - }, true); - option("firstLineNumber", 1, guttersChanged, true); - option("lineNumberFormatter", function(integer) {return integer;}, guttersChanged, true); - option("showCursorWhenSelecting", false, updateSelection, true); - - option("resetSelectionOnContextMenu", true); - option("lineWiseCopyCut", true); - - option("readOnly", false, function(cm, val) { - if (val == "nocursor") { - onBlur(cm); - cm.display.input.blur(); - cm.display.disabled = true; - } else { - cm.display.disabled = false; - } - cm.display.input.readOnlyChanged(val) - }); - option("disableInput", false, function(cm, val) {if (!val) cm.display.input.reset();}, true); - option("dragDrop", true, dragDropChanged); - option("allowDropFileTypes", null); - - option("cursorBlinkRate", 530); - option("cursorScrollMargin", 0); - option("cursorHeight", 1, updateSelection, true); - option("singleCursorHeightPerLine", true, updateSelection, true); - option("workTime", 100); - option("workDelay", 100); - option("flattenSpans", true, resetModeState, true); - option("addModeClass", false, resetModeState, true); - option("pollInterval", 100); - option("undoDepth", 200, function(cm, val){cm.doc.history.undoDepth = val;}); - option("historyEventDelay", 1250); - option("viewportMargin", 10, function(cm){cm.refresh();}, true); - option("maxHighlightLength", 10000, resetModeState, true); - option("moveInputWithCursor", true, function(cm, val) { - if (!val) cm.display.input.resetPosition(); - }); - - option("tabindex", null, function(cm, val) { - cm.display.input.getField().tabIndex = val || ""; - }); - option("autofocus", null); - - // MODE DEFINITION AND QUERYING - - // Known modes, by name and by MIME - var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; - - // Extra arguments are stored as the mode's dependencies, which is - // used by (legacy) mechanisms like loadmode.js to automatically - // load a mode. (Preferred mechanism is the require/define calls.) - CodeMirror.defineMode = function(name, mode) { - if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; - if (arguments.length > 2) - mode.dependencies = Array.prototype.slice.call(arguments, 2); - modes[name] = mode; - }; - - CodeMirror.defineMIME = function(mime, spec) { - mimeModes[mime] = spec; - }; - - // Given a MIME type, a {name, ...options} config object, or a name - // string, return a mode config object. - CodeMirror.resolveMode = function(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { - spec = mimeModes[spec]; - } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { - var found = mimeModes[spec.name]; - if (typeof found == "string") found = {name: found}; - spec = createObj(found, spec); - spec.name = found.name; - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { - return CodeMirror.resolveMode("application/xml"); - } - if (typeof spec == "string") return {name: spec}; - else return spec || {name: "null"}; - }; - - // Given a mode spec (anything that resolveMode accepts), find and - // initialize an actual mode object. - 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)) continue; - if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; - modeObj[prop] = exts[prop]; - } - } - modeObj.name = spec.name; - if (spec.helperType) modeObj.helperType = spec.helperType; - if (spec.modeProps) for (var prop in spec.modeProps) - modeObj[prop] = spec.modeProps[prop]; - - return modeObj; - }; - - // Minimal default mode. - CodeMirror.defineMode("null", function() { - return {token: function(stream) {stream.skipToEnd();}}; - }); - CodeMirror.defineMIME("text/plain", "null"); - - // This can be used to attach properties to mode objects from - // outside the actual mode definition. - var modeExtensions = CodeMirror.modeExtensions = {}; - CodeMirror.extendMode = function(mode, properties) { - var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); - copyObj(properties, exts); - }; - - // EXTENSIONS - - CodeMirror.defineExtension = function(name, func) { - CodeMirror.prototype[name] = func; - }; - CodeMirror.defineDocExtension = function(name, func) { - Doc.prototype[name] = func; - }; - CodeMirror.defineOption = option; - - var initHooks = []; - CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; - - var helpers = CodeMirror.helpers = {}; - CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) helpers[type] = CodeMirror[type] = {_global: []}; - helpers[type][name] = value; - }; - CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { - CodeMirror.registerHelper(type, name, value); - helpers[type]._global.push({pred: predicate, val: value}); - }; - - // MODE STATE HANDLING - - // Utility functions for working with state. Exported because nested - // modes need to do this for their inner modes. - - var copyState = CodeMirror.copyState = function(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; - }; - - var startState = CodeMirror.startState = function(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true; - }; - - // Given a mode and a state (for that mode), find the inner mode and - // state at the position that the state refers to. - CodeMirror.innerMode = function(mode, state) { - while (mode.innerMode) { - var info = mode.innerMode(state); - if (!info || info.mode == mode) break; - state = info.state; - mode = info.mode; - } - return info || {mode: mode, state: state}; - }; - - // STANDARD COMMANDS - - // Commands are parameter-less actions that can be performed on an - // editor, mostly used for keybindings. - var commands = CodeMirror.commands = { - selectAll: function(cm) {cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll);}, - singleSelection: function(cm) { - cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); - }, - killLine: function(cm) { - deleteNearSelection(cm, function(range) { - if (range.empty()) { - var len = getLine(cm.doc, range.head.line).text.length; - if (range.head.ch == len && range.head.line < cm.lastLine()) - return {from: range.head, to: Pos(range.head.line + 1, 0)}; - else - return {from: range.head, to: Pos(range.head.line, len)}; - } else { - return {from: range.from(), to: range.to()}; - } - }); - }, - deleteLine: function(cm) { - deleteNearSelection(cm, function(range) { - return {from: Pos(range.from().line, 0), - to: clipPos(cm.doc, Pos(range.to().line + 1, 0))}; - }); - }, - delLineLeft: function(cm) { - deleteNearSelection(cm, function(range) { - return {from: Pos(range.from().line, 0), to: range.from()}; - }); - }, - delWrappedLineLeft: function(cm) { - deleteNearSelection(cm, function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var leftPos = cm.coordsChar({left: 0, top: top}, "div"); - return {from: leftPos, to: range.from()}; - }); - }, - delWrappedLineRight: function(cm) { - deleteNearSelection(cm, function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); - return {from: range.from(), to: rightPos }; - }); - }, - undo: function(cm) {cm.undo();}, - redo: function(cm) {cm.redo();}, - undoSelection: function(cm) {cm.undoSelection();}, - redoSelection: function(cm) {cm.redoSelection();}, - goDocStart: function(cm) {cm.extendSelection(Pos(cm.firstLine(), 0));}, - goDocEnd: function(cm) {cm.extendSelection(Pos(cm.lastLine()));}, - goLineStart: function(cm) { - cm.extendSelectionsBy(function(range) { return lineStart(cm, range.head.line); }, - {origin: "+move", bias: 1}); - }, - goLineStartSmart: function(cm) { - cm.extendSelectionsBy(function(range) { - return lineStartSmart(cm, range.head); - }, {origin: "+move", bias: 1}); - }, - goLineEnd: function(cm) { - cm.extendSelectionsBy(function(range) { return lineEnd(cm, range.head.line); }, - {origin: "+move", bias: -1}); - }, - goLineRight: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); - }, sel_move); - }, - goLineLeft: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - return cm.coordsChar({left: 0, top: top}, "div"); - }, sel_move); - }, - goLineLeftSmart: function(cm) { - cm.extendSelectionsBy(function(range) { - var top = cm.charCoords(range.head, "div").top + 5; - var pos = cm.coordsChar({left: 0, top: top}, "div"); - if (pos.ch < cm.getLine(pos.line).search(/\S/)) return lineStartSmart(cm, range.head); - return pos; - }, sel_move); - }, - 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");}, - goGroupRight: function(cm) {cm.moveH(1, "group");}, - goGroupLeft: function(cm) {cm.moveH(-1, "group");}, - goWordRight: function(cm) {cm.moveH(1, "word");}, - delCharBefore: function(cm) {cm.deleteH(-1, "char");}, - delCharAfter: function(cm) {cm.deleteH(1, "char");}, - delWordBefore: function(cm) {cm.deleteH(-1, "word");}, - delWordAfter: function(cm) {cm.deleteH(1, "word");}, - delGroupBefore: function(cm) {cm.deleteH(-1, "group");}, - delGroupAfter: function(cm) {cm.deleteH(1, "group");}, - indentAuto: function(cm) {cm.indentSelection("smart");}, - indentMore: function(cm) {cm.indentSelection("add");}, - indentLess: function(cm) {cm.indentSelection("subtract");}, - insertTab: function(cm) {cm.replaceSelection("\t");}, - insertSoftTab: function(cm) { - var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].from(); - var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); - spaces.push(new Array(tabSize - col % tabSize + 1).join(" ")); - } - cm.replaceSelections(spaces); - }, - defaultTab: function(cm) { - if (cm.somethingSelected()) cm.indentSelection("add"); - else cm.execCommand("insertTab"); - }, - transposeChars: function(cm) { - runInOp(cm, function() { - var ranges = cm.listSelections(), newSel = []; - for (var i = 0; i < ranges.length; i++) { - var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; - if (line) { - if (cur.ch == line.length) cur = new Pos(cur.line, cur.ch - 1); - if (cur.ch > 0) { - cur = new Pos(cur.line, cur.ch + 1); - cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), - Pos(cur.line, cur.ch - 2), cur, "+transpose"); - } else if (cur.line > cm.doc.first) { - var prev = getLine(cm.doc, cur.line - 1).text; - if (prev) - cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + - prev.charAt(prev.length - 1), - Pos(cur.line - 1, prev.length - 1), Pos(cur.line, 1), "+transpose"); - } - } - newSel.push(new Range(cur, cur)); - } - cm.setSelections(newSel); - }); - }, - newlineAndIndent: function(cm) { - runInOp(cm, function() { - var len = cm.listSelections().length; - for (var i = 0; i < len; i++) { - var range = cm.listSelections()[i]; - cm.replaceRange(cm.doc.lineSeparator(), range.anchor, range.head, "+input"); - cm.indentLine(range.from().line + 1, null, true); - } - ensureCursorVisible(cm); - }); - }, - toggleOverwrite: function(cm) {cm.toggleOverwrite();} - }; - - - // STANDARD KEYMAPS - - var keyMap = CodeMirror.keyMap = {}; - - keyMap.basic = { - "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", - "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", - "Tab": "defaultTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", - "Esc": "singleSelection" - }; - // Note that the save and find-related commands aren't defined by - // default. User code or addons can define them. Unknown commands - // are simply ignored. - keyMap.pcDefault = { - "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", - "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "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", - "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", - fallthrough: "basic" - }; - // Very basic readline/emacs-style bindings, which are standard on Mac. - 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": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" - }; - keyMap.macDefault = { - "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", - "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", - "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "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", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", - "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", - fallthrough: ["basic", "emacsy"] - }; - keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; - - // KEYMAP DISPATCH - - function normalizeKeyName(name) { - var parts = name.split(/-(?!$)/), name = parts[parts.length - 1]; - var alt, ctrl, shift, cmd; - for (var i = 0; i < parts.length - 1; i++) { - var mod = parts[i]; - if (/^(cmd|meta|m)$/i.test(mod)) cmd = true; - else if (/^a(lt)?$/i.test(mod)) alt = true; - else if (/^(c|ctrl|control)$/i.test(mod)) ctrl = true; - else if (/^s(hift)$/i.test(mod)) shift = true; - else throw new Error("Unrecognized modifier name: " + mod); - } - if (alt) name = "Alt-" + name; - if (ctrl) name = "Ctrl-" + name; - if (cmd) name = "Cmd-" + name; - if (shift) name = "Shift-" + name; - return name; - } - - // This is a kludge to keep keymaps mostly working as raw objects - // (backwards compatibility) while at the same time support features - // like normalization and multi-stroke key bindings. It compiles a - // new normalized keymap, and then updates the old object to reflect - // this. - CodeMirror.normalizeKeyMap = function(keymap) { - var copy = {}; - for (var keyname in keymap) if (keymap.hasOwnProperty(keyname)) { - var value = keymap[keyname]; - if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) continue; - if (value == "...") { delete keymap[keyname]; continue; } - - var keys = map(keyname.split(" "), normalizeKeyName); - for (var i = 0; i < keys.length; i++) { - var val, name; - if (i == keys.length - 1) { - name = keys.join(" "); - val = value; - } else { - name = keys.slice(0, i + 1).join(" "); - val = "..."; - } - var prev = copy[name]; - if (!prev) copy[name] = val; - else if (prev != val) throw new Error("Inconsistent bindings for " + name); - } - delete keymap[keyname]; - } - for (var prop in copy) keymap[prop] = copy[prop]; - return keymap; - }; - - var lookupKey = CodeMirror.lookupKey = function(key, map, handle, context) { - map = getKeyMap(map); - var found = map.call ? map.call(key, context) : map[key]; - if (found === false) return "nothing"; - if (found === "...") return "multi"; - if (found != null && handle(found)) return "handled"; - - if (map.fallthrough) { - if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") - return lookupKey(key, map.fallthrough, handle, context); - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle, context); - if (result) return result; - } - } - }; - - // Modifier key presses don't count as 'real' key presses for the - // purpose of keymap fallthrough. - var isModifierKey = CodeMirror.isModifierKey = function(value) { - var name = typeof value == "string" ? value : keyNames[value.keyCode]; - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; - }; - - // Look up the name of a key as indicated by an event object. - var keyName = CodeMirror.keyName = function(event, noShift) { - if (presto && event.keyCode == 34 && event["char"]) return false; - var base = keyNames[event.keyCode], name = base; - if (name == null || event.altGraphKey) return false; - if (event.altKey && base != "Alt") name = "Alt-" + name; - if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") name = "Ctrl-" + name; - if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") name = "Cmd-" + name; - if (!noShift && event.shiftKey && base != "Shift") name = "Shift-" + name; - return name; - }; - - function getKeyMap(val) { - return typeof val == "string" ? keyMap[val] : val; - } - - // FROMTEXTAREA - - CodeMirror.fromTextArea = function(textarea, options) { - options = options ? copyObj(options) : {}; - options.value = textarea.value; - if (!options.tabindex && textarea.tabIndex) - options.tabindex = textarea.tabIndex; - if (!options.placeholder && textarea.placeholder) - options.placeholder = textarea.placeholder; - // Set autofocus to true if this textarea is focused, or if it has - // autofocus and no other element is focused. - if (options.autofocus == null) { - var hasFocus = activeElt(); - options.autofocus = hasFocus == textarea || - textarea.getAttribute("autofocus") != null && hasFocus == document.body; - } - - function save() {textarea.value = cm.getValue();} - if (textarea.form) { - on(textarea.form, "submit", save); - // Deplorable hack to make the submit method do the right thing. - if (!options.leaveSubmitMethodAlone) { - var form = textarea.form, realSubmit = form.submit; - try { - var wrappedSubmit = form.submit = function() { - save(); - form.submit = realSubmit; - form.submit(); - form.submit = wrappedSubmit; - }; - } catch(e) {} - } - } - - options.finishInit = function(cm) { - cm.save = save; - cm.getTextArea = function() { return textarea; }; - cm.toTextArea = function() { - cm.toTextArea = isNaN; // Prevent this from being ran twice - save(); - textarea.parentNode.removeChild(cm.getWrapperElement()); - textarea.style.display = ""; - if (textarea.form) { - off(textarea.form, "submit", save); - if (typeof textarea.form.submit == "function") - textarea.form.submit = realSubmit; - } - }; - }; - - textarea.style.display = "none"; - var cm = CodeMirror(function(node) { - textarea.parentNode.insertBefore(node, textarea.nextSibling); - }, options); - return cm; - }; - - // STRING STREAM - - // Fed to the mode parsers, provides helper functions to make - // parsers more succinct. - - var StringStream = CodeMirror.StringStream = function(string, tabSize) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - this.lastColumnPos = this.lastColumnValue = 0; - this.lineStart = 0; - }; - - StringStream.prototype = { - eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == this.lineStart;}, - 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() { - if (this.lastColumnPos < this.start) { - this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); - this.lastColumnPos = this.start; - } - return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); - }, - indentation: function() { - return countColumn(this.string, null, this.tabSize) - - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0); - }, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; - var substr = this.string.substr(this.pos, pattern.length); - if (cased(substr) == cased(pattern)) { - if (consume !== false) this.pos += pattern.length; - return true; - } - } else { - var match = this.string.slice(this.pos).match(pattern); - if (match && match.index > 0) return null; - if (match && consume !== false) this.pos += match[0].length; - return match; - } - }, - current: function(){return this.string.slice(this.start, this.pos);}, - hideFirstChars: function(n, inner) { - this.lineStart += n; - try { return inner(); } - finally { this.lineStart -= n; } - } - }; - - // TEXTMARKERS - - // Created with markText and setBookmark methods. A TextMarker is a - // handle that can be used to clear or find a marked position in the - // document. Line objects hold arrays (markedSpans) containing - // {from, to, marker} object pointing to such marker objects, and - // indicating that such a marker is present on that line. Multiple - // lines may point to the same marker when it spans across lines. - // The spans will have null for their from/to properties when the - // marker continues beyond the start/end of the line. Markers have - // links back to the lines they currently touch. - - var nextMarkerId = 0; - - var TextMarker = CodeMirror.TextMarker = function(doc, type) { - this.lines = []; - this.type = type; - this.doc = doc; - this.id = ++nextMarkerId; - }; - eventMixin(TextMarker); - - // Clear the marker. - TextMarker.prototype.clear = function() { - if (this.explicitlyCleared) return; - var cm = this.doc.cm, withOp = cm && !cm.curOp; - if (withOp) startOperation(cm); - if (hasHandler(this, "clear")) { - var found = this.find(); - if (found) signalLater(this, "clear", found.from, found.to); - } - var min = null, max = null; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (cm && !this.collapsed) regLineChange(cm, lineNo(line), "text"); - else if (cm) { - if (span.to != null) max = lineNo(line); - if (span.from != null) min = lineNo(line); - } - line.markedSpans = removeMarkedSpan(line.markedSpans, span); - if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) - updateLineHeight(line, textHeight(cm.display)); - } - if (cm && this.collapsed && !cm.options.lineWrapping) for (var i = 0; i < this.lines.length; ++i) { - var visual = visualLine(this.lines[i]), len = lineLength(visual); - if (len > cm.display.maxLineLength) { - cm.display.maxLine = visual; - cm.display.maxLineLength = len; - cm.display.maxLineChanged = true; - } - } - - if (min != null && cm && this.collapsed) regChange(cm, min, max + 1); - this.lines.length = 0; - this.explicitlyCleared = true; - if (this.atomic && this.doc.cantEdit) { - this.doc.cantEdit = false; - if (cm) reCheckSelection(cm.doc); - } - if (cm) signalLater(cm, "markerCleared", cm, this); - if (withOp) endOperation(cm); - if (this.parent) this.parent.clear(); - }; - - // Find the position of the marker in the document. Returns a {from, - // to} object by default. Side can be passed to get a specific side - // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the - // Pos objects returned contain a line object, rather than a line - // number (used to prevent looking up the same line twice). - TextMarker.prototype.find = function(side, lineObj) { - if (side == null && this.type == "bookmark") side = 1; - 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) { - from = Pos(lineObj ? line : lineNo(line), span.from); - if (side == -1) return from; - } - if (span.to != null) { - to = Pos(lineObj ? line : lineNo(line), span.to); - if (side == 1) return to; - } - } - return from && {from: from, to: to}; - }; - - // Signals that the marker's widget changed, and surrounding layout - // should be recomputed. - TextMarker.prototype.changed = function() { - var pos = this.find(-1, true), widget = this, cm = this.doc.cm; - if (!pos || !cm) return; - runInOp(cm, function() { - var line = pos.line, lineN = lineNo(pos.line); - var view = findViewForLine(cm, lineN); - if (view) { - clearLineMeasurementCacheFor(view); - cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; - } - cm.curOp.updateMaxLine = true; - if (!lineIsHidden(widget.doc, line) && widget.height != null) { - var oldHeight = widget.height; - widget.height = null; - var dHeight = widgetHeight(widget) - oldHeight; - if (dHeight) - updateLineHeight(line, line.height + dHeight); - } - }); - }; - - TextMarker.prototype.attachLine = function(line) { - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp; - if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) - (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); - } - this.lines.push(line); - }; - TextMarker.prototype.detachLine = function(line) { - this.lines.splice(indexOf(this.lines, line), 1); - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp; - (op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); - } - }; - - // Collapsed markers have unique ids, in order to be able to order - // them, which is needed for uniquely determining an outer marker - // when they overlap (they may nest, but not partially overlap). - var nextMarkerId = 0; - - // Create a marker, wire it up to the right lines, and - function markText(doc, from, to, options, type) { - // Shared markers (across linked documents) are handled separately - // (markTextShared will call out to this again, once per - // document). - if (options && options.shared) return markTextShared(doc, from, to, options, type); - // Ensure we are in an operation. - if (doc.cm && !doc.cm.curOp) return operation(doc.cm, markText)(doc, from, to, options, type); - - var marker = new TextMarker(doc, type), diff = cmp(from, to); - if (options) copyObj(options, marker, false); - // Don't connect empty markers unless clearWhenEmpty is false - if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) - return marker; - if (marker.replacedWith) { - // Showing up as a widget implies collapsed (widget replaces text) - marker.collapsed = true; - marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget"); - if (!options.handleMouseEvents) marker.widgetNode.setAttribute("cm-ignore-events", "true"); - if (options.insertLeft) marker.widgetNode.insertLeft = true; - } - if (marker.collapsed) { - if (conflictingCollapsedRange(doc, from.line, from, to, marker) || - from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) - throw new Error("Inserting collapsed marker partially overlapping an existing one"); - sawCollapsedSpans = true; - } - - if (marker.addToHistory) - addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); - - var curLine = from.line, cm = doc.cm, updateMaxLine; - doc.iter(curLine, to.line + 1, function(line) { - if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) - updateMaxLine = true; - if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0); - addMarkedSpan(line, new MarkedSpan(marker, - curLine == from.line ? from.ch : null, - curLine == to.line ? to.ch : null)); - ++curLine; - }); - // lineIsHidden depends on the presence of the spans, so needs a second pass - if (marker.collapsed) doc.iter(from.line, to.line + 1, function(line) { - if (lineIsHidden(doc, line)) updateLineHeight(line, 0); - }); - - if (marker.clearOnEnter) on(marker, "beforeCursorEnter", function() { marker.clear(); }); - - if (marker.readOnly) { - sawReadOnlySpans = true; - if (doc.history.done.length || doc.history.undone.length) - doc.clearHistory(); - } - if (marker.collapsed) { - marker.id = ++nextMarkerId; - marker.atomic = true; - } - if (cm) { - // Sync editor state - if (updateMaxLine) cm.curOp.updateMaxLine = true; - if (marker.collapsed) - regChange(cm, from.line, to.line + 1); - else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) - for (var i = from.line; i <= to.line; i++) regLineChange(cm, i, "text"); - if (marker.atomic) reCheckSelection(cm.doc); - signalLater(cm, "markerAdded", cm, marker); - } - return marker; - } - - // SHARED TEXTMARKERS - - // A shared marker spans multiple linked documents. It is - // implemented as a meta-marker-object controlling multiple normal - // markers. - var SharedTextMarker = CodeMirror.SharedTextMarker = function(markers, primary) { - this.markers = markers; - this.primary = primary; - for (var i = 0; i < markers.length; ++i) - markers[i].parent = this; - }; - eventMixin(SharedTextMarker); - - SharedTextMarker.prototype.clear = function() { - if (this.explicitlyCleared) return; - this.explicitlyCleared = true; - for (var i = 0; i < this.markers.length; ++i) - this.markers[i].clear(); - signalLater(this, "clear"); - }; - SharedTextMarker.prototype.find = function(side, lineObj) { - return this.primary.find(side, lineObj); - }; - - function markTextShared(doc, from, to, options, type) { - options = copyObj(options); - options.shared = false; - var markers = [markText(doc, from, to, options, type)], primary = markers[0]; - var widget = options.widgetNode; - linkedDocs(doc, function(doc) { - if (widget) options.widgetNode = widget.cloneNode(true); - markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); - for (var i = 0; i < doc.linked.length; ++i) - if (doc.linked[i].isParent) return; - primary = lst(markers); - }); - return new SharedTextMarker(markers, primary); - } - - function findSharedMarkers(doc) { - return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), - function(m) { return m.parent; }); - } - - function copySharedMarkers(doc, markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], pos = marker.find(); - var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); - if (cmp(mFrom, mTo)) { - var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); - marker.markers.push(subMark); - subMark.parent = marker; - } - } - } - - function detachSharedMarkers(markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], linked = [marker.primary.doc];; - linkedDocs(marker.primary.doc, function(d) { linked.push(d); }); - for (var j = 0; j < marker.markers.length; j++) { - var subMarker = marker.markers[j]; - if (indexOf(linked, subMarker.doc) == -1) { - subMarker.parent = null; - marker.markers.splice(j--, 1); - } - } - } - } - - // TEXTMARKER SPANS - - function MarkedSpan(marker, from, to) { - this.marker = marker; - this.from = from; this.to = to; - } - - // Search an array of spans for a span matching the given 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; - } - } - // Remove a span from an array, returning undefined if no spans are - // left (we don't store arrays for lines without spans). - function removeMarkedSpan(spans, span) { - for (var r, i = 0; i < spans.length; ++i) - if (spans[i] != span) (r || (r = [])).push(spans[i]); - return r; - } - // Add a span to a line. - function addMarkedSpan(line, span) { - line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; - span.marker.attachLine(line); - } - - // Used for the algorithm that adjusts markers for a change in the - // document. These functions cut an array of spans at a given - // character position, returning an array of remaining chunks (or - // undefined if nothing remains). - function markedSpansBefore(old, startCh, isInsert) { - 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 || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); - (nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); - } - } - return nw; - } - function markedSpansAfter(old, endCh, isInsert) { - 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 || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); - (nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, - span.to == null ? null : span.to - endCh)); - } - } - return nw; - } - - // Given a change object, compute the new set of marker spans that - // cover the line in which the change took place. Removes spans - // entirely within the change, reconnects spans belonging to the - // same marker that appear on both sides of the change, and cuts off - // spans partially within the change. Returns an array of span - // arrays with one element for each line in (after) the change. - function stretchSpansOverChange(doc, change) { - if (change.full) return null; - var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; - var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; - if (!oldFirst && !oldLast) return null; - - var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; - // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh, isInsert); - var last = markedSpansAfter(oldLast, endCh, isInsert); - - // Next, merge those two ends - var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); - if (first) { - // Fix up .to properties of 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) { - // Fix up .from in last (or move them into first in case of sameLine) - 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); - } - } - } - // Make sure we didn't create any zero-length spans - if (first) first = clearEmptySpans(first); - if (last && last != first) last = clearEmptySpans(last); - - var newMarkers = [first]; - if (!sameLine) { - // Fill gap with whole-line-spans - var gap = change.text.length - 2, gapMarkers; - if (gap > 0 && first) - for (var i = 0; i < first.length; ++i) - if (first[i].to == null) - (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i].marker, null, null)); - for (var i = 0; i < gap; ++i) - newMarkers.push(gapMarkers); - newMarkers.push(last); - } - return newMarkers; - } - - // Remove spans that are empty and don't have a clearWhenEmpty - // option of false. - function clearEmptySpans(spans) { - for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) - spans.splice(i--, 1); - } - if (!spans.length) return null; - return spans; - } - - // Used for un/re-doing changes from the history. Combines the - // result of computing the existing spans with the set of spans that - // existed in the history (so that deleting around a span and then - // undoing brings back the span). - function mergeOldSpans(doc, change) { - var old = getOldSpans(doc, change); - var stretched = stretchSpansOverChange(doc, change); - if (!old) return stretched; - if (!stretched) return old; - - for (var i = 0; i < old.length; ++i) { - var oldCur = old[i], stretchCur = stretched[i]; - if (oldCur && stretchCur) { - spans: for (var j = 0; j < stretchCur.length; ++j) { - var span = stretchCur[j]; - for (var k = 0; k < oldCur.length; ++k) - if (oldCur[k].marker == span.marker) continue spans; - oldCur.push(span); - } - } else if (stretchCur) { - old[i] = stretchCur; - } - } - return old; - } - - // Used to 'clip' out readOnly ranges when making a change. - function removeReadOnlyRanges(doc, from, to) { - var markers = null; - doc.iter(from.line, to.line + 1, function(line) { - if (line.markedSpans) for (var i = 0; i < line.markedSpans.length; ++i) { - var mark = line.markedSpans[i].marker; - if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) - (markers || (markers = [])).push(mark); - } - }); - if (!markers) return null; - var parts = [{from: from, to: to}]; - for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(0); - for (var j = 0; j < parts.length; ++j) { - var p = parts[j]; - if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) continue; - var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); - if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) - newParts.push({from: p.from, to: m.from}); - if (dto > 0 || !mk.inclusiveRight && !dto) - newParts.push({from: m.to, to: p.to}); - parts.splice.apply(parts, newParts); - j += newParts.length - 1; - } - } - return parts; - } - - // Connect or disconnect spans from a line. - function detachMarkedSpans(line) { - var spans = line.markedSpans; - if (!spans) return; - for (var i = 0; i < spans.length; ++i) - spans[i].marker.detachLine(line); - line.markedSpans = null; - } - function attachMarkedSpans(line, spans) { - if (!spans) return; - for (var i = 0; i < spans.length; ++i) - spans[i].marker.attachLine(line); - line.markedSpans = spans; - } - - // Helpers used when computing which overlapping collapsed span - // counts as the larger one. - function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0; } - function extraRight(marker) { return marker.inclusiveRight ? 1 : 0; } - - // Returns a number indicating which of two overlapping collapsed - // spans is larger (and thus includes the other). Falls back to - // comparing ids when the spans cover exactly the same range. - function compareCollapsedMarkers(a, b) { - var lenDiff = a.lines.length - b.lines.length; - if (lenDiff != 0) return lenDiff; - var aPos = a.find(), bPos = b.find(); - var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); - if (fromCmp) return -fromCmp; - var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); - if (toCmp) return toCmp; - return b.id - a.id; - } - - // Find out whether a line ends or starts in a collapsed span. If - // so, return the marker for that span. - function collapsedSpanAtSide(line, start) { - var sps = sawCollapsedSpans && line.markedSpans, found; - if (sps) for (var sp, i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) - found = sp.marker; - } - return found; - } - function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true); } - function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false); } - - // Test whether there exists a collapsed span that partially - // overlaps (covers the start or end, but not both) of a new span. - // Such overlap is not allowed. - function conflictingCollapsedRange(doc, lineNo, from, to, marker) { - var line = getLine(doc, lineNo); - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) for (var i = 0; i < sps.length; ++i) { - var sp = sps[i]; - if (!sp.marker.collapsed) continue; - var found = sp.marker.find(0); - var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); - var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); - if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) continue; - if (fromCmp <= 0 && (cmp(found.to, from) > 0 || (sp.marker.inclusiveRight && marker.inclusiveLeft)) || - fromCmp >= 0 && (cmp(found.from, to) < 0 || (sp.marker.inclusiveLeft && marker.inclusiveRight))) - return true; - } - } - - // A visual line is a line as drawn on the screen. Folding, for - // example, can cause multiple logical lines to appear on the same - // visual line. This finds the start of the visual line that the - // given line is part of (usually that is the line itself). - function visualLine(line) { - var merged; - while (merged = collapsedSpanAtStart(line)) - line = merged.find(-1, true).line; - return line; - } - - // Returns an array of logical lines that continue the visual line - // started by the argument, or undefined if there are no such lines. - function visualLineContinued(line) { - var merged, lines; - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line; - (lines || (lines = [])).push(line); - } - return lines; - } - - // Get the line number of the start of the visual line that the - // given line number is part of. - function visualLineNo(doc, lineN) { - var line = getLine(doc, lineN), vis = visualLine(line); - if (line == vis) return lineN; - return lineNo(vis); - } - // Get the line number of the start of the next visual line after - // the given line. - function visualLineEndNo(doc, lineN) { - if (lineN > doc.lastLine()) return lineN; - var line = getLine(doc, lineN), merged; - if (!lineIsHidden(doc, line)) return lineN; - while (merged = collapsedSpanAtEnd(line)) - line = merged.find(1, true).line; - return lineNo(line) + 1; - } - - // Compute whether a line is hidden. Lines count as hidden when they - // are part of a visual line that starts with another line, or when - // they are entirely covered by collapsed, non-widget span. - function lineIsHidden(doc, line) { - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) for (var sp, i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (!sp.marker.collapsed) continue; - if (sp.from == null) return true; - if (sp.marker.widgetNode) continue; - if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) - return true; - } - } - function lineIsHiddenInner(doc, line, span) { - if (span.to == null) { - var end = span.marker.find(1, true); - return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)); - } - if (span.marker.inclusiveRight && span.to == line.text.length) - return true; - for (var sp, i = 0; i < line.markedSpans.length; ++i) { - sp = line.markedSpans[i]; - if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && - (sp.to == null || sp.to != span.from) && - (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && - lineIsHiddenInner(doc, line, sp)) return true; - } - } - - // LINE WIDGETS - - // Line widgets are block elements displayed above or below a line. - - var LineWidget = CodeMirror.LineWidget = function(doc, node, options) { - if (options) for (var opt in options) if (options.hasOwnProperty(opt)) - this[opt] = options[opt]; - this.doc = doc; - this.node = node; - }; - eventMixin(LineWidget); - - function adjustScrollWhenAboveVisible(cm, line, diff) { - if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) - addToScrollPos(cm, null, diff); - } - - LineWidget.prototype.clear = function() { - var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); - if (no == null || !ws) return; - for (var i = 0; i < ws.length; ++i) if (ws[i] == this) ws.splice(i--, 1); - if (!ws.length) line.widgets = null; - var height = widgetHeight(this); - updateLineHeight(line, Math.max(0, line.height - height)); - if (cm) runInOp(cm, function() { - adjustScrollWhenAboveVisible(cm, line, -height); - regLineChange(cm, no, "widget"); - }); - }; - LineWidget.prototype.changed = function() { - var oldH = this.height, cm = this.doc.cm, line = this.line; - this.height = null; - var diff = widgetHeight(this) - oldH; - if (!diff) return; - updateLineHeight(line, line.height + diff); - if (cm) runInOp(cm, function() { - cm.curOp.forceUpdate = true; - adjustScrollWhenAboveVisible(cm, line, diff); - }); - }; - - function widgetHeight(widget) { - if (widget.height != null) return widget.height; - var cm = widget.doc.cm; - if (!cm) return 0; - if (!contains(document.body, widget.node)) { - var parentStyle = "position: relative;"; - if (widget.coverGutter) - parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; - if (widget.noHScroll) - parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; - removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); - } - return widget.height = widget.node.offsetHeight; - } - - function addLineWidget(doc, handle, node, options) { - var widget = new LineWidget(doc, node, options); - var cm = doc.cm; - if (cm && widget.noHScroll) cm.display.alignWidgets = true; - changeLine(doc, handle, "widget", function(line) { - var widgets = line.widgets || (line.widgets = []); - if (widget.insertAt == null) widgets.push(widget); - else widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); - widget.line = line; - if (cm && !lineIsHidden(doc, line)) { - var aboveVisible = heightAtLine(line) < doc.scrollTop; - updateLineHeight(line, line.height + widgetHeight(widget)); - if (aboveVisible) addToScrollPos(cm, null, widget.height); - cm.curOp.forceUpdate = true; - } - return true; - }); - return widget; - } - - // LINE DATA STRUCTURE - - // Line objects. These hold state related to a line, including - // highlighting info (the styles array). - var Line = CodeMirror.Line = function(text, markedSpans, estimateHeight) { - this.text = text; - attachMarkedSpans(this, markedSpans); - this.height = estimateHeight ? estimateHeight(this) : 1; - }; - eventMixin(Line); - Line.prototype.lineNo = function() { return lineNo(this); }; - - // Change the content (text, markers) of a line. Automatically - // invalidates cached information and tries to re-estimate the - // line's height. - function updateLine(line, text, markedSpans, estimateHeight) { - line.text = text; - if (line.stateAfter) line.stateAfter = null; - if (line.styles) line.styles = null; - if (line.order != null) line.order = null; - detachMarkedSpans(line); - attachMarkedSpans(line, markedSpans); - var estHeight = estimateHeight ? estimateHeight(line) : 1; - if (estHeight != line.height) updateLineHeight(line, estHeight); - } - - // Detach a line from the document tree and its markers. - function cleanUpLine(line) { - line.parent = null; - detachMarkedSpans(line); - } - - function extractLineClasses(type, output) { - if (type) for (;;) { - var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); - if (!lineClass) break; - type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); - var prop = lineClass[1] ? "bgClass" : "textClass"; - if (output[prop] == null) - output[prop] = lineClass[2]; - else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) - output[prop] += " " + lineClass[2]; - } - return type; - } - - function callBlankLine(mode, state) { - if (mode.blankLine) return mode.blankLine(state); - if (!mode.innerMode) return; - var inner = CodeMirror.innerMode(mode, state); - if (inner.mode.blankLine) return inner.mode.blankLine(inner.state); - } - - function readToken(mode, stream, state, inner) { - for (var i = 0; i < 10; i++) { - if (inner) inner[0] = CodeMirror.innerMode(mode, state).mode; - var style = mode.token(stream, state); - if (stream.pos > stream.start) return style; - } - throw new Error("Mode " + mode.name + " failed to advance stream."); - } - - // Utility for getTokenAt and getLineTokens - function takeToken(cm, pos, precise, asArray) { - function getObj(copy) { - return {start: stream.start, end: stream.pos, - string: stream.current(), - type: style || null, - state: copy ? copyState(doc.mode, state) : state}; - } - - var doc = cm.doc, mode = doc.mode, style; - pos = clipPos(doc, pos); - var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise); - var stream = new StringStream(line.text, cm.options.tabSize), tokens; - if (asArray) tokens = []; - while ((asArray || stream.pos < pos.ch) && !stream.eol()) { - stream.start = stream.pos; - style = readToken(mode, stream, state); - if (asArray) tokens.push(getObj(true)); - } - return asArray ? tokens : getObj(); - } - - // Run the given mode's parser over a line, calling f for each token. - function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { - var flattenSpans = mode.flattenSpans; - if (flattenSpans == null) flattenSpans = cm.options.flattenSpans; - var curStart = 0, curStyle = null; - var stream = new StringStream(text, cm.options.tabSize), style; - var inner = cm.options.addModeClass && [null]; - if (text == "") extractLineClasses(callBlankLine(mode, state), lineClasses); - while (!stream.eol()) { - if (stream.pos > cm.options.maxHighlightLength) { - flattenSpans = false; - if (forceToEnd) processLine(cm, text, state, stream.pos); - stream.pos = text.length; - style = null; - } else { - style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses); - } - if (inner) { - var mName = inner[0].name; - if (mName) style = "m-" + (style ? mName + " " + style : mName); - } - if (!flattenSpans || curStyle != style) { - while (curStart < stream.start) { - curStart = Math.min(stream.start, curStart + 50000); - f(curStart, curStyle); - } - curStyle = style; - } - stream.start = stream.pos; - } - while (curStart < stream.pos) { - // Webkit seems to refuse to render text nodes longer than 57444 characters - var pos = Math.min(stream.pos, curStart + 50000); - f(pos, curStyle); - curStart = pos; - } - } - - // Compute a style array (an array starting with a mode generation - // -- for invalidation -- followed by pairs of end positions and - // style strings), which is used to highlight the tokens on the - // line. - function highlightLine(cm, line, state, forceToEnd) { - // A styles array always starts with a number identifying the - // mode/overlays that it is based on (for easy invalidation). - var st = [cm.state.modeGen], lineClasses = {}; - // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, state, function(end, style) { - st.push(end, style); - }, lineClasses, forceToEnd); - - // Run overlays, adjust style array. - for (var o = 0; o < cm.state.overlays.length; ++o) { - var overlay = cm.state.overlays[o], i = 1, at = 0; - runMode(cm, line.text, overlay.mode, true, function(end, style) { - var start = i; - // Ensure there's a token end at the current position, and that i points at it - while (at < end) { - var i_end = st[i]; - if (i_end > end) - st.splice(i, 1, end, st[i+1], i_end); - i += 2; - at = Math.min(end, i_end); - } - if (!style) return; - if (overlay.opaque) { - st.splice(start, i - start, end, "cm-overlay " + style); - i = start + 2; - } else { - for (; start < i; start += 2) { - var cur = st[start+1]; - st[start+1] = (cur ? cur + " " : "") + "cm-overlay " + style; - } - } - }, lineClasses); - } - - return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}; - } - - function getLineStyles(cm, line, updateFrontier) { - if (!line.styles || line.styles[0] != cm.state.modeGen) { - var state = getStateBefore(cm, lineNo(line)); - var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state); - line.stateAfter = state; - line.styles = result.styles; - if (result.classes) line.styleClasses = result.classes; - else if (line.styleClasses) line.styleClasses = null; - if (updateFrontier === cm.doc.frontier) cm.doc.frontier++; - } - return line.styles; - } - - // Lightweight form of highlight -- proceed over this line and - // update state, but don't save a style array. Used for lines that - // aren't currently visible. - function processLine(cm, text, state, startAt) { - var mode = cm.doc.mode; - var stream = new StringStream(text, cm.options.tabSize); - stream.start = stream.pos = startAt || 0; - if (text == "") callBlankLine(mode, state); - while (!stream.eol()) { - readToken(mode, stream, state); - stream.start = stream.pos; - } - } - - // Convert a style as returned by a mode (either null, or a string - // containing one or more styles) to a CSS style. This is cached, - // and also looks for line-wide styles. - var styleToClassCache = {}, styleToClassCacheWithMode = {}; - function interpretTokenStyle(style, options) { - if (!style || /^\s*$/.test(style)) return null; - var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; - return cache[style] || - (cache[style] = style.replace(/\S+/g, "cm-$&")); - } - - // Render the DOM representation of the text of a line. Also builds - // up a 'line map', which points at the DOM nodes that represent - // specific stretches of text, and is used by the measuring code. - // The returned object contains the DOM node, this map, and - // information about line-wide styles that were set by the mode. - function buildLineContent(cm, lineView) { - // The padding-right forces the element to have a 'border', which - // is needed on Webkit to be able to get line-level bounding - // rectangles for it (in measureChar). - var content = elt("span", null, null, webkit ? "padding-right: .1px" : null); - var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content, - col: 0, pos: 0, cm: cm, - splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")}; - lineView.measure = {}; - - // Iterate over the logical lines that make up this visual line. - for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { - var line = i ? lineView.rest[i - 1] : lineView.line, order; - builder.pos = 0; - builder.addToken = buildToken; - // Optionally wire in some hacks into the token-rendering - // algorithm, to deal with browser quirks. - if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line))) - builder.addToken = buildTokenBadBidi(builder.addToken, order); - builder.map = []; - var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); - insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); - if (line.styleClasses) { - if (line.styleClasses.bgClass) - builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); - if (line.styleClasses.textClass) - builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); - } - - // Ensure at least a single node is present, for measuring. - if (builder.map.length == 0) - builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); - - // Store the map and a cache object for the current logical line - if (i == 0) { - lineView.measure.map = builder.map; - lineView.measure.cache = {}; - } else { - (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map); - (lineView.measure.caches || (lineView.measure.caches = [])).push({}); - } - } - - // See issue #2901 - if (webkit && /\bcm-tab\b/.test(builder.content.lastChild.className)) - builder.content.className = "cm-tab-wrap-hack"; - - signal(cm, "renderLine", cm, lineView.line, builder.pre); - if (builder.pre.className) - builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); - - return builder; - } - - function defaultSpecialCharPlaceholder(ch) { - var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + ch.charCodeAt(0).toString(16); - token.setAttribute("aria-label", token.title); - return token; - } - - // Build up the DOM representation for a single token, and add it to - // the line map. Takes care to render special characters separately. - function buildToken(builder, text, style, startStyle, endStyle, title, css) { - if (!text) return; - var displayText = builder.splitSpaces ? text.replace(/ {3,}/g, splitSpaces) : text; - var special = builder.cm.state.specialChars, mustWrap = false; - if (!special.test(text)) { - builder.col += text.length; - var content = document.createTextNode(displayText); - builder.map.push(builder.pos, builder.pos + text.length, content); - if (ie && ie_version < 9) mustWrap = true; - builder.pos += text.length; - } else { - var content = document.createDocumentFragment(), pos = 0; - while (true) { - special.lastIndex = pos; - var m = special.exec(text); - var skipped = m ? m.index - pos : text.length - pos; - if (skipped) { - var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); - if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); - else content.appendChild(txt); - builder.map.push(builder.pos, builder.pos + skipped, txt); - builder.col += skipped; - builder.pos += skipped; - } - if (!m) break; - pos += skipped + 1; - if (m[0] == "\t") { - var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; - var txt = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); - txt.setAttribute("role", "presentation"); - txt.setAttribute("cm-text", "\t"); - builder.col += tabWidth; - } else if (m[0] == "\r" || m[0] == "\n") { - var txt = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); - txt.setAttribute("cm-text", m[0]); - builder.col += 1; - } else { - var txt = builder.cm.options.specialCharPlaceholder(m[0]); - txt.setAttribute("cm-text", m[0]); - if (ie && ie_version < 9) content.appendChild(elt("span", [txt])); - else content.appendChild(txt); - builder.col += 1; - } - builder.map.push(builder.pos, builder.pos + 1, txt); - builder.pos++; - } - } - if (style || startStyle || endStyle || mustWrap || css) { - var fullStyle = style || ""; - if (startStyle) fullStyle += startStyle; - if (endStyle) fullStyle += endStyle; - var token = elt("span", [content], fullStyle, css); - if (title) token.title = title; - return builder.content.appendChild(token); - } - builder.content.appendChild(content); - } - - function splitSpaces(old) { - var out = " "; - for (var i = 0; i < old.length - 2; ++i) out += i % 2 ? " " : "\u00a0"; - out += " "; - return out; - } - - // Work around nonsense dimensions being reported for stretches of - // right-to-left text. - function buildTokenBadBidi(inner, order) { - return function(builder, text, style, startStyle, endStyle, title, css) { - style = style ? style + " cm-force-border" : "cm-force-border"; - var start = builder.pos, end = start + text.length; - for (;;) { - // Find the part that overlaps with the start of this text - for (var i = 0; i < order.length; i++) { - var part = order[i]; - if (part.to > start && part.from <= start) break; - } - if (part.to >= end) return inner(builder, text, style, startStyle, endStyle, title, css); - inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css); - startStyle = null; - text = text.slice(part.to - start); - start = part.to; - } - }; - } - - function buildCollapsedSpan(builder, size, marker, ignoreWidget) { - var widget = !ignoreWidget && marker.widgetNode; - if (widget) builder.map.push(builder.pos, builder.pos + size, widget); - if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { - if (!widget) - widget = builder.content.appendChild(document.createElement("span")); - widget.setAttribute("cm-marker", marker.id); - } - if (widget) { - builder.cm.display.input.setUneditable(widget); - builder.content.appendChild(widget); - } - builder.pos += size; - } - - // Outputs a number of spans to make up a line, taking highlighting - // and marked text into account. - function insertLineContent(line, builder, styles) { - var spans = line.markedSpans, allText = line.text, at = 0; - if (!spans) { - for (var i = 1; i < styles.length; i+=2) - builder.addToken(builder, allText.slice(at, at = styles[i]), interpretTokenStyle(styles[i+1], builder.cm.options)); - return; - } - - var len = allText.length, pos = 0, i = 1, text = "", style, css; - var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed; - for (;;) { - if (nextChange == pos) { // Update current marker set - spanStyle = spanEndStyle = spanStartStyle = title = css = ""; - collapsed = null; nextChange = Infinity; - var foundBookmarks = []; - for (var j = 0; j < spans.length; ++j) { - var sp = spans[j], m = sp.marker; - if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { - foundBookmarks.push(m); - } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { - if (sp.to != null && sp.to != pos && nextChange > sp.to) { - nextChange = sp.to; - spanEndStyle = ""; - } - if (m.className) spanStyle += " " + m.className; - if (m.css) css = m.css; - if (m.startStyle && sp.from == pos) spanStartStyle += " " + m.startStyle; - if (m.endStyle && sp.to == nextChange) spanEndStyle += " " + m.endStyle; - if (m.title && !title) title = m.title; - if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) - collapsed = sp; - } else if (sp.from > pos && nextChange > sp.from) { - nextChange = sp.from; - } - } - if (collapsed && (collapsed.from || 0) == pos) { - buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, - collapsed.marker, collapsed.from == null); - if (collapsed.to == null) return; - if (collapsed.to == pos) collapsed = false; - } - if (!collapsed && foundBookmarks.length) for (var j = 0; j < foundBookmarks.length; ++j) - buildCollapsedSpan(builder, 0, foundBookmarks[j]); - } - if (pos >= len) break; - - var upto = Math.min(len, nextChange); - while (true) { - if (text) { - var end = pos + text.length; - if (!collapsed) { - var tokenText = end > upto ? text.slice(0, upto - pos) : text; - builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, - spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css); - } - if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} - pos = end; - spanStartStyle = ""; - } - text = allText.slice(at, at = styles[i++]); - style = interpretTokenStyle(styles[i++], builder.cm.options); - } - } - } - - // DOCUMENT DATA STRUCTURE - - // By default, updates that start and end at the beginning of a line - // are treated specially, in order to make the association of line - // widgets and marker elements with the text behave more intuitive. - function isWholeLineUpdate(doc, change) { - return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && - (!doc.cm || doc.cm.options.wholeLineUpdateBefore); - } - - // Perform a change on the document data structure. - function updateDoc(doc, change, markedSpans, estimateHeight) { - function spansFor(n) {return markedSpans ? markedSpans[n] : null;} - function update(line, text, spans) { - updateLine(line, text, spans, estimateHeight); - signalLater(line, "change", line, change); - } - function linesFor(start, end) { - for (var i = start, result = []; i < end; ++i) - result.push(new Line(text[i], spansFor(i), estimateHeight)); - return result; - } - - var from = change.from, to = change.to, text = change.text; - var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); - var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; - - // Adjust the line structure - if (change.full) { - doc.insert(0, linesFor(0, text.length)); - doc.remove(text.length, doc.size - text.length); - } else if (isWholeLineUpdate(doc, change)) { - // This is a whole-line replace. Treated specially to make - // sure line objects move the way they are supposed to. - var added = linesFor(0, text.length - 1); - update(lastLine, lastLine.text, lastSpans); - if (nlines) doc.remove(from.line, nlines); - if (added.length) doc.insert(from.line, added); - } else if (firstLine == lastLine) { - if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); - } else { - var added = linesFor(1, text.length - 1); - added.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - doc.insert(from.line + 1, added); - } - } else if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); - doc.remove(from.line + 1, nlines); - } else { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); - var added = linesFor(1, text.length - 1); - if (nlines > 1) doc.remove(from.line + 1, nlines - 1); - doc.insert(from.line + 1, added); - } - - signalLater(doc, "change", doc, change); - } - - // The document is represented as a BTree consisting of leaves, with - // chunk of lines in them, and branches, with up to ten leaves or - // other branch nodes below them. The top node is always a branch - // node, and is the document object itself (meaning it has - // additional methods and properties). - // - // All nodes have parent links. The tree is used both to go from - // line numbers to line objects, and to go from objects to numbers. - // It also indexes by height, and is used to convert between height - // and line object, and to find the total height of the document. - // - // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html - - function LeafChunk(lines) { - this.lines = lines; - this.parent = null; - for (var i = 0, height = 0; i < lines.length; ++i) { - lines[i].parent = this; - height += lines[i].height; - } - this.height = height; - } - - LeafChunk.prototype = { - chunkSize: function() { return this.lines.length; }, - // Remove the n lines at offset 'at'. - removeInner: function(at, n) { - for (var i = at, e = at + n; i < e; ++i) { - var line = this.lines[i]; - this.height -= line.height; - cleanUpLine(line); - signalLater(line, "delete"); - } - this.lines.splice(at, n); - }, - // Helper used to collapse a small branch into a single leaf. - collapse: function(lines) { - lines.push.apply(lines, this.lines); - }, - // Insert the given array of lines at offset 'at', count them as - // having the given height. - insertInner: 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; i < lines.length; ++i) lines[i].parent = this; - }, - // Used to iterate over a part of the tree. - 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; i < children.length; ++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; }, - removeInner: function(at, n) { - 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.removeInner(at, rm); - 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 the result is smaller than 25 lines, ensure that it is a - // single leaf node. - if (this.size - n < 25 && - (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { - var lines = []; - this.collapse(lines); - this.children = [new LeafChunk(lines)]; - this.children[0].parent = this; - } - }, - collapse: function(lines) { - for (var i = 0; i < this.children.length; ++i) this.children[i].collapse(lines); - }, - insertInner: function(at, lines, height) { - this.size += lines.length; - this.height += height; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at <= sz) { - child.insertInner(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; - } - }, - // When a node has grown, check whether it should be split. - 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) { // Become the parent node - 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(); - }, - iterN: function(at, n, op) { - for (var i = 0; i < this.children.length; ++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; - } - } - }; - - var nextDocId = 0; - var Doc = CodeMirror.Doc = function(text, mode, firstLine, lineSep) { - if (!(this instanceof Doc)) return new Doc(text, mode, firstLine, lineSep); - if (firstLine == null) firstLine = 0; - - BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); - this.first = firstLine; - this.scrollTop = this.scrollLeft = 0; - this.cantEdit = false; - this.cleanGeneration = 1; - this.frontier = firstLine; - var start = Pos(firstLine, 0); - this.sel = simpleSelection(start); - this.history = new History(null); - this.id = ++nextDocId; - this.modeOption = mode; - this.lineSep = lineSep; - - if (typeof text == "string") text = this.splitLines(text); - updateDoc(this, {from: start, to: start, text: text}); - setSelection(this, simpleSelection(start), sel_dontScroll); - }; - - Doc.prototype = createObj(BranchChunk.prototype, { - constructor: Doc, - // Iterate over the document. Supports two forms -- with only one - // argument, it calls that for each line in the document. With - // three, it iterates over the range given by the first two (with - // the second being non-inclusive). - iter: function(from, to, op) { - if (op) this.iterN(from - this.first, to - from, op); - else this.iterN(this.first, this.first + this.size, from); - }, - - // Non-public interface for adding and removing lines. - insert: function(at, lines) { - var height = 0; - for (var i = 0; i < lines.length; ++i) height += lines[i].height; - this.insertInner(at - this.first, lines, height); - }, - remove: function(at, n) { this.removeInner(at - this.first, n); }, - - // From here, the methods are part of the public interface. Most - // are also available from CodeMirror (editor) instances. - - getValue: function(lineSep) { - var lines = getLines(this, this.first, this.first + this.size); - if (lineSep === false) return lines; - return lines.join(lineSep || this.lineSeparator()); - }, - setValue: docMethodOp(function(code) { - var top = Pos(this.first, 0), last = this.first + this.size - 1; - makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), - text: this.splitLines(code), origin: "setValue", full: true}, true); - setSelection(this, simpleSelection(top)); - }), - replaceRange: function(code, from, to, origin) { - from = clipPos(this, from); - to = to ? clipPos(this, to) : from; - replaceRange(this, code, from, to, origin); - }, - getRange: function(from, to, lineSep) { - var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); - if (lineSep === false) return lines; - return lines.join(lineSep || this.lineSeparator()); - }, - - getLine: function(line) {var l = this.getLineHandle(line); return l && l.text;}, - - getLineHandle: function(line) {if (isLine(this, line)) return getLine(this, line);}, - getLineNumber: function(line) {return lineNo(line);}, - - getLineHandleVisualStart: function(line) { - if (typeof line == "number") line = getLine(this, line); - return visualLine(line); - }, - - lineCount: function() {return this.size;}, - firstLine: function() {return this.first;}, - lastLine: function() {return this.first + this.size - 1;}, - - clipPos: function(pos) {return clipPos(this, pos);}, - - getCursor: function(start) { - var range = this.sel.primary(), pos; - if (start == null || start == "head") pos = range.head; - else if (start == "anchor") pos = range.anchor; - else if (start == "end" || start == "to" || start === false) pos = range.to(); - else pos = range.from(); - return pos; - }, - listSelections: function() { return this.sel.ranges; }, - somethingSelected: function() {return this.sel.somethingSelected();}, - - setCursor: docMethodOp(function(line, ch, options) { - setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); - }), - setSelection: docMethodOp(function(anchor, head, options) { - setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); - }), - extendSelection: docMethodOp(function(head, other, options) { - extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); - }), - extendSelections: docMethodOp(function(heads, options) { - extendSelections(this, clipPosArray(this, heads, options)); - }), - extendSelectionsBy: docMethodOp(function(f, options) { - extendSelections(this, map(this.sel.ranges, f), options); - }), - setSelections: docMethodOp(function(ranges, primary, options) { - if (!ranges.length) return; - for (var i = 0, out = []; i < ranges.length; i++) - out[i] = new Range(clipPos(this, ranges[i].anchor), - clipPos(this, ranges[i].head)); - if (primary == null) primary = Math.min(ranges.length - 1, this.sel.primIndex); - setSelection(this, normalizeSelection(out, primary), options); - }), - addSelection: docMethodOp(function(anchor, head, options) { - var ranges = this.sel.ranges.slice(0); - ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); - setSelection(this, normalizeSelection(ranges, ranges.length - 1), options); - }), - - getSelection: function(lineSep) { - var ranges = this.sel.ranges, lines; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - lines = lines ? lines.concat(sel) : sel; - } - if (lineSep === false) return lines; - else return lines.join(lineSep || this.lineSeparator()); - }, - getSelections: function(lineSep) { - var parts = [], ranges = this.sel.ranges; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - if (lineSep !== false) sel = sel.join(lineSep || this.lineSeparator()); - parts[i] = sel; - } - return parts; - }, - replaceSelection: function(code, collapse, origin) { - var dup = []; - for (var i = 0; i < this.sel.ranges.length; i++) - dup[i] = code; - this.replaceSelections(dup, collapse, origin || "+input"); - }, - replaceSelections: docMethodOp(function(code, collapse, origin) { - var changes = [], sel = this.sel; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; - } - var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); - for (var i = changes.length - 1; i >= 0; i--) - makeChange(this, changes[i]); - if (newSel) setSelectionReplaceHistory(this, newSel); - else if (this.cm) ensureCursorVisible(this.cm); - }), - undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), - redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), - undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), - redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), - - setExtending: function(val) {this.extend = val;}, - getExtending: function() {return this.extend;}, - - historySize: function() { - var hist = this.history, done = 0, undone = 0; - for (var i = 0; i < hist.done.length; i++) if (!hist.done[i].ranges) ++done; - for (var i = 0; i < hist.undone.length; i++) if (!hist.undone[i].ranges) ++undone; - return {undo: done, redo: undone}; - }, - clearHistory: function() {this.history = new History(this.history.maxGeneration);}, - - markClean: function() { - this.cleanGeneration = this.changeGeneration(true); - }, - changeGeneration: function(forceSplit) { - if (forceSplit) - this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; - return this.history.generation; - }, - isClean: function (gen) { - return this.history.generation == (gen || this.cleanGeneration); - }, - - getHistory: function() { - return {done: copyHistoryArray(this.history.done), - undone: copyHistoryArray(this.history.undone)}; - }, - setHistory: function(histData) { - var hist = this.history = new History(this.history.maxGeneration); - hist.done = copyHistoryArray(histData.done.slice(0), null, true); - hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); - }, - - addLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - if (!line[prop]) line[prop] = cls; - else if (classTest(cls).test(line[prop])) return false; - else line[prop] += " " + cls; - return true; - }); - }), - removeLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function(line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - var cur = line[prop]; - if (!cur) return false; - else if (cls == null) line[prop] = null; - else { - var found = cur.match(classTest(cls)); - if (!found) return false; - var end = found.index + found[0].length; - line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; - } - return true; - }); - }), - - addLineWidget: docMethodOp(function(handle, node, options) { - return addLineWidget(this, handle, node, options); - }), - removeLineWidget: function(widget) { widget.clear(); }, - - markText: function(from, to, options) { - return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range"); - }, - setBookmark: function(pos, options) { - var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), - insertLeft: options && options.insertLeft, - clearWhenEmpty: false, shared: options && options.shared, - handleMouseEvents: options && options.handleMouseEvents}; - pos = clipPos(this, pos); - return markText(this, pos, pos, realOpts, "bookmark"); - }, - findMarksAt: function(pos) { - pos = clipPos(this, pos); - var markers = [], spans = getLine(this, 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.parent || span.marker); - } - return markers; - }, - findMarks: function(from, to, filter) { - from = clipPos(this, from); to = clipPos(this, to); - var found = [], lineNo = from.line; - this.iter(from.line, to.line + 1, function(line) { - var spans = line.markedSpans; - if (spans) for (var i = 0; i < spans.length; i++) { - var span = spans[i]; - if (!(lineNo == from.line && from.ch > span.to || - span.from == null && lineNo != from.line|| - lineNo == to.line && span.from > to.ch) && - (!filter || filter(span.marker))) - found.push(span.marker.parent || span.marker); - } - ++lineNo; - }); - return found; - }, - getAllMarks: function() { - var markers = []; - this.iter(function(line) { - var sps = line.markedSpans; - if (sps) for (var i = 0; i < sps.length; ++i) - if (sps[i].from != null) markers.push(sps[i].marker); - }); - return markers; - }, - - posFromIndex: function(off) { - var ch, lineNo = this.first; - this.iter(function(line) { - var sz = line.text.length + 1; - if (sz > off) { ch = off; return true; } - off -= sz; - ++lineNo; - }); - return clipPos(this, Pos(lineNo, ch)); - }, - indexFromPos: function (coords) { - coords = clipPos(this, coords); - var index = coords.ch; - if (coords.line < this.first || coords.ch < 0) return 0; - this.iter(this.first, coords.line, function (line) { - index += line.text.length + 1; - }); - return index; - }, - - copy: function(copyHistory) { - var doc = new Doc(getLines(this, this.first, this.first + this.size), - this.modeOption, this.first, this.lineSep); - doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; - doc.sel = this.sel; - doc.extend = false; - if (copyHistory) { - doc.history.undoDepth = this.history.undoDepth; - doc.setHistory(this.getHistory()); - } - return doc; - }, - - linkedDoc: function(options) { - if (!options) options = {}; - var from = this.first, to = this.first + this.size; - if (options.from != null && options.from > from) from = options.from; - if (options.to != null && options.to < to) to = options.to; - var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep); - if (options.sharedHist) copy.history = this.history; - (this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); - copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; - copySharedMarkers(copy, findSharedMarkers(this)); - return copy; - }, - unlinkDoc: function(other) { - if (other instanceof CodeMirror) other = other.doc; - if (this.linked) for (var i = 0; i < this.linked.length; ++i) { - var link = this.linked[i]; - if (link.doc != other) continue; - this.linked.splice(i, 1); - other.unlinkDoc(this); - detachSharedMarkers(findSharedMarkers(this)); - break; - } - // If the histories were shared, split them again - if (other.history == this.history) { - var splitIds = [other.id]; - linkedDocs(other, function(doc) {splitIds.push(doc.id);}, true); - other.history = new History(null); - other.history.done = copyHistoryArray(this.history.done, splitIds); - other.history.undone = copyHistoryArray(this.history.undone, splitIds); - } - }, - iterLinkedDocs: function(f) {linkedDocs(this, f);}, - - getMode: function() {return this.mode;}, - getEditor: function() {return this.cm;}, - - splitLines: function(str) { - if (this.lineSep) return str.split(this.lineSep); - return splitLinesAuto(str); - }, - lineSeparator: function() { return this.lineSep || "\n"; } - }); - - // Public alias. - Doc.prototype.eachLine = Doc.prototype.iter; - - // Set up methods on CodeMirror's prototype to redirect to the editor's document. - var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); - for (var prop in Doc.prototype) if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) - CodeMirror.prototype[prop] = (function(method) { - return function() {return method.apply(this.doc, arguments);}; - })(Doc.prototype[prop]); - - eventMixin(Doc); - - // Call f for all linked documents. - function linkedDocs(doc, f, sharedHistOnly) { - function propagate(doc, skip, sharedHist) { - if (doc.linked) for (var i = 0; i < doc.linked.length; ++i) { - var rel = doc.linked[i]; - if (rel.doc == skip) continue; - var shared = sharedHist && rel.sharedHist; - if (sharedHistOnly && !shared) continue; - f(rel.doc, shared); - propagate(rel.doc, doc, shared); - } - } - propagate(doc, null, true); - } - - // Attach a document to an editor. - function attachDoc(cm, doc) { - if (doc.cm) throw new Error("This document is already in use."); - cm.doc = doc; - doc.cm = cm; - estimateLineHeights(cm); - loadMode(cm); - if (!cm.options.lineWrapping) findMaxLine(cm); - cm.options.mode = doc.modeOption; - regChange(cm); - } - - // LINE UTILITIES - - // Find the line object corresponding to the given line number. - function getLine(doc, n) { - n -= doc.first; - if (n < 0 || n >= doc.size) throw new Error("There is no line " + (n + doc.first) + " in the document."); - for (var chunk = doc; !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]; - } - - // Get the part of a document between two positions, as an array of - // strings. - function getBetween(doc, start, end) { - var out = [], n = start.line; - doc.iter(start.line, end.line + 1, function(line) { - var text = line.text; - if (n == end.line) text = text.slice(0, end.ch); - if (n == start.line) text = text.slice(start.ch); - out.push(text); - ++n; - }); - return out; - } - // Get the lines between from and to, as array of strings. - function getLines(doc, from, to) { - var out = []; - doc.iter(from, to, function(line) { out.push(line.text); }); - return out; - } - - // Update the height of a line, propagating the height change - // upwards to parent nodes. - function updateLineHeight(line, height) { - var diff = height - line.height; - if (diff) for (var n = line; n; n = n.parent) n.height += diff; - } - - // Given a line object, find its line number by walking up through - // its parent links. - 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;; ++i) { - if (chunk.children[i] == cur) break; - no += chunk.children[i].chunkSize(); - } - } - return no + cur.first; - } - - // Find the line at the given vertical position, using the height - // information in the document tree. - function lineAtHeight(chunk, h) { - var n = chunk.first; - outer: do { - for (var i = 0; i < chunk.children.length; ++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; i < chunk.lines.length; ++i) { - var line = chunk.lines[i], lh = line.height; - if (h < lh) break; - h -= lh; - } - return n + i; - } - - - // Find the height above the given line. - function heightAtLine(lineObj) { - lineObj = visualLine(lineObj); - - var h = 0, chunk = lineObj.parent; - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i]; - if (line == lineObj) break; - else h += line.height; - } - for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { - for (var i = 0; i < p.children.length; ++i) { - var cur = p.children[i]; - if (cur == chunk) break; - else h += cur.height; - } - } - return h; - } - - // Get the bidi ordering for the given line (and cache it). Returns - // false for lines that are fully left-to-right, and an array of - // BidiSpan objects otherwise. - function getOrder(line) { - var order = line.order; - if (order == null) order = line.order = bidiOrdering(line.text); - return order; - } - - // HISTORY - - function History(startGen) { - // Arrays of change events and selections. Doing something adds an - // event to done and clears undo. Undoing moves events from done - // to undone, redoing moves them in the other direction. - this.done = []; this.undone = []; - this.undoDepth = Infinity; - // Used to track when changes can be merged into a single undo - // event - this.lastModTime = this.lastSelTime = 0; - this.lastOp = this.lastSelOp = null; - this.lastOrigin = this.lastSelOrigin = null; - // Used by the isClean() method - this.generation = this.maxGeneration = startGen || 1; - } - - // Create a history change event from an updateDoc-style change - // object. - function historyChangeFromChange(doc, change) { - var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; - attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); - linkedDocs(doc, function(doc) {attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1);}, true); - return histChange; - } - - // Pop all selection events off the end of a history array. Stop at - // a change event. - function clearSelectionEvents(array) { - while (array.length) { - var last = lst(array); - if (last.ranges) array.pop(); - else break; - } - } - - // Find the top change event in the history. Pop off selection - // events that are in the way. - function lastChangeEvent(hist, force) { - if (force) { - clearSelectionEvents(hist.done); - return lst(hist.done); - } else if (hist.done.length && !lst(hist.done).ranges) { - return lst(hist.done); - } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { - hist.done.pop(); - return lst(hist.done); - } - } - - // Register a change in the history. Merges changes that are within - // a single operation, ore are close together with an origin that - // allows merging (starting with "+") into a single event. - function addChangeToHistory(doc, change, selAfter, opId) { - var hist = doc.history; - hist.undone.length = 0; - var time = +new Date, cur; - - if ((hist.lastOp == opId || - hist.lastOrigin == change.origin && change.origin && - ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) || - change.origin.charAt(0) == "*")) && - (cur = lastChangeEvent(hist, hist.lastOp == opId))) { - // Merge this change into the last event - var last = lst(cur.changes); - if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { - // Optimized case for simple insertion -- don't want to add - // new changesets for every character typed - last.to = changeEnd(change); - } else { - // Add new sub-event - cur.changes.push(historyChangeFromChange(doc, change)); - } - } else { - // Can not be merged, start a new event. - var before = lst(hist.done); - if (!before || !before.ranges) - pushSelectionToHistory(doc.sel, hist.done); - cur = {changes: [historyChangeFromChange(doc, change)], - generation: hist.generation}; - hist.done.push(cur); - while (hist.done.length > hist.undoDepth) { - hist.done.shift(); - if (!hist.done[0].ranges) hist.done.shift(); - } - } - hist.done.push(selAfter); - hist.generation = ++hist.maxGeneration; - hist.lastModTime = hist.lastSelTime = time; - hist.lastOp = hist.lastSelOp = opId; - hist.lastOrigin = hist.lastSelOrigin = change.origin; - - if (!last) signal(doc, "historyAdded"); - } - - function selectionEventCanBeMerged(doc, origin, prev, sel) { - var ch = origin.charAt(0); - return ch == "*" || - ch == "+" && - prev.ranges.length == sel.ranges.length && - prev.somethingSelected() == sel.somethingSelected() && - new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500); - } - - // Called whenever the selection changes, sets the new selection as - // the pending selection in the history, and pushes the old pending - // selection into the 'done' array when it was significantly - // different (in number of selected ranges, emptiness, or time). - function addSelectionToHistory(doc, sel, opId, options) { - var hist = doc.history, origin = options && options.origin; - - // A new event is started when the previous origin does not match - // the current, or the origins don't allow matching. Origins - // starting with * are always merged, those starting with + are - // merged when similar and close together in time. - if (opId == hist.lastSelOp || - (origin && hist.lastSelOrigin == origin && - (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || - selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) - hist.done[hist.done.length - 1] = sel; - else - pushSelectionToHistory(sel, hist.done); - - hist.lastSelTime = +new Date; - hist.lastSelOrigin = origin; - hist.lastSelOp = opId; - if (options && options.clearRedo !== false) - clearSelectionEvents(hist.undone); - } - - function pushSelectionToHistory(sel, dest) { - var top = lst(dest); - if (!(top && top.ranges && top.equals(sel))) - dest.push(sel); - } - - // Used to store marked span information in the history. - function attachLocalSpans(doc, change, from, to) { - var existing = change["spans_" + doc.id], n = 0; - doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function(line) { - if (line.markedSpans) - (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; - ++n; - }); - } - - // When un/re-doing restores text containing marked spans, those - // that have been explicitly cleared should not be restored. - function removeClearedSpans(spans) { - if (!spans) return null; - for (var i = 0, out; 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; - } - - // Retrieve and filter the old marked spans stored in a change event. - function getOldSpans(doc, change) { - var found = change["spans_" + doc.id]; - if (!found) return null; - for (var i = 0, nw = []; i < change.text.length; ++i) - nw.push(removeClearedSpans(found[i])); - return nw; - } - - // Used both to provide a JSON-safe object in .getHistory, and, when - // detaching a document, to split the history in two - function copyHistoryArray(events, newGroup, instantiateSel) { - for (var i = 0, copy = []; i < events.length; ++i) { - var event = events[i]; - if (event.ranges) { - copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); - continue; - } - var changes = event.changes, newChanges = []; - copy.push({changes: newChanges}); - for (var j = 0; j < changes.length; ++j) { - var change = changes[j], m; - newChanges.push({from: change.from, to: change.to, text: change.text}); - if (newGroup) for (var prop in change) if (m = prop.match(/^spans_(\d+)$/)) { - if (indexOf(newGroup, Number(m[1])) > -1) { - lst(newChanges)[prop] = change[prop]; - delete change[prop]; - } - } - } - } - return copy; - } - - // Rebasing/resetting history to deal with externally-sourced changes - - function rebaseHistSelSingle(pos, from, to, diff) { - if (to < pos.line) { - pos.line += diff; - } else if (from < pos.line) { - pos.line = from; - pos.ch = 0; - } - } - - // Tries to rebase an array of history events given a change in the - // document. If the change touches the same lines as the event, the - // event, and everything 'behind' it, is discarded. If the change is - // before the event, the event's positions are updated. Uses a - // copy-on-write scheme for the positions, to avoid having to - // reallocate them all on every rebase, but also avoid problems with - // shared position objects being unsafely updated. - function rebaseHistArray(array, from, to, diff) { - for (var i = 0; i < array.length; ++i) { - var sub = array[i], ok = true; - if (sub.ranges) { - if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } - for (var j = 0; j < sub.ranges.length; j++) { - rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); - rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); - } - continue; - } - for (var j = 0; j < sub.changes.length; ++j) { - var cur = sub.changes[j]; - if (to < cur.from.line) { - cur.from = Pos(cur.from.line + diff, cur.from.ch); - cur.to = Pos(cur.to.line + diff, cur.to.ch); - } else if (from <= cur.to.line) { - ok = false; - break; - } - } - if (!ok) { - array.splice(0, i + 1); - i = 0; - } - } - } - - function rebaseHist(hist, change) { - var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; - rebaseHistArray(hist.done, from, to, diff); - rebaseHistArray(hist.undone, from, to, diff); - } - - // EVENT UTILITIES - - // Due to the fact that we still support jurassic IE versions, some - // compatibility wrappers are needed. - - var e_preventDefault = CodeMirror.e_preventDefault = function(e) { - if (e.preventDefault) e.preventDefault(); - else e.returnValue = false; - }; - var e_stopPropagation = CodeMirror.e_stopPropagation = function(e) { - if (e.stopPropagation) e.stopPropagation(); - else e.cancelBubble = true; - }; - function e_defaultPrevented(e) { - return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false; - } - var e_stop = CodeMirror.e_stop = function(e) {e_preventDefault(e); e_stopPropagation(e);}; - - 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; - } - - // EVENT HANDLING - - // Lightweight event framework. on/off also work on DOM nodes, - // registering native DOM handlers. - - var on = CodeMirror.on = function(emitter, type, f) { - if (emitter.addEventListener) - emitter.addEventListener(type, f, false); - else if (emitter.attachEvent) - emitter.attachEvent("on" + type, f); - else { - var map = emitter._handlers || (emitter._handlers = {}); - var arr = map[type] || (map[type] = []); - arr.push(f); - } - }; - - var noHandlers = [] - function getHandlers(emitter, type, copy) { - var arr = emitter._handlers && emitter._handlers[type] - if (copy) return arr && arr.length > 0 ? arr.slice() : noHandlers - else return arr || noHandlers - } - - var off = CodeMirror.off = function(emitter, type, f) { - if (emitter.removeEventListener) - emitter.removeEventListener(type, f, false); - else if (emitter.detachEvent) - emitter.detachEvent("on" + type, f); - else { - var handlers = getHandlers(emitter, type, false) - for (var i = 0; i < handlers.length; ++i) - if (handlers[i] == f) { handlers.splice(i, 1); break; } - } - }; - - var signal = CodeMirror.signal = function(emitter, type /*, values...*/) { - var handlers = getHandlers(emitter, type, true) - if (!handlers.length) return; - var args = Array.prototype.slice.call(arguments, 2); - for (var i = 0; i < handlers.length; ++i) handlers[i].apply(null, args); - }; - - var orphanDelayedCallbacks = null; - - // Often, we want to signal events at a point where we are in the - // middle of some work, but don't want the handler to start calling - // other methods on the editor, which might be in an inconsistent - // state or simply not expect any other events to happen. - // signalLater looks whether there are any handlers, and schedules - // them to be executed when the last operation ends, or, if no - // operation is active, when a timeout fires. - function signalLater(emitter, type /*, values...*/) { - var arr = getHandlers(emitter, type, false) - if (!arr.length) return; - var args = Array.prototype.slice.call(arguments, 2), list; - if (operationGroup) { - list = operationGroup.delayedCallbacks; - } else if (orphanDelayedCallbacks) { - list = orphanDelayedCallbacks; - } else { - list = orphanDelayedCallbacks = []; - setTimeout(fireOrphanDelayed, 0); - } - function bnd(f) {return function(){f.apply(null, args);};}; - for (var i = 0; i < arr.length; ++i) - list.push(bnd(arr[i])); - } - - function fireOrphanDelayed() { - var delayed = orphanDelayedCallbacks; - orphanDelayedCallbacks = null; - for (var i = 0; i < delayed.length; ++i) delayed[i](); - } - - // The DOM events that CodeMirror handles can be overridden by - // registering a (non-DOM) handler on the editor for the event name, - // and preventDefault-ing the event in that handler. - function signalDOMEvent(cm, e, override) { - if (typeof e == "string") - e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; - signal(cm, override || e.type, cm, e); - return e_defaultPrevented(e) || e.codemirrorIgnore; - } - - function signalCursorActivity(cm) { - var arr = cm._handlers && cm._handlers.cursorActivity; - if (!arr) return; - var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); - for (var i = 0; i < arr.length; ++i) if (indexOf(set, arr[i]) == -1) - set.push(arr[i]); - } - - function hasHandler(emitter, type) { - return getHandlers(emitter, type).length > 0 - } - - // Add on and off methods to a constructor's prototype, to make - // registering events on such objects more convenient. - function eventMixin(ctor) { - ctor.prototype.on = function(type, f) {on(this, type, f);}; - ctor.prototype.off = function(type, f) {off(this, type, f);}; - } - - // MISC UTILITIES - - // Number of pixels added to scroller and sizer to hide scrollbar - var scrollerGap = 30; - - // Returned or thrown by various protocols to signal 'I'm not - // handling this'. - var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; - - // Reused option objects for setSelection & friends - var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; - - function Delayed() {this.id = null;} - Delayed.prototype.set = function(ms, f) { - clearTimeout(this.id); - this.id = setTimeout(f, ms); - }; - - // Counts the column offset in a string, taking tabs into account. - // Used mostly to find indentation. - var countColumn = CodeMirror.countColumn = function(string, end, tabSize, startIndex, startValue) { - if (end == null) { - end = string.search(/[^\s\u00a0]/); - if (end == -1) end = string.length; - } - for (var i = startIndex || 0, n = startValue || 0;;) { - var nextTab = string.indexOf("\t", i); - if (nextTab < 0 || nextTab >= end) - return n + (end - i); - n += nextTab - i; - n += tabSize - (n % tabSize); - i = nextTab + 1; - } - }; - - // The inverse of countColumn -- find the offset that corresponds to - // a particular column. - var findColumn = CodeMirror.findColumn = function(string, goal, tabSize) { - for (var pos = 0, col = 0;;) { - var nextTab = string.indexOf("\t", pos); - if (nextTab == -1) nextTab = string.length; - var skipped = nextTab - pos; - if (nextTab == string.length || col + skipped >= goal) - return pos + Math.min(skipped, goal - col); - col += nextTab - pos; - col += tabSize - (col % tabSize); - pos = nextTab + 1; - if (col >= goal) return pos; - } - } - - var spaceStrs = [""]; - function spaceStr(n) { - while (spaceStrs.length <= n) - spaceStrs.push(lst(spaceStrs) + " "); - return spaceStrs[n]; - } - - function lst(arr) { return arr[arr.length-1]; } - - var selectInput = function(node) { node.select(); }; - if (ios) // Mobile Safari apparently has a bug where select() is broken. - selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; - else if (ie) // Suppress mysterious IE10 errors - selectInput = function(node) { try { node.select(); } catch(_e) {} }; - - function indexOf(array, elt) { - for (var i = 0; i < array.length; ++i) - if (array[i] == elt) return i; - return -1; - } - function map(array, f) { - var out = []; - for (var i = 0; i < array.length; i++) out[i] = f(array[i], i); - return out; - } - - function nothing() {} - - function createObj(base, props) { - var inst; - if (Object.create) { - inst = Object.create(base); - } else { - nothing.prototype = base; - inst = new nothing(); - } - if (props) copyObj(props, inst); - return inst; - }; - - function copyObj(obj, target, overwrite) { - if (!target) target = {}; - for (var prop in obj) - if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) - target[prop] = obj[prop]; - return target; - } - - function bind(f) { - var args = Array.prototype.slice.call(arguments, 1); - return function(){return f.apply(null, args);}; - } - - var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; - var isWordCharBasic = CodeMirror.isWordChar = function(ch) { - return /\w/.test(ch) || ch > "\x80" && - (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); - }; - function isWordChar(ch, helper) { - if (!helper) return isWordCharBasic(ch); - if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) return true; - return helper.test(ch); - } - - function isEmpty(obj) { - for (var n in obj) if (obj.hasOwnProperty(n) && obj[n]) return false; - return true; - } - - // Extending unicode characters. A series of a non-extending char + - // any number of extending chars is treated as a single unit as far - // as editing and measuring is concerned. This is not fully correct, - // since some scripts/fonts/browsers also treat other configurations - // of code points as a group. - var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; - function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch); } - - // DOM UTILITIES - - 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") e.appendChild(document.createTextNode(content)); - else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); - return e; - } - - var range; - if (document.createRange) range = function(node, start, end, endNode) { - var r = document.createRange(); - r.setEnd(endNode || node, end); - r.setStart(node, start); - return r; - }; - else range = function(node, start, end) { - var r = document.body.createTextRange(); - try { r.moveToElementText(node.parentNode); } - catch(e) { return r; } - r.collapse(true); - r.moveEnd("character", end); - r.moveStart("character", start); - return r; - }; - - function removeChildren(e) { - for (var count = e.childNodes.length; count > 0; --count) - e.removeChild(e.firstChild); - return e; - } - - function removeChildrenAndAdd(parent, e) { - return removeChildren(parent).appendChild(e); - } - - var contains = CodeMirror.contains = function(parent, child) { - if (child.nodeType == 3) // Android browser always returns false when child is a textnode - child = child.parentNode; - if (parent.contains) - return parent.contains(child); - do { - if (child.nodeType == 11) child = child.host; - if (child == parent) return true; - } while (child = child.parentNode); - }; - - function activeElt() { - var activeElement = document.activeElement; - while (activeElement && activeElement.root && activeElement.root.activeElement) - activeElement = activeElement.root.activeElement; - return activeElement; - } - // Older versions of IE throws unspecified error when touching - // document.activeElement in some cases (during loading, in iframe) - if (ie && ie_version < 11) activeElt = function() { - try { return document.activeElement; } - catch(e) { return document.body; } - }; - - function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); } - var rmClass = CodeMirror.rmClass = function(node, cls) { - var current = node.className; - var match = classTest(cls).exec(current); - if (match) { - var after = current.slice(match.index + match[0].length); - node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); - } - }; - var addClass = CodeMirror.addClass = function(node, cls) { - var current = node.className; - if (!classTest(cls).test(current)) node.className += (current ? " " : "") + cls; - }; - function joinClasses(a, b) { - var as = a.split(" "); - for (var i = 0; i < as.length; i++) - if (as[i] && !classTest(as[i]).test(b)) b += " " + as[i]; - return b; - } - - // WINDOW-WIDE EVENTS - - // These must be handled carefully, because naively registering a - // handler for each editor will cause the editors to never be - // garbage collected. - - function forEachCodeMirror(f) { - if (!document.body.getElementsByClassName) return; - var byClass = document.body.getElementsByClassName("CodeMirror"); - for (var i = 0; i < byClass.length; i++) { - var cm = byClass[i].CodeMirror; - if (cm) f(cm); - } - } - - var globalsRegistered = false; - function ensureGlobalHandlers() { - if (globalsRegistered) return; - registerGlobalHandlers(); - globalsRegistered = true; - } - function registerGlobalHandlers() { - // When the window resizes, we need to refresh active editors. - var resizeTimer; - on(window, "resize", function() { - if (resizeTimer == null) resizeTimer = setTimeout(function() { - resizeTimer = null; - forEachCodeMirror(onResize); - }, 100); - }); - // When the window loses focus, we want to show the editor as blurred - on(window, "blur", function() { - forEachCodeMirror(onBlur); - }); - } - - // FEATURE DETECTION - - // Detect drag-and-drop - var dragAndDrop = function() { - // There is *some* kind of drag-and-drop support in IE6-8, but I - // couldn't get it to work yet. - if (ie && ie_version < 9) return false; - var div = elt('div'); - return "draggable" in div || "dragDrop" in div; - }(); - - var zwspSupported; - function zeroWidthElement(measure) { - if (zwspSupported == null) { - var test = elt("span", "\u200b"); - removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); - if (measure.firstChild.offsetHeight != 0) - zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); - } - var node = zwspSupported ? elt("span", "\u200b") : - elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); - node.setAttribute("cm-text", ""); - return node; - } - - // Feature-detect IE's crummy client rect reporting for bidi text - var badBidiRects; - function hasBadBidiRects(measure) { - if (badBidiRects != null) return badBidiRects; - var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); - var r0 = range(txt, 0, 1).getBoundingClientRect(); - if (!r0 || r0.left == r0.right) return false; // Safari returns null in some cases (#2780) - var r1 = range(txt, 1, 2).getBoundingClientRect(); - return badBidiRects = (r1.right - r0.right < 3); - } - - // See if "".split is the broken IE version, if so, provide an - // alternative way to split lines. - var splitLinesAuto = CodeMirror.splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { - var pos = 0, 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; - } - } - return result; - } : function(string){return string.split(/\r\n?|\n/);}; - - 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; - }; - - var hasCopyEvent = (function() { - var e = elt("div"); - if ("oncopy" in e) return true; - e.setAttribute("oncopy", "return;"); - return typeof e.oncopy == "function"; - })(); - - var badZoomedRects = null; - function hasBadZoomedRects(measure) { - if (badZoomedRects != null) return badZoomedRects; - var node = removeChildrenAndAdd(measure, elt("span", "x")); - var normal = node.getBoundingClientRect(); - var fromRange = range(node, 0, 1).getBoundingClientRect(); - return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1; - } - - // KEY NAMES - - var keyNames = CodeMirror.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: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", - 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", - 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", - 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", - 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" - }; - (function() { - // Number keys - for (var i = 0; i < 10; i++) keyNames[i + 48] = keyNames[i + 96] = String(i); - // Alphabetic keys - for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); - // Function keys - for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; - })(); - - // BIDI HELPERS - - function iterateBidiSections(order, from, to, f) { - if (!order) return f(from, to, "ltr"); - var found = false; - for (var i = 0; i < order.length; ++i) { - var part = order[i]; - if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr"); - found = true; - } - } - if (!found) f(from, to, "ltr"); - } - - function bidiLeft(part) { return part.level % 2 ? part.to : part.from; } - function bidiRight(part) { return part.level % 2 ? part.from : part.to; } - - function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0; } - function lineRight(line) { - var order = getOrder(line); - if (!order) return line.text.length; - return bidiRight(lst(order)); - } - - function lineStart(cm, lineN) { - var line = getLine(cm.doc, lineN); - var visual = visualLine(line); - if (visual != line) lineN = lineNo(visual); - var order = getOrder(visual); - var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual); - return Pos(lineN, ch); - } - function lineEnd(cm, lineN) { - var merged, line = getLine(cm.doc, lineN); - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line; - lineN = null; - } - var order = getOrder(line); - var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line); - return Pos(lineN == null ? lineNo(line) : lineN, ch); - } - function lineStartSmart(cm, pos) { - var start = lineStart(cm, pos.line); - var line = getLine(cm.doc, start.line); - var order = getOrder(line); - if (!order || order[0].level == 0) { - var firstNonWS = Math.max(0, line.text.search(/\S/)); - var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; - return Pos(start.line, inWS ? 0 : firstNonWS); - } - return start; - } - - function compareBidiLevel(order, a, b) { - var linedir = order[0].level; - if (a == linedir) return true; - if (b == linedir) return false; - return a < b; - } - var bidiOther; - function getBidiPartAt(order, pos) { - bidiOther = null; - for (var i = 0, found; i < order.length; ++i) { - var cur = order[i]; - if (cur.from < pos && cur.to > pos) return i; - if ((cur.from == pos || cur.to == pos)) { - if (found == null) { - found = i; - } else if (compareBidiLevel(order, cur.level, order[found].level)) { - if (cur.from != cur.to) bidiOther = found; - return i; - } else { - if (cur.from != cur.to) bidiOther = i; - return found; - } - } - } - return found; - } - - function moveInLine(line, pos, dir, byUnit) { - if (!byUnit) return pos + dir; - do pos += dir; - while (pos > 0 && isExtendingChar(line.text.charAt(pos))); - return pos; - } - - // This is needed in order to move 'visually' through bi-directional - // text -- i.e., pressing left should make the cursor go left, even - // when in RTL text. The tricky part is the 'jumps', where RTL and - // LTR text touch each other. This often requires the cursor offset - // to move more than one unit, in order to visually move one unit. - function moveVisually(line, start, dir, byUnit) { - var bidi = getOrder(line); - if (!bidi) return moveLogically(line, start, dir, byUnit); - var pos = getBidiPartAt(bidi, start), part = bidi[pos]; - var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit); - - for (;;) { - if (target > part.from && target < part.to) return target; - if (target == part.from || target == part.to) { - if (getBidiPartAt(bidi, target) == pos) return target; - part = bidi[pos += dir]; - return (dir > 0) == part.level % 2 ? part.to : part.from; - } else { - part = bidi[pos += dir]; - if (!part) return null; - if ((dir > 0) == part.level % 2) - target = moveInLine(line, part.to, -1, byUnit); - else - target = moveInLine(line, part.from, 1, byUnit); - } - } - } - - function moveLogically(line, start, dir, byUnit) { - var target = start + dir; - if (byUnit) while (target > 0 && isExtendingChar(line.text.charAt(target))) target += dir; - return target < 0 || target > line.text.length ? null : target; - } - - // Bidirectional ordering algorithm - // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm - // that this (partially) implements. - - // One-char codes used for character types: - // L (L): Left-to-Right - // R (R): Right-to-Left - // r (AL): Right-to-Left Arabic - // 1 (EN): European Number - // + (ES): European Number Separator - // % (ET): European Number Terminator - // n (AN): Arabic Number - // , (CS): Common Number Separator - // m (NSM): Non-Spacing Mark - // b (BN): Boundary Neutral - // s (B): Paragraph Separator - // t (S): Segment Separator - // w (WS): Whitespace - // N (ON): Other Neutrals - - // Returns null if characters are ordered as they appear - // (left-to-right), or an array of sections ({from, to, level} - // objects) in the order in which they occur visually. - var bidiOrdering = (function() { - // Character types for codepoints 0 to 0xff - var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; - // Character types for codepoints 0x600 to 0x6ff - var arabicTypes = "rrrrrrrrrrrr,rNNmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmrrrrrrrnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmNmmmm"; - function charType(code) { - if (code <= 0xf7) return lowTypes.charAt(code); - else if (0x590 <= code && code <= 0x5f4) return "R"; - else if (0x600 <= code && code <= 0x6ed) return arabicTypes.charAt(code - 0x600); - else if (0x6ee <= code && code <= 0x8ac) return "r"; - else if (0x2000 <= code && code <= 0x200b) return "w"; - else if (code == 0x200c) return "b"; - else return "L"; - } - - var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; - var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; - // Browsers seem to always treat the boundaries of block elements as being L. - var outerType = "L"; - - function BidiSpan(level, from, to) { - this.level = level; - this.from = from; this.to = to; - } - - return function(str) { - if (!bidiRE.test(str)) return false; - var len = str.length, types = []; - for (var i = 0, type; i < len; ++i) - types.push(type = charType(str.charCodeAt(i))); - - // W1. Examine each non-spacing mark (NSM) in the level run, and - // change the type of the NSM to the type of the previous - // character. If the NSM is at the start of the level run, it will - // get the type of sor. - for (var i = 0, prev = outerType; i < len; ++i) { - var type = types[i]; - if (type == "m") types[i] = prev; - else prev = type; - } - - // W2. Search backwards from each instance of a European number - // until the first strong type (R, L, AL, or sor) is found. If an - // AL is found, change the type of the European number to Arabic - // number. - // W3. Change all ALs to R. - for (var i = 0, cur = outerType; i < len; ++i) { - var type = types[i]; - if (type == "1" && cur == "r") types[i] = "n"; - else if (isStrong.test(type)) { cur = type; if (type == "r") types[i] = "R"; } - } - - // W4. A single European separator between two European numbers - // changes to a European number. A single common separator between - // two numbers of the same type changes to that type. - for (var i = 1, prev = types[0]; i < len - 1; ++i) { - var type = types[i]; - if (type == "+" && prev == "1" && types[i+1] == "1") types[i] = "1"; - else if (type == "," && prev == types[i+1] && - (prev == "1" || prev == "n")) types[i] = prev; - prev = type; - } - - // W5. A sequence of European terminators adjacent to European - // numbers changes to all European numbers. - // W6. Otherwise, separators and terminators change to Other - // Neutral. - for (var i = 0; i < len; ++i) { - var type = types[i]; - if (type == ",") types[i] = "N"; - else if (type == "%") { - for (var end = i + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i && types[i-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; - for (var j = i; j < end; ++j) types[j] = replace; - i = end - 1; - } - } - - // W7. Search backwards from each instance of a European number - // until the first strong type (R, L, or sor) is found. If an L is - // found, then change the type of the European number to L. - for (var i = 0, cur = outerType; i < len; ++i) { - var type = types[i]; - if (cur == "L" && type == "1") types[i] = "L"; - else if (isStrong.test(type)) cur = type; - } - - // N1. A sequence of neutrals takes the direction of the - // surrounding strong text if the text on both sides has the same - // direction. European and Arabic numbers act as if they were R in - // terms of their influence on neutrals. Start-of-level-run (sor) - // and end-of-level-run (eor) are used at level run boundaries. - // N2. Any remaining neutrals take the embedding direction. - for (var i = 0; i < len; ++i) { - if (isNeutral.test(types[i])) { - for (var end = i + 1; end < len && isNeutral.test(types[end]); ++end) {} - var before = (i ? types[i-1] : outerType) == "L"; - var after = (end < len ? types[end] : outerType) == "L"; - var replace = before || after ? "L" : "R"; - for (var j = i; j < end; ++j) types[j] = replace; - i = end - 1; - } - } - - // Here we depart from the documented algorithm, in order to avoid - // building up an actual levels array. Since there are only three - // levels (0, 1, 2) in an implementation that doesn't take - // explicit embedding into account, we can build up the order on - // the fly, without following the level-based algorithm. - var order = [], m; - for (var i = 0; i < len;) { - if (countsAsLeft.test(types[i])) { - var start = i; - for (++i; i < len && countsAsLeft.test(types[i]); ++i) {} - order.push(new BidiSpan(0, start, i)); - } else { - var pos = i, at = order.length; - for (++i; i < len && types[i] != "L"; ++i) {} - for (var j = pos; j < i;) { - if (countsAsNum.test(types[j])) { - if (pos < j) order.splice(at, 0, new BidiSpan(1, pos, j)); - var nstart = j; - for (++j; j < i && countsAsNum.test(types[j]); ++j) {} - order.splice(at, 0, new BidiSpan(2, nstart, j)); - pos = j; - } else ++j; - } - if (pos < i) order.splice(at, 0, new BidiSpan(1, pos, i)); - } - } - if (order[0].level == 1 && (m = str.match(/^\s+/))) { - order[0].from = m[0].length; - order.unshift(new BidiSpan(0, 0, m[0].length)); - } - if (lst(order).level == 1 && (m = str.match(/\s+$/))) { - lst(order).to -= m[0].length; - order.push(new BidiSpan(0, len - m[0].length, len)); - } - if (order[0].level == 2) - order.unshift(new BidiSpan(1, order[0].to, order[0].to)); - if (order[0].level != lst(order).level) - order.push(new BidiSpan(order[0].level, len, len)); - - return order; - }; - })(); - - // THE END - - CodeMirror.version = "5.8.0"; - - return CodeMirror; -}); - -},{}],31:[function(_dereq_,module,exports){ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(_dereq_("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("clike", function(config, parserConfig) { - var indentUnit = config.indentUnit, - statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, - dontAlignCalls = parserConfig.dontAlignCalls, - keywords = parserConfig.keywords || {}, - types = parserConfig.types || {}, - builtin = parserConfig.builtin || {}, - blockKeywords = parserConfig.blockKeywords || {}, - defKeywords = parserConfig.defKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings, - indentStatements = parserConfig.indentStatements !== false, - indentSwitch = parserConfig.indentSwitch !== false, - namespaceSeparator = parserConfig.namespaceSeparator, - isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/, - isNumberChar = parserConfig.isNumberChar || /\d/, - isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/, - endStatement = parserConfig.endStatement || /^[;:,]$/; - - var curPunc, isDefKeyword; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (isPunctuationChar.test(ch)) { - curPunc = ch; - return null; - } - if (isNumberChar.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - if (namespaceSeparator) while (stream.match(namespaceSeparator)) - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - - var cur = stream.current(); - if (contains(keywords, cur)) { - if (contains(blockKeywords, cur)) curPunc = "newstatement"; - if (contains(defKeywords, cur)) isDefKeyword = true; - return "keyword"; - } - if (contains(types, cur)) return "variable-3"; - if (contains(builtin, cur)) { - if (contains(blockKeywords, cur)) curPunc = "newstatement"; - return "builtin"; - } - if (contains(atoms, cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function isStatement(type) { - return type == "statement" || type == "switchstatement" || type == "namespace"; - } - function pushContext(state, col, type) { - var indent = state.indented; - if (state.context && isStatement(state.context.type) && !isStatement(type)) - indent = state.context.indented; - return state.context = new Context(indent, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - function typeBefore(stream, state) { - if (state.prevToken == "variable" || state.prevToken == "variable-3") return true; - if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, stream.start))) return true; - } - - function isTopScope(context) { - for (;;) { - if (!context || context.type == "top") return true; - if (context.type == "}" && context.prev.type != "namespace") return false; - context = context.prev; - } - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true, - prevToken: null - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = isDefKeyword = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if (endStatement.test(curPunc)) while (isStatement(state.context.type)) popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (isStatement(ctx.type)) ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (isStatement(ctx.type)) ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (indentStatements && - (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") || - (isStatement(ctx.type) && curPunc == "newstatement"))) { - var type = "statement"; - if (curPunc == "newstatement" && indentSwitch && stream.current() == "switch") - type = "switchstatement"; - else if (style == "keyword" && stream.current() == "namespace") - type = "namespace"; - pushContext(state, stream.column(), type); - } - - if (style == "variable" && - ((state.prevToken == "def" || - (parserConfig.typeFirstDefinitions && typeBefore(stream, state) && - isTopScope(state.context) && stream.match(/^\s*\(/, false))))) - style = "def"; - - if (hooks.token) { - var result = hooks.token(stream, state, style); - if (result !== undefined) style = result; - } - - if (style == "def" && parserConfig.styleDefs === false) style = "variable"; - - state.startOfLine = false; - state.prevToken = isDefKeyword ? "def" : style || curPunc; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (isStatement(ctx.type) && firstChar == "}") ctx = ctx.prev; - if (hooks.indent) { - var hook = hooks.indent(state, ctx, textAfter); - if (typeof hook == "number") return hook - } - var closing = firstChar == ctx.type; - var switchBlock = ctx.prev && ctx.prev.type == "switchstatement"; - if (isStatement(ctx.type)) - return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - if (ctx.align && (!dontAlignCalls || ctx.type != ")")) - return ctx.column + (closing ? 0 : 1); - if (ctx.type == ")" && !closing) - return ctx.indented + statementIndentUnit; - - return ctx.indented + (closing ? 0 : indentUnit) + - (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0); - }, - - electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/, - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - fold: "brace" - }; -}); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - function contains(words, word) { - if (typeof words === "function") { - return words(word); - } else { - return words.propertyIsEnumerable(word); - } - } - var cKeywords = "auto if break case register continue return default do sizeof " + - "static else struct switch extern typedef float union for " + - "goto while enum const volatile"; - var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t"; - - function cppHook(stream, state) { - if (!state.startOfLine) return false; - for (;;) { - if (stream.skipTo("\\")) { - stream.next(); - if (stream.eol()) { - state.tokenize = cppHook; - break; - } - } else { - stream.skipToEnd(); - state.tokenize = null; - break; - } - } - return "meta"; - } - - function pointerHook(_stream, state) { - if (state.prevToken == "variable-3") return "variable-3"; - return false; - } - - function cpp14Literal(stream) { - stream.eatWhile(/[\w\.']/); - return "number"; - } - - function cpp11StringHook(stream, state) { - stream.backUp(1); - // Raw strings. - if (stream.match(/(R|u8R|uR|UR|LR)/)) { - var match = stream.match(/"([^\s\\()]{0,16})\(/); - if (!match) { - return false; - } - state.cpp11RawStringDelim = match[1]; - state.tokenize = tokenRawString; - return tokenRawString(stream, state); - } - // Unicode strings/chars. - if (stream.match(/(u8|u|U|L)/)) { - if (stream.match(/["']/, /* eat */ false)) { - return "string"; - } - return false; - } - // Ignore this hook. - stream.next(); - return false; - } - - function cppLooksLikeConstructor(word) { - var lastTwo = /(\w+)::(\w+)$/.exec(word); - return lastTwo && lastTwo[1] == lastTwo[2]; - } - - // C#-style strings where "" escapes a quote. - function tokenAtString(stream, state) { - var next; - while ((next = stream.next()) != null) { - if (next == '"' && !stream.eat('"')) { - state.tokenize = null; - break; - } - } - return "string"; - } - - // C++11 raw string literal is "( anything )", where - // can be a string up to 16 characters long. - function tokenRawString(stream, state) { - // Escape characters that have special regex meanings. - var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&'); - var match = stream.match(new RegExp(".*?\\)" + delim + '"')); - if (match) - state.tokenize = null; - else - stream.skipToEnd(); - return "string"; - } - - function def(mimes, mode) { - if (typeof mimes == "string") mimes = [mimes]; - var words = []; - function add(obj) { - if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop)) - words.push(prop); - } - add(mode.keywords); - add(mode.types); - add(mode.builtin); - add(mode.atoms); - if (words.length) { - mode.helperType = mimes[0]; - CodeMirror.registerHelper("hintWords", mimes[0], words); - } - - for (var i = 0; i < mimes.length; ++i) - CodeMirror.defineMIME(mimes[i], mode); - } - - def(["text/x-csrc", "text/x-c", "text/x-chdr"], { - name: "clike", - keywords: words(cKeywords), - types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " + - "int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " + - "uint32_t uint64_t"), - blockKeywords: words("case do else for if switch while struct"), - defKeywords: words("struct"), - typeFirstDefinitions: true, - atoms: words("null true false"), - hooks: {"#": cppHook, "*": pointerHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def(["text/x-c++src", "text/x-c++hdr"], { - name: "clike", - keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " + - "static_cast typeid catch operator template typename class friend private " + - "this using const_cast inline public throw virtual delete mutable protected " + - "alignas alignof constexpr decltype nullptr noexcept thread_local final " + - "static_assert override"), - types: words(cTypes + " bool wchar_t"), - blockKeywords: words("catch class do else finally for if struct switch try while"), - defKeywords: words("class namespace struct enum union"), - typeFirstDefinitions: true, - atoms: words("true false null"), - hooks: { - "#": cppHook, - "*": pointerHook, - "u": cpp11StringHook, - "U": cpp11StringHook, - "L": cpp11StringHook, - "R": cpp11StringHook, - "0": cpp14Literal, - "1": cpp14Literal, - "2": cpp14Literal, - "3": cpp14Literal, - "4": cpp14Literal, - "5": cpp14Literal, - "6": cpp14Literal, - "7": cpp14Literal, - "8": cpp14Literal, - "9": cpp14Literal, - token: function(stream, state, style) { - if (style == "variable" && stream.peek() == "(" && - (state.prevToken == ";" || state.prevToken == null || - state.prevToken == "}") && - cppLooksLikeConstructor(stream.current())) - return "def"; - } - }, - namespaceSeparator: "::", - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-java", { - name: "clike", - keywords: words("abstract assert break case catch class const continue default " + - "do else enum extends final finally float for goto if implements import " + - "instanceof interface native new package private protected public " + - "return static strictfp super switch synchronized this throw throws transient " + - "try volatile while"), - types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " + - "Integer Long Number Object Short String StringBuffer StringBuilder Void"), - blockKeywords: words("catch class do else finally for if switch try while"), - defKeywords: words("class interface package enum"), - typeFirstDefinitions: true, - atoms: words("true false null"), - endStatement: /^[;:]$/, - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - }, - modeProps: {fold: ["brace", "import"]} - }); - - def("text/x-csharp", { - name: "clike", - keywords: words("abstract as async await base break case catch checked class const continue" + - " default delegate do else enum event explicit extern finally fixed for" + - " foreach goto if implicit in interface internal is lock namespace new" + - " operator out override params private protected public readonly ref return sealed" + - " sizeof stackalloc static struct switch this throw try typeof unchecked" + - " unsafe using virtual void volatile while add alias ascending descending dynamic from get" + - " global group into join let orderby partial remove select set value var yield"), - types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" + - " Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" + - " UInt64 bool byte char decimal double short int long object" + - " sbyte float string ushort uint ulong"), - blockKeywords: words("catch class do else finally for foreach if struct switch try while"), - defKeywords: words("class interface namespace struct var"), - typeFirstDefinitions: true, - atoms: words("true false null"), - hooks: { - "@": function(stream, state) { - if (stream.eat('"')) { - state.tokenize = tokenAtString; - return tokenAtString(stream, state); - } - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); - - function tokenTripleString(stream, state) { - var escaped = false; - while (!stream.eol()) { - if (!escaped && stream.match('"""')) { - state.tokenize = null; - break; - } - escaped = stream.next() == "\\" && !escaped; - } - return "string"; - } - - def("text/x-scala", { - name: "clike", - keywords: words( - - /* scala */ - "abstract case catch class def do else extends final finally for forSome if " + - "implicit import lazy match new null object override package private protected return " + - "sealed super this throw trait try type val var while with yield _ : = => <- <: " + - "<% >: # @ " + - - /* package scala */ - "assert assume require print println printf readLine readBoolean readByte readShort " + - "readChar readInt readLong readFloat readDouble " + - - ":: #:: " - ), - types: words( - "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " + - "Enumeration Equiv Error Exception Fractional Function IndexedSeq Integral Iterable " + - "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " + - "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " + - "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " + - - /* package java.lang */ - "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + - "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + - "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + - "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" - ), - multiLineStrings: true, - blockKeywords: words("catch class do else finally for forSome if match switch try while"), - defKeywords: words("class def object package trait type val var"), - atoms: words("true false null"), - indentStatements: false, - indentSwitch: false, - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - }, - '"': function(stream, state) { - if (!stream.match('""')) return false; - state.tokenize = tokenTripleString; - return state.tokenize(stream, state); - }, - "'": function(stream) { - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - return "atom"; - } - }, - modeProps: {closeBrackets: {triples: '"'}} - }); - - def("text/x-kotlin", { - name: "clike", - keywords: words( - /*keywords*/ - "package as typealias class interface this super val " + - "var fun for is in This throw return " + - "break continue object if else while do try when !in !is as?" + - - /*soft keywords*/ - "file import where by get set abstract enum open inner override private public internal " + - "protected catch finally out final vararg reified dynamic companion constructor init " + - "sealed field property receiver param sparam lateinit data inline noinline tailrec " + - "external annotation crossinline" - ), - types: words( - /* package java.lang */ - "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + - "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + - "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + - "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" - ), - multiLineStrings: true, - blockKeywords: words("catch class do else finally for if where try while enum"), - defKeywords: words("class val var object package interface fun"), - atoms: words("true false null this"), - modeProps: {closeBrackets: {triples: '"'}} - }); - - def(["x-shader/x-vertex", "x-shader/x-fragment"], { - name: "clike", - keywords: words("sampler1D sampler2D sampler3D samplerCube " + - "sampler1DShadow sampler2DShadow " + - "const attribute uniform varying " + - "break continue discard return " + - "for while do if else struct " + - "in out inout"), - types: words("float int bool void " + - "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " + - "mat2 mat3 mat4"), - blockKeywords: words("for while do if else struct"), - builtin: words("radians degrees sin cos tan asin acos atan " + - "pow exp log exp2 sqrt inversesqrt " + - "abs sign floor ceil fract mod min max clamp mix step smoothstep " + - "length distance dot cross normalize ftransform faceforward " + - "reflect refract matrixCompMult " + - "lessThan lessThanEqual greaterThan greaterThanEqual " + - "equal notEqual any all not " + - "texture1D texture1DProj texture1DLod texture1DProjLod " + - "texture2D texture2DProj texture2DLod texture2DProjLod " + - "texture3D texture3DProj texture3DLod texture3DProjLod " + - "textureCube textureCubeLod " + - "shadow1D shadow2D shadow1DProj shadow2DProj " + - "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " + - "dFdx dFdy fwidth " + - "noise1 noise2 noise3 noise4"), - atoms: words("true false " + - "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " + - "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " + - "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " + - "gl_FogCoord gl_PointCoord " + - "gl_Position gl_PointSize gl_ClipVertex " + - "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " + - "gl_TexCoord gl_FogFragCoord " + - "gl_FragCoord gl_FrontFacing " + - "gl_FragData gl_FragDepth " + - "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " + - "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " + - "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " + - "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " + - "gl_ProjectionMatrixInverseTranspose " + - "gl_ModelViewProjectionMatrixInverseTranspose " + - "gl_TextureMatrixInverseTranspose " + - "gl_NormalScale gl_DepthRange gl_ClipPlane " + - "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " + - "gl_FrontLightModelProduct gl_BackLightModelProduct " + - "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " + - "gl_FogParameters " + - "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " + - "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " + - "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " + - "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " + - "gl_MaxDrawBuffers"), - indentSwitch: false, - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-nesc", { - name: "clike", - keywords: words(cKeywords + "as atomic async call command component components configuration event generic " + - "implementation includes interface module new norace nx_struct nx_union post provides " + - "signal task uses abstract extends"), - types: words(cTypes), - blockKeywords: words("case do else for if switch while struct"), - atoms: words("null true false"), - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-objectivec", { - name: "clike", - keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginery BOOL Class bycopy byref id IMP in " + - "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"), - types: words(cTypes), - atoms: words("YES NO NULL NILL ON OFF true false"), - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$]/); - return "keyword"; - }, - "#": cppHook, - indent: function(_state, ctx, textAfter) { - if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented - } - }, - modeProps: {fold: "brace"} - }); - - def("text/x-squirrel", { - name: "clike", - keywords: words("base break clone continue const default delete enum extends function in class" + - " foreach local resume return this throw typeof yield constructor instanceof static"), - types: words(cTypes), - blockKeywords: words("case catch class else for foreach if switch try while"), - defKeywords: words("function local class"), - typeFirstDefinitions: true, - atoms: words("true false null"), - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - // Ceylon Strings need to deal with interpolation - var stringTokenizer = null; - function tokenCeylonString(type) { - return function(stream, state) { - var escaped = false, next, end = false; - while (!stream.eol()) { - if (!escaped && stream.match('"') && - (type == "single" || stream.match('""'))) { - end = true; - break; - } - if (!escaped && stream.match('``')) { - stringTokenizer = tokenCeylonString(type); - end = true; - break; - } - next = stream.next(); - escaped = type == "single" && !escaped && next == "\\"; - } - if (end) - state.tokenize = null; - return "string"; - } - } - - def("text/x-ceylon", { - name: "clike", - keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" + - " exists extends finally for function given if import in interface is let module new" + - " nonempty object of out outer package return satisfies super switch then this throw" + - " try value void while"), - types: function(word) { - // In Ceylon all identifiers that start with an uppercase are types - var first = word.charAt(0); - return (first === first.toUpperCase() && first !== first.toLowerCase()); - }, - blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"), - defKeywords: words("class dynamic function interface module object package value"), - builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" + - " native optional sealed see serializable shared suppressWarnings tagged throws variable"), - isPunctuationChar: /[\[\]{}\(\),;\:\.`]/, - isOperatorChar: /[+\-*&%=<>!?|^~:\/]/, - isNumberChar: /[\d#$]/, - multiLineStrings: true, - typeFirstDefinitions: true, - atoms: words("true false null larger smaller equal empty finished"), - indentSwitch: false, - styleDefs: false, - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - }, - '"': function(stream, state) { - state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single"); - return state.tokenize(stream, state); - }, - '`': function(stream, state) { - if (!stringTokenizer || !stream.match('`')) return false; - state.tokenize = stringTokenizer; - stringTokenizer = null; - return state.tokenize(stream, state); - }, - "'": function(stream) { - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - return "atom"; - }, - token: function(_stream, state, style) { - if ((style == "variable" || style == "variable-3") && - state.prevToken == ".") { - return "variable-2"; - } - } - }, - modeProps: { - fold: ["brace", "import"], - closeBrackets: {triples: '"'} - } - }); - -}); - -},{"../../lib/codemirror":30}],32:[function(_dereq_,module,exports){ -_dereq_('../modules/web.dom.iterable'); -_dereq_('../modules/es6.string.iterator'); -module.exports = _dereq_('../modules/core.get-iterator'); -},{"../modules/core.get-iterator":95,"../modules/es6.string.iterator":104,"../modules/web.dom.iterable":106}],33:[function(_dereq_,module,exports){ -_dereq_('../../modules/es6.object.assign'); -module.exports = _dereq_('../../modules/$.core').Object.assign; -},{"../../modules/$.core":49,"../../modules/es6.object.assign":97}],34:[function(_dereq_,module,exports){ -var $ = _dereq_('../../modules/$'); -module.exports = function create(P, D){ - return $.create(P, D); -}; -},{"../../modules/$":71}],35:[function(_dereq_,module,exports){ -var $ = _dereq_('../../modules/$'); -module.exports = function defineProperty(it, key, desc){ - return $.setDesc(it, key, desc); -}; -},{"../../modules/$":71}],36:[function(_dereq_,module,exports){ -var $ = _dereq_('../../modules/$'); -_dereq_('../../modules/es6.object.get-own-property-descriptor'); -module.exports = function getOwnPropertyDescriptor(it, key){ - return $.getDesc(it, key); -}; -},{"../../modules/$":71,"../../modules/es6.object.get-own-property-descriptor":98}],37:[function(_dereq_,module,exports){ -_dereq_('../../modules/es6.object.keys'); -module.exports = _dereq_('../../modules/$.core').Object.keys; -},{"../../modules/$.core":49,"../../modules/es6.object.keys":99}],38:[function(_dereq_,module,exports){ -_dereq_('../../modules/es6.object.set-prototype-of'); -module.exports = _dereq_('../../modules/$.core').Object.setPrototypeOf; -},{"../../modules/$.core":49,"../../modules/es6.object.set-prototype-of":100}],39:[function(_dereq_,module,exports){ -_dereq_('../modules/es6.object.to-string'); -_dereq_('../modules/es6.string.iterator'); -_dereq_('../modules/web.dom.iterable'); -_dereq_('../modules/es6.promise'); -module.exports = _dereq_('../modules/$.core').Promise; -},{"../modules/$.core":49,"../modules/es6.object.to-string":101,"../modules/es6.promise":102,"../modules/es6.string.iterator":104,"../modules/web.dom.iterable":106}],40:[function(_dereq_,module,exports){ -_dereq_('../modules/es6.object.to-string'); -_dereq_('../modules/es6.string.iterator'); -_dereq_('../modules/web.dom.iterable'); -_dereq_('../modules/es6.set'); -_dereq_('../modules/es7.set.to-json'); -module.exports = _dereq_('../modules/$.core').Set; -},{"../modules/$.core":49,"../modules/es6.object.to-string":101,"../modules/es6.set":103,"../modules/es6.string.iterator":104,"../modules/es7.set.to-json":105,"../modules/web.dom.iterable":106}],41:[function(_dereq_,module,exports){ -module.exports = function(it){ - if(typeof it != 'function')throw TypeError(it + ' is not a function!'); - return it; -}; -},{}],42:[function(_dereq_,module,exports){ -module.exports = function(){ /* empty */ }; -},{}],43:[function(_dereq_,module,exports){ -var isObject = _dereq_('./$.is-object'); -module.exports = function(it){ - if(!isObject(it))throw TypeError(it + ' is not an object!'); - return it; -}; -},{"./$.is-object":64}],44:[function(_dereq_,module,exports){ -// getting tag from 19.1.3.6 Object.prototype.toString() -var cof = _dereq_('./$.cof') - , TAG = _dereq_('./$.wks')('toStringTag') - // ES3 wrong here - , ARG = cof(function(){ return arguments; }()) == 'Arguments'; - -module.exports = function(it){ - var O, T, B; - return it === undefined ? 'Undefined' : it === null ? 'Null' - // @@toStringTag case - : typeof (T = (O = Object(it))[TAG]) == 'string' ? T - // builtinTag case - : ARG ? cof(O) - // ES3 arguments fallback - : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; -}; -},{"./$.cof":45,"./$.wks":93}],45:[function(_dereq_,module,exports){ -var toString = {}.toString; - -module.exports = function(it){ - return toString.call(it).slice(8, -1); -}; -},{}],46:[function(_dereq_,module,exports){ -'use strict'; -var $ = _dereq_('./$') - , hide = _dereq_('./$.hide') - , redefineAll = _dereq_('./$.redefine-all') - , ctx = _dereq_('./$.ctx') - , strictNew = _dereq_('./$.strict-new') - , defined = _dereq_('./$.defined') - , forOf = _dereq_('./$.for-of') - , $iterDefine = _dereq_('./$.iter-define') - , step = _dereq_('./$.iter-step') - , ID = _dereq_('./$.uid')('id') - , $has = _dereq_('./$.has') - , isObject = _dereq_('./$.is-object') - , setSpecies = _dereq_('./$.set-species') - , DESCRIPTORS = _dereq_('./$.descriptors') - , isExtensible = Object.isExtensible || isObject - , SIZE = DESCRIPTORS ? '_s' : 'size' - , id = 0; - -var fastKey = function(it, create){ - // return primitive with prefix - if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; - if(!$has(it, ID)){ - // can't set id to frozen object - if(!isExtensible(it))return 'F'; - // not necessary to add id - if(!create)return 'E'; - // add missing object id - hide(it, ID, ++id); - // return object id with prefix - } return 'O' + it[ID]; -}; - -var getEntry = function(that, key){ - // fast case - var index = fastKey(key), entry; - if(index !== 'F')return that._i[index]; - // frozen object case - for(entry = that._f; entry; entry = entry.n){ - if(entry.k == key)return entry; - } -}; - -module.exports = { - getConstructor: function(wrapper, NAME, IS_MAP, ADDER){ - var C = wrapper(function(that, iterable){ - strictNew(that, C, NAME); - that._i = $.create(null); // index - that._f = undefined; // first entry - that._l = undefined; // last entry - that[SIZE] = 0; // size - if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that); - }); - redefineAll(C.prototype, { - // 23.1.3.1 Map.prototype.clear() - // 23.2.3.2 Set.prototype.clear() - clear: function clear(){ - for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){ - entry.r = true; - if(entry.p)entry.p = entry.p.n = undefined; - delete data[entry.i]; - } - that._f = that._l = undefined; - that[SIZE] = 0; - }, - // 23.1.3.3 Map.prototype.delete(key) - // 23.2.3.4 Set.prototype.delete(value) - 'delete': function(key){ - var that = this - , entry = getEntry(that, key); - if(entry){ - var next = entry.n - , prev = entry.p; - delete that._i[entry.i]; - entry.r = true; - if(prev)prev.n = next; - if(next)next.p = prev; - if(that._f == entry)that._f = next; - if(that._l == entry)that._l = prev; - that[SIZE]--; - } return !!entry; - }, - // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined) - // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined) - forEach: function forEach(callbackfn /*, that = undefined */){ - var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3) - , entry; - while(entry = entry ? entry.n : this._f){ - f(entry.v, entry.k, this); - // revert to the last existing entry - while(entry && entry.r)entry = entry.p; - } - }, - // 23.1.3.7 Map.prototype.has(key) - // 23.2.3.7 Set.prototype.has(value) - has: function has(key){ - return !!getEntry(this, key); - } - }); - if(DESCRIPTORS)$.setDesc(C.prototype, 'size', { - get: function(){ - return defined(this[SIZE]); - } - }); - return C; - }, - def: function(that, key, value){ - var entry = getEntry(that, key) - , prev, index; - // change existing entry - if(entry){ - entry.v = value; - // create new entry - } else { - that._l = entry = { - i: index = fastKey(key, true), // <- index - k: key, // <- key - v: value, // <- value - p: prev = that._l, // <- previous entry - n: undefined, // <- next entry - r: false // <- removed - }; - if(!that._f)that._f = entry; - if(prev)prev.n = entry; - that[SIZE]++; - // add to index - if(index !== 'F')that._i[index] = entry; - } return that; - }, - getEntry: getEntry, - setStrong: function(C, NAME, IS_MAP){ - // add .keys, .values, .entries, [@@iterator] - // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11 - $iterDefine(C, NAME, function(iterated, kind){ - this._t = iterated; // target - this._k = kind; // kind - this._l = undefined; // previous - }, function(){ - var that = this - , kind = that._k - , entry = that._l; - // revert to the last existing entry - while(entry && entry.r)entry = entry.p; - // get next entry - if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){ - // or finish the iteration - that._t = undefined; - return step(1); - } - // return step by kind - if(kind == 'keys' )return step(0, entry.k); - if(kind == 'values')return step(0, entry.v); - return step(0, [entry.k, entry.v]); - }, IS_MAP ? 'entries' : 'values' , !IS_MAP, true); - - // add [@@species], 23.1.2.2, 23.2.2.2 - setSpecies(NAME); - } -}; -},{"./$":71,"./$.ctx":50,"./$.defined":51,"./$.descriptors":52,"./$.for-of":56,"./$.has":58,"./$.hide":59,"./$.is-object":64,"./$.iter-define":67,"./$.iter-step":69,"./$.redefine-all":77,"./$.set-species":81,"./$.strict-new":85,"./$.uid":92}],47:[function(_dereq_,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var forOf = _dereq_('./$.for-of') - , classof = _dereq_('./$.classof'); -module.exports = function(NAME){ - return function toJSON(){ - if(classof(this) != NAME)throw TypeError(NAME + "#toJSON isn't generic"); - var arr = []; - forOf(this, false, arr.push, arr); - return arr; - }; -}; -},{"./$.classof":44,"./$.for-of":56}],48:[function(_dereq_,module,exports){ -'use strict'; -var $ = _dereq_('./$') - , global = _dereq_('./$.global') - , $export = _dereq_('./$.export') - , fails = _dereq_('./$.fails') - , hide = _dereq_('./$.hide') - , redefineAll = _dereq_('./$.redefine-all') - , forOf = _dereq_('./$.for-of') - , strictNew = _dereq_('./$.strict-new') - , isObject = _dereq_('./$.is-object') - , setToStringTag = _dereq_('./$.set-to-string-tag') - , DESCRIPTORS = _dereq_('./$.descriptors'); - -module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){ - var Base = global[NAME] - , C = Base - , ADDER = IS_MAP ? 'set' : 'add' - , proto = C && C.prototype - , O = {}; - if(!DESCRIPTORS || typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){ - new C().entries().next(); - }))){ - // create collection constructor - C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); - redefineAll(C.prototype, methods); - } else { - C = wrapper(function(target, iterable){ - strictNew(target, C, NAME); - target._c = new Base; - if(iterable != undefined)forOf(iterable, IS_MAP, target[ADDER], target); - }); - $.each.call('add,clear,delete,forEach,get,has,set,keys,values,entries'.split(','),function(KEY){ - var IS_ADDER = KEY == 'add' || KEY == 'set'; - if(KEY in proto && !(IS_WEAK && KEY == 'clear'))hide(C.prototype, KEY, function(a, b){ - if(!IS_ADDER && IS_WEAK && !isObject(a))return KEY == 'get' ? undefined : false; - var result = this._c[KEY](a === 0 ? 0 : a, b); - return IS_ADDER ? this : result; - }); - }); - if('size' in proto)$.setDesc(C.prototype, 'size', { - get: function(){ - return this._c.size; - } - }); - } - - setToStringTag(C, NAME); - - O[NAME] = C; - $export($export.G + $export.W + $export.F, O); - - if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP); - - return C; -}; -},{"./$":71,"./$.descriptors":52,"./$.export":54,"./$.fails":55,"./$.for-of":56,"./$.global":57,"./$.hide":59,"./$.is-object":64,"./$.redefine-all":77,"./$.set-to-string-tag":82,"./$.strict-new":85}],49:[function(_dereq_,module,exports){ -var core = module.exports = {version: '1.2.6'}; -if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef -},{}],50:[function(_dereq_,module,exports){ -// optional / simple context binding -var aFunction = _dereq_('./$.a-function'); -module.exports = function(fn, that, length){ - aFunction(fn); - if(that === undefined)return fn; - switch(length){ - case 1: return function(a){ - return fn.call(that, a); - }; - case 2: return function(a, b){ - return fn.call(that, a, b); - }; - case 3: return function(a, b, c){ - return fn.call(that, a, b, c); - }; - } - return function(/* ...args */){ - return fn.apply(that, arguments); - }; -}; -},{"./$.a-function":41}],51:[function(_dereq_,module,exports){ -// 7.2.1 RequireObjectCoercible(argument) -module.exports = function(it){ - if(it == undefined)throw TypeError("Can't call method on " + it); - return it; -}; -},{}],52:[function(_dereq_,module,exports){ -// Thank's IE8 for his funny defineProperty -module.exports = !_dereq_('./$.fails')(function(){ - return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; -}); -},{"./$.fails":55}],53:[function(_dereq_,module,exports){ -var isObject = _dereq_('./$.is-object') - , document = _dereq_('./$.global').document - // in old IE typeof document.createElement is 'object' - , is = isObject(document) && isObject(document.createElement); -module.exports = function(it){ - return is ? document.createElement(it) : {}; -}; -},{"./$.global":57,"./$.is-object":64}],54:[function(_dereq_,module,exports){ -var global = _dereq_('./$.global') - , core = _dereq_('./$.core') - , ctx = _dereq_('./$.ctx') - , PROTOTYPE = 'prototype'; - -var $export = function(type, name, source){ - var IS_FORCED = type & $export.F - , IS_GLOBAL = type & $export.G - , IS_STATIC = type & $export.S - , IS_PROTO = type & $export.P - , IS_BIND = type & $export.B - , IS_WRAP = type & $export.W - , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) - , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] - , key, own, out; - if(IS_GLOBAL)source = name; - for(key in source){ - // contains in native - own = !IS_FORCED && target && key in target; - if(own && key in exports)continue; - // export native or passed - out = own ? target[key] : source[key]; - // prevent global pollution for namespaces - exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] - // bind timers to global for call from export context - : IS_BIND && own ? ctx(out, global) - // wrap global constructors for prevent change them in library - : IS_WRAP && target[key] == out ? (function(C){ - var F = function(param){ - return this instanceof C ? new C(param) : C(param); - }; - F[PROTOTYPE] = C[PROTOTYPE]; - return F; - // make static versions for prototype methods - })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; - if(IS_PROTO)(exports[PROTOTYPE] || (exports[PROTOTYPE] = {}))[key] = out; - } -}; -// type bitmap -$export.F = 1; // forced -$export.G = 2; // global -$export.S = 4; // static -$export.P = 8; // proto -$export.B = 16; // bind -$export.W = 32; // wrap -module.exports = $export; -},{"./$.core":49,"./$.ctx":50,"./$.global":57}],55:[function(_dereq_,module,exports){ -module.exports = function(exec){ - try { - return !!exec(); - } catch(e){ - return true; - } -}; -},{}],56:[function(_dereq_,module,exports){ -var ctx = _dereq_('./$.ctx') - , call = _dereq_('./$.iter-call') - , isArrayIter = _dereq_('./$.is-array-iter') - , anObject = _dereq_('./$.an-object') - , toLength = _dereq_('./$.to-length') - , getIterFn = _dereq_('./core.get-iterator-method'); -module.exports = function(iterable, entries, fn, that){ - var iterFn = getIterFn(iterable) - , f = ctx(fn, that, entries ? 2 : 1) - , index = 0 - , length, step, iterator; - if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!'); - // fast case for arrays with default iterator - if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){ - entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); - } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){ - call(iterator, f, step.value, entries); - } -}; -},{"./$.an-object":43,"./$.ctx":50,"./$.is-array-iter":63,"./$.iter-call":65,"./$.to-length":90,"./core.get-iterator-method":94}],57:[function(_dereq_,module,exports){ -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); -if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef -},{}],58:[function(_dereq_,module,exports){ -var hasOwnProperty = {}.hasOwnProperty; -module.exports = function(it, key){ - return hasOwnProperty.call(it, key); -}; -},{}],59:[function(_dereq_,module,exports){ -var $ = _dereq_('./$') - , createDesc = _dereq_('./$.property-desc'); -module.exports = _dereq_('./$.descriptors') ? function(object, key, value){ - return $.setDesc(object, key, createDesc(1, value)); -} : function(object, key, value){ - object[key] = value; - return object; -}; -},{"./$":71,"./$.descriptors":52,"./$.property-desc":76}],60:[function(_dereq_,module,exports){ -module.exports = _dereq_('./$.global').document && document.documentElement; -},{"./$.global":57}],61:[function(_dereq_,module,exports){ -// fast apply, http://jsperf.lnkit.com/fast-apply/5 -module.exports = function(fn, args, that){ - var un = that === undefined; - switch(args.length){ - case 0: return un ? fn() - : fn.call(that); - case 1: return un ? fn(args[0]) - : fn.call(that, args[0]); - case 2: return un ? fn(args[0], args[1]) - : fn.call(that, args[0], args[1]); - case 3: return un ? fn(args[0], args[1], args[2]) - : fn.call(that, args[0], args[1], args[2]); - case 4: return un ? fn(args[0], args[1], args[2], args[3]) - : fn.call(that, args[0], args[1], args[2], args[3]); - } return fn.apply(that, args); -}; -},{}],62:[function(_dereq_,module,exports){ -// fallback for non-array-like ES3 and non-enumerable old V8 strings -var cof = _dereq_('./$.cof'); -module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){ - return cof(it) == 'String' ? it.split('') : Object(it); -}; -},{"./$.cof":45}],63:[function(_dereq_,module,exports){ -// check on default Array iterator -var Iterators = _dereq_('./$.iterators') - , ITERATOR = _dereq_('./$.wks')('iterator') - , ArrayProto = Array.prototype; - -module.exports = function(it){ - return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); -}; -},{"./$.iterators":70,"./$.wks":93}],64:[function(_dereq_,module,exports){ -module.exports = function(it){ - return typeof it === 'object' ? it !== null : typeof it === 'function'; -}; -},{}],65:[function(_dereq_,module,exports){ -// call something on iterator step with safe closing on error -var anObject = _dereq_('./$.an-object'); -module.exports = function(iterator, fn, value, entries){ - try { - return entries ? fn(anObject(value)[0], value[1]) : fn(value); - // 7.4.6 IteratorClose(iterator, completion) - } catch(e){ - var ret = iterator['return']; - if(ret !== undefined)anObject(ret.call(iterator)); - throw e; - } -}; -},{"./$.an-object":43}],66:[function(_dereq_,module,exports){ -'use strict'; -var $ = _dereq_('./$') - , descriptor = _dereq_('./$.property-desc') - , setToStringTag = _dereq_('./$.set-to-string-tag') - , IteratorPrototype = {}; - -// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() -_dereq_('./$.hide')(IteratorPrototype, _dereq_('./$.wks')('iterator'), function(){ return this; }); - -module.exports = function(Constructor, NAME, next){ - Constructor.prototype = $.create(IteratorPrototype, {next: descriptor(1, next)}); - setToStringTag(Constructor, NAME + ' Iterator'); -}; -},{"./$":71,"./$.hide":59,"./$.property-desc":76,"./$.set-to-string-tag":82,"./$.wks":93}],67:[function(_dereq_,module,exports){ -'use strict'; -var LIBRARY = _dereq_('./$.library') - , $export = _dereq_('./$.export') - , redefine = _dereq_('./$.redefine') - , hide = _dereq_('./$.hide') - , has = _dereq_('./$.has') - , Iterators = _dereq_('./$.iterators') - , $iterCreate = _dereq_('./$.iter-create') - , setToStringTag = _dereq_('./$.set-to-string-tag') - , getProto = _dereq_('./$').getProto - , ITERATOR = _dereq_('./$.wks')('iterator') - , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next` - , FF_ITERATOR = '@@iterator' - , KEYS = 'keys' - , VALUES = 'values'; - -var returnThis = function(){ return this; }; - -module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ - $iterCreate(Constructor, NAME, next); - var getMethod = function(kind){ - if(!BUGGY && kind in proto)return proto[kind]; - switch(kind){ - case KEYS: return function keys(){ return new Constructor(this, kind); }; - case VALUES: return function values(){ return new Constructor(this, kind); }; - } return function entries(){ return new Constructor(this, kind); }; - }; - var TAG = NAME + ' Iterator' - , DEF_VALUES = DEFAULT == VALUES - , VALUES_BUG = false - , proto = Base.prototype - , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] - , $default = $native || getMethod(DEFAULT) - , methods, key; - // Fix native - if($native){ - var IteratorPrototype = getProto($default.call(new Base)); - // Set @@toStringTag to native iterators - setToStringTag(IteratorPrototype, TAG, true); - // FF fix - if(!LIBRARY && has(proto, FF_ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis); - // fix Array#{values, @@iterator}.name in V8 / FF - if(DEF_VALUES && $native.name !== VALUES){ - VALUES_BUG = true; - $default = function values(){ return $native.call(this); }; - } - } - // Define iterator - if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ - hide(proto, ITERATOR, $default); - } - // Plug for library - Iterators[NAME] = $default; - Iterators[TAG] = returnThis; - if(DEFAULT){ - methods = { - values: DEF_VALUES ? $default : getMethod(VALUES), - keys: IS_SET ? $default : getMethod(KEYS), - entries: !DEF_VALUES ? $default : getMethod('entries') - }; - if(FORCED)for(key in methods){ - if(!(key in proto))redefine(proto, key, methods[key]); - } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); - } - return methods; -}; -},{"./$":71,"./$.export":54,"./$.has":58,"./$.hide":59,"./$.iter-create":66,"./$.iterators":70,"./$.library":72,"./$.redefine":78,"./$.set-to-string-tag":82,"./$.wks":93}],68:[function(_dereq_,module,exports){ -var ITERATOR = _dereq_('./$.wks')('iterator') - , SAFE_CLOSING = false; - -try { - var riter = [7][ITERATOR](); - riter['return'] = function(){ SAFE_CLOSING = true; }; - Array.from(riter, function(){ throw 2; }); -} catch(e){ /* empty */ } - -module.exports = function(exec, skipClosing){ - if(!skipClosing && !SAFE_CLOSING)return false; - var safe = false; - try { - var arr = [7] - , iter = arr[ITERATOR](); - iter.next = function(){ return {done: safe = true}; }; - arr[ITERATOR] = function(){ return iter; }; - exec(arr); - } catch(e){ /* empty */ } - return safe; -}; -},{"./$.wks":93}],69:[function(_dereq_,module,exports){ -module.exports = function(done, value){ - return {value: value, done: !!done}; -}; -},{}],70:[function(_dereq_,module,exports){ -module.exports = {}; -},{}],71:[function(_dereq_,module,exports){ -var $Object = Object; -module.exports = { - create: $Object.create, - getProto: $Object.getPrototypeOf, - isEnum: {}.propertyIsEnumerable, - getDesc: $Object.getOwnPropertyDescriptor, - setDesc: $Object.defineProperty, - setDescs: $Object.defineProperties, - getKeys: $Object.keys, - getNames: $Object.getOwnPropertyNames, - getSymbols: $Object.getOwnPropertySymbols, - each: [].forEach -}; -},{}],72:[function(_dereq_,module,exports){ -module.exports = true; -},{}],73:[function(_dereq_,module,exports){ -var global = _dereq_('./$.global') - , macrotask = _dereq_('./$.task').set - , Observer = global.MutationObserver || global.WebKitMutationObserver - , process = global.process - , Promise = global.Promise - , isNode = _dereq_('./$.cof')(process) == 'process' - , head, last, notify; - -var flush = function(){ - var parent, domain, fn; - if(isNode && (parent = process.domain)){ - process.domain = null; - parent.exit(); - } - while(head){ - domain = head.domain; - fn = head.fn; - if(domain)domain.enter(); - fn(); // <- currently we use it only for Promise - try / catch not required - if(domain)domain.exit(); - head = head.next; - } last = undefined; - if(parent)parent.enter(); -}; - -// Node.js -if(isNode){ - notify = function(){ - process.nextTick(flush); - }; -// browsers with MutationObserver -} else if(Observer){ - var toggle = 1 - , node = document.createTextNode(''); - new Observer(flush).observe(node, {characterData: true}); // eslint-disable-line no-new - notify = function(){ - node.data = toggle = -toggle; - }; -// environments with maybe non-completely correct, but existent Promise -} else if(Promise && Promise.resolve){ - notify = function(){ - Promise.resolve().then(flush); - }; -// for other environments - macrotask based on: -// - setImmediate -// - MessageChannel -// - window.postMessag -// - onreadystatechange -// - setTimeout -} else { - notify = function(){ - // strange IE + webpack dev server bug - use .call(global) - macrotask.call(global, flush); - }; -} - -module.exports = function asap(fn){ - var task = {fn: fn, next: undefined, domain: isNode && process.domain}; - if(last)last.next = task; - if(!head){ - head = task; - notify(); - } last = task; -}; -},{"./$.cof":45,"./$.global":57,"./$.task":87}],74:[function(_dereq_,module,exports){ -// 19.1.2.1 Object.assign(target, source, ...) -var $ = _dereq_('./$') - , toObject = _dereq_('./$.to-object') - , IObject = _dereq_('./$.iobject'); - -// should work with symbols and should have deterministic property order (V8 bug) -module.exports = _dereq_('./$.fails')(function(){ - var a = Object.assign - , A = {} - , B = {} - , S = Symbol() - , K = 'abcdefghijklmnopqrst'; - A[S] = 7; - K.split('').forEach(function(k){ B[k] = k; }); - return a({}, A)[S] != 7 || Object.keys(a({}, B)).join('') != K; -}) ? function assign(target, source){ // eslint-disable-line no-unused-vars - var T = toObject(target) - , $$ = arguments - , $$len = $$.length - , index = 1 - , getKeys = $.getKeys - , getSymbols = $.getSymbols - , isEnum = $.isEnum; - while($$len > index){ - var S = IObject($$[index++]) - , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) - , length = keys.length - , j = 0 - , key; - while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key]; - } - return T; -} : Object.assign; -},{"./$":71,"./$.fails":55,"./$.iobject":62,"./$.to-object":91}],75:[function(_dereq_,module,exports){ -// most Object methods by ES6 should accept primitives -var $export = _dereq_('./$.export') - , core = _dereq_('./$.core') - , fails = _dereq_('./$.fails'); -module.exports = function(KEY, exec){ - var fn = (core.Object || {})[KEY] || Object[KEY] - , exp = {}; - exp[KEY] = exec(fn); - $export($export.S + $export.F * fails(function(){ fn(1); }), 'Object', exp); -}; -},{"./$.core":49,"./$.export":54,"./$.fails":55}],76:[function(_dereq_,module,exports){ -module.exports = function(bitmap, value){ - return { - enumerable : !(bitmap & 1), - configurable: !(bitmap & 2), - writable : !(bitmap & 4), - value : value - }; -}; -},{}],77:[function(_dereq_,module,exports){ -var redefine = _dereq_('./$.redefine'); -module.exports = function(target, src){ - for(var key in src)redefine(target, key, src[key]); - return target; -}; -},{"./$.redefine":78}],78:[function(_dereq_,module,exports){ -module.exports = _dereq_('./$.hide'); -},{"./$.hide":59}],79:[function(_dereq_,module,exports){ -// 7.2.9 SameValue(x, y) -module.exports = Object.is || function is(x, y){ - return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y; -}; -},{}],80:[function(_dereq_,module,exports){ -// Works with __proto__ only. Old v8 can't work with null proto objects. -/* eslint-disable no-proto */ -var getDesc = _dereq_('./$').getDesc - , isObject = _dereq_('./$.is-object') - , anObject = _dereq_('./$.an-object'); -var check = function(O, proto){ - anObject(O); - if(!isObject(proto) && proto !== null)throw TypeError(proto + ": can't set as prototype!"); -}; -module.exports = { - set: Object.setPrototypeOf || ('__proto__' in {} ? // eslint-disable-line - function(test, buggy, set){ - try { - set = _dereq_('./$.ctx')(Function.call, getDesc(Object.prototype, '__proto__').set, 2); - set(test, []); - buggy = !(test instanceof Array); - } catch(e){ buggy = true; } - return function setPrototypeOf(O, proto){ - check(O, proto); - if(buggy)O.__proto__ = proto; - else set(O, proto); - return O; - }; - }({}, false) : undefined), - check: check -}; -},{"./$":71,"./$.an-object":43,"./$.ctx":50,"./$.is-object":64}],81:[function(_dereq_,module,exports){ -'use strict'; -var core = _dereq_('./$.core') - , $ = _dereq_('./$') - , DESCRIPTORS = _dereq_('./$.descriptors') - , SPECIES = _dereq_('./$.wks')('species'); - -module.exports = function(KEY){ - var C = core[KEY]; - if(DESCRIPTORS && C && !C[SPECIES])$.setDesc(C, SPECIES, { - configurable: true, - get: function(){ return this; } - }); -}; -},{"./$":71,"./$.core":49,"./$.descriptors":52,"./$.wks":93}],82:[function(_dereq_,module,exports){ -var def = _dereq_('./$').setDesc - , has = _dereq_('./$.has') - , TAG = _dereq_('./$.wks')('toStringTag'); - -module.exports = function(it, tag, stat){ - if(it && !has(it = stat ? it : it.prototype, TAG))def(it, TAG, {configurable: true, value: tag}); -}; -},{"./$":71,"./$.has":58,"./$.wks":93}],83:[function(_dereq_,module,exports){ -var global = _dereq_('./$.global') - , SHARED = '__core-js_shared__' - , store = global[SHARED] || (global[SHARED] = {}); -module.exports = function(key){ - return store[key] || (store[key] = {}); -}; -},{"./$.global":57}],84:[function(_dereq_,module,exports){ -// 7.3.20 SpeciesConstructor(O, defaultConstructor) -var anObject = _dereq_('./$.an-object') - , aFunction = _dereq_('./$.a-function') - , SPECIES = _dereq_('./$.wks')('species'); -module.exports = function(O, D){ - var C = anObject(O).constructor, S; - return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S); -}; -},{"./$.a-function":41,"./$.an-object":43,"./$.wks":93}],85:[function(_dereq_,module,exports){ -module.exports = function(it, Constructor, name){ - if(!(it instanceof Constructor))throw TypeError(name + ": use the 'new' operator!"); - return it; -}; -},{}],86:[function(_dereq_,module,exports){ -var toInteger = _dereq_('./$.to-integer') - , defined = _dereq_('./$.defined'); -// true -> String#at -// false -> String#codePointAt -module.exports = function(TO_STRING){ - return function(that, pos){ - var s = String(defined(that)) - , i = toInteger(pos) - , l = s.length - , a, b; - if(i < 0 || i >= l)return TO_STRING ? '' : undefined; - a = s.charCodeAt(i); - return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff - ? TO_STRING ? s.charAt(i) : a - : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000; - }; -}; -},{"./$.defined":51,"./$.to-integer":88}],87:[function(_dereq_,module,exports){ -var ctx = _dereq_('./$.ctx') - , invoke = _dereq_('./$.invoke') - , html = _dereq_('./$.html') - , cel = _dereq_('./$.dom-create') - , global = _dereq_('./$.global') - , process = global.process - , setTask = global.setImmediate - , clearTask = global.clearImmediate - , MessageChannel = global.MessageChannel - , counter = 0 - , queue = {} - , ONREADYSTATECHANGE = 'onreadystatechange' - , defer, channel, port; -var run = function(){ - var id = +this; - if(queue.hasOwnProperty(id)){ - var fn = queue[id]; - delete queue[id]; - fn(); - } -}; -var listner = function(event){ - run.call(event.data); -}; -// Node.js 0.9+ & IE10+ has setImmediate, otherwise: -if(!setTask || !clearTask){ - setTask = function setImmediate(fn){ - var args = [], i = 1; - while(arguments.length > i)args.push(arguments[i++]); - queue[++counter] = function(){ - invoke(typeof fn == 'function' ? fn : Function(fn), args); - }; - defer(counter); - return counter; - }; - clearTask = function clearImmediate(id){ - delete queue[id]; - }; - // Node.js 0.8- - if(_dereq_('./$.cof')(process) == 'process'){ - defer = function(id){ - process.nextTick(ctx(run, id, 1)); - }; - // Browsers with MessageChannel, includes WebWorkers - } else if(MessageChannel){ - channel = new MessageChannel; - port = channel.port2; - channel.port1.onmessage = listner; - defer = ctx(port.postMessage, port, 1); - // Browsers with postMessage, skip WebWorkers - // IE8 has postMessage, but it's sync & typeof its postMessage is 'object' - } else if(global.addEventListener && typeof postMessage == 'function' && !global.importScripts){ - defer = function(id){ - global.postMessage(id + '', '*'); - }; - global.addEventListener('message', listner, false); - // IE8- - } else if(ONREADYSTATECHANGE in cel('script')){ - defer = function(id){ - html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function(){ - html.removeChild(this); - run.call(id); - }; - }; - // Rest old browsers - } else { - defer = function(id){ - setTimeout(ctx(run, id, 1), 0); - }; - } -} -module.exports = { - set: setTask, - clear: clearTask -}; -},{"./$.cof":45,"./$.ctx":50,"./$.dom-create":53,"./$.global":57,"./$.html":60,"./$.invoke":61}],88:[function(_dereq_,module,exports){ -// 7.1.4 ToInteger -var ceil = Math.ceil - , floor = Math.floor; -module.exports = function(it){ - return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); -}; -},{}],89:[function(_dereq_,module,exports){ -// to indexed object, toObject with fallback for non-array-like ES3 strings -var IObject = _dereq_('./$.iobject') - , defined = _dereq_('./$.defined'); -module.exports = function(it){ - return IObject(defined(it)); -}; -},{"./$.defined":51,"./$.iobject":62}],90:[function(_dereq_,module,exports){ -// 7.1.15 ToLength -var toInteger = _dereq_('./$.to-integer') - , min = Math.min; -module.exports = function(it){ - return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 -}; -},{"./$.to-integer":88}],91:[function(_dereq_,module,exports){ -// 7.1.13 ToObject(argument) -var defined = _dereq_('./$.defined'); -module.exports = function(it){ - return Object(defined(it)); -}; -},{"./$.defined":51}],92:[function(_dereq_,module,exports){ -var id = 0 - , px = Math.random(); -module.exports = function(key){ - return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); -}; -},{}],93:[function(_dereq_,module,exports){ -var store = _dereq_('./$.shared')('wks') - , uid = _dereq_('./$.uid') - , Symbol = _dereq_('./$.global').Symbol; -module.exports = function(name){ - return store[name] || (store[name] = - Symbol && Symbol[name] || (Symbol || uid)('Symbol.' + name)); -}; -},{"./$.global":57,"./$.shared":83,"./$.uid":92}],94:[function(_dereq_,module,exports){ -var classof = _dereq_('./$.classof') - , ITERATOR = _dereq_('./$.wks')('iterator') - , Iterators = _dereq_('./$.iterators'); -module.exports = _dereq_('./$.core').getIteratorMethod = function(it){ - if(it != undefined)return it[ITERATOR] - || it['@@iterator'] - || Iterators[classof(it)]; -}; -},{"./$.classof":44,"./$.core":49,"./$.iterators":70,"./$.wks":93}],95:[function(_dereq_,module,exports){ -var anObject = _dereq_('./$.an-object') - , get = _dereq_('./core.get-iterator-method'); -module.exports = _dereq_('./$.core').getIterator = function(it){ - var iterFn = get(it); - if(typeof iterFn != 'function')throw TypeError(it + ' is not iterable!'); - return anObject(iterFn.call(it)); -}; -},{"./$.an-object":43,"./$.core":49,"./core.get-iterator-method":94}],96:[function(_dereq_,module,exports){ -'use strict'; -var addToUnscopables = _dereq_('./$.add-to-unscopables') - , step = _dereq_('./$.iter-step') - , Iterators = _dereq_('./$.iterators') - , toIObject = _dereq_('./$.to-iobject'); - -// 22.1.3.4 Array.prototype.entries() -// 22.1.3.13 Array.prototype.keys() -// 22.1.3.29 Array.prototype.values() -// 22.1.3.30 Array.prototype[@@iterator]() -module.exports = _dereq_('./$.iter-define')(Array, 'Array', function(iterated, kind){ - this._t = toIObject(iterated); // target - this._i = 0; // next index - this._k = kind; // kind -// 22.1.5.2.1 %ArrayIteratorPrototype%.next() -}, function(){ - var O = this._t - , kind = this._k - , index = this._i++; - if(!O || index >= O.length){ - this._t = undefined; - return step(1); - } - if(kind == 'keys' )return step(0, index); - if(kind == 'values')return step(0, O[index]); - return step(0, [index, O[index]]); -}, 'values'); - -// argumentsList[@@iterator] is %ArrayProto_values% (9.4.4.6, 9.4.4.7) -Iterators.Arguments = Iterators.Array; - -addToUnscopables('keys'); -addToUnscopables('values'); -addToUnscopables('entries'); -},{"./$.add-to-unscopables":42,"./$.iter-define":67,"./$.iter-step":69,"./$.iterators":70,"./$.to-iobject":89}],97:[function(_dereq_,module,exports){ -// 19.1.3.1 Object.assign(target, source) -var $export = _dereq_('./$.export'); - -$export($export.S + $export.F, 'Object', {assign: _dereq_('./$.object-assign')}); -},{"./$.export":54,"./$.object-assign":74}],98:[function(_dereq_,module,exports){ -// 19.1.2.6 Object.getOwnPropertyDescriptor(O, P) -var toIObject = _dereq_('./$.to-iobject'); - -_dereq_('./$.object-sap')('getOwnPropertyDescriptor', function($getOwnPropertyDescriptor){ - return function getOwnPropertyDescriptor(it, key){ - return $getOwnPropertyDescriptor(toIObject(it), key); - }; -}); -},{"./$.object-sap":75,"./$.to-iobject":89}],99:[function(_dereq_,module,exports){ -// 19.1.2.14 Object.keys(O) -var toObject = _dereq_('./$.to-object'); - -_dereq_('./$.object-sap')('keys', function($keys){ - return function keys(it){ - return $keys(toObject(it)); - }; -}); -},{"./$.object-sap":75,"./$.to-object":91}],100:[function(_dereq_,module,exports){ -// 19.1.3.19 Object.setPrototypeOf(O, proto) -var $export = _dereq_('./$.export'); -$export($export.S, 'Object', {setPrototypeOf: _dereq_('./$.set-proto').set}); -},{"./$.export":54,"./$.set-proto":80}],101:[function(_dereq_,module,exports){ - -},{}],102:[function(_dereq_,module,exports){ -'use strict'; -var $ = _dereq_('./$') - , LIBRARY = _dereq_('./$.library') - , global = _dereq_('./$.global') - , ctx = _dereq_('./$.ctx') - , classof = _dereq_('./$.classof') - , $export = _dereq_('./$.export') - , isObject = _dereq_('./$.is-object') - , anObject = _dereq_('./$.an-object') - , aFunction = _dereq_('./$.a-function') - , strictNew = _dereq_('./$.strict-new') - , forOf = _dereq_('./$.for-of') - , setProto = _dereq_('./$.set-proto').set - , same = _dereq_('./$.same-value') - , SPECIES = _dereq_('./$.wks')('species') - , speciesConstructor = _dereq_('./$.species-constructor') - , asap = _dereq_('./$.microtask') - , PROMISE = 'Promise' - , process = global.process - , isNode = classof(process) == 'process' - , P = global[PROMISE] - , empty = function(){ /* empty */ } - , Wrapper; - -var testResolve = function(sub){ - var test = new P(empty), promise; - if(sub)test.constructor = function(exec){ - exec(empty, empty); - }; - (promise = P.resolve(test))['catch'](empty); - return promise === test; -}; - -var USE_NATIVE = function(){ - var works = false; - function P2(x){ - var self = new P(x); - setProto(self, P2.prototype); - return self; - } - try { - works = P && P.resolve && testResolve(); - setProto(P2, P); - P2.prototype = $.create(P.prototype, {constructor: {value: P2}}); - // actual Firefox has broken subclass support, test that - if(!(P2.resolve(5).then(function(){}) instanceof P2)){ - works = false; - } - // actual V8 bug, https://code.google.com/p/v8/issues/detail?id=4162 - if(works && _dereq_('./$.descriptors')){ - var thenableThenGotten = false; - P.resolve($.setDesc({}, 'then', { - get: function(){ thenableThenGotten = true; } - })); - works = thenableThenGotten; - } - } catch(e){ works = false; } - return works; -}(); - -// helpers -var sameConstructor = function(a, b){ - // library wrapper special case - if(LIBRARY && a === P && b === Wrapper)return true; - return same(a, b); -}; -var getConstructor = function(C){ - var S = anObject(C)[SPECIES]; - return S != undefined ? S : C; -}; -var isThenable = function(it){ - var then; - return isObject(it) && typeof (then = it.then) == 'function' ? then : false; -}; -var PromiseCapability = function(C){ - var resolve, reject; - this.promise = new C(function($$resolve, $$reject){ - if(resolve !== undefined || reject !== undefined)throw TypeError('Bad Promise constructor'); - resolve = $$resolve; - reject = $$reject; - }); - this.resolve = aFunction(resolve), - this.reject = aFunction(reject) -}; -var perform = function(exec){ - try { - exec(); - } catch(e){ - return {error: e}; - } -}; -var notify = function(record, isReject){ - if(record.n)return; - record.n = true; - var chain = record.c; - asap(function(){ - var value = record.v - , ok = record.s == 1 - , i = 0; - var run = function(reaction){ - var handler = ok ? reaction.ok : reaction.fail - , resolve = reaction.resolve - , reject = reaction.reject - , result, then; - try { - if(handler){ - if(!ok)record.h = true; - result = handler === true ? value : handler(value); - if(result === reaction.promise){ - reject(TypeError('Promise-chain cycle')); - } else if(then = isThenable(result)){ - then.call(result, resolve, reject); - } else resolve(result); - } else reject(value); - } catch(e){ - reject(e); - } - }; - while(chain.length > i)run(chain[i++]); // variable length - can't use forEach - chain.length = 0; - record.n = false; - if(isReject)setTimeout(function(){ - var promise = record.p - , handler, console; - if(isUnhandled(promise)){ - if(isNode){ - process.emit('unhandledRejection', value, promise); - } else if(handler = global.onunhandledrejection){ - handler({promise: promise, reason: value}); - } else if((console = global.console) && console.error){ - console.error('Unhandled promise rejection', value); - } - } record.a = undefined; - }, 1); - }); -}; -var isUnhandled = function(promise){ - var record = promise._d - , chain = record.a || record.c - , i = 0 - , reaction; - if(record.h)return false; - while(chain.length > i){ - reaction = chain[i++]; - if(reaction.fail || !isUnhandled(reaction.promise))return false; - } return true; -}; -var $reject = function(value){ - var record = this; - if(record.d)return; - record.d = true; - record = record.r || record; // unwrap - record.v = value; - record.s = 2; - record.a = record.c.slice(); - notify(record, true); -}; -var $resolve = function(value){ - var record = this - , then; - if(record.d)return; - record.d = true; - record = record.r || record; // unwrap - try { - if(record.p === value)throw TypeError("Promise can't be resolved itself"); - if(then = isThenable(value)){ - asap(function(){ - var wrapper = {r: record, d: false}; // wrap - try { - then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1)); - } catch(e){ - $reject.call(wrapper, e); - } - }); - } else { - record.v = value; - record.s = 1; - notify(record, false); - } - } catch(e){ - $reject.call({r: record, d: false}, e); // wrap - } -}; - -// constructor polyfill -if(!USE_NATIVE){ - // 25.4.3.1 Promise(executor) - P = function Promise(executor){ - aFunction(executor); - var record = this._d = { - p: strictNew(this, P, PROMISE), // <- promise - c: [], // <- awaiting reactions - a: undefined, // <- checked in isUnhandled reactions - s: 0, // <- state - d: false, // <- done - v: undefined, // <- value - h: false, // <- handled rejection - n: false // <- notify - }; - try { - executor(ctx($resolve, record, 1), ctx($reject, record, 1)); - } catch(err){ - $reject.call(record, err); - } - }; - _dereq_('./$.redefine-all')(P.prototype, { - // 25.4.5.3 Promise.prototype.then(onFulfilled, onRejected) - then: function then(onFulfilled, onRejected){ - var reaction = new PromiseCapability(speciesConstructor(this, P)) - , promise = reaction.promise - , record = this._d; - reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true; - reaction.fail = typeof onRejected == 'function' && onRejected; - record.c.push(reaction); - if(record.a)record.a.push(reaction); - if(record.s)notify(record, false); - return promise; - }, - // 25.4.5.1 Promise.prototype.catch(onRejected) - 'catch': function(onRejected){ - return this.then(undefined, onRejected); - } - }); -} - -$export($export.G + $export.W + $export.F * !USE_NATIVE, {Promise: P}); -_dereq_('./$.set-to-string-tag')(P, PROMISE); -_dereq_('./$.set-species')(PROMISE); -Wrapper = _dereq_('./$.core')[PROMISE]; - -// statics -$export($export.S + $export.F * !USE_NATIVE, PROMISE, { - // 25.4.4.5 Promise.reject(r) - reject: function reject(r){ - var capability = new PromiseCapability(this) - , $$reject = capability.reject; - $$reject(r); - return capability.promise; - } -}); -$export($export.S + $export.F * (!USE_NATIVE || testResolve(true)), PROMISE, { - // 25.4.4.6 Promise.resolve(x) - resolve: function resolve(x){ - // instanceof instead of internal slot check because we should fix it without replacement native Promise core - if(x instanceof P && sameConstructor(x.constructor, this))return x; - var capability = new PromiseCapability(this) - , $$resolve = capability.resolve; - $$resolve(x); - return capability.promise; - } -}); -$export($export.S + $export.F * !(USE_NATIVE && _dereq_('./$.iter-detect')(function(iter){ - P.all(iter)['catch'](function(){}); -})), PROMISE, { - // 25.4.4.1 Promise.all(iterable) - all: function all(iterable){ - var C = getConstructor(this) - , capability = new PromiseCapability(C) - , resolve = capability.resolve - , reject = capability.reject - , values = []; - var abrupt = perform(function(){ - forOf(iterable, false, values.push, values); - var remaining = values.length - , results = Array(remaining); - if(remaining)$.each.call(values, function(promise, index){ - var alreadyCalled = false; - C.resolve(promise).then(function(value){ - if(alreadyCalled)return; - alreadyCalled = true; - results[index] = value; - --remaining || resolve(results); - }, reject); - }); - else resolve(results); - }); - if(abrupt)reject(abrupt.error); - return capability.promise; - }, - // 25.4.4.4 Promise.race(iterable) - race: function race(iterable){ - var C = getConstructor(this) - , capability = new PromiseCapability(C) - , reject = capability.reject; - var abrupt = perform(function(){ - forOf(iterable, false, function(promise){ - C.resolve(promise).then(capability.resolve, reject); - }); - }); - if(abrupt)reject(abrupt.error); - return capability.promise; - } -}); -},{"./$":71,"./$.a-function":41,"./$.an-object":43,"./$.classof":44,"./$.core":49,"./$.ctx":50,"./$.descriptors":52,"./$.export":54,"./$.for-of":56,"./$.global":57,"./$.is-object":64,"./$.iter-detect":68,"./$.library":72,"./$.microtask":73,"./$.redefine-all":77,"./$.same-value":79,"./$.set-proto":80,"./$.set-species":81,"./$.set-to-string-tag":82,"./$.species-constructor":84,"./$.strict-new":85,"./$.wks":93}],103:[function(_dereq_,module,exports){ -'use strict'; -var strong = _dereq_('./$.collection-strong'); - -// 23.2 Set Objects -_dereq_('./$.collection')('Set', function(get){ - return function Set(){ return get(this, arguments.length > 0 ? arguments[0] : undefined); }; -}, { - // 23.2.3.1 Set.prototype.add(value) - add: function add(value){ - return strong.def(this, value = value === 0 ? 0 : value, value); - } -}, strong); -},{"./$.collection":48,"./$.collection-strong":46}],104:[function(_dereq_,module,exports){ -'use strict'; -var $at = _dereq_('./$.string-at')(true); - -// 21.1.3.27 String.prototype[@@iterator]() -_dereq_('./$.iter-define')(String, 'String', function(iterated){ - this._t = String(iterated); // target - this._i = 0; // next index -// 21.1.5.2.1 %StringIteratorPrototype%.next() -}, function(){ - var O = this._t - , index = this._i - , point; - if(index >= O.length)return {value: undefined, done: true}; - point = $at(O, index); - this._i += point.length; - return {value: point, done: false}; -}); -},{"./$.iter-define":67,"./$.string-at":86}],105:[function(_dereq_,module,exports){ -// https://github.com/DavidBruant/Map-Set.prototype.toJSON -var $export = _dereq_('./$.export'); - -$export($export.P, 'Set', {toJSON: _dereq_('./$.collection-to-json')('Set')}); -},{"./$.collection-to-json":47,"./$.export":54}],106:[function(_dereq_,module,exports){ -_dereq_('./es6.array.iterator'); -var Iterators = _dereq_('./$.iterators'); -Iterators.NodeList = Iterators.HTMLCollection = Iterators.Array; -},{"./$.iterators":70,"./es6.array.iterator":96}],107:[function(_dereq_,module,exports){ -;(function(root) { - /** - * Constructs a new cross storage client given the url to a hub. By default, - * an iframe is created within the document body that points to the url. It - * also accepts an options object, which may include a timeout, frameId, and - * promise. The timeout, in milliseconds, is applied to each request and - * defaults to 5000ms. The options object may also include a frameId, - * identifying an existing frame on which to install its listeners. If the - * promise key is supplied the constructor for a Promise, that Promise library - * will be used instead of the default window.Promise. - * - * @example - * var storage = new CrossStorageClient('https://store.example.com/hub.html'); - * - * @example - * var storage = new CrossStorageClient('https://store.example.com/hub.html', { - * timeout: 5000, - * frameId: 'storageFrame' - * }); - * - * @constructor - * - * @param {string} url The url to a cross storage hub - * @param {object} [opts] An optional object containing additional options, - * including timeout, frameId, and promise - * - * @property {string} _id A UUID v4 id - * @property {function} _promise The Promise object to use - * @property {string} _frameId The id of the iFrame pointing to the hub url - * @property {string} _origin The hub's origin - * @property {object} _requests Mapping of request ids to callbacks - * @property {bool} _connected Whether or not it has connected - * @property {bool} _closed Whether or not the client has closed - * @property {int} _count Number of requests sent - * @property {function} _listener The listener added to the window - * @property {Window} _hub The hub window - */ - function CrossStorageClient(url, opts) { - opts = opts || {}; - - this._id = CrossStorageClient._generateUUID(); - this._promise = opts.promise || Promise; - this._frameId = opts.frameId || 'CrossStorageClient-' + this._id; - this._origin = CrossStorageClient._getOrigin(url); - this._requests = {}; - this._connected = false; - this._closed = false; - this._count = 0; - this._timeout = opts.timeout || 5000; - this._listener = null; - - this._installListener(); - - var frame; - if (opts.frameId) { - frame = document.getElementById(opts.frameId); - } - - // If using a passed iframe, poll the hub for a ready message - if (frame) { - this._poll(); - } - - // Create the frame if not found or specified - frame = frame || this._createFrame(url); - this._hub = frame.contentWindow; - } - - /** - * The styles to be applied to the generated iFrame. Defines a set of properties - * that hide the element by positioning it outside of the visible area, and - * by modifying its display. - * - * @member {Object} - */ - CrossStorageClient.frameStyle = { - display: 'none', - position: 'absolute', - top: '-999px', - left: '-999px' - }; - - /** - * Returns the origin of an url, with cross browser support. Accommodates - * the lack of location.origin in IE, as well as the discrepancies in the - * inclusion of the port when using the default port for a protocol, e.g. - * 443 over https. Defaults to the origin of window.location if passed a - * relative path. - * - * @param {string} url The url to a cross storage hub - * @returns {string} The origin of the url - */ - CrossStorageClient._getOrigin = function(url) { - var uri, protocol, origin; - - uri = document.createElement('a'); - uri.href = url; - - if (!uri.host) { - uri = window.location; - } - - if (!uri.protocol || uri.protocol === ':') { - protocol = window.location.protocol; - } else { - protocol = uri.protocol; - } - - origin = protocol + '//' + uri.host; - origin = origin.replace(/:80$|:443$/, ''); - - return origin; - }; - - /** - * UUID v4 generation, taken from: http://stackoverflow.com/questions/ - * 105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 - * - * @returns {string} A UUID v4 string - */ - CrossStorageClient._generateUUID = function() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = Math.random() * 16|0, v = c == 'x' ? r : (r&0x3|0x8); - - return v.toString(16); - }); - }; - - /** - * Returns a promise that is fulfilled when a connection has been established - * with the cross storage hub. Its use is required to avoid sending any - * requests prior to initialization being complete. - * - * @returns {Promise} A promise that is resolved on connect - */ - CrossStorageClient.prototype.onConnect = function() { - var client = this; - - if (this._connected) { - return this._promise.resolve(); - } else if (this._closed) { - return this._promise.reject(new Error('CrossStorageClient has closed')); - } - - // Queue connect requests for client re-use - if (!this._requests.connect) { - this._requests.connect = []; - } - - return new this._promise(function(resolve, reject) { - var timeout = setTimeout(function() { - reject(new Error('CrossStorageClient could not connect')); - }, client._timeout); - - client._requests.connect.push(function(err) { - clearTimeout(timeout); - if (err) return reject(err); - - resolve(); - }); - }); - }; - - /** - * Sets a key to the specified value. Returns a promise that is fulfilled on - * success, or rejected if any errors setting the key occurred, or the request - * timed out. - * - * @param {string} key The key to set - * @param {*} value The value to assign - * @returns {Promise} A promise that is settled on hub response or timeout - */ - CrossStorageClient.prototype.set = function(key, value) { - return this._request('set', { - key: key, - value: value - }); - }; - - /** - * Accepts one or more keys for which to retrieve their values. Returns a - * promise that is settled on hub response or timeout. On success, it is - * fulfilled with the value of the key if only passed a single argument. - * Otherwise it's resolved with an array of values. On failure, it is rejected - * with the corresponding error message. - * - * @param {...string} key The key to retrieve - * @returns {Promise} A promise that is settled on hub response or timeout - */ - CrossStorageClient.prototype.get = function(key) { - var args = Array.prototype.slice.call(arguments); - - return this._request('get', {keys: args}); - }; - - /** - * Accepts one or more keys for deletion. Returns a promise that is settled on - * hub response or timeout. - * - * @param {...string} key The key to delete - * @returns {Promise} A promise that is settled on hub response or timeout - */ - CrossStorageClient.prototype.del = function() { - var args = Array.prototype.slice.call(arguments); - - return this._request('del', {keys: args}); - }; - - /** - * Returns a promise that, when resolved, indicates that all localStorage - * data has been cleared. - * - * @returns {Promise} A promise that is settled on hub response or timeout - */ - CrossStorageClient.prototype.clear = function() { - return this._request('clear'); - }; - - /** - * Returns a promise that, when resolved, passes an array of all keys - * currently in storage. - * - * @returns {Promise} A promise that is settled on hub response or timeout - */ - CrossStorageClient.prototype.getKeys = function() { - return this._request('getKeys'); - }; - - /** - * Deletes the iframe and sets the connected state to false. The client can - * no longer be used after being invoked. - */ - CrossStorageClient.prototype.close = function() { - var frame = document.getElementById(this._frameId); - if (frame) { - frame.parentNode.removeChild(frame); - } - - // Support IE8 with detachEvent - if (window.removeEventListener) { - window.removeEventListener('message', this._listener, false); - } else { - window.detachEvent('onmessage', this._listener); - } - - this._connected = false; - this._closed = true; - }; - - /** - * Installs the necessary listener for the window message event. When a message - * is received, the client's _connected status is changed to true, and the - * onConnect promise is fulfilled. Given a response message, the callback - * corresponding to its request is invoked. If response.error holds a truthy - * value, the promise associated with the original request is rejected with - * the error. Otherwise the promise is fulfilled and passed response.result. - * - * @private - */ - CrossStorageClient.prototype._installListener = function() { - var client = this; - - this._listener = function(message) { - var i, origin, error, response; - - // Ignore invalid messages or those after the client has closed - if (client._closed || !message.data || typeof message.data !== 'string') { - return; - } - - // postMessage returns the string "null" as the origin for "file://" - origin = (message.origin === 'null') ? 'file://' : message.origin; - - // Ignore messages not from the correct origin - if (origin !== client._origin) return; - - // LocalStorage isn't available in the hub - if (message.data === 'cross-storage:unavailable') { - if (!client._closed) client.close(); - if (!client._requests.connect) return; - - error = new Error('Closing client. Could not access localStorage in hub.'); - for (i = 0; i < client._requests.connect.length; i++) { - client._requests.connect[i](error); - } - - return; - } - - // Handle initial connection - if (message.data.indexOf('cross-storage:') !== -1 && !client._connected) { - client._connected = true; - if (!client._requests.connect) return; - - for (i = 0; i < client._requests.connect.length; i++) { - client._requests.connect[i](error); - } - delete client._requests.connect; - } - - if (message.data === 'cross-storage:ready') return; - - // All other messages - try { - response = JSON.parse(message.data); - } catch(e) { - return; - } - - if (!response.id) return; - - if (client._requests[response.id]) { - client._requests[response.id](response.error, response.result); - } - }; - - // Support IE8 with attachEvent - if (window.addEventListener) { - window.addEventListener('message', this._listener, false); - } else { - window.attachEvent('onmessage', this._listener); - } - }; - - /** - * Invoked when a frame id was passed to the client, rather than allowing - * the client to create its own iframe. Polls the hub for a ready event to - * establish a connected state. - */ - CrossStorageClient.prototype._poll = function() { - var client, interval, targetOrigin; - - client = this; - - // postMessage requires that the target origin be set to "*" for "file://" - targetOrigin = (client._origin === 'file://') ? '*' : client._origin; - - interval = setInterval(function() { - if (client._connected) return clearInterval(interval); - if (!client._hub) return; - - client._hub.postMessage('cross-storage:poll', targetOrigin); - }, 1000); - }; - - /** - * Creates a new iFrame containing the hub. Applies the necessary styles to - * hide the element from view, prior to adding it to the document body. - * Returns the created element. - * - * @private - * - * @param {string} url The url to the hub - * returns {HTMLIFrameElement} The iFrame element itself - */ - CrossStorageClient.prototype._createFrame = function(url) { - var frame, key; - - frame = window.document.createElement('iframe'); - frame.id = this._frameId; - - // Style the iframe - for (key in CrossStorageClient.frameStyle) { - if (CrossStorageClient.frameStyle.hasOwnProperty(key)) { - frame.style[key] = CrossStorageClient.frameStyle[key]; - } - } - - window.document.body.appendChild(frame); - frame.src = url; - - return frame; - }; - - /** - * Sends a message containing the given method and params to the hub. Stores - * a callback in the _requests object for later invocation on message, or - * deletion on timeout. Returns a promise that is settled in either instance. - * - * @private - * - * @param {string} method The method to invoke - * @param {*} params The arguments to pass - * @returns {Promise} A promise that is settled on hub response or timeout - */ - CrossStorageClient.prototype._request = function(method, params) { - var req, client; - - if (this._closed) { - return this._promise.reject(new Error('CrossStorageClient has closed')); - } - - client = this; - client._count++; - - req = { - id: this._id + ':' + client._count, - method: 'cross-storage:' + method, - params: params - }; - - return new this._promise(function(resolve, reject) { - var timeout, originalToJSON, targetOrigin; - - // Timeout if a response isn't received after 4s - timeout = setTimeout(function() { - if (!client._requests[req.id]) return; - - delete client._requests[req.id]; - reject(new Error('Timeout: could not perform ' + req.method)); - }, client._timeout); - - // Add request callback - client._requests[req.id] = function(err, result) { - clearTimeout(timeout); - delete client._requests[req.id]; - if (err) return reject(new Error(err)); - resolve(result); - }; - - // In case we have a broken Array.prototype.toJSON, e.g. because of - // old versions of prototype - if (Array.prototype.toJSON) { - originalToJSON = Array.prototype.toJSON; - Array.prototype.toJSON = null; - } - - // postMessage requires that the target origin be set to "*" for "file://" - targetOrigin = (client._origin === 'file://') ? '*' : client._origin; - - // Send serialized message - client._hub.postMessage(JSON.stringify(req), targetOrigin); - - // Restore original toJSON - if (originalToJSON) { - Array.prototype.toJSON = originalToJSON; - } - }); - }; - - /** - * Export for various environments. - */ - if (typeof module !== 'undefined' && module.exports) { - module.exports = CrossStorageClient; - } else if (typeof exports !== 'undefined') { - exports.CrossStorageClient = CrossStorageClient; - } else if (typeof define === 'function' && define.amd) { - define([], function() { - return CrossStorageClient; - }); - } else { - root.CrossStorageClient = CrossStorageClient; - } -}(this)); - -},{}],108:[function(_dereq_,module,exports){ -;(function(root) { - var CrossStorageHub = {}; - - /** - * Accepts an array of objects with two keys: origin and allow. The value - * of origin is expected to be a RegExp, and allow, an array of strings. - * The cross storage hub is then initialized to accept requests from any of - * the matching origins, allowing access to the associated lists of methods. - * Methods may include any of: get, set, del, getKeys and clear. A 'ready' - * message is sent to the parent window once complete. - * - * @example - * // Subdomain can get, but only root domain can set and del - * CrossStorageHub.init([ - * {origin: /\.example.com$/, allow: ['get']}, - * {origin: /:(www\.)?example.com$/, allow: ['get', 'set', 'del']} - * ]); - * - * @param {array} permissions An array of objects with origin and allow - */ - CrossStorageHub.init = function(permissions) { - var available = true; - - // Return if localStorage is unavailable, or third party - // access is disabled - try { - if (!window.localStorage) available = false; - } catch (e) { - available = false; - } - - if (!available) { - try { - return window.parent.postMessage('cross-storage:unavailable', '*'); - } catch (e) { - return; - } - } - - CrossStorageHub._permissions = permissions || []; - CrossStorageHub._installListener(); - window.parent.postMessage('cross-storage:ready', '*'); - }; - - /** - * Installs the necessary listener for the window message event. Accommodates - * IE8 and up. - * - * @private - */ - CrossStorageHub._installListener = function() { - var listener = CrossStorageHub._listener; - if (window.addEventListener) { - window.addEventListener('message', listener, false); - } else { - window.attachEvent('onmessage', listener); - } - }; - - /** - * The message handler for all requests posted to the window. It ignores any - * messages having an origin that does not match the originally supplied - * pattern. Given a JSON object with one of get, set, del or getKeys as the - * method, the function performs the requested action and returns its result. - * - * @param {MessageEvent} message A message to be processed - */ - CrossStorageHub._listener = function(message) { - var origin, targetOrigin, request, method, error, result, response; - - // postMessage returns the string "null" as the origin for "file://" - origin = (message.origin === 'null') ? 'file://' : message.origin; - - // Handle polling for a ready message - if (message.data === 'cross-storage:poll') { - return window.parent.postMessage('cross-storage:ready', message.origin); - } - - // Ignore the ready message when viewing the hub directly - if (message.data === 'cross-storage:ready') return; - - // Check whether message.data is a valid json - try { - request = JSON.parse(message.data); - } catch (err) { - return; - } - - // Check whether request.method is a string - if (!request || typeof request.method !== 'string') { - return; - } - - method = request.method.split('cross-storage:')[1]; - - if (!method) { - return; - } else if (!CrossStorageHub._permitted(origin, method)) { - error = 'Invalid permissions for ' + method; - } else { - try { - result = CrossStorageHub['_' + method](request.params); - } catch (err) { - error = err.message; - } - } - - response = JSON.stringify({ - id: request.id, - error: error, - result: result - }); - - // postMessage requires that the target origin be set to "*" for "file://" - targetOrigin = (origin === 'file://') ? '*' : origin; - - window.parent.postMessage(response, targetOrigin); - }; - - /** - * Returns a boolean indicating whether or not the requested method is - * permitted for the given origin. The argument passed to method is expected - * to be one of 'get', 'set', 'del' or 'getKeys'. - * - * @param {string} origin The origin for which to determine permissions - * @param {string} method Requested action - * @returns {bool} Whether or not the request is permitted - */ - CrossStorageHub._permitted = function(origin, method) { - var available, i, entry, match; - - available = ['get', 'set', 'del', 'clear', 'getKeys']; - if (!CrossStorageHub._inArray(method, available)) { - return false; - } - - for (i = 0; i < CrossStorageHub._permissions.length; i++) { - entry = CrossStorageHub._permissions[i]; - if (!(entry.origin instanceof RegExp) || !(entry.allow instanceof Array)) { - continue; - } - - match = entry.origin.test(origin); - if (match && CrossStorageHub._inArray(method, entry.allow)) { - return true; - } - } - - return false; - }; - - /** - * Sets a key to the specified value. - * - * @param {object} params An object with key and value - */ - CrossStorageHub._set = function(params) { - window.localStorage.setItem(params.key, params.value); - }; - - /** - * Accepts an object with an array of keys for which to retrieve their values. - * Returns a single value if only one key was supplied, otherwise it returns - * an array. Any keys not set result in a null element in the resulting array. - * - * @param {object} params An object with an array of keys - * @returns {*|*[]} Either a single value, or an array - */ - CrossStorageHub._get = function(params) { - var storage, result, i, value; - - storage = window.localStorage; - result = []; - - for (i = 0; i < params.keys.length; i++) { - try { - value = storage.getItem(params.keys[i]); - } catch (e) { - value = null; - } - - result.push(value); - } - - return (result.length > 1) ? result : result[0]; - }; - - /** - * Deletes all keys specified in the array found at params.keys. - * - * @param {object} params An object with an array of keys - */ - CrossStorageHub._del = function(params) { - for (var i = 0; i < params.keys.length; i++) { - window.localStorage.removeItem(params.keys[i]); - } - }; - - /** - * Clears localStorage. - */ - CrossStorageHub._clear = function() { - window.localStorage.clear(); - }; - - /** - * Returns an array of all keys stored in localStorage. - * - * @returns {string[]} The array of keys - */ - CrossStorageHub._getKeys = function(params) { - var i, length, keys; - - keys = []; - length = window.localStorage.length; - - for (i = 0; i < length; i++) { - keys.push(window.localStorage.key(i)); - } - - return keys; - }; - - /** - * Returns whether or not a value is present in the array. Consists of an - * alternative to extending the array prototype for indexOf, since it's - * unavailable for IE8. - * - * @param {*} value The value to find - * @parma {[]*} array The array in which to search - * @returns {bool} Whether or not the value was found - */ - CrossStorageHub._inArray = function(value, array) { - for (var i = 0; i < array.length; i++) { - if (value === array[i]) return true; - } - - return false; - }; - - /** - * A cross-browser version of Date.now compatible with IE8 that avoids - * modifying the Date object. - * - * @return {int} The current timestamp in milliseconds - */ - CrossStorageHub._now = function() { - if (typeof Date.now === 'function') { - return Date.now(); - } - - return new Date().getTime(); - }; - - /** - * Export for various environments. - */ - if (typeof module !== 'undefined' && module.exports) { - module.exports = CrossStorageHub; - } else if (typeof exports !== 'undefined') { - exports.CrossStorageHub = CrossStorageHub; - } else if (typeof define === 'function' && define.amd) { - define([], function() { - return CrossStorageHub; - }); - } else { - root.CrossStorageHub = CrossStorageHub; - } -}(this)); - -},{}],109:[function(_dereq_,module,exports){ -module.exports = { - CrossStorageClient: _dereq_('./client.js'), - CrossStorageHub: _dereq_('./hub.js') -}; - -},{"./client.js":107,"./hub.js":108}],110:[function(_dereq_,module,exports){ -/*! (C) Andrea Giammarchi - @WebReflection - ISC Style License */ -(function(window,polyfill){"use strict";var document=window.document,Object=window.Object;var htmlClass=function(info){var catchClass=/^[A-Z]+[a-z]/,filterBy=function(re){var arr=[],tag;for(tag in register){if(re.test(tag))arr.push(tag)}return arr},add=function(Class,tag){tag=tag.toLowerCase();if(!(tag in register)){register[Class]=(register[Class]||[]).concat(tag);register[tag]=register[tag.toUpperCase()]=Class}},register=(Object.create||Object)(null),htmlClass={},i,section,tags,Class;for(section in info){for(Class in info[section]){tags=info[section][Class];register[Class]=tags;for(i=0;i>0),ADD_EVENT_LISTENER="addEventListener",ATTACHED="attached",CALLBACK="Callback",DETACHED="detached",EXTENDS="extends",ATTRIBUTE_CHANGED_CALLBACK="attributeChanged"+CALLBACK,ATTACHED_CALLBACK=ATTACHED+CALLBACK,CONNECTED_CALLBACK="connected"+CALLBACK,DISCONNECTED_CALLBACK="disconnected"+CALLBACK,CREATED_CALLBACK="created"+CALLBACK,DETACHED_CALLBACK=DETACHED+CALLBACK,ADDITION="ADDITION",MODIFICATION="MODIFICATION",REMOVAL="REMOVAL",DOM_ATTR_MODIFIED="DOMAttrModified",DOM_CONTENT_LOADED="DOMContentLoaded",DOM_SUBTREE_MODIFIED="DOMSubtreeModified",PREFIX_TAG="<",PREFIX_IS="=",validName=/^[A-Z][A-Z0-9]*(?:-[A-Z0-9]+)+$/,invalidNames=["ANNOTATION-XML","COLOR-PROFILE","FONT-FACE","FONT-FACE-SRC","FONT-FACE-URI","FONT-FACE-FORMAT","FONT-FACE-NAME","MISSING-GLYPH"],types=[],protos=[],query="",documentElement=document.documentElement,indexOf=types.indexOf||function(v){for(var i=this.length;i--&&this[i]!==v;){}return i},OP=Object.prototype,hOP=OP.hasOwnProperty,iPO=OP.isPrototypeOf,defineProperty=Object.defineProperty,empty=[],gOPD=Object.getOwnPropertyDescriptor,gOPN=Object.getOwnPropertyNames,gPO=Object.getPrototypeOf,sPO=Object.setPrototypeOf,hasProto=!!Object.__proto__,fixGetClass=false,DRECEV1="__dreCEv1",customElements=window.customElements,usableCustomElements=!/^force/.test(polyfill.type)&&!!(customElements&&customElements.define&&customElements.get&&customElements.whenDefined),Dict=Object.create||Object,Map=window.Map||function Map(){var K=[],V=[],i;return{get:function(k){return V[indexOf.call(K,k)]},set:function(k,v){i=indexOf.call(K,k);if(i<0)V[K.push(k)-1]=v;else V[i]=v}}},Promise=window.Promise||function(fn){var notify=[],done=false,p={catch:function(){return p},then:function(cb){notify.push(cb);if(done)setTimeout(resolve,1);return p}};function resolve(value){done=true;while(notify.length)notify.shift()(value)}fn(resolve);return p},justCreated=false,constructors=Dict(null),waitingList=Dict(null),nodeNames=new Map,secondArgument=function(is){return is.toLowerCase()},create=Object.create||function Bridge(proto){return proto?(Bridge.prototype=proto,new Bridge):this},setPrototype=sPO||(hasProto?function(o,p){o.__proto__=p;return o}:gOPN&&gOPD?function(){function setProperties(o,p){for(var key,names=gOPN(p),i=0,length=names.length;i
";new MutationObserver(function(mutations,observer){if(mutations[0]&&mutations[0].type=="childList"&&!mutations[0].removedNodes[0].childNodes.length){tmp=gOPD(HTMLElementPrototype,"innerHTML");var set=tmp&&tmp.set;if(set)defineProperty(HTMLElementPrototype,"innerHTML",{set:function(value){while(this.lastChild)this.removeChild(this.lastChild);set.call(this,value)}})}observer.disconnect();tmp=null}).observe(tmp,{childList:true,subtree:true});tmp.innerHTML=""}if(!V0){if(sPO||hasProto){patchIfNotAlready=function(node,proto){if(!iPO.call(proto,node)){setupNode(node,proto)}};patch=setupNode}else{patchIfNotAlready=function(node,proto){if(!node[EXPANDO_UID]){node[EXPANDO_UID]=Object(true);setupNode(node,proto)}};patch=patchIfNotAlready}if(IE8){doesNotSupportDOMAttrModified=false;(function(){var descriptor=gOPD(HTMLElementPrototype,ADD_EVENT_LISTENER),addEventListener=descriptor.value,patchedRemoveAttribute=function(name){var e=new CustomEvent(DOM_ATTR_MODIFIED,{bubbles:true});e.attrName=name;e.prevValue=getAttribute.call(this,name);e.newValue=null;e[REMOVAL]=e.attrChange=2;removeAttribute.call(this,name);dispatchEvent.call(this,e)},patchedSetAttribute=function(name,value){var had=hasAttribute.call(this,name),old=had&&getAttribute.call(this,name),e=new CustomEvent(DOM_ATTR_MODIFIED,{bubbles:true});setAttribute.call(this,name,value);e.attrName=name;e.prevValue=had?old:null;e.newValue=value;if(had){e[MODIFICATION]=e.attrChange=1}else{e[ADDITION]=e.attrChange=0}dispatchEvent.call(this,e)},onPropertyChange=function(e){var node=e.currentTarget,superSecret=node[EXPANDO_UID],propertyName=e.propertyName,event;if(superSecret.hasOwnProperty(propertyName)){superSecret=superSecret[propertyName];event=new CustomEvent(DOM_ATTR_MODIFIED,{bubbles:true});event.attrName=superSecret.name;event.prevValue=superSecret.value||null;event.newValue=superSecret.value=node[propertyName]||null;if(event.prevValue==null){event[ADDITION]=event.attrChange=0}else{event[MODIFICATION]=event.attrChange=1}dispatchEvent.call(node,event)}};descriptor.value=function(type,handler,capture){if(type===DOM_ATTR_MODIFIED&&this[ATTRIBUTE_CHANGED_CALLBACK]&&this.setAttribute!==patchedSetAttribute){this[EXPANDO_UID]={className:{name:"class",value:this.className}};this.setAttribute=patchedSetAttribute;this.removeAttribute=patchedRemoveAttribute;addEventListener.call(this,"propertychange",onPropertyChange)}addEventListener.call(this,type,handler,capture)};defineProperty(HTMLElementPrototype,ADD_EVENT_LISTENER,descriptor)})()}else if(!MutationObserver){documentElement[ADD_EVENT_LISTENER](DOM_ATTR_MODIFIED,DOMAttrModified);documentElement.setAttribute(EXPANDO_UID,1);documentElement.removeAttribute(EXPANDO_UID);if(doesNotSupportDOMAttrModified){onSubtreeModified=function(e){var node=this,oldAttributes,newAttributes,key;if(node===e.target){oldAttributes=node[EXPANDO_UID];node[EXPANDO_UID]=newAttributes=getAttributesMirror(node);for(key in newAttributes){if(!(key in oldAttributes)){return callDOMAttrModified(0,node,key,oldAttributes[key],newAttributes[key],ADDITION)}else if(newAttributes[key]!==oldAttributes[key]){return callDOMAttrModified(1,node,key,oldAttributes[key],newAttributes[key],MODIFICATION)}}for(key in oldAttributes){if(!(key in newAttributes)){return callDOMAttrModified(2,node,key,oldAttributes[key],newAttributes[key],REMOVAL)}}}};callDOMAttrModified=function(attrChange,currentTarget,attrName,prevValue,newValue,action){var e={attrChange:attrChange,currentTarget:currentTarget,attrName:attrName,prevValue:prevValue,newValue:newValue};e[action]=attrChange;onDOMAttrModified(e)};getAttributesMirror=function(node){for(var attr,name,result={},attributes=node.attributes,i=0,length=attributes.length;i1){notifyAttributes(this)}}}});safeProperty(proto,ATTRIBUTE_CHANGED_CALLBACK,{value:function(name){if(-1$");options[EXTENDS]="a";DRE.prototype=create(HTMLAnchorElement.prototype);DRE.prototype.constructor=DRE;window.customElements.define(name,DRE,options);if(!re.test(document.createElement("a",{is:name}).outerHTML)||!re.test((new DRE).outerHTML)){throw options}})(function DRE(){return Reflect.construct(HTMLAnchorElement,[],DRE)},{},"document-register-element-a")}catch(o_O){polyfillV1()}}if(!polyfill.noBuiltIn){try{createElement.call(document,"a","a")}catch(FireFox){secondArgument=function(is){return{is:is.toLowerCase()}}}}})(window); - -},{}],111:[function(_dereq_,module,exports){ -'use strict'; - -var isCallable = _dereq_('is-callable'); - -var toStr = Object.prototype.toString; -var hasOwnProperty = Object.prototype.hasOwnProperty; - -var forEachArray = function forEachArray(array, iterator, receiver) { - for (var i = 0, len = array.length; i < len; i++) { - if (hasOwnProperty.call(array, i)) { - if (receiver == null) { - iterator(array[i], i, array); - } else { - iterator.call(receiver, array[i], i, array); - } - } - } -}; - -var forEachString = function forEachString(string, iterator, receiver) { - for (var i = 0, len = string.length; i < len; i++) { - // no such thing as a sparse string. - if (receiver == null) { - iterator(string.charAt(i), i, string); - } else { - iterator.call(receiver, string.charAt(i), i, string); - } - } -}; - -var forEachObject = function forEachObject(object, iterator, receiver) { - for (var k in object) { - if (hasOwnProperty.call(object, k)) { - if (receiver == null) { - iterator(object[k], k, object); - } else { - iterator.call(receiver, object[k], k, object); - } - } - } -}; - -var forEach = function forEach(list, iterator, thisArg) { - if (!isCallable(iterator)) { - throw new TypeError('iterator must be a function'); - } - - var receiver; - if (arguments.length >= 3) { - receiver = thisArg; - } - - if (toStr.call(list) === '[object Array]') { - forEachArray(list, iterator, receiver); - } else if (typeof list === 'string') { - forEachString(list, iterator, receiver); - } else { - forEachObject(list, iterator, receiver); - } -}; - -module.exports = forEach; - -},{"is-callable":114}],112:[function(_dereq_,module,exports){ -(function (global){ -var win; - -if (typeof window !== "undefined") { - win = window; -} else if (typeof global !== "undefined") { - win = global; -} else if (typeof self !== "undefined"){ - win = self; -} else { - win = {}; -} - -module.exports = win; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) - -},{}],113:[function(_dereq_,module,exports){ -(function (global){ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.GlslCanvas = factory()); -}(this, (function () { 'use strict'; - -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - - - - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var win; - -if (typeof window !== "undefined") { - win = window; -} else if (typeof commonjsGlobal !== "undefined") { - win = commonjsGlobal; -} else if (typeof self !== "undefined"){ - win = self; -} else { - win = {}; -} - -var window_1 = win; - -var isFunction_1 = isFunction; - -var toString = Object.prototype.toString; - -function isFunction (fn) { - var string = toString.call(fn); - return string === '[object Function]' || - (typeof fn === 'function' && string !== '[object RegExp]') || - (typeof window !== 'undefined' && - // IE8 and below - (fn === window.setTimeout || - fn === window.alert || - fn === window.confirm || - fn === window.prompt)) -} - -var trim_1 = createCommonjsModule(function (module, exports) { -exports = module.exports = trim; - -function trim(str){ - return str.replace(/^\s*|\s*$/g, ''); -} - -exports.left = function(str){ - return str.replace(/^\s*/, ''); -}; - -exports.right = function(str){ - return str.replace(/\s*$/, ''); -}; -}); - -var forEach_1 = forEach; - -var toString$1 = Object.prototype.toString; -var hasOwnProperty = Object.prototype.hasOwnProperty; - -function forEach(list, iterator, context) { - if (!isFunction_1(iterator)) { - throw new TypeError('iterator must be a function') - } - - if (arguments.length < 3) { - context = this; - } - - if (toString$1.call(list) === '[object Array]') - forEachArray$1(list, iterator, context); - else if (typeof list === 'string') - forEachString(list, iterator, context); - else - forEachObject(list, iterator, context); -} - -function forEachArray$1(array, iterator, context) { - for (var i = 0, len = array.length; i < len; i++) { - if (hasOwnProperty.call(array, i)) { - iterator.call(context, array[i], i, array); - } - } -} - -function forEachString(string, iterator, context) { - for (var i = 0, len = string.length; i < len; i++) { - // no such thing as a sparse string. - iterator.call(context, string.charAt(i), i, string); - } -} - -function forEachObject(object, iterator, context) { - for (var k in object) { - if (hasOwnProperty.call(object, k)) { - iterator.call(context, object[k], k, object); - } - } -} - -var isArray = function(arg) { - return Object.prototype.toString.call(arg) === '[object Array]'; - }; - -var parseHeaders = function (headers) { - if (!headers) - return {} - - var result = {}; - - forEach_1( - trim_1(headers).split('\n') - , function (row) { - var index = row.indexOf(':') - , key = trim_1(row.slice(0, index)).toLowerCase() - , value = trim_1(row.slice(index + 1)); - - if (typeof(result[key]) === 'undefined') { - result[key] = value; - } else if (isArray(result[key])) { - result[key].push(value); - } else { - result[key] = [ result[key], value ]; - } - } - ); - - return result -}; - -var immutable = extend; - -var hasOwnProperty$1 = Object.prototype.hasOwnProperty; - -function extend() { - var target = {}; - - for (var i = 0; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (hasOwnProperty$1.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target -} - -"use strict"; - - - - - -var xhr = createXHR; -// Allow use of default import syntax in TypeScript -var default_1 = createXHR; -createXHR.XMLHttpRequest = window_1.XMLHttpRequest || noop; -createXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window_1.XDomainRequest; - -forEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) { - createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) { - options = initParams(uri, options, callback); - options.method = method.toUpperCase(); - return _createXHR(options) - }; -}); - -function forEachArray(array, iterator) { - for (var i = 0; i < array.length; i++) { - iterator(array[i]); - } -} - -function isEmpty(obj){ - for(var i in obj){ - if(obj.hasOwnProperty(i)) return false - } - return true -} - -function initParams(uri, options, callback) { - var params = uri; - - if (isFunction_1(options)) { - callback = options; - if (typeof uri === "string") { - params = {uri:uri}; - } - } else { - params = immutable(options, {uri: uri}); - } - - params.callback = callback; - return params -} - -function createXHR(uri, options, callback) { - options = initParams(uri, options, callback); - return _createXHR(options) -} - -function _createXHR(options) { - if(typeof options.callback === "undefined"){ - throw new Error("callback argument missing") - } - - var called = false; - var callback = function cbOnce(err, response, body){ - if(!called){ - called = true; - options.callback(err, response, body); - } - }; - - function readystatechange() { - if (xhr.readyState === 4) { - setTimeout(loadFunc, 0); - } - } - - function getBody() { - // Chrome with requestType=blob throws errors arround when even testing access to responseText - var body = undefined; - - if (xhr.response) { - body = xhr.response; - } else { - body = xhr.responseText || getXml(xhr); - } - - if (isJson) { - try { - body = JSON.parse(body); - } catch (e) {} - } - - return body - } - - function errorFunc(evt) { - clearTimeout(timeoutTimer); - if(!(evt instanceof Error)){ - evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") ); - } - evt.statusCode = 0; - return callback(evt, failureResponse) - } - - // will load the data & process the response in a special response object - function loadFunc() { - if (aborted) return - var status; - clearTimeout(timeoutTimer); - if(options.useXDR && xhr.status===undefined) { - //IE8 CORS GET successful response doesn't have a status field, but body is fine - status = 200; - } else { - status = (xhr.status === 1223 ? 204 : xhr.status); - } - var response = failureResponse; - var err = null; - - if (status !== 0){ - response = { - body: getBody(), - statusCode: status, - method: method, - headers: {}, - url: uri, - rawRequest: xhr - }; - if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE - response.headers = parseHeaders(xhr.getAllResponseHeaders()); - } - } else { - err = new Error("Internal XMLHttpRequest Error"); - } - return callback(err, response, response.body) - } - - var xhr = options.xhr || null; - - if (!xhr) { - if (options.cors || options.useXDR) { - xhr = new createXHR.XDomainRequest(); - }else{ - xhr = new createXHR.XMLHttpRequest(); - } - } - - var key; - var aborted; - var uri = xhr.url = options.uri || options.url; - var method = xhr.method = options.method || "GET"; - var body = options.body || options.data; - var headers = xhr.headers = options.headers || {}; - var sync = !!options.sync; - var isJson = false; - var timeoutTimer; - var failureResponse = { - body: undefined, - headers: {}, - statusCode: 0, - method: method, - url: uri, - rawRequest: xhr - }; - - if ("json" in options && options.json !== false) { - isJson = true; - headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json"); //Don't override existing accept header declared by user - if (method !== "GET" && method !== "HEAD") { - headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json"); //Don't override existing accept header declared by user - body = JSON.stringify(options.json === true ? body : options.json); - } - } - - xhr.onreadystatechange = readystatechange; - xhr.onload = loadFunc; - xhr.onerror = errorFunc; - // IE9 must have onprogress be set to a unique function. - xhr.onprogress = function () { - // IE must die - }; - xhr.onabort = function(){ - aborted = true; - }; - xhr.ontimeout = errorFunc; - xhr.open(method, uri, !sync, options.username, options.password); - //has to be after open - if(!sync) { - xhr.withCredentials = !!options.withCredentials; - } - // Cannot set timeout with sync request - // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly - // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent - if (!sync && options.timeout > 0 ) { - timeoutTimer = setTimeout(function(){ - if (aborted) return - aborted = true;//IE9 may still call readystatechange - xhr.abort("timeout"); - var e = new Error("XMLHttpRequest timeout"); - e.code = "ETIMEDOUT"; - errorFunc(e); - }, options.timeout ); - } - - if (xhr.setRequestHeader) { - for(key in headers){ - if(headers.hasOwnProperty(key)){ - xhr.setRequestHeader(key, headers[key]); - } - } - } else if (options.headers && !isEmpty(options.headers)) { - throw new Error("Headers cannot be set on an XDomainRequest object") - } - - if ("responseType" in options) { - xhr.responseType = options.responseType; - } - - if ("beforeSend" in options && - typeof options.beforeSend === "function" - ) { - options.beforeSend(xhr); - } - - // Microsoft Edge browser sends "undefined" when send is called with undefined value. - // XMLHttpRequest spec says to pass null as body to indicate no body - // See https://github.com/naugtur/xhr/issues/100. - xhr.send(body || null); - - return xhr - - -} - -function getXml(xhr) { - // xhr.responseXML will throw Exception "InvalidStateError" or "DOMException" - // See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML. - try { - if (xhr.responseType === "document") { - return xhr.responseXML - } - var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"; - if (xhr.responseType === "" && !firefoxBugTakenEffect) { - return xhr.responseXML - } - } catch (e) {} - - return null -} - -function noop() {} - -xhr.default = default_1; - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { - return typeof obj; -} : function (obj) { - return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; -}; - - - - - -var asyncGenerator = function () { - function AwaitValue(value) { - this.value = value; - } - - function AsyncGenerator(gen) { - var front, back; - - function send(key, arg) { - return new Promise(function (resolve, reject) { - var request = { - key: key, - arg: arg, - resolve: resolve, - reject: reject, - next: null - }; - - if (back) { - back = back.next = request; - } else { - front = back = request; - resume(key, arg); - } - }); - } - - function resume(key, arg) { - try { - var result = gen[key](arg); - var value = result.value; - - if (value instanceof AwaitValue) { - Promise.resolve(value.value).then(function (arg) { - resume("next", arg); - }, function (arg) { - resume("throw", arg); - }); - } else { - settle(result.done ? "return" : "normal", result.value); - } - } catch (err) { - settle("throw", err); - } - } - - function settle(type, value) { - switch (type) { - case "return": - front.resolve({ - value: value, - done: true - }); - break; - - case "throw": - front.reject(value); - break; - - default: - front.resolve({ - value: value, - done: false - }); - break; - } - - front = front.next; - - if (front) { - resume(front.key, front.arg); - } else { - back = null; - } - } - - this._invoke = send; - - if (typeof gen.return !== "function") { - this.return = undefined; - } - } - - if (typeof Symbol === "function" && Symbol.asyncIterator) { - AsyncGenerator.prototype[Symbol.asyncIterator] = function () { - return this; - }; - } - - AsyncGenerator.prototype.next = function (arg) { - return this._invoke("next", arg); - }; - - AsyncGenerator.prototype.throw = function (arg) { - return this._invoke("throw", arg); - }; - - AsyncGenerator.prototype.return = function (arg) { - return this._invoke("return", arg); - }; - - return { - wrap: function (fn) { - return function () { - return new AsyncGenerator(fn.apply(this, arguments)); - }; - }, - await: function (value) { - return new AwaitValue(value); - } - }; -}(); - - - - - -var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -}; - -var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; -}(); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -var toConsumableArray = function (arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; - - return arr2; - } else { - return Array.from(arr); - } -}; - -var lastError = ''; - -/** - * Creates the HTLM for a failure message - * @param {string} canvasContainerId id of container of th - * canvas. - * @return {string} The html. - */ -function makeFailHTML(msg) { - return '\n\n
\n
\n
' + msg + '
\n
\n
\n'; -} - -/** - * Message for getting a webgl browser - * @type {string} - */ -var GET_A_WEBGL_BROWSER = '\n\tThis page requires a browser that supports WebGL.
\n\tClick here to upgrade your browser.\n'; - -/** - * Message for need better hardware - * @type {string} - */ -var OTHER_PROBLEM = '\n\tIt does not appear your computer can support WebGL.
\n\tClick here for more information.\n'; - -/** - * Code to return in `onError` callback when the browser doesn't support webgl - * @type {number} - */ -var ERROR_BROWSER_SUPPORT = 1; - -/** - * Code to return in `onError` callback there's any other problem related to webgl - * @type {number} - */ -var ERROR_OTHER = 2; - -/** - * Creates a webgl context. If creation fails it will - * change the contents of the container of the - * tag to an error message with the correct links for WebGL, - * unless `onError` option is defined to a callback, - * which allows for custom error handling.. - * @param {Element} canvas. The canvas element to create a - * context from. - * @param {WebGLContextCreationAttributes} optAttribs Any - * creation attributes you want to pass in. - * @return {WebGLRenderingContext} The created context. - */ -function setupWebGL(canvas, optAttribs, onError) { - function showLink(str) { - var container = canvas.parentNode; - if (container) { - container.innerHTML = makeFailHTML(str); - } - } - - function handleError(errorCode, msg) { - if (typeof onError === 'function') { - onError(errorCode); - } else { - showLink(msg); - } - } - - if (!window.WebGLRenderingContext) { - handleError(ERROR_BROWSER_SUPPORT, GET_A_WEBGL_BROWSER); - return null; - } - - var context = create3DContext(canvas, optAttribs); - if (!context) { - handleError(ERROR_OTHER, OTHER_PROBLEM); - } else { - context.getExtension('OES_standard_derivatives'); - } - return context; -} - -/** - * Creates a webgl context. - * @param {!Canvas} canvas The canvas tag to get context - * from. If one is not passed in one will be created. - * @return {!WebGLContext} The created context. - */ -function create3DContext(canvas, optAttribs) { - var names = ['webgl', 'experimental-webgl']; - var context = null; - for (var ii = 0; ii < names.length; ++ii) { - try { - context = canvas.getContext(names[ii], optAttribs); - } catch (e) { - if (context) { - break; - } - } - } - return context; -} - -/* - * Create a Vertex of a specific type (gl.VERTEX_SHADER/) - */ -function createShader(main, source, type, offset) { - var gl = main.gl; - - var shader = gl.createShader(type); - gl.shaderSource(shader, source); - gl.compileShader(shader); - - var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS); - - if (!compiled) { - // Something went wrong during compilation; get the error - lastError = gl.getShaderInfoLog(shader); - console.error('*** Error compiling shader ' + shader + ':' + lastError); - main.trigger('error', { - shader: shader, - source: source, - type: type, - error: lastError, - offset: offset || 0 - }); - gl.deleteShader(shader); - return null; - } - - return shader; -} - -/** - * Loads a shader. - * @param {!WebGLContext} gl The WebGLContext to use. - * @param {string} shaderSource The shader source. - * @param {number} shaderType The type of shader. - * @param {function(string): void) opt_errorCallback callback for errors. - * @return {!WebGLShader} The created shader. - */ -function createProgram(main, shaders, optAttribs, optLocations) { - var gl = main.gl; - - var program = gl.createProgram(); - for (var ii = 0; ii < shaders.length; ++ii) { - gl.attachShader(program, shaders[ii]); - } - if (optAttribs) { - for (var _ii = 0; _ii < optAttribs.length; ++_ii) { - gl.bindAttribLocation(program, optLocations ? optLocations[_ii] : _ii, optAttribs[_ii]); - } - } - gl.linkProgram(program); - - // Check the link status - var linked = gl.getProgramParameter(program, gl.LINK_STATUS); - if (!linked) { - // something went wrong with the link - lastError = gl.getProgramInfoLog(program); - console.log('Error in program linking:' + lastError); - gl.deleteProgram(program); - return null; - } - return program; -} - -// By Brett Camber on -// https://github.com/tangrams/tangram/blob/master/src/gl/glsl.js -function parseUniforms(uniforms) { - var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - - var parsed = []; - - for (var name in uniforms) { - var uniform = uniforms[name]; - var u = void 0; - - if (prefix) { - name = prefix + '.' + name; - } - - // Single float - if (typeof uniform === 'number') { - parsed.push({ - type: 'float', - method: '1f', - name: name, - value: uniform - }); - } - // Array: vector, array of floats, array of textures, or array of structs - else if (Array.isArray(uniform)) { - // Numeric values - if (typeof uniform[0] === 'number') { - // float vectors (vec2, vec3, vec4) - if (uniform.length === 1) { - parsed.push({ - type: 'float', - method: '1f', - name: name, - value: uniform - }); - } - // float vectors (vec2, vec3, vec4) - else if (uniform.length >= 2 && uniform.length <= 4) { - parsed.push({ - type: 'vec' + uniform.length, - method: uniform.length + 'fv', - name: name, - value: uniform - }); - } - // float array - else if (uniform.length > 4) { - parsed.push({ - type: 'float[]', - method: '1fv', - name: name + '[0]', - value: uniform - }); - } - // TODO: assume matrix for (typeof == Float32Array && length == 16)? - } - // Array of textures - else if (typeof uniform[0] === 'string') { - parsed.push({ - type: 'sampler2D', - method: '1i', - name: name, - value: uniform - }); - } - // Array of arrays - but only arrays of vectors are allowed in this case - else if (Array.isArray(uniform[0]) && typeof uniform[0][0] === 'number') { - // float vectors (vec2, vec3, vec4) - if (uniform[0].length >= 2 && uniform[0].length <= 4) { - // Set each vector in the array - for (u = 0; u < uniform.length; u++) { - parsed.push({ - type: 'vec' + uniform[0].length, - method: uniform[u].length + 'fv', - name: name + '[' + u + ']', - value: uniform[u] - }); - } - } - // else error? - } - // Array of structures - else if (_typeof(uniform[0]) === 'object') { - for (u = 0; u < uniform.length; u++) { - // Set each struct in the array - parsed.push.apply(parsed, toConsumableArray(parseUniforms(uniform[u], name + '[' + u + ']'))); - } - } - } - // Boolean - else if (typeof uniform === 'boolean') { - parsed.push({ - type: 'bool', - method: '1i', - name: name, - value: uniform - }); - } - // Texture - else if (typeof uniform === 'string') { - parsed.push({ - type: 'sampler2D', - method: '1i', - name: name, - value: uniform - }); - } - // Structure - else if ((typeof uniform === 'undefined' ? 'undefined' : _typeof(uniform)) === 'object') { - // Set each field in the struct - parsed.push.apply(parsed, toConsumableArray(parseUniforms(uniform, name))); - } - // TODO: support other non-float types? (int, etc.) - } - return parsed; -} - -function isCanvasVisible(canvas) { - return canvas.getBoundingClientRect().top + canvas.height > 0 && canvas.getBoundingClientRect().top < (window.innerHeight || document.documentElement.clientHeight); -} - -function isPowerOf2(value) { - return (value & value - 1) === 0; -} - -function isSafari() { - return (/^((?!chrome|android).)*safari/i.test(navigator.userAgent) - ); -} - - - - - - - -function isDiff(a, b) { - if (a && b) { - return a.toString() !== b.toString(); - } - return false; -} - -function subscribeMixin$1(target) { - var listeners = new Set(); - - return Object.assign(target, { - on: function on(type, f) { - var listener = {}; - listener[type] = f; - listeners.add(listener); - }, - off: function off(type, f) { - if (f) { - var listener = {}; - listener[type] = f; - listeners.delete(listener); - } else { - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = listeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var item = _step.value; - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - - try { - for (var _iterator2 = Object.keys(item)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var key = _step2.value; - - if (key === type) { - listeners.delete(item); - return; - } - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - } - }, - listSubscriptions: function listSubscriptions() { - var _iteratorNormalCompletion3 = true; - var _didIteratorError3 = false; - var _iteratorError3 = undefined; - - try { - for (var _iterator3 = listeners[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { - var item = _step3.value; - - console.log(item); - } - } catch (err) { - _didIteratorError3 = true; - _iteratorError3 = err; - } finally { - try { - if (!_iteratorNormalCompletion3 && _iterator3.return) { - _iterator3.return(); - } - } finally { - if (_didIteratorError3) { - throw _iteratorError3; - } - } - } - }, - subscribe: function subscribe(listener) { - listeners.add(listener); - }, - unsubscribe: function unsubscribe(listener) { - listeners.delete(listener); - }, - unsubscribeAll: function unsubscribeAll() { - listeners.clear(); - }, - trigger: function trigger(event) { - for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - data[_key - 1] = arguments[_key]; - } - - var _iteratorNormalCompletion4 = true; - var _didIteratorError4 = false; - var _iteratorError4 = undefined; - - try { - for (var _iterator4 = listeners[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { - var listener = _step4.value; - - if (typeof listener[event] === 'function') { - listener[event].apply(listener, toConsumableArray(data)); - } - } - } catch (err) { - _didIteratorError4 = true; - _iteratorError4 = err; - } finally { - try { - if (!_iteratorNormalCompletion4 && _iterator4.return) { - _iterator4.return(); - } - } finally { - if (_didIteratorError4) { - throw _iteratorError4; - } - } - } - } - }); -} - -// Texture management -var Texture = function () { - function Texture(gl, name) { - var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - classCallCheck(this, Texture); - - subscribeMixin$1(this); - - this.gl = gl; - this.texture = gl.createTexture(); - if (this.texture) { - this.valid = true; - } - this.bind(); - - this.name = name; - this.source = null; - this.sourceType = null; - this.loading = null; // a Promise object to track the loading state of this texture - - // Default to a 1-pixel black texture so we can safely render while we wait for an image to load - // See: http://stackoverflow.com/questions/19722247/webgl-wait-for-texture-to-load - this.setData(1, 1, new Uint8Array([0, 0, 0, 255]), { filtering: 'linear' }); - this.setFiltering(options.filtering); - - this.load(options); - } - - // Destroy a single texture instance - - - createClass(Texture, [{ - key: 'destroy', - value: function destroy() { - if (!this.valid) { - return; - } - this.gl.deleteTexture(this.texture); - this.texture = null; - delete this.data; - this.data = null; - this.valid = false; - } - }, { - key: 'bind', - value: function bind(unit) { - if (!this.valid) { - return; - } - if (typeof unit === 'number') { - if (Texture.activeUnit !== unit) { - this.gl.activeTexture(this.gl.TEXTURE0 + unit); - Texture.activeUnit = unit; - } - } - if (Texture.activeTexture !== this.texture) { - this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture); - Texture.activeTexture = this.texture; - } - } - }, { - key: 'load', - value: function load() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - this.loading = null; - - if (typeof options.url === 'string') { - if (this.url === undefined || options.url !== this.url) { - this.setUrl(options.url, options); - } - } else if (options.element) { - this.setElement(options.element, options); - } else if (options.data && options.width && options.height) { - this.setData(options.width, options.height, options.data, options); - } - } - - // Sets texture from an url - - }, { - key: 'setUrl', - value: function setUrl(url) { - var _this = this; - - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - if (!this.valid) { - return; - } - - this.url = url; // save URL reference (will be overwritten when element is loaded below) - this.source = this.url; - this.sourceType = 'url'; - - this.loading = new Promise(function (resolve, reject) { - var ext = url.split('.').pop().toLowerCase(); - var isVideo = ext === 'ogv' || ext === 'webm' || ext === 'mp4'; - - var element = undefined; - if (isVideo) { - element = document.createElement('video'); - element.autoplay = true; - options.filtering = 'nearest'; - // element.preload = 'auto'; - // element.style.display = 'none'; - // document.body.appendChild(element); - } else { - element = new Image(); - } - - element.onload = function () { - try { - _this.setElement(element, options); - } catch (e) { - console.log('Texture \'' + _this.name + '\': failed to load url: \'' + _this.source + '\'', e, options); - } - resolve(_this); - }; - element.onerror = function (e) { - // Warn and resolve on error - console.log('Texture \'' + _this.name + '\': failed to load url: \'' + _this.source + '\'', e, options); - resolve(_this); - }; - - // Safari has a bug loading data-URL elements with CORS enabled, so it must be disabled in that case - // https://bugs.webkit.org/show_bug.cgi?id=123978 - if (!(isSafari() && _this.source.slice(0, 5) === 'data:')) { - element.crossOrigin = 'anonymous'; - } - - element.src = _this.source; - if (isVideo) { - _this.setElement(element, options); - } - }); - return this.loading; - } - - // Sets texture to a raw image buffer - - }, { - key: 'setData', - value: function setData(width, height, data) { - var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; - - this.width = width; - this.height = height; - - this.source = data; - this.sourceType = 'data'; - - this.update(options); - this.setFiltering(options); - - this.loading = Promise.resolve(this); - return this.loading; - } - - // Sets the texture to track a element (canvas/image) - - }, { - key: 'setElement', - value: function setElement(element, options) { - var _this2 = this; - - var el = element; - - // a string element is interpeted as a CSS selector - if (typeof element === 'string') { - element = document.querySelector(element); - } - - if (element instanceof HTMLCanvasElement || element instanceof HTMLImageElement || element instanceof HTMLVideoElement) { - this.source = element; - this.sourceType = 'element'; - - if (element instanceof HTMLVideoElement) { - element.addEventListener('canplaythrough', function () { - _this2.intervalID = setInterval(function () { - _this2.update(options); - }, 15); - }, true); - element.addEventListener('ended', function () { - element.currentTime = 0; - element.play(); - }, true); - } else { - this.update(options); - } - this.setFiltering(options); - } else { - var msg = 'the \'element\' parameter (`element: ' + JSON.stringify(el) + '`) must be a CSS '; - msg += 'selector string, or a , or