diff --git a/src/assets/options.css b/src/assets/options.css deleted file mode 100644 index cbaae76..0000000 --- a/src/assets/options.css +++ /dev/null @@ -1,477 +0,0 @@ -#out { - padding: 0px 10px; - font-size: 13px; - line-height: 26px; - font-family: Monaco, consolas; - white-space: pre-wrap; -} - -#options { - font-size: 15px; - color: #595959; - font-family: consolas, monaco, "微软雅黑"; - padding-bottom: 30px; -} - -#options * { - box-sizing: border-box; -} - -#options .switch-btn { - position: relative; - display: inline-block; - vertical-align: top; - width: 80px; - height: 30px; - border-radius: 5px; - cursor: pointer; - zoom: 0.7; -} - -#options .checked-switch { - position: absolute; - top: 0; - left: 0; - opacity: 0; -} - -#options .text-switch { - background-color: #cccccc; - border: 1px solid #dddddd; - border-radius: inherit; - color: #fff; - display: block; - font-size: 15px; - width: 60px; - height: inherit; - position: relative; - text-transform: uppercase; -} - -#options .text-switch:before, -#options .text-switch:after { - position: absolute; - top: 50%; - margin-top: -.5em; - line-height: 1; - -webkit-transition: inherit; - -moz-transition: inherit; - -o-transition: inherit; - transition: inherit; -} - -#options .text-switch:before { - content: 'OF'; - right: 6px; -} - -#options .text-switch:after { - content: 'ON'; - left: 6px; - color: #FFFFFF; - opacity: 0; -} - -#options .checked-switch:checked~.text-switch { - background-color: #00af2c; - border: 1px solid #068506; -} - -#options .checked-switch:disabled~.text-switch { - cursor: no-drop; -} - -#options .checked-switch:disabled~.text-switch~.toggle-btn { - cursor: no-drop; -} - -#options .checked-switch:disabled~.text-switch:before { - content: '▬'; - right: 11px; -} - -#options .checked-switch:checked~.text-switch:before { - opacity: 0; -} - -#options .checked-switch:checked~.text-switch:after { - opacity: 1; -} - -#options .toggle-btn { - background: linear-gradient(#eee, #fafafa); - border-radius: 5px; - height: 28px; - left: 1px; - position: absolute; - top: 1px; - width: 28px; -} - -#options .checked-switch:checked~.toggle-btn { - left: 30px; -} - -#options .text-switch, -#options .toggle-btn { - transition: All 0.3s ease; - -webkit-transition: All 0.3s ease; - -moz-transition: All 0.3s ease; - -o-transition: All 0.3s ease; -} - -#options .no-radius, -#options .no-radius .toggle-btn { - border-radius: 0; -} - -#options .circle-style .toggle-btn::before { - background: linear-gradient(#dedede, #cacaca); - border-radius: 50%; - content: ""; - height: 14px; - margin-top: 6px; - padding: 0; - width: 14px; -} - -#options table { - border-collapse: collapse; - table-layout:fixed; - width: 100%; -} - -#options table td { - border-collapse: collapse; - padding: 3px; - margin-right: 15px; - word-break:keep-all; - white-space:nowrap; - overflow:hidden; - text-overflow:ellipsis; -} - -#options table tr:nth-child(odd) { - background-color: #fff !important; -} - -#options table tr:nth-child(even) { - background-color: #f8f8f8 !important; -} - -#options .keyword { - display: inline-block; - font-size: 14px; - color: #333; - border: 1px solid #eee; - border-radius: 12px; - height: 24px; - line-height: 22px; - padding: 0 10px; - background-color: #f3f3f3; - margin-right: 5px; -} - -#options .keyword.re { - color: rgb(105, 40, 97); -} - -#options .keyword.win { - color: rgb(48, 21, 122); -} - -#options .logo { - width: 32px; -} - -#options #customize .keys{ - width: 16%; -} - -#options #customize .robot.footBtn{ - background:#3085d6; - float: none; -} - -#options #customize .robot.footBtn:hover{ - background:#55aafa; -} - -#options .footBtn { - /* right: 5px; - bottom: 2px; */ - float: right; - background: #00af2c; - border-radius: 4px; - color: white; - padding: 2px 5px; - margin: 0px 5px; - cursor: pointer; -} - -#options .footBtn.danger { - float: left; - /* right: 5px; - bottom: 2px; */ - border-radius: 4px; - background: #df3f54; - color: white; - padding: 2px 5px; - margin: 0px 5px; - cursor: pointer; -} - -#options .footBtn:hover { - background: #068506; - transition: 0.5s; -} - -#options .footBtn.danger:hover { - background: #b32033; - transition: 0.5s; -} - -#options .foot { - position: fixed; - height: 30px; - right: 0px; - bottom: 0px; - left: 0px; - background: #f3f3f3; - box-shadow: 0px 0px 9px 0px #00000030; - padding: 3px; -} - -#options td span { - margin-right: 10px; -} - -#options span.Btn { - font-size: 16px; - cursor: pointer; -} - -#options span.Btn img { - height: 20px; -} - -#options span.editBtn { - color: #00af2c; -} - -#options span.exportBtn { - color: #407abf; -} - -#options span.delBtn { - color: #ed5b49 -} - -#options span.editBtn:hover { - color: #057205; -} - -#options span.exportBtn:hover { - color: #2d5586; -} - -#options span.delBtn:hover { - color: #bd3523; -} - -#options #customize input.customscript { - margin-left: 5px; - width: 20%; - display: none; -} - -#options #customize { - position: fixed; - z-index: 999; - height: 100%; - top: 100%; - left: 0; - right: 0; - padding: 0px 30px; - box-shadow: 0px 0px 9px 0px #00000030; - color: black; - background: white; -} - -#options .varoutput{ - display: none; -} - -#options #customize p { - line-height: 1.25rem; -} - -#options #customize .word { - color: #2196F3; - display: inline-block; - font-size: 14px; - border: 1px solid #1E88E5; - height: 24px; - line-height: 22px; - padding: 0 5px; - background-color: #E3F2FD; -} - -#options #customize input { - width: 90%; - height: 25px; - border-bottom: 1px solid #dbdbdb; - border-top: 0px; - border-left: 0px; - border-right: 0px; - font-size: 15px; - margin-left: 13px -} - -#options #customize input#rule { - width: 40%; -} - -#options #customize input:hover { - border-bottom-color: #9e9e9ec7; - transition: 0.25s; -} - -#options #customize input:focus { - outline: none; - border-bottom-color: #0277BD; - transition: 0.5s; -} - -input::-webkit-input-placeholder { - color: #999; - font-size: 15px -} - -#options #customize .CodeMirror { - font-size: 13px; - font-family: "Monaco", "consolas"; - width: 100%; - height: 23rem; - border: 1px solid #dbdbdb; - border-radius: 3px; -} - - -#options #customize .CodeMirror:hover { - border: 1px solid #9e9e9ec7; - transition: 0.25s; -} - -#options #customize .CodeMirror-focused { - border: 1px solid #0277BD !important; - box-shadow: 0px 0px 2px 0px #0277BD; - transition: 0.25s; -} - -#options #customize .CodeMirror-placeholder { - color: #999; - font-size: 15px -} - -#options #customize select { - width: 40%; - height: 25px; - margin-left: 3px; - border-bottom: 1px solid #dbdbdb; - border-top: 0px; - border-left: 0px; - border-right: 0px; - background-color: #ffffff; - border-radius: 0px; - outline: none; - font-size: 15px; - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAJAgMAAAB71iXHAAAADFBMVEUAAAAqPz8rN0csOEgGlpD7AAAAA3RSTlMABvwYJ91vAAAAGklEQVQI12OAgQNAaMDMwMAjw8DAVAAWgAEAPFADDsXseo4AAAAASUVORK5CYII=") no-repeat scroll right center transparent; - -webkit-appearance: none -} - -#options #customize select:hover { - border-bottom-color: #9e9e9ec7; - transition: 0.25s; -} - -#options #customize select:focus { - border-bottom-color: #0277BD; - transition: 0.5s; -} - -#options #customize select#vars,#action { - color: #999; -} - -#options #customize select option { - color: black; -} - -#options #customize select option.var { - display: none; - color: rgb(129, 76, 226); -} - -#options #customize input#iconame { - width: 35%; - cursor: pointer; -} - -#options #customize #icon { - float: right; - width: 28px; - cursor: pointer; -} - -#options #customize .selectBtn { - padding: 4px 10px; - font-size: 11px; - color: #1E88C7; - background: #D0EEFF; - border: 1px solid #99D3F5; - border-radius: 4px; - cursor: pointer; -} - -#options #customize .selectBtn:hover { - background: #AADFFD; - border-color: #78C3F3; - color: #004974; - transition: 0.5s; -} - -#options #customize button { - width: 150px; - height: 30px; - border-width: 0px; - border-radius: 3px; - cursor: pointer; - outline: none; - color: white; -} - -#options #customize button.cancelBtn { - float: right; - margin-right: 30px; - background: #808080c9; -} - -#options #customize button.saveBtn { - float: right; - background: #1E90FF; -} - -#options #customize button.saveBtn:hover { - background: #5599FF; - transition: 0.5s; -} - -#options #customize button.cancelBtn:hover { - background: #a5a2a2c9; - transition: 0.5s; -} - -::-webkit-scrollbar { - height: 0; -} \ No newline at end of file diff --git a/src/codemirror/.editorconfig b/src/assets/plugins/codemirror/.editorconfig old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/.editorconfig rename to src/assets/plugins/codemirror/.editorconfig diff --git a/src/codemirror/.gitattributes b/src/assets/plugins/codemirror/.gitattributes old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/.gitattributes rename to src/assets/plugins/codemirror/.gitattributes diff --git a/src/codemirror/.npmignore b/src/assets/plugins/codemirror/.npmignore old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/.npmignore rename to src/assets/plugins/codemirror/.npmignore diff --git a/src/codemirror/.travis.yml b/src/assets/plugins/codemirror/.travis.yml old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/.travis.yml rename to src/assets/plugins/codemirror/.travis.yml diff --git a/src/codemirror/AUTHORS b/src/assets/plugins/codemirror/AUTHORS old mode 100755 new mode 100644 similarity index 92% rename from src/codemirror/AUTHORS rename to src/assets/plugins/codemirror/AUTHORS index 0e4c895..f5b5d7a --- a/src/codemirror/AUTHORS +++ b/src/assets/plugins/codemirror/AUTHORS @@ -20,6 +20,7 @@ aeroson Ahmad Amireh Ahmad M. Zawawi ahoward +Ajin Abraham Akeksandr Motsjonov Alasdair Smith AlbertHilb @@ -31,6 +32,7 @@ Alexander Schepanovski Alexander Shvets Alexander Solovyov Alexandre Bique +Alex Churchill alexey-k Alex Piggott Aliaksei Chapyzhenka @@ -72,11 +74,13 @@ anthonygego Anthony Gégo Anthony Grimes Anton Kovalyov +antosarho Apollo Zhu AQNOUCH Mohammed Aram Shatakhtsyan areos Arnab Bose +Arnoud Buzing Arsène von Wyss Arthur Müller Arun Narasani @@ -95,6 +99,9 @@ Bastian Müller belhaj Bem Jones-Bey benbro +Benedikt Meurer +benhormann +Ben Hormann Beni Cherniavsky-Paskin Benjamin DeCoste Benjamin Young @@ -115,21 +122,26 @@ Bo boomyjee Bo Peng borawjm +Boris K Brad Metcalf Brandon Frohs Brandon Wamboldt Bret Little Brett Zamir Brian Grinstead +BrianHung Brian Sletten brrd Bruce Mitchener +Bruno Logerfo +Bryan Gin-ge Chen Bryan Massoth Caitlin Potter Calin Barbat callodacity Camilo Roca Casey Klebba +cBiscuit87 César González Íñiguez Chad Jolly Chandra Sekhar Pydi @@ -156,6 +168,7 @@ Christopher Pfohl Christopher Wallis Chunliang Lyu ciaranj +clone-it clso CodeAnimal CodeBitt @@ -165,6 +178,7 @@ ComFreek Cristian Prieto Curran Kelleher Curtis Gagliardi +d8888 dagsta daines Dale Jung @@ -192,16 +206,20 @@ David Barnett David H. Bronke David Mignot David Pathakjee +David Rodrigues David Santana David Vázquez David Whittington deebugger Deep Thought +Denis Ovsienko Devin Abbott Devon Carew Dick Choi +Diego Fernandez dignifiedquire Dimage Sapelkin +Dinindu D. Wanniarachchi dmaclach Dmitry Kiselyov domagoj412 @@ -214,12 +232,15 @@ Drew Hintz Drew Khoury Drini Cami Dror BG +Duncan Lilley duralog dwelle eborden +edoroshenko edsharp ekhaled Elisée +elpnt Emmanuel Schanzer Enam Mijbah Noor Eric Allam @@ -227,6 +248,7 @@ Eric Bogard Erik Demaine Erik Welander eustas +Evan Minsk Fabien Dubosson Fabien O'Carroll Fabio Zendhi Nagao @@ -243,11 +265,13 @@ Filype Pereira finalfantasia flack Florian Felten +Fons van der Plas Forbes Lindesay ForbesLindesay Ford_Lawnmower Forrest Oliphant Franco Catena +Frank Seifferth Frank Wiegand fraxx001 Fredrik Borg @@ -278,20 +302,24 @@ Grant Skinner greengiant Gregory Koberger Grzegorz Mazur +Guang Li Guan Gui Guillaume Massé Guillaume Massé guraga Gustavo Rodrigues Hakan Tunc +Hanno Fellmann Hans Engel Hanzhao Deng Harald Schilly Hardest Harshvardhan Gupta +Hasan Delibaş Hasan Karahan Heanes Hector Oswaldo Caballero +Hein Htat Hélio Hendrik Wallbaum Henrik Haugbølle @@ -304,13 +332,17 @@ Hugues Malphettes Ian Beck Ian Davies Ian Dickinson +ianhi Ian Rose Ian Wehrman Ian Wetherbee Ice White ICHIKAWA, Yuji idleberg +Igor Petruk ilvalle +Ilya Kharlamov +Ilya Zverev Ingo Richter Irakli Gozalishvili Ivan Kurnosov @@ -322,6 +354,7 @@ Jakob Miland Jakub Vrana Jakub Vrána James Campos +James Cockshull James Howard James Thorne Jamie Hill @@ -344,6 +377,7 @@ Jason Johnston Jason San Jose Jason Siefken Jayaprabhakar +Jay Contonio Jaydeep Solanki Jean Boussier Jeff Blaisdell @@ -363,10 +397,13 @@ Joel Einbinder joelpinheiro joewalsh Johan Ask +Johannes +John Chen John Connor John-David Dalton John Engler John Lees-Miller +John Ryan John Snelson John Van Der Loo Jon Ander Peñalba @@ -379,6 +416,7 @@ Jon Gacnik jongalloway Jon Malmaud Jon Sangster +Joo Joost-Wim Boekesteijn Joseph Pecoraro Josh Barnes @@ -403,6 +441,7 @@ karevn Karol Kayur Patel Kazuhito Hokamura +kcwiakala Kees de Kooter Kenan Christian Dimas Ken Newman @@ -422,6 +461,7 @@ koops Kris Ciccarello ks-ifware kubelsmieci +kvncp KwanEsq Kyle Kelley KyleMcNutt @@ -430,6 +470,7 @@ Lanfei Lanny laobubu Laszlo Vidacs +leaf leaf corcoran Lemmon Leo Baschy @@ -443,6 +484,7 @@ Lior Shub LloydMilligan LM lochel +Lonnie Abelbeck Lorenzo Simionato Lorenzo Stoakes Louis Mauchet @@ -473,6 +515,7 @@ Mário Gonçalves Mario Pietsch Mark Anderson Mark Dalgleish +Mark Hamstra Mark Lentczner Marko Bonaci Mark Peace @@ -491,11 +534,13 @@ mats cronqvist Matt Gaide Matthew Bauer Matthew Beale +Matthew Casperson matthewhayes Matthew Rathbone Matthew Suozzo Matthias Bussonnier Matthias BUSSONNIER +Mattia Astorino Matt MacPherson Matt McDonald Matt Pass @@ -505,10 +550,12 @@ Maximilian Hils Maxim Kraev Max Kirsch Max Schaefer +Max Wu Max Xiantu mbarkhau McBrainy mce2 +Mélanie Chauvel melpon meshuamam Metatheos @@ -576,14 +623,20 @@ Nikita Vasilyev Nikolaj Kappler Nikolay Kostov nilp0inter +Nils Knappmeier Nisarg Jhaveri nlwillia noragrossman Norman Rzepka +Nouzbe Oleksandr Yakovenko +Olivia Ytterbrink +Opender Singh opl- Oreoluwa Onatemowo +oscar.lofwenhamn Oskar Segersvärd +ossdev overdodactyl pablo pabloferz @@ -596,6 +649,7 @@ paris Paris Paris Kasidiaris Patil Arpith +Patrick Kettner Patrick Stoica Patrick Strawderman Paul Garvin @@ -611,6 +665,7 @@ peter Peter Flynn peterkroon Peter Kroon +Peter László Philipp A Philipp Markovics Philip Stadermann @@ -621,6 +676,7 @@ Pontus Melke prasanthj Prasanth J Prayag Verma +prendota Prendota Qiang Li Radek Piórkowski @@ -634,6 +690,7 @@ Randy Luecke Raphael Amorim Rasmus Erik Voel Jensen Rasmus Schultz +raymondf Raymond Hill ray ratchup Ray Ratchup @@ -649,10 +706,14 @@ Robert Crossfield Robert Martin Roberto Abdelkader Martínez Pérez robertop23 +Roberto Vidal Robert Plummer +Roman Janusz Rrandom Rrrandom Ruslan Osmanov +rvalavicius +Ryan Pangrle Ryan Petrello Ryan Prior ryu-sato @@ -667,6 +728,7 @@ Sander Verweij santec Sarah McAlear and Wenlin Zhang Sascha Peilicke +Sasha Varlamov satamas satchmorun sathyamoorthi @@ -676,6 +738,7 @@ SCLINIC\jdecker Scott Aikin Scott Feeney Scott Goodhew +Seb35 Sebastian Wilzbach Sebastian Zaha Seren D @@ -714,6 +777,7 @@ Stephen Lavelle Steve Champagne Steve Hoover Steve O'Hara +stockiNail stoskov Stryder Crown Stu Kennedy @@ -725,7 +789,9 @@ Tako Schotanus Takuji Shimokawa Takuya Matsuyama Tarmil +T. Brandon Ashley TDaglis +Teja tel Tentone tfjgeorge @@ -741,9 +807,11 @@ thomasmaclean Thomas Schmid Tim Alby Tim Baumann +Tim Gates Timothy Farrell Timothy Gu Timothy Hatcher +Tim van der Lippe Tobias Bertelsen TobiasBg Todd Berman @@ -765,9 +833,11 @@ TSUYUSATO Kitsune Tugrul Elmas twifkak Tyler Long +Tyler Makaro Vadim Dyachenko Vadzim Ramanenka Vaibhav Sagar +vamshi.revu VapidWorx Vestimir Markov vf @@ -791,6 +861,7 @@ Wojtek Ptak wonderboyjon Wu Cheng-Han Xavier Mendez +Yang Guo Yassin N. Hassan YNH Webdev yoongu @@ -802,5 +873,6 @@ Zachary Dremann Zeno Rocha Zhang Hao Ziv +zoobestik zziuni 魏鹏刚 diff --git a/src/codemirror/CHANGELOG.md b/src/assets/plugins/codemirror/CHANGELOG.md old mode 100755 new mode 100644 similarity index 91% rename from src/codemirror/CHANGELOG.md rename to src/assets/plugins/codemirror/CHANGELOG.md index fb64003..a445dd9 --- a/src/codemirror/CHANGELOG.md +++ b/src/assets/plugins/codemirror/CHANGELOG.md @@ -1,3 +1,223 @@ +## 5.54.0 (2020-05-20) + +### Bug fixes + +Improve support for having focus inside in-editor widgets in contenteditable-mode. + +Fix issue where the scroll position could jump when clicking on a selection in Chrome. + +[python mode](https://codemirror.net/mode/python/): Better format string support. + +[javascript mode](https://codemirror.net/mode/javascript/): Improve parsing of private properties and class fields. + +[matchbrackets addon](https://codemirror.net/doc/manual.html#addon_matchbrackets): Disable highlighting when the editor doesn't have focus. + +### New features + +[runmode addon](https://codemirror.net/doc/manual.html#addon_runmode): Properly support for cross-line lookahead. + +[vim bindings](https://codemirror.net/demo/vim.html): Allow Ex-Commands with non-word names. + +[gfm mode](https://codemirror.net/mode/gfm/): Add a `fencedCodeBlockDefaultMode` option. + +## 5.53.2 (2020-04-21) + +### Bug fixes + +[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): Fix a regression that broke completion picking. + +## 5.53.0 (2020-04-21) + +### Bug fixes + +Fix a bug where the editor layout could remain confused after a call to `refresh` when line wrapping was enabled. + +[dialog addon](https://codemirror.net/doc/manual.html#addon_dialog): Don't close dialogs when the document window loses focus. + +[merge addon](https://codemirror.net/doc/manual.html#addon_merge): Compensate for editor top position when aligning lines. + +[vim bindings](https://codemirror.net/demo/vim.html): Improve EOL handling. + +[emacs bindings](https://codemirror.net/demo/emacs.html): Include default keymap as a fallback. + +[julia mode](https://codemirror.net/mode/julia/): Fix an infinite loop bug. + +[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): Scroll cursor into view when picking a completion. + +### New features + +New option: [`screenReaderLabel`](https://codemirror.net/doc/manual.html#option_screenReaderLabel) to add a label to the editor. + +New mode: [wast](https://codemirror.net/mode/wast/). + +## 5.52.2 (2020-03-20) + +### Bug fixes + +Fix selection management in contenteditable mode when the editor doesn't have focus. + +Fix a bug that would cause the editor to get confused about the visible viewport in some situations in line-wrapping mode. + +[markdown mode](https://codemirror.net/mode/markdown/): Don't treat single dashes as setext header markers. + +[zenburn theme](https://codemirror.net/demo/theme.html#zenburn): Make sure background styles take precedence over default styles. + +[css mode](https://codemirror.net/mode/css/): Recognize a number of new properties. + +## 5.52.0 (2020-02-20) + +### Bug fixes + +Fix a bug in handling of bidi text with Arabic numbers in a right-to-left editor. + +Fix a crash when combining file drop with a `"beforeChange"` filter. + +Prevent issue when passing negative coordinates to `scrollTo`. + +### New features + +[lint](https://codemirror.net/doc/manual.html#addon_lint) and [tern](https://codemirror.net/demo/tern.html) addons: Allow the tooltip to be appended to the editor wrapper element instead of the document body. + +## 5.51.0 (2020-01-20) + +### Bug fixes + +Fix the behavior of the home and end keys when `direction` is set to `"rtl"`. + +When dropping multiple files, don't abort the drop of the valid files when there's an invalid or binary file among them. + +Make sure `clearHistory` clears the history in all linked docs with a shared history. + +[vim bindings](https://codemirror.net/demo/vim.html): Fix behavior of `'` and `` ` `` marks, fix `R` in visual mode. + +### New features + +[vim bindings](https://codemirror.net/demo/vim.html): Support `gi`, `gI`, and `gJ`. + +## 5.50.2 (2020-01-01) + +### Bug fixes + +Fix bug that broke removal of line widgets. + +## 5.50.0 (2019-12-20) + +### Bug fixes + +Make Shift-Delete to cut work on Firefox. + +[closetag addon](https://codemirror.net/demo/closetag.html): Properly handle self-closing tags. + +[handlebars mode](https://codemirror.net/mode/handlebars/): Fix triple-brace support. + +[searchcursor addon](https://codemirror.net/doc/manual.html#addon_searchcursor): Support mathing `$` in reverse regexp search. + +[panel addon](https://codemirror.net/doc/manual.html#addon_panel): Don't get confused by changing panel sizes. + +[javascript-hint addon](https://codemirror.net/doc/manual.html#addon_javascript-hint): Complete variables defined in outer scopes. + +[sublime bindings](https://codemirror.net/demo/sublime.html): Make by-subword motion more consistent with Sublime Text. + +[julia mode](https://codemirror.net/mode/julia/): Don't break on zero-prefixed integers. + +[elm mode](https://codemirror.net/mode/elm/): Sync with upstream version. + +[sql mode](https://codemirror.net/mode/sql/): Support Postgres-style backslash-escaped string literals. + +### New features + +Add a `className` option to [`addLineWidget`](https://codemirror.net/doc/manual.html#addLineWidget). + +[foldcode addon](https://codemirror.net/doc/manual.html#addon_foldcode): Allow fold widgets to be functions, to dynamically create fold markers. + +New themes: [ayu-dark](https://codemirror.net/demo/theme.html#ayu-dark) and [ayu-mirage](https://codemirror.net/demo/theme.html#ayu-mirage). + +## 5.49.2 (2019-10-21) + +### Bug fixes + +[sublime bindings](https://codemirror.net/demo/sublime.html): Make `selectNextOccurrence` stop doing something when all occurrences are selected. + +[continuecomment addon](https://codemirror.net/doc/manual.html#addon_continuecomment): Respect `indentWithTabs` option. + +[foldgutter addon](https://codemirror.net/doc/manual.html#addon_foldgutter): Optimize by reusing DOM when possible. + +[markdown mode](https://codemirror.net/mode/markdown/): Don't reset inline styles at the start of a continued list item line. + +[clike mode](https://codemirror.net/mode/clike/): Add a configuration for Objective-C++. + +## 5.49.0 (2019-09-20) + +### Bug fixes + +[octave mode](https://codemirror.net/mode/octave/index.html): Don't mark common punctuation as error. + +[clike mode](https://codemirror.net/mode/clike/): Support nested comments and properly indent lambdas in Kotlin. + +[foldgutter](https://codemirror.net/doc/manual.html#addon_foldgutter) and [annotatescrollbar](https://codemirror.net/doc/manual.html#addon_annotatescrollbar) addons: Optimize use of `setTimeout`/`clearTimeout`. + +### New features + +New themes: [moxer](https://codemirror.net/demo/theme.html#moxer), [material-darker](https://codemirror.net/demo/theme.html#material-darker), [material-palenight](https://codemirror.net/demo/theme.html#material-palenight), [material-ocean](https://codemirror.net/demo/theme.html#material-ocean). + +[xml mode](https://codemirror.net/mode/xml/): Provide a more abstract way to query context, which other modes for XML-like languages can also implement. + +## 5.48.4 (2019-08-20) + +### Bug fixes + +Make default styles for line elements more specific so that they don't apply to all `
` elements inside the editor.
+
+Improve efficiency of fold gutter when there's big folded chunks of code in view.
+
+Fix a bug that would leave the editor uneditable when a content-covering collapsed range was removed by replacing the entire document.
+
+[julia mode](https://codemirror.net/mode/julia/): Support number separators.
+
+[asterisk mode](https://codemirror.net/mode/asterisk/): Improve comment support.
+
+[handlebars mode](https://codemirror.net/mode/handlebars/): Support triple-brace tags.
+
+## 5.48.2 (2019-07-20)
+
+### Bug fixes
+
+[vim bindings](https://codemirror.net/demo/vim.html): Adjust char escape substitution to match vim, support `&/$0`.
+
+[search addon](https://codemirror.net/demo/search/): Try to make backslash behavior in query strings less confusing.
+
+[javascript mode](https://codemirror.net/mode/javascript/): Handle numeric separators, strings in arrow parameter defaults, and TypeScript `in` operator in index types.
+
+[sparql mode](https://codemirror.net/mode/sparql/index.html): Allow non-ASCII identifier characters.
+
+## 5.48.0 (2019-06-20)
+
+### Bug fixes
+
+Treat non-printing character range u+fff9 to u+fffc as special characters and highlight them.
+
+[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): Fix positioning when the dialog is placed in a scrollable container.
+
+### New features
+
+Add [`selectLeft`](https://codemirror.net/doc/manual.html#mark_selectLeft)/[`selectRight`](https://codemirror.net/doc/manual.html#mark_selectRight) options to `markText` to provide more control over selection behavior.
+
+## 5.47.0 (2019-05-21)
+
+### Bug fixes
+
+[python mode](https://codemirror.net/mode/python/): Properly handle `...` syntax.
+
+[ruby mode](https://codemirror.net/mode/ruby): Fix indenting before closing brackets.
+
+[vim bindings](https://codemirror.net/demo/vim.html): Fix repeat for `C-v I`, fix handling of fat cursor `C-v c Esc` and `0`, fix `@@`, fix block-wise yank.
+
+### New features
+
+[vim bindings](https://codemirror.net/demo/vim.html): Add support for `` ` `` text object.
+
+## 5.46.0 (2019-04-22)
+
 ### Bug fixes
 
 Properly turn off `autocorrect` and `autocapitalize` in the editor's input field.
