codemirror: update to 5.58.1

This commit is contained in:
Silvan Calarco 2020-10-02 13:05:50 +02:00
parent 0c8fa3d288
commit 1c266a68b1
256 changed files with 5417 additions and 1669 deletions

View File

@ -0,0 +1,5 @@
<!--
Do not use this bug tracker for questions. We have a forum (https://discuss.codemirror.net) for those.
In order to get us to look at something, you need to make it easy for us to understand what you are doing and what went wrong. When possible, a code example that demonstrates the problem helps a lot. If there's any chance at all that a problem is related to the browser, include information about which browser(s) you tested with.
-->

View File

@ -0,0 +1,5 @@
<!--
NOTE: We are not accepting pull requests for new modes or addons. Please put such code in a separate repository, and release them as stand-alone npm packages. See for example the [Elixir mode](https://github.com/ianwalter/codemirror-mode-elixir).
Also pull requests that rewrite big chunks of code or adjust code style to your own taste are generally not welcome. Make your changes in focused steps that fix or improve a specific thing.
-->

View File

@ -15,11 +15,13 @@ Adán Lobato
Aditya Toshniwal Aditya Toshniwal
Adrian Aichner Adrian Aichner
Adrian Heine Adrian Heine
Adrian Kunz
Adrien Bertrand Adrien Bertrand
aeroson aeroson
Ahmad Amireh Ahmad Amireh
Ahmad M. Zawawi Ahmad M. Zawawi
ahoward ahoward
Ajin Abraham
Akeksandr Motsjonov Akeksandr Motsjonov
Alasdair Smith Alasdair Smith
AlbertHilb AlbertHilb
@ -31,6 +33,7 @@ Alexander Schepanovski
Alexander Shvets Alexander Shvets
Alexander Solovyov Alexander Solovyov
Alexandre Bique Alexandre Bique
Alex Churchill
alexey-k alexey-k
Alex Piggott Alex Piggott
Aliaksei Chapyzhenka Aliaksei Chapyzhenka
@ -72,11 +75,13 @@ anthonygego
Anthony Gégo Anthony Gégo
Anthony Grimes Anthony Grimes
Anton Kovalyov Anton Kovalyov
antosarho
Apollo Zhu Apollo Zhu
AQNOUCH Mohammed AQNOUCH Mohammed
Aram Shatakhtsyan Aram Shatakhtsyan
areos areos
Arnab Bose Arnab Bose
Arnoud Buzing
Arsène von Wyss Arsène von Wyss
Arthur Müller Arthur Müller
Arun Narasani Arun Narasani
@ -95,6 +100,9 @@ Bastian Müller
belhaj belhaj
Bem Jones-Bey Bem Jones-Bey
benbro benbro
Benedikt Meurer
benhormann
Ben Hormann
Beni Cherniavsky-Paskin Beni Cherniavsky-Paskin
Benjamin DeCoste Benjamin DeCoste
Benjamin Young Benjamin Young
@ -106,6 +114,7 @@ Bert Chang
Bharad Bharad
BigBlueHat BigBlueHat
Billy Moon Billy Moon
Bin Ni
binny binny
Bjorn Hansen Bjorn Hansen
B Krishna Chaitanya B Krishna Chaitanya
@ -115,12 +124,14 @@ Bo
boomyjee boomyjee
Bo Peng Bo Peng
borawjm borawjm
Boris K
Brad Metcalf Brad Metcalf
Brandon Frohs Brandon Frohs
Brandon Wamboldt Brandon Wamboldt
Bret Little Bret Little
Brett Zamir Brett Zamir
Brian Grinstead Brian Grinstead
BrianHung
Brian Sletten Brian Sletten
brrd brrd
Bruce Mitchener Bruce Mitchener
@ -132,6 +143,7 @@ Calin Barbat
callodacity callodacity
Camilo Roca Camilo Roca
Casey Klebba Casey Klebba
cBiscuit87
César González Íñiguez César González Íñiguez
Chad Jolly Chad Jolly
Chandra Sekhar Pydi Chandra Sekhar Pydi
@ -158,6 +170,7 @@ Christopher Pfohl
Christopher Wallis Christopher Wallis
Chunliang Lyu Chunliang Lyu
ciaranj ciaranj
clone-it
clso clso
CodeAnimal CodeAnimal
CodeBitt CodeBitt
@ -167,6 +180,7 @@ ComFreek
Cristian Prieto Cristian Prieto
Curran Kelleher Curran Kelleher
Curtis Gagliardi Curtis Gagliardi
d8888
dagsta dagsta
daines daines
Dale Jung Dale Jung
@ -194,6 +208,7 @@ David Barnett
David H. Bronke David H. Bronke
David Mignot David Mignot
David Pathakjee David Pathakjee
David Rodrigues
David Santana David Santana
David Vázquez David Vázquez
David Whittington David Whittington
@ -206,6 +221,7 @@ Dick Choi
Diego Fernandez Diego Fernandez
dignifiedquire dignifiedquire
Dimage Sapelkin Dimage Sapelkin
Dinindu D. Wanniarachchi
dmaclach dmaclach
Dmitry Kiselyov Dmitry Kiselyov
domagoj412 domagoj412
@ -221,10 +237,13 @@ Dror BG
Duncan Lilley Duncan Lilley
duralog duralog
dwelle dwelle
Ealton
eborden eborden
edoroshenko
edsharp edsharp
ekhaled ekhaled
Elisée Elisée
elpnt
Emmanuel Schanzer Emmanuel Schanzer
Enam Mijbah Noor Enam Mijbah Noor
Eric Allam Eric Allam
@ -249,11 +268,13 @@ Filype Pereira
finalfantasia finalfantasia
flack flack
Florian Felten Florian Felten
Fons van der Plas
Forbes Lindesay Forbes Lindesay
ForbesLindesay ForbesLindesay
Ford_Lawnmower Ford_Lawnmower
Forrest Oliphant Forrest Oliphant
Franco Catena Franco Catena
Frank Seifferth
Frank Wiegand Frank Wiegand
fraxx001 fraxx001
Fredrik Borg Fredrik Borg
@ -284,20 +305,25 @@ Grant Skinner
greengiant greengiant
Gregory Koberger Gregory Koberger
Grzegorz Mazur Grzegorz Mazur
Guang Li
Guan Gui Guan Gui
Guillaume Massé Guillaume Massé
Guillaume Massé Guillaume Massé
guraga guraga
Gustavo Rodrigues Gustavo Rodrigues
Hakan Tunc Hakan Tunc
Hanno Fellmann
Hans Engel Hans Engel
Hanzhao Deng Hanzhao Deng
Haoran Yu
Harald Schilly Harald Schilly
Hardest Hardest
Harshvardhan Gupta Harshvardhan Gupta
Hasan Delibaş
Hasan Karahan Hasan Karahan
Heanes Heanes
Hector Oswaldo Caballero Hector Oswaldo Caballero
Hein Htat
Hélio Hélio
Hendrik Wallbaum Hendrik Wallbaum
Henrik Haugbølle Henrik Haugbølle
@ -306,22 +332,29 @@ hidaiy
Hiroyuki Makino Hiroyuki Makino
hitsthings hitsthings
Hocdoc Hocdoc
Howard
Howard Jing
Hugues Malphettes Hugues Malphettes
Ian Beck Ian Beck
Ian Davies Ian Davies
Ian Dickinson Ian Dickinson
ianhi
Ian Rose Ian Rose
Ian Wehrman Ian Wehrman
Ian Wetherbee Ian Wetherbee
Ice White Ice White
ICHIKAWA, Yuji ICHIKAWA, Yuji
idleberg idleberg
Igor Petruk
ilvalle ilvalle
Ilya Kharlamov Ilya Kharlamov
Ilya Zverev
Ingo Richter Ingo Richter
Intervue
Irakli Gozalishvili Irakli Gozalishvili
Ivan Kurnosov Ivan Kurnosov
Ivoah Ivoah
Jack Douglas
Jacob Lee Jacob Lee
Jaimin Jaimin
Jake Peyser Jake Peyser
@ -329,6 +362,7 @@ Jakob Miland
Jakub Vrana Jakub Vrana
Jakub Vrána Jakub Vrána
James Campos James Campos
James Cockshull
James Howard James Howard
James Thorne James Thorne
Jamie Hill Jamie Hill
@ -351,6 +385,7 @@ Jason Johnston
Jason San Jose Jason San Jose
Jason Siefken Jason Siefken
Jayaprabhakar Jayaprabhakar
Jay Contonio
Jaydeep Solanki Jaydeep Solanki
Jean Boussier Jean Boussier
Jeff Blaisdell Jeff Blaisdell
@ -370,10 +405,13 @@ Joel Einbinder
joelpinheiro joelpinheiro
joewalsh joewalsh
Johan Ask Johan Ask
Johannes
John Chen
John Connor John Connor
John-David Dalton John-David Dalton
John Engler John Engler
John Lees-Miller John Lees-Miller
John Ryan
John Snelson John Snelson
John Van Der Loo John Van Der Loo
Jon Ander Peñalba Jon Ander Peñalba
@ -386,6 +424,7 @@ Jon Gacnik
jongalloway jongalloway
Jon Malmaud Jon Malmaud
Jon Sangster Jon Sangster
Joo
Joost-Wim Boekesteijn Joost-Wim Boekesteijn
Joseph Pecoraro Joseph Pecoraro
Josh Barnes Josh Barnes
@ -408,6 +447,7 @@ jwallers@gmail.com
kaniga kaniga
karevn karevn
Karol Karol
Kaushik Kulkarni
Kayur Patel Kayur Patel
Kazuhito Hokamura Kazuhito Hokamura
kcwiakala kcwiakala
@ -430,6 +470,7 @@ koops
Kris Ciccarello Kris Ciccarello
ks-ifware ks-ifware
kubelsmieci kubelsmieci
kvncp
KwanEsq KwanEsq
Kyle Kelley Kyle Kelley
KyleMcNutt KyleMcNutt
@ -438,6 +479,7 @@ Lanfei
Lanny Lanny
laobubu laobubu
Laszlo Vidacs Laszlo Vidacs
leaf
leaf corcoran leaf corcoran
Lemmon Lemmon
Leo Baschy Leo Baschy
@ -451,10 +493,12 @@ Lior Shub
LloydMilligan LloydMilligan
LM LM
lochel lochel
Lonnie Abelbeck
Lorenzo Simionato Lorenzo Simionato
Lorenzo Stoakes Lorenzo Stoakes
Louis Mauchet Louis Mauchet
Luca Fabbri Luca Fabbri
Lucas Buchala
Luciano Longo Luciano Longo
Luciano Santana Luciano Santana
Lu Fangjian Lu Fangjian
@ -481,6 +525,7 @@ Mário Gonçalves
Mario Pietsch Mario Pietsch
Mark Anderson Mark Anderson
Mark Dalgleish Mark Dalgleish
Mark Hamstra
Mark Lentczner Mark Lentczner
Marko Bonaci Marko Bonaci
Mark Peace Mark Peace
@ -499,11 +544,13 @@ mats cronqvist
Matt Gaide Matt Gaide
Matthew Bauer Matthew Bauer
Matthew Beale Matthew Beale
Matthew Casperson
matthewhayes matthewhayes
Matthew Rathbone Matthew Rathbone
Matthew Suozzo Matthew Suozzo
Matthias Bussonnier Matthias Bussonnier
Matthias BUSSONNIER Matthias BUSSONNIER
Mattia Astorino
Matt MacPherson Matt MacPherson
Matt McDonald Matt McDonald
Matt Pass Matt Pass
@ -518,6 +565,7 @@ Max Xiantu
mbarkhau mbarkhau
McBrainy McBrainy
mce2 mce2
Mélanie Chauvel
melpon melpon
meshuamam meshuamam
Metatheos Metatheos
@ -585,15 +633,21 @@ Nikita Vasilyev
Nikolaj Kappler Nikolaj Kappler
Nikolay Kostov Nikolay Kostov
nilp0inter nilp0inter
Nils Knappmeier
Nisarg Jhaveri Nisarg Jhaveri
nlwillia nlwillia
noragrossman noragrossman
Norman Rzepka Norman Rzepka
Nouzbe Nouzbe
Oleksandr Yakovenko Oleksandr Yakovenko
Olivia Ytterbrink
Opender Singh
opl- opl-
Oreoluwa Onatemowo Oreoluwa Onatemowo
orionlee
oscar.lofwenhamn
Oskar Segersvärd Oskar Segersvärd
ossdev
overdodactyl overdodactyl
pablo pablo
pabloferz pabloferz
@ -606,11 +660,13 @@ paris
Paris Paris
Paris Kasidiaris Paris Kasidiaris
Patil Arpith Patil Arpith
Patrick Kettner
Patrick Stoica Patrick Stoica
Patrick Strawderman Patrick Strawderman
Paul Garvin Paul Garvin
Paul Ivanov Paul Ivanov
Paul Masson Paul Masson
Paul Schmidt
Pavel Pavel
Pavel Feldman Pavel Feldman
Pavel Petržela Pavel Petržela
@ -621,6 +677,7 @@ peter
Peter Flynn Peter Flynn
peterkroon peterkroon
Peter Kroon Peter Kroon
Peter László
Philipp A Philipp A
Philipp Markovics Philipp Markovics
Philip Stadermann Philip Stadermann
@ -631,6 +688,7 @@ Pontus Melke
prasanthj prasanthj
Prasanth J Prasanth J
Prayag Verma Prayag Verma
prendota
Prendota Prendota
Qiang Li Qiang Li
Radek Piórkowski Radek Piórkowski
@ -644,6 +702,7 @@ Randy Luecke
Raphael Amorim Raphael Amorim
Rasmus Erik Voel Jensen Rasmus Erik Voel Jensen
Rasmus Schultz Rasmus Schultz
raymondf
Raymond Hill Raymond Hill
ray ratchup ray ratchup
Ray Ratchup Ray Ratchup
@ -659,10 +718,14 @@ Robert Crossfield
Robert Martin Robert Martin
Roberto Abdelkader Martínez Pérez Roberto Abdelkader Martínez Pérez
robertop23 robertop23
Roberto Vidal
Robert Plummer Robert Plummer
Roman Janusz
Rrandom Rrandom
Rrrandom Rrrandom
Ruslan Osmanov Ruslan Osmanov
rvalavicius
Ryan Pangrle
Ryan Petrello Ryan Petrello
Ryan Prior Ryan Prior
ryu-sato ryu-sato
@ -705,6 +768,7 @@ Shiv Deepak
Shmuel Englard Shmuel Englard
Shubham Jain Shubham Jain
Siamak Mokhtari Siamak Mokhtari
Siddhartha Gunti
silverwind silverwind
Simon Edwards Simon Edwards
sinkuu sinkuu
@ -738,7 +802,9 @@ Tako Schotanus
Takuji Shimokawa Takuji Shimokawa
Takuya Matsuyama Takuya Matsuyama
Tarmil Tarmil
T. Brandon Ashley
TDaglis TDaglis
Teja
tel tel
Tentone Tentone
tfjgeorge tfjgeorge
@ -754,13 +820,16 @@ thomasmaclean
Thomas Schmid Thomas Schmid
Tim Alby Tim Alby
Tim Baumann Tim Baumann
Tim Gates
Timothy Farrell Timothy Farrell
Timothy Gu Timothy Gu
Timothy Hatcher Timothy Hatcher
Tim van der Lippe
Tobias Bertelsen Tobias Bertelsen
TobiasBg TobiasBg
Todd Berman Todd Berman
Todd Kennedy Todd Kennedy
tokafew420
Tomas-A Tomas-A
Tomas Varaneckas Tomas Varaneckas
Tom Erik Støwer Tom Erik Støwer
@ -778,9 +847,11 @@ TSUYUSATO Kitsune
Tugrul Elmas Tugrul Elmas
twifkak twifkak
Tyler Long Tyler Long
Tyler Makaro
Vadim Dyachenko Vadim Dyachenko
Vadzim Ramanenka Vadzim Ramanenka
Vaibhav Sagar Vaibhav Sagar
vamshi.revu
VapidWorx VapidWorx
Vestimir Markov Vestimir Markov
vf vf
@ -813,8 +884,10 @@ Yuvi Panda
Yvonnick Esnault Yvonnick Esnault
Zac Anger Zac Anger
Zachary Dremann Zachary Dremann
ZeeshanNoor
Zeno Rocha Zeno Rocha
Zhang Hao Zhang Hao
Ziv Ziv
zoobestik
zziuni zziuni
魏鹏刚 魏鹏刚

View File

@ -1,3 +1,263 @@
## 5.58.1 (2020-09-23)
### Bug fixes
[placeholder addon](https://codemirror.net/doc/manual.html#addon_placeholder): Remove arrow function that ended up in the code.
## 5.58.0 (2020-09-21)
### Bug fixes
Make backspace delete by code point, not glyph.
Suppress flickering focus outline when clicking on scrollbars in Chrome.
Fix a bug that prevented attributes added via `markText` from showing up unless the span also had some other styling.
Suppress cut and paste context menu entries in readonly editors in Chrome.
[placeholder addon](https://codemirror.net/doc/manual.html#addon_placeholder): Update placeholder visibility during composition.
### New features
Make it less cumbersome to style new lint message types.
[vim bindings](https://codemirror.net/demo/vim.html): Support black hole register, `gn` and `gN`
## 5.57.0 (2020-08-20)
### Bug fixes
Fix issue that broke binding the macOS Command key.
[comment addon](https://codemirror.net/doc/manual.html#addon_comment): Keep selection in front of inserted markers when adding a block comment.
[css mode](https://codemirror.net/mode/css/): Recognize more properties and value names.
[annotatescrollbar addon](https://codemirror.net/doc/manual.html#addon_annotatescrollbar): Don't hide matches in collapsed content.
### New features
[vim bindings](https://codemirror.net/demo/vim.html): Support tag text objects in xml and html modes.
## 5.56.0 (2020-07-20)
### Bug fixes
Line-wise pasting was fixed on Chrome Windows.
[wast mode](https://codemirror.net/mode/wast/): Follow standard changes.
[soy mode](https://codemirror.net/mode/soy/): Support import expressions, template type, and loop indices.
[sql-hint addon](https://codemirror.net/doc/manual.html#addon_sql-hint): Improve handling of double quotes.
### New features
[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): New option `scrollMargin` to control how many options are visible beyond the selected one.
[hardwrap addon](https://codemirror.net/doc/manual.html#addon_hardwrap): New option `forceBreak` to disable breaking of words that are longer than a line.
## 5.55.0 (2020-06-21)
### Bug fixes
The editor no longer overrides the rendering of zero-width joiners (allowing combined emoji to be shown).
[vim bindings](https://codemirror.net/demo/vim.html): Fix an issue where the `vim-mode-change` event was fired twice.
[javascript mode](https://codemirror.net/mode/javascript/): Only allow `-->`-style comments at the start of a line.
[julia mode](https://codemirror.net/mode/julia/): Improve indentation.
[pascal mode](https://codemirror.net/mode/pascal/index.html): Recognize curly bracket comments.
[runmode addon](https://codemirror.net/doc/manual.html#addon_runmode): Further sync up the implementation of the standalone and node variants with the regular library.
### New features
[loadmode addon](https://codemirror.net/doc/manual.html#addon_loadmode): Allow overriding the way the addon constructs filenames and loads modules.
## 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 `<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](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) ## 5.48.2 (2019-07-20)
### Bug fixes ### Bug fixes

View File

@ -13,7 +13,7 @@
var noOptions = {}; var noOptions = {};
var nonWS = /[^\s\u00a0]/; var nonWS = /[^\s\u00a0]/;
var Pos = CodeMirror.Pos; var Pos = CodeMirror.Pos, cmp = CodeMirror.cmpPos;
function firstNonWS(str) { function firstNonWS(str) {
var found = str.search(nonWS); var found = str.search(nonWS);
@ -126,7 +126,9 @@
if (i != end || lastLineHasText) if (i != end || lastLineHasText)
self.replaceRange(lead + pad, Pos(i, 0)); self.replaceRange(lead + pad, Pos(i, 0));
} else { } else {
var atCursor = cmp(self.getCursor("to"), to) == 0, empty = !self.somethingSelected()
self.replaceRange(endString, to); self.replaceRange(endString, to);
if (atCursor) self.setSelection(empty ? to : self.getCursor("from"), to)
self.replaceRange(startString, from); self.replaceRange(startString, from);
} }
}); });

View File

@ -9,6 +9,8 @@
else // Plain browser env else // Plain browser env
mod(CodeMirror); mod(CodeMirror);
})(function(CodeMirror) { })(function(CodeMirror) {
var nonspace = /\S/g;
var repeat = String.prototype.repeat || function (n) { return Array(n + 1).join(this); };
function continueComment(cm) { function continueComment(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass; if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), mode, inserts = []; var ranges = cm.listSelections(), mode, inserts = [];
@ -19,29 +21,57 @@
if (!mode) mode = modeHere; if (!mode) mode = modeHere;
else if (mode != modeHere) return CodeMirror.Pass; else if (mode != modeHere) return CodeMirror.Pass;
var insert = null; var insert = null, line, found;
if (mode.blockCommentStart && mode.blockCommentContinue) { var blockStart = mode.blockCommentStart, lineCmt = mode.lineComment;
var line = cm.getLine(pos.line).slice(0, pos.ch) if (blockStart && mode.blockCommentContinue) {
var end = line.lastIndexOf(mode.blockCommentEnd), found line = cm.getLine(pos.line);
if (end != -1 && end == pos.ch - mode.blockCommentEnd.length) { var end = line.lastIndexOf(mode.blockCommentEnd, pos.ch - mode.blockCommentEnd.length);
// Comment ended, don't continue it // 1. if this block comment ended
} else if ((found = line.lastIndexOf(mode.blockCommentStart)) > -1 && found > end) { // 2. if this is actually inside a line comment
insert = line.slice(0, found) if (end != -1 && end == pos.ch - mode.blockCommentEnd.length ||
if (/\S/.test(insert)) { lineCmt && (found = line.lastIndexOf(lineCmt, pos.ch - 1)) > -1 &&
insert = "" /\bcomment\b/.test(cm.getTokenTypeAt({line: pos.line, ch: found + 1}))) {
for (var j = 0; j < found; ++j) insert += " " // ...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 && !/\S/.test(line.slice(0, found))) { } else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 &&
insert = line.slice(0, found) found <= pos.ch &&
found <= nonspaceAfter(0, line)) {
insert = line.slice(0, found);
} }
if (insert != null) insert += mode.blockCommentContinue if (insert != null) insert += mode.blockCommentContinue
} }
if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) { if (insert == null && lineCmt && continueLineCommentEnabled(cm)) {
var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment); if (line == null) line = cm.getLine(pos.line);
if (found > -1) { found = line.indexOf(lineCmt);
insert = line.slice(0, found); // cursor at pos 0, line comment also at pos 0 => shift it down, don't continue
if (/\S/.test(insert)) insert = null; if (!pos.ch && !found) insert = "";
else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0]; // 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; if (insert == null) return CodeMirror.Pass;
@ -54,6 +84,12 @@
}); });
} }
function nonspaceAfter(ch, str) {
nonspace.lastIndex = ch;
var m = nonspace.exec(str);
return m ? m.index : -1;
}
function continueLineCommentEnabled(cm) { function continueLineCommentEnabled(cm) {
var opt = cm.getOption("continueComments"); var opt = cm.getOption("continueComments");
if (opt && typeof opt == "object") if (opt && typeof opt == "object")

View File

@ -82,7 +82,9 @@
if (e.keyCode == 13) callback(inp.value, e); 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]) { } else if (button = dialog.getElementsByTagName("button")[0]) {
CodeMirror.on(button, "click", function() { CodeMirror.on(button, "click", function() {
close(); close();

View File

@ -1,15 +1,15 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE // Distributed under an MIT license: https://codemirror.net/LICENSE
(function(mod) { (function (mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror")); mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod); define(["../../lib/codemirror"], mod);
else // Plain browser env else // Plain browser env
mod(CodeMirror); mod(CodeMirror);
})(function(CodeMirror) { })(function (CodeMirror) {
CodeMirror.defineExtension("addPanel", function(node, options) { CodeMirror.defineExtension("addPanel", function (node, options) {
options = options || {}; options = options || {};
if (!this.state.panels) initPanels(this); if (!this.state.panels) initPanels(this);
@ -25,8 +25,7 @@
wrapper.insertBefore(node, options.before.node); wrapper.insertBefore(node, options.before.node);
} else if (replace) { } else if (replace) {
wrapper.insertBefore(node, options.replace.node); wrapper.insertBefore(node, options.replace.node);
info.panels++; options.replace.clear(true);
options.replace.clear();
} else if (options.position == "bottom") { } else if (options.position == "bottom") {
wrapper.appendChild(node); wrapper.appendChild(node);
} else if (options.position == "before-bottom") { } else if (options.position == "before-bottom") {
@ -38,14 +37,15 @@
} }
var height = (options && options.height) || node.offsetHeight; 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) { function Panel(cm, node, options, height) {
@ -56,22 +56,23 @@
this.cleared = false; 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; if (this.cleared) return;
this.cleared = true; this.cleared = true;
var info = this.cm.state.panels; 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)) if (this.options.stable && isAtTop(this.cm, this.node))
this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height) this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height)
info.wrapper.removeChild(this.node); 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) { Panel.prototype.changed = function () {
var newHeight = height == null ? this.node.offsetHeight : height; this.height = this.node.getBoundingClientRect().height;
var info = this.cm.state.panels; this.cm.setSize();
this.cm._setSize(null, info.heightLeft -= (newHeight - this.height));
this.height = newHeight;
}; };
function initPanels(cm) { function initPanels(cm) {
@ -80,8 +81,7 @@
var height = parseInt(style.height); var height = parseInt(style.height);
var info = cm.state.panels = { var info = cm.state.panels = {
setHeight: wrap.style.height, setHeight: wrap.style.height,
heightLeft: height, panels: [],
panels: 0,
wrapper: document.createElement("div") wrapper: document.createElement("div")
}; };
wrap.parentNode.insertBefore(info.wrapper, wrap); wrap.parentNode.insertBefore(info.wrapper, wrap);
@ -90,8 +90,8 @@
if (hasFocus) cm.focus(); if (hasFocus) cm.focus();
cm._setSize = cm.setSize; cm._setSize = cm.setSize;
if (height != null) cm.setSize = function(width, newHeight) { if (height != null) cm.setSize = function (width, newHeight) {
if (newHeight == null) return this._setSize(width, newHeight); if (!newHeight) newHeight = info.wrapper.offsetHeight;
info.setHeight = newHeight; info.setHeight = newHeight;
if (typeof newHeight != "number") { if (typeof newHeight != "number") {
var px = /^(\d+\.?\d*)px$/.exec(newHeight); var px = /^(\d+\.?\d*)px$/.exec(newHeight);
@ -100,10 +100,12 @@
} else { } else {
info.wrapper.style.height = newHeight; info.wrapper.style.height = newHeight;
newHeight = info.wrapper.offsetHeight; 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; height = newHeight;
}; };
} }

View File

@ -15,11 +15,13 @@
cm.on("blur", onBlur); cm.on("blur", onBlur);
cm.on("change", onChange); cm.on("change", onChange);
cm.on("swapDoc", onChange); cm.on("swapDoc", onChange);
CodeMirror.on(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose = function() { onComposition(cm) })
onChange(cm); onChange(cm);
} else if (!val && prev) { } else if (!val && prev) {
cm.off("blur", onBlur); cm.off("blur", onBlur);
cm.off("change", onChange); cm.off("change", onChange);
cm.off("swapDoc", onChange); cm.off("swapDoc", onChange);
CodeMirror.off(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose)
clearPlaceholder(cm); clearPlaceholder(cm);
var wrapper = cm.getWrapperElement(); var wrapper = cm.getWrapperElement();
wrapper.className = wrapper.className.replace(" CodeMirror-empty", ""); wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
@ -39,13 +41,25 @@
var elt = cm.state.placeholder = document.createElement("pre"); var elt = cm.state.placeholder = document.createElement("pre");
elt.style.cssText = "height: 0; overflow: visible"; elt.style.cssText = "height: 0; overflow: visible";
elt.style.direction = cm.getOption("direction"); elt.style.direction = cm.getOption("direction");
elt.className = "CodeMirror-placeholder"; elt.className = "CodeMirror-placeholder CodeMirror-line-like";
var placeHolder = cm.getOption("placeholder") var placeHolder = cm.getOption("placeholder")
if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder) if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
elt.appendChild(placeHolder) elt.appendChild(placeHolder)
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild); cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
} }
function onComposition(cm) {
setTimeout(function() {
var empty = false, input = cm.getInputField()
if (input.nodeName == "TEXTAREA")
empty = !input.value
else if (cm.lineCount() == 1)
empty = !/[^\u200b]/.test(input.querySelector(".CodeMirror-line").textContent)
if (empty) setPlaceholder(cm)
else clearPlaceholder(cm)
}, 20)
}
function onBlur(cm) { function onBlur(cm) {
if (isEmpty(cm)) setPlaceholder(cm); if (isEmpty(cm)) setPlaceholder(cm);
} }

View File

@ -40,9 +40,9 @@
cm.removeKeyMap("autoCloseTags"); cm.removeKeyMap("autoCloseTags");
if (!val) return; if (!val) return;
var map = {name: "autoCloseTags"}; var map = {name: "autoCloseTags"};
if (typeof val != "object" || val.whenClosing) if (typeof val != "object" || val.whenClosing !== false)
map["'/'"] = function(cm) { return autoCloseSlash(cm); }; map["'/'"] = function(cm) { return autoCloseSlash(cm); };
if (typeof val != "object" || val.whenOpening) if (typeof val != "object" || val.whenOpening !== false)
map["'>'"] = function(cm) { return autoCloseGT(cm); }; map["'>'"] = function(cm) { return autoCloseGT(cm); };
cm.addKeyMap(map); cm.addKeyMap(map);
}); });
@ -60,22 +60,23 @@
if (!ranges[i].empty()) return CodeMirror.Pass; if (!ranges[i].empty()) return CodeMirror.Pass;
var pos = ranges[i].head, tok = cm.getTokenAt(pos); var pos = ranges[i].head, tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state; 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 html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent); 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); if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
var lowerTagName = tagName.toLowerCase(); var lowerTagName = tagName.toLowerCase();
// Don't process the '>' at the end of an end-tag or self-closing tag // Don't process the '>' at the end of an end-tag or self-closing tag
if (!tagName || if (!tagName ||
tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) || 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.type == "tag" && tagInfo.close ||
tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName /> tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like <someTagName />
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 || 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; return CodeMirror.Pass;
var emptyTags = typeof opt == "object" && opt.emptyTags; var emptyTags = typeof opt == "object" && opt.emptyTags;
@ -120,19 +121,16 @@
// when completing in JS/CSS snippet in htmlmixed mode. Does not // when completing in JS/CSS snippet in htmlmixed mode. Does not
// work for other XML embedded languages (there is no general // work for other XML embedded languages (there is no general
// way to go from a mixed mode to its current XML state). // way to go from a mixed mode to its current XML state).
var replacement; var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
if (inner.mode.name != "xml") { if (mixed && inner.mode.name == "javascript") {
if (cm.getMode().name == "htmlmixed" && inner.mode.name == "javascript") replacement = head + "script";
replacement = head + "script"; } else if (mixed && inner.mode.name == "css") {
else if (cm.getMode().name == "htmlmixed" && inner.mode.name == "css") replacement = head + "style";
replacement = head + "style";
else
return CodeMirror.Pass;
} else { } else {
if (!state.context || !state.context.tagName || var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
closingTagExists(cm, state.context.tagName, pos, state)) if (!context || (context.length && closingTagExists(cm, context, context[context.length - 1], pos)))
return CodeMirror.Pass; return CodeMirror.Pass;
replacement = head + state.context.tagName; replacement = head + context[context.length - 1]
} }
if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">"; if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
replacements[i] = replacement; replacements[i] = replacement;
@ -162,16 +160,19 @@
// If xml-fold is loaded, we use its functionality to try and verify // If xml-fold is loaded, we use its functionality to try and verify
// whether a given tag is actually unclosed. // 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; if (!CodeMirror.scanForClosingTag) return false;
var end = Math.min(cm.lastLine() + 1, pos.line + 500); var end = Math.min(cm.lastLine() + 1, pos.line + 500);
var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end); var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
if (!nextClose || nextClose.tag != tagName) return false; if (!nextClose || nextClose.tag != tagName) return false;
var cx = state.context;
// If the immediate wrapping context contains onCx instances of // If the immediate wrapping context contains onCx instances of
// the same tag, a closing tag only exists if there are at least // the same tag, a closing tag only exists if there are at least
// that many closing tags of that type following. // 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; pos = nextClose.to;
for (var i = 1; i < onCx; i++) { for (var i = 1; i < onCx; i++) {
var next = CodeMirror.scanForClosingTag(cm, pos, null, end); var next = CodeMirror.scanForClosingTag(cm, pos, null, end);

View File

@ -41,7 +41,9 @@
return; return;
} }
if (emptyListRE.test(line)) { 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: 0
}, { }, {
line: pos.line, ch: pos.ch + 1 line: pos.line, ch: pos.ch + 1

View File

@ -118,16 +118,24 @@
} }
CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) { function clear(cm) {
cm.off("cursorActivity", doMatchBrackets);
if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) { if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
cm.state.matchBrackets.currentlyHighlighted(); cm.state.matchBrackets.currentlyHighlighted();
cm.state.matchBrackets.currentlyHighlighted = null; 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) { if (val) {
cm.state.matchBrackets = typeof val == "object" ? val : {}; cm.state.matchBrackets = typeof val == "object" ? val : {};
cm.on("cursorActivity", doMatchBrackets); cm.on("cursorActivity", doMatchBrackets);
cm.on("focus", doMatchBrackets)
cm.on("blur", clear)
} }
}); });

View File

@ -42,7 +42,7 @@
} }
if (!range || range.cleared || force === "unfold") return; if (!range || range.cleared || force === "unfold") return;
var myWidget = makeWidget(cm, options); var myWidget = makeWidget(cm, options, range);
CodeMirror.on(myWidget, "mousedown", function(e) { CodeMirror.on(myWidget, "mousedown", function(e) {
myRange.clear(); myRange.clear();
CodeMirror.e_preventDefault(e); CodeMirror.e_preventDefault(e);
@ -58,8 +58,13 @@
CodeMirror.signal(cm, "fold", cm, range.from, range.to); CodeMirror.signal(cm, "fold", cm, range.from, range.to);
} }
function makeWidget(cm, options) { function makeWidget(cm, options, range) {
var widget = getOption(cm, options, "widget"); var widget = getOption(cm, options, "widget");
if (typeof widget == "function") {
widget = widget(range.from, range.to);
}
if (typeof widget == "string") { if (typeof widget == "string") {
var text = document.createTextNode(widget); var text = document.createTextNode(widget);
widget = document.createElement("span"); widget = document.createElement("span");

View File

@ -16,7 +16,7 @@
cm.clearGutter(cm.state.foldGutter.options.gutter); cm.clearGutter(cm.state.foldGutter.options.gutter);
cm.state.foldGutter = null; cm.state.foldGutter = null;
cm.off("gutterClick", onGutterClick); cm.off("gutterClick", onGutterClick);
cm.off("change", onChange); cm.off("changes", onChange);
cm.off("viewportChange", onViewportChange); cm.off("viewportChange", onViewportChange);
cm.off("fold", onFold); cm.off("fold", onFold);
cm.off("unfold", onFold); cm.off("unfold", onFold);
@ -26,7 +26,7 @@
cm.state.foldGutter = new State(parseOptions(val)); cm.state.foldGutter = new State(parseOptions(val));
updateInViewport(cm); updateInViewport(cm);
cm.on("gutterClick", onGutterClick); cm.on("gutterClick", onGutterClick);
cm.on("change", onChange); cm.on("changes", onChange);
cm.on("viewportChange", onViewportChange); cm.on("viewportChange", onViewportChange);
cm.on("fold", onFold); cm.on("fold", onFold);
cm.on("unfold", onFold); cm.on("unfold", onFold);
@ -51,8 +51,13 @@
function isFolded(cm, line) { function isFolded(cm, line) {
var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0)); var marks = cm.findMarks(Pos(line, 0), Pos(line + 1, 0));
for (var i = 0; i < marks.length; ++i) for (var i = 0; i < marks.length; ++i) {
if (marks[i].__isFold && marks[i].find().from.line == line) return marks[i]; if (marks[i].__isFold) {
var fromPos = marks[i].find(-1);
if (fromPos && fromPos.line === line)
return marks[i];
}
}
} }
function marker(spec) { function marker(spec) {
@ -66,24 +71,36 @@
} }
function updateFoldInfo(cm, from, to) { 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 minSize = cm.foldOption(opts, "minFoldSize");
var func = cm.foldOption(opts, "rangeFinder"); 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) { cm.eachLine(from, to, function(line) {
++cur;
var mark = null; var mark = null;
var old = line.gutterMarkers;
if (old) old = old[opts.gutter];
if (isFolded(cm, cur)) { if (isFolded(cm, cur)) {
if (clsFolded && old && clsFolded.test(old.className)) return;
mark = marker(opts.indicatorFolded); mark = marker(opts.indicatorFolded);
} else { } else {
var pos = Pos(cur, 0); var pos = Pos(cur, 0);
var range = func && func(cm, pos); 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); mark = marker(opts.indicatorOpen);
}
} }
if (!mark && !old) return;
cm.setGutterMarker(line, opts.gutter, mark); 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) { function updateInViewport(cm) {
var vp = cm.getViewport(), state = cm.state.foldGutter; var vp = cm.getViewport(), state = cm.state.foldGutter;
if (!state) return; if (!state) return;
@ -100,7 +117,7 @@
if (gutter != opts.gutter) return; if (gutter != opts.gutter) return;
var folded = isFolded(cm, line); var folded = isFolded(cm, line);
if (folded) folded.clear(); if (folded) folded.clear();
else cm.foldCode(Pos(line, 0), opts.rangeFinder); else cm.foldCode(Pos(line, 0), opts);
} }
function onChange(cm) { function onChange(cm) {

View File

@ -11,9 +11,15 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1, var pseudoClasses = {"active":1, "after":1, "before":1, "checked":1, "default":1,
"first-letter": 1, "first-line": 1, "first-child": 1, "disabled":1, "empty":1, "enabled":1, "first-child":1, "first-letter":1,
before: 1, after: 1, lang: 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) { CodeMirror.registerHelper("hint", "css", function(cm) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur); var cur = cm.getCursor(), token = cm.getTokenAt(cur);

View File

@ -144,10 +144,15 @@
base = base[context.pop().string]; base = base[context.pop().string];
if (base != null) gatherCompletions(base); if (base != null) gatherCompletions(base);
} else { } 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) // (reading into JS mode internals to get at the local and global variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name); for (var v = token.state.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); 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) if (!options || options.useGlobalScope !== false)
gatherCompletions(global); gatherCompletions(global);
forEach(keywords, maybeAdd); forEach(keywords, maybeAdd);

View File

@ -85,11 +85,16 @@
}, },
pick: function(data, i) { pick: function(data, i) {
var completion = data.list[i]; var completion = data.list[i], self = this;
if (completion.hint) completion.hint(this.cm, data, completion); this.cm.operation(function() {
else this.cm.replaceRange(getText(completion), completion.from || data.from, if (completion.hint)
completion.to || data.to, "complete"); completion.hint(self.cm, data, completion);
CodeMirror.signal(data, "pick", 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(); this.close();
}, },
@ -99,9 +104,14 @@
this.debounce = 0; 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); 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 || 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)))) { (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
this.close(); this.close();
} else { } else {
@ -322,6 +332,7 @@
CodeMirror.on(hints, "mousedown", function() { CodeMirror.on(hints, "mousedown", function() {
setTimeout(function(){cm.focus();}, 20); setTimeout(function(){cm.focus();}, 20);
}); });
this.scrollToActive()
CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]); CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
return true; return true;
@ -363,13 +374,21 @@
if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, ""); if (node) node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
node = this.hints.childNodes[this.selectedHint = i]; node = this.hints.childNodes[this.selectedHint = i];
node.className += " " + ACTIVE_HINT_ELEMENT_CLASS; node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
if (node.offsetTop < this.hints.scrollTop) this.scrollToActive()
this.hints.scrollTop = node.offsetTop - 3;
else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node); CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
}, },
scrollToActive: function() {
var margin = this.completion.options.scrollMargin || 0;
var node1 = this.hints.childNodes[Math.max(0, this.selectedHint - margin)];
var node2 = this.hints.childNodes[Math.min(this.data.list.length - 1, this.selectedHint + margin)];
var firstNode = this.hints.firstChild;
if (node1.offsetTop < this.hints.scrollTop)
this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
},
screenAmount: function() { screenAmount: function() {
return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1; return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
} }

