From 77380014bbab2ac0341a80942a81e597551bb7eb Mon Sep 17 00:00:00 2001
From: Gvx
Date: Mon, 14 Nov 2022 20:54:31 +0100
Subject: [PATCH] Version 2.3.0
---
CHANGELOG.md | 82 +-
README.md | 2 +-
dcScript/CHANGELOG.md | 8 +-
dcScript/_admin.php | 4 +-
dcScript/_config.php | 4 +-
dcScript/_define.php | 16 +-
dcScript/_init.php | 24 +
dcScript/_install.php | 4 +-
dcScript/_prepend.php | 10 +-
dcScript/_public.php | 4 +-
dcScript/bin/build.bat | 86 ++
dcScript/bin/excludes.txt | 6 +
dcScript/bin/phpStan.bat | 20 +
dcScript/bin/phpstan.bootstrap.php | 42 +
dcScript/bin/release.bat | 81 ++
dcScript/codemirror/addon/comment/comment.js | 8 +-
.../addon/comment/continuecomment.js | 114 +++
dcScript/codemirror/addon/dialog/dialog.css | 32 +
dcScript/codemirror/addon/dialog/dialog.js | 6 +-
.../codemirror/addon/display/autorefresh.js | 47 +
.../codemirror/addon/display/fullscreen.css | 6 +
.../codemirror/addon/display/fullscreen.js | 2 +-
dcScript/codemirror/addon/display/panel.js | 133 +++
.../codemirror/addon/display/placeholder.js | 78 ++
dcScript/codemirror/addon/display/rulers.js | 51 +
.../codemirror/addon/edit/closebrackets.js | 201 ++++
dcScript/codemirror/addon/edit/closetag.js | 185 ++++
.../codemirror/addon/edit/continuelist.js | 101 ++
.../codemirror/addon/edit/matchbrackets.js | 30 +-
dcScript/codemirror/addon/edit/matchtags.js | 2 +-
.../codemirror/addon/edit/trailingspace.js | 2 +-
dcScript/codemirror/addon/fold/brace-fold.js | 96 +-
.../codemirror/addon/fold/comment-fold.js | 2 +-
dcScript/codemirror/addon/fold/foldcode.js | 12 +-
dcScript/codemirror/addon/fold/foldgutter.css | 20 +
dcScript/codemirror/addon/fold/foldgutter.js | 8 +-
dcScript/codemirror/addon/fold/indent-fold.js | 2 +-
.../codemirror/addon/fold/markdown-fold.js | 49 +
dcScript/codemirror/addon/fold/xml-fold.js | 2 +-
.../codemirror/addon/search/jump-to-line.js | 53 ++
.../addon/search/match-highlighter.js | 167 ++++
.../addon/search/matchesonscrollbar.css | 8 +
.../addon/search/matchesonscrollbar.js | 97 ++
dcScript/codemirror/addon/search/search.js | 53 +-
.../codemirror/addon/search/searchcursor.js | 33 +-
.../codemirror/addon/selection/active-line.js | 2 +-
.../addon/selection/mark-selection.js | 119 +++
.../addon/selection/selection-pointer.js | 98 ++
dcScript/codemirror/lib/codemirror.css | 33 +-
dcScript/codemirror/lib/codemirror.js | 889 ++++++++++--------
dcScript/codemirror/mode/css/css.js | 281 +++---
dcScript/codemirror/mode/css/gss.html | 104 ++
dcScript/codemirror/mode/css/gss_test.js | 17 +
dcScript/codemirror/mode/css/index.html | 81 ++
dcScript/codemirror/mode/css/less.html | 152 +++
dcScript/codemirror/mode/css/less_test.js | 54 ++
dcScript/codemirror/mode/css/scss.html | 158 ++++
dcScript/codemirror/mode/css/scss_test.js | 110 +++
dcScript/codemirror/mode/css/test.js | 217 +++++
.../codemirror/mode/htmlmixed/htmlmixed.js | 7 +-
dcScript/codemirror/mode/htmlmixed/index.html | 100 ++
.../codemirror/mode/javascript/index.html | 118 +++
.../codemirror/mode/javascript/javascript.js | 78 +-
.../codemirror/mode/javascript/json-ld.html | 72 ++
dcScript/codemirror/mode/javascript/test.js | 521 ++++++++++
.../mode/javascript/typescript.html | 62 ++
dcScript/codemirror/mode/xml/index.html | 61 ++
dcScript/codemirror/mode/xml/test.js | 51 +
dcScript/codemirror/mode/xml/xml.js | 24 +-
dcScript/dcstore.xml | 13 +
.../class.dcPluginHelper224.php} | 285 +++---
dcScript/inc/class.dcScript.php | 217 ++---
dcScript/inc/css/index.css | 4 +-
dcScript/inc/js/index.js | 4 +-
dcScript/inc/js/index_warning.js | 4 +-
dcScript/index.php | 4 +-
dcScript/locales/en/resources.php | 4 +-
dcScript/locales/fr/resources.php | 4 +-
dcScript/phpstan.neon | 132 +++
dcScript/tools/decrypt.php | 2 +-
dcstore.xml | 13 +
81 files changed, 5049 insertions(+), 1039 deletions(-)
create mode 100644 dcScript/_init.php
create mode 100644 dcScript/bin/build.bat
create mode 100644 dcScript/bin/excludes.txt
create mode 100644 dcScript/bin/phpStan.bat
create mode 100644 dcScript/bin/phpstan.bootstrap.php
create mode 100644 dcScript/bin/release.bat
create mode 100644 dcScript/codemirror/addon/comment/continuecomment.js
create mode 100644 dcScript/codemirror/addon/dialog/dialog.css
create mode 100644 dcScript/codemirror/addon/display/autorefresh.js
create mode 100644 dcScript/codemirror/addon/display/fullscreen.css
create mode 100644 dcScript/codemirror/addon/display/panel.js
create mode 100644 dcScript/codemirror/addon/display/placeholder.js
create mode 100644 dcScript/codemirror/addon/display/rulers.js
create mode 100644 dcScript/codemirror/addon/edit/closebrackets.js
create mode 100644 dcScript/codemirror/addon/edit/closetag.js
create mode 100644 dcScript/codemirror/addon/edit/continuelist.js
create mode 100644 dcScript/codemirror/addon/fold/foldgutter.css
create mode 100644 dcScript/codemirror/addon/fold/markdown-fold.js
create mode 100644 dcScript/codemirror/addon/search/jump-to-line.js
create mode 100644 dcScript/codemirror/addon/search/match-highlighter.js
create mode 100644 dcScript/codemirror/addon/search/matchesonscrollbar.css
create mode 100644 dcScript/codemirror/addon/search/matchesonscrollbar.js
create mode 100644 dcScript/codemirror/addon/selection/mark-selection.js
create mode 100644 dcScript/codemirror/addon/selection/selection-pointer.js
create mode 100644 dcScript/codemirror/mode/css/gss.html
create mode 100644 dcScript/codemirror/mode/css/gss_test.js
create mode 100644 dcScript/codemirror/mode/css/index.html
create mode 100644 dcScript/codemirror/mode/css/less.html
create mode 100644 dcScript/codemirror/mode/css/less_test.js
create mode 100644 dcScript/codemirror/mode/css/scss.html
create mode 100644 dcScript/codemirror/mode/css/scss_test.js
create mode 100644 dcScript/codemirror/mode/css/test.js
create mode 100644 dcScript/codemirror/mode/htmlmixed/index.html
create mode 100644 dcScript/codemirror/mode/javascript/index.html
create mode 100644 dcScript/codemirror/mode/javascript/json-ld.html
create mode 100644 dcScript/codemirror/mode/javascript/test.js
create mode 100644 dcScript/codemirror/mode/javascript/typescript.html
create mode 100644 dcScript/codemirror/mode/xml/index.html
create mode 100644 dcScript/codemirror/mode/xml/test.js
create mode 100644 dcScript/dcstore.xml
rename dcScript/inc/{class.dcPluginHelper.php => _dcPluginHelper/class.dcPluginHelper224.php} (64%)
create mode 100644 dcScript/phpstan.neon
create mode 100644 dcstore.xml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34f0667..ab1d201 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,40 +1,42 @@
-Changelog
-=========
-
-Version 2.2.0 (2020-04-xx)
---------------------------
-
-* Correctifs divers
-* Mise a niveau dcPluginHelper 216
-* Version mini dc 2.16
-
-Version 2.1.2 (2020-04-07)
---------------------------
-
-* Correctif insertion cote public
-* Correctif sauvegarde settings
-
-Version 2.1.1 (2020-04-04)
---------------------------
-
-* Correctif algorithme de cryptage
-
-Version 2.1.0 (2020-03-30)
---------------------------
-
-* Suppression de la dépendance a jQuery
-* Passage a la version 5.52.0 de CodeMirror
-* Changement de système de cryptage compatible PHP 7.2
-* Mise a jour support
-* Correction procédure désinstallation
-* Corrections divers
-
-Version 2.0.1 (2016-03-05)
---------------------------
-
-* Correctif insertion cote public
-
-Version 2.0.0 (2015-10-16)
---------------------------
-
-* Première release publique
+Changelog
+=========
+
+Version 2.3.0 (2022-11-14)
+--------------------------
+
+* Mise a niveau dcPluginHelper pour dc 2.24
+* Version mini dc 2.24
+* Ajout d'un depot alternatif
+* Passage a la version 5.65.9 de CodeMirror
+* Correctifs divers
+
+Version 2.1.2 (2020-04-07)
+--------------------------
+
+* Correctif insertion cote public
+* Correctif sauvegarde settings
+
+Version 2.1.1 (2020-04-04)
+--------------------------
+
+* Correctif algorithme de cryptage
+
+Version 2.1.0 (2020-03-30)
+--------------------------
+
+* Suppression de la dépendance a jQuery
+* Passage a la version 5.52.0 de CodeMirror
+* Changement de système de cryptage compatible PHP 7.2
+* Mise a jour support
+* Correction procédure désinstallation
+* Corrections divers
+
+Version 2.0.1 (2016-03-05)
+--------------------------
+
+* Correctif insertion cote public
+
+Version 2.0.0 (2015-10-16)
+--------------------------
+
+* Première release publique
diff --git a/README.md b/README.md
index d79973d..4e53ae0 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ L'éditeur de code utilise la coloration syntaxique de [CodeMirror](https://code
## Pré-requis ##
-* Dotclear 2.8 ou plus
+* Dotclear 2.24 ou plus
## Utilisation ##
diff --git a/dcScript/CHANGELOG.md b/dcScript/CHANGELOG.md
index 0485c4a..ab1d201 100644
--- a/dcScript/CHANGELOG.md
+++ b/dcScript/CHANGELOG.md
@@ -1,12 +1,14 @@
Changelog
=========
-Version 2.2.0 (2020-05-xx)
+Version 2.3.0 (2022-11-14)
--------------------------
+* Mise a niveau dcPluginHelper pour dc 2.24
+* Version mini dc 2.24
+* Ajout d'un depot alternatif
+* Passage a la version 5.65.9 de CodeMirror
* Correctifs divers
-* Mise a niveau dcPluginHelper 216
-* Version mini dc 2.16
Version 2.1.2 (2020-04-07)
--------------------------
diff --git a/dcScript/_admin.php b/dcScript/_admin.php
index 4c932bb..723e60f 100644
--- a/dcScript/_admin.php
+++ b/dcScript/_admin.php
@@ -5,10 +5,10 @@
* @package Dotclear\plungin\dcScript
*
* @author Gvx
- * @copyright © 2014-2020 Gvx
+ * @copyright © 2014-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
if(!defined('DC_CONTEXT_ADMIN')) { return; }
-$core->dcScript->_admin();
+dcCore::app()->dcScript->_admin();
diff --git a/dcScript/_config.php b/dcScript/_config.php
index 4592e1d..bc518fb 100644
--- a/dcScript/_config.php
+++ b/dcScript/_config.php
@@ -5,10 +5,10 @@
* @package Dotclear\plungin\dcScript
*
* @author Gvx
- * @copyright © 2014-2020 Gvx
+ * @copyright © 2014-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
if(!defined('DC_CONTEXT_ADMIN')) { return; }
-$core->dcScript->_config();
+dcCore::app()->dcScript->_config();
diff --git a/dcScript/_define.php b/dcScript/_define.php
index 93dbeaa..c1913d3 100644
--- a/dcScript/_define.php
+++ b/dcScript/_define.php
@@ -5,7 +5,7 @@
* @package Dotclear\plungin\dcScript
*
* @author Gvx
- * @copyright © 2014-2020 Gvx
+ * @copyright © 2014-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
@@ -15,17 +15,23 @@
/* Name */ 'dcScript',
/* Description*/ 'Add script for DC',
/* Author */ 'Gvx',
- /* Version */ '2.2.0-dev-r0015',
+ /* Version */ '2.3.0',
array(
/* standard plugin options dotclear */
- 'permissions' => 'dcScript.edit',
+ 'permissions' => dcCore::app()->auth->makePermissions([dcScriptPerms::EDIT]),
'type' => 'plugin',
'Priority' => 1010,
'support' /* url */ => 'http://forum.dotclear.org/viewtopic.php?pid=335785#p335785',
'details' /* url */ => 'https://github.com/Gvx-/dcScript',
'requires' /* id(s) */ => array(
- array('core', '2.16')
+ array('core', '2.24')
),
+ 'settings' => array(
+ //'self' => '', // Optionnal: '#onglet' (or false since 2.17)
+ //'blog' => '#params.id', // Optionnal: '#params.id'
+ //'pref' => '#user-options.id', // Optionnal: '#user-options.id'
+ ),
+ 'repository' => 'https://raw.githubusercontent.com/Gvx-/dcScript/master/dcstore.xml', // Optionnal: URL
/* specific plugin options */
'_class_name' => 'dcScript', // Required: plugin master class name
'_class_path' => '/inc/class.dcScript.php', // Required: plugin master class path (relative)
@@ -35,6 +41,6 @@
);
# ---------------------------------------------------------
-# use codemirror version 5.52.0
+# use codemirror version 5.65.9
# see: http://codemirror.net/
# ---------------------------------------------------------
diff --git a/dcScript/_init.php b/dcScript/_init.php
new file mode 100644
index 0000000..4a2a3c6
--- /dev/null
+++ b/dcScript/_init.php
@@ -0,0 +1,24 @@
+
+ * @copyright © 2014-2022 Gvx
+ * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ */
+
+if(!defined('DC_RC_PATH')) { return; }
+
+
+class dcScriptPerms {
+ // Constants
+
+ /**
+ * dcScript permission
+ *
+ * @var string
+ */
+ public const EDIT = 'dcScript.edit';
+}
diff --git a/dcScript/_install.php b/dcScript/_install.php
index 259f67d..122dcf8 100644
--- a/dcScript/_install.php
+++ b/dcScript/_install.php
@@ -5,10 +5,10 @@
* @package Dotclear\plungin\dcScript
*
* @author Gvx
- * @copyright © 2014-2020 Gvx
+ * @copyright © 2014-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
if(!defined('DC_CONTEXT_ADMIN')) { return; }
-return $core->dcScript->_install();
+return dcCore::app()->dcScript->_install();
diff --git a/dcScript/_prepend.php b/dcScript/_prepend.php
index 076e223..0cadcb7 100644
--- a/dcScript/_prepend.php
+++ b/dcScript/_prepend.php
@@ -5,18 +5,18 @@
* @package Dotclear\plungin\dcScript
*
* @author Gvx
- * @copyright © 2014-2020 Gvx
+ * @copyright © 2014-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
if(!defined('DC_RC_PATH')) { return; }
# define id and class specific plugin
-$pluginId = basename(dirname(__FILE__));
-$pluginClassName = $core->plugins->moduleInfo($pluginId, '_class_name');
+$pluginId = basename(__DIR__);
+$pluginClassName = dcCore::app()->plugins->moduleInfo($pluginId, '_class_name');
# Loadings & initialization
if(!empty($pluginClassName)) {
- $__autoload[$pluginClassName] = dirname(__FILE__).$core->plugins->moduleInfo($pluginId, '_class_path');
- $core->{$pluginClassName} = new $pluginClassName($core, $pluginId);
+ Clearbricks::lib()->autoload([$pluginClassName => __DIR__.dcCore::app()->plugins->moduleInfo($pluginId, '_class_path')]);
+ dcCore::app()->{$pluginClassName} = new $pluginClassName($pluginId);
}
diff --git a/dcScript/_public.php b/dcScript/_public.php
index 8512d96..67c447b 100644
--- a/dcScript/_public.php
+++ b/dcScript/_public.php
@@ -5,10 +5,10 @@
* @package Dotclear\plungin\dcScript
*
* @author Gvx
- * @copyright © 2014-2020 Gvx
+ * @copyright © 2014-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
if(!defined('DC_RC_PATH')) { return; }
-$core->dcScript->_public();
+dcCore::app()->dcScript->_public();
diff --git a/dcScript/bin/build.bat b/dcScript/bin/build.bat
new file mode 100644
index 0000000..ea58cf9
--- /dev/null
+++ b/dcScript/bin/build.bat
@@ -0,0 +1,86 @@
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+:: Build plugin dotclear
+:: Author : Gilles Grandveaux
+:: Copyright: (c)2020 Gilles Grandveaux
+:: License : http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+:: Changelog
+::
+:: * 08/11/2022 V0.1.3.0
+:: Changement de structure copie d'un dossier
+:: * 18/04/2020 V0.1.2.3
+:: Correction exit sur message d'erreur et help
+:: Correction protection des noms de fichiers
+:: * 15/04/2020 V0.1.1.2
+:: Correction check paramettres
+:: * 15/04/2020 V0.1.0.1
+:: version initiale
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+@echo off
+
+setlocal enabledelayedexpansion
+:: Version script
+set VERSION=0.1.2.3
+
+if /I "%~1"=="-h" goto :help
+if /I "%~1"=="--help" goto :help
+if /I "%~1"=="-v" echo %VERSION% & exit /b
+if /I "%~1"=="--version" echo %VERSION% & exit /b
+if NOT [%1]==[] goto :help
+
+:: TODO: initialiser et
+::set source=%~dp0..\..\dcHelper\inc\class.dcPluginHelper.php
+::set dest=%~dp0..\inc\class.dcPluginHelper.php
+
+set source=%~dp0..\..\dcHelper\inc\_dcPluginHelper\*.*
+set dest=%~dp0..\inc\_dcPluginHelper\
+
+
+call :parsePath f %source% source
+call :parsePath f %dest% dest
+
+if not exist %source% call :fileError %source%
+::if not exist %dest% call :fileError %dest%
+
+::copy /y "%source%" "%dest%" >NUL
+xcopy "%source%" "%dest%" /Q /I /T /E /Y >NUL
+
+endlocal
+exit /b
+
+:help
+echo --== HELP ==--
+echo.
+echo Usage: %~n0 [^<-v^>^|^<--version^>^|^<-h^>^|^<--help^>]
+echo.
+echo ^<-v^>^|^<--version^> : Display version
+echo ^<-h^>^|^<--help^> : Display help
+echo.
+echo --== HELP ==--
+pause
+exit /b 1
+
+:fileError
+echo --== ERREUR ==--
+echo.
+echo le fichier "%~1" n'a pas ete trouve.
+echo.
+echo --== ERREUR ==--
+pause
+exit 2
+
+:parsePath
+set %3=%~f2
+if /I "%~1"=="d" set %3=%~d2
+if /I "%~1"=="p" set %3=%~p2
+if /I "%~1"=="n" set %3=%~n2
+if /I "%~1"=="x" set %3=%~x2
+if /I "%~1"=="f" set %3=%~f2
+if /I "%~1"=="s" set %3=%~s2
+if /I "%~1"=="a" set %3=%~a2
+if /I "%~1"=="t" set %3=%~t2
+if /I "%~1"=="z" set %3=%~z2
+if /I "%~1"=="dp" set %3=%~dp2
+if /I "%~1"=="nx" set %3=%~nx2
+if /I "%~1"=="pathSearch" set %3=%~$PATH:2 rem search in PATH
+goto:eof
diff --git a/dcScript/bin/excludes.txt b/dcScript/bin/excludes.txt
new file mode 100644
index 0000000..104f2d3
--- /dev/null
+++ b/dcScript/bin/excludes.txt
@@ -0,0 +1,6 @@
+\build-tools\
+.git
+.vscode
+.debug.php
+*.bck.zip
+
diff --git a/dcScript/bin/phpStan.bat b/dcScript/bin/phpStan.bat
new file mode 100644
index 0000000..b513ebb
--- /dev/null
+++ b/dcScript/bin/phpStan.bat
@@ -0,0 +1,20 @@
+@echo off
+set errorCode=0
+
+set project=%~dp0..\phpStan.neon
+if not exist %project% goto :error
+echo phpStan analyse en cours...
+php %userprofile%\vendor\phpstan\phpstan\phpstan analyse -c "%project%"
+goto :endBatch
+
+:error
+echo.
+echo /!\ -- Le fichier %project% n'a pas ete trouve.
+echo.
+set errorCode=1
+
+:: https://askcodez.com/conditionnel-pause-pas-en-ligne-de-commande.html
+:endBatch
+echo.%cmdcmdline% | find /I "%~0" >nul
+if not errorlevel 1 pause
+exit /b %errorCode%
diff --git a/dcScript/bin/phpstan.bootstrap.php b/dcScript/bin/phpstan.bootstrap.php
new file mode 100644
index 0000000..ded5a44
--- /dev/null
+++ b/dcScript/bin/phpstan.bootstrap.php
@@ -0,0 +1,42 @@
+ et
+set source=%~dp0..
+call :parsePath nx %source% plugin
+set dest=%USERPROFILE%\Documents\__mesDocs\Git\%plugin%\%plugin%\
+
+call :parsePath f %source% source
+call :parsePath f %dest% dest
+
+if not exist %source% call :fileError %source%
+if not exist %dest% call :fileError %dest%
+
+del /f /s /q "%dest%" >NUL
+xcopy "%source%" "%dest%" /q /s /e /y /exclude:.\excludes.txt
+
+endlocal
+exit /b
+
+:help
+echo --== HELP ==--
+echo.
+echo Usage: %~n0 [^<-v^>^|^<--version^>^|^<-h^>^|^<--help^>]
+echo.
+echo ^<-v^>^|^<--version^> : Display version
+echo ^<-h^>^|^<--help^> : Display help
+echo.
+echo --== HELP ==--
+pause
+exit /b 1
+
+:fileError
+echo --== ERREUR ==--
+echo.
+echo le fichier "%~1" n'a pas ete trouve.
+echo.
+echo --== ERREUR ==--
+pause
+exit 2
+
+:parsePath
+set %3=%~f2
+if /I "%~1"=="d" set %3=%~d2
+if /I "%~1"=="p" set %3=%~p2
+if /I "%~1"=="n" set %3=%~n2
+if /I "%~1"=="x" set %3=%~x2
+if /I "%~1"=="f" set %3=%~f2
+if /I "%~1"=="s" set %3=%~s2
+if /I "%~1"=="a" set %3=%~a2
+if /I "%~1"=="t" set %3=%~t2
+if /I "%~1"=="z" set %3=%~z2
+if /I "%~1"=="dp" set %3=%~dp2
+if /I "%~1"=="nx" set %3=%~nx2
+if /I "%~1"=="pathSearch" set %3=%~$PATH:2 rem search in PATH
+goto:eof
diff --git a/dcScript/codemirror/addon/comment/comment.js b/dcScript/codemirror/addon/comment/comment.js
index 8394e85..7f6f3ed 100644
--- a/dcScript/codemirror/addon/comment/comment.js
+++ b/dcScript/codemirror/addon/comment/comment.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -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);
@@ -78,7 +78,7 @@
var baseString = null;
for (var i = from.line; i < end; ++i) {
var line = self.getLine(i);
- var whitespace = line.slice(0, firstNonWS(line));
+ var whitespace = line.search(nonWS) === -1 ? line : line.slice(0, firstNonWS(line));
if (baseString == null || baseString.length > whitespace.length) {
baseString = whitespace;
}
@@ -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/dcScript/codemirror/addon/comment/continuecomment.js b/dcScript/codemirror/addon/comment/continuecomment.js
new file mode 100644
index 0000000..2f16da8
--- /dev/null
+++ b/dcScript/codemirror/addon/comment/continuecomment.js
@@ -0,0 +1,114 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ var nonspace = /\S/g;
+ var repeat = String.prototype.repeat || function (n) { return Array(n + 1).join(this); };
+ function continueComment(cm) {
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
+ var ranges = cm.listSelections(), mode, inserts = [];
+ for (var i = 0; i < ranges.length; i++) {
+ var pos = ranges[i].head
+ if (!/\bcomment\b/.test(cm.getTokenTypeAt(pos))) return CodeMirror.Pass;
+ var modeHere = cm.getModeAt(pos)
+ if (!mode) mode = modeHere;
+ else if (mode != modeHere) return CodeMirror.Pass;
+
+ var insert = null, line, found;
+ var blockStart = mode.blockCommentStart, lineCmt = mode.lineComment;
+ if (blockStart && mode.blockCommentContinue) {
+ line = cm.getLine(pos.line);
+ var end = line.lastIndexOf(mode.blockCommentEnd, pos.ch - mode.blockCommentEnd.length);
+ // 1. if this block comment ended
+ // 2. if this is actually inside a line comment
+ if (end != -1 && end == pos.ch - mode.blockCommentEnd.length ||
+ lineCmt && (found = line.lastIndexOf(lineCmt, pos.ch - 1)) > -1 &&
+ /\bcomment\b/.test(cm.getTokenTypeAt({line: pos.line, ch: found + 1}))) {
+ // ...then don't continue it
+ } else if (pos.ch >= blockStart.length &&
+ (found = line.lastIndexOf(blockStart, pos.ch - blockStart.length)) > -1 &&
+ found > end) {
+ // reuse the existing leading spaces/tabs/mixed
+ // or build the correct indent using CM's tab/indent options
+ if (nonspaceAfter(0, line) >= found) {
+ insert = line.slice(0, found);
+ } else {
+ var tabSize = cm.options.tabSize, numTabs;
+ found = CodeMirror.countColumn(line, found, tabSize);
+ insert = !cm.options.indentWithTabs ? repeat.call(" ", found) :
+ repeat.call("\t", (numTabs = Math.floor(found / tabSize))) +
+ repeat.call(" ", found - tabSize * numTabs);
+ }
+ } else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 &&
+ found <= pos.ch &&
+ found <= nonspaceAfter(0, line)) {
+ insert = line.slice(0, found);
+ }
+ if (insert != null) insert += mode.blockCommentContinue
+ }
+ if (insert == null && lineCmt && continueLineCommentEnabled(cm)) {
+ if (line == null) line = cm.getLine(pos.line);
+ found = line.indexOf(lineCmt);
+ // cursor at pos 0, line comment also at pos 0 => shift it down, don't continue
+ if (!pos.ch && !found) insert = "";
+ // continue only if the line starts with an optional space + line comment
+ else if (found > -1 && nonspaceAfter(0, line) >= found) {
+ // don't continue if there's only space(s) after cursor or the end of the line
+ insert = nonspaceAfter(pos.ch, line) > -1;
+ // but always continue if the next line starts with a line comment too
+ if (!insert) {
+ var next = cm.getLine(pos.line + 1) || '',
+ nextFound = next.indexOf(lineCmt);
+ insert = nextFound > -1 && nonspaceAfter(0, next) >= nextFound || null;
+ }
+ if (insert) {
+ insert = line.slice(0, found) + lineCmt +
+ line.slice(found + lineCmt.length).match(/^\s*/)[0];
+ }
+ }
+ }
+ if (insert == null) return CodeMirror.Pass;
+ inserts[i] = "\n" + insert;
+ }
+
+ cm.operation(function() {
+ for (var i = ranges.length - 1; i >= 0; i--)
+ cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
+ });
+ }
+
+ function nonspaceAfter(ch, str) {
+ nonspace.lastIndex = ch;
+ var m = nonspace.exec(str);
+ return m ? m.index : -1;
+ }
+
+ function continueLineCommentEnabled(cm) {
+ var opt = cm.getOption("continueComments");
+ if (opt && typeof opt == "object")
+ return opt.continueLineComment !== false;
+ return true;
+ }
+
+ CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
+ if (prev && prev != CodeMirror.Init)
+ cm.removeKeyMap("continueComment");
+ if (val) {
+ var key = "Enter";
+ if (typeof val == "string")
+ key = val;
+ else if (typeof val == "object" && val.key)
+ key = val.key;
+ var map = {name: "continueComment"};
+ map[key] = continueComment;
+ cm.addKeyMap(map);
+ }
+ });
+});
diff --git a/dcScript/codemirror/addon/dialog/dialog.css b/dcScript/codemirror/addon/dialog/dialog.css
new file mode 100644
index 0000000..677c078
--- /dev/null
+++ b/dcScript/codemirror/addon/dialog/dialog.css
@@ -0,0 +1,32 @@
+.CodeMirror-dialog {
+ position: absolute;
+ left: 0; right: 0;
+ background: inherit;
+ z-index: 15;
+ padding: .1em .8em;
+ overflow: hidden;
+ color: inherit;
+}
+
+.CodeMirror-dialog-top {
+ border-bottom: 1px solid #eee;
+ top: 0;
+}
+
+.CodeMirror-dialog-bottom {
+ border-top: 1px solid #eee;
+ bottom: 0;
+}
+
+.CodeMirror-dialog input {
+ border: none;
+ outline: none;
+ background: transparent;
+ width: 20em;
+ color: inherit;
+ font-family: monospace;
+}
+
+.CodeMirror-dialog button {
+ font-size: 70%;
+}
diff --git a/dcScript/codemirror/addon/dialog/dialog.js b/dcScript/codemirror/addon/dialog/dialog.js
index 23b06a8..0294d23 100644
--- a/dcScript/codemirror/addon/dialog/dialog.js
+++ b/dcScript/codemirror/addon/dialog/dialog.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
// Open simple dialogs on top of an editor. Relies on dialog.css.
@@ -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/dcScript/codemirror/addon/display/autorefresh.js b/dcScript/codemirror/addon/display/autorefresh.js
new file mode 100644
index 0000000..b5e6ab0
--- /dev/null
+++ b/dcScript/codemirror/addon/display/autorefresh.js
@@ -0,0 +1,47 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/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) {
+ "use strict"
+
+ CodeMirror.defineOption("autoRefresh", false, function(cm, val) {
+ if (cm.state.autoRefresh) {
+ stopListening(cm, cm.state.autoRefresh)
+ cm.state.autoRefresh = null
+ }
+ if (val && cm.display.wrapper.offsetHeight == 0)
+ startListening(cm, cm.state.autoRefresh = {delay: val.delay || 250})
+ })
+
+ function startListening(cm, state) {
+ function check() {
+ if (cm.display.wrapper.offsetHeight) {
+ stopListening(cm, state)
+ if (cm.display.lastWrapHeight != cm.display.wrapper.clientHeight)
+ cm.refresh()
+ } else {
+ state.timeout = setTimeout(check, state.delay)
+ }
+ }
+ state.timeout = setTimeout(check, state.delay)
+ state.hurry = function() {
+ clearTimeout(state.timeout)
+ state.timeout = setTimeout(check, 50)
+ }
+ CodeMirror.on(window, "mouseup", state.hurry)
+ CodeMirror.on(window, "keyup", state.hurry)
+ }
+
+ function stopListening(_cm, state) {
+ clearTimeout(state.timeout)
+ CodeMirror.off(window, "mouseup", state.hurry)
+ CodeMirror.off(window, "keyup", state.hurry)
+ }
+});
diff --git a/dcScript/codemirror/addon/display/fullscreen.css b/dcScript/codemirror/addon/display/fullscreen.css
new file mode 100644
index 0000000..437acd8
--- /dev/null
+++ b/dcScript/codemirror/addon/display/fullscreen.css
@@ -0,0 +1,6 @@
+.CodeMirror-fullscreen {
+ position: fixed;
+ top: 0; left: 0; right: 0; bottom: 0;
+ height: auto;
+ z-index: 9;
+}
diff --git a/dcScript/codemirror/addon/display/fullscreen.js b/dcScript/codemirror/addon/display/fullscreen.js
index eda7300..39451bd 100644
--- a/dcScript/codemirror/addon/display/fullscreen.js
+++ b/dcScript/codemirror/addon/display/fullscreen.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
diff --git a/dcScript/codemirror/addon/display/panel.js b/dcScript/codemirror/addon/display/panel.js
new file mode 100644
index 0000000..b00d683
--- /dev/null
+++ b/dcScript/codemirror/addon/display/panel.js
@@ -0,0 +1,133 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/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.defineExtension("addPanel", function (node, options) {
+ options = options || {};
+
+ if (!this.state.panels) initPanels(this);
+
+ var info = this.state.panels;
+ var wrapper = info.wrapper;
+ var cmWrapper = this.getWrapperElement();
+ var replace = options.replace instanceof Panel && !options.replace.cleared;
+
+ if (options.after instanceof Panel && !options.after.cleared) {
+ wrapper.insertBefore(node, options.before.node.nextSibling);
+ } else if (options.before instanceof Panel && !options.before.cleared) {
+ wrapper.insertBefore(node, options.before.node);
+ } else if (replace) {
+ wrapper.insertBefore(node, options.replace.node);
+ options.replace.clear(true);
+ } else if (options.position == "bottom") {
+ wrapper.appendChild(node);
+ } else if (options.position == "before-bottom") {
+ wrapper.insertBefore(node, cmWrapper.nextSibling);
+ } else if (options.position == "after-top") {
+ wrapper.insertBefore(node, cmWrapper);
+ } else {
+ wrapper.insertBefore(node, wrapper.firstChild);
+ }
+
+ var height = (options && options.height) || node.offsetHeight;
+
+ var panel = new Panel(this, node, options, height);
+ info.panels.push(panel);
+
+ this.setSize();
+ if (options.stable && isAtTop(this, node))
+ this.scrollTo(null, this.getScrollInfo().top + height);
+
+ return panel;
+ });
+
+ function Panel(cm, node, options, height) {
+ this.cm = cm;
+ this.node = node;
+ this.options = options;
+ this.height = height;
+ this.cleared = false;
+ }
+
+ /* when skipRemove is true, clear() was called from addPanel().
+ * Thus removePanels() should not be called (issue 5518) */
+ Panel.prototype.clear = function (skipRemove) {
+ if (this.cleared) return;
+ this.cleared = true;
+ var info = this.cm.state.panels;
+ info.panels.splice(info.panels.indexOf(this), 1);
+ this.cm.setSize();
+ if (this.options.stable && isAtTop(this.cm, this.node))
+ this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height)
+ info.wrapper.removeChild(this.node);
+ if (info.panels.length == 0 && !skipRemove) removePanels(this.cm);
+ };
+
+ Panel.prototype.changed = function () {
+ this.height = this.node.getBoundingClientRect().height;
+ this.cm.setSize();
+ };
+
+ function initPanels(cm) {
+ var wrap = cm.getWrapperElement()
+ var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
+ var height = parseInt(style.height);
+ var info = cm.state.panels = {
+ setHeight: wrap.style.height,
+ panels: [],
+ wrapper: document.createElement("div")
+ };
+ var hasFocus = cm.hasFocus(), scrollPos = cm.getScrollInfo()
+ wrap.parentNode.insertBefore(info.wrapper, wrap);
+ info.wrapper.appendChild(wrap);
+ cm.scrollTo(scrollPos.left, scrollPos.top)
+ if (hasFocus) cm.focus();
+
+ cm._setSize = cm.setSize;
+ if (height != null) cm.setSize = function (width, newHeight) {
+ if (!newHeight) newHeight = info.wrapper.offsetHeight;
+ info.setHeight = newHeight;
+ if (typeof newHeight != "number") {
+ var px = /^(\d+\.?\d*)px$/.exec(newHeight);
+ if (px) {
+ newHeight = Number(px[1]);
+ } else {
+ info.wrapper.style.height = newHeight;
+ newHeight = info.wrapper.offsetHeight;
+ }
+ }
+ var editorheight = newHeight - info.panels
+ .map(function (p) { return p.node.getBoundingClientRect().height; })
+ .reduce(function (a, b) { return a + b; }, 0);
+ cm._setSize(width, editorheight);
+ height = newHeight;
+ };
+ }
+
+ function removePanels(cm) {
+ var info = cm.state.panels;
+ cm.state.panels = null;
+
+ 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();
+ }
+
+ function isAtTop(cm, dom) {
+ for (var sibling = dom.nextSibling; sibling; sibling = sibling.nextSibling)
+ if (sibling == cm.getWrapperElement()) return true
+ return false
+ }
+});
diff --git a/dcScript/codemirror/addon/display/placeholder.js b/dcScript/codemirror/addon/display/placeholder.js
new file mode 100644
index 0000000..7848f51
--- /dev/null
+++ b/dcScript/codemirror/addon/display/placeholder.js
@@ -0,0 +1,78 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/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.defineOption("placeholder", "", function(cm, val, old) {
+ var prev = old && old != CodeMirror.Init;
+ if (val && !prev) {
+ 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", "");
+ }
+
+ if (val && !cm.hasFocus()) onBlur(cm);
+ });
+
+ function clearPlaceholder(cm) {
+ if (cm.state.placeholder) {
+ cm.state.placeholder.parentNode.removeChild(cm.state.placeholder);
+ cm.state.placeholder = null;
+ }
+ }
+ function setPlaceholder(cm) {
+ clearPlaceholder(cm);
+ var elt = cm.state.placeholder = document.createElement("pre");
+ elt.style.cssText = "height: 0; overflow: visible";
+ elt.style.direction = cm.getOption("direction");
+ elt.className = "CodeMirror-placeholder CodeMirror-line-like";
+ var placeHolder = cm.getOption("placeholder")
+ if (typeof placeHolder == "string") placeHolder = document.createTextNode(placeHolder)
+ elt.appendChild(placeHolder)
+ 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);
+ }
+ function onChange(cm) {
+ var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
+ wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");
+
+ if (empty) setPlaceholder(cm);
+ else clearPlaceholder(cm);
+ }
+
+ function isEmpty(cm) {
+ return (cm.lineCount() === 1) && (cm.getLine(0) === "");
+ }
+});
diff --git a/dcScript/codemirror/addon/display/rulers.js b/dcScript/codemirror/addon/display/rulers.js
new file mode 100644
index 0000000..4ca15ea
--- /dev/null
+++ b/dcScript/codemirror/addon/display/rulers.js
@@ -0,0 +1,51 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/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) {
+ "use strict";
+
+ CodeMirror.defineOption("rulers", false, function(cm, val) {
+ if (cm.state.rulerDiv) {
+ cm.state.rulerDiv.parentElement.removeChild(cm.state.rulerDiv)
+ cm.state.rulerDiv = null
+ cm.off("refresh", drawRulers)
+ }
+ if (val && val.length) {
+ cm.state.rulerDiv = cm.display.lineSpace.parentElement.insertBefore(document.createElement("div"), cm.display.lineSpace)
+ cm.state.rulerDiv.className = "CodeMirror-rulers"
+ drawRulers(cm)
+ cm.on("refresh", drawRulers)
+ }
+ });
+
+ function drawRulers(cm) {
+ cm.state.rulerDiv.textContent = ""
+ var val = cm.getOption("rulers");
+ var cw = cm.defaultCharWidth();
+ var left = cm.charCoords(CodeMirror.Pos(cm.firstLine(), 0), "div").left;
+ cm.state.rulerDiv.style.minHeight = (cm.display.scroller.offsetHeight + 30) + "px";
+ for (var i = 0; i < val.length; i++) {
+ var elt = document.createElement("div");
+ elt.className = "CodeMirror-ruler";
+ var col, conf = val[i];
+ if (typeof conf == "number") {
+ col = conf;
+ } else {
+ col = conf.column;
+ if (conf.className) elt.className += " " + conf.className;
+ if (conf.color) elt.style.borderColor = conf.color;
+ if (conf.lineStyle) elt.style.borderLeftStyle = conf.lineStyle;
+ if (conf.width) elt.style.borderLeftWidth = conf.width;
+ }
+ elt.style.left = (left + col * cw) + "px";
+ cm.state.rulerDiv.appendChild(elt)
+ }
+ }
+});
diff --git a/dcScript/codemirror/addon/edit/closebrackets.js b/dcScript/codemirror/addon/edit/closebrackets.js
new file mode 100644
index 0000000..badbbd8
--- /dev/null
+++ b/dcScript/codemirror/addon/edit/closebrackets.js
@@ -0,0 +1,201 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ var defaults = {
+ pairs: "()[]{}''\"\"",
+ closeBefore: ")]}'\":;>",
+ triples: "",
+ explode: "[]{}"
+ };
+
+ var Pos = CodeMirror.Pos;
+
+ CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
+ if (old && old != CodeMirror.Init) {
+ cm.removeKeyMap(keyMap);
+ cm.state.closeBrackets = null;
+ }
+ if (val) {
+ ensureBound(getOption(val, "pairs"))
+ cm.state.closeBrackets = val;
+ cm.addKeyMap(keyMap);
+ }
+ });
+
+ function getOption(conf, name) {
+ if (name == "pairs" && typeof conf == "string") return conf;
+ if (typeof conf == "object" && conf[name] != null) return conf[name];
+ return defaults[name];
+ }
+
+ var keyMap = {Backspace: handleBackspace, Enter: handleEnter};
+ function ensureBound(chars) {
+ for (var i = 0; i < chars.length; i++) {
+ var ch = chars.charAt(i), key = "'" + ch + "'"
+ if (!keyMap[key]) keyMap[key] = handler(ch)
+ }
+ }
+ ensureBound(defaults.pairs + "`")
+
+ function handler(ch) {
+ return function(cm) { return handleChar(cm, ch); };
+ }
+
+ function getConfig(cm) {
+ var deflt = cm.state.closeBrackets;
+ if (!deflt || deflt.override) return deflt;
+ var mode = cm.getModeAt(cm.getCursor());
+ return mode.closeBrackets || deflt;
+ }
+
+ function handleBackspace(cm) {
+ var conf = getConfig(cm);
+ if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
+
+ var pairs = getOption(conf, "pairs");
+ var ranges = cm.listSelections();
+ for (var i = 0; i < ranges.length; i++) {
+ if (!ranges[i].empty()) return CodeMirror.Pass;
+ var around = charsAround(cm, ranges[i].head);
+ if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
+ }
+ for (var i = ranges.length - 1; i >= 0; i--) {
+ var cur = ranges[i].head;
+ cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1), "+delete");
+ }
+ }
+
+ function handleEnter(cm) {
+ var conf = getConfig(cm);
+ var explode = conf && getOption(conf, "explode");
+ if (!explode || cm.getOption("disableInput")) return CodeMirror.Pass;
+
+ var ranges = cm.listSelections();
+ for (var i = 0; i < ranges.length; i++) {
+ if (!ranges[i].empty()) return CodeMirror.Pass;
+ var around = charsAround(cm, ranges[i].head);
+ if (!around || explode.indexOf(around) % 2 != 0) return CodeMirror.Pass;
+ }
+ cm.operation(function() {
+ var linesep = cm.lineSeparator() || "\n";
+ cm.replaceSelection(linesep + linesep, null);
+ moveSel(cm, -1)
+ ranges = cm.listSelections();
+ for (var i = 0; i < ranges.length; i++) {
+ var line = ranges[i].head.line;
+ cm.indentLine(line, null, true);
+ cm.indentLine(line + 1, null, true);
+ }
+ });
+ }
+
+ function 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)),
+ head: new Pos(sel.head.line, sel.head.ch + (inverted ? 1 : -1))};
+ }
+
+ function handleChar(cm, ch) {
+ var conf = getConfig(cm);
+ if (!conf || cm.getOption("disableInput")) return CodeMirror.Pass;
+
+ var pairs = getOption(conf, "pairs");
+ var pos = pairs.indexOf(ch);
+ if (pos == -1) return CodeMirror.Pass;
+
+ var closeBefore = getOption(conf,"closeBefore");
+
+ var triples = getOption(conf, "triples");
+
+ var identical = pairs.charAt(pos + 1) == ch;
+ var ranges = cm.listSelections();
+ var opening = pos % 2 == 0;
+
+ var type;
+ for (var i = 0; i < ranges.length; i++) {
+ var range = ranges[i], cur = range.head, curType;
+ var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
+ if (opening && !range.empty()) {
+ curType = "surround";
+ } else if ((identical || !opening) && next == ch) {
+ if (identical && stringStartsAfter(cm, cur))
+ curType = "both";
+ else if (triples.indexOf(ch) >= 0 && cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == ch + ch + ch)
+ curType = "skipThree";
+ else
+ curType = "skip";
+ } else if (identical && cur.ch > 1 && triples.indexOf(ch) >= 0 &&
+ cm.getRange(Pos(cur.line, cur.ch - 2), cur) == ch + ch) {
+ if (cur.ch > 2 && /\bstring/.test(cm.getTokenTypeAt(Pos(cur.line, cur.ch - 2)))) return CodeMirror.Pass;
+ curType = "addFour";
+ } else if (identical) {
+ var prev = cur.ch == 0 ? " " : cm.getRange(Pos(cur.line, cur.ch - 1), cur)
+ if (!CodeMirror.isWordChar(next) && prev != ch && !CodeMirror.isWordChar(prev)) curType = "both";
+ else return CodeMirror.Pass;
+ } else if (opening && (next.length === 0 || /\s/.test(next) || closeBefore.indexOf(next) > -1)) {
+ curType = "both";
+ } else {
+ return CodeMirror.Pass;
+ }
+ if (!type) type = curType;
+ else if (type != curType) return CodeMirror.Pass;
+ }
+
+ var left = pos % 2 ? pairs.charAt(pos - 1) : ch;
+ var right = pos % 2 ? ch : pairs.charAt(pos + 1);
+ cm.operation(function() {
+ if (type == "skip") {
+ moveSel(cm, 1)
+ } else if (type == "skipThree") {
+ moveSel(cm, 3)
+ } else if (type == "surround") {
+ var sels = cm.getSelections();
+ for (var i = 0; i < sels.length; i++)
+ sels[i] = left + sels[i] + right;
+ cm.replaceSelections(sels, "around");
+ sels = cm.listSelections().slice();
+ for (var i = 0; i < sels.length; i++)
+ sels[i] = contractSelection(sels[i]);
+ cm.setSelections(sels);
+ } else if (type == "both") {
+ cm.replaceSelection(left + right, null);
+ cm.triggerElectric(left + right);
+ moveSel(cm, -1)
+ } else if (type == "addFour") {
+ cm.replaceSelection(left + left + left + left, "before");
+ moveSel(cm, 1)
+ }
+ });
+ }
+
+ function charsAround(cm, pos) {
+ var str = cm.getRange(Pos(pos.line, pos.ch - 1),
+ Pos(pos.line, pos.ch + 1));
+ return str.length == 2 ? str : null;
+ }
+
+ function stringStartsAfter(cm, pos) {
+ var token = cm.getTokenAt(Pos(pos.line, pos.ch + 1))
+ return /\bstring/.test(token.type) && token.start == pos.ch &&
+ (pos.ch == 0 || !/\bstring/.test(cm.getTokenTypeAt(pos)))
+ }
+});
diff --git a/dcScript/codemirror/addon/edit/closetag.js b/dcScript/codemirror/addon/edit/closetag.js
new file mode 100644
index 0000000..62c0578
--- /dev/null
+++ b/dcScript/codemirror/addon/edit/closetag.js
@@ -0,0 +1,185 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+/**
+ * Tag-closer extension for CodeMirror.
+ *
+ * This extension adds an "autoCloseTags" option that can be set to
+ * either true to get the default behavior, or an object to further
+ * configure its behavior.
+ *
+ * These are supported options:
+ *
+ * `whenClosing` (default true)
+ * Whether to autoclose when the '/' of a closing tag is typed.
+ * `whenOpening` (default true)
+ * Whether to autoclose the tag when the final '>' of an opening
+ * tag is typed.
+ * `dontCloseTags` (default is empty tags for HTML, none for XML)
+ * An array of tag names that should not be autoclosed.
+ * `indentTags` (default is block tags for HTML, none for XML)
+ * An array of tag names that should, when opened, cause a
+ * blank line to be added inside the tag, and the blank line and
+ * closing line to be indented.
+ * `emptyTags` (default is none)
+ * An array of XML tag names that should be autoclosed with '/>'.
+ *
+ * See demos/closetag.html for a usage example.
+ */
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"), require("../fold/xml-fold"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror", "../fold/xml-fold"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ CodeMirror.defineOption("autoCloseTags", false, function(cm, val, old) {
+ if (old != CodeMirror.Init && old)
+ cm.removeKeyMap("autoCloseTags");
+ if (!val) return;
+ var map = {name: "autoCloseTags"};
+ if (typeof val != "object" || val.whenClosing !== false)
+ map["'/'"] = function(cm) { return autoCloseSlash(cm); };
+ if (typeof val != "object" || val.whenOpening !== false)
+ map["'>'"] = function(cm) { return autoCloseGT(cm); };
+ cm.addKeyMap(map);
+ });
+
+ var htmlDontClose = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
+ "source", "track", "wbr"];
+ var htmlIndent = ["applet", "blockquote", "body", "button", "div", "dl", "fieldset", "form", "frameset", "h1", "h2", "h3", "h4",
+ "h5", "h6", "head", "html", "iframe", "layer", "legend", "object", "ol", "p", "select", "table", "ul"];
+
+ function autoCloseGT(cm) {
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
+ var ranges = cm.listSelections(), replacements = [];
+ var opt = cm.getOption("autoCloseTags");
+ for (var i = 0; i < ranges.length; i++) {
+ if (!ranges[i].empty()) return CodeMirror.Pass;
+ var pos = ranges[i].head, tok = cm.getTokenAt(pos);
+ var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
+ var tagInfo = inner.mode.xmlCurrentTag && inner.mode.xmlCurrentTag(state)
+ var tagName = tagInfo && tagInfo.name
+ if (!tagName) return CodeMirror.Pass
+
+ var html = inner.mode.configuration == "html";
+ var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
+ var indentTags = (typeof opt == "object" && opt.indentTags) || (html && htmlIndent);
+
+ if (tok.end > pos.ch) tagName = tagName.slice(0, tagName.length - tok.end + pos.ch);
+ var lowerTagName = tagName.toLowerCase();
+ // Don't process the '>' at the end of an end-tag or self-closing tag
+ if (!tagName ||
+ tok.type == "string" && (tok.end != pos.ch || !/[\"\']/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1) ||
+ tok.type == "tag" && tagInfo.close ||
+ tok.string.indexOf("/") == (pos.ch - tok.start - 1) || // match something like
+ dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1 ||
+ closingTagExists(cm, inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state) || [], tagName, pos, true))
+ return CodeMirror.Pass;
+
+ var emptyTags = typeof opt == "object" && opt.emptyTags;
+ if (emptyTags && indexOf(emptyTags, tagName) > -1) {
+ replacements[i] = { text: "/>", newPos: CodeMirror.Pos(pos.line, pos.ch + 2) };
+ continue;
+ }
+
+ var indent = indentTags && indexOf(indentTags, lowerTagName) > -1;
+ replacements[i] = {indent: indent,
+ text: ">" + (indent ? "\n\n" : "") + "" + tagName + ">",
+ newPos: indent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1)};
+ }
+
+ var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnAutoClose);
+ for (var i = ranges.length - 1; i >= 0; i--) {
+ var info = replacements[i];
+ cm.replaceRange(info.text, ranges[i].head, ranges[i].anchor, "+insert");
+ var sel = cm.listSelections().slice(0);
+ sel[i] = {head: info.newPos, anchor: info.newPos};
+ cm.setSelections(sel);
+ if (!dontIndentOnAutoClose && info.indent) {
+ cm.indentLine(info.newPos.line, null, true);
+ cm.indentLine(info.newPos.line + 1, null, true);
+ }
+ }
+ }
+
+ function autoCloseCurrent(cm, typingSlash) {
+ var ranges = cm.listSelections(), replacements = [];
+ var head = typingSlash ? "/" : "";
+ var opt = cm.getOption("autoCloseTags");
+ var dontIndentOnAutoClose = (typeof opt == "object" && opt.dontIndentOnSlash);
+ for (var i = 0; i < ranges.length; i++) {
+ if (!ranges[i].empty()) return CodeMirror.Pass;
+ var pos = ranges[i].head, tok = cm.getTokenAt(pos);
+ var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
+ if (typingSlash && (tok.type == "string" || tok.string.charAt(0) != "<" ||
+ tok.start != pos.ch - 1))
+ return CodeMirror.Pass;
+ // Kludge to get around the fact that we are not in XML mode
+ // when completing in JS/CSS snippet in htmlmixed mode. Does not
+ // work for other XML embedded languages (there is no general
+ // way to go from a mixed mode to its current XML state).
+ var replacement, mixed = inner.mode.name != "xml" && cm.getMode().name == "htmlmixed"
+ if (mixed && inner.mode.name == "javascript") {
+ replacement = head + "script";
+ } else if (mixed && inner.mode.name == "css") {
+ replacement = head + "style";
+ } else {
+ var context = inner.mode.xmlCurrentContext && inner.mode.xmlCurrentContext(state)
+ var top = context.length ? context[context.length - 1] : ""
+ if (!context || (context.length && closingTagExists(cm, context, top, pos)))
+ return CodeMirror.Pass;
+ replacement = head + top
+ }
+ if (cm.getLine(pos.line).charAt(tok.end) != ">") replacement += ">";
+ replacements[i] = replacement;
+ }
+ cm.replaceSelections(replacements);
+ ranges = cm.listSelections();
+ if (!dontIndentOnAutoClose) {
+ for (var i = 0; i < ranges.length; i++)
+ if (i == ranges.length - 1 || ranges[i].head.line < ranges[i + 1].head.line)
+ cm.indentLine(ranges[i].head.line);
+ }
+ }
+
+ function autoCloseSlash(cm) {
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
+ return autoCloseCurrent(cm, true);
+ }
+
+ CodeMirror.commands.closeTag = function(cm) { return autoCloseCurrent(cm); };
+
+ function indexOf(collection, elt) {
+ if (collection.indexOf) return collection.indexOf(elt);
+ for (var i = 0, e = collection.length; i < e; ++i)
+ if (collection[i] == elt) return i;
+ return -1;
+ }
+
+ // If xml-fold is loaded, we use its functionality to try and verify
+ // whether a given tag is actually unclosed.
+ function closingTagExists(cm, context, tagName, pos, newTag) {
+ if (!CodeMirror.scanForClosingTag) return false;
+ var end = Math.min(cm.lastLine() + 1, pos.line + 500);
+ var nextClose = CodeMirror.scanForClosingTag(cm, pos, null, end);
+ if (!nextClose || nextClose.tag != tagName) return false;
+ // If the immediate wrapping context contains onCx instances of
+ // the same tag, a closing tag only exists if there are at least
+ // that many closing tags of that type following.
+ var onCx = newTag ? 1 : 0
+ for (var i = context.length - 1; i >= 0; i--) {
+ if (context[i] == tagName) ++onCx
+ else break
+ }
+ pos = nextClose.to;
+ for (var i = 1; i < onCx; i++) {
+ var next = CodeMirror.scanForClosingTag(cm, pos, null, end);
+ if (!next || next.tag != tagName) return false;
+ pos = next.to;
+ }
+ return true;
+ }
+});
diff --git a/dcScript/codemirror/addon/edit/continuelist.js b/dcScript/codemirror/addon/edit/continuelist.js
new file mode 100644
index 0000000..915d813
--- /dev/null
+++ b/dcScript/codemirror/addon/edit/continuelist.js
@@ -0,0 +1,101 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/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) {
+ "use strict";
+
+ var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/,
+ emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/,
+ unorderedListRE = /[*+-]\s/;
+
+ CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
+ if (cm.getOption("disableInput")) return CodeMirror.Pass;
+ var ranges = cm.listSelections(), replacements = [];
+ for (var i = 0; i < ranges.length; i++) {
+ var pos = ranges[i].head;
+
+ // If we're not in Markdown mode, fall back to normal newlineAndIndent
+ var eolState = cm.getStateAfter(pos.line);
+ var inner = CodeMirror.innerMode(cm.getMode(), eolState);
+ if (inner.mode.name !== "markdown" && inner.mode.helperType !== "markdown") {
+ cm.execCommand("newlineAndIndent");
+ return;
+ } else {
+ eolState = inner.state;
+ }
+
+ var inList = eolState.list !== false;
+ var inQuote = eolState.quote !== 0;
+
+ var line = cm.getLine(pos.line), match = listRE.exec(line);
+ var cursorBeforeBullet = /^\s*$/.test(line.slice(0, pos.ch));
+ if (!ranges[i].empty() || (!inList && !inQuote) || !match || cursorBeforeBullet) {
+ cm.execCommand("newlineAndIndent");
+ return;
+ }
+ if (emptyListRE.test(line)) {
+ 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
+ });
+ replacements[i] = "\n";
+ } else {
+ var indent = match[1], after = match[5];
+ var numbered = !(unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0);
+ var bullet = numbered ? (parseInt(match[3], 10) + 1) + match[4] : match[2].replace("x", " ");
+ replacements[i] = "\n" + indent + bullet + after;
+
+ if (numbered) incrementRemainingMarkdownListNumbers(cm, pos);
+ }
+ }
+
+ cm.replaceSelections(replacements);
+ };
+
+ // Auto-updating Markdown list numbers when a new item is added to the
+ // middle of a list
+ function incrementRemainingMarkdownListNumbers(cm, pos) {
+ var startLine = pos.line, lookAhead = 0, skipCount = 0;
+ var startItem = listRE.exec(cm.getLine(startLine)), startIndent = startItem[1];
+
+ do {
+ lookAhead += 1;
+ var nextLineNumber = startLine + lookAhead;
+ var nextLine = cm.getLine(nextLineNumber), nextItem = listRE.exec(nextLine);
+
+ if (nextItem) {
+ var nextIndent = nextItem[1];
+ var newNumber = (parseInt(startItem[3], 10) + lookAhead - skipCount);
+ var nextNumber = (parseInt(nextItem[3], 10)), itemNumber = nextNumber;
+
+ if (startIndent === nextIndent && !isNaN(nextNumber)) {
+ if (newNumber === nextNumber) itemNumber = nextNumber + 1;
+ if (newNumber > nextNumber) itemNumber = newNumber + 1;
+ cm.replaceRange(
+ nextLine.replace(listRE, nextIndent + itemNumber + nextItem[4] + nextItem[5]),
+ {
+ line: nextLineNumber, ch: 0
+ }, {
+ line: nextLineNumber, ch: nextLine.length
+ });
+ } else {
+ if (startIndent.length > nextIndent.length) return;
+ // This doesn't run if the next line 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;
+ }
+ }
+ } while (nextItem);
+ }
+});
diff --git a/dcScript/codemirror/addon/edit/matchbrackets.js b/dcScript/codemirror/addon/edit/matchbrackets.js
index 2a14728..c342910 100644
--- a/dcScript/codemirror/addon/edit/matchbrackets.js
+++ b/dcScript/codemirror/addon/edit/matchbrackets.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -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/dcScript/codemirror/addon/edit/matchtags.js b/dcScript/codemirror/addon/edit/matchtags.js
index 2203d93..afa6105 100644
--- a/dcScript/codemirror/addon/edit/matchtags.js
+++ b/dcScript/codemirror/addon/edit/matchtags.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
diff --git a/dcScript/codemirror/addon/edit/trailingspace.js b/dcScript/codemirror/addon/edit/trailingspace.js
index c39c310..8d01c20 100644
--- a/dcScript/codemirror/addon/edit/trailingspace.js
+++ b/dcScript/codemirror/addon/edit/trailingspace.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
diff --git a/dcScript/codemirror/addon/fold/brace-fold.js b/dcScript/codemirror/addon/fold/brace-fold.js
index 654d1fb..2124768 100644
--- a/dcScript/codemirror/addon/fold/brace-fold.js
+++ b/dcScript/codemirror/addon/fold/brace-fold.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -11,53 +11,67 @@
})(function(CodeMirror) {
"use strict";
-CodeMirror.registerHelper("fold", "brace", function(cm, start) {
- var line = start.line, lineText = cm.getLine(line);
- var tokenType;
+function bracketFolding(pairs) {
+ return function(cm, start) {
+ var line = start.line, lineText = cm.getLine(line);
- function findOpening(openCh) {
- for (var at = start.ch, pass = 0;;) {
- var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
- if (found == -1) {
- if (pass == 1) break;
- pass = 1;
- at = lineText.length;
- continue;
+ function findOpening(pair) {
+ var tokenType;
+ for (var at = start.ch, pass = 0;;) {
+ var found = at <= 0 ? -1 : lineText.lastIndexOf(pair[0], at - 1);
+ if (found == -1) {
+ if (pass == 1) break;
+ pass = 1;
+ at = lineText.length;
+ continue;
+ }
+ if (pass == 1 && found < start.ch) break;
+ tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
+ if (!/^(comment|string)/.test(tokenType)) return {ch: found + 1, tokenType: tokenType, pair: pair};
+ at = found - 1;
}
- if (pass == 1 && found < start.ch) break;
- tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
- if (!/^(comment|string)/.test(tokenType)) return found + 1;
- at = found - 1;
}
- }
-
- var startToken = "{", endToken = "}", startCh = findOpening("{");
- if (startCh == null) {
- startToken = "[", endToken = "]";
- startCh = findOpening("[");
- }
- 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;
- for (;;) {
- var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
- if (nextOpen < 0) nextOpen = text.length;
- if (nextClose < 0) nextClose = text.length;
- pos = Math.min(nextOpen, nextClose);
- if (pos == text.length) break;
- if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
- if (pos == nextOpen) ++count;
- else if (!--count) { end = i; endCh = pos; break outer; }
+ function findRange(found) {
+ var count = 1, lastLine = cm.lastLine(), end, startCh = found.ch, endCh
+ outer: for (var i = line; i <= lastLine; ++i) {
+ var text = cm.getLine(i), pos = i == line ? startCh : 0;
+ for (;;) {
+ var nextOpen = text.indexOf(found.pair[0], pos), nextClose = text.indexOf(found.pair[1], pos);
+ if (nextOpen < 0) nextOpen = text.length;
+ if (nextClose < 0) nextClose = text.length;
+ pos = Math.min(nextOpen, nextClose);
+ if (pos == text.length) break;
+ if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == found.tokenType) {
+ if (pos == nextOpen) ++count;
+ else if (!--count) { end = i; endCh = pos; break outer; }
+ }
+ ++pos;
+ }
}
- ++pos;
+
+ if (end == null || line == end) return null
+ return {from: CodeMirror.Pos(line, startCh),
+ to: CodeMirror.Pos(end, endCh)};
+ }
+
+ var found = []
+ for (var i = 0; i < pairs.length; i++) {
+ var open = findOpening(pairs[i])
+ if (open) found.push(open)
+ }
+ found.sort(function(a, b) { return a.ch - b.ch })
+ for (var i = 0; i < found.length; i++) {
+ var range = findRange(found[i])
+ if (range) return range
}
+ return null
}
- if (end == null || line == end) return;
- return {from: CodeMirror.Pos(line, startCh),
- to: CodeMirror.Pos(end, endCh)};
-});
+}
+
+CodeMirror.registerHelper("fold", "brace", bracketFolding([["{", "}"], ["[", "]"]]));
+
+CodeMirror.registerHelper("fold", "brace-paren", bracketFolding([["{", "}"], ["[", "]"], ["(", ")"]]));
CodeMirror.registerHelper("fold", "import", function(cm, start) {
function hasImport(line) {
diff --git a/dcScript/codemirror/addon/fold/comment-fold.js b/dcScript/codemirror/addon/fold/comment-fold.js
index 836101d..adaa79d 100644
--- a/dcScript/codemirror/addon/fold/comment-fold.js
+++ b/dcScript/codemirror/addon/fold/comment-fold.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
diff --git a/dcScript/codemirror/addon/fold/foldcode.js b/dcScript/codemirror/addon/fold/foldcode.js
index 887df3f..a6a51af 100644
--- a/dcScript/codemirror/addon/fold/foldcode.js
+++ b/dcScript/codemirror/addon/fold/foldcode.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -24,9 +24,11 @@
function getRange(allowFolded) {
var range = finder(cm, pos);
if (!range || range.to.line - range.from.line < minSize) return null;
+ if (force === "fold") return range;
+
var marks = cm.findMarksAt(range.from);
for (var i = 0; i < marks.length; ++i) {
- if (marks[i].__isFold && force !== "fold") {
+ if (marks[i].__isFold) {
if (!allowFolded) return null;
range.cleared = true;
marks[i].clear();
@@ -99,18 +101,18 @@
cm.foldCode(cm.getCursor(), null, "fold");
};
CodeMirror.commands.unfold = function(cm) {
- cm.foldCode(cm.getCursor(), null, "unfold");
+ cm.foldCode(cm.getCursor(), { scanUp: false }, "unfold");
};
CodeMirror.commands.foldAll = function(cm) {
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
- cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
+ cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, "fold");
});
};
CodeMirror.commands.unfoldAll = function(cm) {
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
- cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
+ cm.foldCode(CodeMirror.Pos(i, 0), { scanUp: false }, "unfold");
});
};
diff --git a/dcScript/codemirror/addon/fold/foldgutter.css b/dcScript/codemirror/addon/fold/foldgutter.css
new file mode 100644
index 0000000..ad19ae2
--- /dev/null
+++ b/dcScript/codemirror/addon/fold/foldgutter.css
@@ -0,0 +1,20 @@
+.CodeMirror-foldmarker {
+ color: blue;
+ text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
+ font-family: arial;
+ line-height: .3;
+ cursor: pointer;
+}
+.CodeMirror-foldgutter {
+ width: .7em;
+}
+.CodeMirror-foldgutter-open,
+.CodeMirror-foldgutter-folded {
+ cursor: pointer;
+}
+.CodeMirror-foldgutter-open:after {
+ content: "\25BE";
+}
+.CodeMirror-foldgutter-folded:after {
+ content: "\25B8";
+}
diff --git a/dcScript/codemirror/addon/fold/foldgutter.js b/dcScript/codemirror/addon/fold/foldgutter.js
index 7d46a60..8fc0e99 100644
--- a/dcScript/codemirror/addon/fold/foldgutter.js
+++ b/dcScript/codemirror/addon/fold/foldgutter.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -21,6 +21,7 @@
cm.off("fold", onFold);
cm.off("unfold", onFold);
cm.off("swapDoc", onChange);
+ cm.off("optionChange", optionChange);
}
if (val) {
cm.state.foldGutter = new State(parseOptions(val));
@@ -31,6 +32,7 @@
cm.on("fold", onFold);
cm.on("unfold", onFold);
cm.on("swapDoc", onChange);
+ cm.on("optionChange", optionChange);
}
});
@@ -120,6 +122,10 @@
else cm.foldCode(Pos(line, 0), opts);
}
+ function optionChange(cm, option) {
+ if (option == "mode") onChange(cm)
+ }
+
function onChange(cm) {
var state = cm.state.foldGutter;
if (!state) return;
diff --git a/dcScript/codemirror/addon/fold/indent-fold.js b/dcScript/codemirror/addon/fold/indent-fold.js
index 0cc1126..470e84a 100644
--- a/dcScript/codemirror/addon/fold/indent-fold.js
+++ b/dcScript/codemirror/addon/fold/indent-fold.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
diff --git a/dcScript/codemirror/addon/fold/markdown-fold.js b/dcScript/codemirror/addon/fold/markdown-fold.js
new file mode 100644
index 0000000..4f9cb02
--- /dev/null
+++ b/dcScript/codemirror/addon/fold/markdown-fold.js
@@ -0,0 +1,49 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/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) {
+"use strict";
+
+CodeMirror.registerHelper("fold", "markdown", function(cm, start) {
+ var maxDepth = 100;
+
+ function isHeader(lineNo) {
+ var tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0));
+ return tokentype && /\bheader\b/.test(tokentype);
+ }
+
+ function headerLevel(lineNo, line, nextLine) {
+ var match = line && line.match(/^#+/);
+ if (match && isHeader(lineNo)) return match[0].length;
+ match = nextLine && nextLine.match(/^[=\-]+\s*$/);
+ if (match && isHeader(lineNo + 1)) return nextLine[0] == "=" ? 1 : 2;
+ return maxDepth;
+ }
+
+ var firstLine = cm.getLine(start.line), nextLine = cm.getLine(start.line + 1);
+ var level = headerLevel(start.line, firstLine, nextLine);
+ if (level === maxDepth) return undefined;
+
+ var lastLineNo = cm.lastLine();
+ var end = start.line, nextNextLine = cm.getLine(end + 2);
+ while (end < lastLineNo) {
+ if (headerLevel(end + 1, nextLine, nextNextLine) <= level) break;
+ ++end;
+ nextLine = nextNextLine;
+ nextNextLine = cm.getLine(end + 2);
+ }
+
+ return {
+ from: CodeMirror.Pos(start.line, firstLine.length),
+ to: CodeMirror.Pos(end, cm.getLine(end).length)
+ };
+});
+
+});
diff --git a/dcScript/codemirror/addon/fold/xml-fold.js b/dcScript/codemirror/addon/fold/xml-fold.js
index 13bc383..5450d37 100644
--- a/dcScript/codemirror/addon/fold/xml-fold.js
+++ b/dcScript/codemirror/addon/fold/xml-fold.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
diff --git a/dcScript/codemirror/addon/search/jump-to-line.js b/dcScript/codemirror/addon/search/jump-to-line.js
new file mode 100644
index 0000000..596383b
--- /dev/null
+++ b/dcScript/codemirror/addon/search/jump-to-line.js
@@ -0,0 +1,53 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+// Defines jumpToLine command. Uses dialog.js if present.
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"), require("../dialog/dialog"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror", "../dialog/dialog"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ "use strict";
+
+ // default search panel location
+ CodeMirror.defineOption("search", {bottom: false});
+
+ function dialog(cm, text, shortText, deflt, f) {
+ if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom});
+ else f(prompt(shortText, deflt));
+ }
+
+ function getJumpDialog(cm) {
+ return cm.phrase("Jump to line:") + ' ' + cm.phrase("(Use line:column or scroll% syntax)") + ' ';
+ }
+
+ function interpretLine(cm, string) {
+ var num = Number(string)
+ if (/^[-+]/.test(string)) return cm.getCursor().line + num
+ else return num - 1
+ }
+
+ CodeMirror.commands.jumpToLine = function(cm) {
+ var cur = cm.getCursor();
+ dialog(cm, getJumpDialog(cm), cm.phrase("Jump to line:"), (cur.line + 1) + ":" + cur.ch, function(posStr) {
+ if (!posStr) return;
+
+ var match;
+ if (match = /^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(posStr)) {
+ cm.setCursor(interpretLine(cm, match[1]), Number(match[2]))
+ } else if (match = /^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(posStr)) {
+ var line = Math.round(cm.lineCount() * Number(match[1]) / 100);
+ if (/^[-+]/.test(match[1])) line = cur.line + line + 1;
+ cm.setCursor(line - 1, cur.ch);
+ } else if (match = /^\s*\:?\s*([\+\-]?\d+)\s*/.exec(posStr)) {
+ cm.setCursor(interpretLine(cm, match[1]), cur.ch);
+ }
+ });
+ };
+
+ CodeMirror.keyMap["default"]["Alt-G"] = "jumpToLine";
+});
diff --git a/dcScript/codemirror/addon/search/match-highlighter.js b/dcScript/codemirror/addon/search/match-highlighter.js
new file mode 100644
index 0000000..f7e7fb3
--- /dev/null
+++ b/dcScript/codemirror/addon/search/match-highlighter.js
@@ -0,0 +1,167 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+// Highlighting text that matches the selection
+//
+// Defines an option highlightSelectionMatches, which, when enabled,
+// will style strings that match the selection throughout the
+// document.
+//
+// The option can be set to true to simply enable it, or to a
+// {minChars, style, wordsOnly, showToken, delay} object to explicitly
+// configure it. minChars is the minimum amount of characters that should be
+// selected for the behavior to occur, and style is the token style to
+// apply to the matches. This will be prefixed by "cm-" to create an
+// actual CSS class name. If wordsOnly is enabled, the matches will be
+// highlighted only if the selected text is a word. showToken, when enabled,
+// will cause the current token to be highlighted when nothing is selected.
+// delay is used to specify how much time to wait, in milliseconds, before
+// highlighting the matches. If annotateScrollbar is enabled, the occurrences
+// will be highlighted on the scrollbar via the matchesonscrollbar addon.
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"), require("./matchesonscrollbar"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror", "./matchesonscrollbar"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ "use strict";
+
+ var defaults = {
+ style: "matchhighlight",
+ minChars: 2,
+ delay: 100,
+ wordsOnly: false,
+ annotateScrollbar: false,
+ showToken: false,
+ trim: true
+ }
+
+ function State(options) {
+ this.options = {}
+ for (var name in defaults)
+ this.options[name] = (options && options.hasOwnProperty(name) ? options : defaults)[name]
+ this.overlay = this.timeout = null;
+ this.matchesonscroll = null;
+ this.active = false;
+ }
+
+ CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
+ if (old && old != CodeMirror.Init) {
+ removeOverlay(cm);
+ clearTimeout(cm.state.matchHighlighter.timeout);
+ cm.state.matchHighlighter = null;
+ cm.off("cursorActivity", cursorActivity);
+ cm.off("focus", onFocus)
+ }
+ if (val) {
+ var state = cm.state.matchHighlighter = new State(val);
+ if (cm.hasFocus()) {
+ state.active = true
+ highlightMatches(cm)
+ } else {
+ cm.on("focus", onFocus)
+ }
+ cm.on("cursorActivity", cursorActivity);
+ }
+ });
+
+ function cursorActivity(cm) {
+ var state = cm.state.matchHighlighter;
+ if (state.active || cm.hasFocus()) scheduleHighlight(cm, state)
+ }
+
+ function onFocus(cm) {
+ var state = cm.state.matchHighlighter
+ if (!state.active) {
+ state.active = true
+ scheduleHighlight(cm, state)
+ }
+ }
+
+ function scheduleHighlight(cm, state) {
+ clearTimeout(state.timeout);
+ state.timeout = setTimeout(function() {highlightMatches(cm);}, state.options.delay);
+ }
+
+ function addOverlay(cm, query, hasBoundary, style) {
+ var state = cm.state.matchHighlighter;
+ cm.addOverlay(state.overlay = makeOverlay(query, hasBoundary, style));
+ if (state.options.annotateScrollbar && cm.showMatchesOnScrollbar) {
+ var searchFor = hasBoundary ? new RegExp((/\w/.test(query.charAt(0)) ? "\\b" : "") +
+ query.replace(/[\\\[.+*?(){|^$]/g, "\\$&") +
+ (/\w/.test(query.charAt(query.length - 1)) ? "\\b" : "")) : query;
+ state.matchesonscroll = cm.showMatchesOnScrollbar(searchFor, false,
+ {className: "CodeMirror-selection-highlight-scrollbar"});
+ }
+ }
+
+ function removeOverlay(cm) {
+ var state = cm.state.matchHighlighter;
+ if (state.overlay) {
+ cm.removeOverlay(state.overlay);
+ state.overlay = null;
+ if (state.matchesonscroll) {
+ state.matchesonscroll.clear();
+ state.matchesonscroll = null;
+ }
+ }
+ }
+
+ function highlightMatches(cm) {
+ cm.operation(function() {
+ var state = cm.state.matchHighlighter;
+ removeOverlay(cm);
+ if (!cm.somethingSelected() && state.options.showToken) {
+ var re = state.options.showToken === true ? /[\w$]/ : state.options.showToken;
+ var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
+ while (start && re.test(line.charAt(start - 1))) --start;
+ while (end < line.length && re.test(line.charAt(end))) ++end;
+ if (start < end)
+ addOverlay(cm, line.slice(start, end), re, state.options.style);
+ return;
+ }
+ var from = cm.getCursor("from"), to = cm.getCursor("to");
+ if (from.line != to.line) return;
+ if (state.options.wordsOnly && !isWord(cm, from, to)) return;
+ var selection = cm.getRange(from, to)
+ if (state.options.trim) selection = selection.replace(/^\s+|\s+$/g, "")
+ if (selection.length >= state.options.minChars)
+ addOverlay(cm, selection, false, state.options.style);
+ });
+ }
+
+ function isWord(cm, from, to) {
+ var str = cm.getRange(from, to);
+ if (str.match(/^\w+$/) !== null) {
+ if (from.ch > 0) {
+ var pos = {line: from.line, ch: from.ch - 1};
+ var chr = cm.getRange(pos, from);
+ if (chr.match(/\W/) === null) return false;
+ }
+ if (to.ch < cm.getLine(from.line).length) {
+ var pos = {line: to.line, ch: to.ch + 1};
+ var chr = cm.getRange(to, pos);
+ if (chr.match(/\W/) === null) return false;
+ }
+ return true;
+ } else return false;
+ }
+
+ function boundariesAround(stream, re) {
+ return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
+ (stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
+ }
+
+ function makeOverlay(query, hasBoundary, style) {
+ return {token: function(stream) {
+ if (stream.match(query) &&
+ (!hasBoundary || boundariesAround(stream, hasBoundary)))
+ return style;
+ stream.next();
+ stream.skipTo(query.charAt(0)) || stream.skipToEnd();
+ }};
+ }
+});
diff --git a/dcScript/codemirror/addon/search/matchesonscrollbar.css b/dcScript/codemirror/addon/search/matchesonscrollbar.css
new file mode 100644
index 0000000..77932cc
--- /dev/null
+++ b/dcScript/codemirror/addon/search/matchesonscrollbar.css
@@ -0,0 +1,8 @@
+.CodeMirror-search-match {
+ background: gold;
+ border-top: 1px solid orange;
+ border-bottom: 1px solid orange;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ opacity: .5;
+}
diff --git a/dcScript/codemirror/addon/search/matchesonscrollbar.js b/dcScript/codemirror/addon/search/matchesonscrollbar.js
new file mode 100644
index 0000000..acab47b
--- /dev/null
+++ b/dcScript/codemirror/addon/search/matchesonscrollbar.js
@@ -0,0 +1,97 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"), require("./searchcursor"), require("../scroll/annotatescrollbar"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror", "./searchcursor", "../scroll/annotatescrollbar"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ "use strict";
+
+ CodeMirror.defineExtension("showMatchesOnScrollbar", function(query, caseFold, options) {
+ if (typeof options == "string") options = {className: options};
+ if (!options) options = {};
+ return new SearchAnnotation(this, query, caseFold, options);
+ });
+
+ function SearchAnnotation(cm, query, caseFold, options) {
+ this.cm = cm;
+ this.options = options;
+ var annotateOptions = {listenForChanges: false};
+ for (var prop in options) annotateOptions[prop] = options[prop];
+ if (!annotateOptions.className) annotateOptions.className = "CodeMirror-search-match";
+ this.annotation = cm.annotateScrollbar(annotateOptions);
+ this.query = query;
+ this.caseFold = caseFold;
+ this.gap = {from: cm.firstLine(), to: cm.lastLine() + 1};
+ this.matches = [];
+ this.update = null;
+
+ this.findMatches();
+ this.annotation.update(this.matches);
+
+ var self = this;
+ cm.on("change", this.changeHandler = function(_cm, change) { self.onChange(change); });
+ }
+
+ var MAX_MATCHES = 1000;
+
+ SearchAnnotation.prototype.findMatches = function() {
+ if (!this.gap) return;
+ for (var i = 0; i < this.matches.length; i++) {
+ var match = this.matches[i];
+ if (match.from.line >= this.gap.to) break;
+ if (match.to.line >= this.gap.from) this.matches.splice(i--, 1);
+ }
+ var cursor = this.cm.getSearchCursor(this.query, CodeMirror.Pos(this.gap.from, 0), {caseFold: this.caseFold, multiline: this.options.multiline});
+ var maxMatches = this.options && this.options.maxMatches || MAX_MATCHES;
+ while (cursor.findNext()) {
+ var match = {from: cursor.from(), to: cursor.to()};
+ if (match.from.line >= this.gap.to) break;
+ this.matches.splice(i++, 0, match);
+ if (this.matches.length > maxMatches) break;
+ }
+ this.gap = null;
+ };
+
+ function offsetLine(line, changeStart, sizeChange) {
+ if (line <= changeStart) return line;
+ return Math.max(changeStart, line + sizeChange);
+ }
+
+ SearchAnnotation.prototype.onChange = function(change) {
+ var startLine = change.from.line;
+ var endLine = CodeMirror.changeEnd(change).line;
+ var sizeChange = endLine - change.to.line;
+ if (this.gap) {
+ this.gap.from = Math.min(offsetLine(this.gap.from, startLine, sizeChange), change.from.line);
+ this.gap.to = Math.max(offsetLine(this.gap.to, startLine, sizeChange), change.from.line);
+ } else {
+ this.gap = {from: change.from.line, to: endLine + 1};
+ }
+
+ if (sizeChange) for (var i = 0; i < this.matches.length; i++) {
+ var match = this.matches[i];
+ var newFrom = offsetLine(match.from.line, startLine, sizeChange);
+ if (newFrom != match.from.line) match.from = CodeMirror.Pos(newFrom, match.from.ch);
+ var newTo = offsetLine(match.to.line, startLine, sizeChange);
+ if (newTo != match.to.line) match.to = CodeMirror.Pos(newTo, match.to.ch);
+ }
+ clearTimeout(this.update);
+ var self = this;
+ this.update = setTimeout(function() { self.updateAfterChange(); }, 250);
+ };
+
+ SearchAnnotation.prototype.updateAfterChange = function() {
+ this.findMatches();
+ this.annotation.update(this.matches);
+ };
+
+ SearchAnnotation.prototype.clear = function() {
+ this.cm.off("change", this.changeHandler);
+ this.annotation.clear();
+ };
+});
diff --git a/dcScript/codemirror/addon/search/search.js b/dcScript/codemirror/addon/search/search.js
index cecdd52..9662b09 100644
--- a/dcScript/codemirror/addon/search/search.js
+++ b/dcScript/codemirror/addon/search/search.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
// Define search commands. Depends on dialog.js or another
// implementation of the openDialog method.
@@ -19,6 +19,9 @@
})(function(CodeMirror) {
"use strict";
+ // default search panel location
+ CodeMirror.defineOption("search", {bottom: false});
+
function searchOverlay(query, caseInsensitive) {
if (typeof query == "string")
query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"), caseInsensitive ? "gi" : "g");
@@ -63,12 +66,13 @@
selectValueOnOpen: true,
closeOnEnter: false,
onClose: function() { clearSearch(cm); },
- onKeyDown: onKeyDown
+ onKeyDown: onKeyDown,
+ bottom: cm.options.search.bottom
});
}
function dialog(cm, text, shortText, deflt, f) {
- if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true});
+ if (cm.openDialog) cm.openDialog(text, f, {value: deflt, selectValueOnOpen: true, bottom: cm.options.search.bottom});
else f(prompt(shortText, deflt));
}
@@ -185,18 +189,46 @@
if (state.annotate) { state.annotate.clear(); state.annotate = null; }
});}
+ function el(tag, attrs) {
+ var element = tag ? document.createElement(tag) : document.createDocumentFragment();
+ for (var key in attrs) {
+ element[key] = attrs[key];
+ }
+ for (var i = 2; i < arguments.length; i++) {
+ var child = arguments[i]
+ element.appendChild(typeof child == "string" ? document.createTextNode(child) : child);
+ }
+ return element;
+ }
function getQueryDialog(cm) {
- return '' + cm.phrase("Search:") + ' ' + cm.phrase("(Use /re/ syntax for regexp search)") + ' ';
+ var label = el("label", {className: "CodeMirror-search-label"},
+ cm.phrase("Search:"),
+ el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field",
+ id: "CodeMirror-search-field"}));
+ label.setAttribute("for","CodeMirror-search-field");
+ return el("", null, label, " ",
+ el("span", {style: "color: #666", className: "CodeMirror-search-hint"},
+ cm.phrase("(Use /re/ syntax for regexp search)")));
}
function getReplaceQueryDialog(cm) {
- return ' ' + cm.phrase("(Use /re/ syntax for regexp search)") + ' ';
+ return el("", null, " ",
+ el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"}), " ",
+ el("span", {style: "color: #666", className: "CodeMirror-search-hint"},
+ cm.phrase("(Use /re/ syntax for regexp search)")));
}
function getReplacementQueryDialog(cm) {
- return '' + cm.phrase("With:") + ' ';
+ return el("", null,
+ el("span", {className: "CodeMirror-search-label"}, cm.phrase("With:")), " ",
+ el("input", {type: "text", "style": "width: 10em", className: "CodeMirror-search-field"}));
}
function getDoReplaceConfirm(cm) {
- return '' + cm.phrase("Replace?") + ' ' + cm.phrase("Yes") + ' ' + cm.phrase("No") + ' ' + cm.phrase("All") + ' ' + cm.phrase("Stop") + ' ';
+ return el("", null,
+ el("span", {className: "CodeMirror-search-label"}, cm.phrase("Replace?")), " ",
+ el("button", {}, cm.phrase("Yes")), " ",
+ el("button", {}, cm.phrase("No")), " ",
+ el("button", {}, cm.phrase("All")), " ",
+ el("button", {}, cm.phrase("Stop")));
}
function replaceAll(cm, query, text) {
@@ -213,8 +245,11 @@
function replace(cm, all) {
if (cm.getOption("readOnly")) return;
var query = cm.getSelection() || getSearchState(cm).lastQuery;
- var dialogText = '' + (all ? cm.phrase("Replace all:") : cm.phrase("Replace:")) + ' ';
- dialog(cm, dialogText + getReplaceQueryDialog(cm), dialogText, query, function(query) {
+ var dialogText = all ? cm.phrase("Replace all:") : cm.phrase("Replace:")
+ var fragment = el("", null,
+ el("span", {className: "CodeMirror-search-label"}, dialogText),
+ getReplaceQueryDialog(cm))
+ dialog(cm, fragment, dialogText, query, function(query) {
if (!query) return;
query = parseQuery(query);
dialog(cm, getReplacementQueryDialog(cm), cm.phrase("Replace with:"), "", function(text) {
diff --git a/dcScript/codemirror/addon/search/searchcursor.js b/dcScript/codemirror/addon/search/searchcursor.js
index 816bf77..ffe6932 100644
--- a/dcScript/codemirror/addon/search/searchcursor.js
+++ b/dcScript/codemirror/addon/search/searchcursor.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -202,6 +202,7 @@
function SearchCursor(doc, query, pos, options) {
this.atOccurrence = false
+ this.afterEmptyMatch = false
this.doc = doc
pos = pos ? doc.clipPos(pos) : Pos(0, 0)
this.pos = {from: pos, to: pos}
@@ -237,21 +238,29 @@
findPrevious: function() {return this.find(true)},
find: function(reverse) {
- var result = this.matches(reverse, this.doc.clipPos(reverse ? this.pos.from : this.pos.to))
-
- // Implements weird auto-growing behavior on null-matches for
- // backwards-compatiblity with the vim code (unfortunately)
- while (result && CodeMirror.cmpPos(result.from, result.to) == 0) {
+ var head = this.doc.clipPos(reverse ? this.pos.from : this.pos.to);
+ if (this.afterEmptyMatch && this.atOccurrence) {
+ // do not return the same 0 width match twice
+ head = Pos(head.line, head.ch)
if (reverse) {
- if (result.from.ch) result.from = Pos(result.from.line, result.from.ch - 1)
- else if (result.from.line == this.doc.firstLine()) result = null
- else result = this.matches(reverse, this.doc.clipPos(Pos(result.from.line - 1)))
+ head.ch--;
+ if (head.ch < 0) {
+ head.line--;
+ head.ch = (this.doc.getLine(head.line) || "").length;
+ }
} else {
- if (result.to.ch < this.doc.getLine(result.to.line).length) result.to = Pos(result.to.line, result.to.ch + 1)
- else if (result.to.line == this.doc.lastLine()) result = null
- else result = this.matches(reverse, Pos(result.to.line + 1, 0))
+ head.ch++;
+ if (head.ch > (this.doc.getLine(head.line) || "").length) {
+ head.ch = 0;
+ head.line++;
+ }
+ }
+ if (CodeMirror.cmpPos(head, this.doc.clipPos(head)) != 0) {
+ return this.atOccurrence = false
}
}
+ var result = this.matches(reverse, head)
+ this.afterEmptyMatch = result && CodeMirror.cmpPos(result.from, result.to) == 0
if (result) {
this.pos = result
diff --git a/dcScript/codemirror/addon/selection/active-line.js b/dcScript/codemirror/addon/selection/active-line.js
index c7b14ce..ff81ffc 100644
--- a/dcScript/codemirror/addon/selection/active-line.js
+++ b/dcScript/codemirror/addon/selection/active-line.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
diff --git a/dcScript/codemirror/addon/selection/mark-selection.js b/dcScript/codemirror/addon/selection/mark-selection.js
new file mode 100644
index 0000000..fc80159
--- /dev/null
+++ b/dcScript/codemirror/addon/selection/mark-selection.js
@@ -0,0 +1,119 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+// Because sometimes you need to mark the selected *text*.
+//
+// Adds an option 'styleSelectedText' which, when enabled, gives
+// selected text the CSS class given as option value, or
+// "CodeMirror-selectedtext" when the value is not a string.
+
+(function(mod) {
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
+ mod(require("../../lib/codemirror"));
+ else if (typeof define == "function" && define.amd) // AMD
+ define(["../../lib/codemirror"], mod);
+ else // Plain browser env
+ mod(CodeMirror);
+})(function(CodeMirror) {
+ "use strict";
+
+ CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
+ var prev = old && old != CodeMirror.Init;
+ if (val && !prev) {
+ cm.state.markedSelection = [];
+ cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
+ reset(cm);
+ cm.on("cursorActivity", onCursorActivity);
+ cm.on("change", onChange);
+ } else if (!val && prev) {
+ cm.off("cursorActivity", onCursorActivity);
+ cm.off("change", onChange);
+ clear(cm);
+ cm.state.markedSelection = cm.state.markedSelectionStyle = null;
+ }
+ });
+
+ function onCursorActivity(cm) {
+ if (cm.state.markedSelection)
+ cm.operation(function() { update(cm); });
+ }
+
+ function onChange(cm) {
+ if (cm.state.markedSelection && cm.state.markedSelection.length)
+ cm.operation(function() { clear(cm); });
+ }
+
+ var CHUNK_SIZE = 8;
+ var Pos = CodeMirror.Pos;
+ var cmp = CodeMirror.cmpPos;
+
+ function coverRange(cm, from, to, addAt) {
+ if (cmp(from, to) == 0) return;
+ var array = cm.state.markedSelection;
+ var cls = cm.state.markedSelectionStyle;
+ for (var line = from.line;;) {
+ var start = line == from.line ? from : Pos(line, 0);
+ var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
+ var end = atEnd ? to : Pos(endLine, 0);
+ var mark = cm.markText(start, end, {className: cls});
+ if (addAt == null) array.push(mark);
+ else array.splice(addAt++, 0, mark);
+ if (atEnd) break;
+ line = endLine;
+ }
+ }
+
+ function clear(cm) {
+ var array = cm.state.markedSelection;
+ for (var i = 0; i < array.length; ++i) array[i].clear();
+ array.length = 0;
+ }
+
+ function reset(cm) {
+ clear(cm);
+ var ranges = cm.listSelections();
+ for (var i = 0; i < ranges.length; i++)
+ coverRange(cm, ranges[i].from(), ranges[i].to());
+ }
+
+ function update(cm) {
+ if (!cm.somethingSelected()) return clear(cm);
+ if (cm.listSelections().length > 1) return reset(cm);
+
+ var from = cm.getCursor("start"), to = cm.getCursor("end");
+
+ var array = cm.state.markedSelection;
+ if (!array.length) return coverRange(cm, from, to);
+
+ var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
+ if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE ||
+ cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
+ return reset(cm);
+
+ while (cmp(from, coverStart.from) > 0) {
+ array.shift().clear();
+ coverStart = array[0].find();
+ }
+ if (cmp(from, coverStart.from) < 0) {
+ if (coverStart.to.line - from.line < CHUNK_SIZE) {
+ array.shift().clear();
+ coverRange(cm, from, coverStart.to, 0);
+ } else {
+ coverRange(cm, from, coverStart.from, 0);
+ }
+ }
+
+ while (cmp(to, coverEnd.to) < 0) {
+ array.pop().clear();
+ coverEnd = array[array.length - 1].find();
+ }
+ if (cmp(to, coverEnd.to) > 0) {
+ if (to.line - coverEnd.from.line < CHUNK_SIZE) {
+ array.pop().clear();
+ coverRange(cm, coverEnd.from, to);
+ } else {
+ coverRange(cm, coverEnd.to, to);
+ }
+ }
+ }
+});
diff --git a/dcScript/codemirror/addon/selection/selection-pointer.js b/dcScript/codemirror/addon/selection/selection-pointer.js
new file mode 100644
index 0000000..924b465
--- /dev/null
+++ b/dcScript/codemirror/addon/selection/selection-pointer.js
@@ -0,0 +1,98 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/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) {
+ "use strict";
+
+ CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
+ var data = cm.state.selectionPointer;
+ if (data) {
+ CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
+ CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
+ CodeMirror.off(window, "scroll", data.windowScroll);
+ cm.off("cursorActivity", reset);
+ cm.off("scroll", reset);
+ cm.state.selectionPointer = null;
+ cm.display.lineDiv.style.cursor = "";
+ }
+ if (val) {
+ data = cm.state.selectionPointer = {
+ value: typeof val == "string" ? val : "default",
+ mousemove: function(event) { mousemove(cm, event); },
+ mouseout: function(event) { mouseout(cm, event); },
+ windowScroll: function() { reset(cm); },
+ rects: null,
+ mouseX: null, mouseY: null,
+ willUpdate: false
+ };
+ CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
+ CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
+ CodeMirror.on(window, "scroll", data.windowScroll);
+ cm.on("cursorActivity", reset);
+ cm.on("scroll", reset);
+ }
+ });
+
+ function mousemove(cm, event) {
+ var data = cm.state.selectionPointer;
+ if (event.buttons == null ? event.which : event.buttons) {
+ data.mouseX = data.mouseY = null;
+ } else {
+ data.mouseX = event.clientX;
+ data.mouseY = event.clientY;
+ }
+ scheduleUpdate(cm);
+ }
+
+ function mouseout(cm, event) {
+ if (!cm.getWrapperElement().contains(event.relatedTarget)) {
+ var data = cm.state.selectionPointer;
+ data.mouseX = data.mouseY = null;
+ scheduleUpdate(cm);
+ }
+ }
+
+ function reset(cm) {
+ cm.state.selectionPointer.rects = null;
+ scheduleUpdate(cm);
+ }
+
+ function scheduleUpdate(cm) {
+ if (!cm.state.selectionPointer.willUpdate) {
+ cm.state.selectionPointer.willUpdate = true;
+ setTimeout(function() {
+ update(cm);
+ cm.state.selectionPointer.willUpdate = false;
+ }, 50);
+ }
+ }
+
+ function update(cm) {
+ var data = cm.state.selectionPointer;
+ if (!data) return;
+ if (data.rects == null && data.mouseX != null) {
+ data.rects = [];
+ if (cm.somethingSelected()) {
+ for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
+ data.rects.push(sel.getBoundingClientRect());
+ }
+ }
+ var inside = false;
+ if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
+ var rect = data.rects[i];
+ if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
+ rect.top <= data.mouseY && rect.bottom >= data.mouseY)
+ inside = true;
+ }
+ var cursor = inside ? data.value : "";
+ if (cm.display.lineDiv.style.cursor != cursor)
+ cm.display.lineDiv.style.cursor = cursor;
+ }
+});
diff --git a/dcScript/codemirror/lib/codemirror.css b/dcScript/codemirror/lib/codemirror.css
index bc910fb..f4d5718 100644
--- a/dcScript/codemirror/lib/codemirror.css
+++ b/dcScript/codemirror/lib/codemirror.css
@@ -60,20 +60,13 @@
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
-.cm-fat-cursor-mark {
- background-color: rgba(20, 255, 20, 0.5);
- -webkit-animation: blink 1.06s steps(1) infinite;
- -moz-animation: blink 1.06s steps(1) infinite;
- animation: blink 1.06s steps(1) infinite;
-}
-.cm-animate-fat-cursor {
- width: auto;
- border: 0;
- -webkit-animation: blink 1.06s steps(1) infinite;
- -moz-animation: blink 1.06s steps(1) infinite;
- animation: blink 1.06s steps(1) infinite;
- background-color: #7e7;
-}
+.cm-fat-cursor .CodeMirror-line::selection,
+.cm-fat-cursor .CodeMirror-line > span::selection,
+.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; }
+.cm-fat-cursor .CodeMirror-line::-moz-selection,
+.cm-fat-cursor .CodeMirror-line > span::-moz-selection,
+.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; }
+.cm-fat-cursor { caret-color: transparent; }
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
@@ -164,17 +157,18 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
- /* 30px is the magic margin used to hide the element's real scrollbars */
+ /* 50px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
- margin-bottom: -30px; margin-right: -30px;
- padding-bottom: 30px;
+ margin-bottom: -50px; margin-right: -50px;
+ padding-bottom: 50px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
+ z-index: 0;
}
.CodeMirror-sizer {
position: relative;
- border-right: 30px solid transparent;
+ border-right: 50px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
@@ -184,6 +178,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
position: absolute;
z-index: 6;
display: none;
+ outline: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
@@ -212,7 +207,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
height: 100%;
display: inline-block;
vertical-align: top;
- margin-bottom: -30px;
+ margin-bottom: -50px;
}
.CodeMirror-gutter-wrapper {
position: absolute;
diff --git a/dcScript/codemirror/lib/codemirror.js b/dcScript/codemirror/lib/codemirror.js
index 9489e39..5ca96da 100644
--- a/dcScript/codemirror/lib/codemirror.js
+++ b/dcScript/codemirror/lib/codemirror.js
@@ -1,7 +1,7 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
-// This is CodeMirror (https://codemirror.net), a code editor
+// This is CodeMirror (https://codemirror.net/5), a code editor
// implemented in JavaScript on top of the browser's DOM.
//
// You can find some technical background for some of the code below
@@ -10,7 +10,7 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
- (global.CodeMirror = factory());
+ (global = global || self, global.CodeMirror = factory());
}(this, (function () { 'use strict';
// Kludges for bugs and behavior differences that can't be feature
@@ -26,13 +26,14 @@
var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]);
var webkit = !edge && /WebKit\//.test(userAgent);
var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent);
- var chrome = !edge && /Chrome\//.test(userAgent);
+ var chrome = !edge && /Chrome\/(\d+)/.exec(userAgent);
+ var chrome_version = chrome && +chrome[1];
var presto = /Opera\//.test(userAgent);
var safari = /Apple Computer/.test(navigator.vendor);
var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent);
var phantom = /PhantomJS/.test(userAgent);
- var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent);
+ var ios = safari && (/Mobile\/\w+/.test(userAgent) || navigator.maxTouchPoints > 2);
var android = /Android/.test(userAgent);
// This is woefully incomplete. Suggestions for alternative methods welcome.
var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent);
@@ -111,15 +112,15 @@
} while (child = child.parentNode)
}
- function activeElt() {
+ function activeElt(doc) {
// IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
// IE < 10 will throw when accessed while the page is loading or in an iframe.
// IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
var activeElement;
try {
- activeElement = document.activeElement;
+ activeElement = doc.activeElement;
} catch(e) {
- activeElement = document.body || null;
+ activeElement = doc.body || null;
}
while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement)
{ activeElement = activeElement.shadowRoot.activeElement; }
@@ -143,6 +144,10 @@
else if (ie) // Suppress mysterious IE10 errors
{ selectInput = function(node) { try { node.select(); } catch(_e) {} }; }
+ function doc(cm) { return cm.display.wrapper.ownerDocument }
+
+ function win(cm) { return doc(cm).defaultView }
+
function bind(f) {
var args = Array.prototype.slice.call(arguments, 1);
return function(){return f.apply(null, args)}
@@ -204,7 +209,7 @@
}
// Number of pixels added to scroller and sizer to hide scrollbar
- var scrollerGap = 30;
+ var scrollerGap = 50;
// Returned or thrown by various protocols to signal 'I'm not
// handling this'.
@@ -537,8 +542,8 @@
} else if (emitter.attachEvent) {
emitter.attachEvent("on" + type, f);
} else {
- var map$$1 = emitter._handlers || (emitter._handlers = {});
- map$$1[type] = (map$$1[type] || noHandlers).concat(f);
+ var map = emitter._handlers || (emitter._handlers = {});
+ map[type] = (map[type] || noHandlers).concat(f);
}
};
@@ -552,11 +557,11 @@
} else if (emitter.detachEvent) {
emitter.detachEvent("on" + type, f);
} else {
- var map$$1 = emitter._handlers, arr = map$$1 && map$$1[type];
+ var map = emitter._handlers, arr = map && map[type];
if (arr) {
var index = indexOf(arr, f);
if (index > -1)
- { map$$1[type] = arr.slice(0, index).concat(arr.slice(index + 1)); }
+ { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); }
}
}
}
@@ -684,11 +689,11 @@
try { return te.selectionStart != te.selectionEnd }
catch(e) { return false }
} : function (te) {
- var range$$1;
- try {range$$1 = te.ownerDocument.selection.createRange();}
+ var range;
+ try {range = te.ownerDocument.selection.createRange();}
catch(e) {}
- if (!range$$1 || range$$1.parentElement() != te) { return false }
- return range$$1.compareEndPoints("StartToEnd", range$$1) != 0
+ if (!range || range.parentElement() != te) { return false }
+ return range.compareEndPoints("StartToEnd", range) != 0
};
var hasCopyEvent = (function () {
@@ -836,10 +841,8 @@
return this.pos > start
};
StringStream.prototype.eatSpace = function () {
- var this$1 = this;
-
var start = this.pos;
- while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.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;};
@@ -1035,11 +1038,9 @@
};
Context.prototype.baseToken = function (n) {
- var this$1 = this;
-
if (!this.baseTokens) { return null }
while (this.baseTokens[this.baseTokenPos] <= n)
- { this$1.baseTokenPos += 2; }
+ { this.baseTokenPos += 2; }
var type = this.baseTokens[this.baseTokenPos + 1];
return {type: type && type.replace(/( |^)overlay .*/, ""),
size: this.baseTokens[this.baseTokenPos] - n}
@@ -1205,7 +1206,7 @@
var prop = lineClass[1] ? "bgClass" : "textClass";
if (output[prop] == null)
{ output[prop] = lineClass[2]; }
- else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
+ else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop]))
{ output[prop] += " " + lineClass[2]; }
} }
return type
@@ -1315,6 +1316,7 @@
if (span.marker == marker) { return span }
} }
}
+
// Remove a span from an array, returning undefined if no spans are
// left (we don't store arrays for lines without spans).
function removeMarkedSpan(spans, span) {
@@ -1323,9 +1325,16 @@
{ if (spans[i] != span) { (r || (r = [])).push(spans[i]); } }
return r
}
+
// Add a span to a line.
- function addMarkedSpan(line, span) {
- line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
+ function addMarkedSpan(line, span, op) {
+ var inThisOp = op && window.WeakSet && (op.markedSpans || (op.markedSpans = new WeakSet));
+ if (inThisOp && line.markedSpans && inThisOp.has(line.markedSpans)) {
+ line.markedSpans.push(span);
+ } else {
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span];
+ if (inThisOp) { inThisOp.add(line.markedSpans); }
+ }
span.marker.attachLine(line);
}
@@ -1528,8 +1537,8 @@
// Test whether there exists a collapsed span that partially
// overlaps (covers the start or end, but not both) of a new span.
// Such overlap is not allowed.
- function conflictingCollapsedRange(doc, lineNo$$1, from, to, marker) {
- var line = getLine(doc, lineNo$$1);
+ function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
+ var line = getLine(doc, lineNo);
var sps = sawCollapsedSpans && line.markedSpans;
if (sps) { for (var i = 0; i < sps.length; ++i) {
var sp = sps[i];
@@ -1845,7 +1854,7 @@
}
}
builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32;
- if (style || startStyle || endStyle || mustWrap || css) {
+ if (style || startStyle || endStyle || mustWrap || css || attributes) {
var fullStyle = style || "";
if (startStyle) { fullStyle += startStyle; }
if (endStyle) { fullStyle += endStyle; }
@@ -2190,6 +2199,7 @@
if (cm.options.lineNumbers || markers) {
var wrap$1 = ensureLineWrapped(lineView);
var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"));
+ gutterWrap.setAttribute("aria-hidden", "true");
cm.display.input.setUneditable(gutterWrap);
wrap$1.insertBefore(gutterWrap, lineView.text);
if (lineView.line.gutterClass)
@@ -2346,12 +2356,14 @@
function mapFromLineView(lineView, line, lineN) {
if (lineView.line == line)
{ return {map: lineView.measure.map, cache: lineView.measure.cache} }
- for (var i = 0; i < lineView.rest.length; i++)
- { if (lineView.rest[i] == line)
- { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
- for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
- { if (lineNo(lineView.rest[i$1]) > lineN)
- { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
+ if (lineView.rest) {
+ for (var i = 0; i < lineView.rest.length; i++)
+ { if (lineView.rest[i] == line)
+ { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
+ for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
+ { if (lineNo(lineView.rest[i$1]) > lineN)
+ { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
+ }
}
// Render a line into the hidden node display.externalMeasured. Used
@@ -2431,36 +2443,36 @@
var nullRect = {left: 0, right: 0, top: 0, bottom: 0};
- function nodeAndOffsetInLineMap(map$$1, ch, bias) {
+ function nodeAndOffsetInLineMap(map, ch, bias) {
var node, start, end, collapse, mStart, mEnd;
// First, search the line map for the text node corresponding to,
// or closest to, the target character.
- for (var i = 0; i < map$$1.length; i += 3) {
- mStart = map$$1[i];
- mEnd = map$$1[i + 1];
+ for (var i = 0; i < map.length; i += 3) {
+ mStart = map[i];
+ mEnd = map[i + 1];
if (ch < mStart) {
start = 0; end = 1;
collapse = "left";
} else if (ch < mEnd) {
start = ch - mStart;
end = start + 1;
- } else if (i == map$$1.length - 3 || ch == mEnd && map$$1[i + 3] > ch) {
+ } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
end = mEnd - mStart;
start = end - 1;
if (ch >= mEnd) { collapse = "right"; }
}
if (start != null) {
- node = map$$1[i + 2];
+ node = map[i + 2];
if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
{ collapse = bias; }
if (bias == "left" && start == 0)
- { while (i && map$$1[i - 2] == map$$1[i - 3] && map$$1[i - 1].insertLeft) {
- node = map$$1[(i -= 3) + 2];
+ { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
+ node = map[(i -= 3) + 2];
collapse = "left";
} }
if (bias == "right" && start == mEnd - mStart)
- { while (i < map$$1.length - 3 && map$$1[i + 3] == map$$1[i + 4] && !map$$1[i + 5].insertLeft) {
- node = map$$1[(i += 3) + 2];
+ { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
+ node = map[(i += 3) + 2];
collapse = "right";
} }
break
@@ -2565,22 +2577,24 @@
cm.display.lineNumChars = null;
}
- function pageScrollX() {
+ function pageScrollX(doc) {
// Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206
// which causes page_Offset and bounding client rects to use
// different reference viewports and invalidate our calculations.
- if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) }
- return window.pageXOffset || (document.documentElement || document.body).scrollLeft
+ if (chrome && android) { return -(doc.body.getBoundingClientRect().left - parseInt(getComputedStyle(doc.body).marginLeft)) }
+ return doc.defaultView.pageXOffset || (doc.documentElement || doc.body).scrollLeft
}
- function pageScrollY() {
- if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) }
- return window.pageYOffset || (document.documentElement || document.body).scrollTop
+ function pageScrollY(doc) {
+ if (chrome && android) { return -(doc.body.getBoundingClientRect().top - parseInt(getComputedStyle(doc.body).marginTop)) }
+ return doc.defaultView.pageYOffset || (doc.documentElement || doc.body).scrollTop
}
function widgetTopHeight(lineObj) {
+ var ref = visualLine(lineObj);
+ var widgets = ref.widgets;
var height = 0;
- if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above)
- { height += widgetHeight(lineObj.widgets[i]); } } }
+ if (widgets) { for (var i = 0; i < widgets.length; ++i) { if (widgets[i].above)
+ { height += widgetHeight(widgets[i]); } } }
return height
}
@@ -2600,8 +2614,8 @@
else { yOff -= cm.display.viewOffset; }
if (context == "page" || context == "window") {
var lOff = cm.display.lineSpace.getBoundingClientRect();
- yOff += lOff.top + (context == "window" ? 0 : pageScrollY());
- var xOff = lOff.left + (context == "window" ? 0 : pageScrollX());
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY(doc(cm)));
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX(doc(cm)));
rect.left += xOff; rect.right += xOff;
}
rect.top += yOff; rect.bottom += yOff;
@@ -2615,8 +2629,8 @@
var left = coords.left, top = coords.top;
// First move into "page" coordinate system
if (context == "page") {
- left -= pageScrollX();
- top -= pageScrollY();
+ left -= pageScrollX(doc(cm));
+ top -= pageScrollY(doc(cm));
} else if (context == "local" || !context) {
var localBox = cm.display.sizer.getBoundingClientRect();
left += localBox.left;
@@ -2743,13 +2757,13 @@
return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x
}
- function coordsCharInner(cm, lineObj, lineNo$$1, x, y) {
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
// Move y into line-local coordinate space
y -= heightAtLine(lineObj);
var preparedMeasure = prepareMeasureForLine(cm, lineObj);
// When directly calling `measureCharPrepared`, we have to adjust
// for the widgets at this line.
- var widgetHeight$$1 = widgetTopHeight(lineObj);
+ var widgetHeight = widgetTopHeight(lineObj);
var begin = 0, end = lineObj.text.length, ltr = true;
var order = getOrder(lineObj, cm.doc.direction);
@@ -2757,7 +2771,7 @@
// which bidi section the coordinates fall into.
if (order) {
var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart)
- (cm, lineObj, lineNo$$1, preparedMeasure, order, x, y);
+ (cm, lineObj, lineNo, preparedMeasure, order, x, y);
ltr = part.level != 1;
// The awkward -1 offsets are needed because findFirst (called
// on these below) will treat its first bound as inclusive,
@@ -2773,7 +2787,7 @@
var chAround = null, boxAround = null;
var ch = findFirst(function (ch) {
var box = measureCharPrepared(cm, preparedMeasure, ch);
- box.top += widgetHeight$$1; box.bottom += widgetHeight$$1;
+ box.top += widgetHeight; box.bottom += widgetHeight;
if (!boxIsAfter(box, x, y, false)) { return false }
if (box.top <= y && box.left <= x) {
chAround = ch;
@@ -2797,27 +2811,27 @@
// left of the character and compare it's vertical position to the
// coordinates
sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" :
- (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight$$1 <= y) == ltr ?
+ (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ?
"after" : "before";
// Now get accurate coordinates for this place, in order to get a
// base X position
- var coords = cursorCoords(cm, Pos(lineNo$$1, ch, sticky), "line", lineObj, preparedMeasure);
+ var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure);
baseX = coords.left;
outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0;
}
ch = skipExtendingChars(lineObj.text, ch, 1);
- return PosWithInfo(lineNo$$1, ch, sticky, outside, x - baseX)
+ return PosWithInfo(lineNo, ch, sticky, outside, x - baseX)
}
- function coordsBidiPart(cm, lineObj, lineNo$$1, preparedMeasure, order, x, y) {
+ function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) {
// Bidi parts are sorted left-to-right, and in a non-line-wrapping
// situation, we can take this ordering to correspond to the visual
// ordering. This finds the first part whose end is after the given
// coordinates.
var index = findFirst(function (i) {
var part = order[i], ltr = part.level != 1;
- return boxIsAfter(cursorCoords(cm, Pos(lineNo$$1, ltr ? part.to : part.from, ltr ? "before" : "after"),
+ return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"),
"line", lineObj, preparedMeasure), x, y, true)
}, 0, order.length - 1);
var part = order[index];
@@ -2826,7 +2840,7 @@
// that start, move one part back.
if (index > 0) {
var ltr = part.level != 1;
- var start = cursorCoords(cm, Pos(lineNo$$1, ltr ? part.from : part.to, ltr ? "after" : "before"),
+ var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"),
"line", lineObj, preparedMeasure);
if (boxIsAfter(start, x, y, true) && start.top > y)
{ part = order[index - 1]; }
@@ -2964,7 +2978,7 @@
var x, y, space = display.lineSpace.getBoundingClientRect();
// Fails unpredictably on IE[67] when mouse is dragged around quickly.
try { x = e.clientX - space.left; y = e.clientY - space.top; }
- catch (e) { return null }
+ catch (e$1) { return null }
var coords = coordsChar(cm, x, y), line;
if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length;
@@ -3145,15 +3159,21 @@
var curFragment = result.cursors = document.createDocumentFragment();
var selFragment = result.selection = document.createDocumentFragment();
+ var customCursor = cm.options.$customCursor;
+ if (customCursor) { primary = true; }
for (var i = 0; i < doc.sel.ranges.length; i++) {
if (!primary && i == doc.sel.primIndex) { continue }
- var range$$1 = doc.sel.ranges[i];
- if (range$$1.from().line >= cm.display.viewTo || range$$1.to().line < cm.display.viewFrom) { continue }
- var collapsed = range$$1.empty();
- if (collapsed || cm.options.showCursorWhenSelecting)
- { drawSelectionCursor(cm, range$$1.head, curFragment); }
+ var range = doc.sel.ranges[i];
+ if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
+ var collapsed = range.empty();
+ if (customCursor) {
+ var head = customCursor(cm, range);
+ if (head) { drawSelectionCursor(cm, head, curFragment); }
+ } else if (collapsed || cm.options.showCursorWhenSelecting) {
+ drawSelectionCursor(cm, range.head, curFragment);
+ }
if (!collapsed)
- { drawSelectionRange(cm, range$$1, selFragment); }
+ { drawSelectionRange(cm, range, selFragment); }
}
return result
}
@@ -3167,6 +3187,12 @@
cursor.style.top = pos.top + "px";
cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px";
+ if (/\bcm-fat-cursor\b/.test(cm.getWrapperElement().className)) {
+ var charPos = charCoords(cm, head, "div", null, null);
+ var width = charPos.right - charPos.left;
+ cursor.style.width = (width > 0 ? width : cm.defaultCharWidth()) + "px";
+ }
+
if (pos.other) {
// Secondary cursor, shown when on a 'jump' in bi-directional text
var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"));
@@ -3180,7 +3206,7 @@
function cmpCoords(a, b) { return a.top - b.top || a.left - b.left }
// Draws the given range as a highlighted selection
- function drawSelectionRange(cm, range$$1, output) {
+ function drawSelectionRange(cm, range, output) {
var display = cm.display, doc = cm.doc;
var fragment = document.createDocumentFragment();
var padding = paddingH(cm.display), leftSide = padding.left;
@@ -3249,7 +3275,7 @@
return {start: start, end: end}
}
- var sFrom = range$$1.from(), sTo = range$$1.to();
+ var sFrom = range.from(), sTo = range.to();
if (sFrom.line == sTo.line) {
drawForLine(sFrom.line, sFrom.ch, sTo.ch);
} else {
@@ -3280,26 +3306,31 @@
var on = true;
display.cursorDiv.style.visibility = "";
if (cm.options.cursorBlinkRate > 0)
- { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; },
- cm.options.cursorBlinkRate); }
+ { display.blinker = setInterval(function () {
+ if (!cm.hasFocus()) { onBlur(cm); }
+ display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden";
+ }, cm.options.cursorBlinkRate); }
else if (cm.options.cursorBlinkRate < 0)
{ display.cursorDiv.style.visibility = "hidden"; }
}
function ensureFocus(cm) {
- if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm); }
+ if (!cm.hasFocus()) {
+ cm.display.input.focus();
+ if (!cm.state.focused) { onFocus(cm); }
+ }
}
function delayBlurEvent(cm) {
cm.state.delayingBlurEvent = true;
setTimeout(function () { if (cm.state.delayingBlurEvent) {
cm.state.delayingBlurEvent = false;
- onBlur(cm);
+ if (cm.state.focused) { onBlur(cm); }
} }, 100);
}
function onFocus(cm, e) {
- if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false; }
+ if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; }
if (cm.options.readOnly == "nocursor") { return }
if (!cm.state.focused) {
@@ -3334,10 +3365,14 @@
function updateHeightsInViewport(cm) {
var display = cm.display;
var prevBottom = display.lineDiv.offsetTop;
+ var viewTop = Math.max(0, display.scroller.getBoundingClientRect().top);
+ var oldHeight = display.lineDiv.getBoundingClientRect().top;
+ var mustScroll = 0;
for (var i = 0; i < display.view.length; i++) {
var cur = display.view[i], wrapping = cm.options.lineWrapping;
var height = (void 0), width = 0;
if (cur.hidden) { continue }
+ oldHeight += cur.line.height;
if (ie && ie_version < 8) {
var bot = cur.node.offsetTop + cur.node.offsetHeight;
height = bot - prevBottom;
@@ -3352,6 +3387,7 @@
}
var diff = cur.line.height - height;
if (diff > .005 || diff < -.005) {
+ if (oldHeight < viewTop) { mustScroll -= diff; }
updateLineHeight(cur.line, height);
updateWidgetHeight(cur.line);
if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
@@ -3366,6 +3402,7 @@
}
}
}
+ if (Math.abs(mustScroll) > 2) { display.scroller.scrollTop += mustScroll; }
}
// Read and store the height of line widgets associated with the
@@ -3409,8 +3446,9 @@
if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null;
+ var doc = display.wrapper.ownerDocument;
if (rect.top + box.top < 0) { doScroll = true; }
- else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; }
+ else if (rect.bottom + box.top > (doc.defaultView.innerHeight || doc.documentElement.clientHeight)) { doScroll = false; }
if (doScroll != null && !phantom) {
var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;"));
cm.display.lineSpace.appendChild(scrollNode);
@@ -3429,8 +3467,8 @@
// Set pos and end to the cursor positions around the character pos sticks to
// If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch
// If pos == Pos(_, 0, "before"), pos and end are unchanged
- pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos;
+ pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos;
}
for (var limit = 0; limit < 5; limit++) {
var changed = false;
@@ -3481,14 +3519,15 @@
if (newTop != screentop) { result.scrollTop = newTop; }
}
- var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft;
- var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0);
+ var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth;
+ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace;
+ var screenw = displayWidth(cm) - display.gutters.offsetWidth;
var tooWide = rect.right - rect.left > screenw;
if (tooWide) { rect.right = rect.left + screenw; }
if (rect.left < 10)
{ result.scrollLeft = 0; }
else if (rect.left < screenleft)
- { result.scrollLeft = Math.max(0, rect.left - (tooWide ? 0 : 10)); }
+ { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); }
else if (rect.right > screenw + screenleft - 3)
{ result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; }
return result
@@ -3516,9 +3555,9 @@
if (y != null) { cm.curOp.scrollTop = y; }
}
- function scrollToRange(cm, range$$1) {
+ function scrollToRange(cm, range) {
resolveScrollToPos(cm);
- cm.curOp.scrollToPos = range$$1;
+ cm.curOp.scrollToPos = range;
}
// When an operation has its scrollToPos property set, and another
@@ -3526,11 +3565,11 @@
// 'simulates' scrolling that position into view in a cheap way, so
// that the effect of intermediate scroll commands is not ignored.
function resolveScrollToPos(cm) {
- var range$$1 = cm.curOp.scrollToPos;
- if (range$$1) {
+ var range = cm.curOp.scrollToPos;
+ if (range) {
cm.curOp.scrollToPos = null;
- var from = estimateCoords(cm, range$$1.from), to = estimateCoords(cm, range$$1.to);
- scrollToCoordsRange(cm, from, to, range$$1.margin);
+ var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to);
+ scrollToCoordsRange(cm, from, to, range.margin);
}
}
@@ -3625,6 +3664,7 @@
this.vert.firstChild.style.height =
Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px";
} else {
+ this.vert.scrollTop = 0;
this.vert.style.display = "";
this.vert.firstChild.style.height = "0";
}
@@ -3662,13 +3702,13 @@
NativeScrollbars.prototype.zeroWidthHack = function () {
var w = mac && !mac_geMountainLion ? "12px" : "18px";
this.horiz.style.height = this.vert.style.width = w;
- this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none";
+ this.horiz.style.visibility = this.vert.style.visibility = "hidden";
this.disableHoriz = new Delayed;
this.disableVert = new Delayed;
};
NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) {
- bar.style.pointerEvents = "auto";
+ bar.style.visibility = "";
function maybeDisable() {
// To find out whether the scrollbar is still visible, we
// check whether the element under the pixel in the bottom
@@ -3677,9 +3717,9 @@
// (when the bar is hidden). If it is still visible, we keep
// it enabled, if it's hidden, we disable pointer events.
var box = bar.getBoundingClientRect();
- var elt$$1 = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2)
+ var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2)
: document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1);
- if (elt$$1 != bar) { bar.style.pointerEvents = "none"; }
+ if (elt != bar) { bar.style.visibility = "hidden"; }
else { delay.set(1000, maybeDisable); }
}
delay.set(1000, maybeDisable);
@@ -3780,7 +3820,8 @@
scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
scrollToPos: null, // Used to scroll to a specific position
focus: false,
- id: ++nextOpId // Unique ID
+ id: ++nextOpId, // Unique ID
+ markArrays: null // Used by addMarkedSpan
};
pushOperation(cm.curOp);
}
@@ -3859,7 +3900,7 @@
cm.display.maxLineChanged = false;
}
- var takeFocus = op.focus && op.focus == activeElt();
+ var takeFocus = op.focus && op.focus == activeElt(doc(cm));
if (op.preparedSelection)
{ cm.display.input.showSelection(op.preparedSelection, takeFocus); }
if (op.updatedDisplay || op.startHeight != cm.doc.height)
@@ -4019,10 +4060,8 @@
{ this.events.push(arguments); }
};
DisplayUpdate.prototype.finish = function () {
- var this$1 = this;
-
for (var i = 0; i < this.events.length; i++)
- { signal.apply(null, this$1.events[i]); }
+ { signal.apply(null, this.events[i]); }
};
function maybeClipScrollbars(cm) {
@@ -4038,11 +4077,11 @@
function selectionSnapshot(cm) {
if (cm.hasFocus()) { return null }
- var active = activeElt();
+ var active = activeElt(doc(cm));
if (!active || !contains(cm.display.lineDiv, active)) { return null }
var result = {activeElt: active};
if (window.getSelection) {
- var sel = window.getSelection();
+ var sel = win(cm).getSelection();
if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) {
result.anchorNode = sel.anchorNode;
result.anchorOffset = sel.anchorOffset;
@@ -4054,14 +4093,16 @@
}
function restoreSelection(snapshot) {
- if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return }
+ if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt(snapshot.activeElt.ownerDocument)) { return }
snapshot.activeElt.focus();
- if (snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {
- var sel = window.getSelection(), range$$1 = document.createRange();
- range$$1.setEnd(snapshot.anchorNode, snapshot.anchorOffset);
- range$$1.collapse(false);
+ if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) &&
+ snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) {
+ var doc = snapshot.activeElt.ownerDocument;
+ var sel = doc.defaultView.getSelection(), range = doc.createRange();
+ range.setEnd(snapshot.anchorNode, snapshot.anchorOffset);
+ range.collapse(false);
sel.removeAllRanges();
- sel.addRange(range$$1);
+ sel.addRange(range);
sel.extend(snapshot.focusNode, snapshot.focusOffset);
}
}
@@ -4154,6 +4195,8 @@
update.visible = visibleLines(cm.display, cm.doc, viewport);
if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
{ break }
+ } else if (first) {
+ update.visible = visibleLines(cm.display, cm.doc, viewport);
}
if (!updateDisplayIfNeeded(cm, update)) { break }
updateHeightsInViewport(cm);
@@ -4232,6 +4275,8 @@
function updateGutterSpace(display) {
var width = display.gutters.offsetWidth;
display.sizer.style.marginLeft = width + "px";
+ // Send an event to consumers responding to changes in gutter width.
+ signalLater(display, "gutterChanged", display);
}
function setDocumentHeight(cm, measure) {
@@ -4370,6 +4415,12 @@
d.scroller.setAttribute("tabIndex", "-1");
// The element in which the editor lives.
d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror");
+ // See #6982. FIXME remove when this has been fixed for a while in Chrome
+ if (chrome && chrome_version >= 105) { d.wrapper.style.clipPath = "inset(0px)"; }
+
+ // This attribute is respected by automatic translation systems such as Google Translate,
+ // and may also be respected by tools used by human translators.
+ d.wrapper.setAttribute('translate', 'no');
// Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; }
@@ -4467,7 +4518,24 @@
}
function onScrollWheel(cm, e) {
+ // On Chrome 102, viewport updates somehow stop wheel-based
+ // scrolling. Turning off pointer events during the scroll seems
+ // to avoid the issue.
+ if (chrome && chrome_version == 102) {
+ if (cm.display.chromeScrollHack == null) { cm.display.sizer.style.pointerEvents = "none"; }
+ else { clearTimeout(cm.display.chromeScrollHack); }
+ cm.display.chromeScrollHack = setTimeout(function () {
+ cm.display.chromeScrollHack = null;
+ cm.display.sizer.style.pointerEvents = "";
+ }, 100);
+ }
var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y;
+ var pixelsPerUnit = wheelPixelsPerUnit;
+ if (e.deltaMode === 0) {
+ dx = e.deltaX;
+ dy = e.deltaY;
+ pixelsPerUnit = 1;
+ }
var display = cm.display, scroll = display.scroller;
// Quit if there's nothing to scroll here
@@ -4496,10 +4564,10 @@
// estimated pixels/delta value, we just handle horizontal
// scrolling entirely here. It'll be slightly off from native, but
// better than glitching out.
- if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
+ if (dx && !gecko && !presto && pixelsPerUnit != null) {
if (dy && canScrollY)
- { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); }
- setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit));
+ { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * pixelsPerUnit)); }
+ setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * pixelsPerUnit));
// Only prevent default scrolling if vertical scrolling is
// actually possible. Otherwise, it causes vertical scroll
// jitter on OSX trackpads when deltaX is small and deltaY
@@ -4512,15 +4580,15 @@
// 'Project' the visible viewport to cover the area that is being
// scrolled into view (if we know enough to estimate it).
- if (dy && wheelPixelsPerUnit != null) {
- var pixels = dy * wheelPixelsPerUnit;
+ if (dy && pixelsPerUnit != null) {
+ var pixels = dy * pixelsPerUnit;
var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight;
if (pixels < 0) { top = Math.max(0, top + pixels - 50); }
else { bot = Math.min(cm.doc.height, bot + pixels + 50); }
updateDisplaySimple(cm, {top: top, bottom: bot});
}
- if (wheelSamples < 20) {
+ if (wheelSamples < 20 && e.deltaMode !== 0) {
if (display.wheelStartX == null) {
display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop;
display.wheelDX = dx; display.wheelDY = dy;
@@ -4554,40 +4622,32 @@
Selection.prototype.primary = function () { return this.ranges[this.primIndex] };
Selection.prototype.equals = function (other) {
- var this$1 = this;
-
if (other == this) { return true }
if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
for (var i = 0; i < this.ranges.length; i++) {
- var here = this$1.ranges[i], there = other.ranges[i];
+ var here = this.ranges[i], there = other.ranges[i];
if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false }
}
return true
};
Selection.prototype.deepCopy = function () {
- var this$1 = this;
-
var out = [];
for (var i = 0; i < this.ranges.length; i++)
- { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)); }
+ { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); }
return new Selection(out, this.primIndex)
};
Selection.prototype.somethingSelected = function () {
- var this$1 = this;
-
for (var i = 0; i < this.ranges.length; i++)
- { if (!this$1.ranges[i].empty()) { return true } }
+ { if (!this.ranges[i].empty()) { return true } }
return false
};
Selection.prototype.contains = function (pos, end) {
- var this$1 = this;
-
if (!end) { end = pos; }
for (var i = 0; i < this.ranges.length; i++) {
- var range = this$1.ranges[i];
+ var range = this.ranges[i];
if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
{ return i }
}
@@ -4713,16 +4773,16 @@
}
// Perform a change on the document data structure.
- function updateDoc(doc, change, markedSpans, estimateHeight$$1) {
+ function updateDoc(doc, change, markedSpans, estimateHeight) {
function spansFor(n) {return markedSpans ? markedSpans[n] : null}
function update(line, text, spans) {
- updateLine(line, text, spans, estimateHeight$$1);
+ updateLine(line, text, spans, estimateHeight);
signalLater(line, "change", line, change);
}
function linesFor(start, end) {
var result = [];
for (var i = start; i < end; ++i)
- { result.push(new Line(text[i], spansFor(i), estimateHeight$$1)); }
+ { result.push(new Line(text[i], spansFor(i), estimateHeight)); }
return result
}
@@ -4746,7 +4806,7 @@
update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans);
} else {
var added$1 = linesFor(1, text.length - 1);
- added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight$$1));
+ added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight));
update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0));
doc.insert(from.line + 1, added$1);
}
@@ -4787,6 +4847,7 @@
estimateLineHeights(cm);
loadMode(cm);
setDirectionClass(cm);
+ cm.options.direction = doc.direction;
if (!cm.options.lineWrapping) { findMaxLine(cm); }
cm.options.mode = doc.modeOption;
regChange(cm);
@@ -4803,19 +4864,19 @@
});
}
- function History(startGen) {
+ function History(prev) {
// Arrays of change events and selections. Doing something adds an
// event to done and clears undo. Undoing moves events from done
// to undone, redoing moves them in the other direction.
this.done = []; this.undone = [];
- this.undoDepth = Infinity;
+ this.undoDepth = prev ? prev.undoDepth : Infinity;
// Used to track when changes can be merged into a single undo
// event
this.lastModTime = this.lastSelTime = 0;
this.lastOp = this.lastSelOp = null;
this.lastOrigin = this.lastSelOrigin = null;
// Used by the isClean() method
- this.generation = this.maxGeneration = startGen || 1;
+ this.generation = this.maxGeneration = prev ? prev.maxGeneration : 1;
}
// Create a history change event from an updateDoc-style change
@@ -5083,11 +5144,9 @@
var obj = {
ranges: sel.ranges,
update: function(ranges) {
- var this$1 = this;
-
this.ranges = [];
for (var i = 0; i < ranges.length; i++)
- { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
+ { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
clipPos(doc, ranges[i].head)); }
},
origin: options && options.origin
@@ -5122,7 +5181,7 @@
(cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1);
setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true));
- if (!(options && options.scroll === false) && doc.cm)
+ if (!(options && options.scroll === false) && doc.cm && doc.cm.getOption("readOnly") != "nocursor")
{ ensureCursorVisible(doc.cm); }
}
@@ -5153,7 +5212,7 @@
var range = sel.ranges[i];
var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i];
var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear);
- var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear);
+ var newHead = range.head == range.anchor ? newAnchor : skipAtomic(doc, range.head, old && old.head, bias, mayClear);
if (out || newAnchor != range.anchor || newHead != range.head) {
if (!out) { out = sel.ranges.slice(0, i); }
out[i] = new Range(newAnchor, newHead);
@@ -5574,13 +5633,11 @@
// See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
function LeafChunk(lines) {
- var this$1 = this;
-
this.lines = lines;
this.parent = null;
var height = 0;
for (var i = 0; i < lines.length; ++i) {
- lines[i].parent = this$1;
+ lines[i].parent = this;
height += lines[i].height;
}
this.height = height;
@@ -5591,11 +5648,9 @@
// Remove the n lines at offset 'at'.
removeInner: function(at, n) {
- var this$1 = this;
-
for (var i = at, e = at + n; i < e; ++i) {
- var line = this$1.lines[i];
- this$1.height -= line.height;
+ var line = this.lines[i];
+ this.height -= line.height;
cleanUpLine(line);
signalLater(line, "delete");
}
@@ -5610,31 +5665,25 @@
// Insert the given array of lines at offset 'at', count them as
// having the given height.
insertInner: function(at, lines, height) {
- var this$1 = this;
-
this.height += height;
this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at));
- for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1; }
+ for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; }
},
// Used to iterate over a part of the tree.
iterN: function(at, n, op) {
- var this$1 = this;
-
for (var e = at + n; at < e; ++at)
- { if (op(this$1.lines[at])) { return true } }
+ { if (op(this.lines[at])) { return true } }
}
};
function BranchChunk(children) {
- var this$1 = this;
-
this.children = children;
var size = 0, height = 0;
for (var i = 0; i < children.length; ++i) {
var ch = children[i];
size += ch.chunkSize(); height += ch.height;
- ch.parent = this$1;
+ ch.parent = this;
}
this.size = size;
this.height = height;
@@ -5645,16 +5694,14 @@
chunkSize: function() { return this.size },
removeInner: function(at, n) {
- var this$1 = this;
-
this.size -= n;
for (var i = 0; i < this.children.length; ++i) {
- var child = this$1.children[i], sz = child.chunkSize();
+ var child = this.children[i], sz = child.chunkSize();
if (at < sz) {
var rm = Math.min(n, sz - at), oldHeight = child.height;
child.removeInner(at, rm);
- this$1.height -= oldHeight - child.height;
- if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null; }
+ this.height -= oldHeight - child.height;
+ if (sz == rm) { this.children.splice(i--, 1); child.parent = null; }
if ((n -= rm) == 0) { break }
at = 0;
} else { at -= sz; }
@@ -5671,18 +5718,14 @@
},
collapse: function(lines) {
- var this$1 = this;
-
- for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines); }
+ for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); }
},
insertInner: function(at, lines, height) {
- var this$1 = this;
-
this.size += lines.length;
this.height += height;
for (var i = 0; i < this.children.length; ++i) {
- var child = this$1.children[i], sz = child.chunkSize();
+ var child = this.children[i], sz = child.chunkSize();
if (at <= sz) {
child.insertInner(at, lines, height);
if (child.lines && child.lines.length > 50) {
@@ -5692,11 +5735,11 @@
for (var pos = remaining; pos < child.lines.length;) {
var leaf = new LeafChunk(child.lines.slice(pos, pos += 25));
child.height -= leaf.height;
- this$1.children.splice(++i, 0, leaf);
- leaf.parent = this$1;
+ this.children.splice(++i, 0, leaf);
+ leaf.parent = this;
}
child.lines = child.lines.slice(0, remaining);
- this$1.maybeSpill();
+ this.maybeSpill();
}
break
}
@@ -5728,10 +5771,8 @@
},
iterN: function(at, n, op) {
- var this$1 = this;
-
for (var i = 0; i < this.children.length; ++i) {
- var child = this$1.children[i], sz = child.chunkSize();
+ var child = this.children[i], sz = child.chunkSize();
if (at < sz) {
var used = Math.min(n, sz - at);
if (child.iterN(at, used, op)) { return true }
@@ -5745,20 +5786,16 @@
// Line widgets are block elements displayed above or below a line.
var LineWidget = function(doc, node, options) {
- var this$1 = this;
-
if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
- { this$1[opt] = options[opt]; } } }
+ { this[opt] = options[opt]; } } }
this.doc = doc;
this.node = node;
};
LineWidget.prototype.clear = function () {
- var this$1 = this;
-
var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line);
if (no == null || !ws) { return }
- for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1); } }
+ for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } }
if (!ws.length) { line.widgets = null; }
var height = widgetHeight(this);
updateLineHeight(line, Math.max(0, line.height - height));
@@ -5801,7 +5838,7 @@
changeLine(doc, handle, "widget", function (line) {
var widgets = line.widgets || (line.widgets = []);
if (widget.insertAt == null) { widgets.push(widget); }
- else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget); }
+ else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); }
widget.line = line;
if (cm && !lineIsHidden(doc, line)) {
var aboveVisible = heightAtLine(line) < doc.scrollTop;
@@ -5841,8 +5878,6 @@
// Clear the marker.
TextMarker.prototype.clear = function () {
- var this$1 = this;
-
if (this.explicitlyCleared) { return }
var cm = this.doc.cm, withOp = cm && !cm.curOp;
if (withOp) { startOperation(cm); }
@@ -5852,19 +5887,19 @@
}
var min = null, max = null;
for (var i = 0; i < this.lines.length; ++i) {
- var line = this$1.lines[i];
- var span = getMarkedSpanFor(line.markedSpans, this$1);
- if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text"); }
+ var line = this.lines[i];
+ var span = getMarkedSpanFor(line.markedSpans, this);
+ if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); }
else if (cm) {
if (span.to != null) { max = lineNo(line); }
if (span.from != null) { min = lineNo(line); }
}
line.markedSpans = removeMarkedSpan(line.markedSpans, span);
- if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm)
+ if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm)
{ updateLineHeight(line, textHeight(cm.display)); }
}
if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
- var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual);
+ var visual = visualLine(this.lines[i$1]), len = lineLength(visual);
if (len > cm.display.maxLineLength) {
cm.display.maxLine = visual;
cm.display.maxLineLength = len;
@@ -5890,13 +5925,11 @@
// Pos objects returned contain a line object, rather than a line
// number (used to prevent looking up the same line twice).
TextMarker.prototype.find = function (side, lineObj) {
- var this$1 = this;
-
if (side == null && this.type == "bookmark") { side = 1; }
var from, to;
for (var i = 0; i < this.lines.length; ++i) {
- var line = this$1.lines[i];
- var span = getMarkedSpanFor(line.markedSpans, this$1);
+ var line = this.lines[i];
+ var span = getMarkedSpanFor(line.markedSpans, this);
if (span.from != null) {
from = Pos(lineObj ? line : lineNo(line), span.from);
if (side == -1) { return from }
@@ -5991,7 +6024,7 @@
if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); }
addMarkedSpan(line, new MarkedSpan(marker,
curLine == from.line ? from.ch : null,
- curLine == to.line ? to.ch : null));
+ curLine == to.line ? to.ch : null), doc.cm && doc.cm.curOp);
++curLine;
});
// lineIsHidden depends on the presence of the spans, so needs a second pass
@@ -6030,21 +6063,17 @@
// implemented as a meta-marker-object controlling multiple normal
// markers.
var SharedTextMarker = function(markers, primary) {
- var this$1 = this;
-
this.markers = markers;
this.primary = primary;
for (var i = 0; i < markers.length; ++i)
- { markers[i].parent = this$1; }
+ { markers[i].parent = this; }
};
SharedTextMarker.prototype.clear = function () {
- var this$1 = this;
-
if (this.explicitlyCleared) { return }
this.explicitlyCleared = true;
for (var i = 0; i < this.markers.length; ++i)
- { this$1.markers[i].clear(); }
+ { this.markers[i].clear(); }
signalLater(this, "clear");
};
@@ -6167,6 +6196,7 @@
getRange: function(from, to, lineSep) {
var lines = getBetween(this, clipPos(this, from), clipPos(this, to));
if (lineSep === false) { return lines }
+ if (lineSep === '') { return lines.join('') }
return lines.join(lineSep || this.lineSeparator())
},
@@ -6187,11 +6217,11 @@
clipPos: function(pos) {return clipPos(this, pos)},
getCursor: function(start) {
- var range$$1 = this.sel.primary(), pos;
- if (start == null || start == "head") { pos = range$$1.head; }
- else if (start == "anchor") { pos = range$$1.anchor; }
- else if (start == "end" || start == "to" || start === false) { pos = range$$1.to(); }
- else { pos = range$$1.from(); }
+ var range = this.sel.primary(), pos;
+ if (start == null || start == "head") { pos = range.head; }
+ else if (start == "anchor") { pos = range.anchor; }
+ else if (start == "end" || start == "to" || start === false) { pos = range.to(); }
+ else { pos = range.from(); }
return pos
},
listSelections: function() { return this.sel.ranges },
@@ -6214,13 +6244,11 @@
extendSelections(this, clipPosArray(this, heads), options);
}),
setSelections: docMethodOp(function(ranges, primary, options) {
- var this$1 = this;
-
if (!ranges.length) { return }
var out = [];
for (var i = 0; i < ranges.length; i++)
- { out[i] = new Range(clipPos(this$1, ranges[i].anchor),
- clipPos(this$1, ranges[i].head)); }
+ { out[i] = new Range(clipPos(this, ranges[i].anchor),
+ clipPos(this, ranges[i].head || ranges[i].anchor)); }
if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); }
setSelection(this, normalizeSelection(this.cm, out, primary), options);
}),
@@ -6231,23 +6259,19 @@
}),
getSelection: function(lineSep) {
- var this$1 = this;
-
var ranges = this.sel.ranges, lines;
for (var i = 0; i < ranges.length; i++) {
- var sel = getBetween(this$1, ranges[i].from(), ranges[i].to());
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
lines = lines ? lines.concat(sel) : sel;
}
if (lineSep === false) { return lines }
else { return lines.join(lineSep || this.lineSeparator()) }
},
getSelections: function(lineSep) {
- var this$1 = this;
-
var parts = [], ranges = this.sel.ranges;
for (var i = 0; i < ranges.length; i++) {
- var sel = getBetween(this$1, ranges[i].from(), ranges[i].to());
- if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()); }
+ var sel = getBetween(this, ranges[i].from(), ranges[i].to());
+ if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); }
parts[i] = sel;
}
return parts
@@ -6259,16 +6283,14 @@
this.replaceSelections(dup, collapse, origin || "+input");
},
replaceSelections: docMethodOp(function(code, collapse, origin) {
- var this$1 = this;
-
var changes = [], sel = this.sel;
for (var i = 0; i < sel.ranges.length; i++) {
- var range$$1 = sel.ranges[i];
- changes[i] = {from: range$$1.from(), to: range$$1.to(), text: this$1.splitLines(code[i]), origin: origin};
+ var range = sel.ranges[i];
+ changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin};
}
var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse);
for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
- { makeChange(this$1, changes[i$1]); }
+ { makeChange(this, changes[i$1]); }
if (newSel) { setSelectionReplaceHistory(this, newSel); }
else if (this.cm) { ensureCursorVisible(this.cm); }
}),
@@ -6289,7 +6311,7 @@
clearHistory: function() {
var this$1 = this;
- this.history = new History(this.history.maxGeneration);
+ this.history = new History(this.history);
linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true);
},
@@ -6310,7 +6332,7 @@
undone: copyHistoryArray(this.history.undone)}
},
setHistory: function(histData) {
- var hist = this.history = new History(this.history.maxGeneration);
+ var hist = this.history = new History(this.history);
hist.done = copyHistoryArray(histData.done.slice(0), null, true);
hist.undone = copyHistoryArray(histData.undone.slice(0), null, true);
},
@@ -6412,18 +6434,18 @@
},
findMarks: function(from, to, filter) {
from = clipPos(this, from); to = clipPos(this, to);
- var found = [], lineNo$$1 = from.line;
+ var found = [], lineNo = from.line;
this.iter(from.line, to.line + 1, function (line) {
var spans = line.markedSpans;
if (spans) { for (var i = 0; i < spans.length; i++) {
var span = spans[i];
- if (!(span.to != null && lineNo$$1 == from.line && from.ch >= span.to ||
- span.from == null && lineNo$$1 != from.line ||
- span.from != null && lineNo$$1 == to.line && span.from >= to.ch) &&
+ if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
+ span.from == null && lineNo != from.line ||
+ span.from != null && lineNo == to.line && span.from >= to.ch) &&
(!filter || filter(span.marker)))
{ found.push(span.marker.parent || span.marker); }
} }
- ++lineNo$$1;
+ ++lineNo;
});
return found
},
@@ -6438,14 +6460,14 @@
},
posFromIndex: function(off) {
- var ch, lineNo$$1 = this.first, sepSize = this.lineSeparator().length;
+ var ch, lineNo = this.first, sepSize = this.lineSeparator().length;
this.iter(function (line) {
var sz = line.text.length + sepSize;
if (sz > off) { ch = off; return true }
off -= sz;
- ++lineNo$$1;
+ ++lineNo;
});
- return clipPos(this, Pos(lineNo$$1, ch))
+ return clipPos(this, Pos(lineNo, ch))
},
indexFromPos: function (coords) {
coords = clipPos(this, coords);
@@ -6484,15 +6506,13 @@
return copy
},
unlinkDoc: function(other) {
- var this$1 = this;
-
if (other instanceof CodeMirror) { other = other.doc; }
if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
- var link = this$1.linked[i];
+ var link = this.linked[i];
if (link.doc != other) { continue }
- this$1.linked.splice(i, 1);
- other.unlinkDoc(this$1);
- detachSharedMarkers(findSharedMarkers(this$1));
+ this.linked.splice(i, 1);
+ other.unlinkDoc(this);
+ detachSharedMarkers(findSharedMarkers(this));
break
} }
// If the histories were shared, split them again
@@ -6598,7 +6618,7 @@
cm.display.input.focus();
}
}
- catch(e){}
+ catch(e$1){}
}
}
@@ -6694,7 +6714,7 @@
46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock",
173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
- 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
+ 221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
};
@@ -6731,10 +6751,9 @@
// Very basic readline/emacs-style bindings, which are standard on Mac.
keyMap.emacsy = {
"Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
- "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
- "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
- "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
- "Ctrl-O": "openLine"
+ "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp",
+ "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine",
+ "Ctrl-T": "transposeChars", "Ctrl-O": "openLine"
};
keyMap.macDefault = {
"Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
@@ -6801,18 +6820,18 @@
return keymap
}
- function lookupKey(key, map$$1, handle, context) {
- map$$1 = getKeyMap(map$$1);
- var found = map$$1.call ? map$$1.call(key, context) : map$$1[key];
+ function lookupKey(key, map, handle, context) {
+ map = getKeyMap(map);
+ var found = map.call ? map.call(key, context) : map[key];
if (found === false) { return "nothing" }
if (found === "...") { return "multi" }
if (found != null && handle(found)) { return "handled" }
- if (map$$1.fallthrough) {
- if (Object.prototype.toString.call(map$$1.fallthrough) != "[object Array]")
- { return lookupKey(key, map$$1.fallthrough, handle, context) }
- for (var i = 0; i < map$$1.fallthrough.length; i++) {
- var result = lookupKey(key, map$$1.fallthrough[i], handle, context);
+ if (map.fallthrough) {
+ if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
+ { return lookupKey(key, map.fallthrough, handle, context) }
+ for (var i = 0; i < map.fallthrough.length; i++) {
+ var result = lookupKey(key, map.fallthrough[i], handle, context);
if (result) { return result }
}
}
@@ -6829,7 +6848,7 @@
var base = name;
if (event.altKey && base != "Alt") { name = "Alt-" + name; }
if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; }
- if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name; }
+ if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; }
if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; }
return name
}
@@ -7055,7 +7074,7 @@
goGroupRight: function (cm) { return cm.moveH(1, "group"); },
goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
goWordRight: function (cm) { return cm.moveH(1, "word"); },
- delCharBefore: function (cm) { return cm.deleteH(-1, "char"); },
+ delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); },
delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
@@ -7244,7 +7263,8 @@
var lastStoppedKey = null;
function onKeyDown(e) {
var cm = this;
- cm.curOp.focus = activeElt();
+ if (e.target && e.target != cm.display.input.getField()) { return }
+ cm.curOp.focus = activeElt(doc(cm));
if (signalDOMEvent(cm, e)) { return }
// IE does strange things with escape.
if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; }
@@ -7287,6 +7307,7 @@
function onKeyPress(e) {
var cm = this;
+ if (e.target && e.target != cm.display.input.getField()) { return }
if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
var keyCode = e.keyCode, charCode = e.charCode;
if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
@@ -7350,7 +7371,7 @@
}
if (clickInGutter(cm, e)) { return }
var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single";
- window.focus();
+ win(cm).focus();
// #3261: make sure, that we're not starting a second selection
if (button == 1 && cm.state.selectingText)
@@ -7405,7 +7426,7 @@
function leftButtonDown(cm, pos, repeat, event) {
if (ie) { setTimeout(bind(ensureFocus, cm), 0); }
- else { cm.curOp.focus = activeElt(); }
+ else { cm.curOp.focus = activeElt(doc(cm)); }
var behavior = configureMouse(cm, repeat, event);
@@ -7426,6 +7447,10 @@
var dragEnd = operation(cm, function (e) {
if (webkit) { display.scroller.draggable = false; }
cm.state.draggingText = false;
+ if (cm.state.delayingBlurEvent) {
+ if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; }
+ else { delayBlurEvent(cm); }
+ }
off(display.wrapper.ownerDocument, "mouseup", dragEnd);
off(display.wrapper.ownerDocument, "mousemove", mouseMove);
off(display.scroller, "dragstart", dragStart);
@@ -7435,8 +7460,8 @@
if (!behavior.addNew)
{ extendSelection(cm.doc, pos, null, null, behavior.extend); }
// Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
- if (webkit || ie && ie_version == 9)
- { setTimeout(function () {display.wrapper.ownerDocument.body.focus(); display.input.focus();}, 20); }
+ if ((webkit && !safari) || ie && ie_version == 9)
+ { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); }
else
{ display.input.focus(); }
}
@@ -7449,15 +7474,15 @@
if (webkit) { display.scroller.draggable = true; }
cm.state.draggingText = dragEnd;
dragEnd.copy = !behavior.moveOnDrag;
- // IE's approach to draggable
- if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
on(display.wrapper.ownerDocument, "mouseup", dragEnd);
on(display.wrapper.ownerDocument, "mousemove", mouseMove);
on(display.scroller, "dragstart", dragStart);
on(display.scroller, "drop", dragEnd);
- delayBlurEvent(cm);
+ cm.state.delayingBlurEvent = true;
setTimeout(function () { return display.input.focus(); }, 20);
+ // IE's approach to draggable
+ if (display.scroller.dragDrop) { display.scroller.dragDrop(); }
}
function rangeForUnit(cm, pos, unit) {
@@ -7470,19 +7495,20 @@
// Normal selection, as opposed to text dragging.
function leftButtonSelect(cm, event, start, behavior) {
- var display = cm.display, doc = cm.doc;
+ if (ie) { delayBlurEvent(cm); }
+ var display = cm.display, doc$1 = cm.doc;
e_preventDefault(event);
- var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges;
+ var ourRange, ourIndex, startSel = doc$1.sel, ranges = startSel.ranges;
if (behavior.addNew && !behavior.extend) {
- ourIndex = doc.sel.contains(start);
+ ourIndex = doc$1.sel.contains(start);
if (ourIndex > -1)
{ ourRange = ranges[ourIndex]; }
else
{ ourRange = new Range(start, start); }
} else {
- ourRange = doc.sel.primary();
- ourIndex = doc.sel.primIndex;
+ ourRange = doc$1.sel.primary();
+ ourIndex = doc$1.sel.primIndex;
}
if (behavior.unit == "rectangle") {
@@ -7490,27 +7516,27 @@
start = posFromMouse(cm, event, true, true);
ourIndex = -1;
} else {
- var range$$1 = rangeForUnit(cm, start, behavior.unit);
+ var range = rangeForUnit(cm, start, behavior.unit);
if (behavior.extend)
- { ourRange = extendRange(ourRange, range$$1.anchor, range$$1.head, behavior.extend); }
+ { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); }
else
- { ourRange = range$$1; }
+ { ourRange = range; }
}
if (!behavior.addNew) {
ourIndex = 0;
- setSelection(doc, new Selection([ourRange], 0), sel_mouse);
- startSel = doc.sel;
+ setSelection(doc$1, new Selection([ourRange], 0), sel_mouse);
+ startSel = doc$1.sel;
} else if (ourIndex == -1) {
ourIndex = ranges.length;
- setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex),
+ setSelection(doc$1, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex),
{scroll: false, origin: "*mouse"});
} else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) {
- setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
+ setSelection(doc$1, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
{scroll: false, origin: "*mouse"});
- startSel = doc.sel;
+ startSel = doc$1.sel;
} else {
- replaceOneSelection(doc, ourIndex, ourRange, sel_mouse);
+ replaceOneSelection(doc$1, ourIndex, ourRange, sel_mouse);
}
var lastPos = start;
@@ -7520,35 +7546,35 @@
if (behavior.unit == "rectangle") {
var ranges = [], tabSize = cm.options.tabSize;
- var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize);
- var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize);
+ var startCol = countColumn(getLine(doc$1, start.line).text, start.ch, tabSize);
+ var posCol = countColumn(getLine(doc$1, pos.line).text, pos.ch, tabSize);
var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol);
for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
line <= end; line++) {
- var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize);
+ var text = getLine(doc$1, line).text, leftPos = findColumn(text, left, tabSize);
if (left == right)
{ ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); }
else if (text.length > leftPos)
{ ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); }
}
if (!ranges.length) { ranges.push(new Range(start, start)); }
- setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
+ setSelection(doc$1, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
{origin: "*mouse", scroll: false});
cm.scrollIntoView(pos);
} else {
var oldRange = ourRange;
- var range$$1 = rangeForUnit(cm, pos, behavior.unit);
+ var range = rangeForUnit(cm, pos, behavior.unit);
var anchor = oldRange.anchor, head;
- if (cmp(range$$1.anchor, anchor) > 0) {
- head = range$$1.head;
- anchor = minPos(oldRange.from(), range$$1.anchor);
+ if (cmp(range.anchor, anchor) > 0) {
+ head = range.head;
+ anchor = minPos(oldRange.from(), range.anchor);
} else {
- head = range$$1.anchor;
- anchor = maxPos(oldRange.to(), range$$1.head);
+ head = range.anchor;
+ anchor = maxPos(oldRange.to(), range.head);
}
var ranges$1 = startSel.ranges.slice(0);
- ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head));
- setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse);
+ ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc$1, anchor), head));
+ setSelection(doc$1, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse);
}
}
@@ -7564,9 +7590,9 @@
var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle");
if (!cur) { return }
if (cmp(cur, lastPos) != 0) {
- cm.curOp.focus = activeElt();
+ cm.curOp.focus = activeElt(doc(cm));
extendTo(cur);
- var visible = visibleLines(display, doc);
+ var visible = visibleLines(display, doc$1);
if (cur.line >= visible.to || cur.line < visible.from)
{ setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); }
} else {
@@ -7591,7 +7617,7 @@
}
off(display.wrapper.ownerDocument, "mousemove", move);
off(display.wrapper.ownerDocument, "mouseup", up);
- doc.history.lastSelOrigin = null;
+ doc$1.history.lastSelOrigin = null;
}
var move = operation(cm, function (e) {
@@ -7606,17 +7632,17 @@
// Used when mouse-selecting to adjust the anchor to the proper side
// of a bidi jump depending on the visual position of the head.
- function bidiSimplify(cm, range$$1) {
- var anchor = range$$1.anchor;
- var head = range$$1.head;
+ function bidiSimplify(cm, range) {
+ var anchor = range.anchor;
+ var head = range.head;
var anchorLine = getLine(cm.doc, anchor.line);
- if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range$$1 }
+ if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range }
var order = getOrder(anchorLine);
- if (!order) { return range$$1 }
+ if (!order) { return range }
var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index];
- if (part.from != anchor.ch && part.to != anchor.ch) { return range$$1 }
+ if (part.from != anchor.ch && part.to != anchor.ch) { return range }
var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1);
- if (boundary == 0 || boundary == order.length) { return range$$1 }
+ if (boundary == 0 || boundary == order.length) { return range }
// Compute the relative visual position of the head compared to the
// anchor (<0 is to the left, >0 to the right)
@@ -7635,7 +7661,7 @@
var usePart = order[boundary + (leftSide ? -1 : 0)];
var from = leftSide == (usePart.level == 1);
var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before";
- return anchor.ch == ch && anchor.sticky == sticky ? range$$1 : new Range(new Pos(anchor.line, ch, sticky), head)
+ return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head)
}
@@ -7648,7 +7674,7 @@
mY = e.touches[0].clientY;
} else {
try { mX = e.clientX; mY = e.clientY; }
- catch(e) { return false }
+ catch(e$1) { return false }
}
if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
if (prevent) { e_preventDefault(e); }
@@ -7748,7 +7774,7 @@
for (var i = newBreaks.length - 1; i >= 0; i--)
{ replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); }
});
- option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
+ option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\u202d\u202e\u2066\u2067\u2069\ufeff\ufff9-\ufffc]/g, function (cm, val, old) {
cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g");
if (old != Init) { cm.refresh(); }
});
@@ -7812,6 +7838,12 @@
}
cm.display.input.readOnlyChanged(val);
});
+
+ option("screenReaderLabel", null, function (cm, val) {
+ val = (val === '') ? null : val;
+ cm.display.input.screenReaderLabelChanged(val);
+ });
+
option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true);
option("dragDrop", true, dragDropChanged);
option("allowDropFileTypes", null);
@@ -7922,15 +7954,17 @@
attachDoc(this, doc);
if ((options.autofocus && !mobile) || this.hasFocus())
- { setTimeout(bind(onFocus, this), 20); }
+ { setTimeout(function () {
+ if (this$1.hasFocus() && !this$1.state.focused) { onFocus(this$1); }
+ }, 20); }
else
{ onBlur(this); }
for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
- { optionHandlers[opt](this$1, options[opt], Init); } }
+ { optionHandlers[opt](this, options[opt], Init); } }
maybeUpdateLineNumberWidth(this);
if (options.finishInit) { options.finishInit(this); }
- for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1); }
+ for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); }
endOperation(this);
// Suppress optimizelegibility in Webkit, since it breaks text
// measuring on line wrapping boundaries.
@@ -8155,14 +8189,14 @@
var updateInput = cm.curOp.updateInput;
// Normal behavior is to insert the new text into every selection
for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
- var range$$1 = sel.ranges[i$1];
- var from = range$$1.from(), to = range$$1.to();
- if (range$$1.empty()) {
+ var range = sel.ranges[i$1];
+ var from = range.from(), to = range.to();
+ if (range.empty()) {
if (deleted && deleted > 0) // Handle deletion
{ from = Pos(from.line, from.ch - deleted); }
else if (cm.state.overwrite && !paste) // Handle overwrite
{ to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); }
- else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
+ else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n"))
{ from = to = Pos(from.line, 0); }
}
var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
@@ -8183,7 +8217,7 @@
var pasted = e.clipboardData && e.clipboardData.getData("Text");
if (pasted) {
e.preventDefault();
- if (!cm.isReadOnly() && !cm.options.disableInput)
+ if (!cm.isReadOnly() && !cm.options.disableInput && cm.hasFocus())
{ runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); }
return true
}
@@ -8195,21 +8229,21 @@
var sel = cm.doc.sel;
for (var i = sel.ranges.length - 1; i >= 0; i--) {
- var range$$1 = sel.ranges[i];
- if (range$$1.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range$$1.head.line)) { continue }
- var mode = cm.getModeAt(range$$1.head);
+ var range = sel.ranges[i];
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue }
+ var mode = cm.getModeAt(range.head);
var indented = false;
if (mode.electricChars) {
for (var j = 0; j < mode.electricChars.length; j++)
{ if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
- indented = indentLine(cm, range$$1.head.line, "smart");
+ indented = indentLine(cm, range.head.line, "smart");
break
} }
} else if (mode.electricInput) {
- if (mode.electricInput.test(getLine(cm.doc, range$$1.head.line).text.slice(0, range$$1.head.ch)))
- { indented = indentLine(cm, range$$1.head.line, "smart"); }
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
+ { indented = indentLine(cm, range.head.line, "smart"); }
}
- if (indented) { signalLater(cm, "electricInput", cm, range$$1.head.line); }
+ if (indented) { signalLater(cm, "electricInput", cm, range.head.line); }
}
}
@@ -8231,7 +8265,7 @@
}
function hiddenTextarea() {
- var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none");
+ var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; min-height: 1em; outline: none");
var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;");
// The textarea is kept positioned near the cursor to prevent the
// fact that it'll be scrolled into view on input from scrolling
@@ -8260,7 +8294,7 @@
CodeMirror.prototype = {
constructor: CodeMirror,
- focus: function(){window.focus(); this.display.input.focus();},
+ focus: function(){win(this).focus(); this.display.input.focus();},
setOption: function(option, value) {
var options = this.options, old = options[option];
@@ -8274,13 +8308,13 @@
getOption: function(option) {return this.options[option]},
getDoc: function() {return this.doc},
- addKeyMap: function(map$$1, bottom) {
- this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map$$1));
+ addKeyMap: function(map, bottom) {
+ this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map));
},
- removeKeyMap: function(map$$1) {
+ removeKeyMap: function(map) {
var maps = this.state.keyMaps;
for (var i = 0; i < maps.length; ++i)
- { if (maps[i] == map$$1 || maps[i].name == map$$1) {
+ { if (maps[i] == map || maps[i].name == map) {
maps.splice(i, 1);
return true
} }
@@ -8297,15 +8331,13 @@
regChange(this);
}),
removeOverlay: methodOp(function(spec) {
- var this$1 = this;
-
var overlays = this.state.overlays;
for (var i = 0; i < overlays.length; ++i) {
var cur = overlays[i].modeSpec;
if (cur == spec || typeof spec == "string" && cur.name == spec) {
overlays.splice(i, 1);
- this$1.state.modeGen++;
- regChange(this$1);
+ this.state.modeGen++;
+ regChange(this);
return
}
}
@@ -8319,24 +8351,22 @@
if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); }
}),
indentSelection: methodOp(function(how) {
- var this$1 = this;
-
var ranges = this.doc.sel.ranges, end = -1;
for (var i = 0; i < ranges.length; i++) {
- var range$$1 = ranges[i];
- if (!range$$1.empty()) {
- var from = range$$1.from(), to = range$$1.to();
+ var range = ranges[i];
+ if (!range.empty()) {
+ var from = range.from(), to = range.to();
var start = Math.max(end, from.line);
- end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
+ end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1;
for (var j = start; j < end; ++j)
- { indentLine(this$1, j, how); }
- var newRanges = this$1.doc.sel.ranges;
+ { indentLine(this, j, how); }
+ var newRanges = this.doc.sel.ranges;
if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
- { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); }
- } else if (range$$1.head.line > end) {
- indentLine(this$1, range$$1.head.line, how, true);
- end = range$$1.head.line;
- if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1); }
+ { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); }
+ } else if (range.head.line > end) {
+ indentLine(this, range.head.line, how, true);
+ end = range.head.line;
+ if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); }
}
}
}),
@@ -8378,8 +8408,6 @@
},
getHelpers: function(pos, type) {
- var this$1 = this;
-
var found = [];
if (!helpers.hasOwnProperty(type)) { return found }
var help = helpers[type], mode = this.getModeAt(pos);
@@ -8397,7 +8425,7 @@
}
for (var i$1 = 0; i$1 < help._global.length; i$1++) {
var cur = help._global[i$1];
- if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1)
+ if (cur.pred(mode, this) && indexOf(found, cur.val) == -1)
{ found.push(cur.val); }
}
return found
@@ -8410,10 +8438,10 @@
},
cursorCoords: function(start, mode) {
- var pos, range$$1 = this.doc.sel.primary();
- if (start == null) { pos = range$$1.head; }
+ var pos, range = this.doc.sel.primary();
+ if (start == null) { pos = range.head; }
else if (typeof start == "object") { pos = clipPos(this.doc, start); }
- else { pos = start ? range$$1.from() : range$$1.to(); }
+ else { pos = start ? range.from() : range.to(); }
return cursorCoords(this, pos, mode || "page")
},
@@ -8497,13 +8525,11 @@
triggerElectric: methodOp(function(text) { triggerElectric(this, text); }),
findPosH: function(from, amount, unit, visually) {
- var this$1 = this;
-
var dir = 1;
if (amount < 0) { dir = -1; amount = -amount; }
var cur = clipPos(this.doc, from);
for (var i = 0; i < amount; ++i) {
- cur = findPosH(this$1.doc, cur, dir, unit, visually);
+ cur = findPosH(this.doc, cur, dir, unit, visually);
if (cur.hitSide) { break }
}
return cur
@@ -8512,11 +8538,11 @@
moveH: methodOp(function(dir, unit) {
var this$1 = this;
- this.extendSelectionsBy(function (range$$1) {
- if (this$1.display.shift || this$1.doc.extend || range$$1.empty())
- { return findPosH(this$1.doc, range$$1.head, dir, unit, this$1.options.rtlMoveVisually) }
+ this.extendSelectionsBy(function (range) {
+ if (this$1.display.shift || this$1.doc.extend || range.empty())
+ { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) }
else
- { return dir < 0 ? range$$1.from() : range$$1.to() }
+ { return dir < 0 ? range.from() : range.to() }
}, sel_move);
}),
@@ -8525,23 +8551,21 @@
if (sel.somethingSelected())
{ doc.replaceSelection("", null, "+delete"); }
else
- { deleteNearSelection(this, function (range$$1) {
- var other = findPosH(doc, range$$1.head, dir, unit, false);
- return dir < 0 ? {from: other, to: range$$1.head} : {from: range$$1.head, to: other}
+ { deleteNearSelection(this, function (range) {
+ var other = findPosH(doc, range.head, dir, unit, false);
+ return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}
}); }
}),
findPosV: function(from, amount, unit, goalColumn) {
- var this$1 = this;
-
var dir = 1, x = goalColumn;
if (amount < 0) { dir = -1; amount = -amount; }
var cur = clipPos(this.doc, from);
for (var i = 0; i < amount; ++i) {
- var coords = cursorCoords(this$1, cur, "div");
+ var coords = cursorCoords(this, cur, "div");
if (x == null) { x = coords.left; }
else { coords.left = x; }
- cur = findPosV(this$1, coords, dir, unit);
+ cur = findPosV(this, coords, dir, unit);
if (cur.hitSide) { break }
}
return cur
@@ -8552,14 +8576,14 @@
var doc = this.doc, goals = [];
var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected();
- doc.extendSelectionsBy(function (range$$1) {
+ doc.extendSelectionsBy(function (range) {
if (collapse)
- { return dir < 0 ? range$$1.from() : range$$1.to() }
- var headPos = cursorCoords(this$1, range$$1.head, "div");
- if (range$$1.goalColumn != null) { headPos.left = range$$1.goalColumn; }
+ { return dir < 0 ? range.from() : range.to() }
+ var headPos = cursorCoords(this$1, range.head, "div");
+ if (range.goalColumn != null) { headPos.left = range.goalColumn; }
goals.push(headPos.left);
var pos = findPosV(this$1, headPos, dir, unit);
- if (unit == "page" && range$$1 == doc.sel.primary())
+ if (unit == "page" && range == doc.sel.primary())
{ addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); }
return pos
}, sel_move);
@@ -8594,7 +8618,7 @@
signal(this, "overwriteToggle", this, this.state.overwrite);
},
- hasFocus: function() { return this.display.input.getField() == activeElt() },
+ hasFocus: function() { return this.display.input.getField() == activeElt(doc(this)) },
isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }),
@@ -8606,22 +8630,22 @@
clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
},
- scrollIntoView: methodOp(function(range$$1, margin) {
- if (range$$1 == null) {
- range$$1 = {from: this.doc.sel.primary().head, to: null};
+ scrollIntoView: methodOp(function(range, margin) {
+ if (range == null) {
+ range = {from: this.doc.sel.primary().head, to: null};
if (margin == null) { margin = this.options.cursorScrollMargin; }
- } else if (typeof range$$1 == "number") {
- range$$1 = {from: Pos(range$$1, 0), to: null};
- } else if (range$$1.from == null) {
- range$$1 = {from: range$$1, to: null};
+ } else if (typeof range == "number") {
+ range = {from: Pos(range, 0), to: null};
+ } else if (range.from == null) {
+ range = {from: range, to: null};
}
- if (!range$$1.to) { range$$1.to = range$$1.from; }
- range$$1.margin = margin || 0;
+ if (!range.to) { range.to = range.from; }
+ range.margin = margin || 0;
- if (range$$1.from.line != null) {
- scrollToRange(this, range$$1);
+ if (range.from.line != null) {
+ scrollToRange(this, range);
} else {
- scrollToCoordsRange(this, range$$1.from, range$$1.to, range$$1.margin);
+ scrollToCoordsRange(this, range.from, range.to, range.margin);
}
}),
@@ -8632,11 +8656,11 @@
if (width != null) { this.display.wrapper.style.width = interpret(width); }
if (height != null) { this.display.wrapper.style.height = interpret(height); }
if (this.options.lineWrapping) { clearLineMeasurementCache(this); }
- var lineNo$$1 = this.display.viewFrom;
- this.doc.iter(lineNo$$1, this.display.viewTo, function (line) {
+ var lineNo = this.display.viewFrom;
+ this.doc.iter(lineNo, this.display.viewTo, function (line) {
if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
- { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo$$1, "widget"); break } } }
- ++lineNo$$1;
+ { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } }
+ ++lineNo;
});
this.curOp.forceUpdate = true;
signal(this, "refresh", this);
@@ -8653,7 +8677,7 @@
clearCaches(this);
scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop);
updateGutterSpace(this.display);
- if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
+ if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping)
{ estimateLineHeights(this); }
signal(this, "refresh", this);
}),
@@ -8695,14 +8719,14 @@
}
// Used for horizontal relative motion. Dir is -1 or 1 (left or
- // right), unit can be "char", "column" (like char, but doesn't
- // cross line boundaries), "word" (across next word), or "group" (to
- // the start of next group of word or non-word-non-whitespace
- // chars). The visually param controls whether, in right-to-left
- // text, direction 1 means to move towards the next index in the
- // string, or towards the character to the right of the current
- // position. The resulting position will have a hitSide=true
- // property if it reached the end of the document.
+ // right), unit can be "codepoint", "char", "column" (like char, but
+ // doesn't cross line boundaries), "word" (across next word), or
+ // "group" (to the start of next group of word or
+ // non-word-non-whitespace chars). The visually param controls
+ // whether, in right-to-left text, direction 1 means to move towards
+ // the next index in the string, or towards the character to the right
+ // of the current position. The resulting position will have a
+ // hitSide=true property if it reached the end of the document.
function findPosH(doc, pos, dir, unit, visually) {
var oldPos = pos;
var origDir = dir;
@@ -8716,7 +8740,15 @@
}
function moveOnce(boundToLine) {
var next;
- if (visually) {
+ if (unit == "codepoint") {
+ var ch = lineObj.text.charCodeAt(pos.ch + (dir > 0 ? 0 : -1));
+ if (isNaN(ch)) {
+ next = null;
+ } else {
+ var astral = dir > 0 ? ch >= 0xD800 && ch < 0xDC00 : ch >= 0xDC00 && ch < 0xDFFF;
+ next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (astral ? 2 : 1))), -dir);
+ }
+ } else if (visually) {
next = moveVisually(doc.cm, lineObj, pos, dir);
} else {
next = moveLogically(lineObj, pos, dir);
@@ -8732,7 +8764,7 @@
return true
}
- if (unit == "char") {
+ if (unit == "char" || unit == "codepoint") {
moveOnce();
} else if (unit == "column") {
moveOnce(true);
@@ -8767,7 +8799,7 @@
function findPosV(cm, pos, dir, unit) {
var doc = cm.doc, x = pos.left, y;
if (unit == "page") {
- var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight);
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, win(cm).innerHeight || doc(cm).documentElement.clientHeight);
var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3);
y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount;
@@ -8800,10 +8832,19 @@
var input = this, cm = input.cm;
var div = input.div = display.lineDiv;
+ div.contentEditable = true;
disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize);
+ function belongsToInput(e) {
+ for (var t = e.target; t; t = t.parentNode) {
+ if (t == div) { return true }
+ if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break }
+ }
+ return false
+ }
+
on(div, "paste", function (e) {
- if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
+ if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
// IE doesn't fire input events, so we schedule a read for the pasted content in this way
if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); }
});
@@ -8828,7 +8869,7 @@
});
function onCopyCut(e) {
- if (signalDOMEvent(cm, e)) { return }
+ if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return }
if (cm.somethingSelected()) {
setLastCopied({lineWise: false, text: cm.getSelections()});
if (e.type == "cut") { cm.replaceSelection("", null, "cut"); }
@@ -8858,7 +8899,7 @@
var kludge = hiddenTextarea(), te = kludge.firstChild;
cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild);
te.value = lastCopied.text.join("\n");
- var hadFocus = document.activeElement;
+ var hadFocus = activeElt(div.ownerDocument);
selectInput(te);
setTimeout(function () {
cm.display.lineSpace.removeChild(kludge);
@@ -8870,9 +8911,18 @@
on(div, "cut", onCopyCut);
};
+ ContentEditableInput.prototype.screenReaderLabelChanged = function (label) {
+ // Label for screenreaders, accessibility
+ if(label) {
+ this.div.setAttribute('aria-label', label);
+ } else {
+ this.div.removeAttribute('aria-label');
+ }
+ };
+
ContentEditableInput.prototype.prepareSelection = function () {
var result = prepareSelection(this.cm, false);
- result.focus = this.cm.state.focused;
+ result.focus = activeElt(this.div.ownerDocument) == this.div;
return result
};
@@ -8908,8 +8958,8 @@
var end = to.line < cm.display.viewTo && posToDOM(cm, to);
if (!end) {
var measure = view[view.length - 1].measure;
- var map$$1 = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
- end = {node: map$$1[map$$1.length - 1], offset: map$$1[map$$1.length - 2] - map$$1[map$$1.length - 3]};
+ var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map;
+ end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]};
}
if (!start || !end) {
@@ -8968,7 +9018,7 @@
ContentEditableInput.prototype.focus = function () {
if (this.cm.options.readOnly != "nocursor") {
- if (!this.selectionInEditor())
+ if (!this.selectionInEditor() || activeElt(this.div.ownerDocument) != this.div)
{ this.showSelection(this.prepareSelection(), true); }
this.div.focus();
}
@@ -8979,9 +9029,11 @@
ContentEditableInput.prototype.supportsTouch = function () { return true };
ContentEditableInput.prototype.receivedFocus = function () {
+ var this$1 = this;
+
var input = this;
if (this.selectionInEditor())
- { this.pollSelection(); }
+ { setTimeout(function () { return this$1.pollSelection(); }, 20); }
else
{ runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); }
@@ -9198,11 +9250,11 @@
addText(cmText);
return
}
- var markerID = node.getAttribute("cm-marker"), range$$1;
+ var markerID = node.getAttribute("cm-marker"), range;
if (markerID) {
var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID));
- if (found.length && (range$$1 = found[0].find(0)))
- { addText(getBetween(cm.doc, range$$1.from, range$$1.to).join(lineSep)); }
+ if (found.length && (range = found[0].find(0)))
+ { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); }
return
}
if (node.getAttribute("contenteditable") == "false") { return }
@@ -9270,13 +9322,13 @@
function find(textNode, topNode, offset) {
for (var i = -1; i < (maps ? maps.length : 0); i++) {
- var map$$1 = i < 0 ? measure.map : maps[i];
- for (var j = 0; j < map$$1.length; j += 3) {
- var curNode = map$$1[j + 2];
+ var map = i < 0 ? measure.map : maps[i];
+ for (var j = 0; j < map.length; j += 3) {
+ var curNode = map[j + 2];
if (curNode == textNode || curNode == topNode) {
var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]);
- var ch = map$$1[j] + offset;
- if (offset < 0 || curNode != textNode) { ch = map$$1[j + (offset ? 1 : 0)]; }
+ var ch = map[j] + offset;
+ if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; }
return Pos(line, ch)
}
}
@@ -9318,6 +9370,7 @@
// Used to work around IE issue with selection being forgotten when focus moves away from textarea
this.hasSelection = false;
this.composing = null;
+ this.resetting = false;
};
TextareaInput.prototype.init = function (display) {
@@ -9410,6 +9463,15 @@
this.textarea = this.wrapper.firstChild;
};
+ TextareaInput.prototype.screenReaderLabelChanged = function (label) {
+ // Label for screenreaders, accessibility
+ if(label) {
+ this.textarea.setAttribute('aria-label', label);
+ } else {
+ this.textarea.removeAttribute('aria-label');
+ }
+ };
+
TextareaInput.prototype.prepareSelection = function () {
// Redraw the selection and/or cursor
var cm = this.cm, display = cm.display, doc = cm.doc;
@@ -9441,8 +9503,9 @@
// Reset the input to correspond to the selection (or to be empty,
// when not typing and nothing is selected)
TextareaInput.prototype.reset = function (typing) {
- if (this.contextMenuPending || this.composing) { return }
+ if (this.contextMenuPending || this.composing && typing) { return }
var cm = this.cm;
+ this.resetting = true;
if (cm.somethingSelected()) {
this.prevInput = "";
var content = cm.getSelection();
@@ -9453,6 +9516,7 @@
this.prevInput = this.textarea.value = "";
if (ie && ie_version >= 9) { this.hasSelection = null; }
}
+ this.resetting = false;
};
TextareaInput.prototype.getField = function () { return this.textarea };
@@ -9460,7 +9524,7 @@
TextareaInput.prototype.supportsTouch = function () { return false };
TextareaInput.prototype.focus = function () {
- if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
+ if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt(this.textarea.ownerDocument) != this.textarea)) {
try { this.textarea.focus(); }
catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
}
@@ -9514,7 +9578,7 @@
// possible when it is clear that nothing happened. hasSelection
// will be the case when there is a lot of text in the textarea,
// in which case reading its value would be expensive.
- if (this.contextMenuPending || !cm.state.focused ||
+ if (this.contextMenuPending || this.resetting || !cm.state.focused ||
(hasSelection(input) && !prevInput && !this.composing) ||
cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
{ return false }
@@ -9583,9 +9647,9 @@
input.wrapper.style.cssText = "position: static";
te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";
var oldScrollY;
- if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712)
+ if (webkit) { oldScrollY = te.ownerDocument.defaultView.scrollY; } // Work around Chrome issue (#2712)
display.input.focus();
- if (webkit) { window.scrollTo(null, oldScrollY); }
+ if (webkit) { te.ownerDocument.defaultView.scrollTo(null, oldScrollY); }
display.input.reset();
// Adds "Select all" to context menu in FF
if (!cm.somethingSelected()) { te.value = input.prevInput = " "; }
@@ -9650,6 +9714,7 @@
TextareaInput.prototype.readOnlyChanged = function (val) {
if (!val) { this.reset(); }
this.textarea.disabled = val == "nocursor";
+ this.textarea.readOnly = !!val;
};
TextareaInput.prototype.setUneditable = function () {};
@@ -9666,7 +9731,7 @@
// Set autofocus to true if this textarea is focused, or if it has
// autofocus and no other element is focused.
if (options.autofocus == null) {
- var hasFocus = activeElt();
+ var hasFocus = activeElt(textarea.ownerDocument);
options.autofocus = hasFocus == textarea ||
textarea.getAttribute("autofocus") != null && hasFocus == document.body;
}
@@ -9800,7 +9865,7 @@
addLegacyProps(CodeMirror);
- CodeMirror.version = "5.52.0";
+ CodeMirror.version = "5.65.9";
return CodeMirror;
diff --git a/dcScript/codemirror/mode/css/css.js b/dcScript/codemirror/mode/css/css.js
index 05742c5..b0721b4 100644
--- a/dcScript/codemirror/mode/css/css.js
+++ b/dcScript/codemirror/mode/css/css.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -29,7 +29,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
valueKeywords = parserConfig.valueKeywords || {},
allowNested = parserConfig.allowNested,
lineComment = parserConfig.lineComment,
- supportsAtComponent = parserConfig.supportsAtComponent === true;
+ supportsAtComponent = parserConfig.supportsAtComponent === true,
+ highlightNonStandardPropertyKeywords = config.highlightNonStandardPropertyKeywords !== false;
var type, override;
function ret(style, tp) { type = tp; return style; }
@@ -77,8 +78,8 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
return ret("qualifier", "qualifier");
} else if (/[:;{}\[\]\(\)]/.test(ch)) {
return ret(null, ch);
- } else if (stream.match(/[\w-.]+(?=\()/)) {
- if (/^(url(-prefix)?|domain|regexp)$/.test(stream.current().toLowerCase())) {
+ } else if (stream.match(/^[\w-.]+(?=\()/)) {
+ if (/^(url(-prefix)?|domain|regexp)$/i.test(stream.current())) {
state.tokenize = tokenParenthesized;
}
return ret("variable callee", "variable");
@@ -107,7 +108,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
function tokenParenthesized(stream, state) {
stream.next(); // Must be '('
- if (!stream.match(/\s*[\"\')]/, false))
+ if (!stream.match(/^\s*[\"\')]/, false))
state.tokenize = tokenString(")");
else
state.tokenize = null;
@@ -197,7 +198,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
override = "property";
return "maybeprop";
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
- override = "string-2";
+ override = highlightNonStandardPropertyKeywords ? "string-2" : "property";
return "maybeprop";
} else if (allowNested) {
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
@@ -227,7 +228,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
if (type == "}" || type == "{") return popAndPass(type, stream, state);
if (type == "(") return pushContext(state, stream, "parens");
- if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
+ if (type == "hash" && !/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(stream.current())) {
override += " error";
} else if (type == "word") {
wordAsValue(stream);
@@ -291,7 +292,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
else if (propertyKeywords.hasOwnProperty(word))
override = "property";
else if (nonStandardPropertyKeywords.hasOwnProperty(word))
- override = "string-2";
+ override = highlightNonStandardPropertyKeywords ? "string-2" : "property";
else if (valueKeywords.hasOwnProperty(word))
override = "atom";
else if (colorKeywords.hasOwnProperty(word))
@@ -442,117 +443,151 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid", "orientation",
"device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
- "pointer", "any-pointer", "hover", "any-hover"
+ "pointer", "any-pointer", "hover", "any-hover", "prefers-color-scheme",
+ "dynamic-range", "video-dynamic-range"
], mediaFeatures = keySet(mediaFeatures_);
var mediaValueKeywords_ = [
"landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
- "interlace", "progressive"
+ "interlace", "progressive",
+ "dark", "light",
+ "standard", "high"
], mediaValueKeywords = keySet(mediaValueKeywords_);
var propertyKeywords_ = [
"align-content", "align-items", "align-self", "alignment-adjust",
- "alignment-baseline", "anchor-point", "animation", "animation-delay",
+ "alignment-baseline", "all", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-fill-mode",
"animation-iteration-count", "animation-name", "animation-play-state",
- "animation-timing-function", "appearance", "azimuth", "backface-visibility",
- "background", "background-attachment", "background-blend-mode", "background-clip",
- "background-color", "background-image", "background-origin", "background-position",
- "background-repeat", "background-size", "baseline-shift", "binding",
- "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
- "bookmark-target", "border", "border-bottom", "border-bottom-color",
- "border-bottom-left-radius", "border-bottom-right-radius",
- "border-bottom-style", "border-bottom-width", "border-collapse",
- "border-color", "border-image", "border-image-outset",
+ "animation-timing-function", "appearance", "azimuth", "backdrop-filter",
+ "backface-visibility", "background", "background-attachment",
+ "background-blend-mode", "background-clip", "background-color",
+ "background-image", "background-origin", "background-position",
+ "background-position-x", "background-position-y", "background-repeat",
+ "background-size", "baseline-shift", "binding", "bleed", "block-size",
+ "bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target",
+ "border", "border-bottom", "border-bottom-color", "border-bottom-left-radius",
+ "border-bottom-right-radius", "border-bottom-style", "border-bottom-width",
+ "border-collapse", "border-color", "border-image", "border-image-outset",
"border-image-repeat", "border-image-slice", "border-image-source",
- "border-image-width", "border-left", "border-left-color",
- "border-left-style", "border-left-width", "border-radius", "border-right",
- "border-right-color", "border-right-style", "border-right-width",
- "border-spacing", "border-style", "border-top", "border-top-color",
- "border-top-left-radius", "border-top-right-radius", "border-top-style",
- "border-top-width", "border-width", "bottom", "box-decoration-break",
- "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
- "caption-side", "caret-color", "clear", "clip", "color", "color-profile", "column-count",
- "column-fill", "column-gap", "column-rule", "column-rule-color",
- "column-rule-style", "column-rule-width", "column-span", "column-width",
- "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
- "cue-after", "cue-before", "cursor", "direction", "display",
- "dominant-baseline", "drop-initial-after-adjust",
- "drop-initial-after-align", "drop-initial-before-adjust",
- "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
- "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
- "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
- "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
- "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
- "font-stretch", "font-style", "font-synthesis", "font-variant",
- "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
- "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
- "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
- "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap",
- "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap",
- "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
- "grid-template-rows", "hanging-punctuation", "height", "hyphens",
- "icon", "image-orientation", "image-rendering", "image-resolution",
- "inline-box-align", "justify-content", "justify-items", "justify-self", "left", "letter-spacing",
- "line-break", "line-height", "line-stacking", "line-stacking-ruby",
+ "border-image-width", "border-left", "border-left-color", "border-left-style",
+ "border-left-width", "border-radius", "border-right", "border-right-color",
+ "border-right-style", "border-right-width", "border-spacing", "border-style",
+ "border-top", "border-top-color", "border-top-left-radius",
+ "border-top-right-radius", "border-top-style", "border-top-width",
+ "border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing",
+ "break-after", "break-before", "break-inside", "caption-side", "caret-color",
+ "clear", "clip", "color", "color-profile", "column-count", "column-fill",
+ "column-gap", "column-rule", "column-rule-color", "column-rule-style",
+ "column-rule-width", "column-span", "column-width", "columns", "contain",
+ "content", "counter-increment", "counter-reset", "crop", "cue", "cue-after",
+ "cue-before", "cursor", "direction", "display", "dominant-baseline",
+ "drop-initial-after-adjust", "drop-initial-after-align",
+ "drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size",
+ "drop-initial-value", "elevation", "empty-cells", "fit", "fit-content", "fit-position",
+ "flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow",
+ "flex-shrink", "flex-wrap", "float", "float-offset", "flow-from", "flow-into",
+ "font", "font-family", "font-feature-settings", "font-kerning",
+ "font-language-override", "font-optical-sizing", "font-size",
+ "font-size-adjust", "font-stretch", "font-style", "font-synthesis",
+ "font-variant", "font-variant-alternates", "font-variant-caps",
+ "font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric",
+ "font-variant-position", "font-variation-settings", "font-weight", "gap",
+ "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", "grid-auto-rows",
+ "grid-column", "grid-column-end", "grid-column-gap", "grid-column-start",
+ "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", "grid-row-start",
+ "grid-template", "grid-template-areas", "grid-template-columns",
+ "grid-template-rows", "hanging-punctuation", "height", "hyphens", "icon",
+ "image-orientation", "image-rendering", "image-resolution", "inline-box-align",
+ "inset", "inset-block", "inset-block-end", "inset-block-start", "inset-inline",
+ "inset-inline-end", "inset-inline-start", "isolation", "justify-content",
+ "justify-items", "justify-self", "left", "letter-spacing", "line-break",
+ "line-height", "line-height-step", "line-stacking", "line-stacking-ruby",
"line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin",
- "margin-bottom", "margin-left", "margin-right", "margin-top",
- "marks", "marquee-direction", "marquee-loop",
- "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
- "max-width", "min-height", "min-width", "mix-blend-mode", "move-to", "nav-down", "nav-index",
- "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
- "opacity", "order", "orphans", "outline",
- "outline-color", "outline-offset", "outline-style", "outline-width",
- "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
- "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
- "page", "page-break-after", "page-break-before", "page-break-inside",
- "page-policy", "pause", "pause-after", "pause-before", "perspective",
- "perspective-origin", "pitch", "pitch-range", "place-content", "place-items", "place-self", "play-during", "position",
- "presentation-level", "punctuation-trim", "quotes", "region-break-after",
- "region-break-before", "region-break-inside", "region-fragment",
- "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
- "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
- "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
- "shape-outside", "size", "speak", "speak-as", "speak-header",
- "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
- "tab-size", "table-layout", "target", "target-name", "target-new",
- "target-position", "text-align", "text-align-last", "text-decoration",
+ "margin-bottom", "margin-left", "margin-right", "margin-top", "marks",
+ "marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed",
+ "marquee-style", "mask-clip", "mask-composite", "mask-image", "mask-mode",
+ "mask-origin", "mask-position", "mask-repeat", "mask-size","mask-type",
+ "max-block-size", "max-height", "max-inline-size",
+ "max-width", "min-block-size", "min-height", "min-inline-size", "min-width",
+ "mix-blend-mode", "move-to", "nav-down", "nav-index", "nav-left", "nav-right",
+ "nav-up", "object-fit", "object-position", "offset", "offset-anchor",
+ "offset-distance", "offset-path", "offset-position", "offset-rotate",
+ "opacity", "order", "orphans", "outline", "outline-color", "outline-offset",
+ "outline-style", "outline-width", "overflow", "overflow-style",
+ "overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom",
+ "padding-left", "padding-right", "padding-top", "page", "page-break-after",
+ "page-break-before", "page-break-inside", "page-policy", "pause",
+ "pause-after", "pause-before", "perspective", "perspective-origin", "pitch",
+ "pitch-range", "place-content", "place-items", "place-self", "play-during",
+ "position", "presentation-level", "punctuation-trim", "quotes",
+ "region-break-after", "region-break-before", "region-break-inside",
+ "region-fragment", "rendering-intent", "resize", "rest", "rest-after",
+ "rest-before", "richness", "right", "rotate", "rotation", "rotation-point",
+ "row-gap", "ruby-align", "ruby-overhang", "ruby-position", "ruby-span",
+ "scale", "scroll-behavior", "scroll-margin", "scroll-margin-block",
+ "scroll-margin-block-end", "scroll-margin-block-start", "scroll-margin-bottom",
+ "scroll-margin-inline", "scroll-margin-inline-end",
+ "scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right",
+ "scroll-margin-top", "scroll-padding", "scroll-padding-block",
+ "scroll-padding-block-end", "scroll-padding-block-start",
+ "scroll-padding-bottom", "scroll-padding-inline", "scroll-padding-inline-end",
+ "scroll-padding-inline-start", "scroll-padding-left", "scroll-padding-right",
+ "scroll-padding-top", "scroll-snap-align", "scroll-snap-type",
+ "shape-image-threshold", "shape-inside", "shape-margin", "shape-outside",
+ "size", "speak", "speak-as", "speak-header", "speak-numeral",
+ "speak-punctuation", "speech-rate", "stress", "string-set", "tab-size",
+ "table-layout", "target", "target-name", "target-new", "target-position",
+ "text-align", "text-align-last", "text-combine-upright", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
- "text-decoration-style", "text-emphasis", "text-emphasis-color",
- "text-emphasis-position", "text-emphasis-style", "text-height",
- "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
- "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
- "text-wrap", "top", "transform", "transform-origin", "transform-style",
- "transition", "transition-delay", "transition-duration",
- "transition-property", "transition-timing-function", "unicode-bidi",
- "user-select", "vertical-align", "visibility", "voice-balance", "voice-duration",
- "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
- "voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break",
- "word-spacing", "word-wrap", "z-index",
+ "text-decoration-skip-ink", "text-decoration-style", "text-emphasis",
+ "text-emphasis-color", "text-emphasis-position", "text-emphasis-style",
+ "text-height", "text-indent", "text-justify", "text-orientation",
+ "text-outline", "text-overflow", "text-rendering", "text-shadow",
+ "text-size-adjust", "text-space-collapse", "text-transform",
+ "text-underline-position", "text-wrap", "top", "touch-action", "transform", "transform-origin",
+ "transform-style", "transition", "transition-delay", "transition-duration",
+ "transition-property", "transition-timing-function", "translate",
+ "unicode-bidi", "user-select", "vertical-align", "visibility", "voice-balance",
+ "voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate",
+ "voice-stress", "voice-volume", "volume", "white-space", "widows", "width",
+ "will-change", "word-break", "word-spacing", "word-wrap", "writing-mode", "z-index",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
- "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
+ "marker", "marker-end", "marker-mid", "marker-start", "paint-order", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
- "glyph-orientation-vertical", "text-anchor", "writing-mode"
+ "glyph-orientation-vertical", "text-anchor", "writing-mode",
], propertyKeywords = keySet(propertyKeywords_);
var nonStandardPropertyKeywords_ = [
+ "accent-color", "aspect-ratio", "border-block", "border-block-color", "border-block-end",
+ "border-block-end-color", "border-block-end-style", "border-block-end-width",
+ "border-block-start", "border-block-start-color", "border-block-start-style",
+ "border-block-start-width", "border-block-style", "border-block-width",
+ "border-inline", "border-inline-color", "border-inline-end",
+ "border-inline-end-color", "border-inline-end-style",
+ "border-inline-end-width", "border-inline-start", "border-inline-start-color",
+ "border-inline-start-style", "border-inline-start-width",
+ "border-inline-style", "border-inline-width", "content-visibility", "margin-block",
+ "margin-block-end", "margin-block-start", "margin-inline", "margin-inline-end",
+ "margin-inline-start", "overflow-anchor", "overscroll-behavior", "padding-block", "padding-block-end",
+ "padding-block-start", "padding-inline", "padding-inline-end",
+ "padding-inline-start", "scroll-snap-stop", "scrollbar-3d-light-color",
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
- "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
- "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
- "searchfield-results-decoration", "zoom"
+ "scrollbar-track-color", "searchfield-cancel-button", "searchfield-decoration",
+ "searchfield-results-button", "searchfield-results-decoration", "shape-inside", "zoom"
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
var fontProperties_ = [
- "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
- "font-stretch", "font-weight", "font-style"
+ "font-display", "font-family", "src", "unicode-range", "font-variant",
+ "font-feature-settings", "font-stretch", "font-weight", "font-style"
], fontProperties = keySet(fontProperties_);
var counterDescriptors_ = [
@@ -565,16 +600,16 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
- "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
+ "darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen",
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
- "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
- "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
+ "darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet",
+ "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
- "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
- "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
+ "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink",
+ "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey",
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
@@ -584,7 +619,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
- "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
+ "slateblue", "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan",
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
"whitesmoke", "yellow", "yellowgreen"
], colorKeywords = keySet(colorKeywords_);
@@ -594,22 +629,22 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
- "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
- "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
- "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
+ "avoid-region", "axis-pan", "background", "backwards", "baseline", "below", "bidi-override", "binary",
+ "bengali", "blink", "block", "block-axis", "blur", "bold", "bolder", "border", "border-box",
+ "both", "bottom", "break", "break-all", "break-word", "brightness", "bullets", "button",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
"col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
- "compact", "condensed", "contain", "content", "contents",
- "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
- "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
+ "compact", "condensed", "conic-gradient", "contain", "content", "contents",
+ "content-box", "context-menu", "continuous", "contrast", "copy", "counter", "counters", "cover", "crop",
+ "cross", "crosshair", "cubic-bezier", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari", "difference",
"disc", "discard", "disclosure-closed", "disclosure-open", "document",
"dot-dash", "dot-dot-dash",
- "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
+ "dotted", "double", "down", "drop-shadow", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
@@ -618,11 +653,11 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
"ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
- "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
- "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
+ "extra-expanded", "fantasy", "fast", "fill", "fill-box", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
+ "forwards", "from", "geometricPrecision", "georgian", "grayscale", "graytext", "grid", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
- "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
+ "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "hue-rotate", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
@@ -633,41 +668,37 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
- "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
- "media-controls-background", "media-current-time-display",
- "media-fullscreen-button", "media-mute-button", "media-play-button",
- "media-return-to-realtime-button", "media-rewind-button",
- "media-seek-back-button", "media-seek-forward-button", "media-slider",
- "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
- "media-volume-slider-container", "media-volume-sliderthumb", "medium",
- "menu", "menulist", "menulist-button", "menulist-text",
- "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
- "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize",
+ "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "manipulation", "match", "matrix", "matrix3d",
+ "media-play-button", "media-slider", "media-sliderthumb",
+ "media-volume-slider", "media-volume-sliderthumb", "medium",
+ "menu", "menulist", "menulist-button",
+ "menutext", "message-box", "middle", "min-intrinsic",
+ "mix", "mongolian", "monospace", "move", "multiple", "multiple_mask_images", "multiply", "myanmar", "n-resize",
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
- "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
+ "painted", "page", "paused", "persian", "perspective", "pinch-zoom", "plus-darker", "plus-lighter",
"pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
"progress", "push-button", "radial-gradient", "radio", "read-only",
"read-write", "read-write-plaintext-only", "rectangle", "region",
- "relative", "repeat", "repeating-linear-gradient",
- "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
+ "relative", "repeat", "repeating-linear-gradient", "repeating-radial-gradient",
+ "repeating-conic-gradient", "repeat-x", "repeat-y", "reset", "reverse",
"rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
"rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
- "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
+ "s-resize", "sans-serif", "saturate", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
"scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration", "self-start", "self-end",
- "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
+ "semi-condensed", "semi-expanded", "separate", "sepia", "serif", "show", "sidama",
"simp-chinese-formal", "simp-chinese-informal", "single",
"skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square",
- "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
- "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
+ "square-button", "start", "static", "status-bar", "stretch", "stroke", "stroke-box", "sub",
+ "subpixel-antialiased", "svg_masks", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"tamil",
@@ -677,10 +708,10 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"trad-chinese-formal", "trad-chinese-informal", "transform",
"translate", "translate3d", "translateX", "translateY", "translateZ",
- "transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up",
+ "transparent", "ultra-condensed", "ultra-expanded", "underline", "unidirectional-pan", "unset", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
- "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
+ "var", "vertical", "vertical-text", "view-box", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
"window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
"xx-large", "xx-small"
@@ -748,7 +779,7 @@ CodeMirror.defineMode("css", function(config, parserConfig) {
}
},
":": function(stream) {
- if (stream.match(/\s*\{/, false))
+ if (stream.match(/^\s*\{/, false))
return [null, null]
return false;
},
diff --git a/dcScript/codemirror/mode/css/gss.html b/dcScript/codemirror/mode/css/gss.html
new file mode 100644
index 0000000..aa12bfb
--- /dev/null
+++ b/dcScript/codemirror/mode/css/gss.html
@@ -0,0 +1,104 @@
+
+
+CodeMirror: Closure Stylesheets (GSS) mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Closure Stylesheets (GSS) mode
+
+
+
+ A mode for Closure Stylesheets (GSS).
+ MIME type defined: text/x-gss
.
+
+ Parsing/Highlighting Tests: normal , verbose .
+
+
diff --git a/dcScript/codemirror/mode/css/gss_test.js b/dcScript/codemirror/mode/css/gss_test.js
new file mode 100644
index 0000000..0901563
--- /dev/null
+++ b/dcScript/codemirror/mode/css/gss_test.js
@@ -0,0 +1,17 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function() {
+ "use strict";
+
+ var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-gss");
+ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "gss"); }
+
+ MT("atComponent",
+ "[def @component] {",
+ "[tag foo] {",
+ " [property color]: [keyword black];",
+ "}",
+ "}");
+
+})();
diff --git a/dcScript/codemirror/mode/css/index.html b/dcScript/codemirror/mode/css/index.html
new file mode 100644
index 0000000..233d19b
--- /dev/null
+++ b/dcScript/codemirror/mode/css/index.html
@@ -0,0 +1,81 @@
+
+
+CodeMirror: CSS mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+CSS mode
+
+/* Some example CSS */
+
+@import url("something.css");
+
+body {
+ margin: 0;
+ padding: 3em 6em;
+ font-family: tahoma, arial, sans-serif;
+ color: #000;
+}
+
+#navigation a {
+ font-weight: bold;
+ text-decoration: none !important;
+}
+
+h1 {
+ font-size: 2.5em;
+}
+
+h2 {
+ font-size: 1.7em;
+}
+
+h1:before, h2:before {
+ content: "::";
+}
+
+code {
+ font-family: courier, monospace;
+ font-size: 80%;
+ color: #418A8A;
+}
+
+
+
+ CSS mode supports this option:
+
+ highlightNonStandardPropertyKeywords : boolean
+ Whether to highlight non-standard CSS property keywords such as margin-inline
or zoom
(default: true
).
+
+
+ MIME types defined: text/css
, text/x-scss
(demo ), text/x-less
(demo ).
+
+ Parsing/Highlighting Tests: normal , verbose .
+
+
diff --git a/dcScript/codemirror/mode/css/less.html b/dcScript/codemirror/mode/css/less.html
new file mode 100644
index 0000000..ea7db00
--- /dev/null
+++ b/dcScript/codemirror/mode/css/less.html
@@ -0,0 +1,152 @@
+
+
+CodeMirror: LESS mode
+
+
+
+
+
+
+
+
+
+
+
+LESS mode
+@media screen and (device-aspect-ratio: 16/9) { … }
+@media screen and (device-aspect-ratio: 1280/720) { … }
+@media screen and (device-aspect-ratio: 2560/1440) { … }
+
+html:lang(fr-be)
+
+tr:nth-child(2n+1) /* represents every odd row of an HTML table */
+
+img:nth-of-type(2n+1) { float: right; }
+img:nth-of-type(2n) { float: left; }
+
+body > h2:not(:first-of-type):not(:last-of-type)
+
+html|*:not(:link):not(:visited)
+*|*:not(:hover)
+p::first-line { text-transform: uppercase }
+
+@namespace foo url(http://www.example.com);
+foo|h1 { color: blue } /* first rule */
+
+span[hello="Ocean"][goodbye="Land"]
+
+E[foo]{
+ padding:65px;
+}
+
+input[type="search"]::-webkit-search-decoration,
+input[type="search"]::-webkit-search-cancel-button {
+ -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
+ padding: 0;
+ border: 0;
+}
+.btn {
+ // reset here as of 2.0.3 due to Recess property order
+ border-color: #ccc;
+ border-color: rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);
+}
+fieldset span button, fieldset span input[type="file"] {
+ font-size:12px;
+ font-family:Arial, Helvetica, sans-serif;
+}
+
+.rounded-corners (@radius: 5px) {
+ border-radius: @radius;
+ -webkit-border-radius: @radius;
+ -moz-border-radius: @radius;
+}
+
+@import url("something.css");
+
+@light-blue: hsl(190, 50%, 65%);
+
+#menu {
+ position: absolute;
+ width: 100%;
+ z-index: 3;
+ clear: both;
+ display: block;
+ background-color: @blue;
+ height: 42px;
+ border-top: 2px solid lighten(@alpha-blue, 20%);
+ border-bottom: 2px solid darken(@alpha-blue, 25%);
+ .box-shadow(0, 1px, 8px, 0.6);
+ -moz-box-shadow: 0 0 0 #000; // Because firefox sucks.
+
+ &.docked {
+ background-color: hsla(210, 60%, 40%, 0.4);
+ }
+ &:hover {
+ background-color: @blue;
+ }
+
+ #dropdown {
+ margin: 0 0 0 117px;
+ padding: 0;
+ padding-top: 5px;
+ display: none;
+ width: 190px;
+ border-top: 2px solid @medium;
+ color: @highlight;
+ border: 2px solid darken(@medium, 25%);
+ border-left-color: darken(@medium, 15%);
+ border-right-color: darken(@medium, 15%);
+ border-top-width: 0;
+ background-color: darken(@medium, 10%);
+ ul {
+ padding: 0px;
+ }
+ li {
+ font-size: 14px;
+ display: block;
+ text-align: left;
+ padding: 0;
+ border: 0;
+ a {
+ display: block;
+ padding: 0px 15px;
+ text-decoration: none;
+ color: white;
+ &:hover {
+ background-color: darken(@medium, 15%);
+ text-decoration: none;
+ }
+ }
+ }
+ .border-radius(5px, bottom);
+ .box-shadow(0, 6px, 8px, 0.5);
+ }
+}
+
+
+
+ The LESS mode is a sub-mode of the CSS mode (defined in css.js
).
+
+ Parsing/Highlighting Tests: normal , verbose .
+
diff --git a/dcScript/codemirror/mode/css/less_test.js b/dcScript/codemirror/mode/css/less_test.js
new file mode 100644
index 0000000..cf367ea
--- /dev/null
+++ b/dcScript/codemirror/mode/css/less_test.js
@@ -0,0 +1,54 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function() {
+ "use strict";
+
+ var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less");
+ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); }
+
+ MT("variable",
+ "[variable-2 @base]: [atom #f04615];",
+ "[qualifier .class] {",
+ " [property width]: [variable&callee percentage]([number 0.5]); [comment // returns `50%`]",
+ " [property color]: [variable&callee saturate]([variable-2 @base], [number 5%]);",
+ "}");
+
+ MT("amp",
+ "[qualifier .child], [qualifier .sibling] {",
+ " [qualifier .parent] [atom &] {",
+ " [property color]: [keyword black];",
+ " }",
+ " [atom &] + [atom &] {",
+ " [property color]: [keyword red];",
+ " }",
+ "}");
+
+ MT("mixin",
+ "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {",
+ " [property color]: [variable&callee darken]([variable-2 @color], [number 10%]);",
+ "}",
+ "[qualifier .mixin] ([variable light]; [variable-2 @color]) {",
+ " [property color]: [variable&callee lighten]([variable-2 @color], [number 10%]);",
+ "}",
+ "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {",
+ " [property display]: [atom block];",
+ "}",
+ "[variable-2 @switch]: [variable light];",
+ "[qualifier .class] {",
+ " [qualifier .mixin]([variable-2 @switch]; [atom #888]);",
+ "}");
+
+ MT("nest",
+ "[qualifier .one] {",
+ " [def @media] ([property width]: [number 400px]) {",
+ " [property font-size]: [number 1.2em];",
+ " [def @media] [attribute print] [keyword and] [property color] {",
+ " [property color]: [keyword blue];",
+ " }",
+ " }",
+ "}");
+
+
+ MT("interpolation", ".@{[variable foo]} { [property font-weight]: [atom bold]; }");
+})();
diff --git a/dcScript/codemirror/mode/css/scss.html b/dcScript/codemirror/mode/css/scss.html
new file mode 100644
index 0000000..75ef4f9
--- /dev/null
+++ b/dcScript/codemirror/mode/css/scss.html
@@ -0,0 +1,158 @@
+
+
+CodeMirror: SCSS mode
+
+
+
+
+
+
+
+
+
+
+
+SCSS mode
+
+/* Some example SCSS */
+
+@import "compass/css3";
+$variable: #333;
+
+$blue: #3bbfce;
+$margin: 16px;
+
+.content-navigation {
+ #nested {
+ background-color: black;
+ }
+ border-color: $blue;
+ color:
+ darken($blue, 9%);
+}
+
+.border {
+ padding: $margin / 2;
+ margin: $margin / 2;
+ border-color: $blue;
+}
+
+@mixin table-base {
+ th {
+ text-align: center;
+ font-weight: bold;
+ }
+ td, th {padding: 2px}
+}
+
+table.hl {
+ margin: 2em 0;
+ td.ln {
+ text-align: right;
+ }
+}
+
+li {
+ font: {
+ family: serif;
+ weight: bold;
+ size: 1.2em;
+ }
+}
+
+@mixin left($dist) {
+ float: left;
+ margin-left: $dist;
+}
+
+#data {
+ @include left(10px);
+ @include table-base;
+}
+
+.source {
+ @include flow-into(target);
+ border: 10px solid green;
+ margin: 20px;
+ width: 200px; }
+
+.new-container {
+ @include flow-from(target);
+ border: 10px solid red;
+ margin: 20px;
+ width: 200px; }
+
+body {
+ margin: 0;
+ padding: 3em 6em;
+ font-family: tahoma, arial, sans-serif;
+ color: #000;
+}
+
+@mixin yellow() {
+ background: yellow;
+}
+
+.big {
+ font-size: 14px;
+}
+
+.nested {
+ @include border-radius(3px);
+ @extend .big;
+ p {
+ background: whitesmoke;
+ a {
+ color: red;
+ }
+ }
+}
+
+#navigation a {
+ font-weight: bold;
+ text-decoration: none !important;
+}
+
+h1 {
+ font-size: 2.5em;
+}
+
+h2 {
+ font-size: 1.7em;
+}
+
+h1:before, h2:before {
+ content: "::";
+}
+
+code {
+ font-family: courier, monospace;
+ font-size: 80%;
+ color: #418A8A;
+}
+
+
+
+ The SCSS mode is a sub-mode of the CSS mode (defined in css.js
).
+
+ Parsing/Highlighting Tests: normal , verbose .
+
+
diff --git a/dcScript/codemirror/mode/css/scss_test.js b/dcScript/codemirror/mode/css/scss_test.js
new file mode 100644
index 0000000..14c1d13
--- /dev/null
+++ b/dcScript/codemirror/mode/css/scss_test.js
@@ -0,0 +1,110 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function() {
+ var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss");
+ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); }
+
+ MT('url_with_quotation',
+ "[tag foo] { [property background]:[variable&callee url]([string test.jpg]) }");
+
+ MT('url_with_double_quotes',
+ "[tag foo] { [property background]:[variable&callee url]([string \"test.jpg\"]) }");
+
+ MT('url_with_single_quotes',
+ "[tag foo] { [property background]:[variable&callee url]([string \'test.jpg\']) }");
+
+ MT('string',
+ "[def @import] [string \"compass/css3\"]");
+
+ MT('important_keyword',
+ "[tag foo] { [property background]:[variable&callee url]([string \'test.jpg\']) [keyword !important] }");
+
+ MT('variable',
+ "[variable-2 $blue]:[atom #333]");
+
+ MT('variable_as_attribute',
+ "[tag foo] { [property color]:[variable-2 $blue] }");
+
+ MT('numbers',
+ "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }");
+
+ MT('number_percentage',
+ "[tag foo] { [property width]:[number 80%] }");
+
+ MT('selector',
+ "[builtin #hello][qualifier .world]{}");
+
+ MT('singleline_comment',
+ "[comment // this is a comment]");
+
+ MT('multiline_comment',
+ "[comment /*foobar*/]");
+
+ MT('attribute_with_hyphen',
+ "[tag foo] { [property font-size]:[number 10px] }");
+
+ MT('string_after_attribute',
+ "[tag foo] { [property content]:[string \"::\"] }");
+
+ MT('directives',
+ "[def @include] [qualifier .mixin]");
+
+ MT('basic_structure',
+ "[tag p] { [property background]:[keyword red]; }");
+
+ MT('nested_structure',
+ "[tag p] { [tag a] { [property color]:[keyword red]; } }");
+
+ MT('mixin',
+ "[def @mixin] [tag table-base] {}");
+
+ MT('number_without_semicolon',
+ "[tag p] {[property width]:[number 12]}",
+ "[tag a] {[property color]:[keyword red];}");
+
+ MT('atom_in_nested_block',
+ "[tag p] { [tag a] { [property color]:[atom #000]; } }");
+
+ MT('interpolation_in_property',
+ "[tag foo] { #{[variable-2 $hello]}:[number 2]; }");
+
+ MT('interpolation_in_selector',
+ "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }");
+
+ MT('interpolation_error',
+ "[tag foo]#{[variable foo]} { [property color]:[atom #000]; }");
+
+ MT("divide_operator",
+ "[tag foo] { [property width]:[number 4] [operator /] [number 2] }");
+
+ MT('nested_structure_with_id_selector',
+ "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }");
+
+ MT('indent_mixin',
+ "[def @mixin] [tag container] (",
+ " [variable-2 $a]: [number 10],",
+ " [variable-2 $b]: [number 10])",
+ "{}");
+
+ MT('indent_nested',
+ "[tag foo] {",
+ " [tag bar] {",
+ " }",
+ "}");
+
+ MT('indent_parentheses',
+ "[tag foo] {",
+ " [property color]: [variable&callee darken]([variable-2 $blue],",
+ " [number 9%]);",
+ "}");
+
+ MT('indent_vardef',
+ "[variable-2 $name]:",
+ " [string 'val'];",
+ "[tag tag] {",
+ " [tag inner] {",
+ " [property margin]: [number 3px];",
+ " }",
+ "}");
+})();
diff --git a/dcScript/codemirror/mode/css/test.js b/dcScript/codemirror/mode/css/test.js
new file mode 100644
index 0000000..573207e
--- /dev/null
+++ b/dcScript/codemirror/mode/css/test.js
@@ -0,0 +1,217 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function() {
+ var mode = CodeMirror.getMode({indentUnit: 2}, "css");
+ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
+
+ // Error, because "foobarhello" is neither a known type or property, but
+ // property was expected (after "and"), and it should be in parentheses.
+ MT("atMediaUnknownType",
+ "[def @media] [attribute screen] [keyword and] [error foobarhello] { }");
+
+ // Soft error, because "foobarhello" is not a known property or type.
+ MT("atMediaUnknownProperty",
+ "[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }");
+
+ // Make sure nesting works with media queries
+ MT("atMediaMaxWidthNested",
+ "[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }");
+
+ MT("atMediaFeatureValueKeyword",
+ "[def @media] ([property orientation]: [keyword landscape]) { }");
+
+ MT("atMediaUnknownFeatureValueKeyword",
+ "[def @media] ([property orientation]: [error upsidedown]) { }");
+
+ MT("atMediaUppercase",
+ "[def @MEDIA] ([property orienTAtion]: [keyword landScape]) { }");
+
+ MT("tagSelector",
+ "[tag foo] { }");
+
+ MT("classSelector",
+ "[qualifier .foo-bar_hello] { }");
+
+ MT("idSelector",
+ "[builtin #foo] { [error #foo] }");
+
+ MT("tagSelectorUnclosed",
+ "[tag foo] { [property margin]: [number 0] } [tag bar] { }");
+
+ MT("tagStringNoQuotes",
+ "[tag foo] { [property font-family]: [variable hello] [variable world]; }");
+
+ MT("tagStringDouble",
+ "[tag foo] { [property font-family]: [string \"hello world\"]; }");
+
+ MT("tagStringSingle",
+ "[tag foo] { [property font-family]: [string 'hello world']; }");
+
+ MT("tagColorKeyword",
+ "[tag foo] {",
+ " [property color]: [keyword black];",
+ " [property color]: [keyword navy];",
+ " [property color]: [keyword yellow];",
+ "}");
+
+ MT("tagColorHex3",
+ "[tag foo] { [property background]: [atom #fff]; }");
+
+ MT("tagColorHex4",
+ "[tag foo] { [property background]: [atom #ffff]; }");
+
+ MT("tagColorHex6",
+ "[tag foo] { [property background]: [atom #ffffff]; }");
+
+ MT("tagColorHex8",
+ "[tag foo] { [property background]: [atom #ffffffff]; }");
+
+ MT("tagColorHex5Invalid",
+ "[tag foo] { [property background]: [atom&error #fffff]; }");
+
+ MT("tagColorHexInvalid",
+ "[tag foo] { [property background]: [atom&error #ffg]; }");
+
+ MT("tagNegativeNumber",
+ "[tag foo] { [property margin]: [number -5px]; }");
+
+ MT("tagPositiveNumber",
+ "[tag foo] { [property padding]: [number 5px]; }");
+
+ MT("tagVendor",
+ "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }");
+
+ MT("tagBogusProperty",
+ "[tag foo] { [property&error barhelloworld]: [number 0]; }");
+
+ MT("tagTwoProperties",
+ "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }");
+
+ MT("tagTwoPropertiesURL",
+ "[tag foo] { [property background]: [variable&callee url]([string //example.com/foo.png]); [property padding]: [number 0]; }");
+
+ MT("indent_tagSelector",
+ "[tag strong], [tag em] {",
+ " [property background]: [variable&callee rgba](",
+ " [number 255], [number 255], [number 0], [number .2]",
+ " );",
+ "}");
+
+ MT("indent_atMedia",
+ "[def @media] {",
+ " [tag foo] {",
+ " [property color]:",
+ " [keyword yellow];",
+ " }",
+ "}");
+
+ MT("indent_comma",
+ "[tag foo] {",
+ " [property font-family]: [variable verdana],",
+ " [atom sans-serif];",
+ "}");
+
+ MT("indent_parentheses",
+ "[tag foo]:[variable-3 before] {",
+ " [property background]: [variable&callee url](",
+ "[string blahblah]",
+ "[string etc]",
+ "[string ]) [keyword !important];",
+ "}");
+
+ MT("font_face",
+ "[def @font-face] {",
+ " [property font-family]: [string 'myfont'];",
+ " [error nonsense]: [string 'abc'];",
+ " [property src]: [variable&callee url]([string http://blah]),",
+ " [variable&callee url]([string http://foo]);",
+ "}");
+
+ MT("empty_url",
+ "[def @import] [variable&callee url]() [attribute screen];");
+
+ MT("parens",
+ "[qualifier .foo] {",
+ " [property background-image]: [variable&callee fade]([atom #000], [number 20%]);",
+ " [property border-image]: [variable&callee linear-gradient](",
+ " [atom to] [atom bottom],",
+ " [variable&callee fade]([atom #000], [number 20%]) [number 0%],",
+ " [variable&callee fade]([atom #000], [number 20%]) [number 100%]",
+ " );",
+ "}");
+
+ MT("css_variable",
+ ":[variable-3 root] {",
+ " [variable-2 --main-color]: [atom #06c];",
+ "}",
+ "[tag h1][builtin #foo] {",
+ " [property color]: [variable&callee var]([variable-2 --main-color]);",
+ "}");
+
+ MT("blank_css_variable",
+ ":[variable-3 root] {",
+ " [variable-2 --]: [atom #06c];",
+ "}",
+ "[tag h1][builtin #foo] {",
+ " [property color]: [variable&callee var]([variable-2 --]);",
+ "}");
+
+ MT("supports",
+ "[def @supports] ([keyword not] (([property text-align-last]: [atom justify]) [keyword or] ([meta -moz-][property text-align-last]: [atom justify])) {",
+ " [property text-align-last]: [atom justify];",
+ "}");
+
+ MT("document",
+ "[def @document] [variable&callee url]([string http://blah]),",
+ " [variable&callee url-prefix]([string https://]),",
+ " [variable&callee domain]([string blah.com]),",
+ " [variable&callee regexp]([string \".*blah.+\"]) {",
+ " [builtin #id] {",
+ " [property background-color]: [keyword white];",
+ " }",
+ " [tag foo] {",
+ " [property font-family]: [variable Verdana], [atom sans-serif];",
+ " }",
+ "}");
+
+ MT("document_url",
+ "[def @document] [variable&callee url]([string http://blah]) { [qualifier .class] { } }");
+
+ MT("document_urlPrefix",
+ "[def @document] [variable&callee url-prefix]([string https://]) { [builtin #id] { } }");
+
+ MT("document_domain",
+ "[def @document] [variable&callee domain]([string blah.com]) { [tag foo] { } }");
+
+ MT("document_regexp",
+ "[def @document] [variable&callee regexp]([string \".*blah.+\"]) { [builtin #id] { } }");
+
+ MT("counter-style",
+ "[def @counter-style] [variable binary] {",
+ " [property system]: [atom numeric];",
+ " [property symbols]: [number 0] [number 1];",
+ " [property suffix]: [string \".\"];",
+ " [property range]: [atom infinite];",
+ " [property speak-as]: [atom numeric];",
+ "}");
+
+ MT("counter-style-additive-symbols",
+ "[def @counter-style] [variable simple-roman] {",
+ " [property system]: [atom additive];",
+ " [property additive-symbols]: [number 10] [variable X], [number 5] [variable V], [number 1] [variable I];",
+ " [property range]: [number 1] [number 49];",
+ "}");
+
+ MT("counter-style-use",
+ "[tag ol][qualifier .roman] { [property list-style]: [variable simple-roman]; }");
+
+ MT("counter-style-symbols",
+ "[tag ol] { [property list-style]: [variable&callee symbols]([atom cyclic] [string \"*\"] [string \"\\2020\"] [string \"\\2021\"] [string \"\\A7\"]); }");
+
+ MT("comment-does-not-disrupt",
+ "[def @font-face] [comment /* foo */] {",
+ " [property src]: [variable&callee url]([string x]);",
+ " [property font-family]: [variable One];",
+ "}")
+})();
diff --git a/dcScript/codemirror/mode/htmlmixed/htmlmixed.js b/dcScript/codemirror/mode/htmlmixed/htmlmixed.js
index 8341ac8..3f6d8b7 100644
--- a/dcScript/codemirror/mode/htmlmixed/htmlmixed.js
+++ b/dcScript/codemirror/mode/htmlmixed/htmlmixed.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -50,7 +50,7 @@
}
function getTagRegexp(tagName, anchored) {
- return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
+ return new RegExp((anchored ? "^" : "") + "<\/\\s*" + tagName + "\\s*>", "i");
}
function addTags(from, to) {
@@ -74,7 +74,8 @@
name: "xml",
htmlMode: true,
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
- multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
+ multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag,
+ allowMissingTagName: parserConfig.allowMissingTagName,
});
var tags = {};
diff --git a/dcScript/codemirror/mode/htmlmixed/index.html b/dcScript/codemirror/mode/htmlmixed/index.html
new file mode 100644
index 0000000..9548361
--- /dev/null
+++ b/dcScript/codemirror/mode/htmlmixed/index.html
@@ -0,0 +1,100 @@
+
+
+CodeMirror: HTML mixed mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+HTML mixed mode
+
+
+
+
+ Mixed HTML Example
+
+
+
+ Mixed HTML Example
+
+
+
+
+
+
+ The HTML mixed mode depends on the XML, JavaScript, and CSS modes.
+
+ It takes an optional mode configuration
+ option, tags
, which can be used to add custom
+ behavior for specific tags. When given, it should be an object
+ mapping tag names (for example script
) to arrays or
+ three-element arrays. Those inner arrays indicate [attributeName,
+ valueRegexp, modeSpec ]
+ specifications. For example, you could use ["type", /^foo$/,
+ "foo"]
to map the attribute type="foo"
to
+ the foo
mode. When the first two fields are null
+ ([null, null, "mode"]
), the given mode is used for
+ any such tag that doesn't match any of the previously given
+ attributes. For example:
+
+ var myModeSpec = {
+ name: "htmlmixed",
+ tags: {
+ style: [["type", /^text\/(x-)?scss$/, "text/x-scss"],
+ [null, null, "css"]],
+ custom: [[null, null, "customMode"]]
+ }
+}
+
+ MIME types defined: text/html
+ (redefined, only takes effect if you load this parser after the
+ XML parser).
+
+
diff --git a/dcScript/codemirror/mode/javascript/index.html b/dcScript/codemirror/mode/javascript/index.html
new file mode 100644
index 0000000..f4be5ea
--- /dev/null
+++ b/dcScript/codemirror/mode/javascript/index.html
@@ -0,0 +1,118 @@
+
+
+CodeMirror: JavaScript mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+JavaScript mode
+
+
+
+// Demo code (the actual new parser character stream implementation)
+
+function StringStream(string) {
+ this.pos = 0;
+ this.string = string;
+}
+
+StringStream.prototype = {
+ done: function() {return this.pos >= this.string.length;},
+ peek: function() {return this.string.charAt(this.pos);},
+ 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));
+ if (this.pos > start) return this.string.slice(start, this.pos);
+ },
+ backUp: function(n) {this.pos -= n;},
+ column: function() {return this.pos;},
+ eatSpace: function() {
+ var start = this.pos;
+ while (/\s/.test(this.string.charAt(this.pos))) this.pos++;
+ return this.pos - start;
+ },
+ match: function(pattern, consume, caseInsensitive) {
+ if (typeof pattern == "string") {
+ function cased(str) {return caseInsensitive ? str.toLowerCase() : str;}
+ if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) {
+ if (consume !== false) this.pos += str.length;
+ return true;
+ }
+ }
+ else {
+ var match = this.string.slice(this.pos).match(pattern);
+ if (match && consume !== false) this.pos += match[0].length;
+ return match;
+ }
+ }
+};
+
+
+
+
+
+ JavaScript mode supports several configuration options:
+
+ json
which will set the mode to expect JSON
+ data rather than a JavaScript program.
+ jsonld
which will set the mode to expect
+ JSON-LD linked data rather
+ than a JavaScript program (demo ).
+ typescript
which will activate additional
+ syntax highlighting and some other things for TypeScript code
+ (demo ).
+ trackScope
can be set to false to turn off
+ tracking of local variables. This will prevent locals from
+ getting the "variable-2"
token type, and will
+ break completion of locals with javascript-hint.
+ statementIndent
which (given a number) will
+ determine the amount of indentation to use for statements
+ continued on a new line.
+ wordCharacters
, a regexp that indicates which
+ characters should be considered part of an identifier.
+ Defaults to /[\w$]/
, which does not handle
+ non-ASCII identifiers. Can be set to something more elaborate
+ to improve Unicode support.
+
+
+
+ MIME types defined: text/javascript
, application/javascript
, application/x-javascript
, text/ecmascript
, application/ecmascript
, application/json
, application/x-json
, application/manifest+json
, application/ld+json
, text/typescript
, application/typescript
.
+
diff --git a/dcScript/codemirror/mode/javascript/javascript.js b/dcScript/codemirror/mode/javascript/javascript.js
index 04d01fc..48a46d6 100644
--- a/dcScript/codemirror/mode/javascript/javascript.js
+++ b/dcScript/codemirror/mode/javascript/javascript.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -16,6 +16,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var statementIndent = parserConfig.statementIndent;
var jsonldMode = parserConfig.jsonld;
var jsonMode = parserConfig.json || jsonldMode;
+ var trackScope = parserConfig.trackScope !== false
var isTS = parserConfig.typescript;
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
@@ -98,21 +99,25 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
} else if (ch == "`") {
state.tokenize = tokenQuasi;
return tokenQuasi(stream, state);
- } else if (ch == "#") {
+ } else if (ch == "#" && stream.peek() == "!") {
stream.skipToEnd();
- return ret("error", "error");
- } else if (ch == "<" && stream.match("!--") || ch == "-" && stream.match("->")) {
+ return ret("meta", "meta");
+ } else if (ch == "#" && stream.eatWhile(wordRE)) {
+ return ret("variable", "property")
+ } else if (ch == "<" && stream.match("!--") ||
+ (ch == "-" && stream.match("->") && !/\S/.test(stream.string.slice(0, stream.start)))) {
stream.skipToEnd()
return ret("comment", "comment")
} else if (isOperatorChar.test(ch)) {
if (ch != ">" || !state.lexical || state.lexical.type != ">") {
if (stream.eat("=")) {
if (ch == "!" || ch == "=") stream.eat("=")
- } else if (/[<>*+\-]/.test(ch)) {
+ } else if (/[<>*+\-|&?]/.test(ch)) {
stream.eat(ch)
if (ch == ">") stream.eat(ch)
}
}
+ if (ch == "?" && stream.eat(".")) return ret(".")
return ret("operator", "operator", stream.current());
} else if (wordRE.test(ch)) {
stream.eatWhile(wordRE);
@@ -122,7 +127,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
var kw = keywords[word]
return ret(kw.type, kw.style, word)
}
- if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
+ if (word == "async" && stream.match(/^(\s|\/\*([^*]|\*(?!\/))*?\*\/)*[\[\(\w]/, false))
return ret("async", "keyword", word)
}
return ret("variable", "variable", word)
@@ -214,7 +219,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
// Parser
- var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true,
+ "regexp": true, "this": true, "import": true, "jsonld-keyword": true};
function JSLexical(indented, column, type, align, prev, info) {
this.indented = indented;
@@ -226,6 +232,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function inScope(state, varname) {
+ if (!trackScope) return false
for (var v = state.localVars; v; v = v.next)
if (v.name == varname) return true;
for (var cx = state.context; cx; cx = cx.prev) {
@@ -272,6 +279,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function register(varname) {
var state = cx.state;
cx.marked = "def";
+ if (!trackScope) return
if (state.context) {
if (state.lexical.info == "var" && state.context && state.context.block) {
// FIXME function decls are also not block scoped
@@ -322,6 +330,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
cx.state.localVars = null
}
+ pushcontext.lex = pushblockcontext.lex = true
function popcontext() {
cx.state.localVars = cx.state.context.vars
cx.state.context = cx.state.context.prev
@@ -371,7 +380,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
}
if (type == "function") return cont(functiondef);
- if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
+ if (type == "for") return cont(pushlex("form"), pushblockcontext, forspec, statement, popcontext, poplex);
if (type == "class" || (isTS && value == "interface")) {
cx.marked = "keyword"
return cont(pushlex("form", type == "class" ? type : value), className, poplex)
@@ -417,7 +426,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
function parenExpr(type) {
if (type != "(") return pass()
- return cont(pushlex(")"), expression, expect(")"), poplex)
+ return cont(pushlex(")"), maybeexpression, expect(")"), poplex)
}
function expressionInner(type, value, noComma) {
if (cx.state.fatArrowAt == cx.stream.start) {
@@ -437,7 +446,6 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
if (type == "quasi") return pass(quasi, maybeop);
if (type == "new") return cont(maybeTarget(noComma));
- if (type == "import") return cont(expression);
return cont();
}
function maybeexpression(type) {
@@ -455,7 +463,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
if (type == "operator") {
if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me);
- if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false))
+ if (isTS && value == "<" && cx.stream.match(/^([^<>]|<[^<>]*>)*>\s*\(/, false))
return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
if (value == "?") return cont(expression, expect(":"), expr);
return cont(expr);
@@ -475,7 +483,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function quasi(type, value) {
if (type != "quasi") return pass();
if (value.slice(value.length - 2) != "${") return cont(quasi);
- return cont(expression, continueQuasi);
+ return cont(maybeexpression, continueQuasi);
}
function continueQuasi(type) {
if (type == "}") {
@@ -601,7 +609,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
}
function typeexpr(type, value) {
- if (value == "keyof" || value == "typeof" || value == "infer") {
+ if (value == "keyof" || value == "typeof" || value == "infer" || value == "readonly") {
cx.marked = "keyword"
return cont(value == "typeof" ? expressionNoComma : typeexpr)
}
@@ -612,13 +620,19 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (value == "|" || value == "&") return cont(typeexpr)
if (type == "string" || type == "number" || type == "atom") return cont(afterType);
if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType)
- if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType)
+ if (type == "{") return cont(pushlex("}"), typeprops, poplex, afterType)
if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType, afterType)
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
+ if (type == "quasi") { return pass(quasiType, afterType); }
}
function maybeReturnType(type) {
if (type == "=>") return cont(typeexpr)
}
+ function typeprops(type) {
+ if (type.match(/[\}\)\]]/)) return cont()
+ if (type == "," || type == ";") return cont(typeprops)
+ return pass(typeprop, typeprops)
+ }
function typeprop(type, value) {
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property"
@@ -631,6 +645,20 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
} else if (type == "(") {
return pass(functiondecl, typeprop)
+ } else if (!type.match(/[;\}\)\],]/)) {
+ return cont()
+ }
+ }
+ function quasiType(type, value) {
+ if (type != "quasi") return pass();
+ if (value.slice(value.length - 2) != "${") return cont(quasiType);
+ return cont(typeexpr, continueQuasiType);
+ }
+ function continueQuasiType(type) {
+ if (type == "}") {
+ cx.marked = "string-2";
+ cx.state.tokenize = tokenQuasi;
+ return cont(quasiType);
}
}
function typearg(type, value) {
@@ -757,11 +785,11 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
}
if (type == "variable" || cx.style == "keyword") {
cx.marked = "property";
- return cont(isTS ? classfield : functiondef, classBody);
+ return cont(classfield, classBody);
}
- if (type == "number" || type == "string") return cont(isTS ? classfield : functiondef, classBody);
+ if (type == "number" || type == "string") return cont(classfield, classBody);
if (type == "[")
- return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody)
+ return cont(expression, maybetype, expect("]"), classfield, classBody)
if (value == "*") {
cx.marked = "keyword";
return cont(classBody);
@@ -772,6 +800,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
if (value == "@") return cont(expression, classBody)
}
function classfield(type, value) {
+ if (value == "!") return cont(classfield)
if (value == "?") return cont(classfield)
if (type == ":") return cont(typeexpr, maybeAssign)
if (value == "=") return cont(expressionNoComma)
@@ -791,6 +820,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
function afterImport(type) {
if (type == "string") return cont();
if (type == "(") return pass(expression);
+ if (type == ".") return pass(maybeoperatorComma);
return pass(importSpec, maybeMoreImports, maybeFrom);
}
function importSpec(type, value) {
@@ -864,14 +894,14 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
},
indent: function(state, textAfter) {
- if (state.tokenize == tokenComment) return CodeMirror.Pass;
+ if (state.tokenize == tokenComment || state.tokenize == tokenQuasi) return CodeMirror.Pass;
if (state.tokenize != tokenBase) return 0;
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
// Kludge to prevent 'maybelse' from blocking lexical scope pops
if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
var c = state.cc[i];
if (c == poplex) lexical = lexical.prev;
- else if (c != maybeelse) break;
+ else if (c != maybeelse && c != popcontext) break;
}
while ((lexical.type == "stat" || lexical.type == "form") &&
(firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
@@ -908,8 +938,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
expressionAllowed: expressionAllowed,
skipExpression: function(state) {
- var top = state.cc[state.cc.length - 1]
- if (top == expression || top == expressionNoComma) state.cc.pop()
+ parseJS(state, "atom", "atom", "true", new CodeMirror.StringStream("", 2, null))
}
};
});
@@ -921,9 +950,10 @@ CodeMirror.defineMIME("text/ecmascript", "javascript");
CodeMirror.defineMIME("application/javascript", "javascript");
CodeMirror.defineMIME("application/x-javascript", "javascript");
CodeMirror.defineMIME("application/ecmascript", "javascript");
-CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
-CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
-CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
+CodeMirror.defineMIME("application/json", { name: "javascript", json: true });
+CodeMirror.defineMIME("application/x-json", { name: "javascript", json: true });
+CodeMirror.defineMIME("application/manifest+json", { name: "javascript", json: true })
+CodeMirror.defineMIME("application/ld+json", { name: "javascript", jsonld: true });
CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
diff --git a/dcScript/codemirror/mode/javascript/json-ld.html b/dcScript/codemirror/mode/javascript/json-ld.html
new file mode 100644
index 0000000..d3dff2e
--- /dev/null
+++ b/dcScript/codemirror/mode/javascript/json-ld.html
@@ -0,0 +1,72 @@
+
+
+CodeMirror: JSON-LD mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+JSON-LD mode
+
+
+
+{
+ "@context": {
+ "name": "http://schema.org/name",
+ "description": "http://schema.org/description",
+ "image": {
+ "@id": "http://schema.org/image",
+ "@type": "@id"
+ },
+ "geo": "http://schema.org/geo",
+ "latitude": {
+ "@id": "http://schema.org/latitude",
+ "@type": "xsd:float"
+ },
+ "longitude": {
+ "@id": "http://schema.org/longitude",
+ "@type": "xsd:float"
+ },
+ "xsd": "http://www.w3.org/2001/XMLSchema#"
+ },
+ "name": "The Empire State Building",
+ "description": "The Empire State Building is a 102-story landmark in New York City.",
+ "image": "http://www.civil.usherbrooke.ca/cours/gci215a/empire-state-building.jpg",
+ "geo": {
+ "latitude": "40.75",
+ "longitude": "73.98"
+ }
+}
+
+
+
+
+ This is a specialization of the JavaScript mode .
+
diff --git a/dcScript/codemirror/mode/javascript/test.js b/dcScript/codemirror/mode/javascript/test.js
new file mode 100644
index 0000000..a1bcf1f
--- /dev/null
+++ b/dcScript/codemirror/mode/javascript/test.js
@@ -0,0 +1,521 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function() {
+ var mode = CodeMirror.getMode({indentUnit: 2}, "javascript");
+ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
+
+ MT("locals",
+ "[keyword function] [def foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }");
+
+ MT("comma-and-binop",
+ "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }");
+
+ MT("destructuring",
+ "([keyword function]([def a], [[[def b], [def c] ]]) {",
+ " [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);",
+ " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];",
+ "})();");
+
+ MT("destructure_trailing_comma",
+ "[keyword let] {[def a], [def b],} [operator =] [variable foo];",
+ "[keyword let] [def c];"); // Parser still in good state?
+
+ MT("class_body",
+ "[keyword class] [def Foo] {",
+ " [property constructor]() {}",
+ " [property sayName]() {",
+ " [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];",
+ " }",
+ "}");
+
+ MT("class",
+ "[keyword class] [def Point] [keyword extends] [variable SuperThing] {",
+ " [keyword get] [property prop]() { [keyword return] [number 24]; }",
+ " [property constructor]([def x], [def y]) {",
+ " [keyword super]([string 'something']);",
+ " [keyword this].[property x] [operator =] [variable-2 x];",
+ " }",
+ "}");
+
+ MT("anonymous_class_expression",
+ "[keyword const] [def Adder] [operator =] [keyword class] [keyword extends] [variable Arithmetic] {",
+ " [property add]([def a], [def b]) {}",
+ "};");
+
+ MT("named_class_expression",
+ "[keyword const] [def Subber] [operator =] [keyword class] [def Subtract] {",
+ " [property sub]([def a], [def b]) {}",
+ "};");
+
+ MT("class_async_method",
+ "[keyword class] [def Foo] {",
+ " [property sayName1]() {}",
+ " [keyword async] [property sayName2]() {}",
+ "}");
+
+ MT("import",
+ "[keyword function] [def foo]() {",
+ " [keyword import] [def $] [keyword from] [string 'jquery'];",
+ " [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];",
+ "}");
+
+ MT("import_trailing_comma",
+ "[keyword import] {[def foo], [def bar],} [keyword from] [string 'baz']")
+
+ MT("import_dynamic",
+ "[keyword import]([string 'baz']).[property then]")
+
+ MT("import_dynamic",
+ "[keyword const] [def t] [operator =] [keyword import]([string 'baz']).[property then]")
+
+ MT("const",
+ "[keyword function] [def f]() {",
+ " [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];",
+ "}");
+
+ MT("for/of",
+ "[keyword for]([keyword let] [def of] [keyword of] [variable something]) {}");
+
+ MT("for await",
+ "[keyword for] [keyword await]([keyword let] [def of] [keyword of] [variable something]) {}");
+
+ MT("generator",
+ "[keyword function*] [def repeat]([def n]) {",
+ " [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])",
+ " [keyword yield] [variable-2 i];",
+ "}");
+
+ MT("let_scoping",
+ "[keyword function] [def scoped]([def n]) {",
+ " { [keyword var] [def i]; } [variable-2 i];",
+ " { [keyword let] [def j]; [variable-2 j]; } [variable j];",
+ " [keyword if] ([atom true]) { [keyword const] [def k]; [variable-2 k]; } [variable k];",
+ "}");
+
+ MT("switch_scoping",
+ "[keyword switch] ([variable x]) {",
+ " [keyword default]:",
+ " [keyword let] [def j];",
+ " [keyword return] [variable-2 j]",
+ "}",
+ "[variable j];")
+
+ MT("leaving_scope",
+ "[keyword function] [def a]() {",
+ " {",
+ " [keyword const] [def x] [operator =] [number 1]",
+ " [keyword if] ([atom true]) {",
+ " [keyword let] [def y] [operator =] [number 2]",
+ " [keyword var] [def z] [operator =] [number 3]",
+ " [variable console].[property log]([variable-2 x], [variable-2 y], [variable-2 z])",
+ " }",
+ " [variable console].[property log]([variable-2 x], [variable y], [variable-2 z])",
+ " }",
+ " [variable console].[property log]([variable x], [variable y], [variable-2 z])",
+ "}")
+
+ MT("quotedStringAddition",
+ "[keyword let] [def f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];");
+
+ MT("quotedFatArrow",
+ "[keyword let] [def f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];");
+
+ MT("fatArrow",
+ "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);",
+ "[variable a];", // No longer in scope
+ "[keyword let] [def f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];",
+ "[variable c];");
+
+ MT("fatArrow_stringDefault",
+ "([def a], [def b] [operator =] [string 'x\\'y']) [operator =>] [variable-2 a] [operator +] [variable-2 b]")
+
+ MT("spread",
+ "[keyword function] [def f]([def a], [meta ...][def b]) {",
+ " [variable something]([variable-2 a], [meta ...][variable-2 b]);",
+ "}");
+
+ MT("quasi",
+ "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
+
+ MT("quasi_no_function",
+ "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]");
+
+ MT("indent_statement",
+ "[keyword var] [def x] [operator =] [number 10]",
+ "[variable x] [operator +=] [variable y] [operator +]",
+ " [atom Infinity]",
+ "[keyword debugger];");
+
+ MT("indent_if",
+ "[keyword if] ([number 1])",
+ " [keyword break];",
+ "[keyword else] [keyword if] ([number 2])",
+ " [keyword continue];",
+ "[keyword else]",
+ " [number 10];",
+ "[keyword if] ([number 1]) {",
+ " [keyword break];",
+ "} [keyword else] [keyword if] ([number 2]) {",
+ " [keyword continue];",
+ "} [keyword else] {",
+ " [number 10];",
+ "}");
+
+ MT("indent_for",
+ "[keyword for] ([keyword var] [def i] [operator =] [number 0];",
+ " [variable-2 i] [operator <] [number 100];",
+ " [variable-2 i][operator ++])",
+ " [variable doSomething]([variable-2 i]);",
+ "[keyword debugger];");
+
+ MT("indent_c_style",
+ "[keyword function] [def foo]()",
+ "{",
+ " [keyword debugger];",
+ "}");
+
+ MT("indent_else",
+ "[keyword for] (;;)",
+ " [keyword if] ([variable foo])",
+ " [keyword if] ([variable bar])",
+ " [number 1];",
+ " [keyword else]",
+ " [number 2];",
+ " [keyword else]",
+ " [number 3];");
+
+ MT("indent_funarg",
+ "[variable foo]([number 10000],",
+ " [keyword function]([def a]) {",
+ " [keyword debugger];",
+ "};");
+
+ MT("indent_below_if",
+ "[keyword for] (;;)",
+ " [keyword if] ([variable foo])",
+ " [number 1];",
+ "[number 2];");
+
+ MT("indent_semicolonless_if",
+ "[keyword function] [def foo]() {",
+ " [keyword if] ([variable x])",
+ " [variable foo]()",
+ "}")
+
+ MT("indent_semicolonless_if_with_statement",
+ "[keyword function] [def foo]() {",
+ " [keyword if] ([variable x])",
+ " [variable foo]()",
+ " [variable bar]()",
+ "}")
+
+ MT("multilinestring",
+ "[keyword var] [def x] [operator =] [string 'foo\\]",
+ "[string bar'];");
+
+ MT("scary_regexp",
+ "[string-2 /foo[[/]]bar/];");
+
+ MT("indent_strange_array",
+ "[keyword var] [def x] [operator =] [[",
+ " [number 1],,",
+ " [number 2],",
+ "]];",
+ "[number 10];");
+
+ MT("param_default",
+ "[keyword function] [def foo]([def x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) {",
+ " [keyword return] [variable-2 x];",
+ "}");
+
+ MT(
+ "param_destructuring",
+ "[keyword function] [def foo]([def x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) {",
+ " [keyword return] [variable-2 x];",
+ "}");
+
+ MT("new_target",
+ "[keyword function] [def F]([def target]) {",
+ " [keyword if] ([variable-2 target] [operator &&] [keyword new].[keyword target].[property name]) {",
+ " [keyword return] [keyword new]",
+ " .[keyword target];",
+ " }",
+ "}");
+
+ MT("async",
+ "[keyword async] [keyword function] [def foo]([def args]) { [keyword return] [atom true]; }");
+
+ MT("async_assignment",
+ "[keyword const] [def foo] [operator =] [keyword async] [keyword function] ([def args]) { [keyword return] [atom true]; };");
+
+ MT("async_object",
+ "[keyword let] [def obj] [operator =] { [property async]: [atom false] };");
+
+ // async be highlighted as keyword and foo as def, but it requires potentially expensive look-ahead. See #4173
+ MT("async_object_function",
+ "[keyword let] [def obj] [operator =] { [property async] [property foo]([def args]) { [keyword return] [atom true]; } };");
+
+ MT("async_object_properties",
+ "[keyword let] [def obj] [operator =] {",
+ " [property prop1]: [keyword async] [keyword function] ([def args]) { [keyword return] [atom true]; },",
+ " [property prop2]: [keyword async] [keyword function] ([def args]) { [keyword return] [atom true]; },",
+ " [property prop3]: [keyword async] [keyword function] [def prop3]([def args]) { [keyword return] [atom true]; },",
+ "};");
+
+ MT("async_arrow",
+ "[keyword const] [def foo] [operator =] [keyword async] ([def args]) [operator =>] { [keyword return] [atom true]; };");
+
+ MT("async_jquery",
+ "[variable $].[property ajax]({",
+ " [property url]: [variable url],",
+ " [property async]: [atom true],",
+ " [property method]: [string 'GET']",
+ "});");
+
+ MT("async_variable",
+ "[keyword const] [def async] [operator =] {[property a]: [number 1]};",
+ "[keyword const] [def foo] [operator =] [string-2 `bar ${][variable async].[property a][string-2 }`];")
+
+ MT("bigint", "[number 1n] [operator +] [number 0x1afn] [operator +] [number 0o064n] [operator +] [number 0b100n];")
+
+ MT("async_comment",
+ "[keyword async] [comment /**/] [keyword function] [def foo]([def args]) { [keyword return] [atom true]; }");
+
+ MT("indent_switch",
+ "[keyword switch] ([variable x]) {",
+ " [keyword default]:",
+ " [keyword return] [number 2]",
+ "}")
+
+ MT("regexp_corner_case",
+ "[operator +]{} [operator /] [atom undefined];",
+ "[[[meta ...][string-2 /\\//] ]];",
+ "[keyword void] [string-2 /\\//];",
+ "[keyword do] [string-2 /\\//]; [keyword while] ([number 0]);",
+ "[keyword if] ([number 0]) {} [keyword else] [string-2 /\\//];",
+ "[string-2 `${][variable async][operator ++][string-2 }//`];",
+ "[string-2 `${]{} [operator /] [string-2 /\\//}`];")
+
+ MT("return_eol",
+ "[keyword return]",
+ "{} [string-2 /5/]")
+
+ MT("numeric separator",
+ "[number 123_456];",
+ "[number 0xdead_c0de];",
+ "[number 0o123_456];",
+ "[number 0b1101_1101];",
+ "[number .123_456e0_1];",
+ "[number 1E+123_456];",
+ "[number 12_34_56n];")
+
+ MT("underscore property",
+ "[variable something].[property _property];",
+ "[variable something].[property _123];",
+ "[variable something].[property _for];",
+ "[variable _for];",
+ "[variable _123];")
+
+ MT("private properties",
+ "[keyword class] [def C] {",
+ " [property #x] [operator =] [number 2];",
+ " [property #read]() {",
+ " [keyword return] [keyword this].[property #x]",
+ " }",
+ "}")
+
+ var ts_mode = CodeMirror.getMode({indentUnit: 2}, "application/typescript")
+ function TS(name) {
+ test.mode(name, ts_mode, Array.prototype.slice.call(arguments, 1))
+ }
+
+ TS("typescript_extend_type",
+ "[keyword class] [def Foo] [keyword extends] [type Some][operator <][type Type][operator >] {}")
+
+ TS("typescript_arrow_type",
+ "[keyword let] [def x]: ([variable arg]: [type Type]) [operator =>] [type ReturnType]")
+
+ TS("typescript_class",
+ "[keyword class] [def Foo] {",
+ " [keyword public] [keyword static] [property main]() {}",
+ " [keyword private] [property _foo]: [type string];",
+ "}")
+
+ TS("typescript_literal_types",
+ "[keyword import] [keyword *] [keyword as] [def Sequelize] [keyword from] [string 'sequelize'];",
+ "[keyword interface] [def MyAttributes] {",
+ " [property truthy]: [string 'true'] [operator |] [number 1] [operator |] [atom true];",
+ " [property falsy]: [string 'false'] [operator |] [number 0] [operator |] [atom false];",
+ "}",
+ "[keyword interface] [def MyInstance] [keyword extends] [type Sequelize].[type Instance] [operator <] [type MyAttributes] [operator >] {",
+ " [property rawAttributes]: [type MyAttributes];",
+ " [property truthy]: [string 'true'] [operator |] [number 1] [operator |] [atom true];",
+ " [property falsy]: [string 'false'] [operator |] [number 0] [operator |] [atom false];",
+ "}")
+
+ TS("typescript_extend_operators",
+ "[keyword export] [keyword interface] [def UserModel] [keyword extends]",
+ " [type Sequelize].[type Model] [operator <] [type UserInstance], [type UserAttributes] [operator >] {",
+ " [property findById]: (",
+ " [variable userId]: [type number]",
+ " ) [operator =>] [type Promise] [operator <] [type Array] [operator <] { [property id], [property name] } [operator >>];",
+ " [property updateById]: (",
+ " [variable userId]: [type number],",
+ " [variable isActive]: [type boolean]",
+ " ) [operator =>] [type Promise] [operator <] [type AccountHolderNotificationPreferenceInstance] [operator >];",
+ " }")
+
+ TS("typescript_interface_with_const",
+ "[keyword const] [def hello]: {",
+ " [property prop1][operator ?]: [type string];",
+ " [property prop2][operator ?]: [type string];",
+ "} [operator =] {};")
+
+ TS("typescript_double_extend",
+ "[keyword export] [keyword interface] [def UserAttributes] {",
+ " [property id][operator ?]: [type number];",
+ " [property createdAt][operator ?]: [type Date];",
+ "}",
+ "[keyword export] [keyword interface] [def UserInstance] [keyword extends] [type Sequelize].[type Instance][operator <][type UserAttributes][operator >], [type UserAttributes] {",
+ " [property id]: [type number];",
+ " [property createdAt]: [type Date];",
+ "}");
+
+ TS("typescript_index_signature",
+ "[keyword interface] [def A] {",
+ " [[ [variable prop]: [type string] ]]: [type any];",
+ " [property prop1]: [type any];",
+ "}");
+
+ TS("typescript_generic_class",
+ "[keyword class] [def Foo][operator <][type T][operator >] {",
+ " [property bar]() {}",
+ " [property foo](): [type Foo] {}",
+ "}")
+
+ TS("typescript_type_when_keyword",
+ "[keyword export] [keyword type] [type AB] [operator =] [type A] [operator |] [type B];",
+ "[keyword type] [type Flags] [operator =] {",
+ " [property p1]: [type string];",
+ " [property p2]: [type boolean];",
+ "};")
+
+ TS("typescript_type_when_not_keyword",
+ "[keyword class] [def HasType] {",
+ " [property type]: [type string];",
+ " [property constructor]([def type]: [type string]) {",
+ " [keyword this].[property type] [operator =] [variable-2 type];",
+ " }",
+ " [property setType]({ [def type] }: { [property type]: [type string]; }) {",
+ " [keyword this].[property type] [operator =] [variable-2 type];",
+ " }",
+ "}")
+
+ TS("typescript_function_generics",
+ "[keyword function] [def a]() {}",
+ "[keyword function] [def b][operator <][type IA] [keyword extends] [type object], [type IB] [keyword extends] [type object][operator >]() {}",
+ "[keyword function] [def c]() {}")
+
+ TS("typescript_complex_return_type",
+ "[keyword function] [def A]() {",
+ " [keyword return] [keyword this].[property property];",
+ "}",
+ "[keyword function] [def B](): [type Promise][operator <]{ [[ [variable key]: [type string] ]]: [type any] } [operator |] [atom null][operator >] {",
+ " [keyword return] [keyword this].[property property];",
+ "}")
+
+ TS("typescript_complex_type_casting",
+ "[keyword const] [def giftpay] [operator =] [variable config].[property get]([string 'giftpay']) [keyword as] { [[ [variable platformUuid]: [type string] ]]: { [property version]: [type number]; [property apiCode]: [type string]; } };")
+
+ TS("typescript_keyof",
+ "[keyword function] [def x][operator <][type T] [keyword extends] [keyword keyof] [type X][operator >]([def a]: [type T]) {",
+ " [keyword return]")
+
+ TS("typescript_new_typeargs",
+ "[keyword let] [def x] [operator =] [keyword new] [variable Map][operator <][type string], [type Date][operator >]([string-2 `foo${][variable bar][string-2 }`])")
+
+ TS("modifiers",
+ "[keyword class] [def Foo] {",
+ " [keyword public] [keyword abstract] [property bar]() {}",
+ " [property constructor]([keyword readonly] [keyword private] [def x]) {}",
+ "}")
+
+ TS("arrow prop",
+ "({[property a]: [def p] [operator =>] [variable-2 p]})")
+
+ TS("generic in function call",
+ "[keyword this].[property a][operator <][type Type][operator >]([variable foo]);",
+ "[keyword this].[property a][operator <][variable Type][operator >][variable foo];")
+
+ TS("type guard",
+ "[keyword class] [def Appler] {",
+ " [keyword static] [property assertApple]([def fruit]: [type Fruit]): [variable-2 fruit] [keyword is] [type Apple] {",
+ " [keyword if] ([operator !]([variable-2 fruit] [keyword instanceof] [variable Apple]))",
+ " [keyword throw] [keyword new] [variable Error]();",
+ " }",
+ "}")
+
+ TS("type as variable",
+ "[variable type] [operator =] [variable x] [keyword as] [type Bar];");
+
+ TS("enum body",
+ "[keyword export] [keyword const] [keyword enum] [def CodeInspectionResultType] {",
+ " [def ERROR] [operator =] [string 'problem_type_error'],",
+ " [def WARNING] [operator =] [string 'problem_type_warning'],",
+ " [def META],",
+ "}")
+
+ TS("parenthesized type",
+ "[keyword class] [def Foo] {",
+ " [property x] [operator =] [keyword new] [variable A][operator <][type B], [type string][operator |](() [operator =>] [type void])[operator >]();",
+ " [keyword private] [property bar]();",
+ "}")
+
+ TS("abstract class",
+ "[keyword export] [keyword abstract] [keyword class] [def Foo] {}")
+
+ TS("interface without semicolons",
+ "[keyword interface] [def Foo] {",
+ " [property greet]([def x]: [type int]): [type blah]",
+ " [property bar]: [type void]",
+ "}")
+
+ var jsonld_mode = CodeMirror.getMode(
+ {indentUnit: 2},
+ {name: "javascript", jsonld: true}
+ );
+ function LD(name) {
+ test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1));
+ }
+
+ LD("json_ld_keywords",
+ '{',
+ ' [meta "@context"]: {',
+ ' [meta "@base"]: [string "http://example.com"],',
+ ' [meta "@vocab"]: [string "http://xmlns.com/foaf/0.1/"],',
+ ' [property "likesFlavor"]: {',
+ ' [meta "@container"]: [meta "@list"]',
+ ' [meta "@reverse"]: [string "@beFavoriteOf"]',
+ ' },',
+ ' [property "nick"]: { [meta "@container"]: [meta "@set"] },',
+ ' [property "nick"]: { [meta "@container"]: [meta "@index"] }',
+ ' },',
+ ' [meta "@graph"]: [[ {',
+ ' [meta "@id"]: [string "http://dbpedia.org/resource/John_Lennon"],',
+ ' [property "name"]: [string "John Lennon"],',
+ ' [property "modified"]: {',
+ ' [meta "@value"]: [string "2010-05-29T14:17:39+02:00"],',
+ ' [meta "@type"]: [string "http://www.w3.org/2001/XMLSchema#dateTime"]',
+ ' }',
+ ' } ]]',
+ '}');
+
+ LD("json_ld_fake",
+ '{',
+ ' [property "@fake"]: [string "@fake"],',
+ ' [property "@contextual"]: [string "@identifier"],',
+ ' [property "user@domain.com"]: [string "@graphical"],',
+ ' [property "@ID"]: [string "@@ID"]',
+ '}');
+})();
diff --git a/dcScript/codemirror/mode/javascript/typescript.html b/dcScript/codemirror/mode/javascript/typescript.html
new file mode 100644
index 0000000..d0bc3ae
--- /dev/null
+++ b/dcScript/codemirror/mode/javascript/typescript.html
@@ -0,0 +1,62 @@
+
+
+CodeMirror: TypeScript mode
+
+
+
+
+
+
+
+
+
+
+
+TypeScript mode
+
+
+
+class Greeter {
+ greeting: string;
+ constructor (message: string) {
+ this.greeting = message;
+ }
+ greet() {
+ return "Hello, " + this.greeting;
+ }
+}
+
+var greeter = new Greeter("world");
+
+var button = document.createElement('button')
+button.innerText = "Say Hello"
+button.onclick = function() {
+ alert(greeter.greet())
+}
+
+document.body.appendChild(button)
+
+
+
+
+
+ This is a specialization of the JavaScript mode .
+
diff --git a/dcScript/codemirror/mode/xml/index.html b/dcScript/codemirror/mode/xml/index.html
new file mode 100644
index 0000000..c0f5e84
--- /dev/null
+++ b/dcScript/codemirror/mode/xml/index.html
@@ -0,0 +1,61 @@
+
+
+CodeMirror: XML mode
+
+
+
+
+
+
+
+
+
+
+XML mode
+
+<html style="color: green">
+ <!-- this is a comment -->
+ <head>
+ <title>HTML Example</title>
+ </head>
+ <body>
+ The indentation tries to be <em>somewhat "do what
+ I mean"</em>... but might not match your style.
+ </body>
+</html>
+
+
+ The XML mode supports these configuration parameters:
+
+ htmlMode (boolean)
+ This switches the mode to parse HTML instead of XML. This
+ means attributes do not have to be quoted, and some elements
+ (such as br
) do not require a closing tag.
+ matchClosing (boolean)
+ Controls whether the mode checks that close tags match the
+ corresponding opening tag, and highlights mismatches as errors.
+ Defaults to true.
+ alignCDATA (boolean)
+ Setting this to true will force the opening tag of CDATA
+ blocks to not be indented.
+
+
+ MIME types defined: application/xml
, text/html
.
+
diff --git a/dcScript/codemirror/mode/xml/test.js b/dcScript/codemirror/mode/xml/test.js
new file mode 100644
index 0000000..ab37611
--- /dev/null
+++ b/dcScript/codemirror/mode/xml/test.js
@@ -0,0 +1,51 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function() {
+ var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml";
+ function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); }
+
+ MT("matching",
+ "[tag&bracket <][tag top][tag&bracket >]",
+ " text",
+ " [tag&bracket <][tag inner][tag&bracket />]",
+ "[tag&bracket ][tag top][tag&bracket >]");
+
+ MT("nonmatching",
+ "[tag&bracket <][tag top][tag&bracket >]",
+ " [tag&bracket <][tag inner][tag&bracket />]",
+ " [tag&bracket ][tag&error tip][tag&bracket&error >]");
+
+ MT("doctype",
+ "[meta ]",
+ "[tag&bracket <][tag top][tag&bracket />]");
+
+ MT("cdata",
+ "[tag&bracket <][tag top][tag&bracket >]",
+ " [atom ]",
+ "[tag&bracket ][tag top][tag&bracket >]");
+
+ // HTML tests
+ mode = CodeMirror.getMode({indentUnit: 2}, "text/html");
+
+ MT("selfclose",
+ "[tag&bracket <][tag html][tag&bracket >]",
+ " [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]",
+ "[tag&bracket ][tag html][tag&bracket >]");
+
+ MT("list",
+ "[tag&bracket <][tag ol][tag&bracket >]",
+ " [tag&bracket <][tag li][tag&bracket >]one",
+ " [tag&bracket <][tag li][tag&bracket >]two",
+ "[tag&bracket ][tag ol][tag&bracket >]");
+
+ MT("valueless",
+ "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]");
+
+ MT("pThenArticle",
+ "[tag&bracket <][tag p][tag&bracket >]",
+ " foo",
+ "[tag&bracket <][tag article][tag&bracket >]bar");
+
+})();
diff --git a/dcScript/codemirror/mode/xml/xml.js b/dcScript/codemirror/mode/xml/xml.js
index 73c6e0e..701e151 100644
--- a/dcScript/codemirror/mode/xml/xml.js
+++ b/dcScript/codemirror/mode/xml/xml.js
@@ -1,5 +1,5 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
-// Distributed under an MIT license: https://codemirror.net/LICENSE
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
@@ -187,9 +187,13 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
};
}
+ function lower(tagName) {
+ return tagName && tagName.toLowerCase();
+ }
+
function Context(state, tagName, startOfLine) {
this.prev = state.context;
- this.tagName = tagName;
+ this.tagName = tagName || "";
this.indent = state.indented;
this.startOfLine = startOfLine;
if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
@@ -205,8 +209,8 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
return;
}
parentTagName = state.context.tagName;
- if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
- !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
+ if (!config.contextGrabbers.hasOwnProperty(lower(parentTagName)) ||
+ !config.contextGrabbers[lower(parentTagName)].hasOwnProperty(lower(nextTagName))) {
return;
}
popContext(state);
@@ -240,7 +244,7 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
if (type == "word") {
var tagName = stream.current();
if (state.context && state.context.tagName != tagName &&
- config.implicitlyClosed.hasOwnProperty(state.context.tagName))
+ config.implicitlyClosed.hasOwnProperty(lower(state.context.tagName)))
popContext(state);
if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
setStyle = "tag";
@@ -279,7 +283,7 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
var tagName = state.tagName, tagStart = state.tagStart;
state.tagName = state.tagStart = null;
if (type == "selfcloseTag" ||
- config.autoSelfClosers.hasOwnProperty(tagName)) {
+ config.autoSelfClosers.hasOwnProperty(lower(tagName))) {
maybePopContext(state, tagName);
} else {
maybePopContext(state, tagName);
@@ -359,7 +363,7 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
if (context.tagName == tagAfter[2]) {
context = context.prev;
break;
- } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
+ } else if (config.implicitlyClosed.hasOwnProperty(lower(context.tagName))) {
context = context.prev;
} else {
break;
@@ -367,8 +371,8 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
}
} else if (tagAfter) { // Opening tag spotted
while (context) {
- var grabbers = config.contextGrabbers[context.tagName];
- if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
+ var grabbers = config.contextGrabbers[lower(context.tagName)];
+ if (grabbers && grabbers.hasOwnProperty(lower(tagAfter[2])))
context = context.prev;
else
break;
@@ -399,7 +403,7 @@ CodeMirror.defineMode("xml", function(editorConf, config_) {
xmlCurrentContext: function(state) {
var context = []
for (var cx = state.context; cx; cx = cx.prev)
- if (cx.tagName) context.push(cx.tagName)
+ context.push(cx.tagName)
return context.reverse()
}
};
diff --git a/dcScript/dcstore.xml b/dcScript/dcstore.xml
new file mode 100644
index 0000000..b517a89
--- /dev/null
+++ b/dcScript/dcstore.xml
@@ -0,0 +1,13 @@
+
+
+
+ dcScript
+ 2.3.0
+ Gvx
+ Add script for DC
+ https://github.com/Gvx-/dcScript/releases/download/v2.3.0/plugin-dcScript-2.3.0.zip
+ 2.24
+ https://github.com/Gvx-/dcScript
+ https://forum.dotclear.org/viewtopic.php?id=48714
+
+
diff --git a/dcScript/inc/class.dcPluginHelper.php b/dcScript/inc/_dcPluginHelper/class.dcPluginHelper224.php
similarity index 64%
rename from dcScript/inc/class.dcPluginHelper.php
rename to dcScript/inc/_dcPluginHelper/class.dcPluginHelper224.php
index 23895a3..06d2c50 100644
--- a/dcScript/inc/class.dcPluginHelper.php
+++ b/dcScript/inc/_dcPluginHelper/class.dcPluginHelper224.php
@@ -1,11 +1,11 @@
- * @copyright © 2008-2020 Gvx
+ * @copyright © 2008-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
@@ -13,18 +13,24 @@
if(!defined('NL')) { define('NL', "\n"); } # New Line
-
-if(!function_exists('getInstance')) { # get class instance in $core
- function getInstance($plugin) { return $GLOBALS['core']->{$plugin}; }
+if(!function_exists('getInstance')) { # get class instance in dcCore::app()
+ function getInstance($plugin) { return dcCore::app()->{$plugin}; }
}
/**
- * dcPluginHelper216
+ * dcPluginHelper224
*/
-abstract class dcPluginHelper216 {
+abstract class dcPluginHelper224 {
- /** @var string version */
- const VERSION = '216-r2020.04.25'; # class version
+ /** @var string VERSION */
+ const VERSION = '224-r2022.11.13'; # class version
+
+ /** @var string FILE_DIR_SEPARATOR */
+ const FILE_DIR_SEPARATOR = DIRECTORY_SEPARATOR;
+ /** @var string URL_DIR_SEPARATOR */
+ const URL_DIR_SEPARATOR = '/';
+ /** @var string ZIP_DIR_SEPARATOR */
+ const ZIP_DIR_SEPARATOR = '/';
/**
* setDefaultSettings
@@ -35,7 +41,7 @@ abstract class dcPluginHelper216 {
*/
protected function setDefaultSettings() {
# debug mode
- $this->debugDisplay('Not default settings for this plugin.');
+ $this->debugDisplay('Not default settings for '.$this->plugin_id.' ('.get_class($this).') plugin.');
}
/**
@@ -49,7 +55,7 @@ protected function setDefaultSettings() {
*/
protected function installActions($old_version) {
# debug mode
- $this->debugDisplay('Not install actions for this plugin.');
+ $this->debugDisplay('Not install actions for '.$this->plugin_id.' ('.get_class($this).') plugin.');
}
/**
@@ -61,7 +67,7 @@ protected function installActions($old_version) {
*/
protected function uninstallActions() {
# debug mode
- $this->debugDisplay('Not uninstall actions for this plugin.');
+ $this->debugDisplay('Not uninstall actions for '.$this->plugin_id.' ('.get_class($this).') plugin.');
return true;
}
@@ -73,25 +79,28 @@ protected function uninstallActions() {
* @return void
*/
public function _config() {
- if(!defined('DC_CONTEXT_ADMIN') || !$this->core->auth->check('admin', $this->core->blog->id)) { return; }
+ if(!defined('DC_CONTEXT_ADMIN') || !dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) { return; }
$scope = $this->configScope();
if (isset($_POST['save'])) {
try {
//$this->settings('enabled', !empty($_POST['enabled']), $scope);
- $this->core->blog->triggerBlog();
- $this->core->notices->addSuccessNotice( __('Configuration successfully updated.'));
+ dcCore::app()->blog->triggerBlog();
+ dcAdminNotices::addSuccessNotice( __('Configuration successfully updated.'));
} catch(exception $e) {
- //$this->core->error->add($e->getMessage());
- $this->core->error->add(__('Unable to save the configuration'));
+ //dcCore::app()->error->add($e->getMessage());
+ dcCore::app()->error->add(__('Unable to save the configuration'));
}
if(!empty($_GET['redir']) && strpos($_GET['redir'], 'p='.$this->info('id')) === false) {
- $this->core->error->add(__('Redirection not found'));
- $this->core->adminurl->redirect('admin.home');
+ dcCore::app()->error->add(__('Redirection not found'));
+ dcCore::app()->adminurl->redirect('admin.home');
}
http::redirect($_REQUEST['redir']);
}
+
+ // TODO: HERE display
+
# debug mode
- $this->debugDisplay('Not config page for this plugin.');
+ $this->debugDisplay('Not config page for '.$this->plugin_id.' ('.get_class($this).') plugin.');
}
/**
@@ -104,25 +113,29 @@ public function _config() {
public function index() {
if(!defined('DC_CONTEXT_ADMIN')) { return; }
if(!$this->settings('enabled') && is_file(path::real($this->info('root').'/_config.php'))) {
- if($this->core->auth->check('admin', $this->core->blog->id)) {
- $this->core->adminurl->redirect('admin.plugins', array(
- 'module' => $this->info('id'),'conf' => 1, 'redir' => $this->core->adminurl->get($this->info('adminUrl'))
+ if(dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) {
+ dcCore::app()->adminurl->redirect('admin.plugins', array(
+ 'module' => $this->info('id'),'conf' => 1, 'redir' => dcCore::app()->adminurl->get($this->info('adminUrl'))
));
} else {
- $this->core->notices->addNotice('message', sprintf(__('%s plugin is not configured.'), $this->info('name')));
- $this->core->adminurl->redirect('admin.home');
+ dcAdminNotices::addMessageNotice(sprintf(__('%s plugin is not configured.'), $this->info('name')));
+ dcCore::app()->adminurl->redirect('admin.home');
}
}
try {
if (isset($_POST['save'])) {
- // TODO HERE inputs check
+ // TODO: HERE inputs check
}
+ /** @phpstan-ignore-next-line */
} catch(exception $e) {
- //$this->core->error->add($e->getMessage());
- $this->core->error->add(__('Unable to save the code'));
+ //dcCore::app()->error->add($e->getMessage());
+ dcCore::app()->error->add(__('Unable to save the code'));
}
+
+ // TODO: HERE display
+
# debug mode
- $this->debugDisplay('Not index page for this plugin.');
+ $this->debugDisplay('Not index page for '.$this->plugin_id.' ('.get_class($this).') plugin.');
}
/**
@@ -133,7 +146,6 @@ public function index() {
* @return void
*/
protected function _prepend() {
- global $__autoload;
# common (public & admin)
if(defined('DC_CONTEXT_ADMIN')) {
@@ -145,6 +157,8 @@ protected function _prepend() {
# public only
}
+ # debug mode
+ $this->debugDisplay('Not _prepend actions for '.$this->plugin_id.' ('.get_class($this).') plugin.');
}
/**
@@ -158,7 +172,7 @@ public function _admin() {
if(!defined('DC_CONTEXT_ADMIN')) { return; }
# debug mode
- $this->debugDisplay('Not _admin actions for this plugin.');
+ $this->debugDisplay('Not _admin actions for '.$this->plugin_id.' ('.get_class($this).') plugin.');
}
/**
@@ -170,20 +184,8 @@ public function _admin() {
*/
public function _public() {
- }
-
- /**
- * _xmlrpc
- *
- * @todo overloaded
- *
- * @return void
- */
- public function _xmlrpc() {
- if(!defined('DC_CONTEXT_ADMIN')) { return; }
-
# debug mode
- $this->debugDisplay('Not _xmlrpc actions for this plugin.');
+ $this->debugDisplay('Not _public page for '.$this->plugin_id.' ('.get_class($this).') plugin.');
}
/**
@@ -195,11 +197,10 @@ public function _xmlrpc() {
* @return void
*/
public function resources($path) {
- global $__resources;
/*
- if(!isset($__resources['help']['dcScript-config'])) { $__resources['help']['dcScript-config'] = $path.'/help/config.html'; }
- if(!isset($__resources['help']['dcScript-edit'])) { $__resources['help']['dcScript-edit'] = $path.'/help/edit.html'; }
- if(!isset($__resources['help']['dcScript-warning'])) { $__resources['help']['dcScript-warning'] = $path.'/help/warning.html'; }
+ if(!isset(dcCore::app()->resources['help']['dcScript-config'])) { dcCore::app()->resources['help']['dcScript-config'] = $path.'/help/config.html'; }
+ if(!isset(dcCore::app()->resources['help']['dcScript-edit'])) { dcCore::app()->resources['help']['dcScript-edit'] = $path.'/help/edit.html'; }
+ if(!isset(dcCore::app()->resources['help']['dcScript-warning'])) { dcCore::app()->resources['help']['dcScript-warning'] = $path.'/help/warning.html'; }
*/
# debug mode
@@ -212,7 +213,6 @@ public function resources($path) {
protected $admin_url; # admin url plugin
protected $icon_small; # small icon file
protected $icon_large; # large icon file
- protected $core; # dcCore instance
private $debug_mode = false; # debug mode for plugin
private $debug_log = false; # debug Log for plugin
@@ -222,13 +222,11 @@ public function resources($path) {
/**
* __construct
*
- * @param object $core
* @param string $id
*
* @return void
*/
- public function __construct($core, $id) {
- $this->core =& $core;
+ public function __construct($id) {
# set plugin id and admin url
$this->plugin_id = $id;
@@ -240,20 +238,20 @@ public function __construct($core, $id) {
# start logfile
$this->debugLog('START_DEBUG');
- $this->debugLog('Version', $this->core->getVersion($this->plugin_id));
+ $this->debugLog('Version', dcCore::app()->getVersion($this->plugin_id));
$this->debugLog('Helper version', self::VERSION);
$this->debugLog('Page', $_SERVER['REQUEST_URI']);
# Set admin context
if(defined('DC_CONTEXT_ADMIN')) {
# register self url
- $urls = $this->core->adminurl->dumpUrls();
- if(!array_key_exists('admin.self', $urls)) {
+ $urls = dcCore::app()->adminurl->dumpUrls();
+ if(!$urls->offsetExists('admin.self')) {
$url = http::getSelfURI();
$url = str_replace('?'.parse_url($url, PHP_URL_QUERY), '', $url); // delete query
- $url = substr($url, 1 + strrpos($url, '/')); // keep page name
+ $url = substr($url, 1 + strrpos($url, self::URL_DIR_SEPARATOR)); // keep page name
if(in_array($url, array_column((array)$urls, 'url'))) { // Register checked
- $this->core->adminurl->register('admin.self', $url, (empty($_GET) ? array(): $_GET));
+ dcCore::app()->adminurl->register('admin.self', $url, ($_GET ?: array()));
}
}
@@ -262,7 +260,7 @@ public function __construct($core, $id) {
$this->icon_large = $this->plugin_id.$this->info('_icon_large');
# uninstall plugin procedure
- if($this->core->auth->isSuperAdmin()) { $this->core->addBehavior('pluginBeforeDelete', array($this, 'uninstall')); }
+ if(dcCore::app()->auth->isSuperAdmin()) { dcCore::app()->addBehavior('pluginBeforeDelete', array($this, 'uninstall')); }
}
# set default settings if empty
@@ -283,30 +281,30 @@ public function __destruct() {
# end logfile
$this->debugLog('END_DEBUG');
}
-
+
### Admin functions ###
/**
* _install
*
- * @return void
+ * @return Boolean
*/
public final function _install() {
- if(!defined('DC_CONTEXT_ADMIN')) { return; }
+ if(!defined('DC_CONTEXT_ADMIN')) { return; } /** @phpstan-ignore-line */
try {
# check plugin versions
$new_version = $this->info('version');
- $old_version = $this->core->getVersion($this->plugin_id);
- if (version_compare($old_version, $new_version, '>=')) { return; }
+ $old_version = dcCore::app()->getVersion($this->plugin_id);
+ if (version_compare($old_version, $new_version, '>=')) { return; } /** @phpstan-ignore-line */
# specifics install actions
$this->installActions($old_version);
# valid install
- $this->core->setVersion($this->plugin_id, $new_version);
+ dcCore::app()->setVersion($this->plugin_id, $new_version);
$this->debugLog('Update', 'version '.$new_version);
return true;
} catch (Exception $e) {
$this->debugDisplay('[Install] : '.$e->getMessage());
- $this->core->error->add($e->getMessage());
+ dcCore::app()->error->add($e->getMessage());
}
return false;
}
@@ -316,21 +314,21 @@ public final function _install() {
*
* @param object $plugin
*
- * @return void
+ * @return void
*/
public final function uninstall($plugin) {
- $this->debugLog('uninstall', 'version '.$this->core->getVersion($this->plugin_id));
+ $this->debugLog('uninstall', 'version '.dcCore::app()->getVersion($this->plugin_id));
# specifics uninstall actions
if($plugin['id'] == $this->plugin_id) {
if($this->uninstallActions()) {
# clean DC_VAR
if(self::getVarDir($this->plugin_id)) { files::deltree(self::getVarDir($this->plugin_id)); }
# delete all users prefs
- $this->core->auth->user_prefs->delWorkSpace($this->plugin_id);
+ dcCore::app()->auth->user_prefs->delWorkSpace($this->plugin_id);
# delete all blogs settings
- $this->core->blog->settings->delNamespace($this->plugin_id);
+ dcCore::app()->blog->settings->delNamespace($this->plugin_id);
# delete version
- $this->core->delVersion($this->plugin_id);
+ dcCore::app()->delVersion($this->plugin_id);
}
}
}
@@ -341,7 +339,7 @@ public final function uninstall($plugin) {
* @return string
*/
protected final function configScope() {
- return (isset($_POST['scope']) ? $_POST['scope'] : ($this->core->auth->isSuperAdmin() ? 'global' : 'default'));
+ return (isset($_POST['scope']) ? $_POST['scope'] : (dcCore::app()->auth->isSuperAdmin() ? 'global' : 'default'));
}
/**
@@ -354,11 +352,12 @@ protected final function configScope() {
*/
protected function configBaseline($scope=null, $activate=true) {
$html = '';
- if($this->core->auth->isSuperAdmin()) {
+ if(dcCore::app()->auth->isSuperAdmin()) {
if(empty($scope)) { $scope = $this->configScope(); }
- $html .= '
+ $html .= '
+
'.__('Scope').' :
- '.form::combo('scope', array(__('Global settings') => 'global', sprintf(__('Settings for %s'), html::escapeHTML($this->core->blog->name)) => 'default'), 'default').'
+ '.form::combo('scope', array(__('Global settings') => 'global', sprintf(__('Settings for %s'), html::escapeHTML(dcCore::app()->blog->name)) => 'default'), 'default').'
'.__('Select the blog in which parameters apply').'
@@ -386,44 +385,43 @@ protected function configBaseline($scope=null, $activate=true) {
*
* @param string $menu
*
- * @return void
+ * @return object $this
*/
- public function adminMenu($menu='Plugins') {
- if(!defined('DC_CONTEXT_ADMIN')) { return; }
- global $_menu;
- if(array_key_exists($menu, $_menu)) {
- $_menu[$menu]->addItem(
+ public function adminMenu($menu=dcAdmin::MENU_PLUGINS) {
+ if(!defined('DC_CONTEXT_ADMIN')) { return; } /** @phpstan-ignore-line */
+ if(dcCore::app()->menu->offsetExists($menu)) {
+ dcCore::app()->menu[$menu]->addItem(
html::escapeHTML(__($this->info('name'))), # Item menu
- $this->core->adminurl->get($this->admin_url), # Page admin url
+ dcCore::app()->adminurl->get($this->admin_url), # Page admin url
dcPage::getPF($this->icon_small), # Icon menu
preg_match( # Pattern url
- '/'.$this->core->adminurl->get($this->admin_url).'(&.*)?$/',
+ self::URL_DIR_SEPARATOR.dcCore::app()->adminurl->get($this->admin_url).'(&.*)?$/',
$_SERVER['REQUEST_URI']
),
- $this->core->auth->check($this->info('permissions'), $this->core->blog->id) # Permissions minimum
+ dcCore::app()->auth->check($this->info('permissions'), dcCore::app()->blog->id) # Permissions minimum
);
} else {
$this->debugDisplay('menu not present.');
- throw new ErrorException(sprinf(__('%s menu not present.'), $menu), 0, E_USER_NOTICE, __FILE__, __LINE__);
+ throw new ErrorException(sprintf(__('%s menu not present.'), $menu), 0, E_USER_NOTICE, __FILE__, __LINE__);
}
+ return $this;
}
/**
- * adminDashboardFavs
+ * adminDashboardFavsV2
*
- * @param object $core
* @param object $favs
*
- * @return void
+ * @return void
*/
- public function adminDashboardFavs($core, $favs) {
+ public function adminDashboardFavsV2($favs) {
if(!defined('DC_CONTEXT_ADMIN')) { return; }
$favs->register($this->plugin_id, array(
- 'title' => $core->plugins->moduleInfo($this->plugin_id, 'name'),
- 'url' => $core->adminurl->get($this->admin_url),
+ 'title' => dcCore::app()->plugins->moduleInfo($this->plugin_id, 'name'),
+ 'url' => dcCore::app()->adminurl->get($this->admin_url),
'small-icon' => dcPage::getPF($this->icon_small),
'large-icon' => dcPage::getPF($this->icon_large),
- 'permissions' => $core->plugins->moduleInfo($this->plugin_id, 'permissions')
+ 'permissions' => dcCore::app()->plugins->moduleInfo($this->plugin_id, 'permissions')
));
}
@@ -436,7 +434,7 @@ public function adminDashboardFavs($core, $favs) {
*/
protected function adminBaseline($items=array()) {
if(empty($items)) { $items = array( $this->info('name') => ''); }
- return dcPage::breadcrumb(array_merge(array(html::escapeHTML($this->core->blog->name) => ''), $items)).$this->core->notices->getNotices()."\n";
+ return dcPage::breadcrumb(array_merge(array(html::escapeHTML(dcCore::app()->blog->name) => ''), $items)).dcAdminNotices::getNotices().NL;
}
/**
@@ -445,7 +443,7 @@ protected function adminBaseline($items=array()) {
* @return string
*/
public function adminFooterInfo() {
- if(!defined('DC_CONTEXT_ADMIN')) { return; }
+ if(!defined('DC_CONTEXT_ADMIN')) { return; } /** @phpstan-ignore-line */
$support = $this->info('support');
$details = $this->info('details');
return '
@@ -495,7 +493,7 @@ protected static function widgetFooter(&$w, $context=true, $class='') {
* @param object $w
* @param string $id
* @param string $name
- * @param callback $callback
+ * @param callable $callback
* @param mixed $help
* @param string $title
*
@@ -518,9 +516,8 @@ protected static function widgetAddBasic(&$w, $id, $name, $callback, $help, $tit
* @return string
*/
protected static function widgetRender($w, $content, $class='', $attr='') {
- global $core;
- if (($w->homeonly == 1 && $core->url->type != 'default') || ($w->homeonly == 2 && $core->url->type == 'default') || $w->offline || empty($content)) {
- return;
+ if (($w->homeonly == 1 && dcCore::app()->url->type != 'default') || ($w->homeonly == 2 && dcCore::app()->url->type == 'default') || $w->offline || empty($content)) {
+ return; /** @phpstan-ignore-line */
}
$content = ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '').$content;
return $w->renderDiv($w->content_only, trim(trim($class).' '.$w->class), trim($attr), $content);
@@ -533,7 +530,7 @@ protected static function widgetRender($w, $content, $class='', $attr='') {
*
* @param string $key
* @param mixed $value
- * @param string $scope
+ * @param mixed $scope
*
* @return mixed
*/
@@ -541,15 +538,15 @@ public final function settings($key, $value=null, $scope='default') {
if(is_null($value)) {
try {
if($scope == 'global' || $scope === true) {
- $value = $this->core->blog->settings->{$this->plugin_id}->getGlobal($key);
+ $value = dcCore::app()->blog->settings->{$this->plugin_id}->getGlobal($key);
$v = json_decode($value, true);
return is_array($v) ? $v : $value;
} elseif($scope == 'local') {
- $value = $this->core->blog->settings->{$this->plugin_id}->getLocal($key);
+ $value = dcCore::app()->blog->settings->{$this->plugin_id}->getLocal($key);
$v = json_decode($value, true);
return is_array($v) ? $v : $value;
}
- $value = $this->core->blog->settings->{$this->plugin_id}->$key;
+ $value = dcCore::app()->blog->settings->{$this->plugin_id}->$key;
$v = json_decode($value, true);
return is_array($v) ? $v : $value;
} catch(Exception $e) {
@@ -557,14 +554,14 @@ public final function settings($key, $value=null, $scope='default') {
return null;
}
} else {
+ $global = ($scope == 'global' || $scope === true);
try {
if(is_array($value) || is_object($value)) { $value = json_encode($value); }
- $global = ($scope == 'global' || $scope === true);
- $this->core->blog->settings->{$this->plugin_id}->put($key, $value, null, null, true, $global);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put($key, $value, null, null, true, $global);
} catch(Exception $e) {
$this->debugDisplay('Blog settings write error (namespace not exist).('.$key.')');
- $this->core->blog->settings->addNamespace($this->plugin_id);
- $this->core->blog->settings->{$this->plugin_id}->put($key, $value, null, null, true, $global);
+ dcCore::app()->blog->settings->addNamespace($this->plugin_id);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put($key, $value, null, null, true, $global);
}
}
}
@@ -574,7 +571,7 @@ public final function settings($key, $value=null, $scope='default') {
*
* @param string $key
* @param mixed $value
- * @param string $scope
+ * @param mixed $scope
*
* @return mixed
*/
@@ -582,15 +579,15 @@ public final function userSettings($key, $value=null, $scope='default') {
if(is_null($value)) {
try {
if($scope == 'global' || $scope === true) {
- $value = $this->core->auth->user_prefs->{$this->plugin_id}->getGlobal($key);
+ $value = dcCore::app()->auth->user_prefs->{$this->plugin_id}->getGlobal($key);
$v = json_decode($value, true);
return is_array($v) ? $v : $value;
} elseif($scope == 'local') {
- $value = $this->core->auth->user_prefs->{$this->plugin_id}->getLocal($key);
+ $value = dcCore::app()->auth->user_prefs->{$this->plugin_id}->getLocal($key);
$v = json_decode($value, true);
return is_array($v) ? $v : $value;
}
- $value = $this->core->auth->user_prefs->{$this->plugin_id}->$key;
+ $value = dcCore::app()->auth->user_prefs->{$this->plugin_id}->$key;
$v = json_decode($value, true);
return is_array($v) ? $v : $value;
} catch(Exception $e) {
@@ -598,14 +595,14 @@ public final function userSettings($key, $value=null, $scope='default') {
return null;
}
} else {
+ $global = ($scope == 'global' || $scope === true);
try {
if(is_array($value) || is_object($value)) { $value = json_encode($value); }
- $global = ($scope == 'global' || $scope === true);
- $this->core->auth->user_prefs->{$this->plugin_id}->put($key,$value, null, null, true, $global);
+ dcCore::app()->auth->user_prefs->{$this->plugin_id}->put($key,$value, null, null, true, $global);
} catch(Exception $e) {
$this->debugDisplay('User settings write error (namespace not exist).('.$key.')');
- $this->core->auth->user_prefs->addWorkSpace($this->plugin_id);
- $this->core->auth->user_prefs->{$this->plugin_id}->put($key,$value, null, null, true, $global);
+ dcCore::app()->auth->user_prefs->addWorkSpace($this->plugin_id);
+ dcCore::app()->auth->user_prefs->{$this->plugin_id}->put($key,$value, null, null, true, $global);
}
}
}
@@ -615,12 +612,13 @@ public final function userSettings($key, $value=null, $scope='default') {
*
* @param mixed $key
*
- * @return void
+ * @return object $this
*/
protected final function settingDrop($key) {
- $s = new dcNamespace($this->core, null, $this->plugin_id);
+ $s = new dcNamespace(dcCore::app(), null, $this->plugin_id); /** @phpstan-ignore-line */
$s->drop($key);
unset($s);
+ return $this;
}
/**
@@ -628,12 +626,14 @@ protected final function settingDrop($key) {
*
* @param mixed $key
*
- * @return void
+ * @return object $this
*/
protected final function userSettingDrop($key) {
- $s = new dcWorkspace($this->core, $this->core->auth->userID(), $this->plugin_id);
+ //$s = new dcWorkspace(dcCore::app(), dcCore::app()->auth->userID(), $this->plugin_id);
+ $s = new dcWorkspace(dcCore::app()->auth->userID(), $this->plugin_id);
$s->drop($key);
unset($s);
+ return $this;
}
/**
@@ -652,7 +652,7 @@ public final function info($item=null, $default=null) {
} elseif($item == 'helperVersion') {
return self::VERSION;
} else {
- $res = $this->core->plugins->moduleInfo($this->plugin_id, $item);
+ $res = dcCore::app()->plugins->moduleInfo($this->plugin_id, $item);
return $res === null ? $default : $res;
}
}
@@ -660,7 +660,7 @@ public final function info($item=null, $default=null) {
/**
* nextStep
*
- * @param string $step
+ * @param mixed $step
* @param integer $delay
*
* @return void
@@ -671,8 +671,8 @@ public function nextStep($step, $delay=0) {
if($delay > 0 && ($timeout - $delay) < time()) { return; } # if timeout > next task delay
if($delay < 0 && ($timeout + $delay) > time()) { return; } # if timeout - delay < now
- # --BEHAVIOR-- beforeNextStep
- if($this->core->callBehavior('beforeNextStep', $this->core, $this->plugin_id, $step) === false) { return; }
+ # --BEHAVIOR-- beforeNextStepV2
+ if(dcCore::app()->callBehavior('beforeNextStepV2', $this->plugin_id, $step) === false) { return; }
if(is_array($step)) {
foreach($step as $k => $v) { $_GET[$k] = $v; }
@@ -690,16 +690,16 @@ public function nextStep($step, $delay=0) {
* @param string $dir
* @param boolean $create
*
- * @return string
+ * @return mixed
*/
public static function getVarDir($dir='', $create=false) {
$dir = trim($dir, '\\/');
- $var_dir = path::real(DC_VAR.(empty($dir) ? '' : '/'.$dir), false);
- if(strpos($var_dir, path::real(DC_VAR, false)) === false) { $GLOBALS['core']->error->add(__('The folder is not in the var directory')); }
+ $var_dir = path::real(DC_VAR.(empty($dir) ? '' : self::FILE_DIR_SEPARATOR.$dir), false);
+ if(strpos($var_dir, path::real(DC_VAR, false)) === false) { dcCore::app()->error->add(__('The folder is not in the var directory')); }
if(!is_dir($var_dir)) {
if(!$create) { return false; }
@files::makeDir($var_dir, true);
- if(!is_dir($var_dir)) { $GLOBALS['core']->error->add(__('Creating a var directory failed')); }
+ if(!is_dir($var_dir)) { dcCore::app()->error->add(__('Creating a var directory failed')); }
}
return $var_dir;
}
@@ -715,7 +715,7 @@ public final function getVF($file) {
if(defined('DC_CONTEXT_ADMIN')) {
return dcPage::getVF($file);
} else {
- return $this->core->blog->getVF($file);
+ return dcCore::app()->blog->getVF($file);
}
}
@@ -727,15 +727,16 @@ public final function getVF($file) {
* @return string
*/
public final function jsLoad($src) {
- if(is_file($this->info('root').'/'.ltrim($src, '/'))) {
- $file = $this->plugin_id.'/'.ltrim($src, '/');
+ if(is_file($this->info('root').self::FILE_DIR_SEPARATOR.ltrim($src, self::FILE_DIR_SEPARATOR))) {
+ $file = $this->plugin_id.self::URL_DIR_SEPARATOR.ltrim($src, self::URL_DIR_SEPARATOR);
$version = $this->info('version');
if(defined('DC_CONTEXT_ADMIN')) {
return dcPage::jsLoad(dcPage::getPF($file), $version);
} else {
- return dcUtils::jsLoad($this->core->blog->getPF($file), $version);
+ return dcUtils::jsLoad(dcCore::app()->blog->getPF($file), $version);
}
}
+ return '';
}
/**
@@ -748,8 +749,8 @@ public final function jsLoad($src) {
* @return string
*/
public final function cssLoad($src, $media='all', $import=false) {
- if(is_file($this->info('root').'/'.ltrim($src, '/'))) {
- $file = $this->plugin_id.'/'.ltrim($src, '/');
+ if(is_file($this->info('root').self::FILE_DIR_SEPARATOR.ltrim($src, self::FILE_DIR_SEPARATOR))) {
+ $file = $this->plugin_id.self::URL_DIR_SEPARATOR.ltrim($src, self::URL_DIR_SEPARATOR);
$version = $this->info('version');
if(defined('DC_CONTEXT_ADMIN')) {
if($import) {
@@ -759,12 +760,13 @@ public final function cssLoad($src, $media='all', $import=false) {
}
} else {
if($import) {
- return ''.NL;
+ return ''.NL;
} else {
- return dcUtils::cssLoad($this->core->blog->getPF($file), $media, $version);
+ return dcUtils::cssLoad(dcCore::app()->blog->getPF($file), $media, $version);
}
}
}
+ return '';
}
/**
@@ -791,13 +793,14 @@ public final function jsJson($vars) {
*
* @param string $msg
*
- * @return void
+ * @return object $this
*/
protected final function debugDisplay($msg) {
if($this->debug_mode && !empty($msg)) {
- if(defined('DC_CONTEXT_ADMIN')) { $this->core->notices->addWarningNotice('DEBUG - '.$this->plugin_id.' : '.$msg); }
+ if(defined('DC_CONTEXT_ADMIN')) { dcAdminNotices::addWarningNotice('DEBUG - '.$this->plugin_id.' : '.$msg); }
$this->debugLog('[Debug display]', $msg);
}
+ return $this;
}
/**
@@ -806,7 +809,7 @@ protected final function debugDisplay($msg) {
* @param string $text
* @param mixed $value
*
- * @return void
+ * @return object $this
*/
public final function debugLog($text, $value=null) {
if($this->debug_log && !empty($text)) {
@@ -831,8 +834,9 @@ public final function debugLog($text, $value=null) {
} else {
$text .= ' :'.NL.print_r($value, true).NL.str_pad('END_VALUE', 66, '*');
}
- @file_put_contents ($this->debug_logfile, NL.'['.date('YmdHis').'-'.$this->plugin_id.'-'.$this->core->blog->id.'] '.$text, FILE_APPEND);
+ @file_put_contents ($this->debug_logfile, NL.'['.date('YmdHis').'-'.$this->plugin_id.'-'.dcCore::app()->blog->id.'] '.$text, FILE_APPEND);
}
+ return $this;
}
/**
@@ -841,7 +845,7 @@ public final function debugLog($text, $value=null) {
* @param mixed $filename
* @param boolean $reset_file
*
- * @return void
+ * @return object $this
*/
public final function setDebugFilename($filename=null, $reset_file=false) {
if(empty($filename)) { $filename = self::getVarDir('logs', true).'/log_'.$this->plugin_id.'.txt'; }
@@ -849,7 +853,7 @@ public final function setDebugFilename($filename=null, $reset_file=false) {
if(is_dir(dirname($filename))) {
$this->debug_logfile = $filename;
} else {
- $this->debug_logfile = self::getVarDir('logs', true).'/'.basename($filename);
+ $this->debug_logfile = self::getVarDir('logs', true).self::FILE_DIR_SEPARATOR.basename($filename);
}
if($this->debug_log) {
if($this->debug_log_reset && $reset_file && is_file($this->debug_logfile)) {
@@ -858,6 +862,7 @@ public final function setDebugFilename($filename=null, $reset_file=false) {
@file_put_contents ($this->debug_logfile, NL, FILE_APPEND);
}
}
+ return $this;
}
}
diff --git a/dcScript/inc/class.dcScript.php b/dcScript/inc/class.dcScript.php
index a76a640..1564dda 100644
--- a/dcScript/inc/class.dcScript.php
+++ b/dcScript/inc/class.dcScript.php
@@ -5,21 +5,21 @@
* @package Dotclear\plungin\dcScript
*
* @author Gvx
- * @copyright © 2014-2020 Gvx
+ * @copyright © 2014-2022 Gvx
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
if(!defined('DC_RC_PATH')) { return; }
-if(!isset($__autoload['dcPluginHelper216'])) { $__autoload['dcPluginHelper216'] = dirname(__FILE__).'/class.dcPluginHelper.php'; }
+if(Clearbricks::lib()->autoloadSource('dcPluginHelper224') == false) { Clearbricks::lib()->autoload(['dcPluginHelper224' => __DIR__ . '/_dcPluginHelper/class.dcPluginHelper224.php']); }
define('DECRYPTION_PAGE', 'http://promenade.temporelle.free.fr/tools/decrypt.php');
__('dcScript'); // plugin name
__('Add script for DC'); // description plugin
-//class dcScript extends dcPluginHelper024b {
-class dcScript extends dcPluginHelper216 {
+//class dcScript extends dcPluginHelper224 {
+class dcScript extends dcPluginHelper224 {
### Constants ###
const MCRYPT = 'mcrypt';
@@ -34,9 +34,9 @@ class dcScript extends dcPluginHelper216 {
* @return void
*/
public static function publicHeadContent($core, $_ctx) {
- if(version_compare(PHP_VERSION, '7.2', '>=') && ($core->dcScript->settings('crypt_lib') != self::OPENSSL)) { return; }
- $html = self::decrypt($core->dcScript->settings('header_code'), $core->dcScript->getCryptKey(), $core->dcScript->settings('crypt_lib'));
- if($core->dcScript->settings('enabled') && $core->dcScript->settings('header_code_enabled') && !empty($html)) {
+ if(dcCore::app()->dcScript->settings('crypt_lib') != self::OPENSSL) { return; }
+ $html = self::decrypt(dcCore::app()->dcScript->settings('header_code'), dcCore::app()->dcScript->getCryptKey(), dcCore::app()->dcScript->settings('crypt_lib'));
+ if(dcCore::app()->dcScript->settings('enabled') && dcCore::app()->dcScript->settings('header_code_enabled') && !empty($html)) {
echo "\n".$html."\n\n";
}
}
@@ -49,9 +49,9 @@ public static function publicHeadContent($core, $_ctx) {
* @return void
*/
public static function publicFooterContent($core, $_ctx) {
- if(version_compare(PHP_VERSION, '7.2', '>=') && ($core->dcScript->settings('crypt_lib') != self::OPENSSL)) { return; }
- $html = self::decrypt($core->dcScript->settings('footer_code'), $core->dcScript->getCryptKey(), $core->dcScript->settings('crypt_lib'));
- if($core->dcScript->settings('enabled') && $core->dcScript->settings('footer_code_enabled') && !empty($html)) {
+ if(dcCore::app()->dcScript->settings('crypt_lib') != self::OPENSSL) { return; }
+ $html = self::decrypt(dcCore::app()->dcScript->settings('footer_code'), dcCore::app()->dcScript->getCryptKey(), dcCore::app()->dcScript->settings('crypt_lib'));
+ if(dcCore::app()->dcScript->settings('enabled') && dcCore::app()->dcScript->settings('footer_code_enabled') && !empty($html)) {
echo "\n".$html."\n\n";
}
}
@@ -67,16 +67,12 @@ public static function publicFooterContent($core, $_ctx) {
public static function encrypt($str, $key, $cryptLib=self::OPENSSL) {
global $core;
$key = pack('H*', hash('sha256', $key));
- if($cryptLib == self::MCRYPT) { // REMOVED in PHP 7.2
- if(version_compare(PHP_VERSION, '7.2', '>=')) { throw new Exception(__('Encryption incompatible with PHP 7.2 and more')); }
- $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
- return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $str, MCRYPT_MODE_ECB, $iv)));
- } elseif($cryptLib == self::OPENSSL) {
+ if($cryptLib == self::OPENSSL) {
$ivlen = openssl_cipher_iv_length(self::OPENSSL_METHOD);
$iv = openssl_random_pseudo_bytes($ivlen);
return trim(base64_encode($iv.openssl_encrypt($str, self::OPENSSL_METHOD, $key, OPENSSL_RAW_DATA, $iv)));
} else { // unknown cryptLib
- return self::encrypt($str, $key, $core->dcScript->getCryptLib());
+ return self::encrypt($str, $key, dcCore::app()->dcScript->getCryptLib());
}
}
@@ -88,19 +84,15 @@ public static function encrypt($str, $key, $cryptLib=self::OPENSSL) {
* @param string $cryptLib
* @return string
*/
- public static function decrypt($str, $key, $cryptLib=self::MCRYPT) {
+ public static function decrypt($str, $key, $cryptLib=self::OPENSSL) {
global $core;
$key = pack('H*', hash('sha256', $key));
- if($cryptLib == self::MCRYPT) { // REMOVED in PHP 7.2
- if(version_compare(PHP_VERSION, '7.2', '>=')) { throw new Exception(__('Encryption incompatible with PHP 7.2 and more')); }
- $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND);
- return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($str), MCRYPT_MODE_ECB, $iv));
- } elseif($cryptLib == self::OPENSSL) {
+ if($cryptLib == self::OPENSSL) {
$ivlen = openssl_cipher_iv_length(self::OPENSSL_METHOD);
$str = base64_decode($str);
return trim(openssl_decrypt(substr($str, $ivlen), self::OPENSSL_METHOD, $key, OPENSSL_RAW_DATA, substr($str, 0, $ivlen)));
} else { // unknown cryptLib
- return self::decrypt($str, $key, $core->dcScript->getCryptLib());
+ return self::decrypt($str, $key, dcCore::app()->dcScript->getCryptLib());
}
}
@@ -121,7 +113,7 @@ public function getCryptKey($salt=DC_MASTER_KEY) {
*/
Public function getCryptLib() {
$lib = $this->settings('crypt_lib');
- return (empty($lib) ? (version_compare(PHP_VERSION, '7.2', '>=')? self::OPENSSL : self::MCRYPT) : $lib);
+ return (empty($lib) ? self::OPENSSL : $lib);
}
Public function debugGetinfos() {
@@ -135,14 +127,14 @@ public function getCryptKey($salt=DC_MASTER_KEY) {
protected function setDefaultSettings() {
# create config plugin
- $this->core->blog->settings->addNamespace($this->plugin_id);
- $this->core->blog->settings->{$this->plugin_id}->put('enabled', false, 'boolean', __('Enable plugin'), false, true);
- $this->core->blog->settings->{$this->plugin_id}->put('header_code_enabled', false, 'boolean', __('Enable header code'), false, true);
- $this->core->blog->settings->{$this->plugin_id}->put('footer_code_enabled', false, 'boolean', __('Enable footer code'), false, true);
- $this->core->blog->settings->{$this->plugin_id}->put('header_code', self::encrypt('', $this->getCryptKey()), 'string', __('Header code'), false, true);
- $this->core->blog->settings->{$this->plugin_id}->put('footer_code', self::encrypt('', $this->getCryptKey()), 'string', __('Footer code'), false, true);
- $this->core->blog->settings->{$this->plugin_id}->put('backup_ext', '.html.txt', 'string', __('Extension Backup Files'), false, true);
- $this->core->blog->settings->{$this->plugin_id}->put('crypt_lib', self::OPENSSL, 'string', __('Encryption library'), false, true); // add v2.1.0
+ dcCore::app()->blog->settings->addNamespace($this->plugin_id);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('enabled', false, 'boolean', __('Enable plugin'), false, true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('header_code_enabled', false, 'boolean', __('Enable header code'), false, true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('footer_code_enabled', false, 'boolean', __('Enable footer code'), false, true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('header_code', self::encrypt('', $this->getCryptKey()), 'string', __('Header code'), false, true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('footer_code', self::encrypt('', $this->getCryptKey()), 'string', __('Footer code'), false, true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('backup_ext', '.html.txt', 'string', __('Extension Backup Files'), false, true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('crypt_lib', self::OPENSSL, 'string', __('Encryption library'), false, true); // add v2.1.0
}
protected function installActions($old_version) {
@@ -152,12 +144,12 @@ protected function installActions($old_version) {
# version < 2
if(version_compare($old_version, '2', '<')) { // /!\ timeout possible for a lot of blogs
# upgrade global settings
- $this->core->blog->settings->{$this->plugin_id}->dropAll(true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->dropAll(true);
$this->setDefaultSettings();
# upgrade all blogs settings
- $rs = $this->core->getBlogs();
+ $rs = dcCore::app()->getBlogs();
while ($rs->fetch()) {
- $settings = new dcSettings($this->core, $rs->blog_id);
+ $settings = new dcSettings($rs->blog_id);
$settings->addNamespace($this->plugin_id);
$settings->{$this->plugin_id}->put('enabled', $settings->{$this->plugin_id}->get('enabled'));
$settings->{$this->plugin_id}->put('header_code_enabled', $settings->{$this->plugin_id}->get('header_code_enabled'));
@@ -167,15 +159,15 @@ protected function installActions($old_version) {
$settings->{$this->plugin_id}->put('backup_ext', $settings->{$this->plugin_id}->get('backup_ext'));
unset($settings);
}
- dcPage::addWarningNotice(__('Default settings update.'));
+ dcAdminNotices::addWarningNotice(__('Default settings update.'));
}
# version < 2.0.0-r0143
if(version_compare($old_version, '2.0.0-r0143', '<')) { // /!\ timeout possible for a lot of blogs
# upgrade all blogs settings
- $rs = $this->core->getBlogs();
+ $rs = dcCore::app()->getBlogs();
while ($rs->fetch()) {
- $settings = new dcSettings($this->core, $rs->blog_id);
+ $settings = new dcSettings($rs->blog_id);
$settings->addNamespace($this->plugin_id);
$settings->{$this->plugin_id}->put('header_code', self::encrypt(self::decrypt($settings->{$this->plugin_id}->get('header_code'), DC_MASTER_KEY), $this->getCryptKey()));
$settings->{$this->plugin_id}->put('footer_code', self::encrypt(self::decrypt($settings->{$this->plugin_id}->get('footer_code'), DC_MASTER_KEY), $this->getCryptKey()));
@@ -185,11 +177,11 @@ protected function installActions($old_version) {
# version < 2.1.1-dev-r0001
if(version_compare($old_version, '2.1.1-dev-r0001', '<')) { // /!\ timeout possible for a lot of blogs
- $this->core->blog->settings->{$this->plugin_id}->put('crypt_lib', self::OPENSSL, 'string', __('Encryption library'), false, true);
+ dcCore::app()->blog->settings->{$this->plugin_id}->put('crypt_lib', self::OPENSSL, 'string', __('Encryption library'), false, true);
# upgrade all blogs settings
- $rs = $this->core->getBlogs();
+ $rs = dcCore::app()->getBlogs();
while ($rs->fetch()) {
- $settings = new dcSettings($this->core, $rs->blog_id);
+ $settings = new dcSettings($rs->blog_id);
$settings->addNamespace($this->plugin_id);
if(version_compare(PHP_VERSION, '7.2', '<')) {
$settings->{$this->plugin_id}->put('header_code', self::encrypt(self::decrypt($settings->{$this->plugin_id}->get('header_code'), $this->getCryptKey()), $this->getCryptKey(),self::OPENSSL));
@@ -206,49 +198,49 @@ protected function installActions($old_version) {
public function index() {
if(!defined('DC_CONTEXT_ADMIN')) { return; }
- dcPage::check('dcScript.edit');
+ dcPage::check(dcCore::app()->auth->makePermissions([dcScriptPerms::EDIT]));
if(!$this->settings('enabled') && is_file(path::real($this->info('root').'/_config.php'))) {
- if($this->core->auth->check('admin', $this->core->blog->id)) {
- $this->core->adminurl->redirect('admin.plugins', array(
- 'module' => $this->info('id'),'conf' => 1, 'redir' => $this->core->adminurl->get($this->info('adminUrl'))
+ if(dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id)) {
+ dcCore::app()->adminurl->redirect('admin.plugins', array(
+ 'module' => $this->info('id'),'conf' => 1, 'redir' => dcCore::app()->adminurl->get($this->info('adminUrl'))
));
} else {
- $this->core->notices->addNotice('message', sprintf(__('%s plugin is not configured.'), $this->info('name')));
- $this->core->adminurl->redirect('admin.home');
+ dcAdminNotices::addMessageNotice(sprintf(__('%s plugin is not configured.'), $this->info('name')));
+ dcCore::app()->adminurl->redirect('admin.home');
}
}
if (!empty($_POST)) {
try {
# submit later (warning page)
if (isset($_POST['later'])) {
- $this->core->adminurl->redirect('admin.home');
+ dcCore::app()->adminurl->redirect('admin.home');
}
# submit convert (warning page)
if (isset($_POST['convert'])) {
$this->settings('header_code', dcScript::encrypt(trim($_POST['header_code']), $this->getCryptKey(), dcScript::OPENSSL));
$this->settings('footer_code', dcScript::encrypt(trim($_POST['footer_code']), $this->getCryptKey(), dcScript::OPENSSL));
$this->settings('crypt_lib', dcScript::OPENSSL);
- $this->core->blog->triggerBlog();
- dcPage::addSuccessNotice(__('Code successfully updated.'));
- $this->core->adminurl->redirect($this->info('adminUrl'), array(), '#tab-1');
+ dcCore::app()->blog->triggerBlog();
+ dcAdminNotices::addSuccessNotice(__('Code successfully updated.'));
+ dcCore::app()->adminurl->redirect($this->info('adminUrl'), array(), '#tab-1');
}
# submit tab 1 (standard page)
if (isset($_POST['update_header'])) {
$this->settings('header_code', dcScript::encrypt(trim($_POST['header_code'])."\n", $this->getCryptKey(), dcScript::OPENSSL));
- $this->core->blog->triggerBlog();
- dcPage::addSuccessNotice(__('Code successfully updated.'));
- $this->core->adminurl->redirect($this->info('adminUrl'), array(), '#tab-1');
+ dcCore::app()->blog->triggerBlog();
+ dcAdminNotices::addSuccessNotice(__('Code successfully updated.'));
+ dcCore::app()->adminurl->redirect($this->info('adminUrl'), array(), '#tab-1');
}
# submit tab 2 (standard page)
if (isset($_POST['update_footer'])) {
$this->settings('footer_code', dcScript::encrypt(trim($_POST['footer_code'])."\n", $this->getCryptKey(), dcScript::OPENSSL));
- $this->core->blog->triggerBlog();
- dcPage::addSuccessNotice(__('Code successfully updated.'));
- $this->core->adminurl->redirect($this->info('adminUrl'), array(), '#tab-2');
+ dcCore::app()->blog->triggerBlog();
+ dcAdminNotices::addSuccessNotice(__('Code successfully updated.'));
+ dcCore::app()->adminurl->redirect($this->info('adminUrl'), array(), '#tab-2');
}
} catch(exception $e) {
- //$this->core->error->add($e->getMessage());
- $this->core->error->add(__('Unable to save the code'));
+ //dcCore::app()->error->add($e->getMessage());
+ dcCore::app()->error->add(__('Unable to save the code'));
}
}
@@ -256,79 +248,23 @@ public function index() {
try {
# download code (standard page)
if(isset($_GET['download']) && in_array($_GET['download'], array('header', 'footer'), true)) {
- $filename = '"'.trim($this->core->blog->name).'_'.date('Y-m-d').'_'.$_GET['download'].'.'.trim($this->settings('backup_ext'),'.').'"';
+ $filename = '"'.trim(dcCore::app()->blog->name).'_'.date('Y-m-d').'_'.$_GET['download'].'.'.trim($this->settings('backup_ext'),'.').'"';
header('Content-Disposition: attachment;filename='.$filename);
header('Content-Type: text/plain; charset=UTF-8');
echo dcScript::decrypt($this->settings($_GET['download'].'_code'), $this->getCryptKey(), $this->getCryptLib());
exit;
}
} catch(exception $e) {
- //$this->core->error->add($e->getMessage());
- $this->core->error->add(__('Unable to save the file'));
+ //dcCore::app()->error->add($e->getMessage());
+ dcCore::app()->error->add(__('Unable to save the file'));
}
}
- if(version_compare(PHP_VERSION, '7.2', '>=') && ($this->settings('crypt_lib') != dcScript::OPENSSL)) {
- $this->indexWarning();
- } else {
- $this->indexStandard();
- }
- }
-
- private function indexWarning() {
- echo ''.NL;
- echo ''.NL;
- echo ''.html::escapeHTML($this->info('name')).' '.NL;
- echo $this->cssLoad('/inc/css/index.css');
- echo $this->jsLoad('/inc/js/index_warning.js');
- dcPage::addNotice('message', __('See help for the procedure'));
- echo ''.NL;
-
- echo ''.NL;
- // Baseline
- echo $this->adminBaseline();
- // datas
- echo ''.NL;
- echo '
'.hash('sha256', $this->getCryptKey()).'
'.NL;
- echo ''.NL;
- echo ''.NL;
- echo '
'.NL;
- // admin forms
- echo ''.NL;
- echo '
'.__('Convert fields to new encryption format').' '.NL;
- echo '
'.NL;
- echo ''.__('Copy key').' '.NL;
- echo ''.NL;
- echo ''.NL;
- echo ''.__('Decryption page').' '.NL;
- echo '
'.NL;
- echo
- '
- '.$this->core->formNonce().'
- '.__('Header code').'
- '.form::textArea('header_code',120,9,'','maximal',0,false,'placeholder="'.__('Paste the code here').'"').'
- '.__('Footer code').'
- '.form::textArea('footer_code',120,9,'','maximal',0,false,'placeholder="'.__('Paste the code here').'"').'
-
-
-
-
- '.NL;
- echo '
'.NL;
- // Footer plugin
- echo $this->adminFooterInfo();
- // helpBlock
- dcPage::helpBlock('dcScript-warning');
- echo NL.''.NL;
- echo ''.NL;
- }
-
- private function indexStandard() {
$header = html::escapeHTML(dcScript::decrypt($this->settings('header_code'), $this->getCryptKey(), $this->getCryptLib()));
$footer = html::escapeHTML(dcScript::decrypt($this->settings('footer_code'), $this->getCryptKey(), $this->getCryptLib()));
- $formAction = html::escapeHTML($this->core->adminurl->get($this->info('adminUrl')));
- $downloadHeader = $this->core->adminurl->get($this->info('adminUrl'), array('download' => 'header'));
- $downloadFooter = $this->core->adminurl->get($this->info('adminUrl'), array('download' => 'footer'));
+ $formAction = html::escapeHTML(dcCore::app()->adminurl->get($this->info('adminUrl')));
+ $downloadHeader = dcCore::app()->adminurl->get($this->info('adminUrl'), array('download' => 'header'));
+ $downloadFooter = dcCore::app()->adminurl->get($this->info('adminUrl'), array('download' => 'footer'));
echo ''.NL;
echo ''.NL;
@@ -370,9 +306,9 @@ private function indexStandard() {
echo
'