[Libreoffice-commits] dev-tools.git: help3/xhpeditor

Olivier Hallot (via logerrit) logerrit at kemper.freedesktop.org
Mon Jun 7 16:50:50 UTC 2021


 help3/xhpeditor/cm/AUTHORS                                    |   84 +
 help3/xhpeditor/cm/CHANGELOG.md                               |  300 ++++
 help3/xhpeditor/cm/README.md                                  |    1 
 help3/xhpeditor/cm/addon/comment/comment.js                   |    4 
 help3/xhpeditor/cm/addon/dialog/dialog.js                     |    4 
 help3/xhpeditor/cm/addon/display/panel.js                     |   10 
 help3/xhpeditor/cm/addon/display/placeholder.js               |   15 
 help3/xhpeditor/cm/addon/edit/closebrackets.js                |   22 
 help3/xhpeditor/cm/addon/edit/closetag.js                     |    9 
 help3/xhpeditor/cm/addon/edit/continuelist.js                 |    6 
 help3/xhpeditor/cm/addon/edit/matchbrackets.js                |   28 
 help3/xhpeditor/cm/addon/fold/brace-fold.js                   |   13 
 help3/xhpeditor/cm/addon/hint/html-hint.js                    |    1 
 help3/xhpeditor/cm/addon/hint/javascript-hint.js              |    7 
 help3/xhpeditor/cm/addon/hint/show-hint.js                    |   87 -
 help3/xhpeditor/cm/addon/hint/sql-hint.js                     |    8 
 help3/xhpeditor/cm/addon/hint/xml-hint.js                     |   23 
 help3/xhpeditor/cm/addon/lint/javascript-lint.js              |    2 
 help3/xhpeditor/cm/addon/lint/lint.css                        |   24 
 help3/xhpeditor/cm/addon/lint/lint.js                         |   43 
 help3/xhpeditor/cm/addon/merge/merge.js                       |   16 
 help3/xhpeditor/cm/addon/mode/loadmode.js                     |   22 
 help3/xhpeditor/cm/addon/mode/multiplex.js                    |   13 
 help3/xhpeditor/cm/addon/mode/multiplex_test.js               |   16 
 help3/xhpeditor/cm/addon/mode/simple.js                       |    4 
 help3/xhpeditor/cm/addon/runmode/runmode-standalone.js        |  448 ++++--
 help3/xhpeditor/cm/addon/runmode/runmode.js                   |   16 
 help3/xhpeditor/cm/addon/runmode/runmode.node.js              |  396 +++--
 help3/xhpeditor/cm/addon/scroll/annotatescrollbar.js          |   10 
 help3/xhpeditor/cm/addon/search/jump-to-line.js               |    5 
 help3/xhpeditor/cm/addon/search/match-highlighter.js          |    6 
 help3/xhpeditor/cm/addon/search/search.js                     |    8 
 help3/xhpeditor/cm/addon/search/searchcursor.js               |    2 
 help3/xhpeditor/cm/addon/tern/tern.js                         |   46 
 help3/xhpeditor/cm/addon/wrap/hardwrap.js                     |   31 
 help3/xhpeditor/cm/demo/anywordhint.html                      |   24 
 help3/xhpeditor/cm/demo/closetag.html                         |    1 
 help3/xhpeditor/cm/demo/complete.html                         |    4 
 help3/xhpeditor/cm/demo/matchhighlighter.html                 |    2 
 help3/xhpeditor/cm/demo/mustache.html                         |    2 
 help3/xhpeditor/cm/demo/runmode-standalone.html               |   61 
 help3/xhpeditor/cm/demo/simplemode.html                       |    5 
 help3/xhpeditor/cm/demo/tern.html                             |   20 
 help3/xhpeditor/cm/demo/theme.html                            |    2 
 help3/xhpeditor/cm/demo/vim.html                              |   10 
 help3/xhpeditor/cm/doc/internals.html                         |    2 
 help3/xhpeditor/cm/doc/manual.html                            |  202 ++
 help3/xhpeditor/cm/doc/realworld.html                         |   18 
 help3/xhpeditor/cm/doc/releases.html                          |  211 ++-
 help3/xhpeditor/cm/doc/upgrade_v2.2.html                      |    2 
 help3/xhpeditor/cm/index.html                                 |   40 
 help3/xhpeditor/cm/keymap/emacs.js                            |  395 +++--
 help3/xhpeditor/cm/keymap/sublime.js                          |   18 
 help3/xhpeditor/cm/keymap/vim.js                              |  402 ++++-
 help3/xhpeditor/cm/lib/codemirror.css                         |   11 
 help3/xhpeditor/cm/lib/codemirror.js                          |  699 +++++-----
 help3/xhpeditor/cm/mode/asn.1/asn.1.js                        |    2 
 help3/xhpeditor/cm/mode/clike/clike.js                        |   20 
 help3/xhpeditor/cm/mode/clike/index.html                      |    2 
 help3/xhpeditor/cm/mode/clojure/clojure.js                    |    4 
 help3/xhpeditor/cm/mode/crystal/crystal.js                    |   12 
 help3/xhpeditor/cm/mode/css/css.js                            |  227 +--
 help3/xhpeditor/cm/mode/css/gss.html                          |    2 
 help3/xhpeditor/cm/mode/css/index.html                        |    6 
 help3/xhpeditor/cm/mode/cypher/cypher.js                      |    4 
 help3/xhpeditor/cm/mode/dart/dart.js                          |    4 
 help3/xhpeditor/cm/mode/dtd/dtd.js                            |    4 
 help3/xhpeditor/cm/mode/ebnf/ebnf.js                          |   14 
 help3/xhpeditor/cm/mode/erlang/erlang.js                      |    4 
 help3/xhpeditor/cm/mode/factor/factor.js                      |    2 
 help3/xhpeditor/cm/mode/factor/index.html                     |    4 
 help3/xhpeditor/cm/mode/fcl/index.html                        |   10 
 help3/xhpeditor/cm/mode/forth/index.html                      |    4 
 help3/xhpeditor/cm/mode/gas/gas.js                            |    4 
 help3/xhpeditor/cm/mode/gfm/test.js                           |    2 
 help3/xhpeditor/cm/mode/haml/haml.js                          |    2 
 help3/xhpeditor/cm/mode/htmlembedded/index.html               |    2 
 help3/xhpeditor/cm/mode/htmlmixed/htmlmixed.js                |    3 
 help3/xhpeditor/cm/mode/idl/idl.js                            |    2 
 help3/xhpeditor/cm/mode/index.html                            |    1 
 help3/xhpeditor/cm/mode/javascript/index.html                 |    6 
 help3/xhpeditor/cm/mode/javascript/javascript.js              |   75 -
 help3/xhpeditor/cm/mode/javascript/test.js                    |   16 
 help3/xhpeditor/cm/mode/jsx/jsx.js                            |    2 
 help3/xhpeditor/cm/mode/jsx/test.js                           |    7 
 help3/xhpeditor/cm/mode/julia/julia.js                        |   73 -
 help3/xhpeditor/cm/mode/lua/lua.js                            |    1 
 help3/xhpeditor/cm/mode/markdown/index.html                   |   24 
 help3/xhpeditor/cm/mode/markdown/markdown.js                  |   17 
 help3/xhpeditor/cm/mode/markdown/test.js                      |   22 
 help3/xhpeditor/cm/mode/meta.js                               |   13 
 help3/xhpeditor/cm/mode/modelica/modelica.js                  |    6 
 help3/xhpeditor/cm/mode/mscgen/mscgen.js                      |    8 
 help3/xhpeditor/cm/mode/mumps/mumps.js                        |    2 
 help3/xhpeditor/cm/mode/nginx/index.html                      |    4 
 help3/xhpeditor/cm/mode/nsis/nsis.js                          |    2 
 help3/xhpeditor/cm/mode/ntriples/index.html                   |    2 
 help3/xhpeditor/cm/mode/oz/oz.js                              |    4 
 help3/xhpeditor/cm/mode/pascal/pascal.js                      |   17 
 help3/xhpeditor/cm/mode/pegjs/pegjs.js                        |    6 
 help3/xhpeditor/cm/mode/perl/perl.js                          |    8 
 help3/xhpeditor/cm/mode/php/php.js                            |    6 
 help3/xhpeditor/cm/mode/powershell/index.html                 |    4 
 help3/xhpeditor/cm/mode/powershell/powershell.js              |    2 
 help3/xhpeditor/cm/mode/powershell/test.js                    |    2 
 help3/xhpeditor/cm/mode/protobuf/protobuf.js                  |    5 
 help3/xhpeditor/cm/mode/pug/pug.js                            |    2 
 help3/xhpeditor/cm/mode/puppet/puppet.js                      |    2 
 help3/xhpeditor/cm/mode/python/index.html                     |    2 
 help3/xhpeditor/cm/mode/python/python.js                      |   14 
 help3/xhpeditor/cm/mode/python/test.js                        |    6 
 help3/xhpeditor/cm/mode/r/r.js                                |    4 
 help3/xhpeditor/cm/mode/rpm/rpm.js                            |    8 
 help3/xhpeditor/cm/mode/ruby/index.html                       |    2 
 help3/xhpeditor/cm/mode/ruby/ruby.js                          |   41 
 help3/xhpeditor/cm/mode/rust/rust.js                          |    4 
 help3/xhpeditor/cm/mode/sas/sas.js                            |    2 
 help3/xhpeditor/cm/mode/sass/sass.js                          |    9 
 help3/xhpeditor/cm/mode/scheme/scheme.js                      |    6 
 help3/xhpeditor/cm/mode/shell/shell.js                        |   16 
 help3/xhpeditor/cm/mode/shell/test.js                         |   15 
 help3/xhpeditor/cm/mode/sieve/sieve.js                        |    2 
 help3/xhpeditor/cm/mode/soy/soy.js                            |  273 +++
 help3/xhpeditor/cm/mode/soy/test.js                           |   98 +
 help3/xhpeditor/cm/mode/sparql/sparql.js                      |   14 
 help3/xhpeditor/cm/mode/sql/sql.js                            |   12 
 help3/xhpeditor/cm/mode/stex/stex.js                          |    2 
 help3/xhpeditor/cm/mode/stylus/stylus.js                      |   10 
 help3/xhpeditor/cm/mode/tcl/tcl.js                            |    3 
 help3/xhpeditor/cm/mode/tiddlywiki/tiddlywiki.js              |    2 
 help3/xhpeditor/cm/mode/twig/index.html                       |    4 
 help3/xhpeditor/cm/mode/vb/index.html                         |    2 
 help3/xhpeditor/cm/mode/vbscript/vbscript.js                  |    4 
 help3/xhpeditor/cm/mode/velocity/velocity.js                  |    3 
 help3/xhpeditor/cm/mode/verilog/test.js                       |  170 ++
 help3/xhpeditor/cm/mode/verilog/verilog.js                    |  144 +-
 help3/xhpeditor/cm/mode/vue/index.html                        |    2 
 help3/xhpeditor/cm/mode/wast/index.html                       |   73 +
 help3/xhpeditor/cm/mode/wast/test.js                          |  424 ++++++
 help3/xhpeditor/cm/mode/wast/wast.js                          |  132 +
 help3/xhpeditor/cm/mode/xml/xml.js                            |    4 
 help3/xhpeditor/cm/mode/xquery/index.html                     |    2 
 help3/xhpeditor/cm/mode/yaml-frontmatter/yaml-frontmatter.js  |    6 
 help3/xhpeditor/cm/mode/yaml/yaml.js                          |    8 
 help3/xhpeditor/cm/package.json                               |    9 
 help3/xhpeditor/cm/rollup.config.js                           |   42 
 help3/xhpeditor/cm/src/addon/runmode/codemirror-standalone.js |   24 
 help3/xhpeditor/cm/src/addon/runmode/codemirror.node.js       |   21 
 help3/xhpeditor/cm/src/addon/runmode/runmode-standalone.js    |    2 
 help3/xhpeditor/cm/src/addon/runmode/runmode.node.js          |    2 
 help3/xhpeditor/cm/src/display/focus.js                       |    9 
 help3/xhpeditor/cm/src/display/operations.js                  |    3 
 help3/xhpeditor/cm/src/display/scrolling.js                   |   13 
 help3/xhpeditor/cm/src/display/selection.js                   |    7 
 help3/xhpeditor/cm/src/display/update_display.js              |    8 
 help3/xhpeditor/cm/src/display/update_line.js                 |    1 
 help3/xhpeditor/cm/src/edit/CodeMirror.js                     |    6 
 help3/xhpeditor/cm/src/edit/commands.js                       |    4 
 help3/xhpeditor/cm/src/edit/drop_events.js                    |    4 
 help3/xhpeditor/cm/src/edit/key_events.js                     |    2 
 help3/xhpeditor/cm/src/edit/main.js                           |    2 
 help3/xhpeditor/cm/src/edit/methods.js                        |   32 
 help3/xhpeditor/cm/src/edit/mouse_events.js                   |   17 
 help3/xhpeditor/cm/src/edit/options.js                        |    8 
 help3/xhpeditor/cm/src/input/ContentEditableInput.js          |   30 
 help3/xhpeditor/cm/src/input/TextareaInput.js                 |   10 
 help3/xhpeditor/cm/src/input/input.js                         |    2 
 help3/xhpeditor/cm/src/input/keymap.js                        |    9 
 help3/xhpeditor/cm/src/input/keynames.js                      |    2 
 help3/xhpeditor/cm/src/input/movement.js                      |    2 
 help3/xhpeditor/cm/src/line/highlight.js                      |    2 
 help3/xhpeditor/cm/src/line/line_data.js                      |    2 
 help3/xhpeditor/cm/src/line/spans.js                          |   12 
 help3/xhpeditor/cm/src/model/Doc.js                           |    6 
 help3/xhpeditor/cm/src/model/document_data.js                 |    1 
 help3/xhpeditor/cm/src/model/history.js                       |    6 
 help3/xhpeditor/cm/src/model/line_widget.js                   |    2 
 help3/xhpeditor/cm/src/model/mark_text.js                     |    2 
 help3/xhpeditor/cm/src/model/selection_updates.js             |    2 
 help3/xhpeditor/cm/src/util/bidi.js                           |    5 
 help3/xhpeditor/cm/src/util/browser.js                        |    2 
 help3/xhpeditor/cm/src/util/misc.js                           |    2 
 help3/xhpeditor/cm/test/annotatescrollbar.js                  |   55 
 help3/xhpeditor/cm/test/driver.js                             |   15 
 help3/xhpeditor/cm/test/emacs_test.js                         |   21 
 help3/xhpeditor/cm/test/index.html                            |    5 
 help3/xhpeditor/cm/test/lint.js                               |    3 
 help3/xhpeditor/cm/test/run.js                                |    4 
 help3/xhpeditor/cm/test/test.js                               |    4 
 help3/xhpeditor/cm/test/vim_test.js                           |  351 ++++-
 help3/xhpeditor/cm/theme/abbott.css                           |  268 +++
 help3/xhpeditor/cm/theme/solarized.css                        |    2 
 help3/xhpeditor/cm/theme/zenburn.css                          |    2 
 193 files changed, 5474 insertions(+), 1634 deletions(-)