@@ -12,7 +232,7 @@ Remove a legacy key code for delete that is used for F16 on keyboards that have
 
 ### New features
 
-Allow [gutters](https://codemirror.net/doc/manual.html#option_gutters) to specify direct CSS stings.
+Allow [gutters](https://codemirror.net/doc/manual.html#option_gutters) to specify direct CSS strings.
 
 ## 5.45.0 (2019-03-20)
 
diff --git a/src/codemirror/CONTRIBUTING.md b/src/assets/plugins/codemirror/CONTRIBUTING.md
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/CONTRIBUTING.md
rename to src/assets/plugins/codemirror/CONTRIBUTING.md
diff --git a/src/codemirror/LICENSE b/src/assets/plugins/codemirror/LICENSE
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/LICENSE
rename to src/assets/plugins/codemirror/LICENSE
diff --git a/src/codemirror/README.md b/src/assets/plugins/codemirror/README.md
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/README.md
rename to src/assets/plugins/codemirror/README.md
diff --git a/src/codemirror/addon/comment/comment.js b/src/assets/plugins/codemirror/addon/comment/comment.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/comment/comment.js
rename to src/assets/plugins/codemirror/addon/comment/comment.js
diff --git a/src/assets/plugins/codemirror/addon/comment/continuecomment.js b/src/assets/plugins/codemirror/addon/comment/continuecomment.js
new file mode 100644
index 0000000..7ca1b4a
--- /dev/null
+++ b/src/assets/plugins/codemirror/addon/comment/continuecomment.js
@@ -0,0 +1,114 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/LICENSE
+
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  var nonspace = /\S/g;
+  var repeat = String.prototype.repeat || function (n) { return Array(n + 1).join(this); };
+  function continueComment(cm) {
+    if (cm.getOption("disableInput")) return CodeMirror.Pass;
+    var ranges = cm.listSelections(), mode, inserts = [];
+    for (var i = 0; i < ranges.length; i++) {
+      var pos = ranges[i].head
+      if (!/\bcomment\b/.test(cm.getTokenTypeAt(pos))) return CodeMirror.Pass;
+      var modeHere = cm.getModeAt(pos)
+      if (!mode) mode = modeHere;
+      else if (mode != modeHere) return CodeMirror.Pass;
+
+      var insert = null, line, found;
+      var blockStart = mode.blockCommentStart, lineCmt = mode.lineComment;
+      if (blockStart && mode.blockCommentContinue) {
+        line = cm.getLine(pos.line);
+        var end = line.lastIndexOf(mode.blockCommentEnd, pos.ch - mode.blockCommentEnd.length);
+        // 1. if this block comment ended
+        // 2. if this is actually inside a line comment
+        if (end != -1 && end == pos.ch - mode.blockCommentEnd.length ||
+            lineCmt && (found = line.lastIndexOf(lineCmt, pos.ch - 1)) > -1 &&
+            /\bcomment\b/.test(cm.getTokenTypeAt({line: pos.line, ch: found + 1}))) {
+          // ...then don't continue it
+        } else if (pos.ch >= blockStart.length &&
+                   (found = line.lastIndexOf(blockStart, pos.ch - blockStart.length)) > -1 &&
+                   found > end) {
+          // reuse the existing leading spaces/tabs/mixed
+          // or build the correct indent using CM's tab/indent options
+          if (nonspaceAfter(0, line) >= found) {
+            insert = line.slice(0, found);
+          } else {
+            var tabSize = cm.options.tabSize, numTabs;
+            found = CodeMirror.countColumn(line, found, tabSize);
+            insert = !cm.options.indentWithTabs ? repeat.call(" ", found) :
+              repeat.call("\t", (numTabs = Math.floor(found / tabSize))) +
+              repeat.call(" ", found - tabSize * numTabs);
+          }
+        } else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 &&
+                   found <= pos.ch &&
+                   found <= nonspaceAfter(0, line)) {
+          insert = line.slice(0, found);
+        }
+        if (insert != null) insert += mode.blockCommentContinue
+      }
+      if (insert == null && lineCmt && continueLineCommentEnabled(cm)) {
+        if (line == null) line = cm.getLine(pos.line);
+        found = line.indexOf(lineCmt);
+        // cursor at pos 0, line comment also at pos 0 => shift it down, don't continue
+        if (!pos.ch && !found) insert = "";
+        // continue only if the line starts with an optional space + line comment
+        else if (found > -1 && nonspaceAfter(0, line) >= found) {
+          // don't continue if there's only space(s) after cursor or the end of the line
+          insert = nonspaceAfter(pos.ch, line) > -1;
+          // but always continue if the next line starts with a line comment too
+          if (!insert) {
+            var next = cm.getLine(pos.line + 1) || '',
+                nextFound = next.indexOf(lineCmt);
+            insert = nextFound > -1 && nonspaceAfter(0, next) >= nextFound || null;
+          }
+          if (insert) {
+            insert = line.slice(0, found) + lineCmt +
+                     line.slice(found + lineCmt.length).match(/^\s*/)[0];
+          }
+        }
+      }
+      if (insert == null) return CodeMirror.Pass;
+      inserts[i] = "\n" + insert;
+    }
+
+    cm.operation(function() {
+      for (var i = ranges.length - 1; i >= 0; i--)
+        cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
+    });
+  }
+
+  function nonspaceAfter(ch, str) {
+    nonspace.lastIndex = ch;
+    var m = nonspace.exec(str);
+    return m ? m.index : -1;
+  }
+
+  function continueLineCommentEnabled(cm) {
+    var opt = cm.getOption("continueComments");
+    if (opt && typeof opt == "object")
+      return opt.continueLineComment !== false;
+    return true;
+  }
+
+  CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
+    if (prev && prev != CodeMirror.Init)
+      cm.removeKeyMap("continueComment");
+    if (val) {
+      var key = "Enter";
+      if (typeof val == "string")
+        key = val;
+      else if (typeof val == "object" && val.key)
+        key = val.key;
+      var map = {name: "continueComment"};
+      map[key] = continueComment;
+      cm.addKeyMap(map);
+    }
+  });
+});
diff --git a/src/codemirror/addon/dialog/dialog.css b/src/assets/plugins/codemirror/addon/dialog/dialog.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/dialog/dialog.css
rename to src/assets/plugins/codemirror/addon/dialog/dialog.css
diff --git a/src/codemirror/addon/dialog/dialog.js b/src/assets/plugins/codemirror/addon/dialog/dialog.js
old mode 100755
new mode 100644
similarity index 97%
rename from src/codemirror/addon/dialog/dialog.js
rename to src/assets/plugins/codemirror/addon/dialog/dialog.js
index 23b06a8..5f1f4aa
--- a/src/codemirror/addon/dialog/dialog.js
+++ b/src/assets/plugins/codemirror/addon/dialog/dialog.js
@@ -82,7 +82,9 @@
         if (e.keyCode == 13) callback(inp.value, e);
       });
 