View File

@ -264,7 +264,7 @@
token.string = token.string.slice(0, cur.ch - token.start); token.string = token.string.slice(0, cur.ch - token.start);
} }
if (token.string.match(/^[.`"\w@]\w*$/)) { if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
search = token.string; search = token.string;
start = token.start; start = token.start;
end = token.end; end = token.end;

View File

@ -29,7 +29,7 @@
token.string = token.string.slice(0, cur.ch - token.start); token.string = token.string.slice(0, cur.ch - token.start);
} }
var inner = CodeMirror.innerMode(cm.getMode(), token.state); 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 result = [], replaceToken = false, prefix;
var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string); var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
var tagName = tag && /^\w/.test(token.string), tagStart; var tagName = tag && /^\w/.test(token.string), tagStart;
@ -44,12 +44,15 @@
tagType = "close"; tagType = "close";
} }
if (!tag && !inner.state.tagName || tagType) { var tagInfo = inner.mode.xmlCurrentTag(inner.state)
if (!tag && !tagInfo || tagType) {
if (tagName) if (tagName)
prefix = token.string; prefix = token.string;
replaceToken = tagType; replaceToken = tagType;
var cx = inner.state.context, curTag = cx && tags[cx.tagName]; var context = inner.mode.xmlCurrentContext ? inner.mode.xmlCurrentContext(inner.state) : []
var childList = cx ? curTag && curTag.children : tags["!top"]; 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") { if (childList && tagType != "close") {
for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle)) for (var i = 0; i < childList.length; ++i) if (!prefix || matches(childList[i], prefix, matchInMiddle))
result.push("<" + childList[i]); result.push("<" + childList[i]);
@ -58,11 +61,11 @@
if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle))) if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || matches(name, prefix, matchInMiddle)))
result.push("<" + name); result.push("<" + name);
} }
if (cx && (!prefix || tagType == "close" && matches(cx.tagName, prefix, matchInMiddle))) if (inner && (!prefix || tagType == "close" && matches(inner, prefix, matchInMiddle)))
result.push("</" + cx.tagName + ">"); result.push("</" + inner + ">");
} else { } else {
// Attribute completion // 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"]; var globalAttrs = tags["!attrs"];
if (!attrs && !globalAttrs) return; if (!attrs && !globalAttrs) return;
if (!attrs) { if (!attrs) {
@ -98,8 +101,14 @@
} }
replaceToken = true; replaceToken = true;
} }
for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle)) function returnHintsFromAtValues(atValues) {
result.push(quote + atValues[i] + quote); if (atValues)
for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
result.push(quote + atValues[i] + quote);
return returnHints();
}
if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
return returnHintsFromAtValues(atValues);
} else { // An attribute name } else { // An attribute name
if (token.type == "attribute") { if (token.type == "attribute") {
prefix = token.string; prefix = token.string;
@ -109,11 +118,14 @@
result.push(attr); result.push(attr);
} }
} }
return { function returnHints() {
list: result, return {
from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur, list: result,
to: replaceToken ? Pos(cur.line, token.end) : cur from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
}; to: replaceToken ? Pos(cur.line, token.end) : cur
};
}
return returnHints();
} }
CodeMirror.registerHelper("hint", "xml", getHints); CodeMirror.registerHelper("hint", "xml", getHints);

View File

@ -25,22 +25,20 @@
-ms-transition: opacity .4s; -ms-transition: opacity .4s;
} }
.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning { .CodeMirror-lint-mark {
background-position: left bottom; background-position: left bottom;
background-repeat: repeat-x; background-repeat: repeat-x;
} }
.CodeMirror-lint-mark-error {
background-image:
url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
;
}
.CodeMirror-lint-mark-warning { .CodeMirror-lint-mark-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII="); background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
} }
.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning { .CodeMirror-lint-mark-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==");
}
.CodeMirror-lint-marker {
background-position: center center; background-position: center center;
background-repeat: no-repeat; background-repeat: no-repeat;
cursor: pointer; cursor: pointer;
@ -51,20 +49,20 @@
position: relative; position: relative;
} }
.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { .CodeMirror-lint-message {
padding-left: 18px; padding-left: 18px;
background-position: top left; background-position: top left;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning { .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII="); background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
} }
.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
}
.CodeMirror-lint-marker-multiple { .CodeMirror-lint-marker-multiple {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC"); background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
background-repeat: no-repeat; background-repeat: no-repeat;

View File

@ -12,11 +12,14 @@
"use strict"; "use strict";
var GUTTER_ID = "CodeMirror-lint-markers"; var GUTTER_ID = "CodeMirror-lint-markers";
function showTooltip(e, content) { function showTooltip(cm, e, content) {
var tt = document.createElement("div"); 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)); 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) { function position(e) {
if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position); if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
@ -38,8 +41,8 @@
setTimeout(function() { rm(tt); }, 600); setTimeout(function() { rm(tt); }, 600);
} }
function showTooltipFor(e, content, node) { function showTooltipFor(cm, e, content, node) {
var tooltip = showTooltip(e, content); var tooltip = showTooltip(cm, e, content);
function hide() { function hide() {
CodeMirror.off(node, "mouseout", hide); CodeMirror.off(node, "mouseout", hide);
if (tooltip) { hideTooltip(tooltip); tooltip = null; } if (tooltip) { hideTooltip(tooltip); tooltip = null; }
@ -78,16 +81,16 @@
state.marked.length = 0; state.marked.length = 0;
} }
function makeMarker(labels, severity, multiple, tooltips) { function makeMarker(cm, labels, severity, multiple, tooltips) {
var marker = document.createElement("div"), inner = marker; var marker = document.createElement("div"), inner = marker;
marker.className = "CodeMirror-lint-marker-" + severity; marker.className = "CodeMirror-lint-marker CodeMirror-lint-marker-" + severity;
if (multiple) { if (multiple) {
inner = marker.appendChild(document.createElement("div")); inner = marker.appendChild(document.createElement("div"));
inner.className = "CodeMirror-lint-marker-multiple"; inner.className = "CodeMirror-lint-marker CodeMirror-lint-marker-multiple";
} }
if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) { if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
showTooltipFor(e, labels, inner); showTooltipFor(cm, e, labels, inner);
}); });
return marker; return marker;
@ -111,11 +114,11 @@
var severity = ann.severity; var severity = ann.severity;
if (!severity) severity = "error"; if (!severity) severity = "error";
var tip = document.createElement("div"); var tip = document.createElement("div");
tip.className = "CodeMirror-lint-message-" + severity; tip.className = "CodeMirror-lint-message CodeMirror-lint-message-" + severity;
if (typeof ann.messageHTML != 'undefined') { if (typeof ann.messageHTML != 'undefined') {
tip.innerHTML = ann.messageHTML; tip.innerHTML = ann.messageHTML;
} else { } else {
tip.appendChild(document.createTextNode(ann.message)); tip.appendChild(document.createTextNode(ann.message));
} }
return tip; return tip;
} }
@ -180,13 +183,13 @@
if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann)); if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, { if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
className: "CodeMirror-lint-mark-" + severity, className: "CodeMirror-lint-mark CodeMirror-lint-mark-" + severity,
__annotation: ann __annotation: ann
})); }));
} }
if (state.hasGutter) 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)); state.options.tooltips));
} }
if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm); if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
@ -199,14 +202,14 @@
state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500); 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 target = e.target || e.srcElement;
var tooltip = document.createDocumentFragment(); var tooltip = document.createDocumentFragment();
for (var i = 0; i < annotations.length; i++) { for (var i = 0; i < annotations.length; i++) {
var ann = annotations[i]; var ann = annotations[i];
tooltip.appendChild(annotationTooltip(ann)); tooltip.appendChild(annotationTooltip(ann));
} }
showTooltipFor(e, tooltip, target); showTooltipFor(cm, e, tooltip, target);
} }
function onMouseOver(cm, e) { function onMouseOver(cm, e) {
@ -220,7 +223,7 @@
var ann = spans[i].__annotation; var ann = spans[i].__annotation;
if (ann) annotations.push(ann); 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) { CodeMirror.defineOption("lint", false, function(cm, val, old) {

View File

@ -443,22 +443,26 @@
aligners[i].clear(); aligners[i].clear();
aligners.length = 0; aligners.length = 0;
var cm = [dv.edit, dv.orig], scroll = []; var cm = [dv.edit, dv.orig], scroll = [], offset = []
if (other) cm.push(other.orig); 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); 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++) 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++) for (var i = 0; i < cm.length; i++)
cm[i].scrollTo(null, scroll[i]); cm[i].scrollTo(null, scroll[i]);
} }
function alignLines(cm, lines, aligners) { function alignLines(cm, cmOffset, lines, aligners) {
var maxOffset = 0, offset = []; var maxOffset = -1e8, offset = [];
for (var i = 0; i < cm.length; i++) if (lines[i] != null) { 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; offset[i] = off;
maxOffset = Math.max(maxOffset, off); maxOffset = Math.max(maxOffset, off);
} }

View File

@ -16,8 +16,8 @@
var countDown = n; var countDown = n;
return function() { if (--countDown == 0) cont(); }; return function() { if (--countDown == 0) cont(); };
} }
function ensureDeps(mode, cont) { function ensureDeps(mode, cont, options) {
var deps = CodeMirror.modes[mode].dependencies; var modeObj = CodeMirror.modes[mode], deps = modeObj && modeObj.dependencies;
if (!deps) return cont(); if (!deps) return cont();
var missing = []; var missing = [];
for (var i = 0; i < deps.length; ++i) { for (var i = 0; i < deps.length; ++i) {
@ -27,16 +27,18 @@
if (!missing.length) return cont(); if (!missing.length) return cont();
var split = splitCallback(cont, missing.length); var split = splitCallback(cont, missing.length);
for (var i = 0; i < missing.length; ++i) for (var i = 0; i < missing.length; ++i)
CodeMirror.requireMode(missing[i], split); CodeMirror.requireMode(missing[i], split, options);
} }
CodeMirror.requireMode = function(mode, cont) { CodeMirror.requireMode = function(mode, cont, options) {
if (typeof mode != "string") mode = mode.name; if (typeof mode != "string") mode = mode.name;
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont); if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont, options);
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont); if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
var file = CodeMirror.modeURL.replace(/%N/g, mode); var file = options && options.path ? options.path(mode) : CodeMirror.modeURL.replace(/%N/g, mode);
if (env == "plain") { if (options && options.loadMode) {
options.loadMode(file, function() { ensureDeps(mode, cont, options) })
} else if (env == "plain") {
var script = document.createElement("script"); var script = document.createElement("script");
script.src = file; script.src = file;
var others = document.getElementsByTagName("script")[0]; var others = document.getElementsByTagName("script")[0];
@ -44,7 +46,7 @@
CodeMirror.on(script, "load", function() { CodeMirror.on(script, "load", function() {
ensureDeps(mode, function() { ensureDeps(mode, function() {
for (var i = 0; i < list.length; ++i) list[i](); for (var i = 0; i < list.length; ++i) list[i]();
}); }, options);
}); });
others.parentNode.insertBefore(script, others); others.parentNode.insertBefore(script, others);
} else if (env == "cjs") { } else if (env == "cjs") {
@ -55,10 +57,10 @@
} }
}; };
CodeMirror.autoLoadMode = function(instance, mode) { CodeMirror.autoLoadMode = function(instance, mode, options) {
if (!CodeMirror.modes.hasOwnProperty(mode)) if (!CodeMirror.modes.hasOwnProperty(mode))
CodeMirror.requireMode(mode, function() { CodeMirror.requireMode(mode, function() {
instance.setOption("mode", instance.getOption("mode")); instance.setOption("mode", instance.getOption("mode"));
}); }, options);
}; };
}); });

View File

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

View File

@ -13,11 +13,12 @@
CodeMirror.runMode = function(string, modespec, callback, options) { CodeMirror.runMode = function(string, modespec, callback, options) {
var mode = CodeMirror.getMode(CodeMirror.defaults, modespec); var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
var ie = /MSIE \d/.test(navigator.userAgent); var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
// Create a tokenizing callback function if passed-in callback is a DOM element.
if (callback.appendChild) { if (callback.appendChild) {
var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize; var ie = /MSIE \d/.test(navigator.userAgent);
var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
var node = callback, col = 0; var node = callback, col = 0;
node.innerHTML = ""; node.innerHTML = "";
callback = function(text, style) { callback = function(text, style) {
@ -45,7 +46,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
pos = idx + 1; pos = idx + 1;
} }
} }
// Create a node with token style and append it to the callback DOM element.
if (style) { if (style) {
var sp = node.appendChild(document.createElement("span")); var sp = node.appendChild(document.createElement("span"));
sp.className = "cm-" + style.replace(/ +/g, " cm-"); sp.className = "cm-" + style.replace(/ +/g, " cm-");
@ -59,7 +60,10 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode); var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) { for (var i = 0, e = lines.length; i < e; ++i) {
if (i) callback("\n"); 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); if (!stream.string && mode.blankLine) mode.blankLine(state);
while (!stream.eol()) { while (!stream.eol()) {
var style = mode.token(stream, state); var style = mode.token(stream, state);

View File

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

View File

@ -43,7 +43,7 @@
cm.on("markerAdded", this.resizeHandler); cm.on("markerAdded", this.resizeHandler);
cm.on("markerCleared", this.resizeHandler); cm.on("markerCleared", this.resizeHandler);
if (options.listenForChanges !== false) if (options.listenForChanges !== false)
cm.on("change", this.changeHandler = function() { cm.on("changes", this.changeHandler = function() {
scheduleRedraw(250); scheduleRedraw(250);
}); });
} }
@ -72,10 +72,16 @@
var wrapping = cm.getOption("lineWrapping"); var wrapping = cm.getOption("lineWrapping");
var singleLineH = wrapping && cm.defaultTextHeight() * 1.5; var singleLineH = wrapping && cm.defaultTextHeight() * 1.5;
var curLine = null, curLineObj = null; var curLine = null, curLineObj = null;
function getY(pos, top) { function getY(pos, top) {
if (curLine != pos.line) { if (curLine != pos.line) {
curLine = pos.line; curLine = pos.line
curLineObj = cm.getLineHandle(curLine); curLineObj = cm.getLineHandle(pos.line)
var visual = cm.getLineHandleVisualStart(curLineObj)
if (visual != curLineObj) {
curLine = cm.getLineNumber(visual)
curLineObj = visual
}
} }
if ((curLineObj.widgets && curLineObj.widgets.length) || if ((curLineObj.widgets && curLineObj.widgets.length) ||
(wrapping && curLineObj.height > singleLineH)) (wrapping && curLineObj.height > singleLineH))
@ -116,7 +122,7 @@
this.cm.off("refresh", this.resizeHandler); this.cm.off("refresh", this.resizeHandler);
this.cm.off("markerAdded", this.resizeHandler); this.cm.off("markerAdded", this.resizeHandler);
this.cm.off("markerCleared", 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); this.div.parentNode.removeChild(this.div);
}; };
}); });

View File

@ -90,7 +90,9 @@
var state = cm.state.matchHighlighter; var state = cm.state.matchHighlighter;
cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style)); cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) { 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, state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
{className: "CodeMirror-selection-highlight-scrollbar"}); {className: "CodeMirror-selection-highlight-scrollbar"});
} }

View File

@ -72,24 +72,26 @@
} }
} }
function lastMatchIn(string, regexp) { function lastMatchIn(string, regexp, endMargin) {
var cutOff = 0, match var match, from = 0
for (;;) { while (from <= string.length) {
regexp.lastIndex = cutOff regexp.lastIndex = from
var newMatch = regexp.exec(string) var newMatch = regexp.exec(string)
if (!newMatch) return match if (!newMatch) break
match = newMatch var end = newMatch.index + newMatch[0].length
cutOff = match.index + (match[0].length || 1) if (end > string.length - endMargin) break
if (cutOff == string.length) return match if (!match || end > match.index + match[0].length)
match = newMatch
from = newMatch.index + 1
} }
return match
} }
function searchRegexpBackward(doc, regexp, start) { function searchRegexpBackward(doc, regexp, start) {
regexp = ensureFlags(regexp, "g") regexp = ensureFlags(regexp, "g")
for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) { for (var line = start.line, ch = start.ch, first = doc.firstLine(); line >= first; line--, ch = -1) {
var string = doc.getLine(line) var string = doc.getLine(line)
if (ch > -1) string = string.slice(0, ch) var match = lastMatchIn(string, regexp, ch < 0 ? 0 : string.length - ch)
var match = lastMatchIn(string, regexp)
if (match) if (match)
return {from: Pos(line, match.index), return {from: Pos(line, match.index),
to: Pos(line, match.index + match[0].length), to: Pos(line, match.index + match[0].length),
@ -98,16 +100,17 @@
} }
function searchRegexpBackwardMultiline(doc, regexp, start) { function searchRegexpBackwardMultiline(doc, regexp, start) {
if (!maybeMultiline(regexp)) return searchRegexpBackward(doc, regexp, start)
regexp = ensureFlags(regexp, "gm") 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 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--) 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) { if (match) {
var before = string.slice(0, match.index).split("\n"), inside = match[0].split("\n") 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 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)) var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to))
// Implements weird auto-growing behavior on null-matches for // 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) { while (result && CodeMirror.cmpPos(result.from, result.to) == 0) {
if (reverse) { if (reverse) {
if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1) if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1)

View File

@ -231,7 +231,7 @@
var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc; var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
if (content) { if (content) {
tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset, 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"; tooltip.className += " " + cls + "hint-doc";
} }
}); });
@ -334,7 +334,7 @@
tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")")); tip.appendChild(document.createTextNode(tp.rettype ? ") ->\u00a0" : ")"));
if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype)); if (tp.rettype) tip.appendChild(elt("span", cls + "type", tp.rettype));
var place = cm.cursorCoords(null, "page"); 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() { setTimeout(function() {
tooltip.clear = onEditorActivity(cm, function() { tooltip.clear = onEditorActivity(cm, function() {
if (ts.activeArgHints == tooltip) closeArgHints(ts) }) if (ts.activeArgHints == tooltip) closeArgHints(ts) })
@ -601,7 +601,7 @@
function tempTooltip(cm, content, ts) { function tempTooltip(cm, content, ts) {
if (cm.state.ternTooltip) remove(cm.state.ternTooltip); if (cm.state.ternTooltip) remove(cm.state.ternTooltip);
var where = cm.cursorCoords(); 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() { function maybeClear() {
old = true; old = true;
if (!mouseOnTip) clear(); 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); var node = elt("div", cls + "tooltip", content);
node.style.left = x + "px"; node.style.left = x + "px";
node.style.top = y + "px"; node.style.top = y + "px";
document.body.appendChild(node); var container = ((cm.options || {}).hintOptions || {}).container || document.body;
container.appendChild(node);
return node; return node;
} }

View File

@ -29,11 +29,20 @@
return {from: start, to: end}; return {from: start, to: end};
} }
function findBreakPoint(text, column, wrapOn, killTrailingSpace) { function findBreakPoint(text, column, wrapOn, killTrailingSpace, forceBreak) {
var at = column var at = column
while (at < text.length && text.charAt(at) == " ") at++ while (at < text.length && text.charAt(at) == " ") at++
for (; at > 0; --at) for (; at > 0; --at)
if (wrapOn.test(text.slice(at - 1, at + 1))) break; if (wrapOn.test(text.slice(at - 1, at + 1))) break;
if (at == 0 && !forceBreak) {
// didn't find a break point before column, in non-forceBreak mode try to
// find one after 'column'.
for (at = column + 1; at < text.length - 1; ++at) {
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
}
}
for (var first = true;; first = false) { for (var first = true;; first = false) {
var endOfText = at; var endOfText = at;
if (killTrailingSpace) if (killTrailingSpace)
@ -47,6 +56,7 @@
from = cm.clipPos(from); to = cm.clipPos(to); from = cm.clipPos(from); to = cm.clipPos(to);
var column = options.column || 80; var column = options.column || 80;
var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/; var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
var forceBreak = options.forceBreak !== false;
var killTrailing = options.killTrailingSpace !== false; var killTrailing = options.killTrailingSpace !== false;
var changes = [], curLine = "", curNo = from.line; var changes = [], curLine = "", curNo = from.line;
var lines = cm.getRange(from, to, false); var lines = cm.getRange(from, to, false);
@ -68,7 +78,7 @@
curLine += text; curLine += text;
if (i) { if (i) {
var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed && var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
findBreakPoint(curLine, column, wrapOn, killTrailing); findBreakPoint(curLine, column, wrapOn, killTrailing, forceBreak);
// If this isn't broken, or is broken at a different point, remove old break // If this isn't broken, or is broken at a different point, remove old break
if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) { if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
changes.push({text: [spaceInserted ? " " : ""], changes.push({text: [spaceInserted ? " " : ""],
@ -80,12 +90,16 @@
} }
} }
while (curLine.length > column) { while (curLine.length > column) {
var bp = findBreakPoint(curLine, column, wrapOn, killTrailing); var bp = findBreakPoint(curLine, column, wrapOn, killTrailing, forceBreak);
changes.push({text: ["", leadingSpace], if (bp.from != bp.to || forceBreak) {
from: Pos(curNo, bp.from), changes.push({text: ["", leadingSpace],
to: Pos(curNo, bp.to)}); from: Pos(curNo, bp.from),
curLine = leadingSpace + curLine.slice(bp.to); to: Pos(curNo, bp.to)});
++curNo; curLine = leadingSpace + curLine.slice(bp.to);
++curNo;
} else {
break;
}
} }
} }
if (changes.length) cm.operation(function() { if (changes.length) cm.operation(function() {

View File

@ -53,7 +53,23 @@
<div style="max-width: 50em; margin-bottom: 1em">JavaScript:<br> <div style="max-width: 50em; margin-bottom: 1em">JavaScript:<br>
<textarea id="code" name="code"></textarea></div> <textarea id="code" name="code"></textarea></div>
<div style="max-width: 50em; margin-bottom: 1em">HTML:<br> <div style="max-width: 50em; margin-bottom: 1em">HTML:<br>
<textarea id="code-html" name="code-html"></textarea></div> <textarea id="code-html" name="code-html"></textarea></div>
<div style="max-width: 50em; margin-bottom: 1em">JSON with custom widget:<br>
<textarea id="code-json" name="code-json">
{
"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}
}
</textarea></div>
<div style="max-width: 50em">Python:<br> <div style="max-width: 50em">Python:<br>
<textarea id="code-python" name="code"> <textarea id="code-python" name="code">
def foo(): def foo():
@ -89,6 +105,7 @@ window.onload = function() {
var te_python = document.getElementById("code-python"); var te_python = document.getElementById("code-python");
var te_markdown = document.getElementById("code-markdown"); var te_markdown = document.getElementById("code-markdown");
te_markdown.value = "# Foo\n## Bar\n\nblah blah\n\n## Baz\n\nblah blah\n\n# Quux\n\nblah blah\n" te_markdown.value = "# Foo\n## Bar\n\nblah blah\n\n## Baz\n\nblah blah\n\n# Quux\n\nblah blah\n"
var te_json = document.getElementById("code-json");
window.editor = CodeMirror.fromTextArea(te, { window.editor = CodeMirror.fromTextArea(te, {
mode: "javascript", mode: "javascript",
@ -100,6 +117,40 @@ window.onload = function() {
}); });
editor.foldCode(CodeMirror.Pos(13, 0)); editor.foldCode(CodeMirror.Pos(13, 0));
window.editor_json = CodeMirror.fromTextArea(te_json, {
mode: {name: "javascript", json: true},
lineNumbers: true,
lineWrapping: true,
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
foldOptions: {
widget: (from, to) => {
var count = undefined;
// Get open / close token
var startToken = '{', endToken = '}';
var prevLine = window.editor_json.getLine(from.line);
if (prevLine.lastIndexOf('[') > prevLine.lastIndexOf('{')) {
startToken = '[', endToken = ']';
}
// Get json content
var internal = window.editor_json.getRange(from, to);
var toParse = startToken + internal + endToken;
// Get key count
try {
var parsed = JSON.parse(toParse);
count = Object.keys(parsed).length;
} catch(e) { }
return count ? `\u21A4${count}\u21A6` : '\u2194';
}
}
});
editor_json.foldCode(CodeMirror.Pos(5, 0));
window.editor_html = CodeMirror.fromTextArea(te_html, { window.editor_html = CodeMirror.fromTextArea(te_html, {
mode: "text/html", mode: "text/html",
lineNumbers: true, lineNumbers: true,

View File

@ -0,0 +1,61 @@
<!doctype html>
<title>CodeMirror: Mode Runner Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../addon/runmode/runmode-standalone.js"></script>
<script src="../mode/xml/xml.js"></script>
<div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../doc/logo.png"></a>
<ul>
<li><a href="../index.html">Home</a>
<li><a href="../doc/manual.html">Manual</a>
<li><a href="https://github.com/codemirror/codemirror">Code</a>
</ul>
<ul>
<li><a class=active href="#">Mode Runner</a>
</ul>
</div>
<article>
<h2>Mode Runner Demo</h2>
<textarea id="code" style="width: 90%; height: 7em; border: 1px solid black; padding: .2em .4em;">
<foobar>
<blah>Enter your xml here and press the button below to display
it as highlighted by the CodeMirror XML mode</blah>
<tag2 foo="2" bar="&amp;quot;bar&amp;quot;"/>
</foobar></textarea><br>
<button onclick="doHighlight();">Highlight!</button>
<pre id="output" class="cm-s-default"></pre>
<script>
function doHighlight() {
CodeMirror.runMode(document.getElementById("code").value, "application/xml",
document.getElementById("output"));
}
</script>
<p>Running a CodeMirror mode outside of the editor.
The <code>CodeMirror.runMode</code> function, defined
in <code><a href="../addon/runmode/runmode.js">addon/runmode/runmode.js</a></code> takes the following arguments:</p>
<dl>
<dt><code>text (string)</code></dt>
<dd>The document to run through the highlighter.</dd>
<dt><code>mode (<a href="../doc/manual.html#option_mode">mode spec</a>)</code></dt>
<dd>The mode to use (must be loaded as normal).</dd>
<dt><code>output (function or DOM node)</code></dt>
<dd>If this is a function, it will be called for each token with
two arguments, the token's text and the token's style class (may
be <code>null</code> for unstyled tokens). If it is a DOM node,
the tokens will be converted to <code>span</code> elements as in
an editor, and inserted into the node
(through <code>innerHTML</code>).</dd>
</dl>
</article>

View File

@ -67,7 +67,8 @@ highlighted by the mode shown in it).</p>
will be taken into account when matching the token. This regex will be taken into account when matching the token. This regex
has to capture groups when the <code>token</code> property is has to capture groups when the <code>token</code> property is
an array. If it captures groups, it must capture <em>all</em> of the string an array. If it captures groups, it must capture <em>all</em> of the string
(since JS provides no way to find out where a group matched).</dd> (since JS provides no way to find out where a group matched).
Currently negative lookbehind assertion for regex is not supported, regardless of browser support.</dd>
<dt><code><strong>token</strong></code>: string | array&lt;string&gt; | null</dt> <dt><code><strong>token</strong></code>: string | array&lt;string&gt; | null</dt>
<dd>An optional token style. Multiple styles can be specified by <dd>An optional token style. Multiple styles can be specified by
separating them with dots or spaces. When this property holds an array of token styles, separating them with dots or spaces. When this property holds an array of token styles,

View File

@ -9,6 +9,8 @@
<link rel="stylesheet" href="../theme/3024-night.css"> <link rel="stylesheet" href="../theme/3024-night.css">
<link rel="stylesheet" href="../theme/abcdef.css"> <link rel="stylesheet" href="../theme/abcdef.css">
<link rel="stylesheet" href="../theme/ambiance.css"> <link rel="stylesheet" href="../theme/ambiance.css">
<link rel="stylesheet" href="../theme/ayu-dark.css">
<link rel="stylesheet" href="../theme/ayu-mirage.css">
<link rel="stylesheet" href="../theme/base16-dark.css"> <link rel="stylesheet" href="../theme/base16-dark.css">
<link rel="stylesheet" href="../theme/bespin.css"> <link rel="stylesheet" href="../theme/bespin.css">
<link rel="stylesheet" href="../theme/base16-light.css"> <link rel="stylesheet" href="../theme/base16-light.css">
@ -29,10 +31,14 @@
<link rel="stylesheet" href="../theme/liquibyte.css"> <link rel="stylesheet" href="../theme/liquibyte.css">
<link rel="stylesheet" href="../theme/lucario.css"> <link rel="stylesheet" href="../theme/lucario.css">
<link rel="stylesheet" href="../theme/material.css"> <link rel="stylesheet" href="../theme/material.css">
<link rel="stylesheet" href="../theme/material-darker.css">
<link rel="stylesheet" href="../theme/material-palenight.css">
<link rel="stylesheet" href="../theme/material-ocean.css">
<link rel="stylesheet" href="../theme/mbo.css"> <link rel="stylesheet" href="../theme/mbo.css">
<link rel="stylesheet" href="../theme/mdn-like.css"> <link rel="stylesheet" href="../theme/mdn-like.css">
<link rel="stylesheet" href="../theme/midnight.css"> <link rel="stylesheet" href="../theme/midnight.css">
<link rel="stylesheet" href="../theme/monokai.css"> <link rel="stylesheet" href="../theme/monokai.css">
<link rel="stylesheet" href="../theme/moxer.css">
<link rel="stylesheet" href="../theme/neat.css"> <link rel="stylesheet" href="../theme/neat.css">
<link rel="stylesheet" href="../theme/neo.css"> <link rel="stylesheet" href="../theme/neo.css">
<link rel="stylesheet" href="../theme/night.css"> <link rel="stylesheet" href="../theme/night.css">
@ -102,6 +108,8 @@ function findSequence(goal) {
<option>3024-night</option> <option>3024-night</option>
<option>abcdef</option> <option>abcdef</option>
<option>ambiance</option> <option>ambiance</option>
<option>ayu-dark</option>
<option>ayu-mirage</option>
<option>base16-dark</option> <option>base16-dark</option>
<option>base16-light</option> <option>base16-light</option>
<option>bespin</option> <option>bespin</option>
@ -124,10 +132,14 @@ function findSequence(goal) {
<option>liquibyte</option> <option>liquibyte</option>
<option>lucario</option> <option>lucario</option>
<option>material</option> <option>material</option>
<option>material-darker</option>
<option>material-palenight</option>
<option>material-ocean</option>
<option>mbo</option> <option>mbo</option>
<option>mdn-like</option> <option>mdn-like</option>
<option>midnight</option> <option>midnight</option>
<option>monokai</option> <option>monokai</option>
<option>moxer</option>
<option>neat</option> <option>neat</option>
<option>neo</option> <option>neo</option>
<option>night</option> <option>night</option>
@ -181,4 +193,4 @@ function findSequence(goal) {
if (theme) { input.value = theme; selectTheme(); } if (theme) { input.value = theme; selectTheme(); }
}); });
</script> </script>
</article> </article>

View File

@ -56,6 +56,7 @@ int getchar(void)
} }
</textarea></form> </textarea></form>
<div style="font-size: 13px; width: 300px; height: 30px;">Key buffer: <span id="command-display"></span></div> <div style="font-size: 13px; width: 300px; height: 30px;">Key buffer: <span id="command-display"></span></div>
<div style="font-size: 13px; width: 300px; height: 30px;">Vim mode: <span id="vim-mode"></span></div>
<p>The vim keybindings are enabled by including <code><a <p>The vim keybindings are enabled by including <code><a
href="../keymap/vim.js">keymap/vim.js</a></code> and setting the href="../keymap/vim.js">keymap/vim.js</a></code> and setting the
@ -95,19 +96,22 @@ become a complete vim implementation</p>
mode: "text/x-csrc", mode: "text/x-csrc",
keyMap: "vim", keyMap: "vim",
matchBrackets: true, matchBrackets: true,
showCursorWhenSelecting: true, showCursorWhenSelecting: true
inputStyle: "contenteditable"
}); });
var commandDisplay = document.getElementById('command-display'); var commandDisplay = document.getElementById('command-display');
var keys = ''; var keys = '';
CodeMirror.on(editor, 'vim-keypress', function(key) { CodeMirror.on(editor, 'vim-keypress', function(key) {
keys = keys + key; keys = keys + key;
commandDisplay.innerHTML = keys; commandDisplay.innerText = keys;
}); });
CodeMirror.on(editor, 'vim-command-done', function(e) { CodeMirror.on(editor, 'vim-command-done', function(e) {
keys = ''; keys = '';
commandDisplay.innerHTML = keys; commandDisplay.innerHTML = keys;
}); });
var vimMode = document.getElementById('vim-mode');
CodeMirror.on(editor, 'vim-mode-change', function(e) {
vimMode.innerText = JSON.stringify(e);
});
</script> </script>
</article> </article>

View File

@ -58,6 +58,7 @@
<li><a href="#vimapi">Vim Mode API</a> <li><a href="#vimapi">Vim Mode API</a>
<ul> <ul>
<li><a href="#vimapi_configuration">Configuration</a></li> <li><a href="#vimapi_configuration">Configuration</a></li>
<li><a href="#vimapi_events">Events</a></li>
<li><a href="#vimapi_extending">Extending VIM</a></li> <li><a href="#vimapi_extending">Extending VIM</a></li>
</ul> </ul>
</li> </li>
@ -69,7 +70,7 @@
<section class=first id=overview> <section class=first id=overview>
<h2 style="position: relative"> <h2 style="position: relative">
User manual and reference guide User manual and reference guide
<span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 5.48.2</span> <span style="color: #888; font-size: 1rem; position: absolute; right: 0; bottom: 0">version 5.58.1</span>
</h2> </h2>
<p>CodeMirror is a code-editor component that can be embedded in <p>CodeMirror is a code-editor component that can be embedded in
@ -78,9 +79,9 @@
functionality. It does provide a rich API on top of which such functionality. It does provide a rich API on top of which such
functionality can be straightforwardly implemented. See functionality can be straightforwardly implemented. See
the <a href="#addons">addons</a> included in the distribution, the <a href="#addons">addons</a> included in the distribution,
and the <a href="https://github.com/codemirror/CodeMirror/wiki/CodeMirror-addons">list and <a href="https://npms.io/search?q=codemirror">3rd party
of externally hosted addons</a>, for reusable packages on npm</a>, for reusable implementations of extra
implementations of extra features.</p> features.</p>
<p>CodeMirror works with language-specific modes. Modes are <p>CodeMirror works with language-specific modes. Modes are
JavaScript programs that help color (and optionally indent) text JavaScript programs that help color (and optionally indent) text
@ -223,9 +224,10 @@
first mode that was loaded. It may be a string, which either first mode that was loaded. It may be a string, which either
simply names the mode or is simply names the mode or is
a <a href="http://en.wikipedia.org/wiki/MIME">MIME</a> type a <a href="http://en.wikipedia.org/wiki/MIME">MIME</a> type
associated with the mode. Alternatively, it may be an object associated with the mode. The value <code>"null"</code>
containing configuration options for the mode, with indicates no highlighting should be applied. Alternatively, it
a <code>name</code> property that names the mode (for may be an object containing configuration options for the mode,
with a <code>name</code> property that names the mode (for
example <code>{name: "javascript", json: true}</code>). The demo example <code>{name: "javascript", json: true}</code>). The demo
pages for each mode contain information about what configuration pages for each mode contain information about what configuration
parameters the mode supports. You can ask CodeMirror which modes parameters the mode supports. You can ask CodeMirror which modes
@ -420,6 +422,10 @@
simply <code>true</code>), focusing of the editor is also simply <code>true</code>), focusing of the editor is also
disallowed.</dd> disallowed.</dd>
<dt id="option_screenReaderLabel"><code><strong>screenReaderLabel</strong>: string</code></dt>
<dd>This label is read by the screenreaders when CodeMirror text area is focused. This
is helpful for accessibility.</dd>
<dt id="option_showCursorWhenSelecting"><code><strong>showCursorWhenSelecting</strong>: boolean</code></dt> <dt id="option_showCursorWhenSelecting"><code><strong>showCursorWhenSelecting</strong>: boolean</code></dt>
<dd>Whether the cursor should be drawn when a selection is <dd>Whether the cursor should be drawn when a selection is
active. Defaults to false.</dd> active. Defaults to false.</dd>
@ -557,13 +563,13 @@
always rendered, and thus the browser's text search works on it. always rendered, and thus the browser's text search works on it.
This <em>will</em> have bad effects on performance of big This <em>will</em> have bad effects on performance of big
documents.</dd> documents.</dd>
<dt id="option_spellcheck"><code><strong>spellcheck</strong>: boolean</code></dt> <dt id="option_spellcheck"><code><strong>spellcheck</strong>: boolean</code></dt>
<dd>Specifies whether or not spellcheck will be enabled on the input.</dd> <dd>Specifies whether or not spellcheck will be enabled on the input.</dd>
<dt id="option_autocorrect"><code><strong>autocorrect</strong>: boolean</code></dt> <dt id="option_autocorrect"><code><strong>autocorrect</strong>: boolean</code></dt>
<dd>Specifies whether or not autocorrect will be enabled on the input.</dd> <dd>Specifies whether or not autocorrect will be enabled on the input.</dd>
<dt id="option_autocapitalize"><code><strong>autocapitalize</strong>: boolean</code></dt> <dt id="option_autocapitalize"><code><strong>autocapitalize</strong>: boolean</code></dt>
<dd>Specifies whether or not autocapitalization will be enabled on the input.</dd> <dd>Specifies whether or not autocapitalization will be enabled on the input.</dd>
</dl> </dl>
@ -1880,6 +1886,9 @@ editor.setOption("extraKeys", {
position (zero for the top, N to put it after the Nth other position (zero for the top, N to put it after the Nth other
widget). Note that this only has effect once, when the widget). Note that this only has effect once, when the
widget is created. widget is created.
<dt><code><strong>className</strong>: string</code></dt>
<dd>Add an extra CSS class name to the wrapper element
created for the widget.</dd>
</dl> </dl>
Note that the widget node will become a descendant of nodes with Note that the widget node will become a descendant of nodes with
CodeMirror-specific CSS classes, and those classes might in some CodeMirror-specific CSS classes, and those classes might in some
@ -2563,10 +2572,14 @@ editor.setOption("extraKeys", {
and <code>CodeMirror.fold.xml</code>, for XML-style languages, and <code>CodeMirror.fold.xml</code>, for XML-style languages,
and <code>CodeMirror.fold.comment</code>, for folding comment and <code>CodeMirror.fold.comment</code>, for folding comment
blocks.</dd> blocks.</dd>
<dt><code><strong>widget</strong>: string|Element</code></dt> <dt><code><strong>widget</strong>: string | Element | fn(from: Pos, to: Pos) → string|Element</code></dt>
<dd>The widget to show for folded ranges. Can be either a <dd>The widget to show for folded ranges. Can be either a
string, in which case it'll become a span with string, in which case it'll become a span with
class <code>CodeMirror-foldmarker</code>, or a DOM node.</dd> class <code>CodeMirror-foldmarker</code>, 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.</dd>
<dt><code><strong>scanUp</strong>: boolean</code></dt> <dt><code><strong>scanUp</strong>: boolean</code></dt>
<dd>When true (default is false), the addon will try to find <dd>When true (default is false), the addon will try to find
foldable ranges on the lines above the current one if there foldable ranges on the lines above the current one if there
@ -2777,6 +2790,9 @@ editor.setOption("extraKeys", {
<dd>Like <code>customKeys</code> above, but the bindings will <dd>Like <code>customKeys</code> above, but the bindings will
be added to the set of default bindings, instead of replacing be added to the set of default bindings, instead of replacing
them.</dd> them.</dd>
<dt><code><strong>scrollMargin</strong>: integer</code></dt>
<dd>Show this many lines before and after the selected item.
Default is 0.</dd>
</dl> </dl>
The following events will be fired on the completions object The following events will be fired on the completions object
during completion: during completion:
@ -2903,6 +2919,7 @@ editor.setOption("extraKeys", {
will only be executed when the promise resolves. will only be executed when the promise resolves.
By default, the linter will run (debounced) whenever the document is changed. By default, the linter will run (debounced) whenever the document is changed.
You can pass a <code>lintOnChange: false</code> option to disable that. You can pass a <code>lintOnChange: false</code> option to disable that.
You can pass a <code>selfContain: true</code> option to render the tooltip inside the editor instance.
Depends on <code>addon/lint/lint.css</code>. A demo can be Depends on <code>addon/lint/lint.css</code>. A demo can be
found <a href="../demo/lint.html">here</a>.</dd> found <a href="../demo/lint.html">here</a>.</dd>
@ -2937,13 +2954,20 @@ editor.setOption("extraKeys", {
see a demo <a href="../mode/htmlmixed/index.html">here</a>.</dd> see a demo <a href="../mode/htmlmixed/index.html">here</a>.</dd>
<dt id="addon_loadmode"><a href="../addon/mode/loadmode.js"><code>mode/loadmode.js</code></a></dt> <dt id="addon_loadmode"><a href="../addon/mode/loadmode.js"><code>mode/loadmode.js</code></a></dt>
<dd>Defines a <code>CodeMirror.requireMode(modename, <dd>Defines a <code>CodeMirror.requireMode(modename, callback,
callback)</code> function that will try to load a given mode and options)</code> function that will try to load a given mode and
call the callback when it succeeded. You'll have to call the callback when it succeeded. <code>options</code> is an
set <code>CodeMirror.modeURL</code> to a string that mode paths optional object that may contain:
can be constructed from, for <dl>
example <code>"mode/%N/%N.js"</code>—the <code>%N</code>'s will <dt><code><strong>path</strong>: fn(modeName: string) → string</code></dt>
be replaced with the mode name. Also <dd>Defines the way mode names are mapped to paths.</dd>
<dt><code><strong>loadMode</strong>: fn(path: string, cont: fn())</code></dt>
<dd>Override the way the mode script is loaded. By default,
this will use the CommonJS or AMD module loader if one is
present, and fall back to creating
a <code>&lt;script></code> tag otherwise.</dd>
</dl>
This addon also
defines <code>CodeMirror.autoLoadMode(instance, mode)</code>, defines <code>CodeMirror.autoLoadMode(instance, mode)</code>,
which will ensure the given mode is loaded and cause the given which will ensure the given mode is loaded and cause the given
editor instance to refresh its mode when the loading editor instance to refresh its mode when the loading
@ -3114,10 +3138,20 @@ editor.setOption("extraKeys", {
<dt><code><strong>killTrailingSpace</strong>: boolean</code></dt> <dt><code><strong>killTrailingSpace</strong>: boolean</code></dt>
<dd>Whether trailing space caused by wrapping should be <dd>Whether trailing space caused by wrapping should be
preserved, or deleted. Defaults to true.</dd> preserved, or deleted. Defaults to true.</dd>
<dt><code><strong>forceBreak</strong>: boolean</code></dt>
<dd>If set to true forces a break at <code>column</code> in the case
when no <code>wrapOn</code> pattern is found in the range. If set to
false allows line to overflow the <code>column</code> limit if no
<code>wrapOn</code> pattern found. Defaults to true.</dd>
</dl> </dl>
A demo of the addon is available <a href="../demo/hardwrap.html">here</a>. A demo of the addon is available <a href="../demo/hardwrap.html">here</a>.
</dd> </dd>
<dt id="addon_scrollpastend"><a href="../addon/scroll/scrollpastend.js"><code>scroll/scrollpastend.js</code></a></dt>
<dd>Defines an option `"scrollPastEnd"` that, when set to a
truthy value, allows the user to scroll one editor height of
empty space into view at the bottom of the editor.</dd>
<dt id="addon_merge"><a href="../addon/merge/merge.js"><code>merge/merge.js</code></a></dt> <dt id="addon_merge"><a href="../addon/merge/merge.js"><code>merge/merge.js</code></a></dt>
<dd>Implements an interface for merging changes, using either a <dd>Implements an interface for merging changes, using either a
2-way or a 3-way view. The <code>CodeMirror.MergeView</code> 2-way or a 3-way view. The <code>CodeMirror.MergeView</code>
@ -3170,14 +3204,14 @@ editor.setOption("extraKeys", {
<dt id="addon_tern"><a href="../addon/tern/tern.js"><code>tern/tern.js</code></a></dt> <dt id="addon_tern"><a href="../addon/tern/tern.js"><code>tern/tern.js</code></a></dt>
<dd>Provides integration with <dd>Provides integration with
the <a href="http://ternjs.net">Tern</a> JavaScript analysis the <a href="https://ternjs.net">Tern</a> JavaScript analysis
engine, for completion, definition finding, and minor engine, for completion, definition finding, and minor
refactoring help. See the <a href="../demo/tern.html">demo</a> refactoring help. See the <a href="../demo/tern.html">demo</a>
for a very simple integration. For more involved scenarios, see for a very simple integration. For more involved scenarios, see
the comments at the top of the comments at the top of
the <a href="../addon/tern/tern.js">addon</a> and the the <a href="../addon/tern/tern.js">addon</a> and the
implementation of the implementation of the
(multi-file) <a href="http://ternjs.net/doc/demo.html">demonstration (multi-file) <a href="https://ternjs.net/doc/demo/index.html">demonstration
on the Tern website</a>.</dd> on the Tern website</a>.</dd>
</dl> </dl>
</section> </section>
@ -3517,6 +3551,41 @@ editor.setOption("extraKeys", {
<code>extras.isEdit</code> is applicable only to actions, <code>extras.isEdit</code> is applicable only to actions,
determining whether it is recorded for replay for the determining whether it is recorded for replay for the
<code>.</code> single-repeat command. <code>.</code> single-repeat command.
<dt id="vimapi_unmap"><strong><code>unmap(lhs: string, ctx: string)</code></strong></dt>
<dd>
Remove the command <code>lhs</code> 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 <code>undefined</code> or <code>false</code>.
</dd>
<dt id="vimapi_mapclear"><strong><code>mapclear(ctx: string)</code></strong></dt>
<dd>
Remove all user-defined mappings for the provided context.
</dd>
<dt id="vimapi_noremap"><strong><code>noremap(lhs: string, rhs: string, ctx: {string, array&lt;string&gt;})</code></strong></dt>
<dd>
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.
</dd>
</dl>
<h3 id="vimapi_events">Events</h3>
<p>VIM mode signals a few events on the editor instance. For an example usage, see <a href="https://github.com/codemirror/CodeMirror/blob/5.55.0/demo/vim.html#L101-L110">demo/vim.html#L101</a>.</p>
<dl>
<dt id="vimapi_commanddone"><code><strong>"vim-command-done"</strong> (reason: undefined)</code></dt>
<dd>Fired on keypress and mousedown where command has completed or no command found.</dd>
<dt id="vimapi_keypress"><code><strong>"vim-keypress"</strong> (vimKey: string)</code></dt>
<dd>Fired on keypress, <code>vimKey</code> is in Vim's key notation.</dd>
<dt id="vimapi_modechange"><code><strong>"vim-mode-change"</strong> (modeObj: object)</code></dt>
<dd>Fired after mode change, <code>modeObj</code> parameter is a <code>{mode: string, ?subMode: string}</code> object. Modes: <code>"insert", "normal", "replace", "visual"</code>. Visual sub-modes: <code>"linewise", "blockwise"</code>.</dd>
</dl> </dl>
<h3 id="vimapi_extending">Extending VIM</h3> <h3 id="vimapi_extending">Extending VIM</h3>
@ -3582,7 +3651,74 @@ editor.setOption("extraKeys", {
command was prefixed with a command was prefixed with a
<code><strong><a href="http://vimdoc.sourceforge.net/htmldoc/cmdline.html#cmdline-ranges">line range</a></strong></code>, <code><strong><a href="http://vimdoc.sourceforge.net/htmldoc/cmdline.html#cmdline-ranges">line range</a></strong></code>,
<code>params.line</code> and <code>params.lineEnd</code> will <code>params.line</code> and <code>params.lineEnd</code> will
be set. be set.</dd>
<dt id="vimapi_getRegisterController"><strong><code>getRegisterController()</code></strong></dt>
<dd>Returns the RegisterController that manages the state of registers
used by vim mode. For the RegisterController api see its
defintion <a href="https://github.com/CodeMirror/CodeMirror/blob/b2d26b4ccb1d0994ae84d18ad8b84018de176da9/keymap/vim.js#L1123">here</a>.
</dd>
<dt id='vimapi_buildkeymap'><strong><code>buildKeyMap()</code></strong></dt>
<dd>
Not currently implemented. If you would like to contribute this please open
a pull request on <a href="https://github.com/codemirror/CodeMirror">Github</a>.
</dd>
<dt id="vimapi_defineRegister"><strong><code>defineRegister()</code></strong></dt>
<dd> Defines an external register. The name should be a single character
that will be used to reference the register. The register should support
<code>setText</code>, <code>pushText</code>, <code>clear</code>, and <code>toString</code>.
See <a href="https://github.com/CodeMirror/CodeMirror/blob/b2d26b4ccb1d0994ae84d18ad8b84018de176da9/keymap/vim.js#L1055">Register</a> for a reference implementation.
</dd>
<dt id="vimapi_getVimGlobalState_"><strong><code>getVimGlobalState_()</code></strong></dt>
<dd>
Return a reference to the VimGlobalState.
</dd>
<dt id="vimapi_resetVimGlobalState_"><strong><code>resetVimGlobalState_()</code></strong></dt>
<dd>
Reset the default values of the VimGlobalState to fresh values. Any options
set with <code>setOption</code> will also be applied to the reset global state.
</dd>
<dt id="vimapi_maybeInitVimState_"><strong><code>maybeInitVimState_(cm: CodeMirror)</code></strong></dt>
<dd>
Initialize <code>cm.state.vim</code> if it does not exist. Returns <code>cm.state.vim</code>.
</dd>
<dt id="vimapi_handleKey"><strong><code>handleKey(cm: CodeMirror, key: string, origin: string)</code></strong></dt>
<dd>
Convenience function to pass the arguments to <code>findKey</code> and
call returned function if it is defined.
</dd>
<dt id="vimapi_findKey"><strong><code>findKey(cm: CodeMirror, key: string, origin: string)</code></strong></dt>
<dd>
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 <code>undefined</code>
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.
</dd>
<dt id="vimapi_option_suppressErrorLogging"><code><strong>suppressErrorLogging</strong>: boolean</code></dt>
<dd>Whether to use suppress the use of <code>console.log</code> when catching an
error in the function returned by <code>findKey</code>.
Defaults to false.</dd>
<dt id="vimapi_exitVisualMode"><strong><code>exitVisualMode(cm: CodeMirror, ?moveHead: boolean)</code></strong></dt>
<dd> 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.
</dd>
<dt id="vimapi_exitInsertMode"><strong><code>exitInsertMode(cm: CodeMirror)</code></strong></dt>
<dd>
Exit insert mode.
</dd>
</dl> </dl>
</section> </section>

View File

@ -25,7 +25,9 @@
request</a> if you'd like your project to be added to this list.</p> request</a> if you'd like your project to be added to this list.</p>
<ul> <ul>
<li><a href="https://www.adaface.com/pair-pro">Adaface PairPro</a> (Shared code editor with compiler and video conferencing)</li>
<li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li> <li><a href="http://brackets.io">Adobe Brackets</a> (code editor)</li>
<li><a href="http://adnuntius.com">Adnuntius</a> (used for in-browser code editing and version history)</li>
<li><a href="http://alm.tools">ALM Tools</a> (TypeScript powered IDE)</li> <li><a href="http://alm.tools">ALM Tools</a> (TypeScript powered IDE)</li>
<li><a href="http://amber-lang.net/">Amber</a> (JavaScript-based Smalltalk system)</li> <li><a href="http://amber-lang.net/">Amber</a> (JavaScript-based Smalltalk system)</li>
<li><a href="http://apeye.org/">APEye</a> (tool for testing &amp; documenting APIs)</li> <li><a href="http://apeye.org/">APEye</a> (tool for testing &amp; documenting APIs)</li>
@ -39,6 +41,7 @@
<li><a href="http://cargocollective.com/">Cargo Collective</a> (creative publishing platform)</li> <li><a href="http://cargocollective.com/">Cargo Collective</a> (creative publishing platform)</li>
<li><a href="https://developers.google.com/chrome-developer-tools/">Chrome DevTools</a></li> <li><a href="https://developers.google.com/chrome-developer-tools/">Chrome DevTools</a></li>
<li><a href="http://clickhelp.co/">ClickHelp</a> (technical writing tool)</li> <li><a href="http://clickhelp.co/">ClickHelp</a> (technical writing tool)</li>
<li><a href="https://clone-it.github.io/">Clone-It</a> (HTML & CSS learning game)</li>
<li><a href="https://electronjs.org/apps/colon">Colon</a> (A flexible text editor or IDE)</li> <li><a href="https://electronjs.org/apps/colon">Colon</a> (A flexible text editor or IDE)</li>
<li><a href="http://code.world/">CodeWorld</a> (Haskell playground)</li> <li><a href="http://code.world/">CodeWorld</a> (Haskell playground)</li>
<li><a href="http://complete-ly.appspot.com/playground/code.playground.html">Complete.ly playground</a></li> <li><a href="http://complete-ly.appspot.com/playground/code.playground.html">Complete.ly playground</a></li>
@ -49,6 +52,7 @@
<li><a href="http://codefights.com/">CodeFights</a> (practice programming)</li> <li><a href="http://codefights.com/">CodeFights</a> (practice programming)</li>
<li><a href="https://github.com/angelozerr/CodeMirror-Eclipse">CodeMirror Eclipse</a> (embed CM in Eclipse)</li> <li><a href="https://github.com/angelozerr/CodeMirror-Eclipse">CodeMirror Eclipse</a> (embed CM in Eclipse)</li>
<li><a href="http://emmet.io/blog/codemirror-movie/">CodeMirror movie</a> (scripted editing demos)</li> <li><a href="http://emmet.io/blog/codemirror-movie/">CodeMirror movie</a> (scripted editing demos)</li>
<li><a href="https://github.com/haoranyu/codemirror-record/">CodeMirror Record</a> (codemirror activity recording and playback)</li>
<li><a href="http://code.google.com/p/codemirror2-gwt/">CodeMirror2-GWT</a> (Google Web Toolkit wrapper)</li> <li><a href="http://code.google.com/p/codemirror2-gwt/">CodeMirror2-GWT</a> (Google Web Toolkit wrapper)</li>
<li><a href="http://www.crunchzilla.com/code-monster">Code Monster</a> & <a href="http://www.crunchzilla.com/code-maven">Code Maven</a> (learning environment)</li> <li><a href="http://www.crunchzilla.com/code-monster">Code Monster</a> & <a href="http://www.crunchzilla.com/code-maven">Code Maven</a> (learning environment)</li>
<li><a href="http://codepen.io">Codepen</a> (gallery of animations)</li> <li><a href="http://codepen.io">Codepen</a> (gallery of animations)</li>
@ -57,7 +61,6 @@
<li><a href="http://sasstwo.codeschool.com/levels/1/challenges/1">Code School</a> (online tech learning environment)</li> <li><a href="http://sasstwo.codeschool.com/levels/1/challenges/1">Code School</a> (online tech learning environment)</li>
<li><a href="http://code-snippets.bungeshea.com/">Code Snippets</a> (WordPress snippet management plugin)</li> <li><a href="http://code-snippets.bungeshea.com/">Code Snippets</a> (WordPress snippet management plugin)</li>
<li><a href="http://antonmi.github.io/code_together/">Code together</a> (collaborative editing)</li> <li><a href="http://antonmi.github.io/code_together/">Code together</a> (collaborative editing)</li>
<li><a href="http://codev.it/">Codev</a> (collaborative IDE)</li>
<li><a href="https://www.codevolve.com/">Codevolve</a> (programming lessons as-a-service)</li> <li><a href="https://www.codevolve.com/">Codevolve</a> (programming lessons as-a-service)</li>
<li><a href="http://www.codezample.com">CodeZample</a> (code snippet sharing)</li> <li><a href="http://www.codezample.com">CodeZample</a> (code snippet sharing)</li>
<li><a href="http://codio.com">Codio</a> (Web IDE)</li> <li><a href="http://codio.com">Codio</a> (Web IDE)</li>
@ -101,6 +104,8 @@
<li><a href="http://megafonweblab.github.com/histone-javascript/">Histone template engine playground</a></li> <li><a href="http://megafonweblab.github.com/histone-javascript/">Histone template engine playground</a></li>
<li><a href="http://www.homegenie.it/docs/automation_getstarted.php">Homegenie</a> (home automation server)</li> <li><a href="http://www.homegenie.it/docs/automation_getstarted.php">Homegenie</a> (home automation server)</li>
<li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li> <li><a href="http://icecoder.net">ICEcoder</a> (web IDE)</li>
<li><a href="https://innovay.app/formatter/html">Innovay Web Tools</a> (HTML, JS, CSS code beautifier)</li>
<li><a href="https://www.intervue.io">Intervue</a> (Pair programming for interviews)</li>
<li><a href="http://ipython.org/">IPython</a> (interactive computing shell)</li> <li><a href="http://ipython.org/">IPython</a> (interactive computing shell)</li>
<li><a href="https://joelpinheiro.github.io/itrading/">iTrading</a> (Algorithmic Trading)</li> <li><a href="https://joelpinheiro.github.io/itrading/">iTrading</a> (Algorithmic Trading)</li>
<li><a href="http://i-mos.org/imos/">i-MOS</a> (modeling and simulation platform)</li> <li><a href="http://i-mos.org/imos/">i-MOS</a> (modeling and simulation platform)</li>
@ -150,6 +155,7 @@
<li><a href="https://www.realtime.io/">RealTime.io</a> (Internet-of-Things infrastructure)</li> <li><a href="https://www.realtime.io/">RealTime.io</a> (Internet-of-Things infrastructure)</li>
<li><a href="http://refork.com/">Refork</a> (animation demo gallery and sharing)</li> <li><a href="http://refork.com/">Refork</a> (animation demo gallery and sharing)</li>
<li><a href="http://sagecell.sagemath.org">SageMathCell</a> (interactive mathematical software)</li> <li><a href="http://sagecell.sagemath.org">SageMathCell</a> (interactive mathematical software)</li>
<li><a href="https://www.sass2css.online/">SASS2CSS</a> (SASS, SCSS or LESS to CSS converter and CSS beautifier)</li>
<li><a href="https://cloud.sagemath.com/">SageMathCloud</a> (interactive mathematical software environment)</li> <li><a href="https://cloud.sagemath.com/">SageMathCloud</a> (interactive mathematical software environment)</li>
<li><a href="https://github.com/szekelymilan/salvare">salvare</a> (real-time collaborative code editor)</li> <li><a href="https://github.com/szekelymilan/salvare">salvare</a> (real-time collaborative code editor)</li>
<li><a href="https://chrome.google.com/webstore/detail/servephp/mnpikomdchjhkhbhmbboehfdjkobbfpo">ServePHP</a> (PHP code testing in Chrome dev tools)</li> <li><a href="https://chrome.google.com/webstore/detail/servephp/mnpikomdchjhkhbhmbboehfdjkobbfpo">ServePHP</a> (PHP code testing in Chrome dev tools)</li>
@ -171,11 +177,13 @@
<li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li> <li><a href="https://thefiletree.com">The File Tree</a> (collab editor)</li>
<li><a href="http://www.mapbox.com/tilemill/">TileMill</a> (map design tool)</li> <li><a href="http://www.mapbox.com/tilemill/">TileMill</a> (map design tool)</li>
<li><a href="http://doc.tiki.org/Syntax+Highlighter">Tiki</a> (wiki CMS groupware)</li> <li><a href="http://doc.tiki.org/Syntax+Highlighter">Tiki</a> (wiki CMS groupware)</li>
<li><a href="https://www.tistory.com">Tistory</a> (blog service)</li>
<li><a href="http://www.toolsverse.com/products/data-explorer/">Toolsverse Data Explorer</a> (database management)</li> <li><a href="http://www.toolsverse.com/products/data-explorer/">Toolsverse Data Explorer</a> (database management)</li>
<li><a href="http://blog.englard.net/post/39608000629/codeintumblr">Tumblr code highlighting shim</a></li> <li><a href="http://blog.englard.net/post/39608000629/codeintumblr">Tumblr code highlighting shim</a></li>
<li><a href="http://turbopy.com/">TurboPY</a> (web publishing framework)</li> <li><a href="http://turbopy.com/">TurboPY</a> (web publishing framework)</li>
<li><a href="http://cruise.eecs.uottawa.ca/umpleonline/">UmpleOnline</a> (model-oriented programming tool)</li> <li><a href="http://cruise.eecs.uottawa.ca/umpleonline/">UmpleOnline</a> (model-oriented programming tool)</li>
<li><a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-7706e7832aa9e2fd0c2decdb5cbef2225692c696/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java">Upsource</a> (code browser and review tool)</li> <li><a href="https://upsource.jetbrains.com/idea-ce/file/idea-ce-7706e7832aa9e2fd0c2decdb5cbef2225692c696/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorFactoryImpl.java">Upsource</a> (code browser and review tool)</li>
<li><a href="https://violentmonkey.github.io/">Violentmonkey</a> (userscript manager / editor)</li>
<li><a href="https://github.com/mgaitan/waliki">Waliki</a> (wiki engine)</li> <li><a href="https://github.com/mgaitan/waliki">Waliki</a> (wiki engine)</li>
<li><a href="http://wamer.net/">Wamer</a> (web application builder)</li> <li><a href="http://wamer.net/">Wamer</a> (web application builder)</li>
<li><a href="https://github.com/brettz9/webappfind">webappfind</a> (windows file bindings for webapps)</li> <li><a href="https://github.com/brettz9/webappfind">webappfind</a> (windows file bindings for webapps)</li>

View File

@ -30,6 +30,178 @@
<h2>Version 5.x</h2> <h2>Version 5.x</h2>
<p class="rel">21-09-2020: <a href="https://codemirror.net/codemirror-5.58.0.zip">Version 5.58.0</a>:</p>
<ul class="rel-note">
<li><a href="https://codemirror.net/doc/manual.html#addon_placeholder">placeholder addon</a>: Remove arrow function that ended up in the code.</li>
</ul>
<h2>Version 5.x</h2>
<p class="rel">21-09-2020: <a href="https://codemirror.net/codemirror-5.58.0.zip">Version 5.58.0</a>:</p>
<ul class="rel-note">
<li>Make backspace delete by code point, not glyph.</li>
<li>Suppress flickering focus outline when clicking on scrollbars in Chrome.</li>
<li>Fix a bug that prevented attributes added via <code>markText</code> from showing up unless the span also had some other styling.</li>
<li>Suppress cut and paste context menu entries in readonly editors in Chrome.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_placeholder">placeholder addon</a>: Update placeholder visibility during composition.</li>
<li>Make it less cumbersome to style new lint message types.</li>
<li><a href="https://codemirror.net/demo/vim.html">vim bindings</a>: Support black hole register, <code>gn</code> and <code>gN</code></li>
</ul>
<p class="rel">20-08-2020: <a href="https://codemirror.net/codemirror-5.57.0.zip">Version 5.57.0</a>:</p>
<ul class="rel-note">
<li>Fix issue that broke binding the macOS Command key.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_comment">comment addon</a>: Keep selection in front of inserted markers when adding a block comment.</li>
<li><a href="https://codemirror.net/mode/css/">css mode</a>: Recognize more properties and value names.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_annotatescrollbar">annotatescrollbar addon</a>: Dont hide matches in collapsed content.</li>
<li><a href="https://codemirror.net/demo/vim.html">vim bindings</a>: Support tag text objects in xml and html modes.</li>
</ul>
<p class="rel">20-07-2020: <a href="https://codemirror.net/codemirror-5.56.0.zip">Version 5.56.0</a>:</p>
<ul class="rel-note">
<li>Line-wise pasting was fixed on Chrome Windows.</li>
<li><a href="https://codemirror.net/mode/wast/">wast mode</a>: Follow standard changes.</li>
<li><a href="https://codemirror.net/mode/soy/">soy mode</a>: Support import expressions, template type, and loop indices.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_sql-hint">sql-hint addon</a>: Improve handling of double quotes.</li>
<li><h3 id="new-features">New features</h3></li>
<li><a href="https://codemirror.net/doc/manual.html#addon_show-hint">show-hint addon</a>: New option <code>scrollMargin</code> to control how many options are visible beyond the selected one.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_hardwrap">hardwrap addon</a>: New option <code>forceBreak</code> to disable breaking of words that are longer than a line.</li>
</ul>
<p class="rel">21-06-2020: <a href="https://codemirror.net/codemirror-5.55.0.zip">Version 5.55.0</a>:</p>
<ul class="rel-note">
<li>The editor no longer overrides the rendering of zero-width joiners (allowing combined emoji to be shown).</li>
<li><a href="https://codemirror.net/demo/vim.html">vim bindings</a>: Fix an issue where the <code>vim-mode-change</code> event was fired twice.</li>
<li><a href="https://codemirror.net/mode/javascript/">javascript mode</a>: Only allow <code>--&gt;</code>-style comments at the start of a line.</li>
<li><a href="https://codemirror.net/mode/julia/">julia mode</a>: Improve indentation.</li>
<li><a href="https://codemirror.net/mode/pascal/index.html">pascal mode</a>: Recognize curly bracket comments.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_runmode">runmode addon</a>: Further sync up the implementation of the standalone and node variants with the regular library.</li>
<li><h3 id="new-features">New features</h3></li>
<li><a href="https://codemirror.net/doc/manual.html#addon_loadmode">loadmode addon</a>: Allow overriding the way the addon constructs filenames and loads modules.</li>
</ul>
<p class="rel">20-05-2020: <a href="https://codemirror.net/codemirror-5.54.0.zip">Version 5.54.0</a>:</p>
<ul class="rel-note">
<li><a href="https://codemirror.net/doc/manual.html#addon_runmode">runmode addon</a>: Properly support for cross-line lookahead.</li>
<li><a href="https://codemirror.net/demo/vim.html">vim bindings</a>: Allow Ex-Commands with non-word names.</li>
<li><a href="https://codemirror.net/mode/gfm/">gfm mode</a>: Add a <code>fencedCodeBlockDefaultMode</code> option.</li>
<li>Improve support for having focus inside in-editor widgets in contenteditable-mode.</li>
<li>Fix issue where the scroll position could jump when clicking on a selection in Chrome.</li>
<li><a href="https://codemirror.net/mode/python/">python mode</a>: Better format string support.</li>
<li><a href="https://codemirror.net/mode/javascript/">javascript mode</a>: Improve parsing of private properties and class fields.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_matchbrackets">matchbrackets addon</a>: Disable highlighting when the editor doesnt have focus.</li>
</ul>
<p class="rel">21-04-2020: <a href="https://codemirror.net/codemirror-5.53.2.zip">Version 5.53.2</a>:</p>
<ul class="rel-note">
<li><a href="https://codemirror.net/doc/manual.html#addon_show-hint">show-hint addon</a>: Fix a regression that broke completion picking.
</ul>
<p class="rel">21-04-2020: <a href="https://codemirror.net/codemirror-5.53.0.zip">Version 5.53.0</a>:</p>
<ul class="rel-note">
<li>New option: <a href="https://codemirror.net/doc/manual.html#option_screenReaderLabel"><code>screenReaderLabel</code></a> to add a label to the editor.</li>
<li>New mode: <a href="https://codemirror.net/mode/wast/">wast</a>.</li>
<li>Fix a bug where the editor layout could remain confused after a call to <code>refresh</code> when line wrapping was enabled.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_dialog">dialog addon</a>: Dont close dialogs when the document window loses focus.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_merge">merge addon</a>: Compensate for editor top position when aligning lines.</li>
<li><a href="https://codemirror.net/demo/vim.html">vim bindings</a>: Improve EOL handling.</li>
<li><a href="https://codemirror.net/demo/emacs.html">emacs bindings</a>: Include default keymap as a fallback.</li>
<li><a href="https://codemirror.net/mode/julia/">julia mode</a>: Fix an infinite loop bug.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_show-hint">show-hint addon</a>: Scroll cursor into view when picking a completion.</li>
</ul>
<p class="rel">20-03-2020: <a href="https://codemirror.net/codemirror-5.52.2.zip">Version 5.52.2</a>:</p>
<ul class="rel-note">
<li>Fix selection management in contenteditable mode when the editor doesnt have focus.</li>
<li>Fix a bug that would cause the editor to get confused about the visible viewport in some situations in line-wrapping mode.</li>
<li><a href="https://codemirror.net/mode/markdown/">markdown mode</a>: Dont treat single dashes as setext header markers.</li>
<li><a href="https://codemirror.net/demo/theme.html#zenburn">zenburn theme</a>: Make sure background styles take precedence over default styles.</li>
<li><a href="https://codemirror.net/mode/css/">css mode</a>: Recognize a number of new properties.</li>
</ul>
<p class="rel">20-02-2020: <a href="https://codemirror.net/codemirror-5.52.0.zip">Version 5.52.0</a>:</p>
<ul class="rel-note">
<li>Fix a bug in handling of bidi text with Arabic numbers in a right-to-left editor.</li>
<li>Fix a crash when combining file drop with a <code>"beforeChange"</code> filter.</li>
<li>Prevent issue when passing negative coordinates to <code>scrollTo</code>.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_lint">lint</a> and <a href="https://codemirror.net/demo/tern.html">tern</a> addons: Allow the tooltip to be appended to the editor wrapper element instead of the document body.</li>
</ul>
<p class="rel">20-01-2020: <a href="https://codemirror.net/codemirror-5.51.0.zip">Version 5.51.0</a>:</p>
<ul class="rel-note">
<li>Fix the behavior of the home and end keys when <code>direction</code> is set to <code>"rtl"</code>.</li>
<li>When dropping multiple files, dont abort the drop of the valid files when theres an invalid or binary file among them.</li>
<li>Make sure <code>clearHistory</code> clears the history in all linked docs with a shared history.</li>
<li><a href="https://codemirror.net/demo/vim.html">vim bindings</a>: Fix behavior of <code>'</code> and <code>`</code> marks, fix <code>R</code> in visual mode.</li>
<li><a href="https://codemirror.net/demo/vim.html">vim bindings</a>: Support <code>gi</code>, <code>gI<code>, and <code>gJ</code>.</li>
</ul>
<p class="rel">01-01-2020: <a href="https://codemirror.net/codemirror-5.50.2.zip">Version 5.50.2</a>:</p>
<ul class="rel-note">
<li>Fix bug that broke removal of line widgets.</li>
</ul>
<p class="rel">20-12-2019: <a href="https://codemirror.net/codemirror-5.50.0.zip">Version 5.50.0</a>:</p>
<ul class="rel-note">
<li>Add a <code>className</code> option to <a href="https://codemirror.net/doc/manual.html#addLineWidget"><code>addLineWidget</code></a>.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_foldcode">foldcode addon</a>: Allow fold widgets to be functions, to dynamically create fold markers.</li>
<li>New themes: <a href="https://codemirror.net/demo/theme.html#ayu-dark">ayu-dark</a> and <a href="https://codemirror.net/demo/theme.html#ayu-mirage">ayu-mirage</a>.</li>
<li>Make Shift-Delete to cut work on Firefox.</li>
<li><a href="https://codemirror.net/demo/closetag.html">closetag addon</a>: Properly handle self-closing tags.</li>
<li><a href="https://codemirror.net/mode/handlebars/">handlebars mode</a>: Fix triple-brace support.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_searchcursor">searchcursor addon</a>: Support mathing <code>$</code> in reverse regexp search.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_panel">panel addon</a>: Dont get confused by changing panel sizes.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_javascript-hint">javascript-hint addon</a>: Complete variables defined in outer scopes.</li>
<li><a href="https://codemirror.net/demo/sublime.html">sublime bindings</a>: Make by-subword motion more consistent with Sublime Text.</li>
<li><a href="https://codemirror.net/mode/julia/">julia mode</a>: Dont break on zero-prefixed integers.</li>
<li><a href="https://codemirror.net/mode/elm/">elm mode</a>: Sync with upstream version.</li>
<li><a href="https://codemirror.net/mode/sql/">sql mode</a>: Support Postgres-style backslash-escaped string literals.</li>
</ul>
<p class="rel">21-10-2019: <a href="https://codemirror.net/codemirror-5.49.2.zip">Version 5.49.2</a>:</p>
<ul class="rel-note">
<li><a href="https://codemirror.net/demo/sublime.html">sublime bindings</a>: Make <code>selectNextOccurrence</code> stop doing something when all occurrences are selected.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_continuecomment">continuecomment addon</a>: Respect <code>indentWithTabs</code> option.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_foldgutter">foldgutter addon</a>: Optimize by reusing DOM when possible.</li>
<li><a href="https://codemirror.net/mode/markdown/">markdown mode</a>: Dont reset inline styles at the start of a continued list item line.</li>
<li><a href="https://codemirror.net/mode/clike/">clike mode</a>: Add a configuration for Objective-C++.</li>
</ul>
<p class="rel">20-09-2019: <a href="https://codemirror.net/codemirror-5.49.0.zip">Version 5.49.0</a>:</p>
<ul class="rel-note">
<li>New themes: <a href="https://codemirror.net/demo/theme.html#moxer">moxer</a>, <a href="https://codemirror.net/demo/theme.html#material-darker">material-darker</a>, <a href="https://codemirror.net/demo/theme.html#material-palenight">material-palenight</a>, <a href="https://codemirror.net/demo/theme.html#material-ocean">material-ocean</a>.</li>
<li><a href="https://codemirror.net/mode/xml/">xml mode</a>: Provide a more abstract way to query context, which other modes for XML-like languages can also implement.</li>
<li><a href="https://codemirror.net/mode/octave/index.html">octave mode</a>: Dont mark common punctuation as error.</li>
<li><a href="https://codemirror.net/mode/clike/">clike mode</a>: Support nested comments and properly indent lambdas in Kotlin.</li>
<li><a href="https://codemirror.net/doc/manual.html#addon_foldgutter">foldgutter</a> and <a href="https://codemirror.net/doc/manual.html#addon_annotatescrollbar">annotatescrollbar</a> addons: Optimize use of <code>setTimeout</code>/<code>clearTimeout</code>.</li>
</ul>
<p class="rel">20-08-2019: <a href="https://codemirror.net/codemirror-5.48.4.zip">Version 5.48.4</a>:</p>
<ul class="rel-note">
<li>Make default styles for line elements more specific so that they dont apply to all <code>&lt;pre&gt;</code> elements inside the editor.</li>
<li>Improve efficiency of fold gutter when theres big folded chunks of code in view.</li>
<li>Fix a bug that would leave the editor uneditable when a content-covering collapsed range was removed by replacing the entire document.</li>
<li><a href="https://codemirror.net/mode/julia/">julia mode</a>: Support number separators.</li>
<li><a href="https://codemirror.net/mode/asterisk/">asterisk mode</a>: Improve comment support.</li>
<li><a href="https://codemirror.net/mode/handlebars/">handlebars mode</a>: Support triple-brace tags.</li>
</ul>
<p class="rel">20-07-2019: <a href="https://codemirror.net/codemirror-5.48.2.zip">Version 5.48.2</a>:</p> <p class="rel">20-07-2019: <a href="https://codemirror.net/codemirror-5.48.2.zip">Version 5.48.2</a>:</p>
<ul class="rel-note"> <ul class="rel-note">

View File

@ -99,7 +99,7 @@
</div> </div>
</div> </div>
<div class=actionsleft> <div class=actionsleft>
Get the current version: <a href="https://codemirror.net/codemirror.zip">5.48.2</a>.<br> Get the current version: <a href="https://codemirror.net/codemirror.zip">5.58.1</a>.<br>
You can see the <a href="https://github.com/codemirror/codemirror" title="Github repository">code</a>,<br> You can see the <a href="https://github.com/codemirror/codemirror" title="Github repository">code</a>,<br>
read the <a href="doc/releases.html">release notes</a>,<br> read the <a href="doc/releases.html">release notes</a>,<br>
or study the <a href="doc/manual.html">user manual</a>. or study the <a href="doc/manual.html">user manual</a>.
@ -171,11 +171,6 @@
that explicit, we have that explicit, we have
a <a href="http://contributor-covenant.org/version/1/1/0/">code of a <a href="http://contributor-covenant.org/version/1/1/0/">code of
conduct</a> that applies to communication around the project.</p> conduct</a> that applies to communication around the project.</p>
<p>A list of CodeMirror-related software that is not part of the
main distribution is maintained
on <a href="https://github.com/codemirror/CodeMirror/wiki/CodeMirror-addons">our
wiki</a>. Feel free to add your project.</p>
</section> </section>
<section id=browsersupport> <section id=browsersupport>
@ -195,4 +190,21 @@
pretty well.</p> pretty well.</p>
</section> </section>
<section id=sponsors>
<style>
ul.sponsor-list { padding-left: 10px }
ul.sponsor-list li { list-style: none; margin-bottom: 1em }
ul.sponsor-list img { max-width: 80%; max-height: 10em; width: 20em }
</style>
<h2>Sponsors</h2>
<p>These companies support development of this project:</p>
<ul class=sponsor-list>
<li><a href="https://codepen.io/"><img src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 138 26"><path fill="none" stroke="black" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" d="M15 8a7 7 0 100 10m7-8.7L33 2l11 7.3v7.4L33 24l-11-7.3zm0 0l11 7.4 11-7.4m0 7.4L33 9.3l-11 7.4M33 2v7.3m0 7.4V24M52 6h5a7 7 0 010 14h-5zm28 0h-9v14h9m-9-7h6m11 1h6a4 4 0 000-8h-6v14m26-14h-9v14h9m-9-7h6m11 7V6l11 14V6"/></svg>' alt="CodePen"></a></li>
<li><a href="https://www.jetbrains.com/"><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='39 0 142.7 119'%3E%3ClinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='4.7875' y1='6.8451' x2='75.7999' y2='54.4038'%3E%3Cstop offset='0' stop-color='%23AA4A9B'/%3E%3Cstop offset='1' stop-color='%23F05922'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23SVGID_1_)' d='M81.3,57.6L18.7,3.1c-1.9-1.8-4.5-3-7.3-3.1C5.2-0.2,0.2,4.6,0,10.7c-0.1,4.3,2.3,8.1,5.8,10l70.4,43.7c0.1,0.1,0.2,0.1,0.3,0.2c2.1,1.1,4.6,0.4,5.8-1.6C83.4,61.2,82.9,58.9,81.3,57.6z'/%3E%3ClinearGradient id='SVGID_2_' gradientUnits='userSpaceOnUse' x1='28.3538' y1='119.6551' x2='139.5938' y2='60.2551'%3E%3Cstop offset='0' stop-color='%23FFE42E'/%3E%3Cstop offset='1' stop-color='%23ED417C'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23SVGID_2_)' d='M142.7,66.3c-0.3-8.6-7.6-15.3-16.2-14.9c-2.7,0.1-5.3,0.9-7.5,2.2l-88,50.1c0,0-0.1,0-0.1,0.1c-3,1.2-5,4.2-4.9,7.6c0.2,4.4,3.8,7.8,8.2,7.6c1,0,2-0.3,2.9-0.7l95.9-37c0,0,0.1,0,0.2-0.1C138.9,78.8,142.9,73,142.7,66.3z'/%3E%3ClinearGradient id='SVGID_3_' gradientUnits='userSpaceOnUse' x1='31.6974' y1='114.3816' x2='72.0174' y2='55.3416'%3E%3Cstop offset='0' stop-color='%23FFE42E'/%3E%3Cstop offset='1' stop-color='%23F05922'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23SVGID_3_)' d='M71.8,64c1.1-2.1,0.3-4.7-1.8-5.7c-1.9-1-4.2-0.4-5.4,1.3l-37.1,47.1c0,0,0,0.1-0.1,0.2c-1.8,2.7-1.8,6.3,0.3,9c2.6,3.5,7.5,4.2,11,1.7c1-0.8,1.8-1.8,2.4-2.8l30.5-50.2C71.6,64.3,71.7,64.1,71.8,64z'/%3E%3Crect x='45.5' y='35.7' width='51' height='51'/%3E%3Crect x='49.9' y='77.1' fill='%23fff' width='19.1' height='3.2'/%3E%3Cpath fill='%23fff' d='M49.7,49.1l1.5-1.4c0.4,0.5,0.8,0.8,1.3,0.8c0.6,0,0.9-0.4,0.9-1.2V42h2.3v5.3c0,1-0.3,1.8-0.8,2.3c-0.5,0.5-1.3,0.8-2.3,0.8C51.2,50.5,50.3,49.9,49.7,49.1z'/%3E%3Cpath fill='%23fff' d='M56.3,42h6.7V44h-4.4v1.3h4v1.8h-4v1.3H63v2h-6.7V42z'/%3E%3Cpath fill='%23fff' d='M66,44.1h-2.5v-2h7.3v2h-2.5v6.3H66V44.1z'/%3E%3Cpath fill='%23fff' d='M49.9,52.3h4.3c1,0,1.8,0.3,2.3,0.7c0.3,0.3,0.5,0.8,0.5,1.4v0c0,1-0.5,1.5-1.3,1.9c1,0.3,1.7,0.9,1.7,2v0c0,1.4-1.2,2.3-3.1,2.3h-4.3V52.3z M54.7,54.9c0-0.5-0.4-0.7-1-0.7h-1.5v1.5h1.4C54.3,55.6,54.7,55.4,54.7,54.9L54.7,54.9z M53.9,57.2h-1.8v1.5h1.8c0.7,0,1.1-0.3,1.1-0.8v0C55,57.5,54.7,57.2,53.9,57.2z'/%3E%3Cpath fill='%23fff' d='M57.7,52.3h3.9c1.3,0,2.2,0.3,2.7,0.9c0.5,0.5,0.7,1.1,0.7,1.9v0c0,1.3-0.7,2.1-1.7,2.6l2,2.9h-2.6L61,58.1h-1v2.5h-2.3V52.3z M61.5,56.3c0.8,0,1.2-0.4,1.2-1v0c0-0.7-0.5-1-1.2-1H60v2H61.5z'/%3E%3Cpath fill='%23fff' d='M67.8,52.2H70l3.5,8.4h-2.5l-0.6-1.5h-3.2l-0.6,1.5h-2.4L67.8,52.2z M69.8,57.3L68.9,55l-0.9,2.4H69.8z'/%3E%3Cpath fill='%23fff' d='M73.8,52.3h2.3v8.3h-2.3V52.3z'/%3E%3Cpath fill='%23fff' d='M76.7,52.3h2.2l3.4,4.4v-4.4h2.3v8.3h-2L79,56.1v4.6h-2.3V52.3z'/%3E%3Cpath fill='%23fff' d='M84.7,59.4l1.3-1.5c0.8,0.7,1.7,1,2.7,1c0.6,0,1-0.2,1-0.6v0c0-0.4-0.3-0.5-1.4-0.8c-1.8-0.4-3.1-0.9-3.1-2.6v0c0-1.5,1.2-2.7,3.2-2.7c1.4,0,2.5,0.4,3.4,1.1l-1.2,1.6c-0.8-0.5-1.6-0.8-2.3-0.8c-0.6,0-0.8,0.2-0.8,0.5v0c0,0.4,0.3,0.5,1.4,0.8c1.9,0.4,3.1,1,3.1,2.6v0c0,1.7-1.3,2.7-3.4,2.7C87.1,60.8,85.7,60.3,84.7,59.4z'/%3E%3C/svg%3E%0A" alt="JetBrains"></a>
<li><a href="https://www.desmos.com/"><img src='data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 107.05 22.17" fill="%23187a3d"%3E%3Cpath d="M89.91 7.50c-1.62-1.67-3.64-2.53-5.98-2.53-2.34 0-4.36.85-5.99 2.53s-2.45 3.73-2.45 6.1a8.4 8.4 0 0 0 2.43 6.02 8.13 8.13 0 0 0 6.02 2.51c2.37 0 4.4-.85 6-2.51 1.6-1.68 2.43-3.7 2.43-6.05a8.41 8.41 0 0 0-2.46-6.07m-5.98.41c1.47 0 2.72.56 3.81 1.68a5.6 5.6 0 0 1 1.61 4.01c0 1.58-.52 2.88-1.6 3.98-1.06 1.1-2.32 1.63-3.87 1.63-1.53 0-2.8-.53-3.82-1.61-1.05-1.1-1.56-2.4-1.56-3.97 0-1.58.53-2.90 1.61-4.05 1.07-1.13 2.32-1.68 3.80-1.68M15.25 0a1.47 1.47 0 0 0-1.44 1.25l-.00 5.78c-1.27-1.12-2.75-1.8-4.42-1.97h-.04c-.10-.01-.22-.01-.32-.03l-.33-.03a10.1 10.1 0 0 0-.76.01l-.06.01c-.11 0-.23.01-.34.02l-.43.04-.09.02-.28.04c-.14.01-.26.06-.41.08a7.94 7.94 0 0 0-3.55 1.98l-.04.02-.37.4-.18.21a7.34 7.34 0 0 0-.52.65 1.78 1.78 0 0 0-.15.21l-.04.06C.46 10.17 0 11.79 0 13.55l.00.44.07.78.05.33.07.33.05.26c.36 1.41 1.08 2.7 2.15 3.80a8.59 8.59 0 0 0 1.38 1.17l.23.15c.03.02.06.03.09.05l.03.01c.19.12.4.22.57.32l.38.17c.99.41 2.09.62 3.26.62h.04l.39-.01a1.36 1.36 0 0 0 .19-.01h.05l.18-.01c.04-.01.09-.01.12-.01a7.86 7.86 0 0 0 4.42-1.93v.67l.00.07a1.47 1.47 0 0 0 1.26 1.24h.38c.73-.1 1.27-.73 1.27-1.46V1.47c0-.8-.65-1.47-1.46-1.47M13.74 13.59c0 1.57-.51 2.85-1.57 3.94s-2.30 1.62-3.82 1.62a5.39 5.39 0 0 1-1.87-.32c-.02-.00-.04-.00-.05-.01l-.07-.03c-.64-.25-1.26-.67-1.79-1.23a5.46 5.46 0 0 1-1.38-2.58c-.1-.43-.14-.88-.14-1.34 0-1.57.51-2.87 1.58-4.01C5.66 8.48 6.9 7.94 8.36 7.94c1.47 0 2.69.54 3.77 1.67 1.1 1.13 1.60 2.43 1.60 3.97m21.89-.36c0-.2-.02-.43-.03-.65-.13-1.25-.52-2.41-1.15-3.45-.34-.57-.75-1.11-1.25-1.62-1.2-1.24-2.64-2.05-4.26-2.37l-.13-.01c-.11-.03-.24-.04-.35-.06l-.52-.05-.33-.02a11.34 11.34 0 0 0-.82 0c-1.50.07-2.88.50-4.08 1.30a7.49 7.49 0 0 0-.50.36l-.63.54-.32.31a8.49 8.49 0 0 0-2.45 6.10c0 1.1.19 2.17.57 3.14.39 1.03 1.02 2 1.86 2.86l.62.59a9.28 9.28 0 0 0 1.00.74l.72.39a8.75 8.75 0 0 0 1.96.64l.43.07.42.04c.13.01.26.02.40.02l.06.00a4.88 4.88 0 0 0 .37.01h.04l.39-.01.28-.01.12-.01a7.97 7.97 0 0 0 5.15-2.47c.32-.33.61-.68.86-1.04a4.51 4.51 0 0 0 .27-.40l.04-.08a1.45 1.45 0 0 0 .10-.53 1.5 1.5 0 0 0-1.50-1.49c-.5 0-.95.24-1.24.65a5.5 5.5 0 0 1-.71.89c-1.05 1.1-2.32 1.63-3.87 1.63-1.53 0-2.78-.53-3.83-1.61a7.25 7.25 0 0 1-.50-.6l-.05-.09c-.12-.18-.24-.36-.36-.60a5.01 5.01 0 0 1-.50-1.49h12.45l.11-.02c.62-.13 1.1-.65 1.16-1.30v-.04l-.01-.24m-13.64-1.11a5.36 5.36 0 0 1 .68-1.57l.04-.07c.2-.30.43-.58.7-.87 1.07-1.13 2.31-1.68 3.79-1.68s2.73.56 3.81 1.68c.50.53.89 1.11 1.17 1.74a5.44 5.44 0 0 1 .25.76zm51.46-1.14v9.57a1.48 1.48 0 0 1-1.48 1.47c-.75 0-1.39-.55-1.47-1.32v-9.68a3.2 3.2 0 0 0-.91-2.30c-.56-.57-1.19-.9-1.93-.94-.06-.01-.14-.01-.22-.01-.84 0-1.53.31-2.13.95a3.19 3.19 0 0 0-.91 2.14v.13l.00.09-.00.02v9.45a1.47 1.47 0 0 1-1.47 1.47 1.47 1.47 0 0 1-1.48-1.32l-.00-.05.01-9.64c-.01-.07-.01-.12-.01-.17-.02-.46-.41-1.37-.41-1.37s-.30-.53-.50-.74c-.60-.63-1.31-.95-2.15-.95-.83 0-1.52.31-2.13.95a3.2 3.2 0 0 0-.92 2.3v9.73a1.48 1.48 0 0 1-1.47 1.28 1.48 1.48 0 0 1-1.47-1.47V6.33c0-.82.66-1.48 1.47-1.48.60 0 1.14.38 1.37.91l.32-.21a5.89 5.89 0 0 1 2.83-.7c1.5 0 2.82.5 3.92 1.46a3.73 3.73 0 0 1 .34.34l.27.28.26-.28.35-.34a5.76 5.76 0 0 1 3.90-1.46l.50.02c1.3.1 2.45.58 3.42 1.46l.34.33a5.99 5.99 0 0 1 1.74 4.32"/%3E%3Cpath d="M50.32 17.13c0 2.74-2.21 4.98-4.94 5.03h-5.98a1.45 1.45 0 0 1-1.44-1.45c0-.8.64-1.44 1.45-1.44h5.91a2.13 2.13 0 0 0 2.1-2.13 2.13 2.13 0 0 0-2.12-2.12h-2.86c-2.77 0-5.03-2.24-5.03-5.02a5.04 5.04 0 0 1 5.03-5.03h5.91a1.46 1.46 0 0 1 1.45 1.46 1.46 1.46 0 0 1-1.45 1.44h-5.91c-1.17 0-2.12.95-2.12 2.12 0 1.15.94 2.1 2.1 2.12h.05c.01 0 .04 0 .09-.00h2.73c.70 0 1.39.14 2.03.43a5.04 5.04 0 0 1 3 4.59m56.74-.00c0 2.74-2.22 5-4.95 5.03h-5.98a1.46 1.46 0 0 1-1.45-1.45 1.45 1.45 0 0 1 1.45-1.44h5.9c1.15-.01 2.10-.96 2.10-2.13a2.13 2.13 0 0 0-2.12-2.12h-2.63c-.07.01-.14.01-.22.01-2.77 0-5.03-2.24-5.03-5.03a5.04 5.04 0 0 1 5.03-5.03h5.90a1.47 1.47 0 0 1 1.45 1.46c0 .79-.65 1.45-1.45 1.45h-5.90a2.13 2.13 0 0 0-2.13 2.12 2.14 2.14 0 0 0 2.10 2.12h.05c.01 0 .05 0 .08-.00h2.74a4.87 4.87 0 0 1 2.03.43c1.82.8 3 2.61 3 4.59"/%3E%3C/svg%3E%0A' alt=desmos></a></li>
</ul>
</section>
</article> </article>

View File

@ -404,7 +404,8 @@
"Ctrl-X H": "selectAll", "Ctrl-X H": "selectAll",
"Ctrl-Q Tab": repeated("insertTab"), "Ctrl-Q Tab": repeated("insertTab"),
"Ctrl-U": addPrefixMap "Ctrl-U": addPrefixMap,
"fallthrough": "default"
}); });
var prefixMap = {"Ctrl-G": clearPrefix}; var prefixMap = {"Ctrl-G": clearPrefix};