New commits:
commit 3487affff835b8ed828cc998b2f7f01318f80d3b
Author:     Olivier Hallot <olivier.hallot at libreoffice.org>
AuthorDate: Mon Jun 7 12:55:01 2021 -0300
Commit:     Olivier Hallot <olivier.hallot at libreoffice.org>
CommitDate: Mon Jun 7 18:50:28 2021 +0200

    Update codemirror editor to 5.61.1
    
    Change-Id: Ie974339e17f5d81533d84e31c98ec49e2efb23f2
    Reviewed-on: https://gerrit.libreoffice.org/c/dev-tools/+/116790
    Tested-by: Olivier Hallot <olivier.hallot at libreoffice.org>
    Reviewed-by: Olivier Hallot <olivier.hallot at libreoffice.org>

diff --git a/help3/xhpeditor/cm/AUTHORS b/help3/xhpeditor/cm/AUTHORS
index 77952af..a8ded26 100644
--- a/help3/xhpeditor/cm/AUTHORS
+++ b/help3/xhpeditor/cm/AUTHORS
@@ -10,29 +10,35 @@ Abhishek Gahlot
 Adam Ahmed
 Adam King
 Adam Particka
+Adam Wight
 adanlobato
 Adán Lobato
 Aditya Toshniwal
 Adrian Aichner
 Adrian Heine
+Adrian Kunz
 Adrien Bertrand
 aeroson
 Ahmad Amireh
 Ahmad M. Zawawi
 ahoward
+Ajin Abraham
 Akeksandr Motsjonov
 Alasdair Smith
 AlbertHilb
 Alberto González Palomo
 Alberto Pose
 Albert Xing
+Alexander Marks
 Alexander Pavlov
 Alexander Schepanovski
 Alexander Shvets
 Alexander Solovyov
 Alexandre Bique
+Alex Churchill
 alexey-k
 Alex Piggott
+Alf Eaton
 Aliaksei Chapyzhenka
 Allen Sarkisyan
 Ami Fischman
@@ -97,6 +103,9 @@ Bastian Müller
 belhaj
 Bem Jones-Bey
 benbro
+Benedikt Meurer
+benhormann
+Ben Hormann
 Beni Cherniavsky-Paskin
 Benjamin DeCoste
 Benjamin Young
@@ -108,6 +117,7 @@ Bert Chang
 Bharad
 BigBlueHat
 Billy Moon
+Bin Ni
 binny
 Bjorn Hansen
 B Krishna Chaitanya
@@ -117,12 +127,14 @@ Bo
 boomyjee
 Bo Peng
 borawjm
+Boris K
 Brad Metcalf
 Brandon Frohs
 Brandon Wamboldt
 Bret Little
 Brett Zamir
 Brian Grinstead
+BrianHung
 Brian Sletten
 brrd
 Bruce Mitchener
@@ -134,6 +146,7 @@ Calin Barbat
 callodacity
 Camilo Roca
 Casey Klebba
+cBiscuit87
 César González Íñiguez
 Chad Jolly
 Chandra Sekhar Pydi
@@ -160,15 +173,18 @@ Christopher Pfohl
 Christopher Wallis
 Chunliang Lyu
 ciaranj
+clone-it
 clso
 CodeAnimal
 CodeBitt
 coderaiser
 Cole R Lawrence
 ComFreek
+Cornelius Weig
 Cristian Prieto
 Curran Kelleher
 Curtis Gagliardi
+d8888
 dagsta
 daines
 Dale Jung
@@ -196,6 +212,8 @@ David Barnett
 David H. Bronke
 David Mignot
 David Pathakjee
+David R. Myers
+David Rodrigues
 David Santana
 David Vázquez
 David Whittington
@@ -208,6 +226,7 @@ Dick Choi
 Diego Fernandez
 dignifiedquire
 Dimage Sapelkin
+Dinindu D. Wanniarachchi
 dmaclach
 Dmitry Kiselyov
 domagoj412
@@ -223,11 +242,13 @@ Dror BG
 Duncan Lilley
 duralog
 dwelle
+Ealton
 eborden
 edoroshenko
 edsharp
 ekhaled
 Elisée
+Elmar Peise
 elpnt
 Emmanuel Schanzer
 Enam Mijbah Noor
@@ -235,6 +256,7 @@ Eric Allam
 Eric Bogard
 Erik Demaine
 Erik Welander
+erosman
 eustas
 Evan Minsk
 Fabien Dubosson
@@ -245,6 +267,7 @@ Fauntleroy
 fbuchinger
 feizhang365
 Felipe Lalanne
+Felipe S. S. Schneider
 Felix Raab
 ficristo
 Filip Noetzel
@@ -253,6 +276,7 @@ Filype Pereira
 finalfantasia
 flack
 Florian Felten
+Fons van der Plas
 Forbes Lindesay
 ForbesLindesay
 Ford_Lawnmower
@@ -299,6 +323,7 @@ Hakan Tunc
 Hanno Fellmann
 Hans Engel
 Hanzhao Deng
+Haoran Yu
 Harald Schilly
 Hardest
 Harshvardhan Gupta
@@ -306,7 +331,9 @@ Hasan Delibaş
 Hasan Karahan
 Heanes
 Hector Oswaldo Caballero
+Hein Htat
 Hélio
+Hendrik Erz
 Hendrik Wallbaum
 Henrik Haugbølle
 Herculano Campos
@@ -314,10 +341,14 @@ hidaiy
 Hiroyuki Makino
 hitsthings
 Hocdoc
+Howard
+Howard Jing
 Hugues Malphettes
 Ian Beck
 Ian Davies
 Ian Dickinson
+Ian Henderson
+ianhi
 Ian Rose
 Ian Wehrman
 Ian Wetherbee
@@ -327,14 +358,20 @@ idleberg
 Igor Petruk
 ilvalle
 Ilya Kharlamov
+Ilya Zverev
 Ingo Richter
+Intervue
 Irakli Gozalishvili
+iteriani
 Ivan Kurnosov
 Ivoah
+Jack Douglas
 Jacob Lee
 Jaimin
 Jake Peyser
+Jakob Kummerow
 Jakob Miland
+Jakub T. Jankiewicz
 Jakub Vrana
 Jakub Vrána
 James Campos
@@ -361,6 +398,7 @@ Jason Johnston
 Jason San Jose
 Jason Siefken
 Jayaprabhakar
+Jay Contonio
 Jaydeep Solanki
 Jean Boussier
 Jeff Blaisdell
@@ -378,9 +416,11 @@ jochenberger
 Jochen Berger
 Joel Einbinder
 joelpinheiro
+Joe Predham
 joewalsh
 Johan Ask
 Johannes
+John Chen
 John Connor
 John-David Dalton
 John Engler
@@ -394,12 +434,14 @@ Jonas Helfer
 Jonathan Dierksen
 Jonathan Hart
 Jonathan Malmaud
+Jonathan Rascher
 Jon Gacnik
 jongalloway
 Jon Malmaud
 Jon Sangster
 Joo
 Joost-Wim Boekesteijn
+José dBruxelles
 Joseph Pecoraro
 Josh Barnes
 Josh Cohen
@@ -421,6 +463,7 @@ jwallers at gmail.com
 kaniga
 karevn
 Karol
+Kaushik Kulkarni
 Kayur Patel
 Kazuhito Hokamura
 kcwiakala
@@ -435,14 +478,17 @@ Kevin Muret
 Kevin Sawicki
 Kevin Ushey
 Kier Darby
+Kim-Anh Tran
 Klaus Silveira
 Koh Zi Han, Cliff
 komakino
+Konstantin Chernenko
 Konstantin Lopuhin
 koops
 Kris Ciccarello
 ks-ifware
 kubelsmieci
+kvncp
 KwanEsq
 Kyle Kelley
 KyleMcNutt
@@ -462,6 +508,7 @@ Liam Newman
 Libo Cannici
 Lior Goldberg
 Lior Shub
+lishid
 LloydMilligan
 LM
 lochel
@@ -470,9 +517,11 @@ Lorenzo Simionato
 Lorenzo Stoakes
 Louis Mauchet
 Luca Fabbri
+Lucas Buchala
 Luciano Longo
 Luciano Santana
 Lu Fangjian
+Łukasz Wielgus
 Luke Browning
 Luke Granger-Brown
 Luke Stagner
@@ -487,6 +536,7 @@ Manuel Rego Casasnovas
 Marat Dreizin
 Marcel Gerber
 Marcelo Camargo
+Marc Espín
 Marco Aurélio
 Marco Munizaga
 Marcus Bointon
@@ -495,6 +545,7 @@ Marijn Haverbeke
 Mário Gonçalves
 Mario Pietsch
 Mark Anderson
+Mark Boyes
 Mark Dalgleish
 Mark Hamstra
 Mark Lentczner
@@ -508,13 +559,16 @@ Martin Hasoň
 Martin Hunt
 Martin Laine
 Martin Zagora
+Masahiro MATAYOSHI
 Mason Malone
 Mateusz Paprocki
 Mathias Bynens
 mats cronqvist
+Matt Diehl
 Matt Gaide
 Matthew Bauer
 Matthew Beale
+Matthew Casperson
 matthewhayes
 Matthew Rathbone
 Matthew Suozzo
@@ -535,11 +589,13 @@ Max Xiantu
 mbarkhau
 McBrainy
 mce2
+Mélanie Chauvel
 melpon
 meshuamam
 Metatheos
 Micah Dubinko
 Michael
+Michael Chirico
 Michael Goderbauer
 Michael Grey
 Michael Kaminsky
@@ -567,6 +623,7 @@ Miraculix87
 misfo
 mkaminsky11
 mloginov
+mlsad3
 Moritz Schubotz (physikerwelt)
 Moritz Schwörer
 Moshe Wajnberg
@@ -577,6 +634,7 @@ Mu-An ✌️ Chiou
 Mu-An Chiou
 mzabuawala
 Narciso Jaramillo
+nathanlesage
 Nathan Williams
 ndr
 Neil Anderson
@@ -603,6 +661,7 @@ Nikolaj Kappler
 Nikolay Kostov
 nilp0inter
 Nils Knappmeier
+Nina Pypchenko
 Nisarg Jhaveri
 nlwillia
 noragrossman
@@ -613,6 +672,7 @@ Olivia Ytterbrink
 Opender Singh
 opl-
 Oreoluwa Onatemowo
+orionlee
 oscar.lofwenhamn
 Oskar Segersvärd
 ossdev
@@ -628,11 +688,13 @@ paris
 Paris
 Paris Kasidiaris
 Patil Arpith
+Patrick Kettner
 Patrick Stoica
 Patrick Strawderman
 Paul Garvin
 Paul Ivanov
 Paul Masson
+Paul Schmidt
 Pavel
 Pavel Feldman
 Pavel Petržela
@@ -643,12 +705,15 @@ peter
 Peter Flynn
 peterkroon
 Peter Kroon
+Peter László
+Phil DeJarnett
 Philipp A
 Philipp Markovics
 Philip Stadermann
 Pi Delport
 Pierre Gerold
 Pieter Ouwerkerk
+Piyush
 Pontus Melke
 prasanthj
 Prasanth J
@@ -656,6 +721,7 @@ Prayag Verma
 prendota
 Prendota
 Qiang Li
+quiddity-wp
 Radek Piórkowski
 Rahul
 Rahul Anand
@@ -683,10 +749,14 @@ Robert Crossfield
 Robert Martin
 Roberto Abdelkader Martínez Pérez
 robertop23
+Roberto Vidal
 Robert Plummer
+Roman Frolov
+Roman Janusz
 Rrandom
 Rrrandom
 Ruslan Osmanov
+rvalavicius
 Ryan Pangrle
 Ryan Petrello
 Ryan Prior
@@ -713,6 +783,7 @@ Scott Aikin
 Scott Feeney
 Scott Goodhew
 Seb35
+Sebastian Ślepowroński
 Sebastian Wilzbach
 Sebastian Zaha
 Seren D
@@ -730,9 +801,12 @@ Shiv Deepak
 Shmuel Englard
 Shubham Jain
 Siamak Mokhtari
+Siddhartha Gunti
 silverwind
 Simon Edwards
+Simon Huber
 sinkuu
+Slava Rozhnev
 snasa
 soliton4
 sonson
@@ -765,6 +839,7 @@ Takuya Matsuyama
 Tarmil
 T. Brandon Ashley
 TDaglis
+Teja
 tel
 Tentone
 tfjgeorge
@@ -772,6 +847,7 @@ Thaddee Tyl
 thanasis
 TheHowl
 themrmax
+Thiemo Kreuz
 think
 Thomas Brouard
 Thomas Dvornik
@@ -780,13 +856,16 @@ thomasmaclean
 Thomas Schmid
 Tim Alby
 Tim Baumann
+Tim Gates
 Timothy Farrell
 Timothy Gu
 Timothy Hatcher
+Tim van der Lippe
 Tobias Bertelsen
 TobiasBg
 Todd Berman
 Todd Kennedy
+tokafew420
 Tomas-A
 Tomas Varaneckas
 Tom Erik Støwer
@@ -795,6 +874,7 @@ Tom MacWright
 Tom McLaughlin
 Tony Jian
 tophf
+Torben Bundt
 Torgeir Thoresen
 totalamd
 Travis Heppe
@@ -808,6 +888,7 @@ Tyler Makaro
 Vadim Dyachenko
 Vadzim Ramanenka
 Vaibhav Sagar
+vamshi.revu
 VapidWorx
 Vestimir Markov
 vf
@@ -832,6 +913,8 @@ wonderboyjon
 Wu Cheng-Han
 Xavier Mendez
 Yang Guo
+Yash Singh
+Yash-Singh1
 Yassin N. Hassan
 YNH Webdev
 yoongu
@@ -840,6 +923,7 @@ Yuvi Panda
 Yvonnick Esnault
 Zac Anger
 Zachary Dremann
+ZeeshanNoor
 Zeno Rocha
 Zhang Hao
 Ziv