-      if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
+      if (options.closeOnBlur !== false) CodeMirror.on(dialog, "focusout", function (evt) {
+        if (evt.relatedTarget !== null) close();
+      });
     } else if (button = dialog.getElementsByTagName("button")[0]) {
       CodeMirror.on(button, "click", function() {
         close();
diff --git a/src/codemirror/addon/display/autorefresh.js b/src/assets/plugins/codemirror/addon/display/autorefresh.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/display/autorefresh.js
rename to src/assets/plugins/codemirror/addon/display/autorefresh.js
diff --git a/src/codemirror/addon/display/fullscreen.css b/src/assets/plugins/codemirror/addon/display/fullscreen.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/display/fullscreen.css
rename to src/assets/plugins/codemirror/addon/display/fullscreen.css
diff --git a/src/codemirror/addon/display/fullscreen.js b/src/assets/plugins/codemirror/addon/display/fullscreen.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/display/fullscreen.js
rename to src/assets/plugins/codemirror/addon/display/fullscreen.js
diff --git a/src/codemirror/addon/display/panel.js b/src/assets/plugins/codemirror/addon/display/panel.js
old mode 100755
new mode 100644
similarity index 74%
rename from src/codemirror/addon/display/panel.js
rename to src/assets/plugins/codemirror/addon/display/panel.js
index 5faf1d5..4c9f2c0
--- a/src/codemirror/addon/display/panel.js
+++ b/src/assets/plugins/codemirror/addon/display/panel.js
@@ -1,15 +1,15 @@
 // CodeMirror, copyright (c) by Marijn Haverbeke and others
 // Distributed under an MIT license: https://codemirror.net/LICENSE
 
-(function(mod) {
+(function (mod) {
   if (typeof exports == "object" && typeof module == "object") // CommonJS
     mod(require("../../lib/codemirror"));
   else if (typeof define == "function" && define.amd) // AMD
     define(["../../lib/codemirror"], mod);
   else // Plain browser env
     mod(CodeMirror);
-})(function(CodeMirror) {
-  CodeMirror.defineExtension("addPanel", function(node, options) {
+})(function (CodeMirror) {
+  CodeMirror.defineExtension("addPanel", function (node, options) {
     options = options || {};
 
     if (!this.state.panels) initPanels(this);
@@ -25,8 +25,7 @@
       wrapper.insertBefore(node, options.before.node);
     } else if (replace) {
       wrapper.insertBefore(node, options.replace.node);
-      info.panels++;
-      options.replace.clear();
+      options.replace.clear(true);
     } else if (options.position == "bottom") {
       wrapper.appendChild(node);
     } else if (options.position == "before-bottom") {
@@ -38,14 +37,15 @@
     }
 
     var height = (options && options.height) || node.offsetHeight;
-    this._setSize(null, info.heightLeft -= height);
-    if (!replace) {
-      info.panels++;
-    }
-    if (options.stable && isAtTop(this, node))
-      this.scrollTo(null, this.getScrollInfo().top + height)
 
-    return new Panel(this, node, options, height);
+    var panel = new Panel(this, node, options, height);
+    info.panels.push(panel);
+
+    this.setSize();
+    if (options.stable && isAtTop(this, node))
+      this.scrollTo(null, this.getScrollInfo().top + height);
+
+    return panel;
   });
 
   function Panel(cm, node, options, height) {
@@ -56,22 +56,23 @@
     this.cleared = false;
   }
 
-  Panel.prototype.clear = function() {
+  /* when skipRemove is true, clear() was called from addPanel().
+   * Thus removePanels() should not be called (issue 5518) */
+  Panel.prototype.clear = function (skipRemove) {
     if (this.cleared) return;
     this.cleared = true;
     var info = this.cm.state.panels;
-    this.cm._setSize(null, info.heightLeft += this.height);
+    info.panels.splice(info.panels.indexOf(this), 1);
+    this.cm.setSize();
     if (this.options.stable && isAtTop(this.cm, this.node))
       this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height)
     info.wrapper.removeChild(this.node);
-    if (--info.panels == 0) removePanels(this.cm);
+    if (info.panels.length == 0 && !skipRemove) removePanels(this.cm);
   };
 
-  Panel.prototype.changed = function(height) {
-    var newHeight = height == null ? this.node.offsetHeight : height;
-    var info = this.cm.state.panels;
-    this.cm._setSize(null, info.heightLeft -= (newHeight - this.height));
-    this.height = newHeight;
+  Panel.prototype.changed = function () {
+    this.height = this.node.getBoundingClientRect().height;
+    this.cm.setSize();
   };
 
   function initPanels(cm) {
@@ -80,8 +81,7 @@
     var height = parseInt(style.height);
     var info = cm.state.panels = {
       setHeight: wrap.style.height,
-      heightLeft: height,
-      panels: 0,
+      panels: [],
       wrapper: document.createElement("div")
     };
     wrap.parentNode.insertBefore(info.wrapper, wrap);
@@ -90,8 +90,8 @@
     if (hasFocus) cm.focus();
 
     cm._setSize = cm.setSize;
-    if (height != null) cm.setSize = function(width, newHeight) {
-      if (newHeight == null) return this._setSize(width, newHeight);
+    if (height != null) cm.setSize = function (width, newHeight) {
+      if (!newHeight) newHeight = info.wrapper.offsetHeight;
       info.setHeight = newHeight;
       if (typeof newHeight != "number") {
         var px = /^(\d+\.?\d*)px$/.exec(newHeight);
@@ -100,10 +100,12 @@
         } else {
           info.wrapper.style.height = newHeight;
           newHeight = info.wrapper.offsetHeight;
-          info.wrapper.style.height = "";
         }
       }
-      cm._setSize(width, info.heightLeft += (newHeight - height));
+      var editorheight = newHeight - info.panels
+        .map(function (p) { return p.node.getBoundingClientRect().height; })
+        .reduce(function (a, b) { return a + b; }, 0);
+      cm._setSize(width, editorheight);
       height = newHeight;
     };
   }
diff --git a/src/codemirror/addon/display/placeholder.js b/src/assets/plugins/codemirror/addon/display/placeholder.js
old mode 100755
new mode 100644
similarity index 96%
rename from src/codemirror/addon/display/placeholder.js
rename to src/assets/plugins/codemirror/addon/display/placeholder.js
index 1a3fa33..4eabe3d
--- a/src/codemirror/addon/display/placeholder.js
+++ b/src/assets/plugins/codemirror/addon/display/placeholder.js
@@ -39,7 +39,7 @@
     var elt = cm.state.placeholder = document.createElement("pre");
     elt.style.cssText = "height: 0; overflow: visible";
     elt.style.direction = cm.getOption("direction");
-    elt.className = "CodeMirror-placeholder";
+    elt.className = "CodeMirror-placeholder CodeMirror-line-like";
     var placeHolder = cm.getOption("placeholder")
     if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
     elt.appendChild(placeHolder)
diff --git a/src/codemirror/addon/display/rulers.js b/src/assets/plugins/codemirror/addon/display/rulers.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/display/rulers.js
rename to src/assets/plugins/codemirror/addon/display/rulers.js
diff --git a/src/codemirror/addon/edit/closebrackets.js b/src/assets/plugins/codemirror/addon/edit/closebrackets.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/edit/closebrackets.js
rename to src/assets/plugins/codemirror/addon/edit/closebrackets.js
diff --git a/src/codemirror/addon/edit/closetag.js b/src/assets/plugins/codemirror/addon/edit/closetag.js
old mode 100755
new mode 100644
similarity index 86%
rename from src/codemirror/addon/edit/closetag.js
rename to src/assets/plugins/codemirror/addon/edit/closetag.js
index e5e83bc..b8cbf95
--- a/src/codemirror/addon/edit/closetag.js
+++ b/src/assets/plugins/codemirror/addon/edit/closetag.js
@@ -60,22 +60,23 @@
       if (!ranges[i].empty()) return CodeMirror.Pass;
       var pos = ranges[i].head, tok = cm.getTokenAt(pos);
       var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
-      if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;
+      var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state)
+      var tagName = tagInfo && tagInfo.name
+      if (!tagName) return CodeMirror.Pass
 
       var html = inner.mode.configuration == "html";
       var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
       var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
 
-      var tagName = state.tagName;
       if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
       var lowerTagName = tagName.toLowerCase();
       // Don't process the '>' at the end of an end-tag or self-closing tag
       if (!tagName ||
           tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
-          tok.type == "tag" && state.type == "closeTag" ||
-          tok.string.indexOf("/") == (tok.string.length - 1) || // match something like 
+          tok.type == "tag" && tagInfo.close ||
+          tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like 
           dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
-          closingTagExists(cm, tagName, pos, state, true))
+          closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true))
         return CodeMirror.Pass;
 
       var emptyTags = typeof opt == "object" && opt.emptyTags;
@@ -120,19 +121,16 @@
       // when completing in JS/CSS snippet in htmlmixed mode. Does not
       // work for other XML embedded languages (there is no general
       // way to go from a mixed mode to its current XML state).
-      var replacement;
-      if (inner.mode.name != "xml") {
-        if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript")
-          replacement = head + "script";
-        else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css")
-          replacement = head + "style";
-        else
-          return CodeMirror.Pass;
+      var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
+      if (mixed && inner.mode.name == "javascript") {
+        replacement = head + "script";
+      } else if (mixed && inner.mode.name == "css") {
+        replacement = head + "style";
       } else {
-        if (!state.context || !state.context.tagName ||
-            closingTagExists(cm, state.context.tagName, pos, state))
+        var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
+        if (!context || (context.length && closingTagExists(cm, context, context[context.length - 1], pos)))
           return CodeMirror.Pass;
-        replacement = head + state.context.tagName;
+        replacement = head + context[context.length - 1]
       }
       if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
       replacements[i] = replacement;
@@ -162,16 +160,19 @@
 
   // If xml-fold is loaded, we use its functionality to try and verify
   // whether a given tag is actually unclosed.
-  function closingTagExists(cm, tagName, pos, state, newTag) {
+  function closingTagExists(cm, context, tagName, pos, newTag) {
     if (!CodeMirror.scanForClosingTag) return false;
     var end = Math.min(cm.lastLine() + 1, pos.line + 500);
     var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
     if (!nextClose || nextClose.tag != tagName) return false;
-    var cx = state.context;
     // If the immediate wrapping context contains onCx instances of
     // the same tag, a closing tag only exists if there are at least
     // that many closing tags of that type following.
-    for (var onCx = newTag ? 1 : 0; cx && cx.tagName == tagName; cx = cx.prev) ++onCx;
+    var onCx = newTag ? 1 : 0
+    for (var i = context.length - 1; i >= 0; i--) {
+      if (context[i] == tagName) ++onCx
+      else break
+    }
     pos = nextClose.to;
     for (var i = 1; i < onCx; i++) {
       var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
diff --git a/src/codemirror/addon/edit/continuelist.js b/src/assets/plugins/codemirror/addon/edit/continuelist.js
old mode 100755
new mode 100644
similarity index 95%
rename from src/codemirror/addon/edit/continuelist.js
rename to src/assets/plugins/codemirror/addon/edit/continuelist.js
index fb5f037..2e5625a
--- a/src/codemirror/addon/edit/continuelist.js
+++ b/src/assets/plugins/codemirror/addon/edit/continuelist.js
@@ -41,7 +41,9 @@
         return;
       }
       if (emptyListRE.test(line)) {
-        if (!/>\s*$/.test(line)) cm.replaceRange("", {
+        var endOfQuote = inQuote && />\s*$/.test(line)
+        var endOfList = !/>\s*$/.test(line)
+        if (endOfQuote || endOfList) cm.replaceRange("", {
           line: pos.line, ch: 0
         }, {
           line: pos.line, ch: pos.ch + 1
diff --git a/src/codemirror/addon/edit/matchbrackets.js b/src/assets/plugins/codemirror/addon/edit/matchbrackets.js
old mode 100755
new mode 100644
similarity index 97%
rename from src/codemirror/addon/edit/matchbrackets.js
rename to src/assets/plugins/codemirror/addon/edit/matchbrackets.js
index 2a14728..2c47e07
--- a/src/codemirror/addon/edit/matchbrackets.js
+++ b/src/assets/plugins/codemirror/addon/edit/matchbrackets.js
@@ -118,16 +118,24 @@
   }
 
   CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
-    if (old && old != CodeMirror.Init) {
-      cm.off("cursorActivity", doMatchBrackets);
+    function clear(cm) {
       if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
         cm.state.matchBrackets.currentlyHighlighted();
         cm.state.matchBrackets.currentlyHighlighted = null;
       }
     }
+
+    if (old && old != CodeMirror.Init) {
+      cm.off("cursorActivity", doMatchBrackets);
+      cm.off("focus", doMatchBrackets)
+      cm.off("blur", clear)
+      clear(cm);
+    }
     if (val) {
       cm.state.matchBrackets = typeof val == "object" ? val : {};
       cm.on("cursorActivity", doMatchBrackets);
+      cm.on("focus", doMatchBrackets)
+      cm.on("blur", clear)
     }
   });
 
diff --git a/src/codemirror/addon/edit/matchtags.js b/src/assets/plugins/codemirror/addon/edit/matchtags.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/edit/matchtags.js
rename to src/assets/plugins/codemirror/addon/edit/matchtags.js
diff --git a/src/codemirror/addon/edit/trailingspace.js b/src/assets/plugins/codemirror/addon/edit/trailingspace.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/edit/trailingspace.js
rename to src/assets/plugins/codemirror/addon/edit/trailingspace.js
diff --git a/src/codemirror/addon/fold/brace-fold.js b/src/assets/plugins/codemirror/addon/fold/brace-fold.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/fold/brace-fold.js
rename to src/assets/plugins/codemirror/addon/fold/brace-fold.js
diff --git a/src/codemirror/addon/fold/comment-fold.js b/src/assets/plugins/codemirror/addon/fold/comment-fold.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/fold/comment-fold.js
rename to src/assets/plugins/codemirror/addon/fold/comment-fold.js
diff --git a/src/codemirror/addon/fold/foldcode.js b/src/assets/plugins/codemirror/addon/fold/foldcode.js
old mode 100755
new mode 100644
similarity index 96%
rename from src/codemirror/addon/fold/foldcode.js
rename to src/assets/plugins/codemirror/addon/fold/foldcode.js
index e146fb9..887df3f
--- a/src/codemirror/addon/fold/foldcode.js
+++ b/src/assets/plugins/codemirror/addon/fold/foldcode.js
@@ -42,7 +42,7 @@
     }
     if (!range || range.cleared || force === "unfold") return;
 
-    var myWidget = makeWidget(cm, options);
+    var myWidget = makeWidget(cm, options, range);
     CodeMirror.on(myWidget, "mousedown", function(e) {
       myRange.clear();
       CodeMirror.e_preventDefault(e);
@@ -58,8 +58,13 @@
     CodeMirror.signal(cm, "fold", cm, range.from, range.to);
   }
 
-  function makeWidget(cm, options) {
+  function makeWidget(cm, options, range) {
     var widget = getOption(cm, options, "widget");
+
+    if (typeof widget == "function") {
+      widget = widget(range.from, range.to);
+    }
+
     if (typeof widget == "string") {
       var text = document.createTextNode(widget);
       widget = document.createElement("span");
diff --git a/src/codemirror/addon/fold/foldgutter.css b/src/assets/plugins/codemirror/addon/fold/foldgutter.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/fold/foldgutter.css
rename to src/assets/plugins/codemirror/addon/fold/foldgutter.css
diff --git a/src/codemirror/addon/fold/foldgutter.js b/src/assets/plugins/codemirror/addon/fold/foldgutter.js
old mode 100755
new mode 100644
similarity index 80%
rename from src/codemirror/addon/fold/foldgutter.js
rename to src/assets/plugins/codemirror/addon/fold/foldgutter.js
index 988c67c..7d46a60
--- a/src/codemirror/addon/fold/foldgutter.js
+++ b/src/assets/plugins/codemirror/addon/fold/foldgutter.js
@@ -16,7 +16,7 @@
       cm.clearGutter(cm.state.foldGutter.options.gutter);
       cm.state.foldGutter = null;
       cm.off("gutterClick", onGutterClick);
-      cm.off("change", onChange);
+      cm.off("changes", onChange);
       cm.off("viewportChange", onViewportChange);
       cm.off("fold", onFold);
       cm.off("unfold", onFold);
@@ -26,7 +26,7 @@
       cm.state.foldGutter = new State(parseOptions(val));
       updateInViewport(cm);
       cm.on("gutterClick", onGutterClick);
-      cm.on("change", onChange);
+      cm.on("changes", onChange);
       cm.on("viewportChange", onViewportChange);
       cm.on("fold", onFold);
       cm.on("unfold", onFold);
@@ -51,8 +51,13 @@
 
   function isFolded(cm, line) {
     var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
-    for (var i = 0; i < marks.length; ++i)
-      if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i];
+    for (var i = 0; i < marks.length; ++i) {
+      if (marks[i].__isFold) {
+        var fromPos = marks[i].find(-1);
+        if (fromPos && fromPos.line === line)
+          return marks[i];
+      }
+    }
   }
 
   function marker(spec) {
@@ -66,24 +71,36 @@
   }
 
   function updateFoldInfo(cm, from, to) {
-    var opts = cm.state.foldGutter.options, cur = from;
+    var opts = cm.state.foldGutter.options, cur = from - 1;
     var minSize = cm.foldOption(opts, "minFoldSize");
     var func = cm.foldOption(opts, "rangeFinder");
+    // we can reuse the built-in indicator element if its className matches the new state
+    var clsFolded = typeof opts.indicatorFolded == "string" && classTest(opts.indicatorFolded);
+    var clsOpen = typeof opts.indicatorOpen == "string" && classTest(opts.indicatorOpen);
     cm.eachLine(from, to, function(line) {
+      ++cur;
       var mark = null;
+      var old = line.gutterMarkers;
+      if (old) old = old[opts.gutter];
       if (isFolded(cm, cur)) {
+        if (clsFolded && old && clsFolded.test(old.className)) return;
         mark = marker(opts.indicatorFolded);
       } else {
         var pos = Pos(cur, 0);
         var range = func && func(cm, pos);
-        if (range && range.to.line - range.from.line >= minSize)
+        if (range && range.to.line - range.from.line >= minSize) {
+          if (clsOpen && old && clsOpen.test(old.className)) return;
           mark = marker(opts.indicatorOpen);
+        }
       }
+      if (!mark && !old) return;
       cm.setGutterMarker(line, opts.gutter, mark);
-      ++cur;
     });
   }
 
+  // copied from CodeMirror/src/util/dom.js
+  function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
+
   function updateInViewport(cm) {
     var vp = cm.getViewport(), state = cm.state.foldGutter;
     if (!state) return;
@@ -100,7 +117,7 @@
     if (gutter != opts.gutter) return;
     var folded = isFolded(cm, line);
     if (folded) folded.clear();
-    else cm.foldCode(Pos(line, 0), opts.rangeFinder);
+    else cm.foldCode(Pos(line, 0), opts);
   }
 
   function onChange(cm) {
diff --git a/src/codemirror/addon/fold/indent-fold.js b/src/assets/plugins/codemirror/addon/fold/indent-fold.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/fold/indent-fold.js
rename to src/assets/plugins/codemirror/addon/fold/indent-fold.js
diff --git a/src/codemirror/addon/fold/markdown-fold.js b/src/assets/plugins/codemirror/addon/fold/markdown-fold.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/fold/markdown-fold.js
rename to src/assets/plugins/codemirror/addon/fold/markdown-fold.js
diff --git a/src/codemirror/addon/fold/xml-fold.js b/src/assets/plugins/codemirror/addon/fold/xml-fold.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/fold/xml-fold.js
rename to src/assets/plugins/codemirror/addon/fold/xml-fold.js
diff --git a/src/codemirror/addon/hint/anyword-hint.js b/src/assets/plugins/codemirror/addon/hint/anyword-hint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/hint/anyword-hint.js
rename to src/assets/plugins/codemirror/addon/hint/anyword-hint.js
diff --git a/src/codemirror/addon/hint/css-hint.js b/src/assets/plugins/codemirror/addon/hint/css-hint.js
old mode 100755
new mode 100644
similarity index 76%
rename from src/codemirror/addon/hint/css-hint.js
rename to src/assets/plugins/codemirror/addon/hint/css-hint.js
index 6cdf728..980d119
--- a/src/codemirror/addon/hint/css-hint.js
+++ b/src/assets/plugins/codemirror/addon/hint/css-hint.js
@@ -11,9 +11,15 @@
 })(function(CodeMirror) {
   "use strict";
 
-  var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
-                       "first-letter": 1, "first-line": 1, "first-child": 1,
-                       before: 1, after: 1, lang: 1};
+  var pseudoClasses = {"active":1, "after":1, "before":1, "checked":1, "default":1,
+    "disabled":1, "empty":1, "enabled":1, "first-child":1, "first-letter":1,
+    "first-line":1, "first-of-type":1, "focus":1, "hover":1, "in-range":1,
+    "indeterminate":1, "invalid":1, "lang":1, "last-child":1, "last-of-type":1,
+    "link":1, "not":1, "nth-child":1, "nth-last-child":1, "nth-last-of-type":1,
+    "nth-of-type":1, "only-of-type":1, "only-child":1, "optional":1, "out-of-range":1,
+    "placeholder":1, "read-only":1, "read-write":1, "required":1, "root":1,
+    "selection":1, "target":1, "valid":1, "visited":1
+  };
 
   CodeMirror.registerHelper("hint", "css", function(cm) {
     var cur = cm.getCursor(), token = cm.getTokenAt(cur);
diff --git a/src/codemirror/addon/hint/html-hint.js b/src/assets/plugins/codemirror/addon/hint/html-hint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/hint/html-hint.js
rename to src/assets/plugins/codemirror/addon/hint/html-hint.js
diff --git a/src/codemirror/addon/hint/javascript-hint.js b/src/assets/plugins/codemirror/addon/hint/javascript-hint.js
old mode 100755
new mode 100644
similarity index 94%
rename from src/codemirror/addon/hint/javascript-hint.js
rename to src/assets/plugins/codemirror/addon/hint/javascript-hint.js
index 96a7fe0..6d09e6b
--- a/src/codemirror/addon/hint/javascript-hint.js
+++ b/src/assets/plugins/codemirror/addon/hint/javascript-hint.js
@@ -144,10 +144,15 @@
         base = base[context.pop().string];
       if (base != null) gatherCompletions(base);
     } else {
-      // If not, just look in the global object and any local scope
+      // If not, just look in the global object, any local scope, and optional additional-context
       // (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 c = token.state.context; c; c = c.prev)
+        for (var v = c.vars; v; v = v.next) maybeAdd(v.name)
       for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
+      if (options && options.additionalContext != null)
+        for (var key in options.additionalContext)
+          maybeAdd(key);
       if (!options || options.useGlobalScope !== false)
         gatherCompletions(global);
       forEach(keywords, maybeAdd);
diff --git a/src/codemirror/addon/hint/show-hint.css b/src/assets/plugins/codemirror/addon/hint/show-hint.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/hint/show-hint.css
rename to src/assets/plugins/codemirror/addon/hint/show-hint.css
diff --git a/src/codemirror/addon/hint/show-hint.js b/src/assets/plugins/codemirror/addon/hint/show-hint.js
old mode 100755
new mode 100644
similarity index 87%
rename from src/codemirror/addon/hint/show-hint.js
rename to src/assets/plugins/codemirror/addon/hint/show-hint.js
index e3cd209..c55deab
--- a/src/codemirror/addon/hint/show-hint.js
+++ b/src/assets/plugins/codemirror/addon/hint/show-hint.js
@@ -85,11 +85,16 @@
     },
 
     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);
+      var completion = data.list[i], self = this;
+      this.cm.operation(function() {
+        if (completion.hint)
+          completion.hint(self.cm, data, completion);
+        else
+          self.cm.replaceRange(getText(completion), completion.from || data.from,
+                               completion.to || data.to, "complete");
+        CodeMirror.signal(data, "pick", completion);
+        self.cm.scrollIntoView();
+      })
       this.close();
     },
 
@@ -99,9 +104,14 @@
         this.debounce = 0;
       }
 
+      var identStart = this.startPos;
+      if(this.data) {
+        identStart = this.data.from;
+      }
+
       var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
       if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
-          pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
+          pos.ch < identStart.ch || this.cm.somethingSelected() ||
           (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
         this.close();
       } else {
@@ -229,14 +239,26 @@
       elt.hintId = i;
     }
 
+    var container = completion.options.container || ownerDocument.body;
     var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
     var left = pos.left, top = pos.bottom, below = true;
-    hints.style.left = left + "px";
-    hints.style.top = top + "px";
+    var offsetLeft = 0, offsetTop = 0;
+    if (container !== ownerDocument.body) {
+      // We offset the cursor position because left and top are relative to the offsetParent's top left corner.
+      var isContainerPositioned = ['absolute', 'relative', 'fixed'].indexOf(parentWindow.getComputedStyle(container).position) !== -1;
+      var offsetParent = isContainerPositioned ? container : container.offsetParent;
+      var offsetParentPosition = offsetParent.getBoundingClientRect();
+      var bodyPosition = ownerDocument.body.getBoundingClientRect();
+      offsetLeft = (offsetParentPosition.left - bodyPosition.left - offsetParent.scrollLeft);
+      offsetTop = (offsetParentPosition.top - bodyPosition.top - offsetParent.scrollTop);
+    }
+    hints.style.left = (left - offsetLeft) + "px";
+    hints.style.top = (top - offsetTop) + "px";
+
     // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
     var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
     var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
-    (completion.options.container || ownerDocument.body).appendChild(hints);
+    container.appendChild(hints);
     var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
     var scrolls = hints.scrollHeight > hints.clientHeight + 1
     var startScroll = cm.getScrollInfo();
@@ -244,15 +266,15 @@
     if (overlapY > 0) {
       var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
       if (curTop - height > 0) { // Fits above cursor
-        hints.style.top = (top = pos.top - height) + "px";
+        hints.style.top = (top = pos.top - height - offsetTop) + "px";
         below = false;
       } else if (height > winH) {
         hints.style.height = (winH - 5) + "px";
-        hints.style.top = (top = pos.bottom - box.top) + "px";
+        hints.style.top = (top = pos.bottom - box.top - offsetTop) + "px";
         var cursor = cm.getCursor();
         if (data.from.ch != cursor.ch) {
           pos = cm.cursorCoords(cursor);
-          hints.style.left = (left = pos.left) + "px";
+          hints.style.left = (left = pos.left - offsetLeft) + "px";
           box = hints.getBoundingClientRect();
         }
       }
@@ -263,7 +285,7 @@
         hints.style.width = (winW - 5) + "px";
         overlapX -= (box.right - box.left) - winW;
       }
-      hints.style.left = (left = pos.left - overlapX) + "px";
+      hints.style.left = (left = pos.left - overlapX - offsetLeft) + "px";
     }
     if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
       node.style.paddingRight = cm.display.nativeBarWidth + "px"
@@ -310,6 +332,7 @@
     CodeMirror.on(hints, "mousedown", function() {
       setTimeout(function(){cm.focus();}, 20);
     });
+    this.scrollToActive()
 
     CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
     return true;
@@ -351,13 +374,19 @@
       if (node) 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;
+      this.scrollToActive()
       CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
     },
 
+    scrollToActive: function() {
+      var node = this.hints.childNodes[this.selectedHint]
+      var firstNode = this.hints.firstChild;
+      if (node.offsetTop < this.hints.scrollTop)
+        this.hints.scrollTop = node.offsetTop - firstNode.offsetTop;
+      else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
+        this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
+    },
+
     screenAmount: function() {
       return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
     }
diff --git a/src/codemirror/addon/hint/sql-hint.js b/src/assets/plugins/codemirror/addon/hint/sql-hint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/hint/sql-hint.js
rename to src/assets/plugins/codemirror/addon/hint/sql-hint.js
diff --git a/src/codemirror/addon/hint/xml-hint.js b/src/assets/plugins/codemirror/addon/hint/xml-hint.js
old mode 100755
new mode 100644
similarity index 88%
rename from src/codemirror/addon/hint/xml-hint.js
rename to src/assets/plugins/codemirror/addon/hint/xml-hint.js
index 106ba4f..7575b37
--- a/src/codemirror/addon/hint/xml-hint.js
+++ b/src/assets/plugins/codemirror/addon/hint/xml-hint.js
@@ -29,7 +29,7 @@
       token.string = token.string.slice(0, cur.ch - token.start);
     }
     var inner = CodeMirror.innerMode(cm.getMode(), token.state);
-    if (inner.mode.name != "xml") return;
+    if (!inner.mode.xmlCurrentTag) return
     var result = [], replaceToken = false, prefix;
     var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
     var tagName = tag && /^\w/.test(token.string), tagStart;
@@ -44,12 +44,15 @@
       tagType = "close";
     }
 
-    if (!tag && !inner.state.tagName || tagType) {
+    var tagInfo = inner.mode.xmlCurrentTag(inner.state)
+    if (!tag && !tagInfo || tagType) {
       if (tagName)
         prefix = token.string;
       replaceToken = tagType;
-      var cx = inner.state.context, curTag = cx && tags[cx.tagName];
-      var childList = cx ? curTag && curTag.children : tags["!top"];
+      var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
+      var inner = context.length && context[context.length - 1]
+      var curTag = inner && tags[inner]
+      var childList = inner ? curTag && curTag.children : tags["!top"];
       if (childList && tagType != "close") {
         for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
           result.push("<" + childList[i]);
@@ -58,11 +61,11 @@
           if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
             result.push("<" + name);
       }
-      if (cx && (!prefix || tagType == "close" && matches(cx.tagName, prefix, matchInMiddle)))
-        result.push("");
+      if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
+        result.push("");
     } else {
       // Attribute completion
-      var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
+      var curTag = tagInfo && tags[tagInfo.name], attrs = curTag && curTag.attrs;
       var globalAttrs = tags["!attrs"];
       if (!attrs && !globalAttrs) return;
       if (!attrs) {
diff --git a/src/codemirror/addon/lint/coffeescript-lint.js b/src/assets/plugins/codemirror/addon/lint/coffeescript-lint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/lint/coffeescript-lint.js
rename to src/assets/plugins/codemirror/addon/lint/coffeescript-lint.js
diff --git a/src/codemirror/addon/lint/css-lint.js b/src/assets/plugins/codemirror/addon/lint/css-lint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/lint/css-lint.js
rename to src/assets/plugins/codemirror/addon/lint/css-lint.js
diff --git a/src/codemirror/addon/lint/html-lint.js b/src/assets/plugins/codemirror/addon/lint/html-lint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/lint/html-lint.js
rename to src/assets/plugins/codemirror/addon/lint/html-lint.js
diff --git a/src/codemirror/addon/lint/javascript-lint.js b/src/assets/plugins/codemirror/addon/lint/javascript-lint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/lint/javascript-lint.js
rename to src/assets/plugins/codemirror/addon/lint/javascript-lint.js
diff --git a/src/codemirror/addon/lint/json-lint.js b/src/assets/plugins/codemirror/addon/lint/json-lint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/lint/json-lint.js
rename to src/assets/plugins/codemirror/addon/lint/json-lint.js
diff --git a/src/codemirror/addon/lint/lint.css b/src/assets/plugins/codemirror/addon/lint/lint.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/lint/lint.css
rename to src/assets/plugins/codemirror/addon/lint/lint.css
diff --git a/src/codemirror/addon/lint/lint.js b/src/assets/plugins/codemirror/addon/lint/lint.js
old mode 100755
new mode 100644
similarity index 90%
rename from src/codemirror/addon/lint/lint.js
rename to src/assets/plugins/codemirror/addon/lint/lint.js
index aa75ba0..5bc1af1
--- a/src/codemirror/addon/lint/lint.js
+++ b/src/assets/plugins/codemirror/addon/lint/lint.js
@@ -12,11 +12,14 @@
   "use strict";
   var GUTTER_ID = "CodeMirror-lint-markers";
 
-  function showTooltip(e, content) {
+  function showTooltip(cm, e, content) {
     var tt = document.createElement("div");
-    tt.className = "CodeMirror-lint-tooltip";
+    tt.className = "CodeMirror-lint-tooltip cm-s-" + cm.options.theme;
     tt.appendChild(content.cloneNode(true));
-    document.body.appendChild(tt);
+    if (cm.state.lint.options.selfContain)
+      cm.getWrapperElement().appendChild(tt);
+    else
+      document.body.appendChild(tt);
 
     function position(e) {
       if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
@@ -38,8 +41,8 @@
     setTimeout(function() { rm(tt); }, 600);
   }
 
-  function showTooltipFor(e, content, node) {
-    var tooltip = showTooltip(e, content);
+  function showTooltipFor(cm, e, content, node) {
+    var tooltip = showTooltip(cm, e, content);
     function hide() {
       CodeMirror.off(node, "mouseout", hide);
       if (tooltip) { hideTooltip(tooltip); tooltip = null; }
@@ -78,7 +81,7 @@
     state.marked.length = 0;
   }
 
-  function makeMarker(labels, severity, multiple, tooltips) {
+  function makeMarker(cm, labels, severity, multiple, tooltips) {
     var marker = document.createElement("div"), inner = marker;
     marker.className = "CodeMirror-lint-marker-" + severity;
     if (multiple) {
@@ -87,7 +90,7 @@
     }
 
     if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
-      showTooltipFor(e, labels, inner);
+      showTooltipFor(cm, e, labels, inner);
     });
 
     return marker;
@@ -113,9 +116,9 @@
     var tip = document.createElement("div");
     tip.className = "CodeMirror-lint-message-" + severity;
     if (typeof ann.messageHTML != 'undefined') {
-        tip.innerHTML = ann.messageHTML;
+      tip.innerHTML = ann.messageHTML;
     } else {
-        tip.appendChild(document.createTextNode(ann.message));
+      tip.appendChild(document.createTextNode(ann.message));
     }
     return tip;
   }
@@ -186,7 +189,7 @@
       }
 
       if (state.hasGutter)
-        cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
+        cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, anns.length > 1,
                                                        state.options.tooltips));
     }
     if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
@@ -199,14 +202,14 @@
     state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
   }
 
-  function popupTooltips(annotations, e) {
+  function popupTooltips(cm, annotations, e) {
     var target = e.target || e.srcElement;
     var tooltip = document.createDocumentFragment();
     for (var i = 0; i < annotations.length; i++) {
       var ann = annotations[i];
       tooltip.appendChild(annotationTooltip(ann));
     }
-    showTooltipFor(e, tooltip, target);
+    showTooltipFor(cm, e, tooltip, target);
   }
 
   function onMouseOver(cm, e) {
@@ -220,7 +223,7 @@
       var ann = spans[i].__annotation;
       if (ann) annotations.push(ann);
     }
-    if (annotations.length) popupTooltips(annotations, e);
+    if (annotations.length) popupTooltips(cm, annotations, e);
   }
 
   CodeMirror.defineOption("lint", false, function(cm, val, old) {
diff --git a/src/codemirror/addon/lint/yaml-lint.js b/src/assets/plugins/codemirror/addon/lint/yaml-lint.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/lint/yaml-lint.js
rename to src/assets/plugins/codemirror/addon/lint/yaml-lint.js
diff --git a/src/codemirror/addon/merge/merge.css b/src/assets/plugins/codemirror/addon/merge/merge.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/merge/merge.css
rename to src/assets/plugins/codemirror/addon/merge/merge.css
diff --git a/src/codemirror/addon/merge/merge.js b/src/assets/plugins/codemirror/addon/merge/merge.js
old mode 100755
new mode 100644
similarity index 98%
rename from src/codemirror/addon/merge/merge.js
rename to src/assets/plugins/codemirror/addon/merge/merge.js
index 63373f7..827edb7
--- a/src/codemirror/addon/merge/merge.js
+++ b/src/assets/plugins/codemirror/addon/merge/merge.js
@@ -443,22 +443,26 @@
       aligners[i].clear();
     aligners.length = 0;
 
-    var cm = [dv.edit, dv.orig], scroll = [];
+    var cm = [dv.edit, dv.orig], scroll = [], offset = []
     if (other) cm.push(other.orig);
-    for (var i = 0; i < cm.length; i++)
+    for (var i = 0; i < cm.length; i++) {
       scroll.push(cm[i].getScrollInfo().top);
+      offset.push(-cm[i].getScrollerElement().getBoundingClientRect().top)
+    }
 
+    if (offset[0] != offset[1] || cm.length == 3 && offset[1] != offset[2])
+      alignLines(cm, offset, [0, 0, 0], aligners)
     for (var ln = 0; ln < linesToAlign.length; ln++)
-      alignLines(cm, linesToAlign[ln], aligners);
+      alignLines(cm, offset, linesToAlign[ln], aligners);
 
     for (var i = 0; i < cm.length; i++)
       cm[i].scrollTo(null, scroll[i]);
   }
 
-  function alignLines(cm, lines, aligners) {
-    var maxOffset = 0, offset = [];
+  function alignLines(cm, cmOffset, lines, aligners) {
+    var maxOffset = -1e8, offset = [];
     for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
-      var off = cm[i].heightAtLine(lines[i], "local");
+      var off = cm[i].heightAtLine(lines[i], "local") - cmOffset[i];
       offset[i] = off;
       maxOffset = Math.max(maxOffset, off);
     }
@@ -918,7 +922,7 @@
     hasMarker: function(n) {
       var handle = this.cm.getLineHandle(n)
       if (handle.markedSpans) for (var i = 0; i < handle.markedSpans.length; i++)
-        if (handle.markedSpans[i].mark.collapsed && handle.markedSpans[i].to != null)
+        if (handle.markedSpans[i].marker.collapsed && handle.markedSpans[i].to != null)
           return true
       return false
     },
diff --git a/src/codemirror/addon/mode/loadmode.js b/src/assets/plugins/codemirror/addon/mode/loadmode.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/mode/loadmode.js
rename to src/assets/plugins/codemirror/addon/mode/loadmode.js
diff --git a/src/codemirror/addon/mode/multiplex.js b/src/assets/plugins/codemirror/addon/mode/multiplex.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/mode/multiplex.js
rename to src/assets/plugins/codemirror/addon/mode/multiplex.js
diff --git a/src/codemirror/addon/mode/multiplex_test.js b/src/assets/plugins/codemirror/addon/mode/multiplex_test.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/mode/multiplex_test.js
rename to src/assets/plugins/codemirror/addon/mode/multiplex_test.js
diff --git a/src/codemirror/addon/mode/overlay.js b/src/assets/plugins/codemirror/addon/mode/overlay.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/mode/overlay.js
rename to src/assets/plugins/codemirror/addon/mode/overlay.js
diff --git a/src/codemirror/addon/mode/simple.js b/src/assets/plugins/codemirror/addon/mode/simple.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/mode/simple.js
rename to src/assets/plugins/codemirror/addon/mode/simple.js
diff --git a/src/codemirror/addon/runmode/colorize.js b/src/assets/plugins/codemirror/addon/runmode/colorize.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/runmode/colorize.js
rename to src/assets/plugins/codemirror/addon/runmode/colorize.js
diff --git a/src/codemirror/addon/runmode/runmode-standalone.js b/src/assets/plugins/codemirror/addon/runmode/runmode-standalone.js
old mode 100755
new mode 100644
similarity index 88%
rename from src/codemirror/addon/runmode/runmode-standalone.js
rename to src/assets/plugins/codemirror/addon/runmode/runmode-standalone.js
index 745eaf8..f47af3f
--- a/src/codemirror/addon/runmode/runmode-standalone.js
+++ b/src/assets/plugins/codemirror/addon/runmode/runmode-standalone.js
@@ -1,16 +1,19 @@
 // CodeMirror, copyright (c) by Marijn Haverbeke and others
 // Distributed under an MIT license: https://codemirror.net/LICENSE
 
-window.CodeMirror = {};
+var root = typeof globalThis !== 'undefined' ? globalThis : window;
+root.CodeMirror = {};
 
 (function() {
 "use strict";
 
 function splitLines(string){ return string.split(/\r?\n|\r/); };
 
-function StringStream(string) {
+function StringStream(strings, i) {
   this.pos = this.start = 0;
-  this.string = string;
+  this.string = strings[i];
+  this.strings = strings
+  this.i = i
   this.lineStart = 0;
 }
 StringStream.prototype = {
@@ -66,7 +69,7 @@ StringStream.prototype = {
     try { return inner(); }
     finally { this.lineStart -= n; }
   },
-  lookAhead: function() { return null }
+  lookAhead: function(n) { return this.strings[this.i + n] }
 };
 CodeMirror.StringStream = StringStream;
 
@@ -104,14 +107,18 @@ CodeMirror.defineMIME("text/plain", "null");
 
 CodeMirror.runMode = function (string, modespec, callback, options) {
   var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
+  var ie = /MSIE \d/.test(navigator.userAgent);
+  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
 
-  if (callback.nodeType == 1) {
+  if (callback.appendChild) {
     var tabSize = (options && options.tabSize) || 4;
     var node = callback, col = 0;
     node.innerHTML = "";
     callback = function (text, style) {
       if (text == "\n") {
-        node.appendChild(document.createElement("br"));
+        // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
+        // Emitting a carriage return makes everything ok.
+        node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
         col = 0;
         return;
       }
@@ -146,7 +153,7 @@ CodeMirror.runMode = function (string, modespec, callback, options) {
   var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
   for (var i = 0, e = lines.length; i < e; ++i) {
     if (i) callback("\n");
-    var stream = new CodeMirror.StringStream(lines[i]);
+    var stream = new CodeMirror.StringStream(lines, i);
     if (!stream.string && mode.blankLine) mode.blankLine(state);
     while (!stream.eol()) {
       var style = mode.token(stream, state);
diff --git a/src/codemirror/addon/runmode/runmode.js b/src/assets/plugins/codemirror/addon/runmode/runmode.js
old mode 100755
new mode 100644
similarity index 94%
rename from src/codemirror/addon/runmode/runmode.js
rename to src/assets/plugins/codemirror/addon/runmode/runmode.js
index eb4cadf..ca8d9a9
--- a/src/codemirror/addon/runmode/runmode.js
+++ b/src/assets/plugins/codemirror/addon/runmode/runmode.js
@@ -59,7 +59,10 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
   var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
   for (var i = 0, e = lines.length; i < e; ++i) {
     if (i) callback("\n");
-    var stream = new CodeMirror.StringStream(lines[i]);
+    var stream = new CodeMirror.StringStream(lines[i], null, {
+      lookAhead: function(n) { return lines[i + n] },
+      baseToken: function() {}
+    });
     if (!stream.string && mode.blankLine) mode.blankLine(state);
     while (!stream.eol()) {
       var style = mode.token(stream, state);
diff --git a/src/codemirror/addon/runmode/runmode.node.js b/src/assets/plugins/codemirror/addon/runmode/runmode.node.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/runmode/runmode.node.js
rename to src/assets/plugins/codemirror/addon/runmode/runmode.node.js
diff --git a/src/codemirror/addon/scroll/annotatescrollbar.js b/src/assets/plugins/codemirror/addon/scroll/annotatescrollbar.js
old mode 100755
new mode 100644
similarity index 97%
rename from src/codemirror/addon/scroll/annotatescrollbar.js
rename to src/assets/plugins/codemirror/addon/scroll/annotatescrollbar.js
index 3566258..9fe61ec
--- a/src/codemirror/addon/scroll/annotatescrollbar.js
+++ b/src/assets/plugins/codemirror/addon/scroll/annotatescrollbar.js
@@ -43,7 +43,7 @@
     cm.on("markerAdded", this.resizeHandler);
     cm.on("markerCleared", this.resizeHandler);
     if (options.listenForChanges !== false)
-      cm.on("change", this.changeHandler = function() {
+      cm.on("changes", this.changeHandler = function() {
         scheduleRedraw(250);
       });
   }
@@ -116,7 +116,7 @@
     this.cm.off("refresh", this.resizeHandler);
     this.cm.off("markerAdded", this.resizeHandler);
     this.cm.off("markerCleared", this.resizeHandler);
-    if (this.changeHandler) this.cm.off("change", this.changeHandler);
+    if (this.changeHandler) this.cm.off("changes", this.changeHandler);
     this.div.parentNode.removeChild(this.div);
   };
 });
diff --git a/src/codemirror/addon/scroll/scrollpastend.js b/src/assets/plugins/codemirror/addon/scroll/scrollpastend.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/scroll/scrollpastend.js
rename to src/assets/plugins/codemirror/addon/scroll/scrollpastend.js
diff --git a/src/codemirror/addon/scroll/simplescrollbars.css b/src/assets/plugins/codemirror/addon/scroll/simplescrollbars.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/scroll/simplescrollbars.css
rename to src/assets/plugins/codemirror/addon/scroll/simplescrollbars.css
diff --git a/src/codemirror/addon/scroll/simplescrollbars.js b/src/assets/plugins/codemirror/addon/scroll/simplescrollbars.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/scroll/simplescrollbars.js
rename to src/assets/plugins/codemirror/addon/scroll/simplescrollbars.js
diff --git a/src/codemirror/addon/search/jump-to-line.js b/src/assets/plugins/codemirror/addon/search/jump-to-line.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/search/jump-to-line.js
rename to src/assets/plugins/codemirror/addon/search/jump-to-line.js
diff --git a/src/codemirror/addon/search/match-highlighter.js b/src/assets/plugins/codemirror/addon/search/match-highlighter.js
old mode 100755
new mode 100644
similarity index 95%
rename from src/codemirror/addon/search/match-highlighter.js
rename to src/assets/plugins/codemirror/addon/search/match-highlighter.js
index b344ac7..3a4a7de
--- a/src/codemirror/addon/search/match-highlighter.js
+++ b/src/assets/plugins/codemirror/addon/search/match-highlighter.js
@@ -90,7 +90,9 @@
     var state = cm.state.matchHighlighter;
     cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
     if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
-      var searchFor = hasBoundary ? new RegExp("\\b" + query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") + "\\b") : query;
+      var searchFor = hasBoundary ? new RegExp((/\w/.test(query.charAt(0)) ? "\\b" : "") +
+                                               query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") +
+                                               (/\w/.test(query.charAt(query.length - 1)) ? "\\b" : "")) : query;
       state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
         {className: "CodeMirror-selection-highlight-scrollbar"});
     }
diff --git a/src/codemirror/addon/search/matchesonscrollbar.css b/src/assets/plugins/codemirror/addon/search/matchesonscrollbar.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/search/matchesonscrollbar.css
rename to src/assets/plugins/codemirror/addon/search/matchesonscrollbar.css
diff --git a/src/codemirror/addon/search/matchesonscrollbar.js b/src/assets/plugins/codemirror/addon/search/matchesonscrollbar.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/search/matchesonscrollbar.js
rename to src/assets/plugins/codemirror/addon/search/matchesonscrollbar.js
diff --git a/src/codemirror/addon/search/search.js b/src/assets/plugins/codemirror/addon/search/search.js
old mode 100755
new mode 100644
similarity index 98%
rename from src/codemirror/addon/search/search.js
rename to src/assets/plugins/codemirror/addon/search/search.js
index 5c2559c..cecdd52
--- a/src/codemirror/addon/search/search.js
+++ b/src/assets/plugins/codemirror/addon/search/search.js
@@ -78,10 +78,12 @@
   }
 
   function parseString(string) {
-    return string.replace(/\\(.)/g, function(_, ch) {
+    return string.replace(/\\([nrt\\])/g, function(match, ch) {
       if (ch == "n") return "\n"
       if (ch == "r") return "\r"
-      return ch
+      if (ch == "t") return "\t"
+      if (ch == "\\") return "\\"
+      return match
     })
   }
 
diff --git a/src/codemirror/addon/search/searchcursor.js b/src/assets/plugins/codemirror/addon/search/searchcursor.js
old mode 100755
new mode 100644
similarity index 92%
rename from src/codemirror/addon/search/searchcursor.js
rename to src/assets/plugins/codemirror/addon/search/searchcursor.js
index aae36df..d586957
--- a/src/codemirror/addon/search/searchcursor.js
+++ b/src/assets/plugins/codemirror/addon/search/searchcursor.js
@@ -72,24 +72,26 @@
     }
   }
 
-  function lastMatchIn(string, regexp) {
-    var cutOff = 0, match
-    for (;;) {
-      regexp.lastIndex = cutOff
+  function lastMatchIn(string, regexp, endMargin) {
+    var match, from = 0
+    while (from <= string.length) {
+      regexp.lastIndex = from
       var newMatch = regexp.exec(string)
-      if (!newMatch) return match
-      match = newMatch
-      cutOff = match.index + (match[0].length || 1)
-      if (cutOff == string.length) return match
+      if (!newMatch) break
+      var end = newMatch.index + newMatch[0].length
+      if (end > string.length - endMargin) break
+      if (!match || end > match.index + match[0].length)
+        match = newMatch
+      from = newMatch.index + 1
     }
+    return match
   }
 
   function searchRegexpBackward(doc, regexp, start) {
     regexp = ensureFlags(regexp, "g")
     for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
       var string = doc.getLine(line)
-      if (ch > -1) string = string.slice(0, ch)
-      var match = lastMatchIn(string, regexp)
+      var match = lastMatchIn(string, regexp, ch < 0 ? 0 : string.length - ch)
       if (match)
         return {from: Pos(line, match.index),
                 to: Pos(line, match.index + match[0].length),
@@ -98,16 +100,17 @@
   }
 
   function searchRegexpBackwardMultiline(doc, regexp, start) {
+    if (!maybeMultiline(regexp)) return searchRegexpBackward(doc, regexp, start)
     regexp = ensureFlags(regexp, "gm")
-    var string, chunk = 1
+    var string, chunkSize = 1, endMargin = doc.getLine(start.line).length - start.ch
     for (var line = start.line, first = doc.firstLine(); line >= first;) {
-      for (var i = 0; i < chunk; i++) {
+      for (var i = 0; i < chunkSize && line >= first; i++) {
         var curLine = doc.getLine(line--)
-        string = string == null ? curLine.slice(0, start.ch) : curLine + "\n" + string
+        string = string == null ? curLine : curLine + "\n" + string
       }
-      chunk *= 2
+      chunkSize *= 2
 
-      var match = lastMatchIn(string, regexp)
+      var match = lastMatchIn(string, regexp, endMargin)
       if (match) {
         var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n")
         var startLine = line + before.length, startCh = before[before.length - 1].length
@@ -237,7 +240,7 @@
       var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to))
 
       // Implements weird auto-growing behavior on null-matches for
-      // backwards-compatiblity with the vim code (unfortunately)
+      // backwards-compatibility with the vim code (unfortunately)
       while (result && CodeMirror.cmpPos(result.from, result.to) == 0) {
         if (reverse) {
           if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1)
diff --git a/src/codemirror/addon/selection/active-line.js b/src/assets/plugins/codemirror/addon/selection/active-line.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/selection/active-line.js
rename to src/assets/plugins/codemirror/addon/selection/active-line.js
diff --git a/src/codemirror/addon/selection/mark-selection.js b/src/assets/plugins/codemirror/addon/selection/mark-selection.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/selection/mark-selection.js
rename to src/assets/plugins/codemirror/addon/selection/mark-selection.js
diff --git a/src/codemirror/addon/selection/selection-pointer.js b/src/assets/plugins/codemirror/addon/selection/selection-pointer.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/selection/selection-pointer.js
rename to src/assets/plugins/codemirror/addon/selection/selection-pointer.js
diff --git a/src/codemirror/addon/tern/tern.css b/src/assets/plugins/codemirror/addon/tern/tern.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/tern/tern.css
rename to src/assets/plugins/codemirror/addon/tern/tern.css
diff --git a/src/codemirror/addon/tern/tern.js b/src/assets/plugins/codemirror/addon/tern/tern.js
old mode 100755
new mode 100644
similarity index 98%
rename from src/codemirror/addon/tern/tern.js
rename to src/assets/plugins/codemirror/addon/tern/tern.js
index 253309d..7be3681
--- a/src/codemirror/addon/tern/tern.js
+++ b/src/assets/plugins/codemirror/addon/tern/tern.js
@@ -231,7 +231,7 @@
         var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
         if (content) {
           tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
-                                node.getBoundingClientRect().top + window.pageYOffset, content);
+                                node.getBoundingClientRect().top + window.pageYOffset, content, cm);
           tooltip.className += " " + cls + "hint-doc";
         }
       });
@@ -334,7 +334,7 @@
     tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
     if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
     var place = cm.cursorCoords(null, "page");
-    var tooltip = ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip)
+    var tooltip = ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip, cm)
     setTimeout(function() {
       tooltip.clear = onEditorActivity(cm, function() {
         if (ts.activeArgHints == tooltip) closeArgHints(ts) })
@@ -601,7 +601,7 @@
   function tempTooltip(cm, content, ts) {
     if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
     var where = cm.cursorCoords();
-    var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content);
+    var tip = cm.state.ternTooltip = makeTooltip(where.right + 1, where.bottom, content, cm);
     function maybeClear() {
       old = true;
       if (!mouseOnTip) clear();
@@ -637,11 +637,12 @@
     }
   }
 
-  function makeTooltip(x, y, content) {
+  function makeTooltip(x, y, content, cm) {
     var node = elt("div", cls + "tooltip", content);
     node.style.left = x + "px";
     node.style.top = y + "px";
-    document.body.appendChild(node);
+    var container = ((cm.options || {}).hintOptions || {}).container || document.body;
+    container.appendChild(node);
     return node;
   }
 
diff --git a/src/codemirror/addon/tern/worker.js b/src/assets/plugins/codemirror/addon/tern/worker.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/tern/worker.js
rename to src/assets/plugins/codemirror/addon/tern/worker.js
diff --git a/src/codemirror/addon/wrap/hardwrap.js b/src/assets/plugins/codemirror/addon/wrap/hardwrap.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/addon/wrap/hardwrap.js
rename to src/assets/plugins/codemirror/addon/wrap/hardwrap.js
diff --git a/src/codemirror/bin/authors.sh b/src/assets/plugins/codemirror/bin/authors.sh
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/bin/authors.sh
rename to src/assets/plugins/codemirror/bin/authors.sh
diff --git a/src/codemirror/bin/lint b/src/assets/plugins/codemirror/bin/lint
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/bin/lint
rename to src/assets/plugins/codemirror/bin/lint
diff --git a/src/codemirror/bin/release b/src/assets/plugins/codemirror/bin/release
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/bin/release
rename to src/assets/plugins/codemirror/bin/release
diff --git a/src/codemirror/bin/source-highlight b/src/assets/plugins/codemirror/bin/source-highlight
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/bin/source-highlight
rename to src/assets/plugins/codemirror/bin/source-highlight
diff --git a/src/codemirror/bin/upload-release.js b/src/assets/plugins/codemirror/bin/upload-release.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/bin/upload-release.js
rename to src/assets/plugins/codemirror/bin/upload-release.js
diff --git a/src/codemirror/doc/activebookmark.js b/src/assets/plugins/codemirror/doc/activebookmark.js
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/doc/activebookmark.js
rename to src/assets/plugins/codemirror/doc/activebookmark.js
diff --git a/src/codemirror/doc/docs.css b/src/assets/plugins/codemirror/doc/docs.css
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/doc/docs.css
rename to src/assets/plugins/codemirror/doc/docs.css
diff --git a/src/codemirror/doc/internals.html b/src/assets/plugins/codemirror/doc/internals.html
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/doc/internals.html
rename to src/assets/plugins/codemirror/doc/internals.html
diff --git a/src/codemirror/doc/logo.png b/src/assets/plugins/codemirror/doc/logo.png
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/doc/logo.png
rename to src/assets/plugins/codemirror/doc/logo.png
diff --git a/src/codemirror/doc/logo.svg b/src/assets/plugins/codemirror/doc/logo.svg
old mode 100755
new mode 100644
similarity index 100%
rename from src/codemirror/doc/logo.svg
rename to src/assets/plugins/codemirror/doc/logo.svg
diff --git a/src/codemirror/doc/manual.html b/src/assets/plugins/codemirror/doc/manual.html
old mode 100755
new mode 100644
similarity index 96%
rename from src/codemirror/doc/manual.html
rename to src/assets/plugins/codemirror/doc/manual.html
index f7271e2..e8acb01
--- a/src/codemirror/doc/manual.html
+++ b/src/assets/plugins/codemirror/doc/manual.html
@@ -69,7 +69,7 @@
 

User manual and reference guide - version 5.46.0 + version 5.54.0

CodeMirror is a code-editor component that can be embedded in @@ -223,9 +223,10 @@ first mode that was loaded. It may be a string, which either simply names the mode or is a MIME type - associated with the mode. Alternatively, it may be an object - containing configuration options for the mode, with - a name property that names the mode (for + associated with the mode. The value "null" + indicates no highlighting should be applied. Alternatively, it + may be an object containing configuration options for the mode, + with a name property that names the mode (for example {name: "javascript", json: true}). The demo pages for each mode contain information about what configuration parameters the mode supports. You can ask CodeMirror which modes @@ -284,7 +285,7 @@ should be replaced by a special placeholder. Mostly useful for non-printing special characters. The default - is /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/. + is /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/.

specialCharPlaceholder: function(char) → Element
A function that, given a special character identified by the specialChars @@ -420,6 +421,10 @@ simply true), focusing of the editor is also disallowed.
+
screenReaderLabel: string
+
This label is read by the screenreaders when CodeMirror text area is focused. This + is helpful for accessibility.
+
showCursorWhenSelecting: boolean
Whether the cursor should be drawn when a selection is active. Defaults to false.
@@ -557,13 +562,13 @@ always rendered, and thus the browser's text search works on it. This will have bad effects on performance of big documents. - +
spellcheck: boolean
Specifies whether or not spellcheck will be enabled on the input.
- +
autocorrect: boolean
Specifies whether or not autocorrect will be enabled on the input.
- +
autocapitalize: boolean
Specifies whether or not autocapitalization will be enabled on the input.
@@ -1674,13 +1679,21 @@ editor.setOption("extraKeys", {
inclusiveRight: boolean
Like inclusiveLeft, but for the right side.
+
selectLeft: boolean
+
For atomic ranges, determines whether the cursor is allowed + to be placed directly to the left of the range. Has no effect on + non-atomic ranges.
+
selectRight: boolean
+
Like selectLeft, + but for the right side.
atomic: boolean
Atomic ranges act as a single unit when cursor movement is concerned—i.e. it is impossible to place the cursor inside of - them. In atomic ranges, inclusiveLeft - and inclusiveRight have a different meaning—they - will prevent the cursor from being placed respectively - directly before and directly after the range.
+ them. You can control whether the cursor is allowed to be placed + directly before or after them using selectLeft + or selectRight. If selectLeft + (or right) is not provided, then inclusiveLeft (or + right) will control this behavior.
collapsed: boolean
Collapsed ranges do not show up in the display. Setting a range to be collapsed will automatically make it atomic.
@@ -1872,6 +1885,9 @@ editor.setOption("extraKeys", { position (zero for the top, N to put it after the Nth other widget). Note that this only has effect once, when the widget is created. +
className: string
+
Add an extra CSS class name to the wrapper element + created for the widget.
Note that the widget node will become a descendant of nodes with CodeMirror-specific CSS classes, and those classes might in some @@ -2555,10 +2571,14 @@ editor.setOption("extraKeys", { and CodeMirror.fold.xml, for XML-style languages, and CodeMirror.fold.comment, for folding comment blocks. -
widget: string|Element
+
widget: string | Element | fn(from: Pos, to: Pos) → string|Element
The widget to show for folded ranges. Can be either a string, in which case it'll become a span with - class CodeMirror-foldmarker, or a DOM node.
+ class CodeMirror-foldmarker, or a DOM node. + To dynamically generate the widget, this can be a function + that returns a string or DOM node, which will then render + as described. The function will be invoked with parameters + identifying the range to be folded.
scanUp: boolean
When true (default is false), the addon will try to find foldable ranges on the lines above the current one if there @@ -2895,6 +2915,7 @@ editor.setOption("extraKeys", { will only be executed when the promise resolves. By default, the linter will run (debounced) whenever the document is changed. You can pass a lintOnChange: false option to disable that. + You can pass a selfContain: true option to render the tooltip inside the editor instance. Depends on addon/lint/lint.css. A demo can be found here.
@@ -3162,14 +3183,14 @@ editor.setOption("extraKeys", {
tern/tern.js
Provides integration with - the Tern JavaScript analysis + the Tern JavaScript analysis engine, for completion, definition finding, and minor refactoring help. See the demo for a very simple integration. For more involved scenarios, see the comments at the top of the addon and the implementation of the - (multi-file) demonstration + (multi-file) demonstration on the Tern website.
@@ -3509,6 +3530,26 @@ editor.setOption("extraKeys", { extras.isEdit is applicable only to actions, determining whether it is recorded for replay for the . single-repeat command. + +
unmap(lhs: string, ctx: string)
+
+ Remove the command lhs if it is a user defined command. + If the command is an Ex to Ex or Ex to key mapping then the context + must be undefined or false. +
+ +
mapclear(ctx: string)
+
+ Remove all user-defined mappings for the provided context. +
+ +
noremap(lhs: string, rhs: string, ctx: {string, array<string>})
+
+ Non-recursive map function. This will not create mappings to key maps + that aren't present in the default key map. + If no context is provided then the mapping will be applied to each of + normal, insert, and visual mode. +

Extending VIM

@@ -3574,7 +3615,74 @@ editor.setOption("extraKeys", { command was prefixed with a line range, params.line and params.lineEnd will - be set. + be set. + +
getRegisterController()
+
Returns the RegisterController that manages the state of registers + used by vim mode. For the RegisterController api see its + defintion here. +
+ +
buildKeyMap()
+
+ Not currently implemented. If you would like to contribute this please open + a pull request on Github. +
+ +
defineRegister()
+
Defines an external register. The name should be a single character + that will be used to reference the register. The register should support + setText, pushText, clear, and toString. + See Register for a reference implementation. +
+ +
getVimGlobalState_()
+
+ Return a reference to the VimGlobalState. +
+ +
resetVimGlobalState_()
+
+ Reset the default values of the VimGlobalState to fresh values. Any options + set with setOption will also be applied to the reset global state. +
+ +
maybeInitVimState_(cm: CodeMirror)
+
+ Initialize cm.state.vim if it does not exist. Returns cm.state.vim. +
+ +
handleKey(cm: CodeMirror, key: string, origin: string)
+
+ Convenience function to pass the arguments to findKey and + call returned function if it is defined. +
+ +
findKey(cm: CodeMirror, key: string, origin: string)
+
+ This is the outermost function called by CodeMirror, after keys have + been mapped to their Vim equivalents. Finds a command based on the key + (and cached keys if there is a multi-key sequence). Returns undefined + if no key is matched, a noop function if a partial match is found (multi-key), + and a function to execute the bound command if a a key is matched. The + function always returns true. +
+ +
suppressErrorLogging: boolean
+
Whether to use suppress the use of console.log when catching an + error in the function returned by findKey. + Defaults to false.
+ +
exitVisualMode(cm: CodeMirror, ?moveHead: boolean)
+
Exit visual mode. If moveHead is set to false, the CodeMirror selection + will not be touched. The caller assumes the responsibility of putting + the cursor in the right place. +
+ +
exitInsertMode(cm: CodeMirror)
+
+ Exit insert mode. +
diff --git a/src/codemirror/doc/realworld.html b/src/assets/plugins/codemirror/doc/realworld.html old mode 100755 new mode 100644 similarity index 95% rename from src/codemirror/doc/realworld.html rename to src/assets/plugins/codemirror/doc/realworld.html index 8d4e07a..152b557 --- a/src/codemirror/doc/realworld.html +++ b/src/assets/plugins/codemirror/doc/realworld.html @@ -26,6 +26,7 @@
  • Adobe Brackets (code editor)
  • +
  • Adnuntius (used for in-browser code editing and version history)
  • ALM Tools (TypeScript powered IDE)
  • Amber (JavaScript-based Smalltalk system)
  • APEye (tool for testing & documenting APIs)
  • @@ -39,6 +40,7 @@
  • Cargo Collective (creative publishing platform)
  • Chrome DevTools
  • ClickHelp (technical writing tool)
  • +
  • Clone-It (HTML & CSS learning game)
  • Colon (A flexible text editor or IDE)
  • CodeWorld (Haskell playground)
  • Complete.ly playground
  • @@ -52,11 +54,11 @@
  • CodeMirror2-GWT (Google Web Toolkit wrapper)
  • Code Monster & Code Maven (learning environment)
  • Codepen (gallery of animations)
  • +
  • Coderba Google Web Toolkit (GWT) wrapper
  • Coderpad (interviewing tool)
  • Code School (online tech learning environment)
  • Code Snippets (WordPress snippet management plugin)
  • Code together (collaborative editing)
  • -
  • Codev (collaborative IDE)
  • Codevolve (programming lessons as-a-service)
  • CodeZample (code snippet sharing)
  • Codio (Web IDE)
  • @@ -76,6 +78,7 @@
  • Eloquent JavaScript (book)
  • Emmet (fast XML editing)
  • Espruino Web IDE (Chrome App for writing code on Espruino devices)
  • +
  • EXLskills Live Interivews
  • Fastfig (online computation/math tool)
  • Farabi (modern Perl IDE)
  • FathomJS integration (slides with editors, again)
  • @@ -118,6 +121,7 @@
  • Kotlin (web-based mini-IDE for Kotlin)
  • Light Table (experimental IDE)
  • Liveweave (HTML/CSS/JS scratchpad)
  • +
  • LiveUML (PlantUML online editor)
  • Markdown Delight Editor (extensible markdown editor polymer component)
  • Marklight editor (lightweight markup editor)
  • Mergely (interactive diffing)
  • @@ -142,10 +146,12 @@
  • Quantum (code editor for Chrome OS)
  • Qt+Webkit integration (building a desktop CodeMirror app)
  • Quivive File Manager
  • +
  • RackTables (data centre resources manager)
  • Rascal (tiny computer)
  • RealTime.io (Internet-of-Things infrastructure)
  • Refork (animation demo gallery and sharing)
  • SageMathCell (interactive mathematical software)
  • +
  • SASS2CSS (SASS, SCSS or LESS to CSS converter and CSS beautifier)
  • SageMathCloud (interactive mathematical software environment)
  • salvare (real-time collaborative code editor)
  • ServePHP (PHP code testing in Chrome dev tools)
  • @@ -167,6 +173,7 @@
  • The File Tree (collab editor)
  • TileMill (map design tool)
  • Tiki (wiki CMS groupware)
  • +
  • Tistory (blog service)
  • Toolsverse Data Explorer (database management)
  • Tumblr code highlighting shim
  • TurboPY (web publishing framework)
  • diff --git a/src/codemirror/doc/releases.html b/src/assets/plugins/codemirror/doc/releases.html old mode 100755 new mode 100644 similarity index 91% rename from src/codemirror/doc/releases.html rename to src/assets/plugins/codemirror/doc/releases.html index 6ecaef0..75384de --- a/src/codemirror/doc/releases.html +++ b/src/assets/plugins/codemirror/doc/releases.html @@ -30,6 +30,149 @@

    Version 5.x

    +

    20-05-2020: Version 5.54.0:

    + +
      +
    • runmode addon: Properly support for cross-line lookahead.
    • +
    • vim bindings: Allow Ex-Commands with non-word names.
    • +
    • gfm mode: Add a fencedCodeBlockDefaultMode option.
    • +
    • Improve support for having focus inside in-editor widgets in contenteditable-mode.
    • +
    • Fix issue where the scroll position could jump when clicking on a selection in Chrome.
    • +
    • python mode: Better format string support.
    • +
    • javascript mode: Improve parsing of private properties and class fields.
    • +
    • matchbrackets addon: Disable highlighting when the editor doesn’t have focus.
    • +
    + +

    21-04-2020: Version 5.53.2:

    + + + +

    21-04-2020: Version 5.53.0:

    + +
      +
    • New option: screenReaderLabel to add a label to the editor.
    • +
    • New mode: wast.
    • +
    • Fix a bug where the editor layout could remain confused after a call to refresh when line wrapping was enabled.
    • +
    • dialog addon: Don’t close dialogs when the document window loses focus.
    • +
    • merge addon: Compensate for editor top position when aligning lines.
    • +
    • vim bindings: Improve EOL handling.
    • +
    • emacs bindings: Include default keymap as a fallback.
    • +
    • julia mode: Fix an infinite loop bug.
    • +
    • show-hint addon: Scroll cursor into view when picking a completion.
    • +
    + +

    20-03-2020: Version 5.52.2:

    + +
      +
    • Fix selection management in contenteditable mode when the editor doesn’t have focus.
    • +
    • Fix a bug that would cause the editor to get confused about the visible viewport in some situations in line-wrapping mode.
    • +
    • markdown mode: Don’t treat single dashes as setext header markers.
    • +
    • zenburn theme: Make sure background styles take precedence over default styles.
    • +
    • css mode: Recognize a number of new properties.
    • +
    + +

    20-02-2020: Version 5.52.0:

    + +
      +
    • Fix a bug in handling of bidi text with Arabic numbers in a right-to-left editor.
    • +
    • Fix a crash when combining file drop with a "beforeChange" filter.
    • +
    • Prevent issue when passing negative coordinates to scrollTo.
    • +
    • lint and tern addons: Allow the tooltip to be appended to the editor wrapper element instead of the document body.
    • +
    + +

    20-01-2020: Version 5.51.0:

    + +
      +
    • Fix the behavior of the home and end keys when direction is set to "rtl".
    • +
    • When dropping multiple files, don’t abort the drop of the valid files when there’s an invalid or binary file among them.
    • +
    • Make sure clearHistory clears the history in all linked docs with a shared history.
    • +
    • vim bindings: Fix behavior of ' and ` marks, fix R in visual mode.
    • +
    • vim bindings: Support gi, gI, and gJ.
    • +
    + +

    01-01-2020: Version 5.50.2:

    + +
      +
    • Fix bug that broke removal of line widgets.
    • +
    + +

    20-12-2019: Version 5.50.0:

    + + + +

    21-10-2019: Version 5.49.2:

    + + + +

    20-09-2019: Version 5.49.0:

    + + + +

    20-08-2019: Version 5.48.4:

    + +
      +
    • Make default styles for line elements more specific so that they don’t apply to all <pre> elements inside the editor.
    • +
    • Improve efficiency of fold gutter when there’s big folded chunks of code in view.
    • +
    • Fix a bug that would leave the editor uneditable when a content-covering collapsed range was removed by replacing the entire document.
    • +
    • julia mode: Support number separators.
    • +
    • asterisk mode: Improve comment support.
    • +
    • handlebars mode: Support triple-brace tags.
    • +
    + +

    20-07-2019: Version 5.48.2:

    + +
      +
    • vim bindings: Adjust char escape substitution to match vim, support &/$0.
    • +
    • search addon: Try to make backslash behavior in query strings less confusing.
    • +
    • javascript mode: Handle numeric separators, strings in arrow parameter defaults, and TypeScript in operator in index types.
    • +
    • sparql mode: Allow non-ASCII identifier characters.
    • +
    + +

    20-06-2019: Version 5.48.0:

    + +
      +
    • Treat non-printing character range u+fff9 to u+fffc as special characters and highlight them.
    • +
    • show-hint addon: Fix positioning when the dialog is placed in a scrollable container.
    • +
    • Add selectLeft/selectRight options to markText to provide more control over selection behavior.
    • +
    + +

    21-05-2019: Version 5.47.0:

    + +
      +
    • python mode: Properly handle ... syntax.
    • +
    • ruby mode: Fix indenting before closing brackets.
    • +
    • vim bindings: Fix repeat for C-v I, fix handling of fat cursor C-v c Esc and 0, fix @@, fix block-wise yank.
    • +
    • vim bindings: Add support for ` text object.
    • +
    +

    22-04-2019: Version 5.46.0:

      diff --git a/src/codemirror/doc/reporting.html b/src/assets/plugins/codemirror/doc/reporting.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/doc/reporting.html rename to src/assets/plugins/codemirror/doc/reporting.html diff --git a/src/codemirror/doc/upgrade_v2.2.html b/src/assets/plugins/codemirror/doc/upgrade_v2.2.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/doc/upgrade_v2.2.html rename to src/assets/plugins/codemirror/doc/upgrade_v2.2.html diff --git a/src/codemirror/doc/upgrade_v3.html b/src/assets/plugins/codemirror/doc/upgrade_v3.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/doc/upgrade_v3.html rename to src/assets/plugins/codemirror/doc/upgrade_v3.html diff --git a/src/codemirror/doc/upgrade_v4.html b/src/assets/plugins/codemirror/doc/upgrade_v4.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/doc/upgrade_v4.html rename to src/assets/plugins/codemirror/doc/upgrade_v4.html diff --git a/src/codemirror/doc/yinyang.png b/src/assets/plugins/codemirror/doc/yinyang.png old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/doc/yinyang.png rename to src/assets/plugins/codemirror/doc/yinyang.png diff --git a/src/codemirror/index.html b/src/assets/plugins/codemirror/index.html old mode 100755 new mode 100644 similarity index 69% rename from src/codemirror/index.html rename to src/assets/plugins/codemirror/index.html index 4e4f164..59cac74 --- a/src/codemirror/index.html +++ b/src/assets/plugins/codemirror/index.html @@ -99,7 +99,7 @@
      - Get the current version: 5.46.0.
      + Get the current version: 5.54.0.
      You can see the code,
      read the release notes,
      or study the user manual. @@ -195,4 +195,19 @@ pretty well.

      +
      + + +

      Sponsors

      +

      These companies support development of this project:

      + +
      + diff --git a/src/codemirror/keymap/emacs.js b/src/assets/plugins/codemirror/keymap/emacs.js old mode 100755 new mode 100644 similarity index 99% rename from src/codemirror/keymap/emacs.js rename to src/assets/plugins/codemirror/keymap/emacs.js index d96a6fb..fe4882e --- a/src/codemirror/keymap/emacs.js +++ b/src/assets/plugins/codemirror/keymap/emacs.js @@ -369,6 +369,7 @@ "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"), "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"), + "Shift-Ctrl-Z": "redo", "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", "Ctrl-S": "findPersistentNext", "Ctrl-R": "findPersistentPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace", "Alt-/": "autocomplete", @@ -403,7 +404,8 @@ "Ctrl-X H": "selectAll", "Ctrl-Q Tab": repeated("insertTab"), - "Ctrl-U": addPrefixMap + "Ctrl-U": addPrefixMap, + "fallthrough": "default" }); var prefixMap = {"Ctrl-G": clearPrefix}; diff --git a/src/codemirror/keymap/sublime.js b/src/assets/plugins/codemirror/keymap/sublime.js old mode 100755 new mode 100644 similarity index 94% rename from src/codemirror/keymap/sublime.js rename to src/assets/plugins/codemirror/keymap/sublime.js index 799641a..7edf172 --- a/src/codemirror/keymap/sublime.js +++ b/src/assets/plugins/codemirror/keymap/sublime.js @@ -22,17 +22,21 @@ 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 state = "start", type, startPos = start.ch; + for (var pos = startPos, 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 startPos = pos + dir } 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; } + if (type == "W" && cat == "w" && dir > 0) { // From uppercase to lowercase + if (pos == startPos + 1) { type = "w"; continue; } + else pos--; + } break; } } @@ -144,14 +148,24 @@ cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); found = cur.findNext(); } - if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) - return CodeMirror.Pass + if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) return cm.addSelection(cur.from(), cur.to()); } if (fullWord) cm.state.sublimeFindFullWord = cm.doc.sel; }; + cmds.skipAndSelectNextOccurrence = function(cm) { + var prevAnchor = cm.getCursor("anchor"), prevHead = cm.getCursor("head"); + cmds.selectNextOccurrence(cm); + if (CodeMirror.cmpPos(prevAnchor, prevHead) != 0) { + cm.doc.setSelections(cm.doc.listSelections() + .filter(function (sel) { + return sel.anchor != prevAnchor || sel.head != prevHead; + })); + } + } + function addCursorToSelection(cm, dir) { var ranges = cm.listSelections(), newRanges = []; for (var i = 0; i < ranges.length; i++) { @@ -175,7 +189,8 @@ function isSelectedRange(ranges, from, to) { for (var i = 0; i < ranges.length; i++) - if (ranges[i].from() == from && ranges[i].to() == to) return true + if (CodeMirror.cmpPos(ranges[i].from(), from) == 0 && + CodeMirror.cmpPos(ranges[i].to(), to) == 0) return true return false } @@ -213,11 +228,15 @@ if (!selectBetweenBrackets(cm)) return CodeMirror.Pass; }; + function puncType(type) { + return !type ? null : /\bpunctuation\b/.test(type) ? type : undefined + } + cmds.goToBracket = function(cm) { cm.extendSelectionsBy(function(range) { - var next = cm.scanForBracket(range.head, 1); + var next = cm.scanForBracket(range.head, 1, puncType(cm.getTokenTypeAt(range.head))); if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos; - var prev = cm.scanForBracket(range.head, -1); + var prev = cm.scanForBracket(range.head, -1, puncType(cm.getTokenTypeAt(Pos(range.head.line, range.head.ch + 1)))); return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head; }); }; @@ -597,6 +616,7 @@ "Shift-Cmd-F2": "clearBookmarks", "Alt-F2": "selectBookmarks", "Backspace": "smartBackspace", + "Cmd-K Cmd-D": "skipAndSelectNextOccurrence", "Cmd-K Cmd-K": "delLineRight", "Cmd-K Cmd-U": "upcaseAtCursor", "Cmd-K Cmd-L": "downcaseAtCursor", @@ -608,6 +628,7 @@ "Cmd-K Cmd-C": "showInCenter", "Cmd-K Cmd-G": "clearBookmarks", "Cmd-K Cmd-Backspace": "delLineLeft", + "Cmd-K Cmd-1": "foldAll", "Cmd-K Cmd-0": "unfoldAll", "Cmd-K Cmd-J": "unfoldAll", "Ctrl-Shift-Up": "addCursorToPrevLine", @@ -657,6 +678,7 @@ "Shift-Ctrl-F2": "clearBookmarks", "Alt-F2": "selectBookmarks", "Backspace": "smartBackspace", + "Ctrl-K Ctrl-D": "skipAndSelectNextOccurrence", "Ctrl-K Ctrl-K": "delLineRight", "Ctrl-K Ctrl-U": "upcaseAtCursor", "Ctrl-K Ctrl-L": "downcaseAtCursor", @@ -668,6 +690,7 @@ "Ctrl-K Ctrl-C": "showInCenter", "Ctrl-K Ctrl-G": "clearBookmarks", "Ctrl-K Ctrl-Backspace": "delLineLeft", + "Ctrl-K Ctrl-1": "foldAll", "Ctrl-K Ctrl-0": "unfoldAll", "Ctrl-K Ctrl-J": "unfoldAll", "Ctrl-Alt-Up": "addCursorToPrevLine", diff --git a/src/codemirror/keymap/vim.js b/src/assets/plugins/codemirror/keymap/vim.js old mode 100755 new mode 100644 similarity index 96% rename from src/codemirror/keymap/vim.js rename to src/assets/plugins/codemirror/keymap/vim.js index 5758823..b5be59c --- a/src/codemirror/keymap/vim.js +++ b/src/assets/plugins/codemirror/keymap/vim.js @@ -164,7 +164,9 @@ { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, + { keys: 'gi', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'lastEdit' }, context: 'normal' }, { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, + { keys: 'gI', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'bol'}, context: 'normal' }, { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, @@ -174,13 +176,15 @@ { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, + { keys: 'gJ', type: 'action', action: 'joinLines', actionArgs: { keepSpaces: true }, isEdit: true }, { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, { keys: 'r', type: 'action', action: 'replace', isEdit: true }, { keys: '@', type: 'action', action: 'replayMacro' }, { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, // Handle Replace-mode as a special case of insert mode. - { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, + { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }, context: 'normal'}, + { keys: 'R', type: 'operator', operator: 'change', operatorArgs: { linewise: true, fullLine: true }, context: 'visual', exitVisualBlock: true}, { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, @@ -230,7 +234,6 @@ { name: 'undo', shortName: 'u' }, { name: 'redo', shortName: 'red' }, { name: 'set', shortName: 'se' }, - { name: 'set', shortName: 'se' }, { name: 'setlocal', shortName: 'setl' }, { name: 'setglobal', shortName: 'setg' }, { name: 'sort', shortName: 'sor' }, @@ -286,41 +289,44 @@ enterVimMode(cm); } - function fatCursorMarks(cm) { + function updateFatCursorMark(cm) { + if (!cm.state.fatCursorMarks) return; + clearFatCursorMark(cm); var ranges = cm.listSelections(), result = [] for (var i = 0; i < ranges.length; i++) { - var range = ranges[i] + var range = ranges[i]; if (range.empty()) { - if (range.anchor.ch < cm.getLine(range.anchor.line).length) { + var lineLength = cm.getLine(range.anchor.line).length; + if (range.anchor.ch < lineLength) { result.push(cm.markText(range.anchor, Pos(range.anchor.line, range.anchor.ch + 1), - {className: "cm-fat-cursor-mark"})) + {className: "cm-fat-cursor-mark"})); } else { - var widget = document.createElement("span") - widget.textContent = "\u00a0" - widget.className = "cm-fat-cursor-mark" - result.push(cm.setBookmark(range.anchor, {widget: widget})) + result.push(cm.markText(Pos(range.anchor.line, lineLength - 1), + Pos(range.anchor.line, lineLength), + {className: "cm-fat-cursor-mark"})); } } } - return result + cm.state.fatCursorMarks = result; } - function updateFatCursorMark(cm) { - var marks = cm.state.fatCursorMarks - if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear() - cm.state.fatCursorMarks = fatCursorMarks(cm) + function clearFatCursorMark(cm) { + var marks = cm.state.fatCursorMarks; + if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear(); } function enableFatCursorMark(cm) { - cm.state.fatCursorMarks = fatCursorMarks(cm) + cm.state.fatCursorMarks = []; + updateFatCursorMark(cm) cm.on("cursorActivity", updateFatCursorMark) } function disableFatCursorMark(cm) { - var marks = cm.state.fatCursorMarks - if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear() - cm.state.fatCursorMarks = null - cm.off("cursorActivity", updateFatCursorMark) + clearFatCursorMark(cm); + cm.off("cursorActivity", updateFatCursorMark); + // explicitly set fatCursorMarks to null because event listener above + // can be invoke after removing it, if off is called from operation + cm.state.fatCursorMarks = null; } // Deprecated, simply setting the keymap works again. @@ -591,9 +597,16 @@ } return mark; } + function find(cm, offset) { + var oldPointer = pointer; + var mark = move(cm, offset); + pointer = oldPointer; + return mark && mark.find(); + } return { cachedCursor: undefined, //used for # and * jumps add: add, + find: find, move: move }; }; @@ -1290,6 +1303,10 @@ } inputState.operator = command.operator; inputState.operatorArgs = copyArgs(command.operatorArgs); + if (command.exitVisualBlock) { + vim.visualBlock = false; + updateCmSelection(cm); + } if (vim.visualMode) { // Operating on a selection in visual mode. We don't need a motion. this.evalInput(cm, vim); @@ -1585,10 +1602,10 @@ } if (vim.visualMode) { if (!(vim.visualBlock && newHead.ch === Infinity)) { - newHead = clipCursorToContent(cm, newHead, vim.visualBlock); + newHead = clipCursorToContent(cm, newHead); } if (newAnchor) { - newAnchor = clipCursorToContent(cm, newAnchor, true); + newAnchor = clipCursorToContent(cm, newAnchor); } newAnchor = newAnchor || oldAnchor; sel.anchor = newAnchor; @@ -1714,6 +1731,7 @@ vim.lastEditActionCommand = actionCommand; macroModeState.lastInsertModeChanges.changes = []; macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; + macroModeState.lastInsertModeChanges.visualBlock = vim.visualBlock ? vim.sel.head.line - vim.sel.anchor.line : 0; } }; @@ -1839,12 +1857,18 @@ var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; var first = cm.firstLine(); var last = cm.lastLine(); + var posV = cm.findPosV(cur, (motionArgs.forward ? repeat : -repeat), 'line', vim.lastHSPos); + var hasMarkedText = motionArgs.forward ? posV.line > line : posV.line < line; + if (hasMarkedText) { + line = posV.line; + endCh = posV.ch; + } // Vim go to line begin or line end when cursor at first/last line and // move to previous/next line is triggered. if (line < first && cur.line == first){ return this.moveToStartOfLine(cm, head, motionArgs, vim); }else if (line > last && cur.line == last){ - return this.moveToEol(cm, head, motionArgs, vim); + return this.moveToEol(cm, head, motionArgs, vim, true); } if (motionArgs.toFirstChar){ endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); @@ -1946,13 +1970,15 @@ vim.lastHSPos = cm.charCoords(head,'div').left; return moveToColumn(cm, repeat); }, - moveToEol: function(cm, head, motionArgs, vim) { + moveToEol: function(cm, head, motionArgs, vim, keepHPos) { var cur = head; - vim.lastHPos = Infinity; var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); var end=cm.clipPos(retval); end.ch--; - vim.lastHSPos = cm.charCoords(end,'div').left; + if (!keepHPos) { + vim.lastHPos = Infinity; + vim.lastHSPos = cm.charCoords(end,'div').left; + } return retval; }, moveToFirstNonWhiteSpaceCharacter: function(cm, head) { @@ -2004,7 +2030,7 @@ '{': '}', '}': '{', '[': ']', ']': '[', '<': '>', '>': '<'}; - var selfPaired = {'\'': true, '"': true}; + var selfPaired = {'\'': true, '"': true, '`': true}; var character = motionArgs.selectedCharacter; // 'b' refers to '()' block. @@ -2092,10 +2118,9 @@ change: function(cm, args, ranges) { var finalHead, text; var vim = cm.state.vim; - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; + var anchor = ranges[0].anchor, + head = ranges[0].head; if (!vim.visualMode) { - var anchor = ranges[0].anchor, - head = ranges[0].head; text = cm.getRange(anchor, head); var lastState = vim.lastEditInputState || {}; if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) { @@ -2123,6 +2148,13 @@ anchor.ch = Number.MAX_VALUE; } finalHead = anchor; + } else if (args.fullLine) { + head.ch = Number.MAX_VALUE; + head.line--; + cm.setSelection(anchor, head) + text = cm.getSelection(); + cm.replaceSelection(""); + finalHead = anchor; } else { text = cm.getSelection(); var replacement = fillArray('', ranges.length); @@ -2167,8 +2199,7 @@ vimGlobalState.registerController.pushText( args.registerName, 'delete', text, args.linewise, vim.visualBlock); - var includeLineBreak = vim.insertMode - return clipCursorToContent(cm, finalHead, includeLineBreak); + return clipCursorToContent(cm, finalHead); }, indent: function(cm, args, ranges) { var vim = cm.state.vim; @@ -2315,6 +2346,8 @@ var macroModeState = vimGlobalState.macroModeState; if (registerName == '@') { registerName = macroModeState.latestRegister; + } else { + macroModeState.latestRegister = registerName; } while(repeat--){ executeMacroRegister(cm, vim, macroModeState, registerName); @@ -2348,11 +2381,15 @@ var height = cm.listSelections().length; if (insertAt == 'eol') { head = Pos(head.line, lineLength(cm, head.line)); + } else if (insertAt == 'bol') { + head = Pos(head.line, 0); } else if (insertAt == 'charAfter') { head = offsetCursor(head, 0, 1); } else if (insertAt == 'firstNonBlank') { head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); } else if (insertAt == 'startOfSelectedArea') { + if (!vim.visualMode) + return; if (!vim.visualBlock) { if (sel.head.line < sel.anchor.line) { head = sel.head; @@ -2366,6 +2403,8 @@ height = Math.abs(sel.head.line - sel.anchor.line) + 1; } } else if (insertAt == 'endOfSelectedArea') { + if (!vim.visualMode) + return; if (!vim.visualBlock) { if (sel.head.line >= sel.anchor.line) { head = offsetCursor(sel.head, 0, 1); @@ -2382,6 +2421,8 @@ if (vim.visualMode){ return; } + } else if (insertAt == 'lastEdit') { + head = getLastEditPos(cm) || head; } cm.setOption('disableInput', false); if (actionArgs && actionArgs.replace) { @@ -2417,8 +2458,7 @@ vim.visualLine = !!actionArgs.linewise; vim.visualBlock = !!actionArgs.blockwise; head = clipCursorToContent( - cm, Pos(anchor.line, anchor.ch + repeat - 1), - true /** includeLineBreak */); + cm, Pos(anchor.line, anchor.ch + repeat - 1)); vim.sel = { anchor: anchor, head: head @@ -2490,7 +2530,9 @@ var tmp = Pos(curStart.line + 1, lineLength(cm, curStart.line + 1)); var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); + text = actionArgs.keepSpaces + ? text.replace(/\n\r?/g, '') + : text.replace(/\n\s*/g, ' '); cm.replaceRange(text, curStart, tmp); } var curFinalPos = Pos(curStart.line, finalCh); @@ -2559,7 +2601,17 @@ } var linewise = register.linewise; var blockwise = register.blockwise; - if (linewise) { + if (blockwise) { + text = text.split('\n'); + if (linewise) { + text.pop(); + } + for (var i = 0; i < text.length; i++) { + text[i] = (text[i] == '') ? ' ' : text[i]; + } + cur.ch += actionArgs.after ? 1 : 0; + cur.ch = Math.min(lineLength(cm, cur.line), cur.ch); + } else if (linewise) { if(vim.visualMode) { text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; } else if (actionArgs.after) { @@ -2571,12 +2623,6 @@ cur.ch = 0; } } else { - if (blockwise) { - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - text[i] = (text[i] == '') ? ' ' : text[i]; - } - } cur.ch += actionArgs.after ? 1 : 0; } var curPosFinal; @@ -2788,10 +2834,11 @@ * Clips cursor to ensure that line is within the buffer's range * If includeLineBreak is true, then allow cur.ch == lineLength. */ - function clipCursorToContent(cm, cur, includeLineBreak) { + function clipCursorToContent(cm, cur) { + var vim = cm.state.vim; + var includeLineBreak = vim.insertMode || vim.visualMode; var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); - var maxCh = lineLength(cm, line) - 1; - maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; + var maxCh = lineLength(cm, line) - 1 + !!includeLineBreak; var ch = Math.min(Math.max(0, cur.ch), maxCh); return Pos(line, ch); } @@ -2811,12 +2858,6 @@ } return Pos(cur.line + offsetLine, cur.ch + offsetCh); } - function getOffset(anchor, head) { - return { - line: head.line - anchor.line, - ch: head.line - anchor.line - }; - } function commandMatches(keys, keyMap, context, inputState) { // Partial matches are not applied. They inform the key handler // that the current key sequence is a subsequence of a valid key @@ -3163,9 +3204,7 @@ vim.visualLine = false; vim.visualBlock = false; CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } + clearFakeCursor(vim); } // Remove any trailing newlines from the selection. For @@ -4064,7 +4103,7 @@ } // Unescape \ and / in the replace part, for PCRE mode. - var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t'}; + var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t', '\\&':'&'}; function unescapeRegexReplace(str) { var stream = new CodeMirror.StringStream(str); var output = []; @@ -4143,7 +4182,8 @@ } function makePrompt(prefix, desc) { var raw = '' + - (prefix || "") + ''; + (prefix || "") + ''; if (desc) raw += ' ' + desc + ''; return raw; @@ -4220,23 +4260,27 @@ query: query }; } + var highlightTimeout = 0; function highlightSearchMatches(cm, query) { - var searchState = getSearchState(cm); - var overlay = searchState.getOverlay(); - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay); - } - overlay = searchOverlay(query); - cm.addOverlay(overlay); - if (cm.showMatchesOnScrollbar) { - if (searchState.getScrollbarAnnotate()) { - searchState.getScrollbarAnnotate().clear(); + clearTimeout(highlightTimeout); + highlightTimeout = setTimeout(function() { + var searchState = getSearchState(cm); + var overlay = searchState.getOverlay(); + if (!overlay || query != overlay.query) { + if (overlay) { + cm.removeOverlay(overlay); } - searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); + overlay = searchOverlay(query); + cm.addOverlay(overlay); + if (cm.showMatchesOnScrollbar) { + if (searchState.getScrollbarAnnotate()) { + searchState.getScrollbarAnnotate().clear(); + } + searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); + } + searchState.setOverlay(overlay); } - searchState.setOverlay(overlay); - } + }, 50); } function findNext(cm, prev, query, repeat) { if (repeat === undefined) { repeat = 1; } @@ -4305,25 +4349,25 @@ } function getMarkPos(cm, vim, markName) { - if (markName == '\'') { - var history = cm.doc.history.done; - var event = history[history.length - 2]; - return event && event.ranges && event.ranges[0].head; + if (markName == '\'' || markName == '`') { + return vimGlobalState.jumpList.find(cm, -1) || Pos(0, 0); } else if (markName == '.') { - if (cm.doc.history.lastModTime == 0) { - return // If no changes, bail out; don't bother to copy or reverse history array. - } else { - var changeHistory = cm.doc.history.done.filter(function(el){ if (el.changes !== undefined) { return el } }); - changeHistory.reverse(); - var lastEditPos = changeHistory[0].changes[0].to; - } - return lastEditPos; + return getLastEditPos(cm); } var mark = vim.marks[markName]; return mark && mark.find(); } + function getLastEditPos(cm) { + var done = cm.doc.history.done; + for (var i = done.length; i--;) { + if (done[i].changes) { + return copyCursor(done[i].changes[0].to); + } + } + } + var ExCommandDispatcher = function() { this.buildCommandMap_(); }; @@ -4412,7 +4456,7 @@ } // Parse command name. - var commandMatch = inputStream.match(/^(\w+)/); + var commandMatch = inputStream.match(/^(\w+|!!|@@|[!#&*<=>@~])/); if (commandMatch) { result.commandName = commandMatch[1]; } else { @@ -4848,6 +4892,9 @@ var global = false; // True to replace all instances on a line, false to replace only 1. if (tokens.length) { regexPart = tokens[0]; + if (getOption('pcre') && regexPart !== '') { + regexPart = new RegExp(regexPart).source; //normalize not escaped characters + } replacePart = tokens[1]; if (regexPart && regexPart[regexPart.length - 1] === '$') { regexPart = regexPart.slice(0, regexPart.length - 1) + '\\n'; @@ -4855,7 +4902,7 @@ } if (replacePart !== undefined) { if (getOption('pcre')) { - replacePart = unescapeRegexReplace(replacePart); + replacePart = unescapeRegexReplace(replacePart.replace(/([^\\])&/g,"$1$$&")); } else { replacePart = translateRegexReplace(replacePart); } @@ -4886,7 +4933,11 @@ global = true; flagsPart.replace('g', ''); } - regexPart = regexPart.replace(/\//g, "\\/") + '/' + flagsPart; + if (getOption('pcre')) { + regexPart = regexPart + '/' + flagsPart; + } else { + regexPart = regexPart.replace(/\//g, "\\/") + '/' + flagsPart; + } } } if (regexPart) { @@ -5303,14 +5354,34 @@ updateFakeCursor(cm); } } + /** + * Keeps track of a fake cursor to support visual mode cursor behavior. + */ function updateFakeCursor(cm) { + var className = 'cm-animate-fat-cursor'; var vim = cm.state.vim; var from = clipCursorToContent(cm, copyCursor(vim.sel.head)); var to = offsetCursor(from, 0, 1); + clearFakeCursor(vim); + // In visual mode, the cursor may be positioned over EOL. + if (from.ch == cm.getLine(from.line).length) { + var widget = document.createElement("span"); + widget.textContent = "\u00a0"; + widget.className = className; + vim.fakeCursorBookmark = cm.setBookmark(from, {widget: widget}); + } else { + vim.fakeCursor = cm.markText(from, to, {className: className}); + } + } + function clearFakeCursor(vim) { if (vim.fakeCursor) { vim.fakeCursor.clear(); + vim.fakeCursor = null; + } + if (vim.fakeCursorBookmark) { + vim.fakeCursorBookmark.clear(); + vim.fakeCursorBookmark = null; } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); } function handleExternalSelection(cm, vim) { var anchor = cm.getCursor('anchor'); @@ -5436,18 +5507,15 @@ return true; } var head = cm.getCursor('head'); - var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; - if (inVisualBlock) { + var visualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.visualBlock; + if (visualBlock) { // Set up block selection again for repeating the changes. - var vim = cm.state.vim; - var lastSel = vim.lastSelection; - var offset = getOffset(lastSel.anchor, lastSel.head); - selectForInsert(cm, head, offset.line + 1); + selectForInsert(cm, head, visualBlock + 1); repeat = cm.listSelections().length; cm.setCursor(head); } for (var i = 0; i < repeat; i++) { - if (inVisualBlock) { + if (visualBlock) { cm.setCursor(offsetCursor(head, i, 0)); } for (var j = 0; j < changes.length; j++) { @@ -5464,7 +5532,7 @@ } } } - if (inVisualBlock) { + if (visualBlock) { cm.setCursor(offsetCursor(head, 0, 1)); } } diff --git a/src/codemirror/lib/codemirror.css b/src/assets/plugins/codemirror/lib/codemirror.css old mode 100755 new mode 100644 similarity index 94% rename from src/codemirror/lib/codemirror.css rename to src/assets/plugins/codemirror/lib/codemirror.css index c7a8ae7..5689650 --- a/src/codemirror/lib/codemirror.css +++ b/src/assets/plugins/codemirror/lib/codemirror.css @@ -13,7 +13,8 @@ .CodeMirror-lines { padding: 4px 0; /* Vertical padding around content */ } -.CodeMirror pre { +.CodeMirror pre.CodeMirror-line, +.CodeMirror pre.CodeMirror-line-like { padding: 0 4px; /* Horizontal padding of content */ } @@ -96,7 +97,7 @@ .CodeMirror-rulers { position: absolute; - left: 0; right: 0; top: -50px; bottom: -20px; + left: 0; right: 0; top: -50px; bottom: 0; overflow: hidden; } .CodeMirror-ruler { @@ -163,17 +164,17 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} .CodeMirror-scroll { overflow: scroll !important; /* Things will break if this is overridden */ - /* 30px is the magic margin used to hide the element's real scrollbars */ + /* 50px is the magic margin used to hide the element's real scrollbars */ /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; + margin-bottom: -50px; margin-right: -50px; + padding-bottom: 50px; height: 100%; outline: none; /* Prevent dragging from highlighting the element */ position: relative; } .CodeMirror-sizer { position: relative; - border-right: 30px solid transparent; + border-right: 50px solid transparent; } /* The fake, visible scrollbars. Used to force redraw during scrolling @@ -211,7 +212,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} height: 100%; display: inline-block; vertical-align: top; - margin-bottom: -30px; + margin-bottom: -50px; } .CodeMirror-gutter-wrapper { position: absolute; @@ -236,7 +237,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} cursor: text; min-height: 1px; /* prevents collapsing before first draw */ } -.CodeMirror pre { +.CodeMirror pre.CodeMirror-line, +.CodeMirror pre.CodeMirror-line-like { /* Reset some styles that the rest of the page might have set */ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; border-width: 0; @@ -255,7 +257,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;} -webkit-font-variant-ligatures: contextual; font-variant-ligatures: contextual; } -.CodeMirror-wrap pre { +.CodeMirror-wrap pre.CodeMirror-line, +.CodeMirror-wrap pre.CodeMirror-line-like { word-wrap: break-word; white-space: pre-wrap; word-break: normal; diff --git a/src/codemirror/lib/codemirror.js b/src/assets/plugins/codemirror/lib/codemirror.js old mode 100755 new mode 100644 similarity index 98% rename from src/codemirror/lib/codemirror.js rename to src/assets/plugins/codemirror/lib/codemirror.js index 6d8bd9f..375fa2a --- a/src/codemirror/lib/codemirror.js +++ b/src/assets/plugins/codemirror/lib/codemirror.js @@ -173,10 +173,28 @@ } } - var Delayed = function() {this.id = null;}; + var Delayed = function() { + this.id = null; + this.f = null; + this.time = 0; + this.handler = bind(this.onTimeout, this); + }; + Delayed.prototype.onTimeout = function (self) { + self.id = 0; + if (self.time <= +new Date) { + self.f(); + } else { + setTimeout(self.handler, self.time - +new Date); + } + }; Delayed.prototype.set = function (ms, f) { - clearTimeout(this.id); - this.id = setTimeout(f, ms); + this.f = f; + var time = +new Date + ms; + if (!this.id || time < this.time) { + clearTimeout(this.id); + this.id = setTimeout(this.handler, ms); + this.time = time; + } }; function indexOf(array, elt) { @@ -186,7 +204,7 @@ } // Number of pixels added to scroller and sizer to hide scrollbar - var scrollerGap = 30; + var scrollerGap = 50; // Returned or thrown by various protocols to signal 'I'm not // handling this'. @@ -467,14 +485,15 @@ for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} order.push(new BidiSpan(0, start, i$7)); } else { - var pos = i$7, at = order.length; + var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0; for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} for (var j$2 = pos; j$2 < i$7;) { if (countsAsNum.test(types[j$2])) { - if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); } + if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; } var nstart = j$2; for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} order.splice(at, 0, new BidiSpan(2, nstart, j$2)); + at += isRTL; pos = j$2; } else { ++j$2; } } @@ -1186,7 +1205,7 @@ 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])) + else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop])) { output[prop] += " " + lineClass[2]; } } } return type @@ -2191,10 +2210,10 @@ function updateLineWidgets(cm, lineView, dims) { if (lineView.alignable) { lineView.alignable = null; } + var isWidget = classTest("CodeMirror-linewidget"); for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { next = node.nextSibling; - if (node.className == "CodeMirror-linewidget") - { lineView.node.removeChild(node); } + if (isWidget.test(node.className)) { lineView.node.removeChild(node); } } insertLineWidgets(cm, lineView, dims); } @@ -2224,7 +2243,7 @@ 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"); + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : "")); if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); } positionLineWidget(widget, node, lineView, dims); cm.display.input.setUneditable(node); @@ -2284,7 +2303,7 @@ 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 e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); 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; } @@ -2678,7 +2697,7 @@ function PosWithInfo(line, ch, sticky, outside, xRel) { var pos = Pos(line, ch, sticky); pos.xRel = xRel; - if (outside) { pos.outside = true; } + if (outside) { pos.outside = outside; } return pos } @@ -2687,16 +2706,16 @@ function coordsChar(cm, x, y) { var doc = cm.doc; y += cm.display.viewOffset; - if (y < 0) { return PosWithInfo(doc.first, 0, null, true, -1) } + if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -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, null, true, 1) } + { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) } if (x < 0) { x = 0; } var lineObj = getLine(doc, lineN); for (;;) { var found = coordsCharInner(cm, lineObj, lineN, x, y); - var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 ? 1 : 0)); + var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); if (!collapsed) { return found } var rangeEnd = collapsed.find(1); if (rangeEnd.line == lineN) { return rangeEnd } @@ -2784,7 +2803,7 @@ // base X position var coords = cursorCoords(cm, Pos(lineNo$$1, ch, sticky), "line", lineObj, preparedMeasure); baseX = coords.left; - outside = y < coords.top || y >= coords.bottom; + outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; } ch = skipExtendingChars(lineObj.text, ch, 1); @@ -2853,7 +2872,7 @@ function textHeight(display) { if (display.cachedTextHeight != null) { return display.cachedTextHeight } if (measureText == null) { - measureText = elt("pre"); + measureText = elt("pre", null, "CodeMirror-line-like"); // Measure a bunch of lines, for browsers that compute // fractional heights. for (var i = 0; i < 49; ++i) { @@ -2873,7 +2892,7 @@ function charWidth(display) { if (display.cachedCharWidth != null) { return display.cachedCharWidth } var anchor = elt("span", "xxxxxxxxxx"); - var pre = elt("pre", [anchor]); + var pre = elt("pre", [anchor], "CodeMirror-line-like"); removeChildrenAndAdd(display.measure, pre); var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; if (width > 2) { display.cachedCharWidth = width; } @@ -2947,7 +2966,7 @@ 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) { + if (forRect && coords.xRel > 0 && (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)); } @@ -3536,7 +3555,7 @@ } function setScrollTop(cm, val, forceScroll) { - val = Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val); + val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val)); if (cm.display.scroller.scrollTop == val && !forceScroll) { return } cm.doc.scrollTop = val; cm.display.scrollbars.setScrollTop(val); @@ -3546,7 +3565,7 @@ // Sync scroller and scrollbar, ensure the gutter elements are // aligned. function setScrollLeft(cm, val, isScroller, forceScroll) { - val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth); + val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)); if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } cm.doc.scrollLeft = val; alignHorizontally(cm); @@ -4037,7 +4056,8 @@ function restoreSelection(snapshot) { if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return } snapshot.activeElt.focus(); - if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { + if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) && + snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { var sel = window.getSelection(), range$$1 = document.createRange(); range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset); range$$1.collapse(false); @@ -4135,6 +4155,8 @@ update.visible = visibleLines(cm.display, cm.doc, viewport); if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) { break } + } else if (first) { + update.visible = visibleLines(cm.display, cm.doc, viewport); } if (!updateDisplayIfNeeded(cm, update)) { break } updateHeightsInViewport(cm); @@ -5147,8 +5169,15 @@ var line = getLine(doc, pos.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 <= pos.ch : sp.from < pos.ch)) && - (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + + // Determine if we should prevent the cursor being placed to the left/right of an atomic marker + // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it + // is with selectLeft/Right + var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; + var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; + + if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { if (mayClear) { signal(m, "beforeCursorEnter"); if (m.explicitlyCleared) { @@ -5160,14 +5189,14 @@ if (oldPos) { var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); - if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) + if (dir < 0 ? preventCursorRight : preventCursorLeft) { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) { return skipAtomicInner(doc, near, pos, dir, mayClear) } } var far = m.find(dir < 0 ? -1 : 1); - if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) + if (dir < 0 ? preventCursorLeft : preventCursorRight) { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null } @@ -5396,6 +5425,9 @@ if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); } else { updateDoc(doc, change, spans); } setSelectionNoUndo(doc, selAfter, sel_dontScroll); + + if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) + { doc.cantEdit = false; } } // Handle the interaction of a change to a document with the editor @@ -6257,7 +6289,12 @@ for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } } return {undo: done, redo: undone} }, - clearHistory: function() {this.history = new History(this.history.maxGeneration);}, + clearHistory: function() { + var this$1 = this; + + this.history = new History(this.history.maxGeneration); + linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true); + }, markClean: function() { this.cleanGeneration = this.changeGeneration(true); @@ -6510,28 +6547,39 @@ // 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) { + var markAsReadAndPasteIfAllFilesAreRead = function () { + if (++read == n) { + operation(cm, function () { pos = clipPos(cm.doc, pos); var change = {from: pos, to: pos, - text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), + text: cm.doc.splitLines( + text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())), origin: "paste"}; makeChange(cm.doc, change); - setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))); + setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change)))); + })(); + } + }; + var readTextFromFile = function (file, i) { + if (cm.options.allowDropFileTypes && + indexOf(cm.options.allowDropFileTypes, file.type) == -1) { + markAsReadAndPasteIfAllFilesAreRead(); + return + } + var reader = new FileReader; + reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); }; + reader.onload = function () { + var content = reader.result; + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { + markAsReadAndPasteIfAllFilesAreRead(); + return } - }); + text[i] = content; + markAsReadAndPasteIfAllFilesAreRead(); + }; reader.readAsText(file); }; - for (var i = 0; i < n; ++i) { loadFile(files[i], i); } + for (var i = 0; i < files.length; i++) { readTextFromFile(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) { @@ -6841,6 +6889,7 @@ function endOfLine(visually, cm, lineObj, lineNo, dir) { if (visually) { + if (cm.doc.direction == "rtl") { dir = -dir; } var order = getOrder(lineObj, cm.doc.direction); if (order) { var part = dir < 0 ? lst(order) : order[0]; @@ -7095,7 +7144,7 @@ var line = getLine(cm.doc, start.line); var order = getOrder(line, cm.doc.direction); if (!order || order[0].level == 0) { - var firstNonWS = Math.max(0, line.text.search(/\S/)); + var firstNonWS = Math.max(start.ch, line.text.search(/\S/)); var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) } @@ -7198,6 +7247,7 @@ var lastStoppedKey = null; function onKeyDown(e) { var cm = this; + if (e.target && e.target != cm.display.input.getField()) { return } cm.curOp.focus = activeElt(); if (signalDOMEvent(cm, e)) { return } // IE does strange things with escape. @@ -7211,6 +7261,8 @@ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) { cm.replaceSelection("", null, "cut"); } } + if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand) + { document.execCommand("cut"); } // Turn mouse into crosshair when Alt is held on Mac. if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) @@ -7239,6 +7291,7 @@ function onKeyPress(e) { var cm = this; + if (e.target && e.target != cm.display.input.getField()) { return } 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} @@ -7387,8 +7440,8 @@ if (!behavior.addNew) { extendSelection(cm.doc, pos, null, null, behavior.extend); } // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) - if (webkit || ie && ie_version == 9) - { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus();}, 20); } + if ((webkit && !safari) || ie && ie_version == 9) + { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); } else { display.input.focus(); } } @@ -7700,7 +7753,7 @@ 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", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) { + option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); if (old != Init) { cm.refresh(); } }); @@ -7764,6 +7817,12 @@ } cm.display.input.readOnlyChanged(val); }); + + option("screenReaderLabel", null, function (cm, val) { + val = (val === '') ? null : val; + cm.display.input.screenReaderLabelChanged(val); + }); + option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true); option("dragDrop", true, dragDropChanged); option("allowDropFileTypes", null); @@ -7916,6 +7975,9 @@ // which point we can't mess with it anymore. Context menu is // handled in onMouseDown for these browsers. on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }); + on(d.input.getField(), "contextmenu", function (e) { + if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); } + }); // Used to suppress mouse event handling when a touch happens var touchFinished, prevTouch = {end: 0}; @@ -8602,7 +8664,7 @@ clearCaches(this); scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); updateGutterSpace(this.display); - if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping) { estimateLineHeights(this); } signal(this, "refresh", this); }), @@ -8656,8 +8718,9 @@ var oldPos = pos; var origDir = dir; var lineObj = getLine(doc, pos.line); + var lineDir = visually && doc.direction == "rtl" ? -dir : dir; function findNextLine() { - var l = pos.line + dir; + var l = pos.line + lineDir; if (l < doc.first || l >= doc.first + doc.size) { return false } pos = new Pos(l, pos.ch, pos.sticky); return lineObj = getLine(doc, l) @@ -8671,7 +8734,7 @@ } if (next == null) { if (!boundToLine && findNextLine()) - { pos = endOfLine(visually, doc.cm, lineObj, pos.line, dir); } + { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); } else { return false } } else { @@ -8750,8 +8813,16 @@ var div = input.div = display.lineDiv; disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); + function belongsToInput(e) { + for (var t = e.target; t; t = t.parentNode) { + if (t == div) { return true } + if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break } + } + return false + } + on(div, "paste", function (e) { - if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } // IE doesn't fire input events, so we schedule a read for the pasted content in this way if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); } }); @@ -8776,7 +8847,7 @@ }); function onCopyCut(e) { - if (signalDOMEvent(cm, e)) { return } + if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return } if (cm.somethingSelected()) { setLastCopied({lineWise: false, text: cm.getSelections()}); if (e.type == "cut") { cm.replaceSelection("", null, "cut"); } @@ -8818,9 +8889,18 @@ on(div, "cut", onCopyCut); }; + ContentEditableInput.prototype.screenReaderLabelChanged = function (label) { + // Label for screenreaders, accessibility + if(label) { + this.div.setAttribute('aria-label', label); + } else { + this.div.removeAttribute('aria-label'); + } + }; + ContentEditableInput.prototype.prepareSelection = function () { var result = prepareSelection(this.cm, false); - result.focus = this.cm.state.focused; + result.focus = document.activeElement == this.div; return result }; @@ -8916,7 +8996,7 @@ ContentEditableInput.prototype.focus = function () { if (this.cm.options.readOnly != "nocursor") { - if (!this.selectionInEditor()) + if (!this.selectionInEditor() || document.activeElement != this.div) { this.showSelection(this.prepareSelection(), true); } this.div.focus(); } @@ -9358,6 +9438,15 @@ this.textarea = this.wrapper.firstChild; }; + TextareaInput.prototype.screenReaderLabelChanged = function (label) { + // Label for screenreaders, accessibility + if(label) { + this.textarea.setAttribute('aria-label', label); + } else { + this.textarea.removeAttribute('aria-label'); + } + }; + TextareaInput.prototype.prepareSelection = function () { // Redraw the selection and/or cursor var cm = this.cm, display = cm.display, doc = cm.doc; @@ -9649,7 +9738,7 @@ textarea.style.display = ""; if (textarea.form) { off(textarea.form, "submit", save); - if (typeof textarea.form.submit == "function") + if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") { textarea.form.submit = realSubmit; } } }; @@ -9748,7 +9837,7 @@ addLegacyProps(CodeMirror); - CodeMirror.version = "5.46.0"; + CodeMirror.version = "5.54.0"; return CodeMirror; diff --git a/src/codemirror/mode/clike/clike.js b/src/assets/plugins/codemirror/mode/clike/clike.js old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/clike/clike.js rename to src/assets/plugins/codemirror/mode/clike/clike.js diff --git a/src/codemirror/mode/clike/index.html b/src/assets/plugins/codemirror/mode/clike/index.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/clike/index.html rename to src/assets/plugins/codemirror/mode/clike/index.html diff --git a/src/codemirror/mode/clike/scala.html b/src/assets/plugins/codemirror/mode/clike/scala.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/clike/scala.html rename to src/assets/plugins/codemirror/mode/clike/scala.html diff --git a/src/codemirror/mode/clike/test.js b/src/assets/plugins/codemirror/mode/clike/test.js old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/clike/test.js rename to src/assets/plugins/codemirror/mode/clike/test.js diff --git a/src/assets/plugins/codemirror/mode/coffeescript/coffeescript.js b/src/assets/plugins/codemirror/mode/coffeescript/coffeescript.js new file mode 100644 index 0000000..a54e9d5 --- /dev/null +++ b/src/assets/plugins/codemirror/mode/coffeescript/coffeescript.js @@ -0,0 +1,359 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE + +/** + * Link to the project's GitHub page: + * https://github.com/pickhardt/coffeescript-codemirror-mode + */ +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + +CodeMirror.defineMode("coffeescript", function(conf, parserConf) { + var ERRORCLASS = "error"; + + function wordRegexp(words) { + return new RegExp("^((" + words.join(")|(") + "))\\b"); + } + + var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/; + var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/; + var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/; + var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/; + + var wordOperators = wordRegexp(["and", "or", "not", + "is", "isnt", "in", + "instanceof", "typeof"]); + var indentKeywords = ["for", "while", "loop", "if", "unless", "else", + "switch", "try", "catch", "finally", "class"]; + var commonKeywords = ["break", "by", "continue", "debugger", "delete", + "do", "in", "of", "new", "return", "then", + "this", "@", "throw", "when", "until", "extends"]; + + var keywords = wordRegexp(indentKeywords.concat(commonKeywords)); + + indentKeywords = wordRegexp(indentKeywords); + + + var stringPrefixes = /^('{3}|\"{3}|['\"])/; + var regexPrefixes = /^(\/{3}|\/)/; + var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"]; + var constants = wordRegexp(commonConstants); + + // Tokenizers + function tokenBase(stream, state) { + // Handle scope changes + if (stream.sol()) { + if (state.scope.align === null) state.scope.align = false; + var scopeOffset = state.scope.offset; + if (stream.eatSpace()) { + var lineOffset = stream.indentation(); + if (lineOffset > scopeOffset && state.scope.type == "coffee") { + return "indent"; + } else if (lineOffset < scopeOffset) { + return "dedent"; + } + return null; + } else { + if (scopeOffset > 0) { + dedent(stream, state); + } + } + } + if (stream.eatSpace()) { + return null; + } + + var ch = stream.peek(); + + // Handle docco title comment (single line) + if (stream.match("####")) { + stream.skipToEnd(); + return "comment"; + } + + // Handle multi line comments + if (stream.match("###")) { + state.tokenize = longComment; + return state.tokenize(stream, state); + } + + // Single line comment + if (ch === "#") { + stream.skipToEnd(); + return "comment"; + } + + // Handle number literals + if (stream.match(/^-?[0-9\.]/, false)) { + var floatLiteral = false; + // Floats + if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) { + floatLiteral = true; + } + if (stream.match(/^-?\d+\.\d*/)) { + floatLiteral = true; + } + if (stream.match(/^-?\.\d+/)) { + floatLiteral = true; + } + + if (floatLiteral) { + // prevent from getting extra . on 1.. + if (stream.peek() == "."){ + stream.backUp(1); + } + return "number"; + } + // Integers + var intLiteral = false; + // Hex + if (stream.match(/^-?0x[0-9a-f]+/i)) { + intLiteral = true; + } + // Decimal + if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) { + intLiteral = true; + } + // Zero by itself with no other piece of number. + if (stream.match(/^-?0(?![\dx])/i)) { + intLiteral = true; + } + if (intLiteral) { + return "number"; + } + } + + // Handle strings + if (stream.match(stringPrefixes)) { + state.tokenize = tokenFactory(stream.current(), false, "string"); + return state.tokenize(stream, state); + } + // Handle regex literals + if (stream.match(regexPrefixes)) { + if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division + state.tokenize = tokenFactory(stream.current(), true, "string-2"); + return state.tokenize(stream, state); + } else { + stream.backUp(1); + } + } + + + + // Handle operators and delimiters + if (stream.match(operators) || stream.match(wordOperators)) { + return "operator"; + } + if (stream.match(delimiters)) { + return "punctuation"; + } + + if (stream.match(constants)) { + return "atom"; + } + + if (stream.match(atProp) || state.prop && stream.match(identifiers)) { + return "property"; + } + + if (stream.match(keywords)) { + return "keyword"; + } + + if (stream.match(identifiers)) { + return "variable"; + } + + // Handle non-detected items + stream.next(); + return ERRORCLASS; + } + + function tokenFactory(delimiter, singleline, outclass) { + return function(stream, state) { + while (!stream.eol()) { + stream.eatWhile(/[^'"\/\\]/); + if (stream.eat("\\")) { + stream.next(); + if (singleline && stream.eol()) { + return outclass; + } + } else if (stream.match(delimiter)) { + state.tokenize = tokenBase; + return outclass; + } else { + stream.eat(/['"\/]/); + } + } + if (singleline) { + if (parserConf.singleLineStringErrors) { + outclass = ERRORCLASS; + } else { + state.tokenize = tokenBase; + } + } + return outclass; + }; + } + + function longComment(stream, state) { + while (!stream.eol()) { + stream.eatWhile(/[^#]/); + if (stream.match("###")) { + state.tokenize = tokenBase; + break; + } + stream.eatWhile("#"); + } + return "comment"; + } + + function indent(stream, state, type) { + type = type || "coffee"; + var offset = 0, align = false, alignOffset = null; + for (var scope = state.scope; scope; scope = scope.prev) { + if (scope.type === "coffee" || scope.type == "}") { + offset = scope.offset + conf.indentUnit; + break; + } + } + if (type !== "coffee") { + align = null; + alignOffset = stream.column() + stream.current().length; + } else if (state.scope.align) { + state.scope.align = false; + } + state.scope = { + offset: offset, + type: type, + prev: state.scope, + align: align, + alignOffset: alignOffset + }; + } + + function dedent(stream, state) { + if (!state.scope.prev) return; + if (state.scope.type === "coffee") { + var _indent = stream.indentation(); + var matched = false; + for (var scope = state.scope; scope; scope = scope.prev) { + if (_indent === scope.offset) { + matched = true; + break; + } + } + if (!matched) { + return true; + } + while (state.scope.prev && state.scope.offset !== _indent) { + state.scope = state.scope.prev; + } + return false; + } else { + state.scope = state.scope.prev; + return false; + } + } + + function tokenLexer(stream, state) { + var style = state.tokenize(stream, state); + var current = stream.current(); + + // Handle scope changes. + if (current === "return") { + state.dedent = true; + } + if (((current === "->" || current === "=>") && stream.eol()) + || style === "indent") { + indent(stream, state); + } + var delimiter_index = "[({".indexOf(current); + if (delimiter_index !== -1) { + indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); + } + if (indentKeywords.exec(current)){ + indent(stream, state); + } + if (current == "then"){ + dedent(stream, state); + } + + + if (style === "dedent") { + if (dedent(stream, state)) { + return ERRORCLASS; + } + } + delimiter_index = "])}".indexOf(current); + if (delimiter_index !== -1) { + while (state.scope.type == "coffee" && state.scope.prev) + state.scope = state.scope.prev; + if (state.scope.type == current) + state.scope = state.scope.prev; + } + if (state.dedent && stream.eol()) { + if (state.scope.type == "coffee" && state.scope.prev) + state.scope = state.scope.prev; + state.dedent = false; + } + + return style; + } + + var external = { + startState: function(basecolumn) { + return { + tokenize: tokenBase, + scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false}, + prop: false, + dedent: 0 + }; + }, + + token: function(stream, state) { + var fillAlign = state.scope.align === null && state.scope; + if (fillAlign && stream.sol()) fillAlign.align = false; + + var style = tokenLexer(stream, state); + if (style && style != "comment") { + if (fillAlign) fillAlign.align = true; + state.prop = style == "punctuation" && stream.current() == "." + } + + return style; + }, + + indent: function(state, text) { + if (state.tokenize != tokenBase) return 0; + var scope = state.scope; + var closer = text && "])}".indexOf(text.charAt(0)) > -1; + if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev; + var closes = closer && scope.type === text.charAt(0); + if (scope.align) + return scope.alignOffset - (closes ? 1 : 0); + else + return (closes ? scope.prev : scope).offset; + }, + + lineComment: "#", + fold: "indent" + }; + return external; +}); + +// IANA registered media type +// https://www.iana.org/assignments/media-types/ +CodeMirror.defineMIME("application/vnd.coffeescript", "coffeescript"); + +CodeMirror.defineMIME("text/x-coffeescript", "coffeescript"); +CodeMirror.defineMIME("text/coffeescript", "coffeescript"); + +}); diff --git a/src/assets/plugins/codemirror/mode/coffeescript/index.html b/src/assets/plugins/codemirror/mode/coffeescript/index.html new file mode 100644 index 0000000..6d51aab --- /dev/null +++ b/src/assets/plugins/codemirror/mode/coffeescript/index.html @@ -0,0 +1,740 @@ + + +CodeMirror: CoffeeScript mode + + + + + + + + + +
      +

      CoffeeScript mode

      +
      + + +

      MIME types defined: application/vnd.coffeescript, text/coffeescript, text/x-coffeescript.

      + +

      The CoffeeScript mode was written by Jeff Pickhardt.

      + +
      diff --git a/src/codemirror/mode/css/css.js b/src/assets/plugins/codemirror/mode/css/css.js old mode 100755 new mode 100644 similarity index 80% rename from src/codemirror/mode/css/css.js rename to src/assets/plugins/codemirror/mode/css/css.js index 05742c5..441ba4a --- a/src/codemirror/mode/css/css.js +++ b/src/assets/plugins/codemirror/mode/css/css.js @@ -455,81 +455,98 @@ CodeMirror.defineMode("css", function(config, parserConfig) { "alignment-baseline", "anchor-point", "animation", "animation-delay", "animation-direction", "animation-duration", "animation-fill-mode", "animation-iteration-count", "animation-name", "animation-play-state", - "animation-timing-function", "appearance", "azimuth", "backface-visibility", - "background", "background-attachment", "background-blend-mode", "background-clip", - "background-color", "background-image", "background-origin", "background-position", - "background-repeat", "background-size", "baseline-shift", "binding", - "bleed", "bookmark-label", "bookmark-level", "bookmark-state", - "bookmark-target", "border", "border-bottom", "border-bottom-color", - "border-bottom-left-radius", "border-bottom-right-radius", - "border-bottom-style", "border-bottom-width", "border-collapse", - "border-color", "border-image", "border-image-outset", + "animation-timing-function", "appearance", "azimuth", "backdrop-filter", + "backface-visibility", "background", "background-attachment", + "background-blend-mode", "background-clip", "background-color", + "background-image", "background-origin", "background-position", + "background-position-x", "background-position-y", "background-repeat", + "background-size", "baseline-shift", "binding", "bleed", "block-size", + "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target", + "border", "border-bottom", "border-bottom-color", "border-bottom-left-radius", + "border-bottom-right-radius", "border-bottom-style", "border-bottom-width", + "border-collapse", "border-color", "border-image", "border-image-outset", "border-image-repeat", "border-image-slice", "border-image-source", - "border-image-width", "border-left", "border-left-color", - "border-left-style", "border-left-width", "border-radius", "border-right", - "border-right-color", "border-right-style", "border-right-width", - "border-spacing", "border-style", "border-top", "border-top-color", - "border-top-left-radius", "border-top-right-radius", "border-top-style", - "border-top-width", "border-width", "bottom", "box-decoration-break", - "box-shadow", "box-sizing", "break-after", "break-before", "break-inside", - "caption-side", "caret-color", "clear", "clip", "color", "color-profile", "column-count", - "column-fill", "column-gap", "column-rule", "column-rule-color", - "column-rule-style", "column-rule-width", "column-span", "column-width", - "columns", "content", "counter-increment", "counter-reset", "crop", "cue", - "cue-after", "cue-before", "cursor", "direction", "display", - "dominant-baseline", "drop-initial-after-adjust", - "drop-initial-after-align", "drop-initial-before-adjust", - "drop-initial-before-align", "drop-initial-size", "drop-initial-value", - "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", - "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", - "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings", - "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", - "font-stretch", "font-style", "font-synthesis", "font-variant", - "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", - "font-variant-ligatures", "font-variant-numeric", "font-variant-position", - "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", - "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap", - "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", - "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns", - "grid-template-rows", "hanging-punctuation", "height", "hyphens", - "icon", "image-orientation", "image-rendering", "image-resolution", - "inline-box-align", "justify-content", "justify-items", "justify-self", "left", "letter-spacing", - "line-break", "line-height", "line-stacking", "line-stacking-ruby", + "border-image-width", "border-left", "border-left-color", "border-left-style", + "border-left-width", "border-radius", "border-right", "border-right-color", + "border-right-style", "border-right-width", "border-spacing", "border-style", + "border-top", "border-top-color", "border-top-left-radius", + "border-top-right-radius", "border-top-style", "border-top-width", + "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing", + "break-after", "break-before", "break-inside", "caption-side", "caret-color", + "clear", "clip", "color", "color-profile", "column-count", "column-fill", + "column-gap", "column-rule", "column-rule-color", "column-rule-style", + "column-rule-width", "column-span", "column-width", "columns", "contain", + "content", "counter-increment", "counter-reset", "crop", "cue", "cue-after", + "cue-before", "cursor", "direction", "display", "dominant-baseline", + "drop-initial-after-adjust", "drop-initial-after-align", + "drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size", + "drop-initial-value", "elevation", "empty-cells", "fit", "fit-position", + "flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow", + "flex-shrink", "flex-wrap", "float", "float-offset", "flow-from", "flow-into", + "font", "font-family", "font-feature-settings", "font-kerning", + "font-language-override", "font-optical-sizing", "font-size", + "font-size-adjust", "font-stretch", "font-style", "font-synthesis", + "font-variant", "font-variant-alternates", "font-variant-caps", + "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric", + "font-variant-position", "font-variation-settings", "font-weight", "gap", + "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", "grid-auto-rows", + "grid-column", "grid-column-end", "grid-column-gap", "grid-column-start", + "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", "grid-row-start", + "grid-template", "grid-template-areas", "grid-template-columns", + "grid-template-rows", "hanging-punctuation", "height", "hyphens", "icon", + "image-orientation", "image-rendering", "image-resolution", "inline-box-align", + "inset", "inset-block", "inset-block-end", "inset-block-start", "inset-inline", + "inset-inline-end", "inset-inline-start", "isolation", "justify-content", + "justify-items", "justify-self", "left", "letter-spacing", "line-break", + "line-height", "line-height-step", "line-stacking", "line-stacking-ruby", "line-stacking-shift", "line-stacking-strategy", "list-style", "list-style-image", "list-style-position", "list-style-type", "margin", - "margin-bottom", "margin-left", "margin-right", "margin-top", - "marks", "marquee-direction", "marquee-loop", - "marquee-play-count", "marquee-speed", "marquee-style", "max-height", - "max-width", "min-height", "min-width", "mix-blend-mode", "move-to", "nav-down", "nav-index", - "nav-left", "nav-right", "nav-up", "object-fit", "object-position", - "opacity", "order", "orphans", "outline", - "outline-color", "outline-offset", "outline-style", "outline-width", - "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", - "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", - "page", "page-break-after", "page-break-before", "page-break-inside", - "page-policy", "pause", "pause-after", "pause-before", "perspective", - "perspective-origin", "pitch", "pitch-range", "place-content", "place-items", "place-self", "play-during", "position", - "presentation-level", "punctuation-trim", "quotes", "region-break-after", - "region-break-before", "region-break-inside", "region-fragment", - "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", - "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", - "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin", - "shape-outside", "size", "speak", "speak-as", "speak-header", - "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", - "tab-size", "table-layout", "target", "target-name", "target-new", - "target-position", "text-align", "text-align-last", "text-decoration", + "margin-bottom", "margin-left", "margin-right", "margin-top", "marks", + "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed", + "marquee-style", "max-block-size", "max-height", "max-inline-size", + "max-width", "min-block-size", "min-height", "min-inline-size", "min-width", + "mix-blend-mode", "move-to", "nav-down", "nav-index", "nav-left", "nav-right", + "nav-up", "object-fit", "object-position", "offset", "offset-anchor", + "offset-distance", "offset-path", "offset-position", "offset-rotate", + "opacity", "order", "orphans", "outline", "outline-color", "outline-offset", + "outline-style", "outline-width", "overflow", "overflow-style", + "overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom", + "padding-left", "padding-right", "padding-top", "page", "page-break-after", + "page-break-before", "page-break-inside", "page-policy", "pause", + "pause-after", "pause-before", "perspective", "perspective-origin", "pitch", + "pitch-range", "place-content", "place-items", "place-self", "play-during", + "position", "presentation-level", "punctuation-trim", "quotes", + "region-break-after", "region-break-before", "region-break-inside", + "region-fragment", "rendering-intent", "resize", "rest", "rest-after", + "rest-before", "richness", "right", "rotate", "rotation", "rotation-point", + "row-gap", "ruby-align", "ruby-overhang", "ruby-position", "ruby-span", + "scale", "scroll-behavior", "scroll-margin", "scroll-margin-block", + "scroll-margin-block-end", "scroll-margin-block-start", "scroll-margin-bottom", + "scroll-margin-inline", "scroll-margin-inline-end", + "scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right", + "scroll-margin-top", "scroll-padding", "scroll-padding-block", + "scroll-padding-block-end", "scroll-padding-block-start", + "scroll-padding-bottom", "scroll-padding-inline", "scroll-padding-inline-end", + "scroll-padding-inline-start", "scroll-padding-left", "scroll-padding-right", + "scroll-padding-top", "scroll-snap-align", "scroll-snap-type", + "shape-image-threshold", "shape-inside", "shape-margin", "shape-outside", + "size", "speak", "speak-as", "speak-header", "speak-numeral", + "speak-punctuation", "speech-rate", "stress", "string-set", "tab-size", + "table-layout", "target", "target-name", "target-new", "target-position", + "text-align", "text-align-last", "text-combine-upright", "text-decoration", "text-decoration-color", "text-decoration-line", "text-decoration-skip", - "text-decoration-style", "text-emphasis", "text-emphasis-color", - "text-emphasis-position", "text-emphasis-style", "text-height", - "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow", - "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position", - "text-wrap", "top", "transform", "transform-origin", "transform-style", - "transition", "transition-delay", "transition-duration", - "transition-property", "transition-timing-function", "unicode-bidi", - "user-select", "vertical-align", "visibility", "voice-balance", "voice-duration", - "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", - "voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break", - "word-spacing", "word-wrap", "z-index", + "text-decoration-skip-ink", "text-decoration-style", "text-emphasis", + "text-emphasis-color", "text-emphasis-position", "text-emphasis-style", + "text-height", "text-indent", "text-justify", "text-orientation", + "text-outline", "text-overflow", "text-rendering", "text-shadow", + "text-size-adjust", "text-space-collapse", "text-transform", + "text-underline-position", "text-wrap", "top", "transform", "transform-origin", + "transform-style", "transition", "transition-delay", "transition-duration", + "transition-property", "transition-timing-function", "translate", + "unicode-bidi", "user-select", "vertical-align", "visibility", "voice-balance", + "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate", + "voice-stress", "voice-volume", "volume", "white-space", "widows", "width", + "will-change", "word-break", "word-spacing", "word-wrap", "writing-mode", "z-index", // SVG-specific "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", @@ -543,16 +560,28 @@ CodeMirror.defineMode("css", function(config, parserConfig) { ], propertyKeywords = keySet(propertyKeywords_); var nonStandardPropertyKeywords_ = [ + "border-block", "border-block-color", "border-block-end", + "border-block-end-color", "border-block-end-style", "border-block-end-width", + "border-block-start", "border-block-start-color", "border-block-start-style", + "border-block-start-width", "border-block-style", "border-block-width", + "border-inline", "border-inline-color", "border-inline-end", + "border-inline-end-color", "border-inline-end-style", + "border-inline-end-width", "border-inline-start", "border-inline-start-color", + "border-inline-start-style", "border-inline-start-width", + "border-inline-style", "border-inline-width", "margin-block", + "margin-block-end", "margin-block-start", "margin-inline", "margin-inline-end", + "margin-inline-start", "padding-block", "padding-block-end", + "padding-block-start", "padding-inline", "padding-inline-end", + "padding-inline-start", "scroll-snap-stop", "scrollbar-3d-light-color", "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color", "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color", - "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside", - "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", - "searchfield-results-decoration", "zoom" + "scrollbar-track-color", "searchfield-cancel-button", "searchfield-decoration", + "searchfield-results-button", "searchfield-results-decoration", "shape-inside", "zoom" ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_); var fontProperties_ = [ - "font-family", "src", "unicode-range", "font-variant", "font-feature-settings", - "font-stretch", "font-weight", "font-style" + "font-display", "font-family", "src", "unicode-range", "font-variant", + "font-feature-settings", "font-stretch", "font-weight", "font-style" ], fontProperties = keySet(fontProperties_); var counterDescriptors_ = [ diff --git a/src/codemirror/mode/css/gss.html b/src/assets/plugins/codemirror/mode/css/gss.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/gss.html rename to src/assets/plugins/codemirror/mode/css/gss.html diff --git a/src/codemirror/mode/css/gss_test.js b/src/assets/plugins/codemirror/mode/css/gss_test.js old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/gss_test.js rename to src/assets/plugins/codemirror/mode/css/gss_test.js diff --git a/src/codemirror/mode/css/index.html b/src/assets/plugins/codemirror/mode/css/index.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/index.html rename to src/assets/plugins/codemirror/mode/css/index.html diff --git a/src/codemirror/mode/css/less.html b/src/assets/plugins/codemirror/mode/css/less.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/less.html rename to src/assets/plugins/codemirror/mode/css/less.html diff --git a/src/codemirror/mode/css/less_test.js b/src/assets/plugins/codemirror/mode/css/less_test.js old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/less_test.js rename to src/assets/plugins/codemirror/mode/css/less_test.js diff --git a/src/codemirror/mode/css/scss.html b/src/assets/plugins/codemirror/mode/css/scss.html old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/scss.html rename to src/assets/plugins/codemirror/mode/css/scss.html diff --git a/src/codemirror/mode/css/scss_test.js b/src/assets/plugins/codemirror/mode/css/scss_test.js old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/scss_test.js rename to src/assets/plugins/codemirror/mode/css/scss_test.js diff --git a/src/codemirror/mode/css/test.js b/src/assets/plugins/codemirror/mode/css/test.js old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/css/test.js rename to src/assets/plugins/codemirror/mode/css/test.js diff --git a/src/codemirror/mode/go/go.js b/src/assets/plugins/codemirror/mode/go/go.js old mode 100755 new mode 100644 similarity index 100% rename from src/codemirror/mode/go/go.js rename to src/assets/plugins/codemirror/mode/go/go.js diff --git a/src/codemirror/mode/go/index.html b/src/assets/plugins/codemirror/mode/go/index.html old mode 100755 new mode 100644 similarity index 98% rename from src/codemirror/mode/go/index.html rename to src/assets/plugins/codemirror/mode/go/index.html index 4489211..10ec024 --- a/src/codemirror/mode/go/index.html +++ b/src/assets/plugins/codemirror/mode/go/index.html @@ -11,7 +11,7 @@