View File

@ -22,17 +22,21 @@
if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1)); if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1));
var line = doc.getLine(start.line); var line = doc.getLine(start.line);
if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0)); if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0));
var state = "start", type; var state = "start", type, startPos = start.ch;
for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) { 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 next = line.charAt(dir < 0 ? pos - 1 : pos);
var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o"; var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o";
if (cat == "w" && next.toUpperCase() == next) cat = "W"; if (cat == "w" && next.toUpperCase() == next) cat = "W";
if (state == "start") { if (state == "start") {
if (cat != "o") { state = "in"; type = cat; } if (cat != "o") { state = "in"; type = cat; }
else startPos = pos + dir
} else if (state == "in") { } else if (state == "in") {
if (type != cat) { if (type != cat) {
if (type == "w" && cat == "W" && dir < 0) pos--; 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; break;
} }
} }
@ -144,14 +148,24 @@
cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0));
found = cur.findNext(); found = cur.findNext();
} }
if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) if (!found || isSelectedRange(cm.listSelections(), cur.from(), cur.to())) return
return CodeMirror.Pass
cm.addSelection(cur.from(), cur.to()); cm.addSelection(cur.from(), cur.to());
} }
if (fullWord) if (fullWord)
cm.state.sublimeFindFullWord = cm.doc.sel; 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) { function addCursorToSelection(cm, dir) {
var ranges = cm.listSelections(), newRanges = []; var ranges = cm.listSelections(), newRanges = [];
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
@ -175,7 +189,8 @@
function isSelectedRange(ranges, from, to) { function isSelectedRange(ranges, from, to) {
for (var i = 0; i < ranges.length; i++) 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 return false
} }
@ -213,11 +228,15 @@
if (!selectBetweenBrackets(cm)) return CodeMirror.Pass; if (!selectBetweenBrackets(cm)) return CodeMirror.Pass;
}; };
function puncType(type) {
return !type ? null : /\bpunctuation\b/.test(type) ? type : undefined
}
cmds.goToBracket = function(cm) { cmds.goToBracket = function(cm) {
cm.extendSelectionsBy(function(range) { 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; 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; return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head;
}); });
}; };
@ -597,6 +616,7 @@
"Shift-Cmd-F2": "clearBookmarks", "Shift-Cmd-F2": "clearBookmarks",
"Alt-F2": "selectBookmarks", "Alt-F2": "selectBookmarks",
"Backspace": "smartBackspace", "Backspace": "smartBackspace",
"Cmd-K Cmd-D": "skipAndSelectNextOccurrence",
"Cmd-K Cmd-K": "delLineRight", "Cmd-K Cmd-K": "delLineRight",
"Cmd-K Cmd-U": "upcaseAtCursor", "Cmd-K Cmd-U": "upcaseAtCursor",
"Cmd-K Cmd-L": "downcaseAtCursor", "Cmd-K Cmd-L": "downcaseAtCursor",
@ -608,6 +628,7 @@
"Cmd-K Cmd-C": "showInCenter", "Cmd-K Cmd-C": "showInCenter",
"Cmd-K Cmd-G": "clearBookmarks", "Cmd-K Cmd-G": "clearBookmarks",
"Cmd-K Cmd-Backspace": "delLineLeft", "Cmd-K Cmd-Backspace": "delLineLeft",
"Cmd-K Cmd-1": "foldAll",
"Cmd-K Cmd-0": "unfoldAll", "Cmd-K Cmd-0": "unfoldAll",
"Cmd-K Cmd-J": "unfoldAll", "Cmd-K Cmd-J": "unfoldAll",
"Ctrl-Shift-Up": "addCursorToPrevLine", "Ctrl-Shift-Up": "addCursorToPrevLine",
@ -657,6 +678,7 @@
"Shift-Ctrl-F2": "clearBookmarks", "Shift-Ctrl-F2": "clearBookmarks",
"Alt-F2": "selectBookmarks", "Alt-F2": "selectBookmarks",
"Backspace": "smartBackspace", "Backspace": "smartBackspace",
"Ctrl-K Ctrl-D": "skipAndSelectNextOccurrence",
"Ctrl-K Ctrl-K": "delLineRight", "Ctrl-K Ctrl-K": "delLineRight",
"Ctrl-K Ctrl-U": "upcaseAtCursor", "Ctrl-K Ctrl-U": "upcaseAtCursor",
"Ctrl-K Ctrl-L": "downcaseAtCursor", "Ctrl-K Ctrl-L": "downcaseAtCursor",
@ -668,6 +690,7 @@
"Ctrl-K Ctrl-C": "showInCenter", "Ctrl-K Ctrl-C": "showInCenter",
"Ctrl-K Ctrl-G": "clearBookmarks", "Ctrl-K Ctrl-G": "clearBookmarks",
"Ctrl-K Ctrl-Backspace": "delLineLeft", "Ctrl-K Ctrl-Backspace": "delLineLeft",
"Ctrl-K Ctrl-1": "foldAll",
"Ctrl-K Ctrl-0": "unfoldAll", "Ctrl-K Ctrl-0": "unfoldAll",
"Ctrl-K Ctrl-J": "unfoldAll", "Ctrl-K Ctrl-J": "unfoldAll",
"Ctrl-Alt-Up": "addCursorToPrevLine", "Ctrl-Alt-Up": "addCursorToPrevLine",

View File

@ -8,7 +8,7 @@
* Supported Ex commands: * Supported Ex commands:
* Refer to defaultExCommandMap below. * Refer to defaultExCommandMap below.
* *
* Registers: unnamed, -, a-z, A-Z, 0-9 * Registers: unnamed, -, ., :, /, _, a-z, A-Z, 0-9
* (Does not respect the special case for number registers when delete * (Does not respect the special case for number registers when delete
* operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) * operator is made with these commands: %, (, ), , /, ?, n, N, {, } )
* TODO: Implement the remaining registers. * TODO: Implement the remaining registers.
@ -141,6 +141,8 @@
{ keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true },
{ keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }},
{ keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }},
{ keys: 'gn', type: 'motion', motion: 'findAndSelectNextInclusive', motionArgs: { forward: true }},
{ keys: 'gN', type: 'motion', motion: 'findAndSelectNextInclusive', motionArgs: { forward: false }},
// Operator-Motion dual commands // Operator-Motion dual commands
{ keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }},
{ keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }},
@ -164,7 +166,9 @@
{ keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, { 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: '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: '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: '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: '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: true }, context: 'normal' },
{ keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' },
@ -174,13 +178,15 @@
{ keys: '<C-q>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, { keys: '<C-q>', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }},
{ keys: 'gv', type: 'action', action: 'reselectLastSelection' }, { keys: 'gv', type: 'action', action: 'reselectLastSelection' },
{ keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, { 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: true, isEdit: true }},
{ keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }},
{ keys: 'r<character>', type: 'action', action: 'replace', isEdit: true }, { keys: 'r<character>', type: 'action', action: 'replace', isEdit: true },
{ keys: '@<character>', type: 'action', action: 'replayMacro' }, { keys: '@<character>', type: 'action', action: 'replayMacro' },
{ keys: 'q<character>', type: 'action', action: 'enterMacroRecordMode' }, { keys: 'q<character>', type: 'action', action: 'enterMacroRecordMode' },
// Handle Replace-mode as a special case of insert mode. // 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: '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: true}, context: 'visual', isEdit: true },
{ keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true },
@ -230,7 +236,6 @@
{ name: 'undo', shortName: 'u' }, { name: 'undo', shortName: 'u' },
{ name: 'redo', shortName: 'red' }, { name: 'redo', shortName: 'red' },
{ name: 'set', shortName: 'se' }, { name: 'set', shortName: 'se' },
{ name: 'set', shortName: 'se' },
{ name: 'setlocal', shortName: 'setl' }, { name: 'setlocal', shortName: 'setl' },
{ name: 'setglobal', shortName: 'setg' }, { name: 'setglobal', shortName: 'setg' },
{ name: 'sort', shortName: 'sor' }, { name: 'sort', shortName: 'sor' },
@ -291,16 +296,16 @@
clearFatCursorMark(cm); clearFatCursorMark(cm);
var ranges = cm.listSelections(), result = [] var ranges = cm.listSelections(), result = []
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var range = ranges[i] var range = ranges[i];
if (range.empty()) { 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), 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 { } else {
var widget = document.createElement("span") result.push(cm.markText(Pos(range.anchor.line, lineLength - 1),
widget.textContent = "\u00a0" Pos(range.anchor.line, lineLength),
widget.className = "cm-fat-cursor-mark" {className: "cm-fat-cursor-mark"}));
result.push(cm.setBookmark(range.anchor, {widget: widget}))
} }
} }
} }
@ -413,7 +418,7 @@
var lowerCaseAlphabet = makeKeyRange(97, 26); var lowerCaseAlphabet = makeKeyRange(97, 26);
var numbers = makeKeyRange(48, 10); var numbers = makeKeyRange(48, 10);
var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']);
var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '_', '/']);
function isLine(cm, line) { function isLine(cm, line) {
return line >= cm.firstLine() && line <= cm.lastLine(); return line >= cm.firstLine() && line <= cm.lastLine();
@ -594,9 +599,16 @@
} }
return mark; return mark;
} }
function find(cm, offset) {
var oldPointer = pointer;
var mark = move(cm, offset);
pointer = oldPointer;
return mark && mark.find();
}
return { return {
cachedCursor: undefined, //used for # and * jumps cachedCursor: undefined, //used for # and * jumps
add: add, add: add,
find: find,
move: move move: move
}; };
}; };
@ -1118,6 +1130,8 @@
} }
RegisterController.prototype = { RegisterController.prototype = {
pushText: function(registerName, operator, text, linewise, blockwise) { pushText: function(registerName, operator, text, linewise, blockwise) {
// The black hole register, "_, means delete/yank to nowhere.
if (registerName === '_') return;
if (linewise && text.charAt(text.length - 1) !== '\n'){ if (linewise && text.charAt(text.length - 1) !== '\n'){
text += '\n'; text += '\n';
} }
@ -1293,6 +1307,10 @@
} }
inputState.operator = command.operator; inputState.operator = command.operator;
inputState.operatorArgs = copyArgs(command.operatorArgs); inputState.operatorArgs = copyArgs(command.operatorArgs);
if (command.exitVisualBlock) {
vim.visualBlock = false;
updateCmSelection(cm);
}
if (vim.visualMode) { if (vim.visualMode) {
// Operating on a selection in visual mode. We don't need a motion. // Operating on a selection in visual mode. We don't need a motion.
this.evalInput(cm, vim); this.evalInput(cm, vim);
@ -1560,7 +1578,7 @@
motionArgs.repeat = repeat; motionArgs.repeat = repeat;
clearInputState(cm); clearInputState(cm);
if (motion) { if (motion) {
var motionResult = motions[motion](cm, origHead, motionArgs, vim); var motionResult = motions[motion](cm, origHead, motionArgs, vim, inputState);
vim.lastMotion = motions[motion]; vim.lastMotion = motions[motion];
if (!motionResult) { if (!motionResult) {
return; return;
@ -1588,10 +1606,10 @@
} }
if (vim.visualMode) { if (vim.visualMode) {
if (!(vim.visualBlock && newHead.ch === Infinity)) { if (!(vim.visualBlock && newHead.ch === Infinity)) {
newHead = clipCursorToContent(cm, newHead, vim.visualBlock); newHead = clipCursorToContent(cm, newHead);
} }
if (newAnchor) { if (newAnchor) {
newAnchor = clipCursorToContent(cm, newAnchor, true); newAnchor = clipCursorToContent(cm, newAnchor);
} }
newAnchor = newAnchor || oldAnchor; newAnchor = newAnchor || oldAnchor;
sel.anchor = newAnchor; sel.anchor = newAnchor;
@ -1758,6 +1776,87 @@
highlightSearchMatches(cm, query); highlightSearchMatches(cm, query);
return findNext(cm, prev/** prev */, query, motionArgs.repeat); return findNext(cm, prev/** prev */, query, motionArgs.repeat);
}, },
/**
* Find and select the next occurrence of the search query. If the cursor is currently
* within a match, then find and select the current match. Otherwise, find the next occurrence in the
* appropriate direction.
*
* This differs from `findNext` in the following ways:
*
* 1. Instead of only returning the "from", this returns a "from", "to" range.
* 2. If the cursor is currently inside a search match, this selects the current match
* instead of the next match.
* 3. If there is no associated operator, this will turn on visual mode.
*/
findAndSelectNextInclusive: function(cm, _head, motionArgs, vim, prevInputState) {
var state = getSearchState(cm);
var query = state.getQuery();
if (!query) {
return;
}
var prev = !motionArgs.forward;
prev = (state.isReversed()) ? !prev : prev;
// next: [from, to] | null
var next = findNextFromAndToInclusive(cm, prev, query, motionArgs.repeat, vim);
// No matches.
if (!next) {
return;
}
// If there's an operator that will be executed, return the selection.
if (prevInputState.operator) {
return next;
}
// At this point, we know that there is no accompanying operator -- let's
// deal with visual mode in order to select an appropriate match.
var from = next[0];
// For whatever reason, when we use the "to" as returned by searchcursor.js directly,
// the resulting selection is extended by 1 char. Let's shrink it so that only the
// match is selected.
var to = Pos(next[1].line, next[1].ch - 1);
if (vim.visualMode) {
// If we were in visualLine or visualBlock mode, get out of it.
if (vim.visualLine || vim.visualBlock) {
vim.visualLine = false;
vim.visualBlock = false;
CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: ""});
}
// If we're currently in visual mode, we should extend the selection to include
// the search result.
var anchor = vim.sel.anchor;
if (anchor) {
if (state.isReversed()) {
if (motionArgs.forward) {
return [anchor, from];
}
return [anchor, to];
} else {
if (motionArgs.forward) {
return [anchor, to];
}
return [anchor, from];
}
}
} else {
// Let's turn visual mode on.
vim.visualMode = true;
vim.visualLine = false;
vim.visualBlock = false;
CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: ""});
}
return prev ? [to, from] : [from, to];
},
goToMark: function(cm, _head, motionArgs, vim) { goToMark: function(cm, _head, motionArgs, vim) {
var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter); var pos = getMarkPos(cm, vim, motionArgs.selectedCharacter);
if (pos) { if (pos) {
@ -1843,12 +1942,18 @@
var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat;
var first = cm.firstLine(); var first = cm.firstLine();
var last = cm.lastLine(); 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 // Vim go to line begin or line end when cursor at first/last line and
// move to previous/next line is triggered. // move to previous/next line is triggered.
if (line < first && cur.line == first){ if (line < first && cur.line == first){
return this.moveToStartOfLine(cm, head, motionArgs, vim); return this.moveToStartOfLine(cm, head, motionArgs, vim);
}else if (line > last && cur.line == last){ } else if (line > last && cur.line == last){
return this.moveToEol(cm, head, motionArgs, vim, true); return moveToEol(cm, head, motionArgs, vim, true);
} }
if (motionArgs.toFirstChar){ if (motionArgs.toFirstChar){
endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line));
@ -1950,16 +2055,8 @@
vim.lastHSPos = cm.charCoords(head,'div').left; vim.lastHSPos = cm.charCoords(head,'div').left;
return moveToColumn(cm, repeat); return moveToColumn(cm, repeat);
}, },
moveToEol: function(cm, head, motionArgs, vim, keepHPos) { moveToEol: function(cm, head, motionArgs, vim) {
var cur = head; return moveToEol(cm, head, motionArgs, vim, false);
var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity);
var end=cm.clipPos(retval);
end.ch--;
if (!keepHPos) {
vim.lastHPos = Infinity;
vim.lastHSPos = cm.charCoords(end,'div').left;
}
return retval;
}, },
moveToFirstNonWhiteSpaceCharacter: function(cm, head) { moveToFirstNonWhiteSpaceCharacter: function(cm, head) {
// Go to the start of the line where the text begins, or the end for // Go to the start of the line where the text begins, or the end for
@ -2049,6 +2146,8 @@
if (operatorArgs) { operatorArgs.linewise = true; } if (operatorArgs) { operatorArgs.linewise = true; }
tmp.end.line--; tmp.end.line--;
} }
} else if (character === 't') {
tmp = expandTagUnderCursor(cm, head, inclusive);
} else { } else {
// No text object defined for this, don't move. // No text object defined for this, don't move.
return null; return null;
@ -2098,9 +2197,9 @@
change: function(cm, args, ranges) { change: function(cm, args, ranges) {
var finalHead, text; var finalHead, text;
var vim = cm.state.vim; var vim = cm.state.vim;
var anchor = ranges[0].anchor,
head = ranges[0].head;
if (!vim.visualMode) { if (!vim.visualMode) {
var anchor = ranges[0].anchor,
head = ranges[0].head;
text = cm.getRange(anchor, head); text = cm.getRange(anchor, head);
var lastState = vim.lastEditInputState || {}; var lastState = vim.lastEditInputState || {};
if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) { if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) {
@ -2128,6 +2227,13 @@
anchor.ch = Number.MAX_VALUE; anchor.ch = Number.MAX_VALUE;
} }
finalHead = anchor; 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 { } else {
text = cm.getSelection(); text = cm.getSelection();
var replacement = fillArray('', ranges.length); var replacement = fillArray('', ranges.length);
@ -2172,8 +2278,7 @@
vimGlobalState.registerController.pushText( vimGlobalState.registerController.pushText(
args.registerName, 'delete', text, args.registerName, 'delete', text,
args.linewise, vim.visualBlock); args.linewise, vim.visualBlock);
var includeLineBreak = vim.insertMode return clipCursorToContent(cm, finalHead);
return clipCursorToContent(cm, finalHead, includeLineBreak);
}, },
indent: function(cm, args, ranges) { indent: function(cm, args, ranges) {
var vim = cm.state.vim; var vim = cm.state.vim;
@ -2355,6 +2460,8 @@
var height = cm.listSelections().length; var height = cm.listSelections().length;
if (insertAt == 'eol') { if (insertAt == 'eol') {
head = Pos(head.line, lineLength(cm, head.line)); head = Pos(head.line, lineLength(cm, head.line));
} else if (insertAt == 'bol') {
head = Pos(head.line, 0);
} else if (insertAt == 'charAfter') { } else if (insertAt == 'charAfter') {
head = offsetCursor(head, 0, 1); head = offsetCursor(head, 0, 1);
} else if (insertAt == 'firstNonBlank') { } else if (insertAt == 'firstNonBlank') {
@ -2393,6 +2500,8 @@
if (vim.visualMode){ if (vim.visualMode){
return; return;
} }
} else if (insertAt == 'lastEdit') {
head = getLastEditPos(cm) || head;
} }
cm.setOption('disableInput', false); cm.setOption('disableInput', false);
if (actionArgs && actionArgs.replace) { if (actionArgs && actionArgs.replace) {
@ -2428,8 +2537,7 @@
vim.visualLine = !!actionArgs.linewise; vim.visualLine = !!actionArgs.linewise;
vim.visualBlock = !!actionArgs.blockwise; vim.visualBlock = !!actionArgs.blockwise;
head = clipCursorToContent( head = clipCursorToContent(
cm, Pos(anchor.line, anchor.ch + repeat - 1), cm, Pos(anchor.line, anchor.ch + repeat - 1));
true /** includeLineBreak */);
vim.sel = { vim.sel = {
anchor: anchor, anchor: anchor,
head: head head: head
@ -2501,7 +2609,9 @@
var tmp = Pos(curStart.line + 1, var tmp = Pos(curStart.line + 1,
lineLength(cm, curStart.line + 1)); lineLength(cm, curStart.line + 1));
var text = cm.getRange(curStart, tmp); 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); cm.replaceRange(text, curStart, tmp);
} }
var curFinalPos = Pos(curStart.line, finalCh); var curFinalPos = Pos(curStart.line, finalCh);
@ -2803,10 +2913,11 @@
* Clips cursor to ensure that line is within the buffer's range * Clips cursor to ensure that line is within the buffer's range
* If includeLineBreak is true, then allow cur.ch == lineLength. * 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 line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() );
var maxCh = lineLength(cm, line) - 1; var maxCh = lineLength(cm, line) - 1 + !!includeLineBreak;
maxCh = (includeLineBreak) ? maxCh + 1 : maxCh;
var ch = Math.min(Math.max(0, cur.ch), maxCh); var ch = Math.min(Math.max(0, cur.ch), maxCh);
return Pos(line, ch); return Pos(line, ch);
} }
@ -3171,10 +3282,8 @@
vim.visualMode = false; vim.visualMode = false;
vim.visualLine = false; vim.visualLine = false;
vim.visualBlock = false; vim.visualBlock = false;
CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); if (!vim.insertMode) CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"});
if (vim.fakeCursor) { clearFakeCursor(vim);
vim.fakeCursor.clear();
}
} }
// Remove any trailing newlines from the selection. For // Remove any trailing newlines from the selection. For
@ -3265,6 +3374,49 @@
return { start: Pos(cur.line, start), end: Pos(cur.line, end) }; return { start: Pos(cur.line, start), end: Pos(cur.line, end) };
} }
/**
* Depends on the following:
*
* - editor mode should be htmlmixedmode / xml
* - mode/xml/xml.js should be loaded
* - addon/fold/xml-fold.js should be loaded
*
* If any of the above requirements are not true, this function noops.
*
* This is _NOT_ a 100% accurate implementation of vim tag text objects.
* The following caveats apply (based off cursory testing, I'm sure there
* are other discrepancies):
*
* - Does not work inside comments:
* ```
* <!-- <div>broken</div> -->
* ```
* - Does not work when tags have different cases:
* ```
* <div>broken</DIV>
* ```
* - Does not work when cursor is inside a broken tag:
* ```
* <div><brok><en></div>
* ```
*/
function expandTagUnderCursor(cm, head, inclusive) {
var cur = head;
if (!CodeMirror.findMatchingTag || !CodeMirror.findEnclosingTag) {
return { start: cur, end: cur };
}
var tags = CodeMirror.findMatchingTag(cm, head) || CodeMirror.findEnclosingTag(cm, head);
if (!tags || !tags.open || !tags.close) {
return { start: cur, end: cur };
}
if (inclusive) {
return { start: tags.open.from, end: tags.close.to };
}
return { start: tags.open.to, end: tags.close.from };
}
function recordJumpPosition(cm, oldCur, newCur) { function recordJumpPosition(cm, oldCur, newCur) {
if (!cursorEqual(oldCur, newCur)) { if (!cursorEqual(oldCur, newCur)) {
vimGlobalState.jumpList.add(cm, oldCur, newCur); vimGlobalState.jumpList.add(cm, oldCur, newCur);
@ -3532,6 +3684,18 @@
} }
} }
function moveToEol(cm, head, motionArgs, vim, keepHPos) {
var cur = head;
var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity);
var end=cm.clipPos(retval);
end.ch--;
if (!keepHPos) {
vim.lastHPos = Infinity;
vim.lastHSPos = cm.charCoords(end,'div').left;
}
return retval;
}
function moveToCharacter(cm, repeat, forward, character) { function moveToCharacter(cm, repeat, forward, character) {
var cur = cm.getCursor(); var cur = cm.getCursor();
var start = cur.ch; var start = cur.ch;
@ -3806,7 +3970,7 @@
return Pos(curr_index.ln, curr_index.pos); return Pos(curr_index.ln, curr_index.pos);
} }
// TODO: perhaps this finagling of start and end positions belonds // TODO: perhaps this finagling of start and end positions belongs
// in codemirror/replaceRange? // in codemirror/replaceRange?
function selectCompanionObject(cm, head, symb, inclusive) { function selectCompanionObject(cm, head, symb, inclusive) {
var cur = head, start, end; var cur = head, start, end;
@ -4152,7 +4316,8 @@
} }
function makePrompt(prefix, desc) { function makePrompt(prefix, desc) {
var raw = '<span style="font-family: monospace; white-space: pre">' + var raw = '<span style="font-family: monospace; white-space: pre">' +
(prefix || "") + '<input type="text"></span>'; (prefix || "") + '<input type="text" autocorrect="off" ' +
'autocapitalize="off" spellcheck="false"></span>';
if (desc) if (desc)
raw += ' <span style="color: #888">' + desc + '</span>'; raw += ' <span style="color: #888">' + desc + '</span>';
return raw; return raw;
@ -4272,6 +4437,42 @@
return cursor.from(); return cursor.from();
}); });
} }
/**
* Pretty much the same as `findNext`, except for the following differences:
*
* 1. Before starting the search, move to the previous search. This way if our cursor is
* already inside a match, we should return the current match.
* 2. Rather than only returning the cursor's from, we return the cursor's from and to as a tuple.
*/
function findNextFromAndToInclusive(cm, prev, query, repeat, vim) {
if (repeat === undefined) { repeat = 1; }
return cm.operation(function() {
var pos = cm.getCursor();
var cursor = cm.getSearchCursor(query, pos);
// Go back one result to ensure that if the cursor is currently a match, we keep it.
var found = cursor.find(!prev);
// If we haven't moved, go back one more (similar to if i==0 logic in findNext).
if (!vim.visualMode && found && cursorEqual(cursor.from(), pos)) {
cursor.find(!prev);
}
for (var i = 0; i < repeat; i++) {
found = cursor.find(prev);
if (!found) {
// SearchCursor may have returned null because it hit EOF, wrap
// around and try again.
cursor = cm.getSearchCursor(query,
(prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) );
if (!cursor.find(prev)) {
return;
}
}
}
return [cursor.from(), cursor.to()];
});
}
function clearSearchHighlight(cm) { function clearSearchHighlight(cm) {
var state = getSearchState(cm); var state = getSearchState(cm);
cm.removeOverlay(getSearchState(cm).getOverlay()); cm.removeOverlay(getSearchState(cm).getOverlay());
@ -4318,25 +4519,25 @@
} }
function getMarkPos(cm, vim, markName) { function getMarkPos(cm, vim, markName) {
if (markName == '\'') { if (markName == '\'' || markName == '`') {
var history = cm.doc.history.done; return vimGlobalState.jumpList.find(cm, -1) || Pos(0, 0);
var event = history[history.length - 2];
return event && event.ranges && event.ranges[0].head;
} else if (markName == '.') { } else if (markName == '.') {
if (cm.doc.history.lastModTime == 0) { return getLastEditPos(cm);
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;
} }
var mark = vim.marks[markName]; var mark = vim.marks[markName];
return mark && mark.find(); 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() { var ExCommandDispatcher = function() {
this.buildCommandMap_(); this.buildCommandMap_();
}; };
@ -4425,7 +4626,7 @@
} }
// Parse command name. // Parse command name.
var commandMatch = inputStream.match(/^(\w+)/); var commandMatch = inputStream.match(/^(\w+|!!|@@|[!#&*<=>@~])/);
if (commandMatch) { if (commandMatch) {
result.commandName = commandMatch[1]; result.commandName = commandMatch[1];
} else { } else {
@ -5323,14 +5524,34 @@
updateFakeCursor(cm); updateFakeCursor(cm);
} }
} }
/**
* Keeps track of a fake cursor to support visual mode cursor behavior.
*/
function updateFakeCursor(cm) { function updateFakeCursor(cm) {
var className = 'cm-animate-fat-cursor';
var vim = cm.state.vim; var vim = cm.state.vim;
var from = clipCursorToContent(cm, copyCursor(vim.sel.head)); var from = clipCursorToContent(cm, copyCursor(vim.sel.head));
var to = offsetCursor(from, 0, 1); 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) { if (vim.fakeCursor) {
vim.fakeCursor.clear(); 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) { function handleExternalSelection(cm, vim) {
var anchor = cm.getCursor('anchor'); var anchor = cm.getCursor('anchor');

View File

@ -13,7 +13,8 @@
.CodeMirror-lines { .CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */ 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 */ padding: 0 4px; /* Horizontal padding of content */
} }
@ -96,7 +97,7 @@
.CodeMirror-rulers { .CodeMirror-rulers {
position: absolute; position: absolute;
left: 0; right: 0; top: -50px; bottom: -20px; left: 0; right: 0; top: -50px; bottom: 0;
overflow: hidden; overflow: hidden;
} }
.CodeMirror-ruler { .CodeMirror-ruler {
@ -163,17 +164,17 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
.CodeMirror-scroll { .CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */ 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 */ /* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px; margin-bottom: -50px; margin-right: -50px;
padding-bottom: 30px; padding-bottom: 50px;
height: 100%; height: 100%;
outline: none; /* Prevent dragging from highlighting the element */ outline: none; /* Prevent dragging from highlighting the element */
position: relative; position: relative;
} }
.CodeMirror-sizer { .CodeMirror-sizer {
position: relative; position: relative;
border-right: 30px solid transparent; border-right: 50px solid transparent;
} }
/* The fake, visible scrollbars. Used to force redraw during scrolling /* The fake, visible scrollbars. Used to force redraw during scrolling
@ -183,6 +184,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
position: absolute; position: absolute;
z-index: 6; z-index: 6;
display: none; display: none;
outline: none;
} }
.CodeMirror-vscrollbar { .CodeMirror-vscrollbar {
right: 0; top: 0; right: 0; top: 0;
@ -211,7 +213,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
height: 100%; height: 100%;
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
margin-bottom: -30px; margin-bottom: -50px;
} }
.CodeMirror-gutter-wrapper { .CodeMirror-gutter-wrapper {
position: absolute; position: absolute;
@ -236,7 +238,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
cursor: text; cursor: text;
min-height: 1px; /* prevents collapsing before first draw */ 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 */ /* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0; border-width: 0;
@ -255,7 +258,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
-webkit-font-variant-ligatures: contextual; -webkit-font-variant-ligatures: contextual;
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; word-wrap: break-word;
white-space: pre-wrap; white-space: pre-wrap;
word-break: normal; word-break: normal;

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -9,7 +9,7 @@
<script src="asciiarmor.js"></script> <script src="asciiarmor.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -16,7 +16,7 @@
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1> <a href="https://codemirror.net"><h1>CodeMirror</h1>
<img id=logo src="../../doc/logo.png"> <img id=logo src="../../doc/logo.png" alt="">
</a> </a>
<ul> <ul>

View File

@ -9,7 +9,7 @@
* Description: CodeMirror mode for Asterisk dialplan * Description: CodeMirror mode for Asterisk dialplan
* *
* Created: 05/17/2012 09:20:25 PM * Created: 05/17/2012 09:20:25 PM
* Revision: none * Revision: 08/05/2019 AstLinux Project: Support block-comments
* *
* Author: Stas Kobzar (stas@modulis.ca), * Author: Stas Kobzar (stas@modulis.ca),
* Company: Modulis.ca Inc. * Company: Modulis.ca Inc.
@ -67,7 +67,26 @@ CodeMirror.defineMode("asterisk", function() {
var cur = ''; var cur = '';
var ch = stream.next(); var ch = stream.next();
// comment // comment
if (state.blockComment) {
if (ch == "-" && stream.match("-;", true)) {
state.blockComment = false;
} else if (stream.skipTo("--;")) {
stream.next();
stream.next();
stream.next();
state.blockComment = false;
} else {
stream.skipToEnd();
}
return "comment";
}
if(ch == ";") { if(ch == ";") {
if (stream.match("--", true)) {
if (!stream.match("-", false)) { // Except ;--- is not a block comment
state.blockComment = true;
return "comment";
}
}
stream.skipToEnd(); stream.skipToEnd();
return "comment"; return "comment";
} }
@ -124,6 +143,7 @@ CodeMirror.defineMode("asterisk", function() {
return { return {
startState: function() { startState: function() {
return { return {
blockComment: false,
extenStart: false, extenStart: false,
extenSame: false, extenSame: false,
extenInclude: false, extenInclude: false,
@ -187,7 +207,11 @@ CodeMirror.defineMode("asterisk", function() {
} }
return null; return null;
} },
blockCommentStart: ";--",
blockCommentEnd: "--;",
lineComment: ";"
}; };
}); });

View File

@ -13,7 +13,7 @@
.cm-s-default span.cm-arrow { color: red; } .cm-s-default span.cm-arrow { color: red; }
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

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

View File

@ -270,6 +270,25 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
"static else struct switch extern typedef union for goto while enum const " + "static else struct switch extern typedef union for goto while enum const " +
"volatile inline restrict asm fortran"; "volatile inline restrict asm fortran";
// Keywords from https://en.cppreference.com/w/cpp/keyword includes C++20.
var cppKeywords = "alignas alignof and and_eq audit axiom bitand bitor catch " +
"class compl concept constexpr const_cast decltype delete dynamic_cast " +
"explicit export final friend import module mutable namespace new noexcept " +
"not not_eq operator or or_eq override private protected public " +
"reinterpret_cast requires static_assert static_cast template this " +
"thread_local throw try typeid typename using virtual xor xor_eq";
var objCKeywords = "bycopy byref in inout oneway out self super atomic nonatomic retain copy " +
"readwrite readonly strong weak assign typeof nullable nonnull null_resettable _cmd " +
"@interface @implementation @end @protocol @encode @property @synthesize @dynamic @class " +
"@public @package @private @protected @required @optional @try @catch @finally @import " +
"@selector @encode @defs @synchronized @autoreleasepool @compatibility_alias @available";
var objCBuiltins = "FOUNDATION_EXPORT FOUNDATION_EXTERN NS_INLINE NS_FORMAT_FUNCTION " +
" NS_RETURNS_RETAINEDNS_ERROR_ENUM NS_RETURNS_NOT_RETAINED NS_RETURNS_INNER_POINTER " +
"NS_DESIGNATED_INITIALIZER NS_ENUM NS_OPTIONS NS_REQUIRES_NIL_TERMINATION " +
"NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_SWIFT_NAME NS_REFINED_FOR_SWIFT"
// Do not use this. Use the cTypes function below. This is global just to avoid // Do not use this. Use the cTypes function below. This is global just to avoid
// excessive calls when cTypes is being called multiple times during a parse. // excessive calls when cTypes is being called multiple times during a parse.
var basicCTypes = words("int long char short double float unsigned signed " + var basicCTypes = words("int long char short double float unsigned signed " +
@ -420,13 +439,7 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
def(["text/x-c++src", "text/x-c++hdr"], { def(["text/x-c++src", "text/x-c++hdr"], {
name: "clike", name: "clike",
// Keywords from https://en.cppreference.com/w/cpp/keyword includes C++20. keywords: words(cKeywords + " " + cppKeywords),
keywords: words(cKeywords + "alignas alignof and and_eq audit axiom bitand bitor catch " +
"class compl concept constexpr const_cast decltype delete dynamic_cast " +
"explicit export final friend import module mutable namespace new noexcept " +
"not not_eq operator or or_eq override private protected public " +
"reinterpret_cast requires static_assert static_cast template this " +
"thread_local throw try typeid typename using virtual xor xor_eq"),
types: cTypes, types: cTypes,
blockKeywords: words(cBlockKeywords + " class try catch"), blockKeywords: words(cBlockKeywords + " class try catch"),
defKeywords: words(cDefKeywords + " class namespace"), defKeywords: words(cDefKeywords + " class namespace"),
@ -676,11 +689,16 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
state.tokenize = tokenKotlinString(stream.match('""')); state.tokenize = tokenKotlinString(stream.match('""'));
return state.tokenize(stream, state); return state.tokenize(stream, state);
}, },
"/": function(stream, state) {
if (!stream.eat("*")) return false;
state.tokenize = tokenNestedComment(1);
return state.tokenize(stream, state)
},
indent: function(state, ctx, textAfter, indentUnit) { indent: function(state, ctx, textAfter, indentUnit) {
var firstChar = textAfter && textAfter.charAt(0); var firstChar = textAfter && textAfter.charAt(0);
if ((state.prevToken == "}" || state.prevToken == ")") && textAfter == "") if ((state.prevToken == "}" || state.prevToken == ")") && textAfter == "")
return state.indented; return state.indented;
if (state.prevToken == "operator" && textAfter != "}" || if ((state.prevToken == "operator" && textAfter != "}" && state.context.type != "}") ||
state.prevToken == "variable" && firstChar == "." || state.prevToken == "variable" && firstChar == "." ||
(state.prevToken == "}" || state.prevToken == ")") && firstChar == ".") (state.prevToken == "}" || state.prevToken == ")") && firstChar == ".")
return indentUnit * 2 + ctx.indented; return indentUnit * 2 + ctx.indented;
@ -764,16 +782,9 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
def("text/x-objectivec", { def("text/x-objectivec", {
name: "clike", name: "clike",
keywords: words(cKeywords + " bycopy byref in inout oneway out self super atomic nonatomic retain copy " + keywords: words(cKeywords + " " + objCKeywords),
"readwrite readonly strong weak assign typeof nullable nonnull null_resettable _cmd " +
"@interface @implementation @end @protocol @encode @property @synthesize @dynamic @class " +
"@public @package @private @protected @required @optional @try @catch @finally @import " +
"@selector @encode @defs @synchronized @autoreleasepool @compatibility_alias @available"),
types: objCTypes, types: objCTypes,
builtin: words("FOUNDATION_EXPORT FOUNDATION_EXTERN NS_INLINE NS_FORMAT_FUNCTION NS_RETURNS_RETAINED " + builtin: words(objCBuiltins),
"NS_ERROR_ENUM NS_RETURNS_NOT_RETAINED NS_RETURNS_INNER_POINTER NS_DESIGNATED_INITIALIZER " +
"NS_ENUM NS_OPTIONS NS_REQUIRES_NIL_TERMINATION NS_ASSUME_NONNULL_BEGIN " +
"NS_ASSUME_NONNULL_END NS_SWIFT_NAME NS_REFINED_FOR_SWIFT"),
blockKeywords: words(cBlockKeywords + " @synthesize @try @catch @finally @autoreleasepool @synchronized"), blockKeywords: words(cBlockKeywords + " @synthesize @try @catch @finally @autoreleasepool @synchronized"),
defKeywords: words(cDefKeywords + " @interface @implementation @protocol @class"), defKeywords: words(cDefKeywords + " @interface @implementation @protocol @class"),
dontIndentStatements: /^@.*$/, dontIndentStatements: /^@.*$/,
@ -787,6 +798,46 @@ CodeMirror.defineMode("clike", function(config, parserConfig) {
modeProps: {fold: ["brace", "include"]} modeProps: {fold: ["brace", "include"]}
}); });
def("text/x-objectivec++", {
name: "clike",
keywords: words(cKeywords + " " + objCKeywords + " " + cppKeywords),
types: objCTypes,
builtin: words(objCBuiltins),
blockKeywords: words(cBlockKeywords + " @synthesize @try @catch @finally @autoreleasepool @synchronized class try catch"),
defKeywords: words(cDefKeywords + " @interface @implementation @protocol @class class namespace"),
dontIndentStatements: /^@.*$|^template$/,
typeFirstDefinitions: true,
atoms: words("YES NO NULL Nil nil true false nullptr"),
isReservedIdentifier: cIsReservedIdentifier,
hooks: {
"#": cppHook,
"*": pointerHook,
"u": cpp11StringHook,
"U": cpp11StringHook,
"L": cpp11StringHook,
"R": cpp11StringHook,
"0": cpp14Literal,
"1": cpp14Literal,
"2": cpp14Literal,
"3": cpp14Literal,
"4": cpp14Literal,
"5": cpp14Literal,
"6": cpp14Literal,
"7": cpp14Literal,
"8": cpp14Literal,
"9": cpp14Literal,
token: function(stream, state, style) {
if (style == "variable" && stream.peek() == "(" &&
(state.prevToken == ";" || state.prevToken == null ||
state.prevToken == "}") &&
cppLooksLikeConstructor(stream.current()))
return "def";
}
},
namespaceSeparator: "::",
modeProps: {fold: ["brace", "include"]}
});
def("text/x-squirrel", { def("text/x-squirrel", {
name: "clike", name: "clike",
keywords: words("base break clone continue const default delete enum extends function in class" + keywords: words("base break clone continue const default delete enum extends function in class" +

View File

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

View File

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

View File

@ -11,7 +11,7 @@
<script src="clojure.js"></script> <script src="clojure.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -13,7 +13,7 @@
.cm-s-default span.cm-arrow { color: red; } .cm-s-default span.cm-arrow { color: red; }
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -39,7 +39,7 @@
.CodeMirror-activeline-background {background: #555555 !important;} .CodeMirror-activeline-background {background: #555555 !important;}
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="coffeescript.js"></script> <script src="coffeescript.js"></script>
<style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style> <style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="commonlisp.js"></script> <script src="commonlisp.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -14,7 +14,7 @@
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -442,117 +442,149 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"monochrome", "min-monochrome", "max-monochrome", "resolution", "monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid", "orientation", "min-resolution", "max-resolution", "scan", "grid", "orientation",
"device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio", "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
"pointer", "any-pointer", "hover", "any-hover" "pointer", "any-pointer", "hover", "any-hover", "prefers-color-scheme"
], mediaFeatures = keySet(mediaFeatures_); ], mediaFeatures = keySet(mediaFeatures_);
var mediaValueKeywords_ = [ var mediaValueKeywords_ = [
"landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover", "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
"interlace", "progressive" "interlace", "progressive",
"dark", "light"
], mediaValueKeywords = keySet(mediaValueKeywords_); ], mediaValueKeywords = keySet(mediaValueKeywords_);
var propertyKeywords_ = [ var propertyKeywords_ = [
"align-content", "align-items", "align-self", "alignment-adjust", "align-content", "align-items", "align-self", "alignment-adjust",
"alignment-baseline", "anchor-point", "animation", "animation-delay", "alignment-baseline", "all", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-fill-mode", "animation-direction", "animation-duration", "animation-fill-mode",
"animation-iteration-count", "animation-name", "animation-play-state", "animation-iteration-count", "animation-name", "animation-play-state",
"animation-timing-function", "appearance", "azimuth", "backface-visibility", "animation-timing-function", "appearance", "azimuth", "backdrop-filter",
"background", "background-attachment", "background-blend-mode", "background-clip", "backface-visibility", "background", "background-attachment",
"background-color", "background-image", "background-origin", "background-position", "background-blend-mode", "background-clip", "background-color",
"background-repeat", "background-size", "baseline-shift", "binding", "background-image", "background-origin", "background-position",
"bleed", "bookmark-label", "bookmark-level", "bookmark-state", "background-position-x", "background-position-y", "background-repeat",
"bookmark-target", "border", "border-bottom", "border-bottom-color", "background-size", "baseline-shift", "binding", "bleed", "block-size",
"border-bottom-left-radius", "border-bottom-right-radius", "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target",
"border-bottom-style", "border-bottom-width", "border-collapse", "border", "border-bottom", "border-bottom-color", "border-bottom-left-radius",
"border-color", "border-image", "border-image-outset", "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-repeat", "border-image-slice", "border-image-source",
"border-image-width", "border-left", "border-left-color", "border-image-width", "border-left", "border-left-color", "border-left-style",
"border-left-style", "border-left-width", "border-radius", "border-right", "border-left-width", "border-radius", "border-right", "border-right-color",
"border-right-color", "border-right-style", "border-right-width", "border-right-style", "border-right-width", "border-spacing", "border-style",
"border-spacing", "border-style", "border-top", "border-top-color", "border-top", "border-top-color", "border-top-left-radius",
"border-top-left-radius", "border-top-right-radius", "border-top-style", "border-top-right-radius", "border-top-style", "border-top-width",
"border-top-width", "border-width", "bottom", "box-decoration-break", "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing",
"box-shadow", "box-sizing", "break-after", "break-before", "break-inside", "break-after", "break-before", "break-inside", "caption-side", "caret-color",
"caption-side", "caret-color", "clear", "clip", "color", "color-profile", "column-count", "clear", "clip", "color", "color-profile", "column-count", "column-fill",
"column-fill", "column-gap", "column-rule", "column-rule-color", "column-gap", "column-rule", "column-rule-color", "column-rule-style",
"column-rule-style", "column-rule-width", "column-span", "column-width", "column-rule-width", "column-span", "column-width", "columns", "contain",
"columns", "content", "counter-increment", "counter-reset", "crop", "cue", "content", "counter-increment", "counter-reset", "crop", "cue", "cue-after",
"cue-after", "cue-before", "cursor", "direction", "display", "cue-before", "cursor", "direction", "display", "dominant-baseline",
"dominant-baseline", "drop-initial-after-adjust", "drop-initial-after-adjust", "drop-initial-after-align",
"drop-initial-after-align", "drop-initial-before-adjust", "drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size",
"drop-initial-before-align", "drop-initial-size", "drop-initial-value", "drop-initial-value", "elevation", "empty-cells", "fit", "fit-position",
"elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", "flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow",
"flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", "flex-shrink", "flex-wrap", "float", "float-offset", "flow-from", "flow-into",
"float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings", "font", "font-family", "font-feature-settings", "font-kerning",
"font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", "font-language-override", "font-optical-sizing", "font-size",
"font-stretch", "font-style", "font-synthesis", "font-variant", "font-size-adjust", "font-stretch", "font-style", "font-synthesis",
"font-variant-alternates", "font-variant-caps", "font-variant-east-asian", "font-variant", "font-variant-alternates", "font-variant-caps",
"font-variant-ligatures", "font-variant-numeric", "font-variant-position", "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric",
"font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", "font-variant-position", "font-variation-settings", "font-weight", "gap",
"grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", "grid-auto-rows",
"grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", "grid-column", "grid-column-end", "grid-column-gap", "grid-column-start",
"grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", "grid-row-start",
"grid-template-rows", "hanging-punctuation", "height", "hyphens", "grid-template", "grid-template-areas", "grid-template-columns",
"icon", "image-orientation", "image-rendering", "image-resolution", "grid-template-rows", "hanging-punctuation", "height", "hyphens", "icon",
"inline-box-align", "justify-content", "justify-items", "justify-self", "left", "letter-spacing", "image-orientation", "image-rendering", "image-resolution", "inline-box-align",
"line-break", "line-height", "line-stacking", "line-stacking-ruby", "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", "line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin", "list-style-image", "list-style-position", "list-style-type", "margin",
"margin-bottom", "margin-left", "margin-right", "margin-top", "margin-bottom", "margin-left", "margin-right", "margin-top", "marks",
"marks", "marquee-direction", "marquee-loop", "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed",
"marquee-play-count", "marquee-speed", "marquee-style", "max-height", "marquee-style", "mask-clip", "mask-composite", "mask-image", "mask-mode",
"max-width", "min-height", "min-width", "mix-blend-mode", "move-to", "nav-down", "nav-index", "mask-origin", "mask-position", "mask-repeat", "mask-size","mask-type",
"nav-left", "nav-right", "nav-up", "object-fit", "object-position", "max-block-size", "max-height", "max-inline-size",
"opacity", "order", "orphans", "outline", "max-width", "min-block-size", "min-height", "min-inline-size", "min-width",
"outline-color", "outline-offset", "outline-style", "outline-width", "mix-blend-mode", "move-to", "nav-down", "nav-index", "nav-left", "nav-right",
"overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", "nav-up", "object-fit", "object-position", "offset", "offset-anchor",
"padding", "padding-bottom", "padding-left", "padding-right", "padding-top", "offset-distance", "offset-path", "offset-position", "offset-rotate",
"page", "page-break-after", "page-break-before", "page-break-inside", "opacity", "order", "orphans", "outline", "outline-color", "outline-offset",
"page-policy", "pause", "pause-after", "pause-before", "perspective", "outline-style", "outline-width", "overflow", "overflow-style",
"perspective-origin", "pitch", "pitch-range", "place-content", "place-items", "place-self", "play-during", "position", "overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom",
"presentation-level", "punctuation-trim", "quotes", "region-break-after", "padding-left", "padding-right", "padding-top", "page", "page-break-after",
"region-break-before", "region-break-inside", "region-fragment", "page-break-before", "page-break-inside", "page-policy", "pause",
"rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", "pause-after", "pause-before", "perspective", "perspective-origin", "pitch",
"right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", "pitch-range", "place-content", "place-items", "place-self", "play-during",
"ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin", "position", "presentation-level", "punctuation-trim", "quotes",
"shape-outside", "size", "speak", "speak-as", "speak-header", "region-break-after", "region-break-before", "region-break-inside",
"speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", "region-fragment", "rendering-intent", "resize", "rest", "rest-after",
"tab-size", "table-layout", "target", "target-name", "target-new", "rest-before", "richness", "right", "rotate", "rotation", "rotation-point",
"target-position", "text-align", "text-align-last", "text-decoration", "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-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-style", "text-emphasis", "text-emphasis-color", "text-decoration-skip-ink", "text-decoration-style", "text-emphasis",
"text-emphasis-position", "text-emphasis-style", "text-height", "text-emphasis-color", "text-emphasis-position", "text-emphasis-style",
"text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow", "text-height", "text-indent", "text-justify", "text-orientation",
"text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position", "text-outline", "text-overflow", "text-rendering", "text-shadow",
"text-wrap", "top", "transform", "transform-origin", "transform-style", "text-size-adjust", "text-space-collapse", "text-transform",
"transition", "transition-delay", "transition-duration", "text-underline-position", "text-wrap", "top", "touch-action", "transform", "transform-origin",
"transition-property", "transition-timing-function", "unicode-bidi", "transform-style", "transition", "transition-delay", "transition-duration",
"user-select", "vertical-align", "visibility", "voice-balance", "voice-duration", "transition-property", "transition-timing-function", "translate",
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", "unicode-bidi", "user-select", "vertical-align", "visibility", "voice-balance",
"voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break", "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate",
"word-spacing", "word-wrap", "z-index", "voice-stress", "voice-volume", "volume", "white-space", "widows", "width",
"will-change", "word-break", "word-spacing", "word-wrap", "writing-mode", "z-index",
// SVG-specific // SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters", "color-interpolation", "color-interpolation-filters",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering", "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
"marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", "marker", "marker-end", "marker-mid", "marker-start", "paint-order", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
"glyph-orientation-vertical", "text-anchor", "writing-mode" "glyph-orientation-vertical", "text-anchor", "writing-mode",
], propertyKeywords = keySet(propertyKeywords_); ], propertyKeywords = keySet(propertyKeywords_);
var nonStandardPropertyKeywords_ = [ 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-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color", "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
"scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside", "scrollbar-track-color", "searchfield-cancel-button", "searchfield-decoration",
"searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", "searchfield-results-button", "searchfield-results-decoration", "shape-inside", "zoom"
"searchfield-results-decoration", "zoom"
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_); ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
var fontProperties_ = [ var fontProperties_ = [
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings", "font-display", "font-family", "src", "unicode-range", "font-variant",
"font-stretch", "font-weight", "font-style" "font-feature-settings", "font-stretch", "font-weight", "font-style"
], fontProperties = keySet(fontProperties_); ], fontProperties = keySet(fontProperties_);
var counterDescriptors_ = [ var counterDescriptors_ = [
@ -594,7 +626,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate", "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace", "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page", "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
"avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary", "avoid-region", "axis-pan", "background", "backwards", "baseline", "below", "bidi-override", "binary",
"bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
"both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel", "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
@ -618,7 +650,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
"ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed", "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes", "extra-expanded", "fantasy", "fast", "fill", "fill-box", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove", "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext", "help", "hidden", "hide", "higher", "highlight", "highlighttext",
@ -633,7 +665,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem", "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
"lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d", "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "manipulation", "match", "matrix", "matrix3d",
"media-controls-background", "media-current-time-display", "media-controls-background", "media-current-time-display",
"media-fullscreen-button", "media-mute-button", "media-play-button", "media-fullscreen-button", "media-mute-button", "media-play-button",
"media-return-to-realtime-button", "media-rewind-button", "media-return-to-realtime-button", "media-rewind-button",
@ -642,13 +674,13 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"media-volume-slider-container", "media-volume-sliderthumb", "medium", "media-volume-slider-container", "media-volume-sliderthumb", "medium",
"menu", "menulist", "menulist-button", "menulist-text", "menu", "menulist", "menulist-button", "menulist-text",
"menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
"mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize", "mix", "mongolian", "monospace", "move", "multiple", "multiple_mask_images", "multiply", "myanmar", "n-resize",
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote", "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset", "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box", "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
"painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter", "painted", "page", "paused", "persian", "perspective", "pinch-zoom", "plus-darker", "plus-lighter",
"pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
"progress", "push-button", "radial-gradient", "radio", "read-only", "progress", "push-button", "radial-gradient", "radio", "read-only",
"read-write", "read-write-plaintext-only", "rectangle", "region", "read-write", "read-write-plaintext-only", "rectangle", "region",
@ -666,8 +698,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali", "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square", "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "square-button", "start", "static", "status-bar", "stretch", "stroke", "stroke-box", "sub",
"subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table", "subpixel-antialiased", "svg_masks", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
"table-caption", "table-cell", "table-column", "table-column-group", "table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group", "table-footer-group", "table-header-group", "table-row", "table-row-group",
"tamil", "tamil",
@ -677,10 +709,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top", "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"trad-chinese-formal", "trad-chinese-informal", "transform", "trad-chinese-formal", "trad-chinese-informal", "transform",
"translate", "translate3d", "translateX", "translateY", "translateZ", "translate", "translate3d", "translateX", "translateY", "translateZ",
"transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up", "transparent", "ultra-condensed", "ultra-expanded", "underline", "unidirectional-pan", "unset", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal", "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", "var", "vertical", "vertical-text", "view-box", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider", "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
"window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor", "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
"xx-large", "xx-small" "xx-large", "xx-small"

View File

@ -13,7 +13,7 @@
<script src="../../addon/hint/css-hint.js"></script> <script src="../../addon/hint/css-hint.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -12,7 +12,7 @@
<script src="../../addon/hint/css-hint.js"></script> <script src="../../addon/hint/css-hint.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -10,7 +10,7 @@
<script src="css.js"></script> <script src="css.js"></script>
<style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style> <style>.CodeMirror {border: 1px solid #ddd; line-height: 1.2;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -10,7 +10,7 @@
<script src="css.js"></script> <script src="css.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -46,7 +46,7 @@
var word = stream.current(); var word = stream.current();
if (funcs.test(word)) return "builtin"; if (funcs.test(word)) return "builtin";
if (preds.test(word)) return "def"; if (preds.test(word)) return "def";
if (keywords.test(word)) return "keyword"; if (keywords.test(word) || systemKeywords.test(word)) return "keyword";
return "variable"; return "variable";
} }
}; };
@ -67,6 +67,7 @@
var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "reverse", "right", "round", "rtrim", "shortestPath", "sign", "sin", "size", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "toString", "trim", "type", "upper"]); var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "reverse", "right", "round", "rtrim", "shortestPath", "sign", "sin", "size", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "toString", "trim", "type", "upper"]);
var preds = wordRegexp(["all", "and", "any", "contains", "exists", "has", "in", "none", "not", "or", "single", "xor"]); var preds = wordRegexp(["all", "and", "any", "contains", "exists", "has", "in", "none", "not", "or", "single", "xor"]);
var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "detach", "distinct", "drop", "else", "end", "ends", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "starts", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with", "call", "yield"]); var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "detach", "distinct", "drop", "else", "end", "ends", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "starts", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with", "call", "yield"]);
var systemKeywords = wordRegexp(["access", "active", "assign", "all", "alter", "as", "catalog", "change", "copy", "create", "constraint", "constraints", "current", "database", "databases", "dbms", "default", "deny", "drop", "element", "elements", "exists", "from", "grant", "graph", "graphs", "if", "index", "indexes", "label", "labels", "management", "match", "name", "names", "new", "node", "nodes", "not", "of", "on", "or", "password", "populated", "privileges", "property", "read", "relationship", "relationships", "remove", "replace", "required", "revoke", "role", "roles", "set", "show", "start", "status", "stop", "suspended", "to", "traverse", "type", "types", "user", "users", "with", "write"]);
var operatorChars = /[*+\-<>=&|~%^]/; var operatorChars = /[*+\-<>=&|~%^]/;
return { return {

View File

@ -16,7 +16,7 @@
} }
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

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

View File

@ -15,10 +15,10 @@
"implements mixin get native set typedef with enum throw rethrow " + "implements mixin get native set typedef with enum throw rethrow " +
"assert break case continue default in return new deferred async await covariant " + "assert break case continue default in return new deferred async await covariant " +
"try catch finally do else for if switch while import library export " + "try catch finally do else for if switch while import library export " +
"part of show hide is as").split(" "); "part of show hide is as extension on yield late required").split(" ");
var blockKeywords = "try catch finally do else for if switch while".split(" "); var blockKeywords = "try catch finally do else for if switch while".split(" ");
var atoms = "true false null".split(" "); var atoms = "true false null".split(" ");
var builtins = "void bool num int double dynamic var String".split(" "); var builtins = "void bool num int double dynamic var String Null Never".split(" ");
function set(words) { function set(words) {
var obj = {}; var obj = {};
@ -78,6 +78,15 @@
if (!stream.eat("*")) return false if (!stream.eat("*")) return false
state.tokenize = tokenNestedComment(1) state.tokenize = tokenNestedComment(1)
return state.tokenize(stream, state) return state.tokenize(stream, state)
},
token: function(stream, _, style) {
if (style == "variable") {
// Assume uppercase symbols are classes using variable-2
var isUpper = RegExp('^[_$]*[A-Z][a-zA-Z0-9_$]*$','g');
if (isUpper.test(stream.current())) {
return 'variable-2';
}
}
} }
} }
}); });

View File

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

View File

@ -15,7 +15,7 @@
span.cm-error.cm-tag { background-color: #2b2; } span.cm-error.cm-tag { background-color: #2b2; }
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -13,7 +13,7 @@
<script src="django.js"></script> <script src="django.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -10,7 +10,7 @@
<script src="dockerfile.js"></script> <script src="dockerfile.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="dtd.js"></script> <script src="dtd.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -12,7 +12,7 @@
<script src="dylan.js"></script> <script src="dylan.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -13,7 +13,7 @@
</head> </head>
<body> <body>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="ecl.js"></script> <script src="ecl.js"></script>
<style>.CodeMirror {border: 1px solid black;}</style> <style>.CodeMirror {border: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -13,7 +13,7 @@
.cm-s-default span.cm-arrow { color: red; } .cm-s-default span.cm-arrow { color: red; }
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others // CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE // Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) { (function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS if (typeof exports == "object" && typeof module == "object") // CommonJS
@ -13,189 +13,227 @@
CodeMirror.defineMode("elm", function() { CodeMirror.defineMode("elm", function() {
function switchState(source, setState, f) { function switchState(source, setState, f)
{
setState(f); setState(f);
return f(source, setState); return f(source, setState);
} }
// These should all be Unicode extended, as per the Haskell 2010 report var lowerRE = /[a-z]/;
var smallRE = /[a-z_]/; var upperRE = /[A-Z]/;
var largeRE = /[A-Z]/; var innerRE = /[a-zA-Z0-9_]/;
var digitRE = /[0-9]/; var digitRE = /[0-9]/;
var hexitRE = /[0-9A-Fa-f]/; var hexRE = /[0-9A-Fa-f]/;
var octitRE = /[0-7]/; var symbolRE = /[-&*+.\\/<>=?^|:]/;
var idRE = /[a-z_A-Z0-9\']/; var specialRE = /[(),[\]{}]/;
var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:\u03BB\u2192]/; var spacesRE = /[ \v\f]/; // newlines are handled in tokenizer
var specialRE = /[(),;[\]`{}]/;
var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
function normal() { function normal()
return function (source, setState) { {
if (source.eatWhile(whiteCharRE)) { return function(source, setState)
{
if (source.eatWhile(spacesRE))
{
return null; return null;
} }
var ch = source.next(); var char = source.next();
if (specialRE.test(ch)) {
if (ch == '{' && source.eat('-')) { if (specialRE.test(char))
var t = "comment"; {
if (source.eat('#')) t = "meta"; return (char === '{' && source.eat('-'))
return switchState(source, setState, ncomment(t, 1)); ? switchState(source, setState, chompMultiComment(1))
} : (char === '[' && source.match('glsl|'))
return null; ? switchState(source, setState, chompGlsl)
: 'builtin';
} }
if (ch == '\'') { if (char === '\'')
if (source.eat('\\')) {
source.next(); // should handle other escapes here return switchState(source, setState, chompChar);
else
source.next();
if (source.eat('\''))
return "string";
return "error";
} }
if (ch == '"') { if (char === '"')
return switchState(source, setState, stringLiteral); {
return source.eat('"')
? source.eat('"')
? switchState(source, setState, chompMultiString)
: 'string'
: switchState(source, setState, chompSingleString);
} }
if (largeRE.test(ch)) { if (upperRE.test(char))
source.eatWhile(idRE); {
if (source.eat('.')) source.eatWhile(innerRE);
return "qualifier"; return 'variable-2';
return "variable-2";
} }
if (smallRE.test(ch)) { if (lowerRE.test(char))
{
var isDef = source.pos === 1; var isDef = source.pos === 1;
source.eatWhile(idRE); source.eatWhile(innerRE);
return isDef ? "type" : "variable"; return isDef ? "def" : "variable";
} }
if (digitRE.test(ch)) { if (digitRE.test(char))
if (ch == '0') { {
if (source.eat(/[xX]/)) { if (char === '0')
source.eatWhile(hexitRE); // should require at least 1 {
return "integer"; if (source.eat(/[xX]/))
} {
if (source.eat(/[oO]/)) { source.eatWhile(hexRE); // should require at least 1
source.eatWhile(octitRE); // should require at least 1
return "number"; return "number";
} }
} }
source.eatWhile(digitRE); else
var t = "number"; {
if (source.eat('.')) { source.eatWhile(digitRE);
t = "number"; }
if (source.eat('.'))
{
source.eatWhile(digitRE); // should require at least 1 source.eatWhile(digitRE); // should require at least 1
} }
if (source.eat(/[eE]/)) { if (source.eat(/[eE]/))
t = "number"; {
source.eat(/[-+]/); source.eat(/[-+]/);
source.eatWhile(digitRE); // should require at least 1 source.eatWhile(digitRE); // should require at least 1
} }
return t; return "number";
} }
if (symbolRE.test(ch)) { if (symbolRE.test(char))
if (ch == '-' && source.eat(/-/)) { {
source.eatWhile(/-/); if (char === '-' && source.eat('-'))
if (!source.eat(symbolRE)) { {
source.skipToEnd(); source.skipToEnd();
return "comment"; return "comment";
}
} }
source.eatWhile(symbolRE); source.eatWhile(symbolRE);
return "builtin"; return "keyword";
}
if (char === '_')
{
return "keyword";
} }
return "error"; return "error";
} }
} }
function ncomment(type, nest) { function chompMultiComment(nest)
if (nest == 0) { {
if (nest == 0)
{
return normal(); return normal();
} }
return function(source, setState) { return function(source, setState)
var currNest = nest; {
while (!source.eol()) { while (!source.eol())
var ch = source.next(); {
if (ch == '{' && source.eat('-')) { var char = source.next();
++currNest; if (char == '{' && source.eat('-'))
} else if (ch == '-' && source.eat('}')) { {
--currNest; ++nest;
if (currNest == 0) { }
else if (char == '-' && source.eat('}'))
{
--nest;
if (nest === 0)
{
setState(normal()); setState(normal());
return type; return 'comment';
} }
} }
} }
setState(ncomment(type, currNest)); setState(chompMultiComment(nest));
return type; return 'comment';
} }
} }
function stringLiteral(source, setState) { function chompMultiString(source, setState)
while (!source.eol()) { {
var ch = source.next(); while (!source.eol())
if (ch == '"') { {
var char = source.next();
if (char === '"' && source.eat('"') && source.eat('"'))
{
setState(normal()); setState(normal());
return "string"; return 'string';
}
if (ch == '\\') {
if (source.eol() || source.eat(whiteCharRE)) {
setState(stringGap);
return "string";
}
if (!source.eat('&')) source.next(); // should handle other escapes here
} }
} }
setState(normal()); return 'string';
return "error";
} }
function stringGap(source, setState) { function chompSingleString(source, setState)
if (source.eat('\\')) { {
return switchState(source, setState, stringLiteral); while (source.skipTo('\\"')) { source.next(); source.next(); }
if (source.skipTo('"'))
{
source.next();
setState(normal());
return 'string';
} }
source.next(); source.skipToEnd();
setState(normal()); setState(normal());
return "error"; return 'error';
} }
function chompChar(source, setState)
{
while (source.skipTo("\\'")) { source.next(); source.next(); }
if (source.skipTo("'"))
{
source.next();
setState(normal());
return 'string';
}
source.skipToEnd();
setState(normal());
return 'error';
}
var wellKnownWords = (function() { function chompGlsl(source, setState)
var wkw = {}; {
while (!source.eol())
var keywords = [ {
"case", "of", "as", var char = source.next();
"if", "then", "else", if (char === '|' && source.eat(']'))
"let", "in", {
"infix", "infixl", "infixr", setState(normal());
"type", "alias", return 'string';
"input", "output", "foreign", "loopback", }
"module", "where", "import", "exposing", }
"_", "..", "|", ":", "=", "\\", "\"", "->", "<-" return 'string';
]; }
for (var i = keywords.length; i--;)
wkw[keywords[i]] = "keyword";
return wkw;
})();
var wellKnownWords = {
case: 1,
of: 1,
as: 1,
if: 1,
then: 1,
else: 1,
let: 1,
in: 1,
type: 1,
alias: 1,
module: 1,
where: 1,
import: 1,
exposing: 1,
port: 1
};
return { return {
startState: function () { return { f: normal() }; }, startState: function () { return { f: normal() }; },
copyState: function (s) { return { f: s.f }; }, copyState: function (s) { return { f: s.f }; },
token: function(stream, state) { token: function(stream, state) {
var t = state.f(stream, function(s) { state.f = s; }); var type = state.f(stream, function(s) { state.f = s; });
var w = stream.current(); var word = stream.current();
return (wellKnownWords.hasOwnProperty(w)) ? wellKnownWords[w] : t; return (wellKnownWords.hasOwnProperty(word)) ? 'keyword' : type;
} }
}; };

View File

@ -9,7 +9,7 @@
<script src="elm.js"></script> <script src="elm.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -11,7 +11,7 @@
<script src="erlang.js"></script> <script src="erlang.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -16,7 +16,7 @@
} }
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -11,7 +11,7 @@
<script src="fcl.js"></script> <script src="fcl.js"></script>
<style>.CodeMirror {border:1px solid #999; background:#ffc}</style> <style>.CodeMirror {border:1px solid #999; background:#ffc}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -16,7 +16,7 @@
} }
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="fortran.js"></script> <script src="fortran.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

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

View File

@ -20,7 +20,7 @@
.cm-s-default .cm-emoji {color: #009688;} .cm-s-default .cm-emoji {color: #009688;}
</style> </style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="gherkin.js"></script> <script src="gherkin.js"></script>
<style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style> <style>.CodeMirror { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; }</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -11,7 +11,7 @@
<script src="go.js"></script> <script src="go.js"></script>
<style>.CodeMirror {border:1px solid #999; background:#ffc}</style> <style>.CodeMirror {border:1px solid #999; background:#ffc}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -10,7 +10,7 @@
<script src="groovy.js"></script> <script src="groovy.js"></script>
<style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style> <style>.CodeMirror {border-top: 1px solid #500; border-bottom: 1px solid #500;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -13,7 +13,7 @@
<script src="haml.js"></script> <script src="haml.js"></script>
<style>.CodeMirror {background: #f8f8f8;}</style> <style>.CodeMirror {background: #f8f8f8;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -13,10 +13,14 @@
CodeMirror.defineSimpleMode("handlebars-tags", { CodeMirror.defineSimpleMode("handlebars-tags", {
start: [ start: [
{ regex: /\{\{\{/, push: "handlebars_raw", token: "tag" },
{ regex: /\{\{!--/, push: "dash_comment", token: "comment" }, { regex: /\{\{!--/, push: "dash_comment", token: "comment" },
{ regex: /\{\{!/, push: "comment", token: "comment" }, { regex: /\{\{!/, push: "comment", token: "comment" },
{ regex: /\{\{/, push: "handlebars", token: "tag" } { regex: /\{\{/, push: "handlebars", token: "tag" }
], ],
handlebars_raw: [
{ regex: /\}\}\}/, pop: true, token: "tag" },
],
handlebars: [ handlebars: [
{ regex: /\}\}/, pop: true, token: "tag" }, { regex: /\}\}/, pop: true, token: "tag" },
@ -58,7 +62,7 @@
if (!parserConfig || !parserConfig.base) return handlebars; if (!parserConfig || !parserConfig.base) return handlebars;
return CodeMirror.multiplexingMode( return CodeMirror.multiplexingMode(
CodeMirror.getMode(config, parserConfig.base), CodeMirror.getMode(config, parserConfig.base),
{open: "{{", close: "}}", mode: handlebars, parseDelimiters: true} {open: "{{", close: /\}\}\}?/, mode: handlebars, parseDelimiters: true}
); );
}); });

View File

@ -13,7 +13,7 @@
<script src="handlebars.js"></script> <script src="handlebars.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>
@ -41,6 +41,8 @@
{{! one line comment }} {{! one line comment }}
{{{propertyContainingRawHtml}}}
{{#each articles}} {{#each articles}}
{{~title}} {{~title}}
<p>{{excerpt body size=120 ellipsis=true}}</p> <p>{{excerpt body size=120 ellipsis=true}}</p>

View File

@ -11,7 +11,7 @@
<script src="haskell.js"></script> <script src="haskell.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="haxe.js"></script> <script src="haxe.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -14,7 +14,7 @@
<script src="htmlembedded.js"></script> <script src="htmlembedded.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -14,7 +14,7 @@
<script src="htmlmixed.js"></script> <script src="htmlmixed.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -9,7 +9,7 @@
<script src="http.js"></script> <script src="http.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -10,7 +10,7 @@
<script src="idl.js"></script> <script src="idl.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

View File

@ -12,7 +12,7 @@
<script src="javascript.js"></script> <script src="javascript.js"></script>
<style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style> <style>.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
<div id=nav> <div id=nav>
<a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a> <a href="https://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png" alt=""></a>
<ul> <ul>
<li><a href="../../index.html">Home</a> <li><a href="../../index.html">Home</a>

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