diff --git a/help3/xhpeditor/cm/CHANGELOG.md b/help3/xhpeditor/cm/CHANGELOG.md
index 4adfb8b..4145ff4 100644
--- a/help3/xhpeditor/cm/CHANGELOG.md
+++ b/help3/xhpeditor/cm/CHANGELOG.md
@@ -1,3 +1,285 @@
+## 5.61.1 (2021-05-20)
+
+### Bug fixes
+
+Fix a bug where changing the editor's document could confuse text-direction management.
+
+Fix a bug in horizontally scrolling the cursor into view.
+
+Optimize adding lots of marks in a single transaction.
+
+[simple mode addon](https://codemirror.net/demo/simplemode.html): Support regexps with a unicode flag.
+
+[javascript mode](https://codemirror.net/mode/javascript/index.html): Add support for TypeScript template string types, improve integration with JSX mode.
+
+## 5.61.0 (2021-04-20)
+
+### Bug fixes
+
+Improve support for being in a shadow DOM in contenteditable mode.
+
+Prevent line number from being read by screen readers.
+
+[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): Fix a crash caused by a race condition.
+
+[javascript mode](https://codemirror.net/mode/javascript/): Improve scope tracking.
+
+### New features
+
+The library now emits an `"updateGutter"` event when the gutter width changes.
+
+[emacs bindings](https://codemirror.net/demo/emacs.html): Provide named commands for all bindings.
+
+## 5.60.0 (2021-03-20)
+
+### Bug fixes
+
+Fix autofocus feature in contenteditable mode.
+
+[simple mode addon](https://codemirror.net/demo/simplemode.html): Fix a null-dereference crash.
+
+[multiplex addon](https://codemirror.net/demo/multiplex.html): Make it possible to use `parseDelimiters` when both delimiters are the same.
+
+[julia mode](https://codemirror.net/mode/julia/): Fix a lockup bug.
+
+### New features
+
+`setSelections` now allows ranges to omit the `head` property when it is equal to `anchor`.
+
+[sublime bindings](https://codemirror.net/demo/sublime.html): Add support for reverse line sorting.
+
+## 5.59.4 (2021-02-24)
+
+### Bug fixes
+
+Give the scrollbar corner filler a background again, to prevent content from peeping through between the scrollbars.
+
+## 5.59.3 (2021-02-20)
+
+### Bug fixes
+
+Don't override the way zero-with non-joiners are rendered.
+
+Fix an issue where resetting the history cleared the `undoDepth` option's value.
+
+[vim bindings](https://codemirror.net/demo/vim.html): Fix substitute command when joining and splitting lines, fix global command when line number change, add support for `:vglobal`, properly treat caps lock as a modifier key.
+
+## 5.59.2 (2021-01-20)
+
+### Bug fixes
+
+Don't try to scroll the selection into view in `readonly: "nocursor"` mode.
+
+[closebrackets addon](https://codemirror.net/doc/manual.html#addon_closebrackets): Fix a regression in the behavior of pressing enter between brackets.
+
+[javascript mode](https://codemirror.net/mode/javascript/): Fix an infinite loop on specific syntax errors in object types.
+
+various modes: Fix inefficient RegExp matching.
+
+## 5.59.1 (2020-12-31)
+
+### Bug fixes
+
+Fix an issue where some Chrome browsers were detected as iOS.
+
+## 5.59.0 (2020-12-20)
+
+### Bug fixes
+
+Fix platform detection on recent iPadOS.
+
+[lint addon](https://codemirror.net/doc/manual.html#addon_lint): Don't show duplicate messages for a given line.
+
+[clojure mode](https://codemirror.net/mode/clojure/index.html): Fix regexp that matched in exponential time for some inputs.
+
+[hardwrap addon](https://codemirror.net/doc/manual.html#addon_hardwrap): Improve handling of words that are longer than the line length.
+
+[matchbrackets addon](https://codemirror.net/doc/manual.html#addon_matchbrackets): Fix leaked event handler on disabling the addon.
+
+### New features
+
+[search addon](https://codemirror.net/demo/search.html): Make it possible to configure the search addon to show the dialog at the bottom of the editor.
+
+## 5.58.3 (2020-11-19)
+
+### Bug fixes
+
+Suppress quick-firing of blur-focus events when dragging and clicking on Internet Explorer.
+
+Fix the `insertAt` option to `addLineWidget` to actually allow the widget to be placed after all widgets for the line.
+
+[soy mode](https://codemirror.net/mode/soy/): Support `@Attribute` and element composition.
+
+[shell mode](https://codemirror.net/mode/shell/): Support heredoc quoting.
+
+## 5.58.2 (2020-10-23)
+
+### Bug fixes
+
+Fix a bug where horizontally scrolling the cursor into view sometimes failed with a non-fixed gutter.
+
+[julia mode](https://codemirror.net/mode/julia/): Fix an infinite recursion bug.
+
+## 5.58.1 (2020-09-23)
+
+### Bug fixes
+
+[placeholder addon](https://codemirror.net/doc/manual.html#addon_placeholder): Remove arrow function that ended up in the code.
+
+## 5.58.0 (2020-09-21)
+
+### Bug fixes
+
+Make backspace delete by code point, not glyph.
+
+Suppress flickering focus outline when clicking on scrollbars in Chrome.
+
+Fix a bug that prevented attributes added via `markText` from showing up unless the span also had some other styling.
+
+Suppress cut and paste context menu entries in readonly editors in Chrome.
+
+[placeholder addon](https://codemirror.net/doc/manual.html#addon_placeholder): Update placeholder visibility during composition.
+
+### New features
+
+Make it less cumbersome to style new lint message types.
+
+[vim bindings](https://codemirror.net/demo/vim.html): Support black hole register, `gn` and `gN`
+
+## 5.57.0 (2020-08-20)
+
+### Bug fixes
+
+Fix issue that broke binding the macOS Command key.
+
+[comment addon](https://codemirror.net/doc/manual.html#addon_comment): Keep selection in front of inserted markers when adding a block comment.
+
+[css mode](https://codemirror.net/mode/css/): Recognize more properties and value names.
+
+[annotatescrollbar addon](https://codemirror.net/doc/manual.html#addon_annotatescrollbar): Don't hide matches in collapsed content.
+
+### New features
+
+[vim bindings](https://codemirror.net/demo/vim.html): Support tag text objects in xml and html modes.
+
+## 5.56.0 (2020-07-20)
+
+### Bug fixes
+
+Line-wise pasting was fixed on Chrome Windows.
+
+[wast mode](https://codemirror.net/mode/wast/): Follow standard changes.
+
+[soy mode](https://codemirror.net/mode/soy/): Support import expressions, template type, and loop indices.
+
+[sql-hint addon](https://codemirror.net/doc/manual.html#addon_sql-hint): Improve handling of double quotes.
+
+### New features
+
+[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): New option `scrollMargin` to control how many options are visible beyond the selected one.
+
+[hardwrap addon](https://codemirror.net/doc/manual.html#addon_hardwrap): New option `forceBreak` to disable breaking of words that are longer than a line.
+
+## 5.55.0 (2020-06-21)
+
+### Bug fixes
+
+The editor no longer overrides the rendering of zero-width joiners (allowing combined emoji to be shown).
+
+[vim bindings](https://codemirror.net/demo/vim.html): Fix an issue where the `vim-mode-change` event was fired twice.
+
+[javascript mode](https://codemirror.net/mode/javascript/): Only allow `-->`-style comments at the start of a line.
+
+[julia mode](https://codemirror.net/mode/julia/): Improve indentation.
+
+[pascal mode](https://codemirror.net/mode/pascal/index.html): Recognize curly bracket comments.
+
+[runmode addon](https://codemirror.net/doc/manual.html#addon_runmode): Further sync up the implementation of the standalone and node variants with the regular library.
+
+### New features
+
+[loadmode addon](https://codemirror.net/doc/manual.html#addon_loadmode): Allow overriding the way the addon constructs filenames and loads modules.
+
+## 5.54.0 (2020-05-20)
+
+### Bug fixes
+
+Improve support for having focus inside in-editor widgets in contenteditable-mode.
+
+Fix issue where the scroll position could jump when clicking on a selection in Chrome.
+
+[python mode](https://codemirror.net/mode/python/): Better format string support.
+
+[javascript mode](https://codemirror.net/mode/javascript/): Improve parsing of private properties and class fields.
+
+[matchbrackets addon](https://codemirror.net/doc/manual.html#addon_matchbrackets): Disable highlighting when the editor doesn't have focus.
+
+### New features
+
+[runmode addon](https://codemirror.net/doc/manual.html#addon_runmode): Properly support for cross-line lookahead.
+
+[vim bindings](https://codemirror.net/demo/vim.html): Allow Ex-Commands with non-word names.
+
+[gfm mode](https://codemirror.net/mode/gfm/): Add a `fencedCodeBlockDefaultMode` option.
+
+## 5.53.2 (2020-04-21)
+
+### Bug fixes
+
+[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): Fix a regression that broke completion picking.
+
+## 5.53.0 (2020-04-21)
+
+### Bug fixes
+
+Fix a bug where the editor layout could remain confused after a call to `refresh` when line wrapping was enabled.
+
+[dialog addon](https://codemirror.net/doc/manual.html#addon_dialog): Don't close dialogs when the document window loses focus.
+
+[merge addon](https://codemirror.net/doc/manual.html#addon_merge): Compensate for editor top position when aligning lines.
+
+[vim bindings](https://codemirror.net/demo/vim.html): Improve EOL handling.
+
+[emacs bindings](https://codemirror.net/demo/emacs.html): Include default keymap as a fallback.
+
+[julia mode](https://codemirror.net/mode/julia/): Fix an infinite loop bug.
+
+[show-hint addon](https://codemirror.net/doc/manual.html#addon_show-hint): Scroll cursor into view when picking a completion.
+
+### New features
+
+New option: [`screenReaderLabel`](https://codemirror.net/doc/manual.html#option_screenReaderLabel) to add a label to the editor.
+
+New mode: [wast](https://codemirror.net/mode/wast/).
+
+## 5.52.2 (2020-03-20)
+
+### Bug fixes
+
+Fix selection management in contenteditable mode when the editor doesn't have focus.
+
+Fix a bug that would cause the editor to get confused about the visible viewport in some situations in line-wrapping mode.
+
+[markdown mode](https://codemirror.net/mode/markdown/): Don't treat single dashes as setext header markers.
+
+[zenburn theme](https://codemirror.net/demo/theme.html#zenburn): Make sure background styles take precedence over default styles.
+
+[css mode](https://codemirror.net/mode/css/): Recognize a number of new properties.
+
+## 5.52.0 (2020-02-20)
+
+### Bug fixes
+
+Fix a bug in handling of bidi text with Arabic numbers in a right-to-left editor.
+
+Fix a crash when combining file drop with a `"beforeChange"` filter.
+
+Prevent issue when passing negative coordinates to `scrollTo`.
+
+### New features
+
+[lint](https://codemirror.net/doc/manual.html#addon_lint) and [tern](https://codemirror.net/demo/tern.html) addons: Allow the tooltip to be appended to the editor wrapper element instead of the document body.
+
 ## 5.51.0 (2020-01-20)
 
 ### Bug fixes
@@ -12,7 +294,7 @@ Make sure `clearHistory` clears the history in all linked docs with a shared his
 
 ### New features
 
-[vim bindings](https://codemirror.net/demo/vim.html): Support `gi`, gI`, and `gJ`.
+[vim bindings](https://codemirror.net/demo/vim.html): Support `gi`, `gI`, and `gJ`.
 
 ## 5.50.2 (2020-01-01)
 
@@ -30,7 +312,7 @@ Make Shift-Delete to cut work on Firefox.
 
 [handlebars mode](https://codemirror.net/mode/handlebars/): Fix triple-brace support.
 
-[searchcursor addon](https://codemirror.net/doc/manual.html#addon_searchcursor): Support mathing `$` in reverse regexp search.
+[searchcursor addon](https://codemirror.net/doc/manual.html#addon_searchcursor): Support matching `$` in reverse regexp search.
 
 [panel addon](https://codemirror.net/doc/manual.html#addon_panel): Don't get confused by changing panel sizes.
 
@@ -286,7 +568,7 @@ Add `hintWords` (basic completion) helper to [clojure](https://codemirror.net/mo
 
 [panel addon](https://codemirror.net/doc/manual.html#addon_panel): Fix problem where replacing the last remaining panel dropped the newly added panel.
 
-[hardwrap addon](https://codemirror.net/doc/manual.html#addon_hardwrap): Fix an infinite loop when the indention is greater than the target column.
+[hardwrap addon](https://codemirror.net/doc/manual.html#addon_hardwrap): Fix an infinite loop when the indentation is greater than the target column.
 
 [jinja2](https://codemirror.net/mode/jinja2/) and [markdown](https://codemirror.net/mode/markdown/) modes: Add comment metadata.
 
@@ -674,7 +956,7 @@ Add `role=presentation` to more DOM elements to improve screen reader support.
 
 [merge addon](https://codemirror.net/doc/manual.html#addon_merge): Make aligning of unchanged chunks more robust.
 
-[comment addon](https://codemirror.net/doc/manual.html#addon_comment): Fix comment-toggling on a block of text that starts and ends in a (differnet) block comment.
+[comment addon](https://codemirror.net/doc/manual.html#addon_comment): Fix comment-toggling on a block of text that starts and ends in a (different) block comment.
 
 [javascript mode](https://codemirror.net/mode/javascript/): Improve support for TypeScript syntax.
 
@@ -792,7 +1074,7 @@ New event: [`optionChange`](https://codemirror.net/doc/manual.html#event_optionC
 
 Tapping/clicking the editor in [contentEditable mode](https://codemirror.net/doc/manual.html#option_inputStyle) on Chrome now puts the cursor at the tapped position.
 
-Fix various crashes and misbehaviors when reading composition events in [contentEditable mode](https://codemirror.net/doc/manual.html#option_inputStyle).
+Fix various crashes and misbehavior when reading composition events in [contentEditable mode](https://codemirror.net/doc/manual.html#option_inputStyle).
 
 Catches and ignores an IE 'Unspecified Error' when creating an editor in an iframe before there is a `<body>`.
 
@@ -1127,7 +1409,7 @@ Fix a [bug](https://github.com/codemirror/CodeMirror/issues/3834) that caused ph
 * New modes: [Vue](https://codemirror.net/mode/vue/index.html), [Oz](https://codemirror.net/mode/oz/index.html), [MscGen](https://codemirror.net/mode/mscgen/index.html) (and dialects), [Closure Stylesheets](https://codemirror.net/mode/css/gss.html)
 * Implement [CommonMark](http://commonmark.org)-style flexible list indent and cross-line code spans in [Markdown](https://codemirror.net/mode/markdown/index.html) mode
 * Add a replace-all button to the [search addon](https://codemirror.net/doc/manual.html#addon_search), and make the persistent search dialog transparent when it obscures the match
-* Handle `acync`/`await` and ocal and binary numbers in [JavaScript mode](https://codemirror.net/mode/javascript/index.html)
+* Handle `async`/`await` and ocal and binary numbers in [JavaScript mode](https://codemirror.net/mode/javascript/index.html)
 * Fix various issues with the [Haxe mode](https://codemirror.net/mode/haxe/index.html)
 * Make the [closebrackets addon](https://codemirror.net/doc/manual.html#addon_closebrackets) select only the wrapped text when wrapping selection in brackets
 * Tokenize properties as properties in the [CoffeeScript mode](https://codemirror.net/mode/coffeescript/index.html)
@@ -1614,7 +1896,7 @@ Emergency fix for a bug where an editor with line wrapping on IE will break when
 *   Slightly incompatible API changes. Read [this](https://codemirror.net/doc/upgrade_v2.2.html).
 *   New approach to [binding](https://codemirror.net/doc/manual.html#option_extraKeys) keys, support for [custom bindings](https://codemirror.net/doc/manual.html#option_keyMap).
 *   Support for overwrite (insert).
-*   [Custom-width](https://codemirror.net/doc/manual.html#option_tabSize) and [stylable](https://codemirror.net/demo/visibletabs.html) tabs.
+*   [Custom-width](https://codemirror.net/doc/manual.html#option_tabSize) and [styleable](https://codemirror.net/demo/visibletabs.html) tabs.
 *   Moved more code into [add-on scripts](https://codemirror.net/doc/manual.html#addons).
 *   Support for sane vertical cursor movement in wrapped lines.
 *   More reliable handling of editing [marked text](https://codemirror.net/doc/manual.html#markText).
@@ -1628,7 +1910,7 @@ Fixes `TextMarker.clear`, which is broken in 2.17.
 ## 2.17.0 (2011-11-21)
 
 *   Add support for [line wrapping](https://codemirror.net/doc/manual.html#option_lineWrapping) and [code folding](https://codemirror.net/doc/manual.html#hideLine).
-*   Add [Github-style Markdown](https://codemirror.net/mode/gfm/index.html) mode.
+*   Add [GitHub-style Markdown](https://codemirror.net/mode/gfm/index.html) mode.
 *   Add [Monokai](https://codemirror.net/theme/monokai.css) and [Rubyblue](https://codemirror.net/theme/rubyblue.css) themes.
 *   Add [`setBookmark`](https://codemirror.net/doc/manual.html#setBookmark) method.
 *   Move some of the demo code into reusable components under [`lib/util`](https://codemirror.net/addon/).
@@ -1729,4 +2011,4 @@ Add a [theme](https://codemirror.net/doc/manual.html#option_theme) system ([demo
 
 ## 2.0.0 (2011-03-28)
 
-CodeMirror 2 is a complete rewrite that's faster, smaller, simpler to use, and less dependent on browser quirks. See [this](https://codemirror.net/doc/internals.html) and [this](https://groups.google.com/group/codemirror/browse_thread/thread/5a8e894024a9f580) for more information.
+CodeMirror 2 is a complete rewrite that's faster, smaller, simpler to use, and less dependent on browser quirks. See [this](https://codemirror.net/doc/internals.html) and [this](http://groups.google.com/group/codemirror/browse_thread/thread/5a8e894024a9f580) for more information.
diff --git a/help3/xhpeditor/cm/README.md b/help3/xhpeditor/cm/README.md
index 2a7b1f5..92debf4 100644
--- a/help3/xhpeditor/cm/README.md
+++ b/help3/xhpeditor/cm/README.md
@@ -2,7 +2,6 @@
 
 [![Build Status](https://travis-ci.org/codemirror/CodeMirror.svg)](https://travis-ci.org/codemirror/CodeMirror)
 [![NPM version](https://img.shields.io/npm/v/codemirror.svg)](https://www.npmjs.org/package/codemirror)
-[![Join the chat at https://gitter.im/codemirror/CodeMirror](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/codemirror/CodeMirror)  
 
 CodeMirror is a versatile text editor implemented in JavaScript for
 the browser. It is specialized for editing code, and comes with over
diff --git a/help3/xhpeditor/cm/addon/comment/comment.js b/help3/xhpeditor/cm/addon/comment/comment.js
index 8394e85..dac48d0 100644
--- a/help3/xhpeditor/cm/addon/comment/comment.js
+++ b/help3/xhpeditor/cm/addon/comment/comment.js
@@ -13,7 +13,7 @@
 
   var noOptions = {};
   var nonWS = /[^\s\u00a0]/;
-  var Pos = CodeMirror.Pos;
+  var Pos = CodeMirror.Pos, cmp = CodeMirror.cmpPos;
 
   function firstNonWS(str) {
     var found = str.search(nonWS);
@@ -126,7 +126,9 @@
           if (i != end || lastLineHasText)
             self.replaceRange(lead + pad, Pos(i, 0));
       } else {
+        var atCursor = cmp(self.getCursor("to"), to) == 0, empty = !self.somethingSelected()
         self.replaceRange(endString, to);
+        if (atCursor) self.setSelection(empty ? to : self.getCursor("from"), to)
         self.replaceRange(startString, from);
       }
     });
diff --git a/help3/xhpeditor/cm/addon/dialog/dialog.js b/help3/xhpeditor/cm/addon/dialog/dialog.js
index 23b06a8..5f1f4aa 100644
--- a/help3/xhpeditor/cm/addon/dialog/dialog.js
+++ b/help3/xhpeditor/cm/addon/dialog/dialog.js
@@ -82,7 +82,9 @@
         if (e.keyCode == 13) callback(inp.value, e);
       });
 
-      if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close);
+      if (options.closeOnBlur !== false) CodeMirror.on(dialog, "focusout", function (evt) {
+        if (evt.relatedTarget !== null) close();
+      });
     } else if (button = dialog.getElementsByTagName("button")[0]) {
       CodeMirror.on(button, "click", function() {
         close();
diff --git a/help3/xhpeditor/cm/addon/display/panel.js b/help3/xhpeditor/cm/addon/display/panel.js
index 4c9f2c0..29f7e0b 100644
--- a/help3/xhpeditor/cm/addon/display/panel.js
+++ b/help3/xhpeditor/cm/addon/display/panel.js
@@ -76,7 +76,7 @@
   };
 
   function initPanels(cm) {
-    var wrap = cm.getWrapperElement();
+    var wrap = cm.getWrapperElement()
     var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
     var height = parseInt(style.height);
     var info = cm.state.panels = {
@@ -84,9 +84,10 @@
       panels: [],
       wrapper: document.createElement("div")
     };
+    var hasFocus = cm.hasFocus(), scrollPos = cm.getScrollInfo()
     wrap.parentNode.insertBefore(info.wrapper, wrap);
-    var hasFocus = cm.hasFocus();
     info.wrapper.appendChild(wrap);
+    cm.scrollTo(scrollPos.left, scrollPos.top)
     if (hasFocus) cm.focus();
 
     cm._setSize = cm.setSize;
@@ -114,8 +115,11 @@
     var info = cm.state.panels;
     cm.state.panels = null;
 
-    var wrap = cm.getWrapperElement();
+    var wrap = cm.getWrapperElement()
+    var hasFocus = cm.hasFocus(), scrollPos = cm.getScrollInfo()
     info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
+    cm.scrollTo(scrollPos.left, scrollPos.top)
+    if (hasFocus) cm.focus();
     wrap.style.height = info.setHeight;
     cm.setSize = cm._setSize;
     cm.setSize();
diff --git a/help3/xhpeditor/cm/addon/display/placeholder.js b/help3/xhpeditor/cm/addon/display/placeholder.js
index 4eabe3d..cfb8341 100644
--- a/help3/xhpeditor/cm/addon/display/placeholder.js
+++ b/help3/xhpeditor/cm/addon/display/placeholder.js
@@ -15,11 +15,13 @@
       cm.on("blur", onBlur);
       cm.on("change", onChange);
       cm.on("swapDoc", onChange);
+      CodeMirror.on(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose = function() { onComposition(cm) })
       onChange(cm);
     } else if (!val && prev) {
       cm.off("blur", onBlur);
       cm.off("change", onChange);
       cm.off("swapDoc", onChange);
+      CodeMirror.off(cm.getInputField(), "compositionupdate", cm.state.placeholderCompose)
       clearPlaceholder(cm);
       var wrapper = cm.getWrapperElement();
       wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
@@ -46,6 +48,19 @@
     cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
   }
 
+  function onComposition(cm) {
+    setTimeout(function() {
+      var empty = false
+      if (cm.lineCount() == 1) {
+        var input = cm.getInputField()
+        empty = input.nodeName == "TEXTAREA" ? !cm.getLine(0).length
+          : !/[^\u200b]/.test(input.querySelector(".CodeMirror-line").textContent)
+      }
+      if (empty) setPlaceholder(cm)
+      else clearPlaceholder(cm)
+    }, 20)
+  }
+
   function onBlur(cm) {
     if (isEmpty(cm)) setPlaceholder(cm);
   }
diff --git a/help3/xhpeditor/cm/addon/edit/closebrackets.js b/help3/xhpeditor/cm/addon/edit/closebrackets.js
index 4415c39..593d443 100644
--- a/help3/xhpeditor/cm/addon/edit/closebrackets.js
+++ b/help3/xhpeditor/cm/addon/edit/closebrackets.js
@@ -87,7 +87,7 @@
     cm.operation(function() {
       var linesep = cm.lineSeparator() || "\n";
       cm.replaceSelection(linesep + linesep, null);
-      cm.execCommand("goCharLeft");
+      moveSel(cm, -1)
       ranges = cm.listSelections();
       for (var i = 0; i < ranges.length; i++) {
         var line = ranges[i].head.line;
@@ -97,6 +97,17 @@
     });
   }
 
+  function moveSel(cm, dir) {
+    var newRanges = [], ranges = cm.listSelections(), primary = 0
+    for (var i = 0; i < ranges.length; i++) {
+      var range = ranges[i]
+      if (range.head == cm.getCursor()) primary = i
+      var pos = range.head.ch || dir > 0 ? {line: range.head.line, ch: range.head.ch + dir} : {line: range.head.line - 1}
+      newRanges.push({anchor: pos, head: pos})
+    }
+    cm.setSelections(newRanges, primary)
+  }
+
   function contractSelection(sel) {
     var inverted = CodeMirror.cmpPos(sel.anchor, sel.head) > 0;
     return {anchor: new Pos(sel.anchor.line, sel.anchor.ch + (inverted ? -1 : 1)),
@@ -153,10 +164,9 @@
     var right = pos % 2 ? ch : pairs.charAt(pos + 1);
     cm.operation(function() {
       if (type == "skip") {
-        cm.execCommand("goCharRight");
+        moveSel(cm, 1)
       } else if (type == "skipThree") {
-        for (var i = 0; i < 3; i++)
-          cm.execCommand("goCharRight");
+        moveSel(cm, 3)
       } else if (type == "surround") {
         var sels = cm.getSelections();
         for (var i = 0; i < sels.length; i++)
@@ -169,10 +179,10 @@
       } else if (type == "both") {
         cm.replaceSelection(left + right, null);
         cm.triggerElectric(left + right);
-        cm.execCommand("goCharLeft");
+        moveSel(cm, -1)
       } else if (type == "addFour") {
         cm.replaceSelection(left + left + left + left, "before");
-        cm.execCommand("goCharRight");
+        moveSel(cm, 1)
       }
     });
   }
diff --git a/help3/xhpeditor/cm/addon/edit/closetag.js b/help3/xhpeditor/cm/addon/edit/closetag.js
index b8cbf95..7c22a50 100644
--- a/help3/xhpeditor/cm/addon/edit/closetag.js
+++ b/help3/xhpeditor/cm/addon/edit/closetag.js
@@ -40,9 +40,9 @@
       cm.removeKeyMap("autoCloseTags");
     if (!val) return;
     var map = {name: "autoCloseTags"};
-    if (typeof val != "object" || val.whenClosing)
+    if (typeof val != "object" || val.whenClosing !== false)
       map["'/'"] = function(cm) { return autoCloseSlash(cm); };
-    if (typeof val != "object" || val.whenOpening)
+    if (typeof val != "object" || val.whenOpening !== false)
       map["'>'"] = function(cm) { return autoCloseGT(cm); };
     cm.addKeyMap(map);
   });
@@ -128,9 +128,10 @@
         replacement = head + "style";
       } else {
         var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
-        if (!context || (context.length && closingTagExists(cm, context, context[context.length - 1], pos)))
+        var top = context.length ? context[context.length - 1] : ""
+        if (!context || (context.length && closingTagExists(cm, context, top, pos)))
           return CodeMirror.Pass;
-        replacement = head + context[context.length - 1]
+        replacement = head + top
       }
       if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
       replacements[i] = replacement;
diff --git a/help3/xhpeditor/cm/addon/edit/continuelist.js b/help3/xhpeditor/cm/addon/edit/continuelist.js
index fb5f037..6ec6501 100644
--- a/help3/xhpeditor/cm/addon/edit/continuelist.js
+++ b/help3/xhpeditor/cm/addon/edit/continuelist.js
@@ -41,7 +41,9 @@
         return;
       }
       if (emptyListRE.test(line)) {
-        if (!/>\s*$/.test(line)) cm.replaceRange("", {
+        var endOfQuote = inQuote && />\s*$/.test(line)
+        var endOfList = !/>\s*$/.test(line)
+        if (endOfQuote || endOfList) cm.replaceRange("", {
           line: pos.line, ch: 0
         }, {
           line: pos.line, ch: pos.ch + 1
@@ -88,7 +90,7 @@
           });
         } else {
           if (startIndent.length > nextIndent.length) return;
-          // This doesn't run if the next line immediatley indents, as it is
+          // This doesn't run if the next line immediately 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;
diff --git a/help3/xhpeditor/cm/addon/edit/matchbrackets.js b/help3/xhpeditor/cm/addon/edit/matchbrackets.js
index 2a14728..43dc884 100644
--- a/help3/xhpeditor/cm/addon/edit/matchbrackets.js
+++ b/help3/xhpeditor/cm/addon/edit/matchbrackets.js
@@ -38,7 +38,7 @@
     if (config && config.strict && (dir > 0) != (pos == where.ch)) return null;
     var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
 
-    var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
+    var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style, config);
     if (found == null) return null;
     return {from: Pos(where.line, pos), to: found && found.pos,
             match: found && found.ch == match.charAt(0), forward: dir > 0};
@@ -67,7 +67,8 @@
       if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
       for (; pos != end; pos += dir) {
         var ch = line.charAt(pos);
-        if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
+        if (re.test(ch) && (style === undefined ||
+                            (cm.getTokenTypeAt(Pos(lineNo, pos + 1)) || "") == (style || ""))) {
           var match = matching[ch];
           if (match && (match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
           else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
@@ -80,11 +81,12 @@
 
   function matchBrackets(cm, autoclear, config) {
     // Disable brace matching in long lines, since it'll cause hugely slow updates
-    var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
+    var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000,
+      highlightNonMatching = config && config.highlightNonMatching;
     var marks = [], ranges = cm.listSelections();
     for (var i = 0; i < ranges.length; i++) {
       var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, config);
-      if (match && cm.getLine(match.from.line).length <= maxHighlightLen) {
+      if (match && (match.match || highlightNonMatching !== false) && cm.getLine(match.from.line).length <= maxHighlightLen) {
         var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
         marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
         if (match.to && cm.getLine(match.to.line).length <= maxHighlightLen)
@@ -94,7 +96,7 @@
 
     if (marks.length) {
       // Kludge to work around the IE bug from issue #1193, where text
-      // input stops going to the textare whever this fires.
+      // input stops going to the textarea whenever this fires.
       if (ie_lt8 && cm.state.focused) cm.focus();
 
       var clear = function() {
@@ -117,17 +119,25 @@
     });
   }
 
+  function clearHighlighted(cm) {
+    if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
+      cm.state.matchBrackets.currentlyHighlighted();
+      cm.state.matchBrackets.currentlyHighlighted = null;
+    }
+  }
+
   CodeMirror.defineOption("matchBrackets", false, function(cm, val, old) {
     if (old && old != CodeMirror.Init) {
       cm.off("cursorActivity", doMatchBrackets);
-      if (cm.state.matchBrackets && cm.state.matchBrackets.currentlyHighlighted) {
-        cm.state.matchBrackets.currentlyHighlighted();
-        cm.state.matchBrackets.currentlyHighlighted = null;
-      }
+      cm.off("focus", doMatchBrackets)
+      cm.off("blur", clearHighlighted)
+      clearHighlighted(cm);
     }
     if (val) {
       cm.state.matchBrackets = typeof val == "object" ? val : {};
       cm.on("cursorActivity", doMatchBrackets);
+      cm.on("focus", doMatchBrackets)
+      cm.on("blur", clearHighlighted)
     }
   });
 
diff --git a/help3/xhpeditor/cm/addon/fold/brace-fold.js b/help3/xhpeditor/cm/addon/fold/brace-fold.js
index 654d1fb..79a331c 100644
--- a/help3/xhpeditor/cm/addon/fold/brace-fold.js
+++ b/help3/xhpeditor/cm/addon/fold/brace-fold.js
@@ -31,13 +31,16 @@ CodeMirror.registerHelper("fold", "brace", function(cm, start) {
     }
   }
 
-  var startToken = "{", endToken = "}", startCh = findOpening("{");
-  if (startCh == null) {
-    startToken = "[", endToken = "]";
-    startCh = findOpening("[");
+  var startBrace = findOpening("{"), startBracket = findOpening("[")
+  var startToken, endToken, startCh
+  if (startBrace != null && (startBracket == null || startBracket > startBrace)) {
+    startCh = startBrace; startToken = "{"; endToken = "}"
+  } else if (startBracket != null) {
+    startCh = startBracket; startToken = "["; endToken = "]"
+  } else {
+    return
   }
 
-  if (startCh == null) return;
   var count = 1, lastLine = cm.lastLine(), end, endCh;
   outer: for (var i = line; i <= lastLine; ++i) {
     var text = cm.getLine(i), pos = i == line ? startCh : 0;
diff --git a/help3/xhpeditor/cm/addon/hint/html-hint.js b/help3/xhpeditor/cm/addon/hint/html-hint.js
index d0cca4f..9878eca 100644
--- a/help3/xhpeditor/cm/addon/hint/html-hint.js
+++ b/help3/xhpeditor/cm/addon/hint/html-hint.js
@@ -98,6 +98,7 @@
     dfn: s,
     dir: s,
     div: s,
+    dialog: { attrs: { open: null } },
     dl: s,
     dt: s,
     em: s,
diff --git a/help3/xhpeditor/cm/addon/hint/javascript-hint.js b/help3/xhpeditor/cm/addon/hint/javascript-hint.js
index 182224d..9f06b1b 100644
--- a/help3/xhpeditor/cm/addon/hint/javascript-hint.js
+++ b/help3/xhpeditor/cm/addon/hint/javascript-hint.js
@@ -69,7 +69,7 @@
   function getCoffeeScriptToken(editor, cur) {
   // This getToken, it is for coffeescript, imitates the behavior of
   // getTokenAt method in javascript.js, that is, returning "property"
-  // type and treat "." as indepenent token.
+  // type and treat "." as independent token.
     var token = editor.getTokenAt(cur);
     if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
       token.end = token.start;
@@ -144,12 +144,15 @@
         base = base[context.pop().string];
       if (base != null) gatherCompletions(base);
     } else {
-      // If not, just look in the global object and any local scope
+      // If not, just look in the global object, any local scope, and optional additional-context
       // (reading into JS mode internals to get at the local and global variables)
       for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
       for (var c = token.state.context; c; c = c.prev)
         for (var v = c.vars; v; v = v.next) maybeAdd(v.name)
       for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
+      if (options && options.additionalContext != null)
+        for (var key in options.additionalContext)
+          maybeAdd(key);
       if (!options || options.useGlobalScope !== false)
         gatherCompletions(global);
       forEach(keywords, maybeAdd);
diff --git a/help3/xhpeditor/cm/addon/hint/show-hint.js b/help3/xhpeditor/cm/addon/hint/show-hint.js
index 374cddf..8f23656 100644
--- a/help3/xhpeditor/cm/addon/hint/show-hint.js
+++ b/help3/xhpeditor/cm/addon/hint/show-hint.js
@@ -1,6 +1,8 @@
 // CodeMirror, copyright (c) by Marijn Haverbeke and others
 // Distributed under an MIT license: https://codemirror.net/LICENSE
 
+// declare global: DOMRect
+
 (function(mod) {
   if (typeof exports == "object" && typeof module == "object") // CommonJS
     mod(require("../../lib/codemirror"));
@@ -59,8 +61,10 @@
     this.startPos = this.cm.getCursor("start");
     this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
 
-    var self = this;
-    cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
+    if (this.options.updateOnCursorActivity) {
+      var self = this;
+      cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
+    }
   }
 
   var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
@@ -73,7 +77,9 @@
       if (!this.active()) return;
       this.cm.state.completionActive = null;
       this.tick = null;
-      this.cm.off("cursorActivity", this.activityFunc);
+      if (this.options.updateOnCursorActivity) {
+        this.cm.off("cursorActivity", this.activityFunc);
+      }
 
       if (this.widget && this.data) CodeMirror.signal(this.data, "close");
       if (this.widget) this.widget.close();
@@ -85,12 +91,19 @@
     },
 
     pick: function(data, i) {
-      var completion = data.list[i];
-      if (completion.hint) completion.hint(this.cm, data, completion);
-      else this.cm.replaceRange(getText(completion), completion.from || data.from,
-                                completion.to || data.to, "complete");
-      CodeMirror.signal(data, "pick", completion);
-      this.close();
+      var completion = data.list[i], self = this;
+      this.cm.operation(function() {
+        if (completion.hint)
+          completion.hint(self.cm, data, completion);
+        else
+          self.cm.replaceRange(getText(completion), completion.from || data.from,
+                               completion.to || data.to, "complete");
+        CodeMirror.signal(data, "pick", completion);
+        self.cm.scrollIntoView();
+      });
+      if (this.options.closeOnPick) {
+        this.close();
+      }
     },
 
     cursorActivity: function() {
@@ -99,9 +112,14 @@
         this.debounce = 0;
       }
 
+      var identStart = this.startPos;
+      if(this.data) {
+        identStart = this.data.from;
+      }
+
       var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
       if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
-          pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
+          pos.ch < identStart.ch || this.cm.somethingSelected() ||
           (!pos.ch || this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
         this.close();
       } else {
@@ -249,10 +267,15 @@
     var winW = parentWindow.innerWidth || Math.max(ownerDocument.body.offsetWidth, ownerDocument.documentElement.offsetWidth);
     var winH = parentWindow.innerHeight || Math.max(ownerDocument.body.offsetHeight, ownerDocument.documentElement.offsetHeight);
     container.appendChild(hints);
-    var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
-    var scrolls = hints.scrollHeight > hints.clientHeight + 1
-    var startScroll = cm.getScrollInfo();
 
+    var box = completion.options.moveOnOverlap ? hints.getBoundingClientRect() : new DOMRect();
+    var scrolls = completion.options.paddingForScrollbar ? hints.scrollHeight > hints.clientHeight + 1 : false;
+
+    // Compute in the timeout to avoid reflow on init
+    var startScroll;
+    setTimeout(function() { startScroll = cm.getScrollInfo(); });
+
+    var overlapY = box.bottom - winH;
     if (overlapY > 0) {
       var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
       if (curTop - height > 0) { // Fits above cursor
@@ -270,6 +293,7 @@
       }
     }
     var overlapX = box.right - winW;
+    if (scrolls) overlapX += cm.display.nativeBarWidth;
     if (overlapX > 0) {
       if (box.right - box.left > winW) {
         hints.style.width = (winW - 5) + "px";
@@ -298,6 +322,7 @@
 
     cm.on("scroll", this.onScroll = function() {
       var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
+      if (!startScroll) startScroll = cm.getScrollInfo();
       var newTop = top + startScroll.top - curScroll.top;
       var point = newTop - (parentWindow.pageYOffset || (ownerDocument.documentElement || ownerDocument.body).scrollTop);
       if (!below) point += hints.offsetHeight;
@@ -322,7 +347,12 @@
     CodeMirror.on(hints, "mousedown", function() {
       setTimeout(function(){cm.focus();}, 20);
     });
-    this.scrollToActive()
+
+    // The first hint doesn't need to be scrolled to on init
+    var selectedHintRange = this.getSelectedHintRange();
+    if (selectedHintRange.from !== 0 || selectedHintRange.to !== 0) {
+      this.scrollToActive();
+    }
 
     CodeMirror.signal(data, "select", completions[this.selectedHint], hints.childNodes[this.selectedHint]);
     return true;
@@ -332,7 +362,7 @@
     close: function() {
       if (this.completion.widget != this) return;
       this.completion.widget = null;
-      this.hints.parentNode.removeChild(this.hints);
+      if (this.hints.parentNode) this.hints.parentNode.removeChild(this.hints);
       this.completion.cm.removeKeyMap(this.keyMap);
 
       var cm = this.completion.cm;
@@ -369,15 +399,26 @@
     },
 
     scrollToActive: function() {
-      var node = this.hints.childNodes[this.selectedHint]
-      if (node.offsetTop < this.hints.scrollTop)
-        this.hints.scrollTop = node.offsetTop - 3;
-      else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
-        this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
+      var selectedHintRange = this.getSelectedHintRange();
+      var node1 = this.hints.childNodes[selectedHintRange.from];
+      var node2 = this.hints.childNodes[selectedHintRange.to];
+      var firstNode = this.hints.firstChild;
+      if (node1.offsetTop < this.hints.scrollTop)
+        this.hints.scrollTop = node1.offsetTop - firstNode.offsetTop;
+      else if (node2.offsetTop + node2.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
+        this.hints.scrollTop = node2.offsetTop + node2.offsetHeight - this.hints.clientHeight + firstNode.offsetTop;
     },
 
     screenAmount: function() {
       return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
+    },
+
+    getSelectedHintRange: function() {
+      var margin = this.completion.options.scrollMargin || 0;
+      return {
+        from: Math.max(0, this.selectedHint - margin),
+        to: Math.min(this.data.list.length - 1, this.selectedHint + margin),
+      };
     }
   };
 
@@ -455,11 +496,15 @@
     completeSingle: true,
     alignWithWord: true,
     closeCharacters: /[\s()\[\]{};:>,]/,
+    closeOnPick: true,
     closeOnUnfocus: true,
+    updateOnCursorActivity: true,
     completeOnSingleClick: true,
     container: null,
     customKeys: null,
-    extraKeys: null
+    extraKeys: null,
+    paddingForScrollbar: true,
+    moveOnOverlap: true,
   };
 
   CodeMirror.defineOption("hintOptions", null);
diff --git a/help3/xhpeditor/cm/addon/hint/sql-hint.js b/help3/xhpeditor/cm/addon/hint/sql-hint.js
index 444eba8..efdce81 100644
--- a/help3/xhpeditor/cm/addon/hint/sql-hint.js
+++ b/help3/xhpeditor/cm/addon/hint/sql-hint.js
@@ -97,7 +97,7 @@
     if (name.charAt(0) == ".") {
       name = name.substr(1);
     }
-    // replace doublicated identifierQuotes with single identifierQuotes
+    // replace duplicated identifierQuotes with single identifierQuotes
     // and remove single identifierQuotes
     var nameParts = name.split(identifierQuote+identifierQuote);
     for (var i = 0; i < nameParts.length; i++)
@@ -109,7 +109,7 @@
     var nameParts = getText(name).split(".");
     for (var i = 0; i < nameParts.length; i++)
       nameParts[i] = identifierQuote +
-        // doublicate identifierQuotes
+        // duplicate identifierQuotes
         nameParts[i].replace(new RegExp(identifierQuote,"g"), identifierQuote+identifierQuote) +
         identifierQuote;
     var escaped = nameParts.join(".");
@@ -187,7 +187,7 @@
   function eachWord(lineText, f) {
     var words = lineText.split(/\s+/)
     for (var i = 0; i < words.length; i++)
-      if (words[i]) f(words[i].replace(/[,;]/g, ''))
+      if (words[i]) f(words[i].replace(/[`,;]/g, ''))
   }
 
   function findTableByAlias(alias, editor) {
@@ -264,7 +264,7 @@
       token.string = token.string.slice(0, cur.ch - token.start);
     }
 
-    if (token.string.match(/^[.`"\w@]\w*$/)) {
+    if (token.string.match(/^[.`"'\w@][\w$#]*$/g)) {
       search = token.string;
       start = token.start;
       end = token.end;
diff --git a/help3/xhpeditor/cm/addon/hint/xml-hint.js b/help3/xhpeditor/cm/addon/hint/xml-hint.js
index 7575b37..2b31531 100644
--- a/help3/xhpeditor/cm/addon/hint/xml-hint.js
+++ b/help3/xhpeditor/cm/addon/hint/xml-hint.js
@@ -101,8 +101,14 @@
           }
           replaceToken = true;
         }
-        for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
-          result.push(quote + atValues[i] + quote);
+        var returnHintsFromAtValues = function(atValues) {
+          if (atValues)
+            for (var i = 0; i < atValues.length; ++i) if (!prefix || matches(atValues[i], prefix, matchInMiddle))
+              result.push(quote + atValues[i] + quote);
+          return returnHints();
+        };
+        if (atValues && atValues.then) return atValues.then(returnHintsFromAtValues);
+        return returnHintsFromAtValues(atValues);
       } else { // An attribute name
         if (token.type == "attribute") {
           prefix = token.string;
@@ -112,11 +118,14 @@
           result.push(attr);
       }
     }
-    return {
-      list: result,
-      from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
-      to: replaceToken ? Pos(cur.line, token.end) : cur
-    };
+    function returnHints() {
+      return {
+        list: result,
+        from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
+        to: replaceToken ? Pos(cur.line, token.end) : cur
+      };
+    }
+    return returnHints();
   }
 
   CodeMirror.registerHelper("hint", "xml", getHints);
diff --git a/help3/xhpeditor/cm/addon/lint/javascript-lint.js b/help3/xhpeditor/cm/addon/lint/javascript-lint.js
index cc132d7..e5bc752 100644
--- a/help3/xhpeditor/cm/addon/lint/javascript-lint.js
+++ b/help3/xhpeditor/cm/addon/lint/javascript-lint.js
@@ -1,6 +1,8 @@
 // CodeMirror, copyright (c) by Marijn Haverbeke and others
 // Distributed under an MIT license: https://codemirror.net/LICENSE
 
+// Depends on jshint.js from https://github.com/jshint/jshint
+
 (function(mod) {
   if (typeof exports == "object" && typeof module == "object") // CommonJS
     mod(require("../../lib/codemirror"));
diff --git a/help3/xhpeditor/cm/addon/lint/lint.css b/help3/xhpeditor/cm/addon/lint/lint.css
index f097cfe..0871865 100644
--- a/help3/xhpeditor/cm/addon/lint/lint.css
+++ b/help3/xhpeditor/cm/addon/lint/lint.css
@@ -25,22 +25,20 @@
   -ms-transition: opacity .4s;
 }
 
-.CodeMirror-lint-mark-error, .CodeMirror-lint-mark-warning {
+.CodeMirror-lint-mark {
   background-position: left bottom;
   background-repeat: repeat-x;
 }
 
-.CodeMirror-lint-mark-error {
-  background-image:
-  url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==")
-  ;
-}
-
 .CodeMirror-lint-mark-warning {
   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=");
 }
 
-.CodeMirror-lint-marker-error, .CodeMirror-lint-marker-warning {
+.CodeMirror-lint-mark-error {
+  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==");
+}
+
+.CodeMirror-lint-marker {
   background-position: center center;
   background-repeat: no-repeat;
   cursor: pointer;
@@ -51,20 +49,20 @@
   position: relative;
 }
 
-.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning {
+.CodeMirror-lint-message {
   padding-left: 18px;
   background-position: top left;
   background-repeat: no-repeat;
 }
 
-.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
-  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
-}
-
 .CodeMirror-lint-marker-warning, .CodeMirror-lint-message-warning {
   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=");
 }
 
+.CodeMirror-lint-marker-error, .CodeMirror-lint-message-error {
+  background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=");
+}
+
 .CodeMirror-lint-marker-multiple {
   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC");
   background-repeat: no-repeat;
diff --git a/help3/xhpeditor/cm/addon/lint/lint.js b/help3/xhpeditor/cm/addon/lint/lint.js
index aa75ba0..395f0d9 100644
--- a/help3/xhpeditor/cm/addon/lint/lint.js
+++ b/help3/xhpeditor/cm/addon/lint/lint.js
@@ -12,11 +12,14 @@
   "use strict";
   var GUTTER_ID = "CodeMirror-lint-markers";
 
-  function showTooltip(e, content) {
+  function showTooltip(cm, e, content) {
     var tt = document.createElement("div");
-    tt.className = "CodeMirror-lint-tooltip";
+    tt.className = "CodeMirror-lint-tooltip cm-s-" + cm.options.theme;
     tt.appendChild(content.cloneNode(true));
-    document.body.appendChild(tt);
+    if (cm.state.lint.options.selfContain)
+      cm.getWrapperElement().appendChild(tt);
+    else
+      document.body.appendChild(tt);
 
     function position(e) {
       if (!tt.parentNode) return CodeMirror.off(document, "mousemove", position);
@@ -38,8 +41,8 @@
     setTimeout(function() { rm(tt); }, 600);
   }
 
-  function showTooltipFor(e, content, node) {
-    var tooltip = showTooltip(e, content);
+  function showTooltipFor(cm, e, content, node) {
+    var tooltip = showTooltip(cm, e, content);
     function hide() {
       CodeMirror.off(node, "mouseout", hide);
       if (tooltip) { hideTooltip(tooltip); tooltip = null; }
@@ -78,16 +81,16 @@
     state.marked.length = 0;
   }
 
-  function makeMarker(labels, severity, multiple, tooltips) {
+  function makeMarker(cm, labels, severity, multiple, tooltips) {
     var marker = document.createElement("div"), inner = marker;
-    marker.className = "CodeMirror-lint-marker-" + severity;
+    marker.className = "CodeMirror-lint-marker CodeMirror-lint-marker-" + severity;
     if (multiple) {
       inner = marker.appendChild(document.createElement("div"));
-      inner.className = "CodeMirror-lint-marker-multiple";
+      inner.className = "CodeMirror-lint-marker CodeMirror-lint-marker-multiple";
     }
 
     if (tooltips != false) CodeMirror.on(inner, "mouseover", function(e) {
-      showTooltipFor(e, labels, inner);
+      showTooltipFor(cm, e, labels, inner);
     });
 
     return marker;
@@ -111,11 +114,11 @@
     var severity = ann.severity;
     if (!severity) severity = "error";
     var tip = document.createElement("div");
-    tip.className = "CodeMirror-lint-message-" + severity;
+    tip.className = "CodeMirror-lint-message CodeMirror-lint-message-" + severity;
     if (typeof ann.messageHTML != 'undefined') {
-        tip.innerHTML = ann.messageHTML;
+      tip.innerHTML = ann.messageHTML;
     } else {
-        tip.appendChild(document.createTextNode(ann.message));
+      tip.appendChild(document.createTextNode(ann.message));
     }
     return tip;
   }
@@ -167,6 +170,10 @@
       var anns = annotations[line];
       if (!anns) continue;
 
+      // filter out duplicate messages
+      var message = [];
+      anns = anns.filter(function(item) { return message.indexOf(item.message) > -1 ? false : message.push(item.message) });
+
       var maxSeverity = null;
       var tipLabel = state.hasGutter && document.createDocumentFragment();
 
@@ -180,13 +187,13 @@
         if (state.hasGutter) tipLabel.appendChild(annotationTooltip(ann));
 
         if (ann.to) state.marked.push(cm.markText(ann.from, ann.to, {
-          className: "CodeMirror-lint-mark-" + severity,
+          className: "CodeMirror-lint-mark CodeMirror-lint-mark-" + severity,
           __annotation: ann
         }));
       }
-
+      // use original annotations[line] to show multiple messages
       if (state.hasGutter)
-        cm.setGutterMarker(line, GUTTER_ID, makeMarker(tipLabel, maxSeverity, anns.length > 1,
+        cm.setGutterMarker(line, GUTTER_ID, makeMarker(cm, tipLabel, maxSeverity, annotations[line].length > 1,
                                                        state.options.tooltips));
     }
     if (options.onUpdateLinting) options.onUpdateLinting(annotationsNotSorted, annotations, cm);
@@ -199,14 +206,14 @@
     state.timeout = setTimeout(function(){startLinting(cm);}, state.options.delay || 500);
   }
 
-  function popupTooltips(annotations, e) {
+  function popupTooltips(cm, annotations, e) {
     var target = e.target || e.srcElement;
     var tooltip = document.createDocumentFragment();
     for (var i = 0; i < annotations.length; i++) {
       var ann = annotations[i];
       tooltip.appendChild(annotationTooltip(ann));
     }
-    showTooltipFor(e, tooltip, target);
+    showTooltipFor(cm, e, tooltip, target);
   }
 
   function onMouseOver(cm, e) {
@@ -220,7 +227,7 @@
       var ann = spans[i].__annotation;
       if (ann) annotations.push(ann);
     }
-    if (annotations.length) popupTooltips(annotations, e);
+    if (annotations.length) popupTooltips(cm, annotations, e);
   }
 
   CodeMirror.defineOption("lint", false, function(cm, val, old) {
diff --git a/help3/xhpeditor/cm/addon/merge/merge.js b/help3/xhpeditor/cm/addon/merge/merge.js
index 8296540..827edb7 100644
--- a/help3/xhpeditor/cm/addon/merge/merge.js
+++ b/help3/xhpeditor/cm/addon/merge/merge.js
@@ -443,22 +443,26 @@
       aligners[i].clear();
     aligners.length = 0;
 
-    var cm = [dv.edit, dv.orig], scroll = [];
+    var cm = [dv.edit, dv.orig], scroll = [], offset = []
     if (other) cm.push(other.orig);
-    for (var i = 0; i < cm.length; i++)
+    for (var i = 0; i < cm.length; i++) {
       scroll.push(cm[i].getScrollInfo().top);
+      offset.push(-cm[i].getScrollerElement().getBoundingClientRect().top)
+    }
 
+    if (offset[0] != offset[1] || cm.length == 3 && offset[1] != offset[2])
+      alignLines(cm, offset, [0, 0, 0], aligners)
     for (var ln = 0; ln < linesToAlign.length; ln++)
-      alignLines(cm, linesToAlign[ln], aligners);
+      alignLines(cm, offset, linesToAlign[ln], aligners);
 
     for (var i = 0; i < cm.length; i++)
       cm[i].scrollTo(null, scroll[i]);
   }
 
-  function alignLines(cm, lines, aligners) {
-    var maxOffset = 0, offset = [];
+  function alignLines(cm, cmOffset, lines, aligners) {
+    var maxOffset = -1e8, offset = [];
     for (var i = 0; i < cm.length; i++) if (lines[i] != null) {
-      var off = cm[i].heightAtLine(lines[i], "local");
+      var off = cm[i].heightAtLine(lines[i], "local") - cmOffset[i];
       offset[i] = off;
       maxOffset = Math.max(maxOffset, off);
     }
diff --git a/help3/xhpeditor/cm/addon/mode/loadmode.js b/help3/xhpeditor/cm/addon/mode/loadmode.js
index 4ce716a..fc695d0 100644
--- a/help3/xhpeditor/cm/addon/mode/loadmode.js
+++ b/help3/xhpeditor/cm/addon/mode/loadmode.js
@@ -16,8 +16,8 @@
     var countDown = n;
     return function() { if (--countDown == 0) cont(); };
   }
-  function ensureDeps(mode, cont) {
-    var deps = CodeMirror.modes[mode].dependencies;
+  function ensureDeps(mode, cont, options) {
+    var modeObj = CodeMirror.modes[mode], deps = modeObj && modeObj.dependencies;
     if (!deps) return cont();
     var missing = [];
     for (var i = 0; i < deps.length; ++i) {
@@ -27,16 +27,18 @@
     if (!missing.length) return cont();
     var split = splitCallback(cont, missing.length);
     for (var i = 0; i < missing.length; ++i)
-      CodeMirror.requireMode(missing[i], split);
+      CodeMirror.requireMode(missing[i], split, options);
   }
 
-  CodeMirror.requireMode = function(mode, cont) {
+  CodeMirror.requireMode = function(mode, cont, options) {
     if (typeof mode != "string") mode = mode.name;
-    if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
+    if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont, options);
     if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
 
-    var file = CodeMirror.modeURL.replace(/%N/g, mode);
-    if (env == "plain") {
+    var file = options && options.path ? options.path(mode) : CodeMirror.modeURL.replace(/%N/g, mode);
+    if (options && options.loadMode) {
+      options.loadMode(file, function() { ensureDeps(mode, cont, options) })
+    } else if (env == "plain") {
       var script = document.createElement("script");
       script.src = file;
       var others = document.getElementsByTagName("script")[0];
@@ -44,7 +46,7 @@
       CodeMirror.on(script, "load", function() {
         ensureDeps(mode, function() {
           for (var i = 0; i < list.length; ++i) list[i]();
-        });
+        }, options);
       });
       others.parentNode.insertBefore(script, others);
     } else if (env == "cjs") {
@@ -55,10 +57,10 @@
     }
   };
 
-  CodeMirror.autoLoadMode = function(instance, mode) {
+  CodeMirror.autoLoadMode = function(instance, mode, options) {
     if (!CodeMirror.modes.hasOwnProperty(mode))
       CodeMirror.requireMode(mode, function() {
         instance.setOption("mode", instance.getOption("mode"));
-      });
+      }, options);
   };
 });
diff --git a/help3/xhpeditor/cm/addon/mode/multiplex.js b/help3/xhpeditor/cm/addon/mode/multiplex.js
index 93fd9a5..6140bc4 100644
--- a/help3/xhpeditor/cm/addon/mode/multiplex.js
+++ b/help3/xhpeditor/cm/addon/mode/multiplex.js
@@ -12,7 +12,7 @@
 "use strict";
 
 CodeMirror.multiplexingMode = function(outer /*, others */) {
-  // Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
+  // Others should be {open, close, mode [, delimStyle] [, innerStyle] [, parseDelimiters]} objects
   var others = Array.prototype.slice.call(arguments, 1);
 
   function indexOf(string, pattern, from, returnEnd) {
@@ -29,7 +29,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
       return {
         outer: CodeMirror.startState(outer),
         innerActive: null,
-        inner: null
+        inner: null,
+        startingInner: false
       };
     },
 
@@ -37,7 +38,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
       return {
         outer: CodeMirror.copyState(outer, state.outer),
         innerActive: state.innerActive,
-        inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
+        inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner),
+        startingInner: state.startingInner
       };
     },
 
@@ -49,6 +51,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
           var found = indexOf(oldContent, other.open, stream.pos);
           if (found == stream.pos) {
             if (!other.parseDelimiters) stream.match(other.open);
+            state.startingInner = !!other.parseDelimiters
             state.innerActive = other;
 
             // Get the outer indent, making sure to handle CodeMirror.Pass
@@ -74,7 +77,8 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
           state.innerActive = state.inner = null;
           return this.token(stream, state);
         }
-        var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
+        var found = curInner.close && !state.startingInner ?
+            indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
         if (found == stream.pos && !curInner.parseDelimiters) {
           stream.match(curInner.close);
           state.innerActive = state.inner = null;
@@ -83,6 +87,7 @@ CodeMirror.multiplexingMode = function(outer /*, others */) {
         if (found > -1) stream.string = oldContent.slice(0, found);
         var innerToken = curInner.mode.token(stream, state.inner);
         if (found > -1) stream.string = oldContent;
+        else if (stream.pos > stream.start) state.startingInner = false
 
         if (found == stream.pos && curInner.parseDelimiters)
           state.innerActive = state.inner = null;
diff --git a/help3/xhpeditor/cm/addon/mode/multiplex_test.js b/help3/xhpeditor/cm/addon/mode/multiplex_test.js
index c51cad4..8503988 100644
--- a/help3/xhpeditor/cm/addon/mode/multiplex_test.js
+++ b/help3/xhpeditor/cm/addon/mode/multiplex_test.js
@@ -30,4 +30,20 @@
   MT(
     "stexInsideMarkdown",
     "[strong **Equation:**] [delim&delim-open $][inner&tag \\pi][delim&delim-close $]");
+
+  CodeMirror.defineMode("identical_delim_multiplex", function() {
+    return CodeMirror.multiplexingMode(CodeMirror.getMode({indentUnit: 2}, "javascript"), {
+      open: "#",
+      close: "#",
+      mode: CodeMirror.getMode({}, "markdown"),
+      parseDelimiters: true,
+      innerStyle: "q"
+    });
+  });
+
+  var mode2 = CodeMirror.getMode({}, "identical_delim_multiplex");
+
+  test.mode("identical_delimiters_with_parseDelimiters", mode2, [
+    "[keyword let] [def x] [operator =] [q #foo][q&em *bar*][q #];"
+  ], "multiplexing")
 })();
diff --git a/help3/xhpeditor/cm/addon/mode/simple.js b/help3/xhpeditor/cm/addon/mode/simple.js
index 655f991..0d8cbde 100644
--- a/help3/xhpeditor/cm/addon/mode/simple.js
+++ b/help3/xhpeditor/cm/addon/mode/simple.js
@@ -68,6 +68,7 @@
     var flags = "";
     if (val instanceof RegExp) {
       if (val.ignoreCase) flags = "i";
+      if (val.unicode) flags += "u"
       val = val.source;
     } else {
       val = String(val);
@@ -137,10 +138,9 @@
           var token = rule.token
           if (token && token.apply) token = token(matches)
           if (matches.length > 2 && rule.token && typeof rule.token != "string") {
-            state.pending = [];
             for (var j = 2; j < matches.length; j++)
               if (matches[j])
-                state.pending.push({text: matches[j], token: rule.token[j - 1]});
+                (state.pending || (state.pending = [])).push({text: matches[j], token: rule.token[j - 1]});
             stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
             return token[0];
           } else if (token && token.join) {
diff --git a/help3/xhpeditor/cm/addon/runmode/runmode-standalone.js b/help3/xhpeditor/cm/addon/runmode/runmode-standalone.js
index 745eaf8..76cf3d7 100644
--- a/help3/xhpeditor/cm/addon/runmode/runmode-standalone.js
+++ b/help3/xhpeditor/cm/addon/runmode/runmode-standalone.js
@@ -1,158 +1,334 @@
-// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
-
-window.CodeMirror = {};
-
-(function() {
-"use strict";
-
-function splitLines(string){ return string.split(/\r?\n|\r/); };
-
-function StringStream(string) {
-  this.pos = this.start = 0;
-  this.string = string;
-  this.lineStart = 0;
-}
-StringStream.prototype = {
-  eol: function() {return this.pos >= this.string.length;},
-  sol: function() {return this.pos == 0;},
-  peek: function() {return this.string.charAt(this.pos) || null;},
-  next: function() {
+(function () {
+  'use strict';
+
+  function copyObj(obj, target, overwrite) {
+    if (!target) { target = {}; }
+    for (var prop in obj)
+      { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
+        { target[prop] = obj[prop]; } }
+    return target
+  }
+
+  // Counts the column offset in a string, taking tabs into account.
+  // Used mostly to find indentation.
+  function countColumn(string, end, tabSize, startIndex, startValue) {
+    if (end == null) {
+      end = string.search(/[^\s\u00a0]/);
+      if (end == -1) { end = string.length; }
+    }
+    for (var i = startIndex || 0, n = startValue || 0;;) {
+      var nextTab = string.indexOf("\t", i);
+      if (nextTab < 0 || nextTab >= end)
+        { return n + (end - i) }
+      n += nextTab - i;
+      n += tabSize - (n % tabSize);
+      i = nextTab + 1;
+    }
+  }
+
+  function nothing() {}
+
+  function createObj(base, props) {
+    var inst;
+    if (Object.create) {
+      inst = Object.create(base);
+    } else {
+      nothing.prototype = base;
+      inst = new nothing();
+    }
+    if (props) { copyObj(props, inst); }
+    return inst
+  }
+
+  // STRING STREAM
+
+  // Fed to the mode parsers, provides helper functions to make
+  // parsers more succinct.
+
+  var StringStream = function(string, tabSize, lineOracle) {
+    this.pos = this.start = 0;
+    this.string = string;
+    this.tabSize = tabSize || 8;
+    this.lastColumnPos = this.lastColumnValue = 0;
+    this.lineStart = 0;
+    this.lineOracle = lineOracle;
+  };
+
+  StringStream.prototype.eol = function () {return this.pos >= this.string.length};
+  StringStream.prototype.sol = function () {return this.pos == this.lineStart};
+  StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
+  StringStream.prototype.next = function () {
     if (this.pos < this.string.length)
-      return this.string.charAt(this.pos++);
-  },
-  eat: function(match) {
+      { return this.string.charAt(this.pos++) }
+  };
+  StringStream.prototype.eat = function (match) {
     var ch = this.string.charAt(this.pos);
-    if (typeof match == "string") var ok = ch == match;
-    else var ok = ch && (match.test ? match.test(ch) : match(ch));
-    if (ok) {++this.pos; return ch;}
-  },
-  eatWhile: function(match) {
+    var ok;
+    if (typeof match == "string") { ok = ch == match; }
+    else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
+    if (ok) {++this.pos; return ch}
+  };
+  StringStream.prototype.eatWhile = function (match) {
     var start = this.pos;
     while (this.eat(match)){}
-    return this.pos > start;
-  },
-  eatSpace: function() {
+    return this.pos > start
+  };
+  StringStream.prototype.eatSpace = function () {
     var start = this.pos;
-    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
-    return this.pos > start;
-  },
-  skipToEnd: function() {this.pos = this.string.length;},
-  skipTo: function(ch) {
+    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
+    return this.pos > start
+  };
+  StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
+  StringStream.prototype.skipTo = function (ch) {
     var found = this.string.indexOf(ch, this.pos);
-    if (found > -1) {this.pos = found; return true;}
-  },
-  backUp: function(n) {this.pos -= n;},
-  column: function() {return this.start - this.lineStart;},
-  indentation: function() {return 0;},
-  match: function(pattern, consume, caseInsensitive) {
+    if (found > -1) {this.pos = found; return true}
+  };
+  StringStream.prototype.backUp = function (n) {this.pos -= n;};
+  StringStream.prototype.column = function () {
+    if (this.lastColumnPos < this.start) {
+      this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
+      this.lastColumnPos = this.start;
+    }
+    return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+  };
+  StringStream.prototype.indentation = function () {
+    return countColumn(this.string, null, this.tabSize) -
+      (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+  };
+  StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
     if (typeof pattern == "string") {
-      var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
+      var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
       var substr = this.string.substr(this.pos, pattern.length);
       if (cased(substr) == cased(pattern)) {
-        if (consume !== false) this.pos += pattern.length;
-        return true;
+        if (consume !== false) { this.pos += pattern.length; }
+        return true
       }
     } else {
       var match = this.string.slice(this.pos).match(pattern);
-      if (match && match.index > 0) return null;
-      if (match && consume !== false) this.pos += match[0].length;
-      return match;
+      if (match && match.index > 0) { return null }
+      if (match && consume !== false) { this.pos += match[0].length; }
+      return match
     }
-  },
-  current: function(){return this.string.slice(this.start, this.pos);},
-  hideFirstChars: function(n, inner) {
+  };
+  StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
+  StringStream.prototype.hideFirstChars = function (n, inner) {
     this.lineStart += n;
-    try { return inner(); }
+    try { return inner() }
     finally { this.lineStart -= n; }
-  },
-  lookAhead: function() { return null }
-};
-CodeMirror.StringStream = StringStream;
-
-CodeMirror.startState = function (mode, a1, a2) {
-  return mode.startState ? mode.startState(a1, a2) : true;
-};
-
-var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {};
-CodeMirror.defineMode = function (name, mode) {
-  if (arguments.length > 2)
-    mode.dependencies = Array.prototype.slice.call(arguments, 2);
-  modes[name] = mode;
-};
-CodeMirror.defineMIME = function (mime, spec) { mimeModes[mime] = spec; };
-CodeMirror.resolveMode = function(spec) {
-  if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
-    spec = mimeModes[spec];
-  } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
-    spec = mimeModes[spec.name];
+  };
+  StringStream.prototype.lookAhead = function (n) {
+    var oracle = this.lineOracle;
+    return oracle && oracle.lookAhead(n)
+  };
+  StringStream.prototype.baseToken = function () {
+    var oracle = this.lineOracle;
+    return oracle && oracle.baseToken(this.pos)
+  };
+
+  // Known modes, by name and by MIME
+  var modes = {}, mimeModes = {};
+
+  // Extra arguments are stored as the mode's dependencies, which is
+  // used by (legacy) mechanisms like loadmode.js to automatically
+  // load a mode. (Preferred mechanism is the require/define calls.)
+  function defineMode(name, mode) {
+    if (arguments.length > 2)
+      { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
+    modes[name] = mode;
   }
-  if (typeof spec == "string") return {name: spec};
-  else return spec || {name: "null"};
-};
-CodeMirror.getMode = function (options, spec) {
-  spec = CodeMirror.resolveMode(spec);
-  var mfactory = modes[spec.name];
-  if (!mfactory) throw new Error("Unknown mode: " + spec);
-  return mfactory(options, spec);
-};
-CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
-CodeMirror.defineMode("null", function() {
-  return {token: function(stream) {stream.skipToEnd();}};
-});
-CodeMirror.defineMIME("text/plain", "null");
-
-CodeMirror.runMode = function (string, modespec, callback, options) {
-  var mode = CodeMirror.getMode({ indentUnit: 2 }, modespec);
-
-  if (callback.nodeType == 1) {
-    var tabSize = (options && options.tabSize) || 4;
-    var node = callback, col = 0;
-    node.innerHTML = "";
-    callback = function (text, style) {
-      if (text == "\n") {
-        node.appendChild(document.createElement("br"));
-        col = 0;
-        return;
-      }
-      var content = "";
-      // replace tabs
-      for (var pos = 0; ;) {
-        var idx = text.indexOf("\t", pos);
-        if (idx == -1) {
-          content += text.slice(pos);
-          col += text.length - pos;
-          break;
-        } else {
-          col += idx - pos;
-          content += text.slice(pos, idx);
-          var size = tabSize - col % tabSize;
-          col += size;
-          for (var i = 0; i < size; ++i) content += " ";
-          pos = idx + 1;
-        }
-      }
 
-      if (style) {
-        var sp = node.appendChild(document.createElement("span"));
-        sp.className = "cm-" + style.replace(/ +/g, " cm-");
-        sp.appendChild(document.createTextNode(content));
-      } else {
-        node.appendChild(document.createTextNode(content));
+  function defineMIME(mime, spec) {
+    mimeModes[mime] = spec;
+  }
+
+  // Given a MIME type, a {name, ...options} config object, or a name
+  // string, return a mode config object.
+  function resolveMode(spec) {
+    if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
+      spec = mimeModes[spec];
+    } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
+      var found = mimeModes[spec.name];
+      if (typeof found == "string") { found = {name: found}; }
+      spec = createObj(found, spec);
+      spec.name = found.name;
+    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
+      return resolveMode("application/xml")
+    } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
+      return resolveMode("application/json")
+    }
+    if (typeof spec == "string") { return {name: spec} }
+    else { return spec || {name: "null"} }
+  }
+
+  // Given a mode spec (anything that resolveMode accepts), find and
+  // initialize an actual mode object.
+  function getMode(options, spec) {
+    spec = resolveMode(spec);
+    var mfactory = modes[spec.name];
+    if (!mfactory) { return getMode(options, "text/plain") }
+    var modeObj = mfactory(options, spec);
+    if (modeExtensions.hasOwnProperty(spec.name)) {
+      var exts = modeExtensions[spec.name];
+      for (var prop in exts) {
+        if (!exts.hasOwnProperty(prop)) { continue }
+        if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; }
+        modeObj[prop] = exts[prop];
       }
-    };
+    }
+    modeObj.name = spec.name;
+    if (spec.helperType) { modeObj.helperType = spec.helperType; }
+    if (spec.modeProps) { for (var prop$1 in spec.modeProps)
+      { modeObj[prop$1] = spec.modeProps[prop$1]; } }
+
+    return modeObj
   }
 
-  var lines = splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
-  for (var i = 0, e = lines.length; i < e; ++i) {
-    if (i) callback("\n");
-    var stream = new CodeMirror.StringStream(lines[i]);
-    if (!stream.string && mode.blankLine) mode.blankLine(state);
-    while (!stream.eol()) {
-      var style = mode.token(stream, state);
-      callback(stream.current(), style, i, stream.start, state);
-      stream.start = stream.pos;
+  // This can be used to attach properties to mode objects from
+  // outside the actual mode definition.
+  var modeExtensions = {};
+  function extendMode(mode, properties) {
+    var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {});
+    copyObj(properties, exts);
+  }
+
+  function copyState(mode, state) {
+    if (state === true) { return state }
+    if (mode.copyState) { return mode.copyState(state) }
+    var nstate = {};
+    for (var n in state) {
+      var val = state[n];
+      if (val instanceof Array) { val = val.concat([]); }
+      nstate[n] = val;
     }
+    return nstate
+  }
+
+  // Given a mode and a state (for that mode), find the inner mode and
+  // state at the position that the state refers to.
+  function innerMode(mode, state) {
+    var info;
+    while (mode.innerMode) {
+      info = mode.innerMode(state);
+      if (!info || info.mode == mode) { break }
+      state = info.state;
+      mode = info.mode;
+    }
+    return info || {mode: mode, state: state}
+  }
+
+  function startState(mode, a1, a2) {
+    return mode.startState ? mode.startState(a1, a2) : true
   }
-};
-})();
+
+  var modeMethods = {
+    __proto__: null,
+    modes: modes,
+    mimeModes: mimeModes,
+    defineMode: defineMode,
+    defineMIME: defineMIME,
+    resolveMode: resolveMode,
+    getMode: getMode,
+    modeExtensions: modeExtensions,
+    extendMode: extendMode,
+    copyState: copyState,
+    innerMode: innerMode,
+    startState: startState
+  };
+
+  // declare global: globalThis, CodeMirror
+
+  // Create a minimal CodeMirror needed to use runMode, and assign to root.
+  var root = typeof globalThis !== 'undefined' ? globalThis : window;
+  root.CodeMirror = {};
+
+  // Copy StringStream and mode methods into CodeMirror object.
+  CodeMirror.StringStream = StringStream;
+  for (var exported in modeMethods) { CodeMirror[exported] = modeMethods[exported]; }
+
+  // Minimal default mode.
+  CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); });
+  CodeMirror.defineMIME("text/plain", "null");
+
+  CodeMirror.registerHelper = CodeMirror.registerGlobalHelper = Math.min;
+  CodeMirror.splitLines = function(string) { return string.split(/\r?\n|\r/) };
+  CodeMirror.countColumn = countColumn;
+
+  CodeMirror.defaults = { indentUnit: 2 };
+
+  // CodeMirror, copyright (c) by Marijn Haverbeke and others
+  // Distributed under an MIT license: https://codemirror.net/LICENSE
+
+  (function(mod) {
+    if (typeof exports == "object" && typeof module == "object") // CommonJS
+      { mod(require("../../lib/codemirror")); }
+    else if (typeof define == "function" && define.amd) // AMD
+      { define(["../../lib/codemirror"], mod); }
+    else // Plain browser env
+      { mod(CodeMirror); }
+  })(function(CodeMirror) {
+
+  CodeMirror.runMode = function(string, modespec, callback, options) {
+    var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
+    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
+
+    // Create a tokenizing callback function if passed-in callback is a DOM element.
+    if (callback.appendChild) {
+      var ie = /MSIE \d/.test(navigator.userAgent);
+      var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+      var node = callback, col = 0;
+      node.innerHTML = "";
+      callback = function(text, style) {
+        if (text == "\n") {
+          // Emitting LF or CRLF on IE8 or earlier results in an incorrect display.
+          // Emitting a carriage return makes everything ok.
+          node.appendChild(document.createTextNode(ie_lt9 ? '\r' : text));
+          col = 0;
+          return;
+        }
+        var content = "";
+        // replace tabs
+        for (var pos = 0;;) {
+          var idx = text.indexOf("\t", pos);
+          if (idx == -1) {
+            content += text.slice(pos);
+            col += text.length - pos;
+            break;
+          } else {
+            col += idx - pos;
+            content += text.slice(pos, idx);
+            var size = tabSize - col % tabSize;
+            col += size;
+            for (var i = 0; i < size; ++i) { content += " "; }
+            pos = idx + 1;
+          }
+        }
+        // Create a node with token style and append it to the callback DOM element.
+        if (style) {
+          var sp = node.appendChild(document.createElement("span"));
+          sp.className = "cm-" + style.replace(/ +/g, " cm-");
+          sp.appendChild(document.createTextNode(content));
+        } else {
+          node.appendChild(document.createTextNode(content));
+        }
+      };
+    }
+
+    var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
+    for (var i = 0, e = lines.length; i < e; ++i) {
+      if (i) { callback("\n"); }
+      var stream = new CodeMirror.StringStream(lines[i], null, {
+        lookAhead: function(n) { return lines[i + n] },
+        baseToken: function() {}
+      });
+      if (!stream.string && mode.blankLine) { mode.blankLine(state); }
+      while (!stream.eol()) {
+        var style = mode.token(stream, state);
+        callback(stream.current(), style, i, stream.start, state, mode);
+        stream.start = stream.pos;
+      }
+    }
+  };
+
+  });
+
+}());
diff --git a/help3/xhpeditor/cm/addon/runmode/runmode.js b/help3/xhpeditor/cm/addon/runmode/runmode.js
index eb4cadf..f5d58e2 100644
--- a/help3/xhpeditor/cm/addon/runmode/runmode.js
+++ b/help3/xhpeditor/cm/addon/runmode/runmode.js
@@ -13,11 +13,12 @@
 
 CodeMirror.runMode = function(string, modespec, callback, options) {
   var mode = CodeMirror.getMode(CodeMirror.defaults, modespec);
-  var ie = /MSIE \d/.test(navigator.userAgent);
-  var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
+  var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
 
+  // Create a tokenizing callback function if passed-in callback is a DOM element.
   if (callback.appendChild) {
-    var tabSize = (options && options.tabSize) || CodeMirror.defaults.tabSize;
+    var ie = /MSIE \d/.test(navigator.userAgent);
+    var ie_lt9 = ie && (document.documentMode == null || document.documentMode < 9);
     var node = callback, col = 0;
     node.innerHTML = "";
     callback = function(text, style) {
@@ -45,7 +46,7 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
           pos = idx + 1;
         }
       }
-
+      // Create a node with token style and append it to the callback DOM element.
       if (style) {
         var sp = node.appendChild(document.createElement("span"));
         sp.className = "cm-" + style.replace(/ +/g, " cm-");
@@ -59,11 +60,14 @@ CodeMirror.runMode = function(string, modespec, callback, options) {
   var lines = CodeMirror.splitLines(string), state = (options && options.state) || CodeMirror.startState(mode);
   for (var i = 0, e = lines.length; i < e; ++i) {
     if (i) callback("\n");
-    var stream = new CodeMirror.StringStream(lines[i]);
+    var stream = new CodeMirror.StringStream(lines[i], null, {
+      lookAhead: function(n) { return lines[i + n] },
+      baseToken: function() {}
+    });
     if (!stream.string && mode.blankLine) mode.blankLine(state);
     while (!stream.eol()) {
       var style = mode.token(stream, state);
-      callback(stream.current(), style, i, stream.start, state);
+      callback(stream.current(), style, i, stream.start, state, mode);
       stream.start = stream.pos;
     }
   }
diff --git a/help3/xhpeditor/cm/addon/runmode/runmode.node.js b/help3/xhpeditor/cm/addon/runmode/runmode.node.js
index 53b6994..ddd255a 100644
--- a/help3/xhpeditor/cm/addon/runmode/runmode.node.js
+++ b/help3/xhpeditor/cm/addon/runmode/runmode.node.js
@@ -1,197 +1,329 @@
-// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
-
-/* Just enough of CodeMirror to run runMode under node.js */
+'use strict';
 
-function splitLines(string){return string.split(/\r\n?|\n/);};
+function copyObj(obj, target, overwrite) {
+  if (!target) { target = {}; }
+  for (var prop in obj)
+    { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
+      { target[prop] = obj[prop]; } }
+  return target
+}
 
 // Counts the column offset in a string, taking tabs into account.
 // Used mostly to find indentation.
-var countColumn = exports.countColumn = function(string, end, tabSize, startIndex, startValue) {
+function countColumn(string, end, tabSize, startIndex, startValue) {
   if (end == null) {
     end = string.search(/[^\s\u00a0]/);
-    if (end == -1) end = string.length;
+    if (end == -1) { end = string.length; }
   }
   for (var i = startIndex || 0, n = startValue || 0;;) {
     var nextTab = string.indexOf("\t", i);
     if (nextTab < 0 || nextTab >= end)
-      return n + (end - i);
+      { return n + (end - i) }
     n += nextTab - i;
     n += tabSize - (n % tabSize);
     i = nextTab + 1;
   }
-};
+}
+
+function nothing() {}
+
+function createObj(base, props) {
+  var inst;
+  if (Object.create) {
+    inst = Object.create(base);
+  } else {
+    nothing.prototype = base;
+    inst = new nothing();
+  }
+  if (props) { copyObj(props, inst); }
+  return inst
+}
+
+// STRING STREAM
 
-function StringStream(string, tabSize, context) {
+// Fed to the mode parsers, provides helper functions to make
+// parsers more succinct.
+
+var StringStream = function(string, tabSize, lineOracle) {
   this.pos = this.start = 0;
   this.string = string;
   this.tabSize = tabSize || 8;
   this.lastColumnPos = this.lastColumnValue = 0;
   this.lineStart = 0;
-  this.context = context
+  this.lineOracle = lineOracle;
 };
 
-StringStream.prototype = {
-  eol: function() {return this.pos >= this.string.length;},
-  sol: function() {return this.pos == this.lineStart;},
-  peek: function() {return this.string.charAt(this.pos) || undefined;},
-  next: function() {
-    if (this.pos < this.string.length)
-      return this.string.charAt(this.pos++);
-  },
-  eat: function(match) {
-    var ch = this.string.charAt(this.pos);
-    if (typeof match == "string") var ok = ch == match;
-    else var ok = ch && (match.test ? match.test(ch) : match(ch));
-    if (ok) {++this.pos; return ch;}
-  },
-  eatWhile: function(match) {
-    var start = this.pos;
-    while (this.eat(match)){}
-    return this.pos > start;
-  },
-  eatSpace: function() {
-    var start = this.pos;
-    while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos;
-    return this.pos > start;
-  },
-  skipToEnd: function() {this.pos = this.string.length;},
-  skipTo: function(ch) {
-    var found = this.string.indexOf(ch, this.pos);
-    if (found > -1) {this.pos = found; return true;}
-  },
-  backUp: function(n) {this.pos -= n;},
-  column: function() {
-    if (this.lastColumnPos < this.start) {
-      this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
-      this.lastColumnPos = this.start;
-    }
-    return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
-  },
-  indentation: function() {
-    return countColumn(this.string, null, this.tabSize) -
-      (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0);
-  },
-  match: function(pattern, consume, caseInsensitive) {
-    if (typeof pattern == "string") {
-      var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;};
-      var substr = this.string.substr(this.pos, pattern.length);
-      if (cased(substr) == cased(pattern)) {
-        if (consume !== false) this.pos += pattern.length;
-        return true;
-      }
-    } else {
-      var match = this.string.slice(this.pos).match(pattern);
-      if (match && match.index > 0) return null;
-      if (match && consume !== false) this.pos += match[0].length;
-      return match;
+StringStream.prototype.eol = function () {return this.pos >= this.string.length};
+StringStream.prototype.sol = function () {return this.pos == this.lineStart};
+StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined};
+StringStream.prototype.next = function () {
+  if (this.pos < this.string.length)
+    { return this.string.charAt(this.pos++) }
+};
+StringStream.prototype.eat = function (match) {
+  var ch = this.string.charAt(this.pos);
+  var ok;
+  if (typeof match == "string") { ok = ch == match; }
+  else { ok = ch && (match.test ? match.test(ch) : match(ch)); }
+  if (ok) {++this.pos; return ch}
+};
+StringStream.prototype.eatWhile = function (match) {
+  var start = this.pos;
+  while (this.eat(match)){}
+  return this.pos > start
+};
+StringStream.prototype.eatSpace = function () {
+  var start = this.pos;
+  while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; }
+  return this.pos > start
+};
+StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;};
+StringStream.prototype.skipTo = function (ch) {
+  var found = this.string.indexOf(ch, this.pos);
+  if (found > -1) {this.pos = found; return true}
+};
+StringStream.prototype.backUp = function (n) {this.pos -= n;};
+StringStream.prototype.column = function () {
+  if (this.lastColumnPos < this.start) {
+    this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue);
+    this.lastColumnPos = this.start;
+  }
+  return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+};
+StringStream.prototype.indentation = function () {
+  return countColumn(this.string, null, this.tabSize) -
+    (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
+};
+StringStream.prototype.match = function (pattern, consume, caseInsensitive) {
+  if (typeof pattern == "string") {
+    var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; };
+    var substr = this.string.substr(this.pos, pattern.length);
+    if (cased(substr) == cased(pattern)) {
+      if (consume !== false) { this.pos += pattern.length; }
+      return true
     }
-  },
-  current: function(){return this.string.slice(this.start, this.pos);},
-  hideFirstChars: function(n, inner) {
-    this.lineStart += n;
-    try { return inner(); }
-    finally { this.lineStart -= n; }
-  },
-  lookAhead: function(n) {
-    var line = this.context.line + n
-    return line >= this.context.lines.length ? null : this.context.lines[line]
+  } else {
+    var match = this.string.slice(this.pos).match(pattern);
+    if (match && match.index > 0) { return null }
+    if (match && consume !== false) { this.pos += match[0].length; }
+    return match
   }
 };
-exports.StringStream = StringStream;
-
-exports.startState = function(mode, a1, a2) {
-  return mode.startState ? mode.startState(a1, a2) : true;
+StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)};
+StringStream.prototype.hideFirstChars = function (n, inner) {
+  this.lineStart += n;
+  try { return inner() }
+  finally { this.lineStart -= n; }
+};
+StringStream.prototype.lookAhead = function (n) {
+  var oracle = this.lineOracle;
+  return oracle && oracle.lookAhead(n)
+};
+StringStream.prototype.baseToken = function () {
+  var oracle = this.lineOracle;
+  return oracle && oracle.baseToken(this.pos)
 };
 
-var modes = exports.modes = {}, mimeModes = exports.mimeModes = {};
-exports.defineMode = function(name, mode) {
+// Known modes, by name and by MIME
+var modes = {}, mimeModes = {};
+
+// Extra arguments are stored as the mode's dependencies, which is
+// used by (legacy) mechanisms like loadmode.js to automatically
+// load a mode. (Preferred mechanism is the require/define calls.)
+function defineMode(name, mode) {
   if (arguments.length > 2)
-    mode.dependencies = Array.prototype.slice.call(arguments, 2);
+    { mode.dependencies = Array.prototype.slice.call(arguments, 2); }
   modes[name] = mode;
-};
-exports.defineMIME = function(mime, spec) { mimeModes[mime] = spec; };
+}
 
-exports.defineMode("null", function() {
-  return {token: function(stream) {stream.skipToEnd();}};
-});
-exports.defineMIME("text/plain", "null");
+function defineMIME(mime, spec) {
+  mimeModes[mime] = spec;
+}
 
-exports.resolveMode = function(spec) {
+// Given a MIME type, a {name, ...options} config object, or a name
+// string, return a mode config object.
+function resolveMode(spec) {

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list