Commit 01c61e97 authored by Arnaud Fontaine's avatar Arnaud Fontaine

erp5_code_mirror: Update to 5.36.0 (2018-03-20) and disable Ctrl-V emacs shortcut.

0. Download codemirror tarball ('lib/codemirror.js' is not available in git repository anymore):
   wget http://codemirror.net/codemirror.zip && unzip codemirror.zip

1. Prepare files to upload:
   cd UNZIPPED_CODEMIRROR_DIRECTORY/
   rm -r bin/ doc/ index.html demo/ src/ test/ rollup.config.js package.json mode/*/index.html mode/index.html .[a-z]*
   # 54087b03
   mv addon/edit/ addon/cm_edit/ && find -type f | xargs sed -i 's#addon/edit/#addon/cm_edit/#g'
   # https://github.com/codemirror/CodeMirror/issues/5321
   sed -i '/"Ctrl-V"/d' keymap/emacs.js

2. Edit zope.conf to enable FTP access:
   <ftp-server>
    address localhost:2202
   </ftp-server>

3. Upload files to Zope:
   yafc ftp://zope:zope@localhost:2202/erp5/portal_skins/erp5_code_mirror/codemirror/
   yafc> rm -r *
   yafc> put -r *

4. Run portal_alarms/Alarm_checkSkinCacheActive?fixit:int=1
parent 8f70571d
List of CodeMirror contributors. Updated before every release. List of CodeMirror contributors. Updated before every release.
4oo4
4r2r 4r2r
Aaron Brooks Aaron Brooks
Abdelouahab Abdelouahab
Abe Fettig Abe Fettig
Adam Ahmed Adam Ahmed
Adam King Adam King
Adam Particka
adanlobato adanlobato
Adán Lobato Adán Lobato
Adrian Aichner Adrian Aichner
...@@ -29,6 +31,7 @@ alexey-k ...@@ -29,6 +31,7 @@ alexey-k
Alex Piggott Alex Piggott
Aliaksei Chapyzhenka Aliaksei Chapyzhenka
Allen Sarkisyan Allen Sarkisyan
Ami Fischman
Amin Shali Amin Shali
Amin Ullah Khan Amin Ullah Khan
amshali@google.com amshali@google.com
...@@ -46,6 +49,7 @@ Andreas Reischuck ...@@ -46,6 +49,7 @@ Andreas Reischuck
Andres Taylor Andres Taylor
Andre von Houck Andre von Houck
Andrew Cheng Andrew Cheng
Andrew Dassonville
Andrey Fedorov Andrey Fedorov
Andrey Klyuchnikov Andrey Klyuchnikov
Andrey Lushnikov Andrey Lushnikov
...@@ -66,14 +70,19 @@ Anthony Grimes ...@@ -66,14 +70,19 @@ Anthony Grimes
Anton Kovalyov Anton Kovalyov
Apollo Zhu Apollo Zhu
AQNOUCH Mohammed AQNOUCH Mohammed
Aram Shatakhtsyan
areos areos
Arnab Bose Arnab Bose
Arsène von Wyss
Arthur Müller Arthur Müller
Arun Narasani
as3boyan as3boyan
asolove
atelierbram atelierbram
AtomicPages LLC AtomicPages LLC
Atul Bhouraskar Atul Bhouraskar
Aurelian Oancea Aurelian Oancea
Axel Lewenhaupt
Barret Rennie Barret Rennie
Basarat Ali Syed Basarat Ali Syed
Bastian Müller Bastian Müller
...@@ -82,6 +91,7 @@ Bem Jones-Bey ...@@ -82,6 +91,7 @@ Bem Jones-Bey
benbro benbro
Beni Cherniavsky-Paskin Beni Cherniavsky-Paskin
Benjamin DeCoste Benjamin DeCoste
Benjamin Young
Ben Keen Ben Keen
Ben Miller Ben Miller
Ben Mosher Ben Mosher
...@@ -99,15 +109,19 @@ borawjm ...@@ -99,15 +109,19 @@ borawjm
Brad Metcalf Brad Metcalf
Brandon Frohs Brandon Frohs
Brandon Wamboldt Brandon Wamboldt
Bret Little
Brett Zamir Brett Zamir
Brian Grinstead Brian Grinstead
Brian Sletten Brian Sletten
brrd
Bruce Mitchener Bruce Mitchener
Bryan Massoth Bryan Massoth
Caitlin Potter Caitlin Potter
Calin Barbat Calin Barbat
callodacity callodacity
Camilo Roca Camilo Roca
Casey Klebba
César González Íñiguez
Chad Jolly Chad Jolly
Chandra Sekhar Pydi Chandra Sekhar Pydi
Charles Skelton Charles Skelton
...@@ -118,18 +132,23 @@ Chris Granger ...@@ -118,18 +132,23 @@ Chris Granger
Chris Houseknecht Chris Houseknecht
Chris Lohfink Chris Lohfink
Chris Morgan Chris Morgan
Chris Reeves
Chris Smith Chris Smith
Christian Gruen
Christian Oyarzun Christian Oyarzun
Christian Petrov Christian Petrov
Christopher Brown Christopher Brown
Christopher Kramer
Christopher Mitchell Christopher Mitchell
Christopher Pfohl Christopher Pfohl
Chunliang Lyu Chunliang Lyu
ciaranj ciaranj
CodeAnimal CodeAnimal
CodeBitt
coderaiser coderaiser
Cole R Lawrence Cole R Lawrence
ComFreek ComFreek
Cristian Prieto
Curtis Gagliardi Curtis Gagliardi
dagsta dagsta
daines daines
...@@ -144,6 +163,8 @@ Daniel Kesler ...@@ -144,6 +163,8 @@ Daniel Kesler
Daniel KJ Daniel KJ
Daniel Neel Daniel Neel
Daniel Parnell Daniel Parnell
Daniel Thwaites
Danila Malyutin
Danny Yoo Danny Yoo
darealshinji darealshinji
Darius Roberts Darius Roberts
...@@ -173,6 +194,7 @@ Drew Khoury ...@@ -173,6 +194,7 @@ Drew Khoury
Drini Cami Drini Cami
Dror BG Dror BG
duralog duralog
dwelle
eborden eborden
edsharp edsharp
ekhaled ekhaled
...@@ -194,12 +216,16 @@ Felix Raab ...@@ -194,12 +216,16 @@ Felix Raab
ficristo ficristo
Filip Noetzel Filip Noetzel
Filip Stollár Filip Stollár
Filype Pereira
flack flack
Florian Felten
ForbesLindesay ForbesLindesay
Forbes Lindesay Forbes Lindesay
Ford_Lawnmower Ford_Lawnmower
Forrest Oliphant Forrest Oliphant
Franco Catena
Frank Wiegand Frank Wiegand
Fredrik Borg
Gabriel Gheorghian Gabriel Gheorghian
Gabriel Horner Gabriel Horner
Gabriel Nahmias Gabriel Nahmias
...@@ -209,6 +235,7 @@ Gautam Mehta ...@@ -209,6 +235,7 @@ Gautam Mehta
Gavin Douglas Gavin Douglas
gekkoe gekkoe
Geordie Hall Geordie Hall
George Stephanis
geowarin geowarin
Gerard Braad Gerard Braad
Gergely Hegykozi Gergely Hegykozi
...@@ -223,6 +250,7 @@ Grant Skinner ...@@ -223,6 +250,7 @@ Grant Skinner
greengiant greengiant
Gregory Koberger Gregory Koberger
Grzegorz Mazur Grzegorz Mazur
Guan Gui
Guillaume Massé Guillaume Massé
Guillaume Massé Guillaume Massé
guraga guraga
...@@ -232,15 +260,20 @@ Hans Engel ...@@ -232,15 +260,20 @@ Hans Engel
Hardest Hardest
Harshvardhan Gupta Harshvardhan Gupta
Hasan Karahan Hasan Karahan
Heanes
Hector Oswaldo Caballero Hector Oswaldo Caballero
Hélio
Hendrik Wallbaum Hendrik Wallbaum
Henrik Haugbølle
Herculano Campos Herculano Campos
Hiroyuki Makino Hiroyuki Makino
hitsthings hitsthings
Hocdoc Hocdoc
Hugues Malphettes Hugues Malphettes
Ian Beck Ian Beck
Ian Davies
Ian Dickinson Ian Dickinson
Ian Rose
Ian Wehrman Ian Wehrman
Ian Wetherbee Ian Wetherbee
Ice White Ice White
...@@ -252,6 +285,7 @@ Irakli Gozalishvili ...@@ -252,6 +285,7 @@ Irakli Gozalishvili
Ivan Kurnosov Ivan Kurnosov
Ivoah Ivoah
Jacob Lee Jacob Lee
Jaimin
Jake Peyser Jake Peyser
Jakob Miland Jakob Miland
Jakub Vrana Jakub Vrana
...@@ -260,6 +294,7 @@ James Campos ...@@ -260,6 +294,7 @@ James Campos
James Howard James Howard
James Thorne James Thorne
Jamie Hill Jamie Hill
Jamie Morris
Jan Jongboom Jan Jongboom
jankeromnes jankeromnes
Jan Keromnes Jan Keromnes
...@@ -275,9 +310,11 @@ Jason Grout ...@@ -275,9 +310,11 @@ Jason Grout
Jason Johnston Jason Johnston
Jason San Jose Jason San Jose
Jason Siefken Jason Siefken
Jayaprabhakar
Jaydeep Solanki Jaydeep Solanki
Jean Boussier Jean Boussier
Jeff Blaisdell Jeff Blaisdell
Jeff Hanke
Jeff Jenkins Jeff Jenkins
jeffkenton jeffkenton
Jeff Pickhardt Jeff Pickhardt
...@@ -285,6 +322,7 @@ jem (graphite) ...@@ -285,6 +322,7 @@ jem (graphite)
Jeremy Parmenter Jeremy Parmenter
Jim Jim
Jim Avery Jim Avery
jkaplon
JobJob JobJob
jochenberger jochenberger
Jochen Berger Jochen Berger
...@@ -299,6 +337,8 @@ John Snelson ...@@ -299,6 +337,8 @@ John Snelson
John Van Der Loo John Van Der Loo
Jon Ander Peñalba Jon Ander Peñalba
Jonas Döbertin Jonas Döbertin
Jonas Helfer
Jonathan Hart
Jonathan Malmaud Jonathan Malmaud
Jon Gacnik Jon Gacnik
jongalloway jongalloway
...@@ -317,6 +357,7 @@ ju1ius ...@@ -317,6 +357,7 @@ ju1ius
Juan Benavides Romero Juan Benavides Romero
Jucovschi Constantin Jucovschi Constantin
Juho Vuori Juho Vuori
Julien CROUZET
Julien Rebetez Julien Rebetez
Justin Andresen Justin Andresen
Justin Hileman Justin Hileman
...@@ -329,6 +370,7 @@ Ken Newman ...@@ -329,6 +370,7 @@ Ken Newman
ken restivo ken restivo
Ken Rockot Ken Rockot
Kevin Earls Kevin Earls
Kevin Kwok
Kevin Muret Kevin Muret
Kevin Sawicki Kevin Sawicki
Kevin Ushey Kevin Ushey
...@@ -342,19 +384,25 @@ ks-ifware ...@@ -342,19 +384,25 @@ ks-ifware
kubelsmieci kubelsmieci
KwanEsq KwanEsq
Kyle Kelley Kyle Kelley
KyleMcNutt
Lanfei Lanfei
Lanny Lanny
Laszlo Vidacs Laszlo Vidacs
leaf corcoran leaf corcoran
Lemmon
Leonid Khachaturov Leonid Khachaturov
Leon Sorokin Leon Sorokin
Leonya Khachaturov Leonya Khachaturov
Liam Newman Liam Newman
Libo Cannici Libo Cannici
Lior Goldberg
Lior Shub
LloydMilligan LloydMilligan
LM LM
lochel lochel
Lorenzo Stoakes Lorenzo Stoakes
Louis Mauchet
Luca Fabbri
Luciano Longo Luciano Longo
Lu Fangjian Lu Fangjian
Luke Browning Luke Browning
...@@ -383,6 +431,7 @@ Mark Lentczner ...@@ -383,6 +431,7 @@ Mark Lentczner
Marko Bonaci Marko Bonaci
Mark Peace Mark Peace
Markus Bordihn Markus Bordihn
Markus Olsson
Martin Balek Martin Balek
Martín Gaitán Martín Gaitán
Martin Hasoň Martin Hasoň
...@@ -411,7 +460,9 @@ Max Schaefer ...@@ -411,7 +460,9 @@ Max Schaefer
Max Xiantu Max Xiantu
mbarkhau mbarkhau
McBrainy McBrainy
mce2
melpon melpon
meshuamam
Metatheos Metatheos
Micah Dubinko Micah Dubinko
Michael Michael
...@@ -419,8 +470,11 @@ Michael Goderbauer ...@@ -419,8 +470,11 @@ Michael Goderbauer
Michael Grey Michael Grey
Michael Kaminsky Michael Kaminsky
Michael Lehenbauer Michael Lehenbauer
Michael Walker
Michael Zhou Michael Zhou
Michal Čihař
Michal Dorner Michal Dorner
Michal Kapiczynski
Mighty Guava Mighty Guava
Miguel Castillo Miguel Castillo
mihailik mihailik
...@@ -436,22 +490,29 @@ misfo ...@@ -436,22 +490,29 @@ misfo
mkaminsky11 mkaminsky11
mloginov mloginov
Moritz Schwörer Moritz Schwörer
Moshe Wajnberg
mps mps
ms ms
mtaran-google mtaran-google
Mu-An Chiou Mu-An Chiou
mzabuawala
Narciso Jaramillo Narciso Jaramillo
Nathan Williams Nathan Williams
ndr ndr
Neil Anderson
neon-dev
nerbert nerbert
NetworkNode
nextrevision nextrevision
ngn ngn
nguillaumin nguillaumin
Ng Zhi An Ng Zhi An
Nicholas Bollweg Nicholas Bollweg
Nicholas Bollweg (Nick) Nicholas Bollweg (Nick)
NickKolok
Nick Kreeger Nick Kreeger
Nick Small Nick Small
Nicolas Kick
Nicolò Ribaudo Nicolò Ribaudo
Niels van Groningen Niels van Groningen
nightwing nightwing
...@@ -463,11 +524,15 @@ Nisarg Jhaveri ...@@ -463,11 +524,15 @@ Nisarg Jhaveri
nlwillia nlwillia
noragrossman noragrossman
Norman Rzepka Norman Rzepka
opl-
Oreoluwa Onatemowo Oreoluwa Onatemowo
Oskar Segersvärd Oskar Segersvärd
overdodactyl
pablo pablo
pabloferz pabloferz
Pablo Zubieta
Page Page
paladox
Panupong Pasupat Panupong Pasupat
paris paris
Paris Paris
...@@ -490,12 +555,15 @@ peterkroon ...@@ -490,12 +555,15 @@ peterkroon
Peter Kroon Peter Kroon
Philipp A Philipp A
Philip Stadermann Philip Stadermann
Pi Delport
Pierre Gerold Pierre Gerold
Piët Delport Pieter Ouwerkerk
Pontus Melke Pontus Melke
prasanthj prasanthj
Prasanth J Prasanth J
Prayag Verma Prayag Verma
Prendota
Qiang Li
Radek Piórkowski Radek Piórkowski
Rahul Rahul
Rahul Anand Rahul Anand
...@@ -503,14 +571,20 @@ ramwin1 ...@@ -503,14 +571,20 @@ ramwin1
Randall Mason Randall Mason
Randy Burden Randy Burden
Randy Edmunds Randy Edmunds
Randy Luecke
Raphael Amorim
Rasmus Erik Voel Jensen Rasmus Erik Voel Jensen
Rasmus Schultz
Raymond Hill
ray ratchup ray ratchup
Ray Ratchup Ray Ratchup
Remi Nyborg Remi Nyborg
Renaud Durlin
Richard Denton Richard Denton
Richard van der Meer Richard van der Meer
Richard Z.H. Wang Richard Z.H. Wang
Rishi Goomar Rishi Goomar
Robert Brignull
Robert Crossfield Robert Crossfield
Roberto Abdelkader Martínez Pérez Roberto Abdelkader Martínez Pérez
robertop23 robertop23
...@@ -518,41 +592,51 @@ Robert Plummer ...@@ -518,41 +592,51 @@ Robert Plummer
Rrandom Rrandom
Rrrandom Rrrandom
Ruslan Osmanov Ruslan Osmanov
Ryan Petrello
Ryan Prior Ryan Prior
ryu-sato
sabaca sabaca
Sam Lee Sam Lee
Sam Rawlins
Samuel Ainsworth Samuel Ainsworth
Sam Wilson Sam Wilson
sandeepshetty sandeepshetty
Sander AKA Redsandro Sander AKA Redsandro
Sander Verweij Sander Verweij
santec santec
Sarah McAlear and Wenlin Zhang
Sascha Peilicke Sascha Peilicke
satamas satamas
satchmorun satchmorun
sathyamoorthi sathyamoorthi
Saul Costa
S. Chris Colbert S. Chris Colbert
SCLINIC\jdecker SCLINIC\jdecker
Scott Aikin Scott Aikin
Scott Goodhew Scott Goodhew
Sebastian Wilzbach
Sebastian Zaha Sebastian Zaha
Sergey Goder Sergey Goder
Sergey Tselovalnikov Sergey Tselovalnikov
Se-Won Kim Se-Won Kim
Shane Liesegang
shaund shaund
shaun gilchrist shaun gilchrist
Shawn A Shawn A
Shea Bunge Shea Bunge
sheopory sheopory
Shil S
Shiv Deepak Shiv Deepak
Shmuel Englard Shmuel Englard
Shubham Jain Shubham Jain
Siamak Mokhtari Siamak Mokhtari
silverwind silverwind
Simon Edwards
sinkuu sinkuu
snasa snasa
soliton4 soliton4
sonson sonson
Sorab Bisht
spastorelli spastorelli
srajanpaliwal srajanpaliwal
Stanislav Oaserele Stanislav Oaserele
...@@ -560,6 +644,8 @@ Stas Kobzar ...@@ -560,6 +644,8 @@ Stas Kobzar
Stefan Borsje Stefan Borsje
Steffen Beyer Steffen Beyer
Steffen Bruchmann Steffen Bruchmann
Steffen Kowalski
Stephane Moore
Stephen Lavelle Stephen Lavelle
Steve Champagne Steve Champagne
Steve Hoover Steve Hoover
...@@ -572,15 +658,18 @@ Taha Jahangir ...@@ -572,15 +658,18 @@ Taha Jahangir
takamori takamori
Tako Schotanus Tako Schotanus
Takuji Shimokawa Takuji Shimokawa
Takuya Matsuyama
Tarmil Tarmil
TDaglis TDaglis
tel tel
Tentone
tfjgeorge tfjgeorge
Thaddee Tyl Thaddee Tyl
thanasis thanasis
TheHowl TheHowl
themrmax themrmax
think think
Thomas Brouard
Thomas Dvornik Thomas Dvornik
Thomas Kluyver Thomas Kluyver
Thomas Schmid Thomas Schmid
...@@ -589,29 +678,38 @@ Tim Baumann ...@@ -589,29 +678,38 @@ Tim Baumann
Timothy Farrell Timothy Farrell
Timothy Gu Timothy Gu
Timothy Hatcher Timothy Hatcher
Tobias Bertelsen
TobiasBg TobiasBg
Todd Berman Todd Berman
Todd Kennedy
Tomas-A Tomas-A
Tomas Varaneckas Tomas Varaneckas
Tom Erik Støwer Tom Erik Støwer
Tom Klancer Tom Klancer
Tom MacWright Tom MacWright
Tom McLaughlin
Tony Jian Tony Jian
tophf
totalamd
Travis Heppe Travis Heppe
Triangle717 Triangle717
Tristan Tarrant Tristan Tarrant
TSUYUSATO Kitsune TSUYUSATO Kitsune
twifkak twifkak
Tyler Long
Vaibhav Sagar
VapidWorx VapidWorx
Vestimir Markov Vestimir Markov
vf vf
Victor Bocharsky Victor Bocharsky
Vincent Woo Vincent Woo
Volker Mische Volker Mische
vtripolitakis
Weiyan Shao Weiyan Shao
wenli wenli
Wes Cossick Wes Cossick
Wesley Wiser Wesley Wiser
Weston Ruter
Will Binns-Smith Will Binns-Smith
Will Dean Will Dean
William Jamieson William Jamieson
...@@ -624,9 +722,11 @@ Yassin N. Hassan ...@@ -624,9 +722,11 @@ Yassin N. Hassan
YNH Webdev YNH Webdev
Yunchi Luo Yunchi Luo
Yuvi Panda Yuvi Panda
Yvonnick Esnault
Zac Anger Zac Anger
Zachary Dremann Zachary Dremann
Zeno Rocha Zeno Rocha
Zhang Hao Zhang Hao
Ziv
zziuni zziuni
魏鹏刚 魏鹏刚
...@@ -2,29 +2,25 @@ ...@@ -2,29 +2,25 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item> <item>
<key> <string>__name__</string> </key> <key> <string>__name__</string> </key>
<value> <string>AUTHORS</string> </value> <value> <string>AUTHORS</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>application/octet-stream</string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
<dictionary/>
</value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -2,29 +2,25 @@ ...@@ -2,29 +2,25 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item> <item>
<key> <string>__name__</string> </key> <key> <string>__name__</string> </key>
<value> <string>CHANGELOG.md</string> </value> <value> <string>CHANGELOG.md</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>application/octet-stream</string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
<dictionary/>
</value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -47,6 +47,10 @@ should be asked on the ...@@ -47,6 +47,10 @@ should be asked on the
## Contributing code ## Contributing code
Note that we are not accepting any new addons or modes into the main
distribution. If you've written such a module, please distribute it as
a separate NPM package.
- Make sure you have a [GitHub Account](https://github.com/signup/free) - Make sure you have a [GitHub Account](https://github.com/signup/free)
- Fork [CodeMirror](https://github.com/codemirror/CodeMirror/) - Fork [CodeMirror](https://github.com/codemirror/CodeMirror/)
([how to fork a repo](https://help.github.com/articles/fork-a-repo)) ([how to fork a repo](https://help.github.com/articles/fork-a-repo))
......
...@@ -2,29 +2,25 @@ ...@@ -2,29 +2,25 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item> <item>
<key> <string>__name__</string> </key> <key> <string>__name__</string> </key>
<value> <string>CONTRIBUTING.md</string> </value> <value> <string>CONTRIBUTING.md</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>application/octet-stream</string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
<dictionary/>
</value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -2,29 +2,25 @@ ...@@ -2,29 +2,25 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item> <item>
<key> <string>__name__</string> </key> <key> <string>__name__</string> </key>
<value> <string>LICENSE</string> </value> <value> <string>LICENSE</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>application/octet-stream</string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
<dictionary/>
</value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -7,7 +7,8 @@ ...@@ -7,7 +7,8 @@
CodeMirror is a versatile text editor implemented in JavaScript for CodeMirror is a versatile text editor implemented in JavaScript for
the browser. It is specialized for editing code, and comes with over the browser. It is specialized for editing code, and comes with over
100 language modes and various addons that implement more advanced 100 language modes and various addons that implement more advanced
editing functionality. editing functionality. Every language comes with fully-featured code
and syntax highlighting to help with reading and editing complex code.
A rich programming API and a CSS theming system are available for A rich programming API and a CSS theming system are available for
customizing CodeMirror to fit your application, and extending it with customizing CodeMirror to fit your application, and extending it with
......
...@@ -2,29 +2,25 @@ ...@@ -2,29 +2,25 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item> <item>
<key> <string>__name__</string> </key> <key> <string>__name__</string> </key>
<value> <string>README.md</string> </value> <value> <string>README.md</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>application/octet-stream</string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
<dictionary/>
</value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
cm.state.closeBrackets = null; cm.state.closeBrackets = null;
} }
if (val) { if (val) {
ensureBound(getOption(val, "pairs"))
cm.state.closeBrackets = val; cm.state.closeBrackets = val;
cm.addKeyMap(keyMap); cm.addKeyMap(keyMap);
} }
...@@ -34,10 +35,14 @@ ...@@ -34,10 +35,14 @@
return defaults[name]; return defaults[name];
} }
var bind = defaults.pairs + "`";
var keyMap = {Backspace: handleBackspace, Enter: handleEnter}; var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
for (var i = 0; i < bind.length; i++) function ensureBound(chars) {
keyMap["'" + bind.charAt(i) + "'"] = handler(bind.charAt(i)); for (var i = 0; i < chars.length; i++) {
var ch = chars.charAt(i), key = "'" + ch + "'"
if (!keyMap[key]) keyMap[key] = handler(ch)
}
}
ensureBound(defaults.pairs + "`")
function handler(ch) { function handler(ch) {
return function(cm) { return handleChar(cm, ch); }; return function(cm) { return handleChar(cm, ch); };
...@@ -79,7 +84,8 @@ ...@@ -79,7 +84,8 @@
if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass; if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
} }
cm.operation(function() { cm.operation(function() {
cm.replaceSelection("\n\n", null); var linesep = cm.lineSeparator() || "\n";
cm.replaceSelection(linesep + linesep, null);
cm.execCommand("goCharLeft"); cm.execCommand("goCharLeft");
ranges = cm.listSelections(); ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
...@@ -123,11 +129,12 @@ ...@@ -123,11 +129,12 @@
else else
curType = "skip"; curType = "skip";
} else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 && } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch && cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) {
(cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != ch)) { if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass;
curType = "addFour"; curType = "addFour";
} else if (identical) { } else if (identical) {
if (!CodeMirror.isWordChar(next) && enteringString(cm, cur, ch)) curType = "both"; var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
else return CodeMirror.Pass; else return CodeMirror.Pass;
} else if (opening && (cm.getLine(cur.line).length == cur.ch || } else if (opening && (cm.getLine(cur.line).length == cur.ch ||
isClosingBracket(next, pairs) || isClosingBracket(next, pairs) ||
...@@ -179,24 +186,9 @@ ...@@ -179,24 +186,9 @@
return str.length == 2 ? str : null; return str.length == 2 ? str : null;
} }
// Project the token type that will exists after the given char is
// typed, and use it to determine whether it would cause the start
// of a string token.
function enteringString(cm, pos, ch) {
var line = cm.getLine(pos.line);
var token = cm.getTokenAt(pos);
if (/\bstring2?\b/.test(token.type) || stringStartsAfter(cm, pos)) return false;
var stream = new CodeMirror.StringStream(line.slice(0, pos.ch) + ch + line.slice(pos.ch), 4);
stream.pos = stream.start = token.start;
for (;;) {
var type1 = cm.getMode().token(stream, token.state);
if (stream.pos >= pos.ch + 1) return /\bstring2?\b/.test(type1);
stream.start = stream.pos;
}
}
function stringStartsAfter(cm, pos) { function stringStartsAfter(cm, pos) {
var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1)) var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
return /\bstring/.test(token.type) && token.start == pos.ch return /\bstring/.test(token.type) && token.start == pos.ch &&
(pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
} }
}); });
...@@ -53,13 +53,14 @@ ...@@ -53,13 +53,14 @@
function autoCloseGT(cm) { function autoCloseGT(cm) {
if (cm.getOption("disableInput")) return CodeMirror.Pass; if (cm.getOption("disableInput")) return CodeMirror.Pass;
var ranges = cm.listSelections(), replacements = []; var ranges = cm.listSelections(), replacements = [];
var opt = cm.getOption("autoCloseTags");
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
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; if (inner.mode.name != "xml" || !state.tagName) return CodeMirror.Pass;
var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html"; var html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose); var 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);
...@@ -81,13 +82,14 @@ ...@@ -81,13 +82,14 @@
newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)}; newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
} }
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnAutoClose);
for (var i = ranges.length - 1; i >= 0; i--) { for (var i = ranges.length - 1; i >= 0; i--) {
var info = replacements[i]; var info = replacements[i];
cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert"); cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
var sel = cm.listSelections().slice(0); var sel = cm.listSelections().slice(0);
sel[i] = {head: info.newPos, anchor: info.newPos}; sel[i] = {head: info.newPos, anchor: info.newPos};
cm.setSelections(sel); cm.setSelections(sel);
if (info.indent) { if (!dontIndentOnAutoClose && info.indent) {
cm.indentLine(info.newPos.line, null, true); cm.indentLine(info.newPos.line, null, true);
cm.indentLine(info.newPos.line + 1, null, true); cm.indentLine(info.newPos.line + 1, null, true);
} }
...@@ -97,6 +99,8 @@ ...@@ -97,6 +99,8 @@
function autoCloseCurrent(cm, typingSlash) { function autoCloseCurrent(cm, typingSlash) {
var ranges = cm.listSelections(), replacements = []; var ranges = cm.listSelections(), replacements = [];
var head = typingSlash ? "/" : "</"; var head = typingSlash ? "/" : "</";
var opt = cm.getOption("autoCloseTags");
var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnSlash);
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
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);
...@@ -127,9 +131,11 @@ ...@@ -127,9 +131,11 @@
} }
cm.replaceSelections(replacements); cm.replaceSelections(replacements);
ranges = cm.listSelections(); ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) if (!dontIndentOnAutoClose) {
if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line) for (var i = 0; i < ranges.length; i++)
cm.indentLine(ranges[i].head.line); if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
cm.indentLine(ranges[i].head.line);
}
} }
function autoCloseSlash(cm) { function autoCloseSlash(cm) {
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
var listRE = /^(\s*)(>[> ]*|- \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/,
emptyListRE = /^(\s*)(>[> ]*|- \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,
unorderedListRE = /[*+-]\s/; unorderedListRE = /[*+-]\s/;
CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) { CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
var inQuote = eolState.quote !== 0; var inQuote = eolState.quote !== 0;
var line = cm.getLine(pos.line), match = listRE.exec(line); var line = cm.getLine(pos.line), match = listRE.exec(line);
if (!ranges[i].empty() || (!inList && !inQuote) || !match) { var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch));
if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) {
cm.execCommand("newlineAndIndent"); cm.execCommand("newlineAndIndent");
return; return;
} }
...@@ -38,14 +39,51 @@ ...@@ -38,14 +39,51 @@
replacements[i] = "\n"; replacements[i] = "\n";
} else { } else {
var indent = match[1], after = match[5]; var indent = match[1], after = match[5];
var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0 var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
? match[2].replace("x", " ") var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " ");
: (parseInt(match[3], 10) + 1) + match[4];
replacements[i] = "\n" + indent + bullet + after; replacements[i] = "\n" + indent + bullet + after;
if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
} }
} }
cm.replaceSelections(replacements); cm.replaceSelections(replacements);
}; };
// Auto-updating Markdown list numbers when a new item is added to the
// middle of a list
function incrementRemainingMarkdownListNumbers(cm, pos) {
var startLine = pos.line, lookAhead = 0, skipCount = 0;
var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1];
do {
lookAhead += 1;
var nextLineNumber = startLine + lookAhead;
var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine);
if (nextItem) {
var nextIndent = nextItem[1];
var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount);
var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber;
if (startIndent === nextIndent && !isNaN(nextNumber)) {
if (newNumber === nextNumber) itemNumber = nextNumber + 1;
if (newNumber > nextNumber) itemNumber = newNumber + 1;
cm.replaceRange(
nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
{
line: nextLineNumber, ch: 0
}, {
line: nextLineNumber, ch: nextLine.length
});
} else {
if (startIndent.length > nextIndent.length) return;
// This doesn't run if the next line immediatley indents, as it is
// not clear of the users intention (new indented item or same level)
if ((startIndent.length < nextIndent.length) && (lookAhead === 1)) return;
skipCount += 1;
}
}
} while (nextItem);
}
}); });
...@@ -16,12 +16,21 @@ ...@@ -16,12 +16,21 @@
var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
function findMatchingBracket(cm, where, strict, config) { function findMatchingBracket(cm, where, config) {
var line = cm.getLineHandle(where.line), pos = where.ch - 1; var line = cm.getLineHandle(where.line), pos = where.ch - 1;
var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; var afterCursor = config && config.afterCursor
if (afterCursor == null)
afterCursor = /(^| )cm-fat-cursor($| )/.test(cm.getWrapperElement().className)
// A cursor is defined as between two characters, but in in vim command mode
// (i.e. not insert mode), the cursor is visually represented as a
// highlighted box on top of the 2nd character. Otherwise, we allow matches
// from before or after the cursor.
var match = (!afterCursor && pos >= 0 && matching[line.text.charAt(pos)]) ||
matching[line.text.charAt(++pos)];
if (!match) return null; if (!match) return null;
var dir = match.charAt(1) == ">" ? 1 : -1; var dir = match.charAt(1) == ">" ? 1 : -1;
if (strict && (dir > 0) != (pos == where.ch)) return null; if (config && config.strict && (dir > 0) != (pos == where.ch)) return null;
var style = cm.getTokenTypeAt(Pos(where.line, pos + 1)); var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config); var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
...@@ -69,7 +78,7 @@ ...@@ -69,7 +78,7 @@
var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000; var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
var marks = [], ranges = cm.listSelections(); var marks = [], ranges = cm.listSelections();
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config); var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config);
if (match && cm.getLine(match.from.line).length <= maxHighlightLen) { if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style})); marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
...@@ -93,18 +102,23 @@ ...@@ -93,18 +102,23 @@
} }
} }
var currentlyHighlighted = null;
function doMatchBrackets(cm) { function doMatchBrackets(cm) {
cm.operation(function() { cm.operation(function() {
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} if (cm.state.matchBrackets.currentlyHighlighted) {
currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets); cm.state.matchBrackets.currentlyHighlighted();
cm.state.matchBrackets.currentlyHighlighted = null;
}
cm.state.matchBrackets.currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
}); });
} }
CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) { CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) { if (old && old != CodeMirror.Init) {
cm.off("cursorActivity", doMatchBrackets); cm.off("cursorActivity", doMatchBrackets);
if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;} if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
cm.state.matchBrackets.currentlyHighlighted();
cm.state.matchBrackets.currentlyHighlighted = null;
}
} }
if (val) { if (val) {
cm.state.matchBrackets = typeof val == "object" ? val : {}; cm.state.matchBrackets = typeof val == "object" ? val : {};
...@@ -113,8 +127,17 @@ ...@@ -113,8 +127,17 @@
}); });
CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);}); CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){ CodeMirror.defineExtension("findMatchingBracket", function(pos, config, oldConfig){
return findMatchingBracket(this, pos, strict, config); // Backwards-compatibility kludge
if (oldConfig || typeof config == "boolean") {
if (!oldConfig) {
config = config ? {strict: true} : null
} else {
oldConfig.strict = config
config = oldConfig
}
}
return findMatchingBracket(this, pos, config)
}); });
CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){ CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
return scanForBracket(this, pos, dir, style, config); return scanForBracket(this, pos, dir, style, config);
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
// Rough heuristic to try and detect lines that are part of multi-line string // Rough heuristic to try and detect lines that are part of multi-line string
function probablyInsideString(cm, pos, line) { function probablyInsideString(cm, pos, line) {
return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"`]/.test(line) return /\bstring\b/.test(cm.getTokenTypeAt(Pos(pos.line, 0))) && !/^[\'\"\`]/.test(line)
} }
function getMode(cm, pos) { function getMode(cm, pos) {
...@@ -172,13 +172,11 @@ ...@@ -172,13 +172,11 @@
if (open == -1) return false if (open == -1) return false
var endLine = end == start ? startLine : self.getLine(end) var endLine = end == start ? startLine : self.getLine(end)
var close = endLine.indexOf(endString, end == start ? open + startString.length : 0); var close = endLine.indexOf(endString, end == start ? open + startString.length : 0);
if (close == -1 && start != end) { var insideStart = Pos(start, open + 1), insideEnd = Pos(end, close + 1)
endLine = self.getLine(--end);
close = endLine.indexOf(endString);
}
if (close == -1 || if (close == -1 ||
!/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) || !/comment/.test(self.getTokenTypeAt(insideStart)) ||
!/comment/.test(self.getTokenTypeAt(Pos(end, close + 1)))) !/comment/.test(self.getTokenTypeAt(insideEnd)) ||
self.getRange(insideStart, insideEnd, "\n").indexOf(endString) > -1)
return false; return false;
// Avoid killing block comments completely outside the selection. // Avoid killing block comments completely outside the selection.
......
...@@ -9,39 +9,32 @@ ...@@ -9,39 +9,32 @@
else // Plain browser env else // Plain browser env
mod(CodeMirror); mod(CodeMirror);
})(function(CodeMirror) { })(function(CodeMirror) {
var modes = ["clike", "css", "javascript"];
for (var i = 0; i < modes.length; ++i)
CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});
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 = [];
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var pos = ranges[i].head, token = cm.getTokenAt(pos); var pos = ranges[i].head
if (token.type != "comment") return CodeMirror.Pass; if (!/\bcomment\b/.test(cm.getTokenTypeAt(pos))) return CodeMirror.Pass;
var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode; var modeHere = cm.getModeAt(pos)
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;
if (mode.blockCommentStart && mode.blockCommentContinue) { if (mode.blockCommentStart && mode.blockCommentContinue) {
var end = token.string.indexOf(mode.blockCommentEnd); var line = cm.getLine(pos.line).slice(0, pos.ch)
var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found; var end = line.lastIndexOf(mode.blockCommentEnd), found
if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) { if (end != -1 && end == pos.ch - mode.blockCommentEnd.length) {
// Comment ended, don't continue it // Comment ended, don't continue it
} else if (token.string.indexOf(mode.blockCommentStart) == 0) { } else if ((found = line.lastIndexOf(mode.blockCommentStart)) > -1 && found > end) {
insert = full.slice(0, token.start); insert = line.slice(0, found)
if (!/^\s*$/.test(insert)) { if (/\S/.test(insert)) {
insert = ""; insert = ""
for (var j = 0; j < token.start; ++j) insert += " "; for (var j = 0; j < found; ++j) insert += " "
} }
} else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 && } else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 && !/\S/.test(line.slice(0, found))) {
found + mode.blockCommentContinue.length > token.start && insert = line.slice(0, found)
/^\s*$/.test(full.slice(0, found))) {
insert = full.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 && mode.lineComment && continueLineCommentEnabled(cm)) {
var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment); var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>dialog.css</string> </value> <value> <string>dialog.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>fullscreen.css</string> </value> <value> <string>fullscreen.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
Panel.prototype.changed = function(height) { Panel.prototype.changed = function(height) {
var newHeight = height == null ? this.node.offsetHeight : height; var newHeight = height == null ? this.node.offsetHeight : height;
var info = this.cm.state.panels; var info = this.cm.state.panels;
this.cm._setSize(null, info.height += (newHeight - this.height)); this.cm._setSize(null, info.heightLeft -= (newHeight - this.height));
this.height = newHeight; this.height = newHeight;
}; };
......
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
clearPlaceholder(cm); clearPlaceholder(cm);
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.className = "CodeMirror-placeholder"; elt.className = "CodeMirror-placeholder";
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)
......
...@@ -65,6 +65,8 @@ ...@@ -65,6 +65,8 @@
widget = document.createElement("span"); widget = document.createElement("span");
widget.appendChild(text); widget.appendChild(text);
widget.className = "CodeMirror-foldmarker"; widget.className = "CodeMirror-foldmarker";
} else if (widget) {
widget = widget.cloneNode(true)
} }
return widget; return widget;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>foldgutter.css</string> </value> <value> <string>foldgutter.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -18,7 +18,7 @@ function lineIndent(cm, lineNo) { ...@@ -18,7 +18,7 @@ function lineIndent(cm, lineNo) {
return -1 return -1
return CodeMirror.countColumn(text, null, cm.getOption("tabSize")) return CodeMirror.countColumn(text, null, cm.getOption("tabSize"))
} }
!
CodeMirror.registerHelper("fold", "indent", function(cm, start) { CodeMirror.registerHelper("fold", "indent", function(cm, start) {
var myIndent = lineIndent(cm, start.line) var myIndent = lineIndent(cm, start.line)
if (myIndent < 0) return if (myIndent < 0) return
......
...@@ -138,7 +138,7 @@ ...@@ -138,7 +138,7 @@
var iter = new Iter(cm, start.line, 0); var iter = new Iter(cm, start.line, 0);
for (;;) { for (;;) {
var openTag = toNextTag(iter), end; var openTag = toNextTag(iter), end;
if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return; if (!openTag || !(end = toTagEnd(iter)) || iter.line != start.line) return;
if (!openTag[1] && end != "selfClose") { if (!openTag[1] && end != "selfClose") {
var startPos = Pos(iter.line, iter.ch); var startPos = Pos(iter.line, iter.ch);
var endPos = findMatchingClose(iter, openTag[2]); var endPos = findMatchingClose(iter, openTag[2]);
...@@ -163,10 +163,10 @@ ...@@ -163,10 +163,10 @@
} }
}; };
CodeMirror.findEnclosingTag = function(cm, pos, range) { CodeMirror.findEnclosingTag = function(cm, pos, range, tag) {
var iter = new Iter(cm, pos.line, pos.ch, range); var iter = new Iter(cm, pos.line, pos.ch, range);
for (;;) { for (;;) {
var open = findMatchingOpen(iter); var open = findMatchingOpen(iter, tag);
if (!open) break; if (!open) break;
var forward = new Iter(cm, pos.line, pos.ch, range); var forward = new Iter(cm, pos.line, pos.ch, range);
var close = findMatchingClose(forward, open.tag); var close = findMatchingClose(forward, open.tag);
...@@ -174,7 +174,7 @@ ...@@ -174,7 +174,7 @@
} }
}; };
// Used by addon/edit/closetag.js // Used by addon/cm_edit/closetag.js
CodeMirror.scanForClosingTag = function(cm, pos, name, end) { CodeMirror.scanForClosingTag = function(cm, pos, name, end) {
var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null); var iter = new Iter(cm, pos.line, pos.ch, end ? {from: 0, to: end} : null);
return findMatchingClose(iter, name); return findMatchingClose(iter, name);
......
...@@ -32,7 +32,9 @@ ...@@ -32,7 +32,9 @@
// Find the token at the cursor // Find the token at the cursor
var cur = editor.getCursor(), token = getToken(editor, cur); var cur = editor.getCursor(), token = getToken(editor, cur);
if (/\b(?:string|comment)\b/.test(token.type)) return; if (/\b(?:string|comment)\b/.test(token.type)) return;
token.state = CodeMirror.innerMode(editor.getMode(), token.state).state; var innerMode = CodeMirror.innerMode(editor.getMode(), token.state);
if (innerMode.mode.helperType === "json") return;
token.state = innerMode.state;
// If it's not a 'word-style' token, ignore the token. // If it's not a 'word-style' token, ignore the token.
if (!/^[\w$_]*$/.test(token.string)) { if (!/^[\w$_]*$/.test(token.string)) {
...@@ -92,8 +94,8 @@ ...@@ -92,8 +94,8 @@
var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " + var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
"lastIndexOf every some filter forEach map reduce reduceRight ").split(" "); "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
var funcProps = "prototype apply call bind".split(" "); var funcProps = "prototype apply call bind".split(" ");
var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " + var javascriptKeywords = ("break case catch class const continue debugger default delete do else export extends false finally for function " +
"if in instanceof new null return switch throw true try typeof var void while with").split(" "); "if in import instanceof new null return super switch this throw true try typeof var void while with yield").split(" ");
var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " + var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
"if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" "); "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>show-hint.css</string> </value> <value> <string>show-hint.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -121,7 +121,6 @@ ...@@ -121,7 +121,6 @@
var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle); var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
if (this.widget) this.widget.close(); if (this.widget) this.widget.close();
if (data && this.data && isNewCompletion(this.data, data)) return;
this.data = data; this.data = data;
if (data && data.list.length) { if (data && data.list.length) {
...@@ -135,11 +134,6 @@ ...@@ -135,11 +134,6 @@
} }
}; };
function isNewCompletion(old, nw) {
var moved = CodeMirror.cmpPos(nw.from, old.from)
return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
}
function parseOptions(cm, pos, options) { function parseOptions(cm, pos, options) {
var editor = cm.options.hintOptions; var editor = cm.options.hintOptions;
var out = {}; var out = {};
...@@ -302,7 +296,7 @@ ...@@ -302,7 +296,7 @@
setTimeout(function(){cm.focus();}, 20); setTimeout(function(){cm.focus();}, 20);
}); });
CodeMirror.signal(data, "select", completions[0], hints.firstChild); CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
return true; return true;
} }
...@@ -403,12 +397,13 @@ ...@@ -403,12 +397,13 @@
}); });
CodeMirror.registerHelper("hint", "fromList", function(cm, options) { CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
var cur = cm.getCursor(), token = cm.getTokenAt(cur); var cur = cm.getCursor(), token = cm.getTokenAt(cur)
var to = CodeMirror.Pos(cur.line, token.end); var term, from = CodeMirror.Pos(cur.line, token.start), to = cur
if (token.string && /\w/.test(token.string[token.string.length - 1])) { if (token.start < cur.ch && /\w/.test(token.string.charAt(cur.ch - token.start - 1))) {
var term = token.string, from = CodeMirror.Pos(cur.line, token.start); term = token.string.substr(0, cur.ch - token.start)
} else { } else {
var term = "", from = to; term = ""
from = cur
} }
var found = []; var found = [];
for (var i = 0; i < options.words.length; i++) { for (var i = 0; i < options.words.length; i++) {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
var tables; var tables;
var defaultTable; var defaultTable;
var keywords; var keywords;
var identifierQuote;
var CONS = { var CONS = {
QUERY_DIV: ";", QUERY_DIV: ";",
ALIAS_KEYWORD: "AS" ALIAS_KEYWORD: "AS"
...@@ -28,6 +29,12 @@ ...@@ -28,6 +29,12 @@
return CodeMirror.resolveMode(mode).keywords; return CodeMirror.resolveMode(mode).keywords;
} }
function getIdentifierQuote(editor) {
var mode = editor.doc.modeOption;
if (mode === "sql") mode = "text/x-sql";
return CodeMirror.resolveMode(mode).identifierQuote || "`";
}
function getText(item) { function getText(item) {
return typeof item == "string" ? item : item.text; return typeof item == "string" ? item : item.text;
} }
...@@ -86,17 +93,25 @@ ...@@ -86,17 +93,25 @@
} }
function cleanName(name) { function cleanName(name) {
// Get rid name from backticks(`) and preceding dot(.) // Get rid name from identifierQuote and preceding dot(.)
if (name.charAt(0) == ".") { if (name.charAt(0) == ".") {
name = name.substr(1); name = name.substr(1);
} }
return name.replace(/`/g, ""); // replace doublicated identifierQuotes with single identifierQuotes
// and remove single identifierQuotes
var nameParts = name.split(identifierQuote+identifierQuote);
for (var i = 0; i < nameParts.length; i++)
nameParts[i] = nameParts[i].replace(new RegExp(identifierQuote,"g"), "");
return nameParts.join(identifierQuote);
} }
function insertBackticks(name) { function insertIdentifierQuotes(name) {
var nameParts = getText(name).split("."); var nameParts = getText(name).split(".");
for (var i = 0; i < nameParts.length; i++) for (var i = 0; i < nameParts.length; i++)
nameParts[i] = "`" + nameParts[i] + "`"; nameParts[i] = identifierQuote +
// doublicate identifierQuotes
nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
identifierQuote;
var escaped = nameParts.join("."); var escaped = nameParts.join(".");
if (typeof name == "string") return escaped; if (typeof name == "string") return escaped;
name = shallowClone(name); name = shallowClone(name);
...@@ -106,13 +121,13 @@ ...@@ -106,13 +121,13 @@
function nameCompletion(cur, token, result, editor) { function nameCompletion(cur, token, result, editor) {
// Try to complete table, column names and return start position of completion // Try to complete table, column names and return start position of completion
var useBacktick = false; var useIdentifierQuotes = false;
var nameParts = []; var nameParts = [];
var start = token.start; var start = token.start;
var cont = true; var cont = true;
while (cont) { while (cont) {
cont = (token.string.charAt(0) == "."); cont = (token.string.charAt(0) == ".");
useBacktick = useBacktick || (token.string.charAt(0) == "`"); useIdentifierQuotes = useIdentifierQuotes || (token.string.charAt(0) == identifierQuote);
start = token.start; start = token.start;
nameParts.unshift(cleanName(token.string)); nameParts.unshift(cleanName(token.string));
...@@ -127,12 +142,12 @@ ...@@ -127,12 +142,12 @@
// Try to complete table names // Try to complete table names
var string = nameParts.join("."); var string = nameParts.join(".");
addMatches(result, string, tables, function(w) { addMatches(result, string, tables, function(w) {
return useBacktick ? insertBackticks(w) : w; return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
}); });
// Try to complete columns from defaultTable // Try to complete columns from defaultTable
addMatches(result, string, defaultTable, function(w) { addMatches(result, string, defaultTable, function(w) {
return useBacktick ? insertBackticks(w) : w; return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
}); });
// Try to complete columns // Try to complete columns
...@@ -162,7 +177,7 @@ ...@@ -162,7 +177,7 @@
w = shallowClone(w); w = shallowClone(w);
w.text = tableInsert + "." + w.text; w.text = tableInsert + "." + w.text;
} }
return useBacktick ? insertBackticks(w) : w; return useIdentifierQuotes ? insertIdentifierQuotes(w) : w;
}); });
} }
...@@ -170,12 +185,9 @@ ...@@ -170,12 +185,9 @@
} }
function eachWord(lineText, f) { function eachWord(lineText, f) {
if (!lineText) return; var words = lineText.split(/\s+/)
var excepted = /[,;]/g; for (var i = 0; i < words.length; i++)
var words = lineText.split(" "); if (words[i]) f(words[i].replace(/[,;]/g, ''))
for (var i = 0; i < words.length; i++) {
f(words[i]?words[i].replace(excepted, '') : '');
}
} }
function findTableByAlias(alias, editor) { function findTableByAlias(alias, editor) {
...@@ -210,18 +222,20 @@ ...@@ -210,18 +222,20 @@
prevItem = separator[i]; prevItem = separator[i];
} }
var query = doc.getRange(validRange.start, validRange.end, false); if (validRange.start) {
var query = doc.getRange(validRange.start, validRange.end, false);
for (var i = 0; i < query.length; i++) {
var lineText = query[i]; for (var i = 0; i < query.length; i++) {
eachWord(lineText, function(word) { var lineText = query[i];
var wordUpperCase = word.toUpperCase(); eachWord(lineText, function(word) {
if (wordUpperCase === aliasUpperCase && getTable(previousWord)) var wordUpperCase = word.toUpperCase();
table = previousWord; if (wordUpperCase === aliasUpperCase && getTable(previousWord))
if (wordUpperCase !== CONS.ALIAS_KEYWORD) table = previousWord;
previousWord = word; if (wordUpperCase !== CONS.ALIAS_KEYWORD)
}); previousWord = word;
if (table) break; });
if (table) break;
}
} }
return table; return table;
} }
...@@ -232,6 +246,7 @@ ...@@ -232,6 +246,7 @@
var disableKeywords = options && options.disableKeywords; var disableKeywords = options && options.disableKeywords;
defaultTable = defaultTableName && getTable(defaultTableName); defaultTable = defaultTableName && getTable(defaultTableName);
keywords = getKeywords(editor); keywords = getKeywords(editor);
identifierQuote = getIdentifierQuote(editor);
if (defaultTableName && !defaultTable) if (defaultTableName && !defaultTable)
defaultTable = findTableByAlias(defaultTableName, editor); defaultTable = findTableByAlias(defaultTableName, editor);
...@@ -249,7 +264,7 @@ ...@@ -249,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*$/)) {
search = token.string; search = token.string;
start = token.start; start = token.start;
end = token.end; end = token.end;
...@@ -257,11 +272,11 @@ ...@@ -257,11 +272,11 @@
start = end = cur.ch; start = end = cur.ch;
search = ""; search = "";
} }
if (search.charAt(0) == "." || search.charAt(0) == "`") { if (search.charAt(0) == "." || search.charAt(0) == identifierQuote) {
start = nameCompletion(cur, token, result, editor); start = nameCompletion(cur, token, result, editor);
} else { } else {
addMatches(result, search, tables, function(w) {return w;});
addMatches(result, search, defaultTable, function(w) {return w;}); addMatches(result, search, defaultTable, function(w) {return w;});
addMatches(result, search, tables, function(w) {return w;});
if (!disableKeywords) if (!disableKeywords)
addMatches(result, search, keywords, function(w) {return w.toUpperCase();}); addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
} }
......
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
CodeMirror.registerHelper("lint", "coffeescript", function(text) { CodeMirror.registerHelper("lint", "coffeescript", function(text) {
var found = []; var found = [];
if (!window.coffeelint) {
if (window.console) {
window.console.error("Error: window.coffeelint not defined, CodeMirror CoffeeScript linting cannot run.");
}
return found;
}
var parseError = function(err) { var parseError = function(err) {
var loc = err.lineNumber; var loc = err.lineNumber;
found.push({from: CodeMirror.Pos(loc-1, 0), found.push({from: CodeMirror.Pos(loc-1, 0),
......
...@@ -15,10 +15,15 @@ ...@@ -15,10 +15,15 @@
})(function(CodeMirror) { })(function(CodeMirror) {
"use strict"; "use strict";
CodeMirror.registerHelper("lint", "css", function(text) { CodeMirror.registerHelper("lint", "css", function(text, options) {
var found = []; var found = [];
if (!window.CSSLint) return found; if (!window.CSSLint) {
var results = CSSLint.verify(text), messages = results.messages, message = null; if (window.console) {
window.console.error("Error: window.CSSLint not defined, CodeMirror CSS linting cannot run.");
}
return found;
}
var results = CSSLint.verify(text, options), messages = results.messages, message = null;
for ( var i = 0; i < messages.length; i++) { for ( var i = 0; i < messages.length; i++) {
message = messages[i]; message = messages[i];
var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col; var startLine = message.line -1, endLine = message.line -1, startCol = message.col -1, endCol = message.col;
......
...@@ -11,8 +11,8 @@ ...@@ -11,8 +11,8 @@
else if (typeof define == "function" && define.amd) // AMD else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "htmlhint"], mod); define(["../../lib/codemirror", "htmlhint"], mod);
else // Plain browser env else // Plain browser env
mod(CodeMirror); mod(CodeMirror, window.HTMLHint);
})(function(CodeMirror) { })(function(CodeMirror, HTMLHint) {
"use strict"; "use strict";
var defaultRules = { var defaultRules = {
...@@ -29,7 +29,14 @@ ...@@ -29,7 +29,14 @@
CodeMirror.registerHelper("lint", "html", function(text, options) { CodeMirror.registerHelper("lint", "html", function(text, options) {
var found = []; var found = [];
if (!window.HTMLHint) return found; if (HTMLHint && !HTMLHint.verify) HTMLHint = HTMLHint.HTMLHint;
if (!HTMLHint) HTMLHint = window.HTMLHint;
if (!HTMLHint) {
if (window.console) {
window.console.error("Error: HTMLHint not found, not defined on window, or not available through define/require, CodeMirror HTML linting cannot run.");
}
return found;
}
var messages = HTMLHint.verify(text, options && options.rules || defaultRules); var messages = HTMLHint.verify(text, options && options.rules || defaultRules);
for (var i = 0; i < messages.length; i++) { for (var i = 0; i < messages.length; i++) {
var message = messages[i]; var message = messages[i];
......
...@@ -12,17 +12,15 @@ ...@@ -12,17 +12,15 @@
"use strict"; "use strict";
// declare global: JSHINT // declare global: JSHINT
var bogus = [ "Dangerous comment" ];
var warnings = [ [ "Expected '{'",
"Statement body should be inside '{ }' braces." ] ];
var errors = [ "Missing semicolon", "Extra comma", "Missing property name",
"Unmatched ", " and instead saw", " is not defined",
"Unclosed string", "Stopping, unable to continue" ];
function validator(text, options) { function validator(text, options) {
if (!window.JSHINT) return []; if (!window.JSHINT) {
if (window.console) {
window.console.error("Error: window.JSHINT not defined, CodeMirror JavaScript linting cannot run.");
}
return [];
}
if (!options.indent) // JSHint error.character actually is a column index, this fixes underlining on lines using tabs for indentation
options.indent = 1; // JSHint default value is 4
JSHINT(text, options, options.globals); JSHINT(text, options, options.globals);
var errors = JSHINT.data().errors, result = []; var errors = JSHINT.data().errors, result = [];
if (errors) parseErrors(errors, result); if (errors) parseErrors(errors, result);
...@@ -31,105 +29,34 @@ ...@@ -31,105 +29,34 @@
CodeMirror.registerHelper("lint", "javascript", validator); CodeMirror.registerHelper("lint", "javascript", validator);
function cleanup(error) {
// All problems are warnings by default
fixWith(error, warnings, "warning", true);
fixWith(error, errors, "error");
return isBogus(error) ? null : error;
}
function fixWith(error, fixes, severity, force) {
var description, fix, find, replace, found;
description = error.description;
for ( var i = 0; i < fixes.length; i++) {
fix = fixes[i];
find = (typeof fix === "string" ? fix : fix[0]);
replace = (typeof fix === "string" ? null : fix[1]);
found = description.indexOf(find) !== -1;
if (force || found) {
error.severity = severity;
}
if (found && replace) {
error.description = replace;
}
}
}
function isBogus(error) {
var description = error.description;
for ( var i = 0; i < bogus.length; i++) {
if (description.indexOf(bogus[i]) !== -1) {
return true;
}
}
return false;
}
function parseErrors(errors, output) { function parseErrors(errors, output) {
for ( var i = 0; i < errors.length; i++) { for ( var i = 0; i < errors.length; i++) {
var error = errors[i]; var error = errors[i];
if (error) { if (error) {
var linetabpositions, index; if (error.line <= 0) {
if (window.console) {
linetabpositions = []; window.console.warn("Cannot display JSHint error (invalid line " + error.line + ")", error);
// This next block is to fix a problem in jshint. Jshint
// replaces
// all tabs with spaces then performs some checks. The error
// positions (character/space) are then reported incorrectly,
// not taking the replacement step into account. Here we look
// at the evidence line and try to adjust the character position
// to the correct value.
if (error.evidence) {
// Tab positions are computed once per line and cached
var tabpositions = linetabpositions[error.line];
if (!tabpositions) {
var evidence = error.evidence;
tabpositions = [];
// ugggh phantomjs does not like this
// forEachChar(evidence, function(item, index) {
Array.prototype.forEach.call(evidence, function(item,
index) {
if (item === '\t') {
// First col is 1 (not 0) to match error
// positions
tabpositions.push(index + 1);
}
});
linetabpositions[error.line] = tabpositions;
}
if (tabpositions.length > 0) {
var pos = error.character;
tabpositions.forEach(function(tabposition) {
if (pos > tabposition) pos -= 1;
});
error.character = pos;
} }
continue;
} }
var start = error.character - 1, end = start + 1; var start = error.character - 1, end = start + 1;
if (error.evidence) { if (error.evidence) {
index = error.evidence.substring(start).search(/.\b/); var index = error.evidence.substring(start).search(/.\b/);
if (index > -1) { if (index > -1) {
end += index; end += index;
} }
} }
// Convert to format expected by validation service // Convert to format expected by validation service
error.description = error.reason;// + "(jshint)"; var hint = {
error.start = error.character; message: error.reason,
error.end = end; severity: error.code ? (error.code.startsWith('W') ? "warning" : "error") : "error",
error = cleanup(error); from: CodeMirror.Pos(error.line - 1, start),
to: CodeMirror.Pos(error.line - 1, end)
if (error) };
output.push({message: error.description,
severity: error.severity, output.push(hint);
from: CodeMirror.Pos(error.line - 1, start),
to: CodeMirror.Pos(error.line - 1, end)});
} }
} }
} }
......
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
CodeMirror.registerHelper("lint", "json", function(text) { CodeMirror.registerHelper("lint", "json", function(text) {
var found = []; var found = [];
if (!window.jsonlint) {
if (window.console) {
window.console.error("Error: window.jsonlint not defined, CodeMirror JSON linting cannot run.");
}
return found;
}
jsonlint.parseError = function(str, hash) { jsonlint.parseError = function(str, hash) {
var loc = hash.loc; var loc = hash.loc;
found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column), found.push({from: CodeMirror.Pos(loc.first_line - 1, loc.first_column),
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>lint.css</string> </value> <value> <string>lint.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -112,7 +112,11 @@ ...@@ -112,7 +112,11 @@
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-" + severity;
tip.appendChild(document.createTextNode(ann.message)); if (typeof ann.messageHTML != 'undefined') {
tip.innerHTML = ann.messageHTML;
} else {
tip.appendChild(document.createTextNode(ann.message));
}
return tip; return tip;
} }
...@@ -128,19 +132,28 @@ ...@@ -128,19 +132,28 @@
cm.off("change", abort) cm.off("change", abort)
if (state.waitingFor != id) return if (state.waitingFor != id) return
if (arg2 && annotations instanceof CodeMirror) annotations = arg2 if (arg2 && annotations instanceof CodeMirror) annotations = arg2
updateLinting(cm, annotations) cm.operation(function() {updateLinting(cm, annotations)})
}, passOptions, cm); }, passOptions, cm);
} }
function startLinting(cm) { function startLinting(cm) {
var state = cm.state.lint, options = state.options; var state = cm.state.lint, options = state.options;
var passOptions = options.options || options; // Support deprecated passing of `options` property in options /*
* Passing rules in `options` property prevents JSHint (and other linters) from complaining
* about unrecognized rules like `onUpdateLinting`, `delay`, `lintOnChange`, etc.
*/
var passOptions = options.options || options;
var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint"); var getAnnotations = options.getAnnotations || cm.getHelper(CodeMirror.Pos(0, 0), "lint");
if (!getAnnotations) return; if (!getAnnotations) return;
if (options.async || getAnnotations.async) { if (options.async || getAnnotations.async) {
lintAsync(cm, getAnnotations, passOptions) lintAsync(cm, getAnnotations, passOptions)
} else { } else {
updateLinting(cm, getAnnotations(cm.getValue(), passOptions, cm)); var annotations = getAnnotations(cm.getValue(), passOptions, cm);
if (!annotations) return;
if (annotations.then) annotations.then(function(issues) {
cm.operation(function() {updateLinting(cm, issues)})
});
else cm.operation(function() {updateLinting(cm, annotations)})
} }
} }
......
...@@ -17,10 +17,23 @@ ...@@ -17,10 +17,23 @@
CodeMirror.registerHelper("lint", "yaml", function(text) { CodeMirror.registerHelper("lint", "yaml", function(text) {
var found = []; var found = [];
if (!window.jsyaml) {
if (window.console) {
window.console.error("Error: window.jsyaml not defined, CodeMirror YAML linting cannot run.");
}
return found;
}
try { jsyaml.load(text); } try { jsyaml.load(text); }
catch(e) { catch(e) {
var loc = e.mark; var loc = e.mark,
found.push({ from: CodeMirror.Pos(loc.line, loc.column), to: CodeMirror.Pos(loc.line, loc.column), message: e.message }); // js-yaml YAMLException doesn't always provide an accurate lineno
// e.g., when there are multiple yaml docs
// ---
// ---
// foo:bar
from = loc ? CodeMirror.Pos(loc.line, loc.column) : CodeMirror.Pos(0, 0),
to = from;
found.push({ from: from, to: to, message: e.message });
} }
return found; return found;
}); });
......
...@@ -48,6 +48,12 @@ ...@@ -48,6 +48,12 @@
color: #555; color: #555;
line-height: 1; line-height: 1;
} }
.CodeMirror-merge-scrolllock:after {
content: "\21db\00a0\00a0\21da";
}
.CodeMirror-merge-scrolllock.CodeMirror-merge-scrolllock-enabled:after {
content: "\21db\21da";
}
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right { .CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
position: absolute; position: absolute;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>merge.css</string> </value> <value> <string>merge.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -49,17 +49,17 @@ ...@@ -49,17 +49,17 @@
if (Object.prototype.toString.call(classLocation) != "[object Array]") classLocation = [classLocation] if (Object.prototype.toString.call(classLocation) != "[object Array]") classLocation = [classLocation]
this.classes.classLocation = classLocation this.classes.classLocation = classLocation
this.diff = getDiff(asString(orig), asString(options.value)); this.diff = getDiff(asString(orig), asString(options.value), this.mv.options.ignoreWhitespace);
this.chunks = getChunks(this.diff); this.chunks = getChunks(this.diff);
this.diffOutOfDate = this.dealigned = false; this.diffOutOfDate = this.dealigned = false;
this.needsScrollSync = null this.needsScrollSync = null
this.showDifferences = options.showDifferences !== false; this.showDifferences = options.showDifferences !== false;
}, },
registerEvents: function() { registerEvents: function(otherDv) {
this.forceUpdate = registerUpdate(this); this.forceUpdate = registerUpdate(this);
setScrollLock(this, true, false); setScrollLock(this, true, false);
registerScroll(this); registerScroll(this, otherDv);
}, },
setShowDifferences: function(val) { setShowDifferences: function(val) {
val = val !== false; val = val !== false;
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
function ensureDiff(dv) { function ensureDiff(dv) {
if (dv.diffOutOfDate) { if (dv.diffOutOfDate) {
dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue()); dv.diff = getDiff(dv.orig.getValue(), dv.edit.getValue(), dv.mv.options.ignoreWhitespace);
dv.chunks = getChunks(dv.diff); dv.chunks = getChunks(dv.diff);
dv.diffOutOfDate = false; dv.diffOutOfDate = false;
CodeMirror.signal(dv.edit, "updateDiff", dv.diff); CodeMirror.signal(dv.edit, "updateDiff", dv.diff);
...@@ -128,6 +128,7 @@ ...@@ -128,6 +128,7 @@
} }
function swapDoc() { function swapDoc() {
dv.diffOutOfDate = true; dv.diffOutOfDate = true;
dv.dealigned = true;
update("full"); update("full");
} }
dv.edit.on("change", change); dv.edit.on("change", change);
...@@ -144,12 +145,13 @@ ...@@ -144,12 +145,13 @@
return update; return update;
} }
function registerScroll(dv) { function registerScroll(dv, otherDv) {
dv.edit.on("scroll", function() { dv.edit.on("scroll", function() {
syncScroll(dv, true) && makeConnections(dv); syncScroll(dv, true) && makeConnections(dv);
}); });
dv.orig.on("scroll", function() { dv.orig.on("scroll", function() {
syncScroll(dv, false) && makeConnections(dv); syncScroll(dv, false) && makeConnections(dv);
if (otherDv) syncScroll(otherDv, true) && makeConnections(otherDv);
}); });
} }
...@@ -209,7 +211,7 @@ ...@@ -209,7 +211,7 @@
function setScrollLock(dv, val, action) { function setScrollLock(dv, val, action) {
dv.lockScroll = val; dv.lockScroll = val;
if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv); if (val && action != false) syncScroll(dv, DIFF_INSERT) && makeConnections(dv);
dv.lockButton.innerHTML = val ? "\u21db\u21da" : "\u21db&nbsp;&nbsp;\u21da"; (val ? CodeMirror.addClass : CodeMirror.rmClass)(dv.lockButton, "CodeMirror-merge-scrolllock-enabled");
} }
// Updating the marks for editor content // Updating the marks for editor content
...@@ -352,11 +354,11 @@ ...@@ -352,11 +354,11 @@
var result = [] var result = []
for (var i = 0;; i++) { for (var i = 0;; i++) {
var chunk = chunks[i] var chunk = chunks[i]
var chunkStart = !chunk ? cm.lastLine() + 1 : isOrig ? chunk.origFrom : chunk.editFrom var chunkStart = !chunk ? 1e9 : isOrig ? chunk.origFrom : chunk.editFrom
for (; trackI < tracker.alignable.length; trackI += 2) { for (; trackI < tracker.alignable.length; trackI += 2) {
var n = tracker.alignable[trackI] + 1 var n = tracker.alignable[trackI] + 1
if (n <= start) continue if (n <= start) continue
if (n < chunkStart) result.push(n) if (n <= chunkStart) result.push(n)
else break else break
} }
if (!chunk) break if (!chunk) break
...@@ -370,14 +372,22 @@ ...@@ -370,14 +372,22 @@
// lines that need to be aligned with each other. // lines that need to be aligned with each other.
function mergeAlignable(result, origAlignable, chunks, setIndex) { function mergeAlignable(result, origAlignable, chunks, setIndex) {
var rI = 0, origI = 0, chunkI = 0, diff = 0 var rI = 0, origI = 0, chunkI = 0, diff = 0
for (;; rI++) { outer: for (;; rI++) {
var nextR = result[rI], nextO = origAlignable[origI] var nextR = result[rI], nextO = origAlignable[origI]
if (!nextR && nextO == null) break if (!nextR && nextO == null) break
var rLine = nextR ? nextR[0] : 1e9, oLine = nextO == null ? 1e9 : nextO var rLine = nextR ? nextR[0] : 1e9, oLine = nextO == null ? 1e9 : nextO
while (chunkI < chunks.length) { while (chunkI < chunks.length) {
var chunk = chunks[chunkI] var chunk = chunks[chunkI]
if (chunk.editTo > rLine) break if (chunk.origFrom <= oLine && chunk.origTo > oLine) {
origI++
rI--
continue outer;
}
if (chunk.editTo > rLine) {
if (chunk.editFrom <= rLine) continue outer;
break
}
diff += (chunk.origTo - chunk.origFrom) - (chunk.editTo - chunk.editFrom) diff += (chunk.origTo - chunk.origFrom) - (chunk.editTo - chunk.editFrom)
chunkI++ chunkI++
} }
...@@ -467,7 +477,7 @@ ...@@ -467,7 +477,7 @@
var elt = document.createElement("div"); var elt = document.createElement("div");
elt.className = "CodeMirror-merge-spacer"; elt.className = "CodeMirror-merge-spacer";
elt.style.height = size + "px"; elt.style.minWidth = "1px"; elt.style.height = size + "px"; elt.style.minWidth = "1px";
return cm.addLineWidget(line, elt, {height: size, above: above, mergeSpacer: true}); return cm.addLineWidget(line, elt, {height: size, above: above, mergeSpacer: true, handleMouseEvents: true});
} }
function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) { function drawConnectorsForChunk(dv, chunk, sTopOrig, sTopEdit, w) {
...@@ -567,8 +577,8 @@ ...@@ -567,8 +577,8 @@
this.aligners = []; this.aligners = [];
alignChunks(this.left || this.right, true); alignChunks(this.left || this.right, true);
} }
if (left) left.registerEvents() if (left) left.registerEvents(right)
if (right) right.registerEvents() if (right) right.registerEvents(left)
var onResize = function() { var onResize = function() {
...@@ -634,14 +644,15 @@ ...@@ -634,14 +644,15 @@
} }
// Operations on diffs // Operations on diffs
var dmp;
function getDiff(a, b, ignoreWhitespace) {
if (!dmp) dmp = new diff_match_patch();
var dmp = new diff_match_patch();
function getDiff(a, b) {
var diff = dmp.diff_main(a, b); var diff = dmp.diff_main(a, b);
// The library sometimes leaves in empty parts, which confuse the algorithm // The library sometimes leaves in empty parts, which confuse the algorithm
for (var i = 0; i < diff.length; ++i) { for (var i = 0; i < diff.length; ++i) {
var part = diff[i]; var part = diff[i];
if (!part[1]) { if (ignoreWhitespace ? !/[^ \t]/.test(part[1]) : !part[1]) {
diff.splice(i--, 1); diff.splice(i--, 1);
} else if (i && diff[i - 1][0] == part[0]) { } else if (i && diff[i - 1][0] == part[0]) {
diff.splice(i--, 1); diff.splice(i--, 1);
...@@ -658,7 +669,7 @@ ...@@ -658,7 +669,7 @@
for (var i = 0; i < diff.length; ++i) { for (var i = 0; i < diff.length; ++i) {
var part = diff[i], tp = part[0]; var part = diff[i], tp = part[0];
if (tp == DIFF_EQUAL) { if (tp == DIFF_EQUAL) {
var startOff = startOfLineClean(diff, i) ? 0 : 1; var startOff = !startOfLineClean(diff, i) || edit.line < startEdit || orig.line < startOrig ? 1 : 0;
var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff; var cleanFromEdit = edit.line + startOff, cleanFromOrig = orig.line + startOff;
moveOver(edit, part[1], null, orig); moveOver(edit, part[1], null, orig);
var endOff = endOfLineClean(diff, i) ? 1 : 0; var endOff = endOfLineClean(diff, i) ? 1 : 0;
...@@ -727,6 +738,9 @@ ...@@ -727,6 +738,9 @@
mark.clear(); mark.clear();
cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line"); cm.removeLineClass(from, "wrap", "CodeMirror-merge-collapsed-line");
} }
if (mark.explicitlyCleared) clear();
CodeMirror.on(widget, "click", clear);
mark.on("clear", clear);
CodeMirror.on(widget, "click", clear); CodeMirror.on(widget, "click", clear);
return {mark: mark, clear: clear}; return {mark: mark, clear: clear};
} }
...@@ -826,6 +840,7 @@ ...@@ -826,6 +840,7 @@
function TrackAlignable(cm) { function TrackAlignable(cm) {
this.cm = cm this.cm = cm
this.alignable = [] this.alignable = []
this.height = cm.doc.height
var self = this var self = this
cm.on("markerAdded", function(_, marker) { cm.on("markerAdded", function(_, marker) {
if (!marker.collapsed) return if (!marker.collapsed) return
...@@ -855,11 +870,15 @@ ...@@ -855,11 +870,15 @@
self.check(end, F_MARKER, self.hasMarker) self.check(end, F_MARKER, self.hasMarker)
if (nBefore || nAfter) self.check(change.from.line, F_MARKER, self.hasMarker) if (nBefore || nAfter) self.check(change.from.line, F_MARKER, self.hasMarker)
}) })
cm.on("viewportChange", function() {
if (self.cm.doc.height != self.height) self.signal()
})
} }
TrackAlignable.prototype = { TrackAlignable.prototype = {
signal: function() { signal: function() {
CodeMirror.signal(this, "realign") CodeMirror.signal(this, "realign")
this.height = this.cm.doc.height
}, },
set: function(n, flags) { set: function(n, flags) {
......
...@@ -50,7 +50,15 @@ CodeMirror.multiplexingMode = function(outer /*, others */) { ...@@ -50,7 +50,15 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
if (found == stream.pos) { if (found == stream.pos) {
if (!other.parseDelimiters) stream.match(other.open); if (!other.parseDelimiters) stream.match(other.open);
state.innerActive = other; state.innerActive = other;
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
// Get the outer indent, making sure to handle CodeMirror.Pass
var outerIndent = 0;
if (outer.indent) {
var possibleOuterIndent = outer.indent(state.outer, "");
if (possibleOuterIndent !== CodeMirror.Pass) outerIndent = possibleOuterIndent;
}
state.inner = CodeMirror.startState(other.mode, outerIndent);
return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open"); return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
} else if (found != -1 && found < cutOff) { } else if (found != -1 && found < cutOff) {
cutOff = found; cutOff = found;
......
...@@ -77,6 +77,7 @@ ...@@ -77,6 +77,7 @@
function asToken(val) { function asToken(val) {
if (!val) return null; if (!val) return null;
if (val.apply) return val
if (typeof val == "string") return val.replace(/\./g, " "); if (typeof val == "string") return val.replace(/\./g, " ");
var result = []; var result = [];
for (var i = 0; i < val.length; i++) for (var i = 0; i < val.length; i++)
...@@ -133,17 +134,19 @@ ...@@ -133,17 +134,19 @@
state.indent.push(stream.indentation() + config.indentUnit); state.indent.push(stream.indentation() + config.indentUnit);
if (rule.data.dedent) if (rule.data.dedent)
state.indent.pop(); state.indent.pop();
if (matches.length > 2) { var token = rule.token
if (token && token.apply) token = token(matches)
if (matches.length > 2 && rule.token && typeof rule.token != "string") {
state.pending = []; state.pending = [];
for (var j = 2; j < matches.length; j++) for (var j = 2; j < matches.length; j++)
if (matches[j]) if (matches[j])
state.pending.push({text: matches[j], token: rule.token[j - 1]}); state.pending.push({text: matches[j], token: rule.token[j - 1]});
stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0)); stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
return rule.token[0]; return token[0];
} else if (rule.token && rule.token.join) { } else if (token && token.join) {
return rule.token[0]; return token[0];
} else { } else {
return rule.token; return token;
} }
} }
} }
......
...@@ -65,7 +65,8 @@ StringStream.prototype = { ...@@ -65,7 +65,8 @@ StringStream.prototype = {
this.lineStart += n; this.lineStart += n;
try { return inner(); } try { return inner(); }
finally { this.lineStart -= n; } finally { this.lineStart -= n; }
} },
lookAhead: function() { return null }
}; };
CodeMirror.StringStream = StringStream; CodeMirror.StringStream = StringStream;
......
...@@ -7,7 +7,7 @@ function splitLines(string){return string.split(/\r\n?|\n/);}; ...@@ -7,7 +7,7 @@ function splitLines(string){return string.split(/\r\n?|\n/);};
// 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 = function(string, end, tabSize, startIndex, startValue) { var countColumn = exports.countColumn = function(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;
...@@ -22,12 +22,13 @@ var countColumn = function(string, end, tabSize, startIndex, startValue) { ...@@ -22,12 +22,13 @@ var countColumn = function(string, end, tabSize, startIndex, startValue) {
} }
}; };
function StringStream(string, tabSize) { function StringStream(string, tabSize, context) {
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
}; };
StringStream.prototype = { StringStream.prototype = {
...@@ -91,6 +92,10 @@ StringStream.prototype = { ...@@ -91,6 +92,10 @@ StringStream.prototype = {
this.lineStart += n; this.lineStart += n;
try { return inner(); } try { return inner(); }
finally { this.lineStart -= n; } 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; exports.StringStream = StringStream;
...@@ -158,14 +163,27 @@ exports.getMode = function(options, spec) { ...@@ -158,14 +163,27 @@ exports.getMode = function(options, spec) {
return modeObj; return modeObj;
}; };
exports.innerMode = function(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};
}
exports.registerHelper = exports.registerGlobalHelper = Math.min; exports.registerHelper = exports.registerGlobalHelper = Math.min;
exports.runMode = function(string, modespec, callback, options) { exports.runMode = function(string, modespec, callback, options) {
var mode = exports.getMode({indentUnit: 2}, modespec); var mode = exports.getMode({indentUnit: 2}, modespec);
var lines = splitLines(string), state = (options && options.state) || exports.startState(mode); var lines = splitLines(string), state = (options && options.state) || exports.startState(mode);
for (var i = 0, e = lines.length; i < e; ++i) { var context = {lines: lines, line: 0}
for (var i = 0, e = lines.length; i < e; ++i, ++context.line) {
if (i) callback("\n"); if (i) callback("\n");
var stream = new exports.StringStream(lines[i]); var stream = new exports.StringStream(lines[i], 4, context);
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);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>simplescrollbars.css</string> </value> <value> <string>simplescrollbars.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
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 + "\\b") : query; var searchFor = hasBoundary ? new RegExp("\\b" + query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") + "\\b") : query;
state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false, state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
{className: "CodeMirror-selection-highlight-scrollbar"}); {className: "CodeMirror-selection-highlight-scrollbar"});
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>matchesonscrollbar.css</string> </value> <value> <string>matchesonscrollbar.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
function getSearchCursor(cm, query, pos) { function getSearchCursor(cm, query, pos) {
// Heuristic: if the query string is all lowercase, do a case insensitive search. // Heuristic: if the query string is all lowercase, do a case insensitive search.
return cm.getSearchCursor(query, pos, queryCaseInsensitive(query)); return cm.getSearchCursor(query, pos, {caseFold: queryCaseInsensitive(query), multiline: true});
} }
function persistentDialog(cm, text, deflt, onEnter, onKeyDown) { function persistentDialog(cm, text, deflt, onEnter, onKeyDown) {
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
} }
var queryDialog = var queryDialog =
'Search: <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>'; '<span class="CodeMirror-search-label">Search:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
function startSearch(cm, state, query) { function startSearch(cm, state, query) {
state.queryText = query; state.queryText = query;
...@@ -117,6 +117,7 @@ ...@@ -117,6 +117,7 @@
var state = getSearchState(cm); var state = getSearchState(cm);
if (state.query) return findNext(cm, rev); if (state.query) return findNext(cm, rev);
var q = cm.getSelection() || state.lastQuery; var q = cm.getSelection() || state.lastQuery;
if (q instanceof RegExp && q.source == "x^") q = null
if (persistent && cm.openDialog) { if (persistent && cm.openDialog) {
var hiding = null var hiding = null
var searchNext = function(query, event) { var searchNext = function(query, event) {
...@@ -137,8 +138,7 @@ ...@@ -137,8 +138,7 @@
}; };
persistentDialog(cm, queryDialog, q, searchNext, function(event, query) { persistentDialog(cm, queryDialog, q, searchNext, function(event, query) {
var keyName = CodeMirror.keyName(event) var keyName = CodeMirror.keyName(event)
var cmd = CodeMirror.keyMap[cm.getOption("keyMap")][keyName] var extra = cm.getOption('extraKeys'), cmd = (extra && extra[keyName]) || CodeMirror.keyMap[cm.getOption("keyMap")][keyName]
if (!cmd) cmd = cm.getOption('extraKeys')[keyName]
if (cmd == "findNext" || cmd == "findPrev" || if (cmd == "findNext" || cmd == "findPrev" ||
cmd == "findPersistentNext" || cmd == "findPersistentPrev") { cmd == "findPersistentNext" || cmd == "findPersistentPrev") {
CodeMirror.e_stop(event); CodeMirror.e_stop(event);
...@@ -188,8 +188,8 @@ ...@@ -188,8 +188,8 @@
var replaceQueryDialog = var replaceQueryDialog =
' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>'; ' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">(Use /re/ syntax for regexp search)</span>';
var replacementQueryDialog = 'With: <input type="text" style="width: 10em" class="CodeMirror-search-field"/>'; var replacementQueryDialog = '<span class="CodeMirror-search-label">With:</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>';
var doReplaceConfirm = "Replace? <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>"; var doReplaceConfirm = '<span class="CodeMirror-search-label">Replace?</span> <button>Yes</button> <button>No</button> <button>All</button> <button>Stop</button>';
function replaceAll(cm, query, text) { function replaceAll(cm, query, text) {
cm.operation(function() { cm.operation(function() {
...@@ -205,7 +205,7 @@ ...@@ -205,7 +205,7 @@
function replace(cm, all) { function replace(cm, all) {
if (cm.getOption("readOnly")) return; if (cm.getOption("readOnly")) return;
var query = cm.getSelection() || getSearchState(cm).lastQuery; var query = cm.getSelection() || getSearchState(cm).lastQuery;
var dialogText = all ? "Replace all:" : "Replace:" var dialogText = '<span class="CodeMirror-search-label">' + (all ? 'Replace all:' : 'Replace:') + '</span>';
dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) { dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function(query) {
if (!query) return; if (!query) return;
query = parseQuery(query); query = parseQuery(query);
......
...@@ -34,11 +34,12 @@ ...@@ -34,11 +34,12 @@
}); });
function onCursorActivity(cm) { function onCursorActivity(cm) {
cm.operation(function() { update(cm); }); if (cm.state.markedSelection)
cm.operation(function() { update(cm); });
} }
function onChange(cm) { function onChange(cm) {
if (cm.state.markedSelection.length) if (cm.state.markedSelection && cm.state.markedSelection.length)
cm.operation(function() { clear(cm); }); cm.operation(function() { clear(cm); });
} }
...@@ -85,7 +86,7 @@ ...@@ -85,7 +86,7 @@
if (!array.length) return coverRange(cm, from, to); if (!array.length) return coverRange(cm, from, to);
var coverStart = array[0].find(), coverEnd = array[array.length - 1].find(); var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE || if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE ||
cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0) cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
return reset(cm); return reset(cm);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<ZopeData> <ZopeData>
<record id="1" aka="AAAAAAAAAAE="> <record id="1" aka="AAAAAAAAAAE=">
<pickle> <pickle>
<global name="File" module="OFS.Image"/> <global name="DTMLMethod" module="OFS.DTMLMethod"/>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
...@@ -15,16 +15,16 @@ ...@@ -15,16 +15,16 @@
<value> <string>tern.css</string> </value> <value> <string>tern.css</string> </value>
</item> </item>
<item> <item>
<key> <string>content_type</string> </key> <key> <string>_vars</string> </key>
<value> <string>text/css</string> </value> <value>
<dictionary/>
</value>
</item> </item>
<item> <item>
<key> <string>precondition</string> </key> <key> <string>globals</string> </key>
<value> <string></string> </value> <value>
</item> <dictionary/>
<item> </value>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -334,7 +334,11 @@ ...@@ -334,7 +334,11 @@
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");
ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip); var tooltip = ts.activeArgHints = makeTooltip(place.right + 1, place.bottom, tip)
setTimeout(function() {
tooltip.clear = onEditorActivity(cm, function() {
if (ts.activeArgHints == tooltip) closeArgHints(ts) })
}, 20)
} }
function parseFnType(text) { function parseFnType(text) {
...@@ -567,7 +571,7 @@ ...@@ -567,7 +571,7 @@
return {type: "part", return {type: "part",
name: data.name, name: data.name,
offsetLines: from.line, offsetLines: from.line,
text: doc.getRange(from, Pos(endLine, 0))}; text: doc.getRange(from, Pos(endLine, end.line == endLine ? null : 0))};
} }
// Generic utilities // Generic utilities
...@@ -604,24 +608,33 @@ ...@@ -604,24 +608,33 @@
} }
function clear() { function clear() {
cm.state.ternTooltip = null; cm.state.ternTooltip = null;
if (!tip.parentNode) return; if (tip.parentNode) fadeOut(tip)
cm.off("cursorActivity", clear); clearActivity()
cm.off('blur', clear);
cm.off('scroll', clear);
fadeOut(tip);
} }
var mouseOnTip = false, old = false; var mouseOnTip = false, old = false;
CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; }); CodeMirror.on(tip, "mousemove", function() { mouseOnTip = true; });
CodeMirror.on(tip, "mouseout", function(e) { CodeMirror.on(tip, "mouseout", function(e) {
if (!CodeMirror.contains(tip, e.relatedTarget || e.toElement)) { var related = e.relatedTarget || e.toElement
if (!related || !CodeMirror.contains(tip, related)) {
if (old) clear(); if (old) clear();
else mouseOnTip = false; else mouseOnTip = false;
} }
}); });
setTimeout(maybeClear, ts.options.hintDelay ? ts.options.hintDelay : 1700); setTimeout(maybeClear, ts.options.hintDelay ? ts.options.hintDelay : 1700);
cm.on("cursorActivity", clear); var clearActivity = onEditorActivity(cm, clear)
cm.on('blur', clear); }
cm.on('scroll', clear);
function onEditorActivity(cm, f) {
cm.on("cursorActivity", f)
cm.on("blur", f)
cm.on("scroll", f)
cm.on("setDoc", f)
return function() {
cm.off("cursorActivity", f)
cm.off("blur", f)
cm.off("scroll", f)
cm.off("setDoc", f)
}
} }
function makeTooltip(x, y, content) { function makeTooltip(x, y, content) {
...@@ -650,7 +663,11 @@ ...@@ -650,7 +663,11 @@
} }
function closeArgHints(ts) { function closeArgHints(ts) {
if (ts.activeArgHints) { remove(ts.activeArgHints); ts.activeArgHints = null; } if (ts.activeArgHints) {
if (ts.activeArgHints.clear) ts.activeArgHints.clear()
remove(ts.activeArgHints)
ts.activeArgHints = null
}
} }
function docValue(ts, doc) { function docValue(ts, doc) {
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>bin</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
# Combine existing list of authors with everyone known in git, sort, add header.
tail --lines=+3 AUTHORS > AUTHORS.tmp
git log --format='%aN' >> AUTHORS.tmp
echo -e "List of CodeMirror contributors. Updated before every release.\n" > AUTHORS
sort -u AUTHORS.tmp >> AUTHORS
rm -f AUTHORS.tmp
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>authors.sh</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/x-sh</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
#!/usr/bin/env node
// Compression helper for CodeMirror
//
// Example:
//
// bin/compress codemirror runmode javascript xml
//
// Will take lib/codemirror.js, addon/runmode/runmode.js,
// mode/javascript/javascript.js, and mode/xml/xml.js, run them though
// the online minifier at http://marijnhaverbeke.nl/uglifyjs, and spit
// out the result.
//
// bin/compress codemirror --local /path/to/bin/UglifyJS
//
// Will use a local minifier instead of the online default one.
//
// Script files are specified without .js ending. Prefixing them with
// their full (local) path is optional. So you may say lib/codemirror
// or mode/xml/xml to be more precise. In fact, even the .js suffix
// may be specified, if wanted.
"use strict";
var fs = require("fs");
function help(ok) {
console.log("usage: " + process.argv[1] + " [--local /path/to/uglifyjs] files...");
process.exit(ok ? 0 : 1);
}
var local = null, args = [], extraArgs = null, files = [], blob = "";
for (var i = 2; i < process.argv.length; ++i) {
var arg = process.argv[i];
if (arg == "--local" && i + 1 < process.argv.length) {
var parts = process.argv[++i].split(/\s+/);
local = parts[0];
extraArgs = parts.slice(1);
if (!extraArgs.length) extraArgs = ["-c", "-m"];
} else if (arg == "--help") {
help(true);
} else if (arg[0] != "-") {
files.push({name: arg, re: new RegExp("(?:\\/|^)" + arg + (/\.js$/.test(arg) ? "$" : "\\.js$"))});
} else help(false);
}
function walk(dir) {
fs.readdirSync(dir).forEach(function(fname) {
if (/^[_\.]/.test(fname)) return;
var file = dir + fname;
if (fs.statSync(file).isDirectory()) return walk(file + "/");
if (files.some(function(spec, i) {
var match = spec.re.test(file);
if (match) files.splice(i, 1);
return match;
})) {
if (local) args.push(file);
else blob += fs.readFileSync(file, "utf8");
}
});
}
walk("lib/");
walk("addon/");
walk("mode/");
if (!local && !blob) help(false);
if (files.length) {
console.log("Some specified files were not found: " +
files.map(function(a){return a.name;}).join(", "));
process.exit(1);
}
if (local) {
require("child_process").spawn(local, args.concat(extraArgs), {stdio: ["ignore", process.stdout, process.stderr]});
} else {
var data = new Buffer("js_code=" + require("querystring").escape(blob), "utf8");
var req = require("http").request({
host: "marijnhaverbeke.nl",
port: 80,
method: "POST",
path: "/uglifyjs",
headers: {"content-type": "application/x-www-form-urlencoded",
"content-length": data.length}
});
req.on("response", function(resp) {
resp.on("data", function (chunk) { process.stdout.write(chunk); });
});
req.end(data);
}
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>compress</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/octet-stream</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
#!/usr/bin/env node
process.exit(require("../test/lint").ok ? 0 : 1);
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>lint</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/octet-stream</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
#!/usr/bin/env node
var fs = require("fs"), child = require("child_process");
var number, bumpOnly;
for (var i = 2; i < process.argv.length; i++) {
if (process.argv[i] == "-bump") bumpOnly = true;
else if (/^\d+\.\d+\.\d+$/.test(process.argv[i])) number = process.argv[i];
else { console.log("Bogus command line arg: " + process.argv[i]); process.exit(1); }
}
if (!number) { console.log("Must give a version"); process.exit(1); }
function rewrite(file, f) {
fs.writeFileSync(file, f(fs.readFileSync(file, "utf8")), "utf8");
}
rewrite("src/edit/main.js", function(lib) {
return lib.replace(/CodeMirror\.version = "\d+\.\d+\.\d+"/,
"CodeMirror.version = \"" + number + "\"");
});
function rewriteJSON(pack) {
return pack.replace(/"version":\s*"\d+\.\d+\.\d+"/, "\"version\": \"" + number + "\"");
}
rewrite("package.json", rewriteJSON);
rewrite("doc/manual.html", function(manual) {
return manual.replace(/>version \d+\.\d+\.\d+<\/span>/, ">version " + number + "</span>");
});
if (bumpOnly) process.exit(0);
child.exec("bash bin/authors.sh", function(){});
rewrite("index.html", function(index) {
return index.replace(/\.zip">\d+\.\d+\.\d+<\/a>/,
".zip\">" + number + "</a>");
});
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>release</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/octet-stream</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
#!/usr/bin/env node
// Simple command-line code highlighting tool. Reads code from stdin,
// spits html to stdout. For example:
//
// echo 'function foo(a) { return a; }' | bin/source-highlight -s javascript
// bin/source-highlight -s
var fs = require("fs");
var CodeMirror = require("../addon/runmode/runmode.node.js");
require("../mode/meta.js");
var sPos = process.argv.indexOf("-s");
if (sPos == -1 || sPos == process.argv.length - 1) {
console.error("Usage: source-highlight -s language");
process.exit(1);
}
var lang = process.argv[sPos + 1].toLowerCase(), modeName = lang;
var found = CodeMirror.findModeByMIME(lang) || CodeMirror.findModeByName(lang)
if (found) {
modeName = found.mode
lang = found.mime
}
if (!CodeMirror.modes[modeName])
require("../mode/" + modeName + "/" + modeName + ".js");
function esc(str) {
return str.replace(/[<&]/g, function(ch) { return ch == "&" ? "&amp;" : "&lt;"; });
}
var code = fs.readFileSync("/dev/stdin", "utf8");
var curStyle = null, accum = "";
function flush() {
if (curStyle) process.stdout.write("<span class=\"" + curStyle.replace(/(^|\s+)/g, "$1cm-") + "\">" + esc(accum) + "</span>");
else process.stdout.write(esc(accum));
}
CodeMirror.runMode(code, lang, function(text, style) {
if (style != curStyle) {
flush();
curStyle = style; accum = text;
} else {
accum += text;
}
});
flush();
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>source-highlight</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/octet-stream</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
"use strict"
let version = process.argv[2]
let auth = process.argv[3]
if (!auth) {
console.log("Usage: upload-release.js [TAG] [github-user:password]")
process.exit(1)
}
require('child_process').exec("git --no-pager show -s --format='%s' " + version, (error, stdout) => {
if (error) throw error
let message = stdout.split("\n").slice(2)
message = message.slice(0, message.indexOf("-----BEGIN PGP SIGNATURE-----")).join("\n")
let req = require("https").request({
host: "api.github.com",
auth: auth,
headers: {"user-agent": "Release uploader"},
path: "/repos/codemirror/codemirror/releases",
method: "POST"
}, res => {
if (res.statusCode >= 300) {
console.error(res.statusMessage)
res.on("data", d => console.log(d.toString()))
res.on("end", process.exit(1))
}
})
req.write(JSON.stringify({
tag_name: version,
name: version,
body: message
}))
req.end()
})
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Cacheable__manager_id</string> </key>
<value> <string>http_cache</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>upload-release.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>demo</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Active Line Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../addon/selection/active-line.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
<div id=nav>
<a href="http://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="#">Active Line</a>
</ul>
</div>
<article>
<h2>Active Line Demo</h2>
<form><textarea id="code" name="code">
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"
xmlns:georss="http://www.georss.org/georss"
xmlns:twitter="http://api.twitter.com">
<channel>
<title>Twitter / codemirror</title>
<link>http://twitter.com/codemirror</link>
<atom:link type="application/rss+xml"
href="http://twitter.com/statuses/user_timeline/242283288.rss" rel="self"/>
<description>Twitter updates from CodeMirror / codemirror.</description>
<language>en-us</language>
<ttl>40</ttl>
<item>
<title>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This one
uses CodeMirror as its editor.</title>
<description>codemirror: http://cloud-ide.com &#8212; they're springing up like mushrooms. This
one uses CodeMirror as its editor.</description>
<pubDate>Thu, 17 Mar 2011 23:34:47 +0000</pubDate>
<guid>http://twitter.com/codemirror/statuses/48527733722058752</guid>
<link>http://twitter.com/codemirror/statuses/48527733722058752</link>
<twitter:source>web</twitter:source>
<twitter:place/>
</item>
<item>
<title>codemirror: Posted a description of the CodeMirror 2 internals at
http://codemirror.net/2/internals.html</title>
<description>codemirror: Posted a description of the CodeMirror 2 internals at
http://codemirror.net/2/internals.html</description>
<pubDate>Wed, 02 Mar 2011 12:15:09 +0000</pubDate>
<guid>http://twitter.com/codemirror/statuses/42920879788789760</guid>
<link>http://twitter.com/codemirror/statuses/42920879788789760</link>
<twitter:source>web</twitter:source>
<twitter:place/>
</item>
</channel>
</rss></textarea></form>
<script>
var nonEmpty = false;
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "application/xml",
styleActiveLine: true,
lineNumbers: true,
lineWrapping: true
});
function toggleSelProp() {
nonEmpty = !nonEmpty;
editor.setOption("styleActiveLine", {nonEmpty: nonEmpty});
var label = nonEmpty ? 'Disable nonEmpty option' : 'Enable nonEmpty option';
document.getElementById('toggleButton').innerText = label;
}
</script>
<p>Styling the current cursor line.</p>
<button onclick="toggleSelProp()" id="toggleButton">Enable <code>nonEmpty</code> option</button>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>activeline.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Any Word Completion Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<link rel="stylesheet" href="../addon/hint/show-hint.css">
<script src="../lib/codemirror.js"></script>
<script src="../addon/hint/show-hint.js"></script>
<script src="../addon/hint/anyword-hint.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<div id=nav>
<a href="http://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="#">Any Word Completion</a>
</ul>
</div>
<article>
<h2>Any Word Completion Demo</h2>
<form><textarea id="code" name="code">
(function() {
"use strict";
var WORD = /[\w$]+/g, RANGE = 500;
CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
var word = options && options.word || WORD;
var range = options && options.range || RANGE;
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
var start = cur.ch, end = start;
while (end < curLine.length && word.test(curLine.charAt(end))) ++end;
while (start && word.test(curLine.charAt(start - 1))) --start;
var curWord = start != end && curLine.slice(start, end);
var list = [], seen = {};
function scan(dir) {
var line = cur.line, end = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
for (; line != end; line += dir) {
var text = editor.getLine(line), m;
word.lastIndex = 0;
while (m = word.exec(text)) {
if ((!curWord || m[0].indexOf(curWord) == 0) && !seen.hasOwnProperty(m[0])) {
seen[m[0]] = true;
list.push(m[0]);
}
}
}
}
scan(-1);
scan(1);
return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
});
})();
</textarea></form>
<p>Press <strong>ctrl-space</strong> to activate autocompletion. The
completion uses
the <a href="../doc/manual.html#addon_anyword-hint">anyword-hint.js</a>
module, which simply looks at nearby words in the buffer and completes
to those.</p>
<script>
CodeMirror.commands.autocomplete = function(cm) {
cm.showHint({hint: CodeMirror.hint.anyword});
}
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
extraKeys: {"Ctrl-Space": "autocomplete"}
});
</script>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>anywordhint.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Bi-directional Text Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<script src="../mode/xml/xml.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
<div id=nav>
<a href="http://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="#">Bi-directional Text</a>
</ul>
</div>
<article>
<h2>Bi-directional Text Demo</h2>
<form><textarea id="code" name="code"><!-- Piece of the CodeMirror manual, 'translated' into Arabic by
Google Translate -->
<dl>
<dt id=option_value><code>value (string or Doc)</code></dt>
<dd>قيمة البداية المحرر. يمكن أن تكون سلسلة، أو. كائن مستند.</dd>
<dt id=option_mode><code>mode (string or object)</code></dt>
<dd>وضع الاستخدام. عندما لا تعطى، وهذا الافتراضي إلى الطريقة الاولى
التي تم تحميلها. قد يكون من سلسلة، والتي إما أسماء أو ببساطة هو وضع
MIME نوع المرتبطة اسطة. بدلا من ذلك، قد يكون من كائن يحتوي على
خيارات التكوين لواسطة، مع <code>name</code> الخاصية التي وضع أسماء
(على سبيل المثال <code>{name: "javascript", json: true}</code>).
صفحات التجريبي لكل وضع تحتوي على معلومات حول ما معلمات تكوين وضع
يدعمها. يمكنك أن تطلب CodeMirror التي تم تعريفها طرق وأنواع MIME
الكشف على <code>CodeMirror.modes</code>
و <code>CodeMirror.mimeModes</code> الكائنات. وضع خرائط الأسماء
الأولى لمنشئات الخاصة بهم، وخرائط لأنواع MIME 2 المواصفات
واسطة.</dd>
<dt id=option_theme><code>theme (string)</code></dt>
<dd>موضوع لنمط المحرر مع. يجب عليك التأكد من الملف CSS تحديد
المقابلة <code>.cm-s-[name]</code> يتم تحميل أنماط (انظر
<a href="../theme/"><code>theme</code></a> الدليل في التوزيع).
الافتراضي هو <code>"default"</code> ، والتي تم تضمينها في
الألوان <code>codemirror.css</code>. فمن الممكن استخدام فئات متعددة
في تطبيق السمات مرة واحدة على سبيل المثال <code>"foo bar"</code>
سيتم تعيين كل من <code>cm-s-foo</code> و <code>cm-s-bar</code>
الطبقات إلى المحرر.</dd>
</dl>
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "text/html",
lineNumbers: true
});
</script>
<p>Demonstration of bi-directional text support. See
the <a href="http://marijnhaverbeke.nl/blog/cursor-in-bidi-text.html">related
blog post</a> for more background.</p>
<p><strong>Note:</strong> There is
a <a href="https://github.com/codemirror/CodeMirror/issues/1757">known
bug</a> with cursor motion and mouse clicks in bi-directional lines
that are line wrapped.</p>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>bidi.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: B-Tree visualization</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<style type="text/css">
.lineblock { display: inline-block; margin: 1px; height: 5px; }
.CodeMirror {border: 1px solid #aaa; height: 400px}
</style>
<div id=nav>
<a href="http://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="#">B-Tree visualization</a>
</ul>
</div>
<article>
<h2>B-Tree visualization</h2>
<form><textarea id="code" name="code">type here, see a summary of the document b-tree below</textarea></form>
<div style="display: inline-block; height: 402px; overflow-y: auto" id="output"></div>
<script id="me">
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
lineWrapping: true
});
var updateTimeout;
editor.on("change", function(cm) {
clearTimeout(updateTimeout);
updateTimeout = setTimeout(updateVisual, 200);
});
updateVisual();
function updateVisual() {
var out = document.getElementById("output");
out.innerHTML = "";
function drawTree(out, node) {
if (node.lines) {
out.appendChild(document.createElement("div")).innerHTML =
"<b>leaf</b>: " + node.lines.length + " lines, " + Math.round(node.height) + " px";
var lines = out.appendChild(document.createElement("div"));
lines.style.lineHeight = "6px"; lines.style.marginLeft = "10px";
for (var i = 0; i < node.lines.length; ++i) {
var line = node.lines[i], lineElt = lines.appendChild(document.createElement("div"));
lineElt.className = "lineblock";
var gray = Math.min(line.text.length * 3, 230), col = gray.toString(16);
if (col.length == 1) col = "0" + col;
lineElt.style.background = "#" + col + col + col;
lineElt.style.width = Math.max(Math.round(line.height / 3), 1) + "px";
}
} else {
out.appendChild(document.createElement("div")).innerHTML =
"<b>node</b>: " + node.size + " lines, " + Math.round(node.height) + " px";
var sub = out.appendChild(document.createElement("div"));
sub.style.paddingLeft = "20px";
for (var i = 0; i < node.children.length; ++i)
drawTree(sub, node.children[i]);
}
}
drawTree(out, editor.getDoc());
}
function fillEditor() {
var sc = document.getElementById("me");
var doc = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "") + "\n";
doc += doc; doc += doc; doc += doc; doc += doc; doc += doc; doc += doc;
editor.setValue(doc);
}
</script>
<p><button onclick="fillEditor()">Add a lot of content</button></p>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>btree.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Multiple Buffer & Split View Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/css/css.js"></script>
<style type="text/css" id=style>
.CodeMirror {border: 1px solid black; height: 250px;}
</style>
<div id=nav>
<a href="http://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="#">Multiple Buffer & Split View</a>
</ul>
</div>
<article>
<h2>Multiple Buffer & Split View Demo</h2>
<div id=code_top></div>
<div>
Select buffer: <select id=buffers_top></select>
&nbsp; &nbsp; <button onclick="newBuf('top')">New buffer</button>
</div>
<div id=code_bot></div>
<div>
Select buffer: <select id=buffers_bot></select>
&nbsp; &nbsp; <button onclick="newBuf('bot')">New buffer</button>
</div>
<script id=script>
var sel_top = document.getElementById("buffers_top");
CodeMirror.on(sel_top, "change", function() {
selectBuffer(ed_top, sel_top.options[sel_top.selectedIndex].value);
});
var sel_bot = document.getElementById("buffers_bot");
CodeMirror.on(sel_bot, "change", function() {
selectBuffer(ed_bot, sel_bot.options[sel_bot.selectedIndex].value);
});
var buffers = {};
function openBuffer(name, text, mode) {
buffers[name] = CodeMirror.Doc(text, mode);
var opt = document.createElement("option");
opt.appendChild(document.createTextNode(name));
sel_top.appendChild(opt);
sel_bot.appendChild(opt.cloneNode(true));
}
function newBuf(where) {
var name = prompt("Name for the buffer", "*scratch*");
if (name == null) return;
if (buffers.hasOwnProperty(name)) {
alert("There's already a buffer by that name.");
return;
}
openBuffer(name, "", "javascript");
selectBuffer(where == "top" ? ed_top : ed_bot, name);
var sel = where == "top" ? sel_top : sel_bot;
sel.value = name;
}
function selectBuffer(editor, name) {
var buf = buffers[name];
if (buf.getEditor()) buf = buf.linkedDoc({sharedHist: true});
var old = editor.swapDoc(buf);
var linked = old.iterLinkedDocs(function(doc) {linked = doc;});
if (linked) {
// Make sure the document in buffers is the one the other view is looking at
for (var name in buffers) if (buffers[name] == old) buffers[name] = linked;
old.unlinkDoc(linked);
}
editor.focus();
}
function nodeContent(id) {
var node = document.getElementById(id), val = node.textContent || node.innerText;
val = val.slice(val.match(/^\s*/)[0].length, val.length - val.match(/\s*$/)[0].length) + "\n";
return val;
}
openBuffer("js", nodeContent("script"), "javascript");
openBuffer("css", nodeContent("style"), "css");
var ed_top = CodeMirror(document.getElementById("code_top"), {lineNumbers: true});
selectBuffer(ed_top, "js");
var ed_bot = CodeMirror(document.getElementById("code_bot"), {lineNumbers: true});
selectBuffer(ed_bot, "js");
</script>
<p>Demonstration of
using <a href="../doc/manual.html#linkedDoc">linked documents</a>
to provide a split view on a document, and
using <a href="../doc/manual.html#swapDoc"><code>swapDoc</code></a>
to use a single editor to display multiple documents.</p>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>buffers.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Mode-Changing Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/scheme/scheme.js"></script>
<style type="text/css">
.CodeMirror {border: 1px solid black;}
</style>
<div id=nav>
<a href="http://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-Changing</a>
</ul>
</div>
<article>
<h2>Mode-Changing Demo</h2>
<form><textarea id="code" name="code">
;; If there is Scheme code in here, the editor will be in Scheme mode.
;; If you put in JS instead, it'll switch to JS mode.
(define (double x)
(* x x))
</textarea></form>
<p>On changes to the content of the above editor, a (crude) script
tries to auto-detect the language used, and switches the editor to
either JavaScript or Scheme mode based on that.</p>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "scheme",
lineNumbers: true
});
var pending;
editor.on("change", function() {
clearTimeout(pending);
pending = setTimeout(update, 400);
});
function looksLikeScheme(code) {
return !/^\s*\(\s*function\b/.test(code) && /^\s*[;\(]/.test(code);
}
function update() {
editor.setOption("mode", looksLikeScheme(editor.getValue()) ? "scheme" : "javascript");
}
</script>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>changemode.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Closebrackets Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<script src="../addon/edit/closebrackets.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
</style>
<div id=nav>
<a href="http://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="#">Closebrackets</a>
</ul>
</div>
<article>
<h2>Closebrackets Demo</h2>
<form><textarea id="code" name="code">function Grid(width, height) {
this.width = width;
this.height = height;
this.cells = new Array(width * height);
}
Grid.prototype.valueAt = function(point) {
return this.cells[point.y * this.width + point.x];
};
Grid.prototype.setValueAt = function(point, value) {
this.cells[point.y * this.width + point.x] = value;
};
Grid.prototype.isInside = function(point) {
return point.x >= 0 && point.y >= 0 &&
point.x < this.width && point.y < this.height;
};
Grid.prototype.moveValue = function(from, to) {
this.setValueAt(to, this.valueAt(from));
this.setValueAt(from, undefined);
};</textarea></form>
<script type="text/javascript">
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {autoCloseBrackets: true});
</script>
</article>
<!doctype html>
<title>CodeMirror: Close-Tag Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<script src="../addon/edit/closetag.js"></script>
<script src="../addon/fold/xml-fold.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/css/css.js"></script>
<script src="../mode/htmlmixed/htmlmixed.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid #888; border-bottom: 1px solid #888;}
</style>
<div id=nav>
<a href="http://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="#">Close-Tag</a>
</ul>
</div>
<article>
<h2>Close-Tag Demo</h2>
<form><textarea id="code" name="code"><html</textarea></form>
<script type="text/javascript">
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: 'text/html',
autoCloseTags: true
});
</script>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>closetag.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Autocomplete Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<link rel="stylesheet" href="../addon/hint/show-hint.css">
<script src="../lib/codemirror.js"></script>
<script src="../addon/hint/show-hint.js"></script>
<script src="../addon/hint/javascript-hint.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/markdown/markdown.js"></script>
<div id=nav>
<a href="http://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="#">Autocomplete</a>
</ul>
</div>
<article>
<h2>Autocomplete Demo</h2>
<form><textarea id="code" name="code">
function getCompletions(token, context) {
var found = [], start = token.string;
function maybeAdd(str) {
if (str.indexOf(start) == 0) found.push(str);
}
function gatherCompletions(obj) {
if (typeof obj == "string") forEach(stringProps, maybeAdd);
else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
else if (obj instanceof Function) forEach(funcProps, maybeAdd);
for (var name in obj) maybeAdd(name);
}
if (context) {
// If this is a property, see if it belongs to some object we can
// find in the current environment.
var obj = context.pop(), base;
if (obj.className == "js-variable")
base = window[obj.string];
else if (obj.className == "js-string")
base = "";
else if (obj.className == "js-atom")
base = 1;
while (base != null && context.length)
base = base[context.pop().string];
if (base != null) gatherCompletions(base);
}
else {
// If not, just look in the window object and any local scope
// (reading into JS mode internals to get at the local variables)
for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
gatherCompletions(window);
forEach(keywords, maybeAdd);
}
return found;
}
</textarea></form>
<p>Press <strong>ctrl-space</strong> to activate autocompletion. Built
on top of the <a href="../doc/manual.html#addon_show-hint"><code>show-hint</code></a>
and <a href="../doc/manual.html#addon_javascript-hint"><code>javascript-hint</code></a>
addons.</p>
<form><textarea style="display: none" id="synonyms" name="synonyms">
Here, the completion use an asynchronous hinting functions to provide
synonyms for each words. If your browser support `Promises`, the
hinting function can also return one.
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
extraKeys: {"Ctrl-Space": "autocomplete"},
mode: {name: "javascript", globalVars: true}
});
if (typeof Promise !== undefined) {
var comp = [
["here", "hither"],
["asynchronous", "nonsynchronous"],
["completion", "achievement", "conclusion", "culmination", "expirations"],
["hinting", "advive", "broach", "imply"],
["function","action"],
["provide", "add", "bring", "give"],
["synonyms", "equivalents"],
["words", "token"],
["each", "every"],
]
function synonyms(cm, option) {
return new Promise(function(accept) {
setTimeout(function() {
var cursor = cm.getCursor(), line = cm.getLine(cursor.line)
var start = cursor.ch, end = cursor.ch
while (start && /\w/.test(line.charAt(start - 1))) --start
while (end < line.length && /\w/.test(line.charAt(end))) ++end
var word = line.slice(start, end).toLowerCase()
for (var i = 0; i < comp.length; i++) if (comp[i].indexOf(word) != -1)
return accept({list: comp[i],
from: CodeMirror.Pos(cursor.line, start),
to: CodeMirror.Pos(cursor.line, end)})
return accept(null)
}, 100)
})
}
var editor2 = CodeMirror.fromTextArea(document.getElementById("synonyms"), {
extraKeys: {"Ctrl-Space": "autocomplete"},
lineNumbers: true,
lineWrapping: true,
mode: "text/x-markdown",
hintOptions: {hint: synonyms}
})
}
</script>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>complete.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Emacs bindings demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<link rel="stylesheet" href="../addon/dialog/dialog.css">
<script src="../lib/codemirror.js"></script>
<script src="../mode/clike/clike.js"></script>
<script src="../keymap/emacs.js"></script>
<script src="../addon/edit/matchbrackets.js"></script>
<script src="../addon/comment/comment.js"></script>
<script src="../addon/dialog/dialog.js"></script>
<script src="../addon/search/searchcursor.js"></script>
<script src="../addon/search/search.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid #eee; border-bottom: 1px solid #eee;}
</style>
<div id=nav>
<a href="http://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="#">Emacs bindings</a>
</ul>
</div>
<article>
<h2>Emacs bindings demo</h2>
<form><textarea id="code" name="code">
#include "syscalls.h"
/* getchar: simple buffered version */
int getchar(void)
{
static char buf[BUFSIZ];
static char *bufp = buf;
static int n = 0;
if (n == 0) { /* buffer is empty */
n = read(0, buf, sizeof buf);
bufp = buf;
}
return (--n >= 0) ? (unsigned char) *bufp++ : EOF;
}
</textarea></form>
<p>The emacs keybindings are enabled by
including <a href="../keymap/emacs.js">keymap/emacs.js</a> and setting
the <code>keyMap</code> option to <code>"emacs"</code>. Because
CodeMirror's internal API is quite different from Emacs, they are only
a loose approximation of actual emacs bindings, though.</p>
<p>Also note that a lot of browsers disallow certain keys from being
captured. For example, Chrome blocks both Ctrl-W and Ctrl-N, with the
result that idiomatic use of Emacs keys will constantly close your tab
or open a new window.</p>
<script>
CodeMirror.commands.save = function() {
var elt = editor.getWrapperElement();
elt.style.background = "#def";
setTimeout(function() { elt.style.background = ""; }, 300);
};
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
mode: "text/x-csrc",
keyMap: "emacs"
});
</script>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>emacs.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<head>
<title>CodeMirror: Code Folding Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<link rel="stylesheet" href="../addon/fold/foldgutter.css" />
<script src="../lib/codemirror.js"></script>
<script src="../addon/fold/foldcode.js"></script>
<script src="../addon/fold/foldgutter.js"></script>
<script src="../addon/fold/brace-fold.js"></script>
<script src="../addon/fold/xml-fold.js"></script>
<script src="../addon/fold/indent-fold.js"></script>
<script src="../addon/fold/markdown-fold.js"></script>
<script src="../addon/fold/comment-fold.js"></script>
<script src="../mode/javascript/javascript.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../mode/python/python.js"></script>
<script src="../mode/markdown/markdown.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
</head>
<body>
<div id=nav>
<a href="http://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="#">Code Folding</a>
</ul>
</div>
<article>
<h2>Code Folding Demo</h2>
<form>
<div style="max-width: 50em; margin-bottom: 1em">JavaScript:<br>
<textarea id="code" name="code"></textarea></div>
<div style="max-width: 50em; margin-bottom: 1em">HTML:<br>
<textarea id="code-html" name="code-html"></textarea></div>
<div style="max-width: 50em">Python:<br>
<textarea id="code-python" name="code">
def foo():
do_some_stuff()
here
return None
class Bar:
__init__(self):
if True:
print("True")
else:
print("False")
this_code_makes_no_sense():
pass
# A comment</textarea></div>
<div style="max-width: 50em">Markdown:<br>
<textarea id="code-markdown" name="code"></textarea></div>
</form>
<script id="script">
/*
* Demonstration of code folding
*/
window.onload = function() {
var te = document.getElementById("code");
var sc = document.getElementById("script");
te.value = (sc.textContent || sc.innerText || sc.innerHTML).replace(/^\s*/, "");
sc.innerHTML = "";
var te_html = document.getElementById("code-html");
te_html.value = document.documentElement.innerHTML;
var te_python = document.getElementById("code-python");
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"
window.editor = CodeMirror.fromTextArea(te, {
mode: "javascript",
lineNumbers: true,
lineWrapping: true,
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
editor.foldCode(CodeMirror.Pos(13, 0));
window.editor_html = CodeMirror.fromTextArea(te_html, {
mode: "text/html",
lineNumbers: true,
lineWrapping: true,
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
editor_html.foldCode(CodeMirror.Pos(0, 0));
editor_html.foldCode(CodeMirror.Pos(21, 0));
window.editor_python = CodeMirror.fromTextArea(te_python, {
mode: "python",
lineNumbers: true,
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
window.editor_markdown = CodeMirror.fromTextArea(te_markdown, {
mode: "markdown",
lineNumbers: true,
lineWrapping: true,
extraKeys: {"Ctrl-Q": function(cm){ cm.foldCode(cm.getCursor()); }},
foldGutter: true,
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"]
});
};
</script>
</article>
</body>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>folding.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<!doctype html>
<title>CodeMirror: Full Screen Editing</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<link rel="stylesheet" href="../addon/display/fullscreen.css">
<link rel="stylesheet" href="../theme/night.css">
<script src="../lib/codemirror.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../addon/display/fullscreen.js"></script>
<div id=nav>
<a href="http://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="#">Full Screen Editing</a>
</ul>
</div>
<article>
<h2>Full Screen Editing</h2>
<form><textarea id="code" name="code" rows="5">
<dl>
<dt id="option_indentWithTabs"><code><strong>indentWithTabs</strong>: boolean</code></dt>
<dd>Whether, when indenting, the first N*<code>tabSize</code>
spaces should be replaced by N tabs. Default is false.</dd>
<dt id="option_electricChars"><code><strong>electricChars</strong>: boolean</code></dt>
<dd>Configures whether the editor should re-indent the current
line when a character is typed that might change its proper
indentation (only works if the mode supports indentation).
Default is true.</dd>
<dt id="option_specialChars"><code><strong>specialChars</strong>: RegExp</code></dt>
<dd>A regular expression used to determine which characters
should be replaced by a
special <a href="#option_specialCharPlaceholder">placeholder</a>.
Mostly useful for non-printing special characters. The default
is <code>/[\u0000-\u0019\u00ad\u200b\u2028\u2029\ufeff]/</code>.</dd>
<dt id="option_specialCharPlaceholder"><code><strong>specialCharPlaceholder</strong>: function(char) → Element</code></dt>
<dd>A function that, given a special character identified by
the <a href="#option_specialChars"><code>specialChars</code></a>
option, produces a DOM node that is used to represent the
character. By default, a red dot (<span style="color: red"></span>)
is shown, with a title tooltip to indicate the character code.</dd>
<dt id="option_rtlMoveVisually"><code><strong>rtlMoveVisually</strong>: boolean</code></dt>
<dd>Determines whether horizontal cursor movement through
right-to-left (Arabic, Hebrew) text is visual (pressing the left
arrow moves the cursor left) or logical (pressing the left arrow
moves to the next lower index in the string, which is visually
right in right-to-left text). The default is <code>false</code>
on Windows, and <code>true</code> on other platforms.</dd>
</dl>
</textarea></form>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
theme: "night",
extraKeys: {
"F11": function(cm) {
cm.setOption("fullScreen", !cm.getOption("fullScreen"));
},
"Esc": function(cm) {
if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
}
}
});
</script>
<p>Demonstration of
the <a href="../doc/manual.html#addon_fullscreen">fullscreen</a>
addon. Press <strong>F11</strong> when cursor is in the editor to
toggle full screen editing. <strong>Esc</strong> can also be used
to <i>exit</i> full screen editing.</p>
</article>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>fullscreen.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>hardwrap.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="DTMLDocument" module="OFS.DTMLDocument"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>__name__</string> </key>
<value> <string>indentwrap.html</string> </value>
</item>
<item>
<key> <string>_vars</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>globals</string> </key>
<value>
<dictionary/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment