editeur blocks avif etc
|
@ -1,5 +1,11 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Version 4.4.02 de Deltacms
|
||||||
|
- Modifications :
|
||||||
|
|
||||||
|
- Corrections :
|
||||||
|
- gestion des utilisateurs : description des droits éditeur et modérateur
|
||||||
|
|
||||||
## Version 4.4.01 de Deltacms
|
## Version 4.4.01 de Deltacms
|
||||||
- Modifications :
|
- Modifications :
|
||||||
- Ajout du groupe éditeur, autorisations limitées à l'édition des pages, l'ajout de fichiers, l'accès aux pages privées membre et éditeur,
|
- Ajout du groupe éditeur, autorisations limitées à l'édition des pages, l'ajout de fichiers, l'accès aux pages privées membre et éditeur,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
# DeltaCMS 4.4.01
|
# DeltaCMS 4.4.02
|
||||||
|
|
||||||
DeltaCMS est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation.
|
DeltaCMS est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation.
|
||||||
L'administration du site est bilingue anglais ou français, le site peut être rédigé dans une des principales langues européennes.
|
L'administration du site est bilingue anglais ou français, le site peut être rédigé dans une des principales langues européennes.
|
||||||
|
|
|
@ -49,7 +49,7 @@ class common {
|
||||||
|
|
||||||
// Numéro de version
|
// Numéro de version
|
||||||
const DELTA_UPDATE_URL = 'https://update.deltacms.fr/master/';
|
const DELTA_UPDATE_URL = 'https://update.deltacms.fr/master/';
|
||||||
const DELTA_VERSION = '4.4.01';
|
const DELTA_VERSION = '4.4.02';
|
||||||
const DELTA_UPDATE_CHANNEL = "v4";
|
const DELTA_UPDATE_CHANNEL = "v4";
|
||||||
|
|
||||||
public static $actions = [];
|
public static $actions = [];
|
||||||
|
@ -2391,13 +2391,13 @@ class core extends common {
|
||||||
$css .= '.helpButton span:hover{color:' . $colors['darken'] . '}';
|
$css .= '.helpButton span:hover{color:' . $colors['darken'] . '}';
|
||||||
$css .= '.button:active,button[type=\'submit\']:active,.pagination a:active{background-color:' . $colors['veryDarken'] . '}';
|
$css .= '.button:active,button[type=\'submit\']:active,.pagination a:active{background-color:' . $colors['veryDarken'] . '}';
|
||||||
$colors = helper::colorVariants($this->getData(['theme', 'title', 'textColor']));
|
$colors = helper::colorVariants($this->getData(['theme', 'title', 'textColor']));
|
||||||
$css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:' . $colors['normal'] . ';font-family:"' . $this->getData(['fonts', $this->getData(['theme', 'title', 'font']), 'name']) . '",sans-serif;font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}';
|
$css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a,.block .blockTitle{color:' . $colors['normal'] . ';font-family:"' . $this->getData(['fonts', $this->getData(['theme', 'title', 'font']), 'name']) . '",sans-serif;font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}';
|
||||||
$css .= 'h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color:' . $colors['darken'] . '}';
|
$css .= 'h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color:' . $colors['darken'] . '}';
|
||||||
// Les blocs
|
// Les blocs
|
||||||
$colors = helper::colorVariants($this->getData(['theme', 'block', 'backgroundTitleColor']));
|
$colors = helper::colorVariants($this->getData(['theme', 'block', 'backgroundTitleColor']));
|
||||||
$css .= '.block {border: 1px solid ' . $this->getdata(['theme','block','borderColor']) . ';background-color: ' . $this->getdata(['theme','block','backgroundColor']) .';border-radius: ' . $this->getdata(['theme','block','blockBorderRadius']) . ';box-shadow :' . $this->getdata(['theme','block','blockBorderShadow']) . ' ' . $this->getdata(['theme','block','borderColor']) . ';}';
|
$css .= '.block {border: 1px solid ' . $this->getdata(['theme','block','borderColor']) . ';background-color: ' . $this->getdata(['theme','block','backgroundColor']) .';border-radius: ' . $this->getdata(['theme','block','blockBorderRadius']) . ';box-shadow :' . $this->getdata(['theme','block','blockBorderShadow']) . ' ' . $this->getdata(['theme','block','borderColor']) . ';}';
|
||||||
$css .= '.block h4 {background-color:'. $colors['normal'] . ';color:' . $colors['text'] .';border-radius: ' . $this->getdata(['theme','block','blockBorderRadius']) . ' ' . $this->getdata(['theme','block','blockBorderRadius']) . ' 0px 0px;}';
|
$css .= '.block > h4, .block .blockTitle {background-color:'. $colors['normal'] . ';color:' . $colors['text'] .';border-radius: ' . $this->getdata(['theme','block','blockBorderRadius']) . ' ' . $this->getdata(['theme','block','blockBorderRadius']) . ' 0px 0px;}';
|
||||||
$css .= '.block p {margin: 0px -5px;}';
|
$css .= '.block > p {margin: 0px -5px;}';
|
||||||
//$css .= '.mce-tinymce {border: 1px solid ' . $this->getdata(['theme','block','borderColor']) .' !important;}';
|
//$css .= '.mce-tinymce {border: 1px solid ' . $this->getdata(['theme','block','borderColor']) .' !important;}';
|
||||||
|
|
||||||
//Tinymce option titre sous une image valeurs par défaut modifiables dans custom.css
|
//Tinymce option titre sous une image valeurs par défaut modifiables dans custom.css
|
||||||
|
@ -2531,6 +2531,7 @@ class core extends common {
|
||||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
header("Cache-Control: post-check=0, pre-check=0", false);
|
||||||
header("Pragma: no-cache");
|
header("Pragma: no-cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check la mise à jour du theme admin
|
// Check la mise à jour du theme admin
|
||||||
if( $this-> getData(['admin', 'maj']) === true){
|
if( $this-> getData(['admin', 'maj']) === true){
|
||||||
// Version
|
// Version
|
||||||
|
@ -2571,7 +2572,7 @@ class core extends common {
|
||||||
$colors = helper::colorVariants($this->getData(['admin','backgroundColor']));
|
$colors = helper::colorVariants($this->getData(['admin','backgroundColor']));
|
||||||
$css .= '#site{background-color:' . $colors['normal']. ';}';
|
$css .= '#site{background-color:' . $colors['normal']. ';}';
|
||||||
$css .= '.row > div {font:' . $this->getData(['admin','fontSize']) . ' "' . $this->getData(['fonts', $this->getData(['admin', 'fontText']), 'name']) . '", sans-serif;}';
|
$css .= '.row > div {font:' . $this->getData(['admin','fontSize']) . ' "' . $this->getData(['fonts', $this->getData(['admin', 'fontText']), 'name']) . '", sans-serif;}';
|
||||||
$css .= 'body h1, h2, h3, .block h4, h5, h6 {font-family:' . $this->getData(['fonts', $this->getData(['admin', 'fontTitle']), 'name']) . ', sans-serif;color:' . $this->getData(['admin','colorTitle' ]) . ';}';
|
$css .= 'body h1, h2, h3, .block > h4, .block .blockTitle, h5, h6 {font-family:' . $this->getData(['fonts', $this->getData(['admin', 'fontTitle']), 'name']) . ', sans-serif;color:' . $this->getData(['admin','colorTitle' ]) . ';}';
|
||||||
|
|
||||||
// TinyMCE
|
// TinyMCE
|
||||||
$css .= 'body:not(.editorWysiwyg),span .zwiico-help {color:' . $this->getData(['admin','colorText']) . ';}';
|
$css .= 'body:not(.editorWysiwyg),span .zwiico-help {color:' . $this->getData(['admin','colorText']) . ';}';
|
||||||
|
@ -2589,9 +2590,9 @@ class core extends common {
|
||||||
$colors = helper::colorVariants($this->getData(['admin','backgroundColorButtonGreen']));
|
$colors = helper::colorVariants($this->getData(['admin','backgroundColorButtonGreen']));
|
||||||
$css .= '.button.buttonGreen, button[type=submit] {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:hover, button[type=submit]:hover {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] .';}.button.buttonGreen:active, button[type=submit]:active {background-color: ' . $colors['darken'] . ';color: ' .$colors['text'] .';}';
|
$css .= '.button.buttonGreen, button[type=submit] {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:hover, button[type=submit]:hover {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] .';}.button.buttonGreen:active, button[type=submit]:active {background-color: ' . $colors['darken'] . ';color: ' .$colors['text'] .';}';
|
||||||
$colors = helper::colorVariants($this->getData(['admin','backgroundBlockColor']));
|
$colors = helper::colorVariants($this->getData(['admin','backgroundBlockColor']));
|
||||||
$css .= '.block {border: 1px solid ' . $this->getData(['admin','borderBlockColor']) . ';}.block h4 {background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
|
$css .= '.block {border: 1px solid ' . $this->getData(['admin','borderBlockColor']) . ';}.block > h4, .block .blockTitle {background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
|
||||||
// en admin la couleur de fond du block est la couleur de la page admin, on supprime l'ombre et le radius du block définis pour le theme
|
// en admin la couleur de fond du block est la couleur de la page admin, on supprime l'ombre et le radius du block définis pour le theme
|
||||||
$css .= '.block {border-radius: 0px;box-shadow: none;}.block h4 {border-radius: 0px;}';
|
$css .= '.block {border-radius: 0px;box-shadow: none;}.block > h4, .block .blockTitle {border-radius: 0px;}';
|
||||||
$css .= '.block {background-color: ' . $this->getData(['admin','backgroundColor']) . ';}';
|
$css .= '.block {background-color: ' . $this->getData(['admin','backgroundColor']) . ';}';
|
||||||
$css .= 'table tr,input[type=email],input[type=text],input[type=password],select:not(#barSelectPage),textarea:not(.editorWysiwyg),.inputFile{background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';border: 1px solid ' . $this->getData(['admin','borderBlockColor']) . ';}';
|
$css .= 'table tr,input[type=email],input[type=text],input[type=password],select:not(#barSelectPage),textarea:not(.editorWysiwyg),.inputFile{background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';border: 1px solid ' . $this->getData(['admin','borderBlockColor']) . ';}';
|
||||||
// Bordure du contour TinyMCE
|
// Bordure du contour TinyMCE
|
||||||
|
|
|
@ -90,4 +90,9 @@ if ($this->getData(['core', 'dataVersion']) < 4401) {
|
||||||
// Mise à jour
|
// Mise à jour
|
||||||
$this->setData(['core', 'dataVersion', 4401]);
|
$this->setData(['core', 'dataVersion', 4401]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->getData(['core', 'dataVersion']) < 4402) {
|
||||||
|
// Mise à jour
|
||||||
|
$this->setData(['core', 'dataVersion', 4402]);
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -1050,7 +1050,6 @@ footer #footerSocials .zwiico-github:hover {
|
||||||
|
|
||||||
/* Bloc */
|
/* Bloc */
|
||||||
.block {
|
.block {
|
||||||
/* border: 1px solid #D8DFE3;*/
|
|
||||||
padding: 20px 20px 10px;
|
padding: 20px 20px 10px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
|
@ -1065,15 +1064,13 @@ footer #footerSocials .zwiico-github:hover {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block h4 {
|
.block > h4, .block .blockTitle {
|
||||||
margin: -20px -20px 10px -20px;
|
margin: -20px -20px 10px -20px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
/* background: #ECEFF1;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.block h4 .openClose {
|
.blockTitle > h1, .blockTitle > h2, .blockTitle > h3, .blockTitle > h4 ,.blockTitle > h5, .blockTitle > p {
|
||||||
display: inline-flex;
|
margin: 0 -5px;
|
||||||
float: right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Aides */
|
/* Aides */
|
||||||
|
|
|
@ -68,7 +68,7 @@ class init extends common {
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
'core' => [
|
'core' => [
|
||||||
'dataVersion' => 4401,
|
'dataVersion' => 4402,
|
||||||
'lastBackup' => 0,
|
'lastBackup' => 0,
|
||||||
'lastClearTmp' => 0,
|
'lastClearTmp' => 0,
|
||||||
'lastAutoUpdate' => 0,
|
'lastAutoUpdate' => 0,
|
||||||
|
|
|
@ -25,7 +25,7 @@ include('./core/module/install/lang/'. $this->getData(['config', 'i18n', 'langAd
|
||||||
<div class="col3 verticalAlignMiddle">
|
<div class="col3 verticalAlignMiddle">
|
||||||
<?php echo template::button('installUpdateEnd', [
|
<?php echo template::button('installUpdateEnd', [
|
||||||
'value' => $text['core_install_view']['update'][9],
|
'value' => $text['core_install_view']['update'][9],
|
||||||
'href' => helper::baseUrl() . 'config',
|
'href' => helper::baseUrl(false) . 'index.php',
|
||||||
'ico' => 'check',
|
'ico' => 'check',
|
||||||
'class' => 'disabled'
|
'class' => 'disabled'
|
||||||
]); ?>
|
]); ?>
|
||||||
|
|
|
@ -45,7 +45,7 @@ $text['core_user_view']['edit'][8] = 'File sharing allowed';
|
||||||
$text['core_user_view']['edit'][9] = 'This member will be able to upload or download files to the \'partage\' folder and its subfolders';
|
$text['core_user_view']['edit'][9] = 'This member will be able to upload or download files to the \'partage\' folder and its subfolders';
|
||||||
$text['core_user_view']['edit'][10] = 'Authorisations :';
|
$text['core_user_view']['edit'][10] = 'Authorisations :';
|
||||||
$text['core_user_view']['edit'][11] = 'Access to private member pages';
|
$text['core_user_view']['edit'][11] = 'Access to private member pages';
|
||||||
$text['core_user_view']['edit'][12] = 'Access to members\' and editors\' private pages';
|
$text['core_user_view']['edit'][12] = 'Access to private member to moderator pages';
|
||||||
$text['core_user_view']['edit'][13] = 'General information';
|
$text['core_user_view']['edit'][13] = 'General information';
|
||||||
$text['core_user_view']['edit'][14] = 'Add / Edit / Delete pages';
|
$text['core_user_view']['edit'][14] = 'Add / Edit / Delete pages';
|
||||||
$text['core_user_view']['edit'][15] = 'Add / Edit / Delete files';
|
$text['core_user_view']['edit'][15] = 'Add / Edit / Delete files';
|
||||||
|
@ -66,6 +66,9 @@ $text['core_user_view']['edit'][29] = 'Register';
|
||||||
$text['core_user_view']['edit'][30] = 'You cannot change your own group.';
|
$text['core_user_view']['edit'][30] = 'You cannot change your own group.';
|
||||||
$text['core_user_view']['edit'][31] = 'The username is defined when the account is created and cannot be changed.';
|
$text['core_user_view']['edit'][31] = 'The username is defined when the account is created and cannot be changed.';
|
||||||
$text['core_user_view']['edit'][32] = 'New password';
|
$text['core_user_view']['edit'][32] = 'New password';
|
||||||
|
$text['core_user_view']['edit'][33] = 'Edit pages';
|
||||||
|
$text['core_user_view']['edit'][34] = 'Add files';
|
||||||
|
$text['core_user_view']['edit'][35] = 'Access to private members\' and editors\' pages';
|
||||||
$text['core_user_view']['forgot'][0] = 'Identifier';
|
$text['core_user_view']['forgot'][0] = 'Identifier';
|
||||||
$text['core_user_view']['forgot'][1] = 'Back';
|
$text['core_user_view']['forgot'][1] = 'Back';
|
||||||
$text['core_user_view']['forgot'][2] = 'Validate';
|
$text['core_user_view']['forgot'][2] = 'Validate';
|
||||||
|
|
|
@ -45,7 +45,7 @@ $text['core_user_view']['edit'][8] = 'Partage de fichiers autorisé';
|
||||||
$text['core_user_view']['edit'][9] = 'Ce membre pourra téléverser ou télécharger des fichiers dans le dossier \'partage\' et ses sous-dossiers';
|
$text['core_user_view']['edit'][9] = 'Ce membre pourra téléverser ou télécharger des fichiers dans le dossier \'partage\' et ses sous-dossiers';
|
||||||
$text['core_user_view']['edit'][10] = 'Autorisations :';
|
$text['core_user_view']['edit'][10] = 'Autorisations :';
|
||||||
$text['core_user_view']['edit'][11] = 'Accès aux pages privées membres';
|
$text['core_user_view']['edit'][11] = 'Accès aux pages privées membres';
|
||||||
$text['core_user_view']['edit'][12] = 'Accès aux pages privées membres et éditeurs';
|
$text['core_user_view']['edit'][12] = 'Accès aux pages privées membres à modérateurs';
|
||||||
$text['core_user_view']['edit'][13] = 'Informations générales';
|
$text['core_user_view']['edit'][13] = 'Informations générales';
|
||||||
$text['core_user_view']['edit'][14] = 'Ajout / Édition / Suppression de pages';
|
$text['core_user_view']['edit'][14] = 'Ajout / Édition / Suppression de pages';
|
||||||
$text['core_user_view']['edit'][15] = 'Ajout / Édition / Suppression de fichiers';
|
$text['core_user_view']['edit'][15] = 'Ajout / Édition / Suppression de fichiers';
|
||||||
|
@ -66,6 +66,9 @@ $text['core_user_view']['edit'][29] = 'Enregistrer';
|
||||||
$text['core_user_view']['edit'][30] = 'Impossible de modifier votre propre groupe.';
|
$text['core_user_view']['edit'][30] = 'Impossible de modifier votre propre groupe.';
|
||||||
$text['core_user_view']['edit'][31] = 'L\'identifiant est défini lors de la création du compte, il ne peut pas être modifié.';
|
$text['core_user_view']['edit'][31] = 'L\'identifiant est défini lors de la création du compte, il ne peut pas être modifié.';
|
||||||
$text['core_user_view']['edit'][32] = 'Nouveau mot de passe';
|
$text['core_user_view']['edit'][32] = 'Nouveau mot de passe';
|
||||||
|
$text['core_user_view']['edit'][33] = 'Édition de pages';
|
||||||
|
$text['core_user_view']['edit'][34] = 'Ajout de fichiers';
|
||||||
|
$text['core_user_view']['edit'][35] = 'Accès aux pages privées membres et éditeurs';
|
||||||
$text['core_user_view']['forgot'][0] = 'Identifiant';
|
$text['core_user_view']['forgot'][0] = 'Identifiant';
|
||||||
$text['core_user_view']['forgot'][1] = 'Retour';
|
$text['core_user_view']['forgot'][1] = 'Retour';
|
||||||
$text['core_user_view']['forgot'][2] = 'Valider';
|
$text['core_user_view']['forgot'][2] = 'Valider';
|
||||||
|
|
|
@ -79,6 +79,11 @@ include('./core/module/user/lang/'. $this->getData(['config', 'i18n', 'langAdmin
|
||||||
<ul id="userEditGroupDescription<?php echo self::GROUP_MEMBER; ?>" class="userEditGroupDescription displayNone">
|
<ul id="userEditGroupDescription<?php echo self::GROUP_MEMBER; ?>" class="userEditGroupDescription displayNone">
|
||||||
<li><?php echo $text['core_user_view']['edit'][11]; ?></li>
|
<li><?php echo $text['core_user_view']['edit'][11]; ?></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<ul id="userEditGroupDescription<?php echo self::GROUP_EDITOR; ?>" class="userEditGroupDescription displayNone">
|
||||||
|
<li><?php echo $text['core_user_view']['edit'][33]; ?></li>
|
||||||
|
<li><?php echo $text['core_user_view']['edit'][34]; ?></li>
|
||||||
|
<li><?php echo $text['core_user_view']['edit'][35]; ?></li>
|
||||||
|
</ul>
|
||||||
<ul id="userEditGroupDescription<?php echo self::GROUP_MODERATOR; ?>" class="userEditGroupDescription displayNone">
|
<ul id="userEditGroupDescription<?php echo self::GROUP_MODERATOR; ?>" class="userEditGroupDescription displayNone">
|
||||||
<li><?php echo $text['core_user_view']['edit'][12]; ?></li>
|
<li><?php echo $text['core_user_view']['edit'][12]; ?></li>
|
||||||
<li><?php echo $text['core_user_view']['edit'][14]; ?></li>
|
<li><?php echo $text['core_user_view']['edit'][14]; ?></li>
|
||||||
|
|
|
@ -0,0 +1,349 @@
|
||||||
|
/* BASICS */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
/* Set height, width, borders, and global font properties here */
|
||||||
|
font-family: monospace;
|
||||||
|
height: 300px;
|
||||||
|
color: black;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PADDING */
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
padding: 4px 0; /* Vertical padding around content */
|
||||||
|
}
|
||||||
|
.CodeMirror pre.CodeMirror-line,
|
||||||
|
.CodeMirror pre.CodeMirror-line-like {
|
||||||
|
padding: 0 4px; /* Horizontal padding of content */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
background-color: white; /* The little square between H and V scrollbars */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GUTTER */
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.CodeMirror-linenumbers {}
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
padding: 0 3px 0 5px;
|
||||||
|
min-width: 20px;
|
||||||
|
text-align: right;
|
||||||
|
color: #999;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-guttermarker { color: black; }
|
||||||
|
.CodeMirror-guttermarker-subtle { color: #999; }
|
||||||
|
|
||||||
|
/* CURSOR */
|
||||||
|
|
||||||
|
.CodeMirror-cursor {
|
||||||
|
border-left: 1px solid black;
|
||||||
|
border-right: none;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
/* Shown when moving in bi-directional text */
|
||||||
|
.CodeMirror div.CodeMirror-secondarycursor {
|
||||||
|
border-left: 1px solid silver;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor .CodeMirror-cursor {
|
||||||
|
width: auto;
|
||||||
|
border: 0 !important;
|
||||||
|
background: #7e7;
|
||||||
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
@-moz-keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
@keyframes blink {
|
||||||
|
0% {}
|
||||||
|
50% { background-color: transparent; }
|
||||||
|
100% {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can style cursor different in overwrite (non-insert) mode */
|
||||||
|
.CodeMirror-overwrite .CodeMirror-cursor {}
|
||||||
|
|
||||||
|
.cm-tab { display: inline-block; text-decoration: inherit; }
|
||||||
|
|
||||||
|
.CodeMirror-rulers {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; right: 0; top: -50px; bottom: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.CodeMirror-ruler {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
top: 0; bottom: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEFAULT THEME */
|
||||||
|
|
||||||
|
.cm-s-default .cm-header {color: blue;}
|
||||||
|
.cm-s-default .cm-quote {color: #090;}
|
||||||
|
.cm-negative {color: #d44;}
|
||||||
|
.cm-positive {color: #292;}
|
||||||
|
.cm-header, .cm-strong {font-weight: bold;}
|
||||||
|
.cm-em {font-style: italic;}
|
||||||
|
.cm-link {text-decoration: underline;}
|
||||||
|
.cm-strikethrough {text-decoration: line-through;}
|
||||||
|
|
||||||
|
.cm-s-default .cm-keyword {color: #708;}
|
||||||
|
.cm-s-default .cm-atom {color: #219;}
|
||||||
|
.cm-s-default .cm-number {color: #164;}
|
||||||
|
.cm-s-default .cm-def {color: #00f;}
|
||||||
|
.cm-s-default .cm-variable,
|
||||||
|
.cm-s-default .cm-punctuation,
|
||||||
|
.cm-s-default .cm-property,
|
||||||
|
.cm-s-default .cm-operator {}
|
||||||
|
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||||
|
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
|
||||||
|
.cm-s-default .cm-comment {color: #a50;}
|
||||||
|
.cm-s-default .cm-string {color: #a11;}
|
||||||
|
.cm-s-default .cm-string-2 {color: #f50;}
|
||||||
|
.cm-s-default .cm-meta {color: #555;}
|
||||||
|
.cm-s-default .cm-qualifier {color: #555;}
|
||||||
|
.cm-s-default .cm-builtin {color: #30a;}
|
||||||
|
.cm-s-default .cm-bracket {color: #997;}
|
||||||
|
.cm-s-default .cm-tag {color: #170;}
|
||||||
|
.cm-s-default .cm-attribute {color: #00c;}
|
||||||
|
.cm-s-default .cm-hr {color: #999;}
|
||||||
|
.cm-s-default .cm-link {color: #00c;}
|
||||||
|
|
||||||
|
.cm-s-default .cm-error {color: #f00;}
|
||||||
|
.cm-invalidchar {color: #f00;}
|
||||||
|
|
||||||
|
.CodeMirror-composing { border-bottom: 2px solid; }
|
||||||
|
|
||||||
|
/* Default styles for common addons */
|
||||||
|
|
||||||
|
div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
|
||||||
|
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
|
||||||
|
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
|
||||||
|
.CodeMirror-activeline-background {background: #e8f2ff;}
|
||||||
|
|
||||||
|
/* STOP */
|
||||||
|
|
||||||
|
/* The rest of this file contains styles related to the mechanics of
|
||||||
|
the editor. You probably shouldn't touch them. */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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 */
|
||||||
|
/* See overflow: hidden in .CodeMirror */
|
||||||
|
margin-bottom: -30px; margin-right: -30px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
height: 100%;
|
||||||
|
outline: none; /* Prevent dragging from highlighting the element */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.CodeMirror-sizer {
|
||||||
|
position: relative;
|
||||||
|
border-right: 30px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||||
|
before actual scrolling happens, thus preventing shaking and
|
||||||
|
flickering artifacts. */
|
||||||
|
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-vscrollbar {
|
||||||
|
right: 0; top: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-hscrollbar {
|
||||||
|
bottom: 0; left: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-scrollbar-filler {
|
||||||
|
right: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-filler {
|
||||||
|
left: 0; bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
position: absolute; left: 0; top: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter {
|
||||||
|
white-space: normal;
|
||||||
|
height: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin-bottom: -30px;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 4;
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; bottom: 0;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-elt {
|
||||||
|
position: absolute;
|
||||||
|
cursor: default;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
|
||||||
|
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
cursor: text;
|
||||||
|
min-height: 1px; /* prevents collapsing before first draw */
|
||||||
|
}
|
||||||
|
.CodeMirror pre.CodeMirror-line,
|
||||||
|
.CodeMirror pre.CodeMirror-line-like {
|
||||||
|
/* Reset some styles that the rest of the page might have set */
|
||||||
|
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
|
||||||
|
border-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
-webkit-font-variant-ligatures: contextual;
|
||||||
|
font-variant-ligatures: contextual;
|
||||||
|
}
|
||||||
|
.CodeMirror-wrap pre.CodeMirror-line,
|
||||||
|
.CodeMirror-wrap pre.CodeMirror-line-like {
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linebackground {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; right: 0; top: 0; bottom: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linewidget {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 0.1px; /* Force widget margins to stay inside of the container */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-widget {}
|
||||||
|
|
||||||
|
.CodeMirror-rtl pre { direction: rtl; }
|
||||||
|
|
||||||
|
.CodeMirror-code {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force content-box sizing for the elements where we expect it */
|
||||||
|
.CodeMirror-scroll,
|
||||||
|
.CodeMirror-sizer,
|
||||||
|
.CodeMirror-gutter,
|
||||||
|
.CodeMirror-gutters,
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-measure {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-cursor {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-measure pre { position: static; }
|
||||||
|
|
||||||
|
div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
div.CodeMirror-dragcursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-focused div.CodeMirror-cursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-selected { background: #d9d9d9; }
|
||||||
|
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||||
|
.CodeMirror-crosshair { cursor: crosshair; }
|
||||||
|
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
|
||||||
|
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
|
||||||
|
|
||||||
|
.cm-searching {
|
||||||
|
background-color: #ffa;
|
||||||
|
background-color: rgba(255, 255, 0, .4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used to force a border model for a node */
|
||||||
|
.cm-force-border { padding-right: .1px; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
/* Hide the cursor when printing */
|
||||||
|
.CodeMirror div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See issue #2901 */
|
||||||
|
.cm-tab-wrap-hack:after { content: ''; }
|
||||||
|
|
||||||
|
/* Help users use markselection to safely style text background */
|
||||||
|
span.CodeMirror-selectedtext { background: none; }
|
|
@ -0,0 +1,831 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("css", function(config, parserConfig) {
|
||||||
|
var inline = parserConfig.inline
|
||||||
|
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
|
||||||
|
|
||||||
|
var indentUnit = config.indentUnit,
|
||||||
|
tokenHooks = parserConfig.tokenHooks,
|
||||||
|
documentTypes = parserConfig.documentTypes || {},
|
||||||
|
mediaTypes = parserConfig.mediaTypes || {},
|
||||||
|
mediaFeatures = parserConfig.mediaFeatures || {},
|
||||||
|
mediaValueKeywords = parserConfig.mediaValueKeywords || {},
|
||||||
|
propertyKeywords = parserConfig.propertyKeywords || {},
|
||||||
|
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
|
||||||
|
fontProperties = parserConfig.fontProperties || {},
|
||||||
|
counterDescriptors = parserConfig.counterDescriptors || {},
|
||||||
|
colorKeywords = parserConfig.colorKeywords || {},
|
||||||
|
valueKeywords = parserConfig.valueKeywords || {},
|
||||||
|
allowNested = parserConfig.allowNested,
|
||||||
|
lineComment = parserConfig.lineComment,
|
||||||
|
supportsAtComponent = parserConfig.supportsAtComponent === true;
|
||||||
|
|
||||||
|
var type, override;
|
||||||
|
function ret(style, tp) { type = tp; return style; }
|
||||||
|
|
||||||
|
// Tokenizers
|
||||||
|
|
||||||
|
function tokenBase(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (tokenHooks[ch]) {
|
||||||
|
var result = tokenHooks[ch](stream, state);
|
||||||
|
if (result !== false) return result;
|
||||||
|
}
|
||||||
|
if (ch == "@") {
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
return ret("def", stream.current());
|
||||||
|
} else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
|
||||||
|
return ret(null, "compare");
|
||||||
|
} else if (ch == "\"" || ch == "'") {
|
||||||
|
state.tokenize = tokenString(ch);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else if (ch == "#") {
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
return ret("atom", "hash");
|
||||||
|
} else if (ch == "!") {
|
||||||
|
stream.match(/^\s*\w*/);
|
||||||
|
return ret("keyword", "important");
|
||||||
|
} else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
|
||||||
|
stream.eatWhile(/[\w.%]/);
|
||||||
|
return ret("number", "unit");
|
||||||
|
} else if (ch === "-") {
|
||||||
|
if (/[\d.]/.test(stream.peek())) {
|
||||||
|
stream.eatWhile(/[\w.%]/);
|
||||||
|
return ret("number", "unit");
|
||||||
|
} else if (stream.match(/^-[\w\\\-]*/)) {
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
if (stream.match(/^\s*:/, false))
|
||||||
|
return ret("variable-2", "variable-definition");
|
||||||
|
return ret("variable-2", "variable");
|
||||||
|
} else if (stream.match(/^\w+-/)) {
|
||||||
|
return ret("meta", "meta");
|
||||||
|
}
|
||||||
|
} else if (/[,+>*\/]/.test(ch)) {
|
||||||
|
return ret(null, "select-op");
|
||||||
|
} else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
|
||||||
|
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())) {
|
||||||
|
state.tokenize = tokenParenthesized;
|
||||||
|
}
|
||||||
|
return ret("variable callee", "variable");
|
||||||
|
} else if (/[\w\\\-]/.test(ch)) {
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
return ret("property", "word");
|
||||||
|
} else {
|
||||||
|
return ret(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenString(quote) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var escaped = false, ch;
|
||||||
|
while ((ch = stream.next()) != null) {
|
||||||
|
if (ch == quote && !escaped) {
|
||||||
|
if (quote == ")") stream.backUp(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = !escaped && ch == "\\";
|
||||||
|
}
|
||||||
|
if (ch == quote || !escaped && quote != ")") state.tokenize = null;
|
||||||
|
return ret("string", "string");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenParenthesized(stream, state) {
|
||||||
|
stream.next(); // Must be '('
|
||||||
|
if (!stream.match(/\s*[\"\')]/, false))
|
||||||
|
state.tokenize = tokenString(")");
|
||||||
|
else
|
||||||
|
state.tokenize = null;
|
||||||
|
return ret(null, "(");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context management
|
||||||
|
|
||||||
|
function Context(type, indent, prev) {
|
||||||
|
this.type = type;
|
||||||
|
this.indent = indent;
|
||||||
|
this.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushContext(state, stream, type, indent) {
|
||||||
|
state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function popContext(state) {
|
||||||
|
if (state.context.prev)
|
||||||
|
state.context = state.context.prev;
|
||||||
|
return state.context.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pass(type, stream, state) {
|
||||||
|
return states[state.context.type](type, stream, state);
|
||||||
|
}
|
||||||
|
function popAndPass(type, stream, state, n) {
|
||||||
|
for (var i = n || 1; i > 0; i--)
|
||||||
|
state.context = state.context.prev;
|
||||||
|
return pass(type, stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
function wordAsValue(stream) {
|
||||||
|
var word = stream.current().toLowerCase();
|
||||||
|
if (valueKeywords.hasOwnProperty(word))
|
||||||
|
override = "atom";
|
||||||
|
else if (colorKeywords.hasOwnProperty(word))
|
||||||
|
override = "keyword";
|
||||||
|
else
|
||||||
|
override = "variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
var states = {};
|
||||||
|
|
||||||
|
states.top = function(type, stream, state) {
|
||||||
|
if (type == "{") {
|
||||||
|
return pushContext(state, stream, "block");
|
||||||
|
} else if (type == "}" && state.context.prev) {
|
||||||
|
return popContext(state);
|
||||||
|
} else if (supportsAtComponent && /@component/i.test(type)) {
|
||||||
|
return pushContext(state, stream, "atComponentBlock");
|
||||||
|
} else if (/^@(-moz-)?document$/i.test(type)) {
|
||||||
|
return pushContext(state, stream, "documentTypes");
|
||||||
|
} else if (/^@(media|supports|(-moz-)?document|import)$/i.test(type)) {
|
||||||
|
return pushContext(state, stream, "atBlock");
|
||||||
|
} else if (/^@(font-face|counter-style)/i.test(type)) {
|
||||||
|
state.stateArg = type;
|
||||||
|
return "restricted_atBlock_before";
|
||||||
|
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(type)) {
|
||||||
|
return "keyframes";
|
||||||
|
} else if (type && type.charAt(0) == "@") {
|
||||||
|
return pushContext(state, stream, "at");
|
||||||
|
} else if (type == "hash") {
|
||||||
|
override = "builtin";
|
||||||
|
} else if (type == "word") {
|
||||||
|
override = "tag";
|
||||||
|
} else if (type == "variable-definition") {
|
||||||
|
return "maybeprop";
|
||||||
|
} else if (type == "interpolation") {
|
||||||
|
return pushContext(state, stream, "interpolation");
|
||||||
|
} else if (type == ":") {
|
||||||
|
return "pseudo";
|
||||||
|
} else if (allowNested && type == "(") {
|
||||||
|
return pushContext(state, stream, "parens");
|
||||||
|
}
|
||||||
|
return state.context.type;
|
||||||
|
};
|
||||||
|
|
||||||
|
states.block = function(type, stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
var word = stream.current().toLowerCase();
|
||||||
|
if (propertyKeywords.hasOwnProperty(word)) {
|
||||||
|
override = "property";
|
||||||
|
return "maybeprop";
|
||||||
|
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
|
||||||
|
override = "string-2";
|
||||||
|
return "maybeprop";
|
||||||
|
} else if (allowNested) {
|
||||||
|
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
|
||||||
|
return "block";
|
||||||
|
} else {
|
||||||
|
override += " error";
|
||||||
|
return "maybeprop";
|
||||||
|
}
|
||||||
|
} else if (type == "meta") {
|
||||||
|
return "block";
|
||||||
|
} else if (!allowNested && (type == "hash" || type == "qualifier")) {
|
||||||
|
override = "error";
|
||||||
|
return "block";
|
||||||
|
} else {
|
||||||
|
return states.top(type, stream, state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
states.maybeprop = function(type, stream, state) {
|
||||||
|
if (type == ":") return pushContext(state, stream, "prop");
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.prop = function(type, stream, state) {
|
||||||
|
if (type == ";") return popContext(state);
|
||||||
|
if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
|
||||||
|
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())) {
|
||||||
|
override += " error";
|
||||||
|
} else if (type == "word") {
|
||||||
|
wordAsValue(stream);
|
||||||
|
} else if (type == "interpolation") {
|
||||||
|
return pushContext(state, stream, "interpolation");
|
||||||
|
}
|
||||||
|
return "prop";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.propBlock = function(type, _stream, state) {
|
||||||
|
if (type == "}") return popContext(state);
|
||||||
|
if (type == "word") { override = "property"; return "maybeprop"; }
|
||||||
|
return state.context.type;
|
||||||
|
};
|
||||||
|
|
||||||
|
states.parens = function(type, stream, state) {
|
||||||
|
if (type == "{" || type == "}") return popAndPass(type, stream, state);
|
||||||
|
if (type == ")") return popContext(state);
|
||||||
|
if (type == "(") return pushContext(state, stream, "parens");
|
||||||
|
if (type == "interpolation") return pushContext(state, stream, "interpolation");
|
||||||
|
if (type == "word") wordAsValue(stream);
|
||||||
|
return "parens";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.pseudo = function(type, stream, state) {
|
||||||
|
if (type == "meta") return "pseudo";
|
||||||
|
|
||||||
|
if (type == "word") {
|
||||||
|
override = "variable-3";
|
||||||
|
return state.context.type;
|
||||||
|
}
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.documentTypes = function(type, stream, state) {
|
||||||
|
if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
|
||||||
|
override = "tag";
|
||||||
|
return state.context.type;
|
||||||
|
} else {
|
||||||
|
return states.atBlock(type, stream, state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
states.atBlock = function(type, stream, state) {
|
||||||
|
if (type == "(") return pushContext(state, stream, "atBlock_parens");
|
||||||
|
if (type == "}" || type == ";") return popAndPass(type, stream, state);
|
||||||
|
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
|
||||||
|
|
||||||
|
if (type == "interpolation") return pushContext(state, stream, "interpolation");
|
||||||
|
|
||||||
|
if (type == "word") {
|
||||||
|
var word = stream.current().toLowerCase();
|
||||||
|
if (word == "only" || word == "not" || word == "and" || word == "or")
|
||||||
|
override = "keyword";
|
||||||
|
else if (mediaTypes.hasOwnProperty(word))
|
||||||
|
override = "attribute";
|
||||||
|
else if (mediaFeatures.hasOwnProperty(word))
|
||||||
|
override = "property";
|
||||||
|
else if (mediaValueKeywords.hasOwnProperty(word))
|
||||||
|
override = "keyword";
|
||||||
|
else if (propertyKeywords.hasOwnProperty(word))
|
||||||
|
override = "property";
|
||||||
|
else if (nonStandardPropertyKeywords.hasOwnProperty(word))
|
||||||
|
override = "string-2";
|
||||||
|
else if (valueKeywords.hasOwnProperty(word))
|
||||||
|
override = "atom";
|
||||||
|
else if (colorKeywords.hasOwnProperty(word))
|
||||||
|
override = "keyword";
|
||||||
|
else
|
||||||
|
override = "error";
|
||||||
|
}
|
||||||
|
return state.context.type;
|
||||||
|
};
|
||||||
|
|
||||||
|
states.atComponentBlock = function(type, stream, state) {
|
||||||
|
if (type == "}")
|
||||||
|
return popAndPass(type, stream, state);
|
||||||
|
if (type == "{")
|
||||||
|
return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
|
||||||
|
if (type == "word")
|
||||||
|
override = "error";
|
||||||
|
return state.context.type;
|
||||||
|
};
|
||||||
|
|
||||||
|
states.atBlock_parens = function(type, stream, state) {
|
||||||
|
if (type == ")") return popContext(state);
|
||||||
|
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
|
||||||
|
return states.atBlock(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.restricted_atBlock_before = function(type, stream, state) {
|
||||||
|
if (type == "{")
|
||||||
|
return pushContext(state, stream, "restricted_atBlock");
|
||||||
|
if (type == "word" && state.stateArg == "@counter-style") {
|
||||||
|
override = "variable";
|
||||||
|
return "restricted_atBlock_before";
|
||||||
|
}
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.restricted_atBlock = function(type, stream, state) {
|
||||||
|
if (type == "}") {
|
||||||
|
state.stateArg = null;
|
||||||
|
return popContext(state);
|
||||||
|
}
|
||||||
|
if (type == "word") {
|
||||||
|
if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
|
||||||
|
(state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
|
||||||
|
override = "error";
|
||||||
|
else
|
||||||
|
override = "property";
|
||||||
|
return "maybeprop";
|
||||||
|
}
|
||||||
|
return "restricted_atBlock";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.keyframes = function(type, stream, state) {
|
||||||
|
if (type == "word") { override = "variable"; return "keyframes"; }
|
||||||
|
if (type == "{") return pushContext(state, stream, "top");
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.at = function(type, stream, state) {
|
||||||
|
if (type == ";") return popContext(state);
|
||||||
|
if (type == "{" || type == "}") return popAndPass(type, stream, state);
|
||||||
|
if (type == "word") override = "tag";
|
||||||
|
else if (type == "hash") override = "builtin";
|
||||||
|
return "at";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.interpolation = function(type, stream, state) {
|
||||||
|
if (type == "}") return popContext(state);
|
||||||
|
if (type == "{" || type == ";") return popAndPass(type, stream, state);
|
||||||
|
if (type == "word") override = "variable";
|
||||||
|
else if (type != "variable" && type != "(" && type != ")") override = "error";
|
||||||
|
return "interpolation";
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function(base) {
|
||||||
|
return {tokenize: null,
|
||||||
|
state: inline ? "block" : "top",
|
||||||
|
stateArg: null,
|
||||||
|
context: new Context(inline ? "block" : "top", base || 0, null)};
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (!state.tokenize && stream.eatSpace()) return null;
|
||||||
|
var style = (state.tokenize || tokenBase)(stream, state);
|
||||||
|
if (style && typeof style == "object") {
|
||||||
|
type = style[1];
|
||||||
|
style = style[0];
|
||||||
|
}
|
||||||
|
override = style;
|
||||||
|
if (type != "comment")
|
||||||
|
state.state = states[state.state](type, stream, state);
|
||||||
|
return override;
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
var cx = state.context, ch = textAfter && textAfter.charAt(0);
|
||||||
|
var indent = cx.indent;
|
||||||
|
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
|
||||||
|
if (cx.prev) {
|
||||||
|
if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
|
||||||
|
cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
|
||||||
|
// Resume indentation from parent context.
|
||||||
|
cx = cx.prev;
|
||||||
|
indent = cx.indent;
|
||||||
|
} else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
|
||||||
|
ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
|
||||||
|
// Dedent relative to current context.
|
||||||
|
indent = Math.max(0, cx.indent - indentUnit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return indent;
|
||||||
|
},
|
||||||
|
|
||||||
|
electricChars: "}",
|
||||||
|
blockCommentStart: "/*",
|
||||||
|
blockCommentEnd: "*/",
|
||||||
|
blockCommentContinue: " * ",
|
||||||
|
lineComment: lineComment,
|
||||||
|
fold: "brace"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function keySet(array) {
|
||||||
|
var keys = {};
|
||||||
|
for (var i = 0; i < array.length; ++i) {
|
||||||
|
keys[array[i].toLowerCase()] = true;
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
var documentTypes_ = [
|
||||||
|
"domain", "regexp", "url", "url-prefix"
|
||||||
|
], documentTypes = keySet(documentTypes_);
|
||||||
|
|
||||||
|
var mediaTypes_ = [
|
||||||
|
"all", "aural", "braille", "handheld", "print", "projection", "screen",
|
||||||
|
"tty", "tv", "embossed"
|
||||||
|
], mediaTypes = keySet(mediaTypes_);
|
||||||
|
|
||||||
|
var mediaFeatures_ = [
|
||||||
|
"width", "min-width", "max-width", "height", "min-height", "max-height",
|
||||||
|
"device-width", "min-device-width", "max-device-width", "device-height",
|
||||||
|
"min-device-height", "max-device-height", "aspect-ratio",
|
||||||
|
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
|
||||||
|
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
|
||||||
|
"max-color", "color-index", "min-color-index", "max-color-index",
|
||||||
|
"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"
|
||||||
|
], mediaFeatures = keySet(mediaFeatures_);
|
||||||
|
|
||||||
|
var mediaValueKeywords_ = [
|
||||||
|
"landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
|
||||||
|
"interlace", "progressive"
|
||||||
|
], mediaValueKeywords = keySet(mediaValueKeywords_);
|
||||||
|
|
||||||
|
var propertyKeywords_ = [
|
||||||
|
"align-content", "align-items", "align-self", "alignment-adjust",
|
||||||
|
"alignment-baseline", "anchor-point", "animation", "animation-delay",
|
||||||
|
"animation-direction", "animation-duration", "animation-fill-mode",
|
||||||
|
"animation-iteration-count", "animation-name", "animation-play-state",
|
||||||
|
"animation-timing-function", "appearance", "azimuth", "backface-visibility",
|
||||||
|
"background", "background-attachment", "background-blend-mode", "background-clip",
|
||||||
|
"background-color", "background-image", "background-origin", "background-position",
|
||||||
|
"background-repeat", "background-size", "baseline-shift", "binding",
|
||||||
|
"bleed", "bookmark-label", "bookmark-level", "bookmark-state",
|
||||||
|
"bookmark-target", "border", "border-bottom", "border-bottom-color",
|
||||||
|
"border-bottom-left-radius", "border-bottom-right-radius",
|
||||||
|
"border-bottom-style", "border-bottom-width", "border-collapse",
|
||||||
|
"border-color", "border-image", "border-image-outset",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
// 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",
|
||||||
|
"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"
|
||||||
|
], propertyKeywords = keySet(propertyKeywords_);
|
||||||
|
|
||||||
|
var nonStandardPropertyKeywords_ = [
|
||||||
|
"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"
|
||||||
|
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
|
||||||
|
|
||||||
|
var fontProperties_ = [
|
||||||
|
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
|
||||||
|
"font-stretch", "font-weight", "font-style"
|
||||||
|
], fontProperties = keySet(fontProperties_);
|
||||||
|
|
||||||
|
var counterDescriptors_ = [
|
||||||
|
"additive-symbols", "fallback", "negative", "pad", "prefix", "range",
|
||||||
|
"speak-as", "suffix", "symbols", "system"
|
||||||
|
], counterDescriptors = keySet(counterDescriptors_);
|
||||||
|
|
||||||
|
var colorKeywords_ = [
|
||||||
|
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
|
||||||
|
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
|
||||||
|
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
|
||||||
|
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
|
||||||
|
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
|
||||||
|
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
|
||||||
|
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
|
||||||
|
"deeppink", "deepskyblue", "dimgray", "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",
|
||||||
|
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
|
||||||
|
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
|
||||||
|
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
|
||||||
|
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
|
||||||
|
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
|
||||||
|
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
|
||||||
|
"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",
|
||||||
|
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
|
||||||
|
"whitesmoke", "yellow", "yellowgreen"
|
||||||
|
], colorKeywords = keySet(colorKeywords_);
|
||||||
|
|
||||||
|
var valueKeywords_ = [
|
||||||
|
"above", "absolute", "activeborder", "additive", "activecaption", "afar",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
|
||||||
|
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
|
||||||
|
"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",
|
||||||
|
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
|
||||||
|
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
|
||||||
|
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "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",
|
||||||
|
"italic", "japanese-formal", "japanese-informal", "justify", "kannada",
|
||||||
|
"katakana", "katakana-iroha", "keep-all", "khmer",
|
||||||
|
"korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
|
||||||
|
"landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"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",
|
||||||
|
"table-caption", "table-cell", "table-column", "table-column-group",
|
||||||
|
"table-footer-group", "table-header-group", "table-row", "table-row-group",
|
||||||
|
"tamil",
|
||||||
|
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
|
||||||
|
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
|
||||||
|
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
|
||||||
|
"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",
|
||||||
|
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
|
||||||
|
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
|
||||||
|
"var", "vertical", "vertical-text", "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"
|
||||||
|
], valueKeywords = keySet(valueKeywords_);
|
||||||
|
|
||||||
|
var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
|
||||||
|
.concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
|
||||||
|
.concat(valueKeywords_);
|
||||||
|
CodeMirror.registerHelper("hintWords", "css", allWords);
|
||||||
|
|
||||||
|
function tokenCComment(stream, state) {
|
||||||
|
var maybeEnd = false, ch;
|
||||||
|
while ((ch = stream.next()) != null) {
|
||||||
|
if (maybeEnd && ch == "/") {
|
||||||
|
state.tokenize = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maybeEnd = (ch == "*");
|
||||||
|
}
|
||||||
|
return ["comment", "comment"];
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/css", {
|
||||||
|
documentTypes: documentTypes,
|
||||||
|
mediaTypes: mediaTypes,
|
||||||
|
mediaFeatures: mediaFeatures,
|
||||||
|
mediaValueKeywords: mediaValueKeywords,
|
||||||
|
propertyKeywords: propertyKeywords,
|
||||||
|
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||||
|
fontProperties: fontProperties,
|
||||||
|
counterDescriptors: counterDescriptors,
|
||||||
|
colorKeywords: colorKeywords,
|
||||||
|
valueKeywords: valueKeywords,
|
||||||
|
tokenHooks: {
|
||||||
|
"/": function(stream, state) {
|
||||||
|
if (!stream.eat("*")) return false;
|
||||||
|
state.tokenize = tokenCComment;
|
||||||
|
return tokenCComment(stream, state);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "css"
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/x-scss", {
|
||||||
|
mediaTypes: mediaTypes,
|
||||||
|
mediaFeatures: mediaFeatures,
|
||||||
|
mediaValueKeywords: mediaValueKeywords,
|
||||||
|
propertyKeywords: propertyKeywords,
|
||||||
|
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||||
|
colorKeywords: colorKeywords,
|
||||||
|
valueKeywords: valueKeywords,
|
||||||
|
fontProperties: fontProperties,
|
||||||
|
allowNested: true,
|
||||||
|
lineComment: "//",
|
||||||
|
tokenHooks: {
|
||||||
|
"/": function(stream, state) {
|
||||||
|
if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ["comment", "comment"];
|
||||||
|
} else if (stream.eat("*")) {
|
||||||
|
state.tokenize = tokenCComment;
|
||||||
|
return tokenCComment(stream, state);
|
||||||
|
} else {
|
||||||
|
return ["operator", "operator"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
":": function(stream) {
|
||||||
|
if (stream.match(/\s*\{/, false))
|
||||||
|
return [null, null]
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
"$": function(stream) {
|
||||||
|
stream.match(/^[\w-]+/);
|
||||||
|
if (stream.match(/^\s*:/, false))
|
||||||
|
return ["variable-2", "variable-definition"];
|
||||||
|
return ["variable-2", "variable"];
|
||||||
|
},
|
||||||
|
"#": function(stream) {
|
||||||
|
if (!stream.eat("{")) return false;
|
||||||
|
return [null, "interpolation"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "css",
|
||||||
|
helperType: "scss"
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/x-less", {
|
||||||
|
mediaTypes: mediaTypes,
|
||||||
|
mediaFeatures: mediaFeatures,
|
||||||
|
mediaValueKeywords: mediaValueKeywords,
|
||||||
|
propertyKeywords: propertyKeywords,
|
||||||
|
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||||
|
colorKeywords: colorKeywords,
|
||||||
|
valueKeywords: valueKeywords,
|
||||||
|
fontProperties: fontProperties,
|
||||||
|
allowNested: true,
|
||||||
|
lineComment: "//",
|
||||||
|
tokenHooks: {
|
||||||
|
"/": function(stream, state) {
|
||||||
|
if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ["comment", "comment"];
|
||||||
|
} else if (stream.eat("*")) {
|
||||||
|
state.tokenize = tokenCComment;
|
||||||
|
return tokenCComment(stream, state);
|
||||||
|
} else {
|
||||||
|
return ["operator", "operator"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@": function(stream) {
|
||||||
|
if (stream.eat("{")) return [null, "interpolation"];
|
||||||
|
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i, false)) return false;
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
if (stream.match(/^\s*:/, false))
|
||||||
|
return ["variable-2", "variable-definition"];
|
||||||
|
return ["variable-2", "variable"];
|
||||||
|
},
|
||||||
|
"&": function() {
|
||||||
|
return ["atom", "atom"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "css",
|
||||||
|
helperType: "less"
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/x-gss", {
|
||||||
|
documentTypes: documentTypes,
|
||||||
|
mediaTypes: mediaTypes,
|
||||||
|
mediaFeatures: mediaFeatures,
|
||||||
|
propertyKeywords: propertyKeywords,
|
||||||
|
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||||
|
fontProperties: fontProperties,
|
||||||
|
counterDescriptors: counterDescriptors,
|
||||||
|
colorKeywords: colorKeywords,
|
||||||
|
valueKeywords: valueKeywords,
|
||||||
|
supportsAtComponent: true,
|
||||||
|
tokenHooks: {
|
||||||
|
"/": function(stream, state) {
|
||||||
|
if (!stream.eat("*")) return false;
|
||||||
|
state.tokenize = tokenCComment;
|
||||||
|
return tokenCComment(stream, state);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "css",
|
||||||
|
helperType: "gss"
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,717 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("css", function(config, parserConfig) {
|
||||||
|
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
|
||||||
|
|
||||||
|
var indentUnit = config.indentUnit,
|
||||||
|
tokenHooks = parserConfig.tokenHooks,
|
||||||
|
mediaTypes = parserConfig.mediaTypes || {},
|
||||||
|
mediaFeatures = parserConfig.mediaFeatures || {},
|
||||||
|
propertyKeywords = parserConfig.propertyKeywords || {},
|
||||||
|
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
|
||||||
|
colorKeywords = parserConfig.colorKeywords || {},
|
||||||
|
valueKeywords = parserConfig.valueKeywords || {},
|
||||||
|
fontProperties = parserConfig.fontProperties || {},
|
||||||
|
allowNested = parserConfig.allowNested;
|
||||||
|
|
||||||
|
var type, override;
|
||||||
|
function ret(style, tp) { type = tp; return style; }
|
||||||
|
|
||||||
|
// Tokenizers
|
||||||
|
|
||||||
|
function tokenBase(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (tokenHooks[ch]) {
|
||||||
|
var result = tokenHooks[ch](stream, state);
|
||||||
|
if (result !== false) return result;
|
||||||
|
}
|
||||||
|
if (ch == "@") {
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
return ret("def", stream.current());
|
||||||
|
} else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
|
||||||
|
return ret(null, "compare");
|
||||||
|
} else if (ch == "\"" || ch == "'") {
|
||||||
|
state.tokenize = tokenString(ch);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else if (ch == "#") {
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
return ret("atom", "hash");
|
||||||
|
} else if (ch == "!") {
|
||||||
|
stream.match(/^\s*\w*/);
|
||||||
|
return ret("keyword", "important");
|
||||||
|
} else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
|
||||||
|
stream.eatWhile(/[\w.%]/);
|
||||||
|
return ret("number", "unit");
|
||||||
|
} else if (ch === "-") {
|
||||||
|
if (/[\d.]/.test(stream.peek())) {
|
||||||
|
stream.eatWhile(/[\w.%]/);
|
||||||
|
return ret("number", "unit");
|
||||||
|
} else if (stream.match(/^\w+-/)) {
|
||||||
|
return ret("meta", "meta");
|
||||||
|
}
|
||||||
|
} else if (/[,+>*\/]/.test(ch)) {
|
||||||
|
return ret(null, "select-op");
|
||||||
|
} else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
|
||||||
|
return ret("qualifier", "qualifier");
|
||||||
|
} else if (/[:;{}\[\]\(\)]/.test(ch)) {
|
||||||
|
return ret(null, ch);
|
||||||
|
} else if (ch == "u" && stream.match("rl(")) {
|
||||||
|
stream.backUp(1);
|
||||||
|
state.tokenize = tokenParenthesized;
|
||||||
|
return ret("property", "word");
|
||||||
|
} else if (/[\w\\\-]/.test(ch)) {
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
return ret("property", "word");
|
||||||
|
} else {
|
||||||
|
return ret(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenString(quote) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var escaped = false, ch;
|
||||||
|
while ((ch = stream.next()) != null) {
|
||||||
|
if (ch == quote && !escaped) {
|
||||||
|
if (quote == ")") stream.backUp(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = !escaped && ch == "\\";
|
||||||
|
}
|
||||||
|
if (ch == quote || !escaped && quote != ")") state.tokenize = null;
|
||||||
|
return ret("string", "string");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenParenthesized(stream, state) {
|
||||||
|
stream.next(); // Must be '('
|
||||||
|
if (!stream.match(/\s*[\"\')]/, false))
|
||||||
|
state.tokenize = tokenString(")");
|
||||||
|
else
|
||||||
|
state.tokenize = null;
|
||||||
|
return ret(null, "(");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context management
|
||||||
|
|
||||||
|
function Context(type, indent, prev) {
|
||||||
|
this.type = type;
|
||||||
|
this.indent = indent;
|
||||||
|
this.prev = prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushContext(state, stream, type) {
|
||||||
|
state.context = new Context(type, stream.indentation() + indentUnit, state.context);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function popContext(state) {
|
||||||
|
state.context = state.context.prev;
|
||||||
|
return state.context.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pass(type, stream, state) {
|
||||||
|
return states[state.context.type](type, stream, state);
|
||||||
|
}
|
||||||
|
function popAndPass(type, stream, state, n) {
|
||||||
|
for (var i = n || 1; i > 0; i--)
|
||||||
|
state.context = state.context.prev;
|
||||||
|
return pass(type, stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
function wordAsValue(stream) {
|
||||||
|
var word = stream.current().toLowerCase();
|
||||||
|
if (valueKeywords.hasOwnProperty(word))
|
||||||
|
override = "atom";
|
||||||
|
else if (colorKeywords.hasOwnProperty(word))
|
||||||
|
override = "keyword";
|
||||||
|
else
|
||||||
|
override = "variable";
|
||||||
|
}
|
||||||
|
|
||||||
|
var states = {};
|
||||||
|
|
||||||
|
states.top = function(type, stream, state) {
|
||||||
|
if (type == "{") {
|
||||||
|
return pushContext(state, stream, "block");
|
||||||
|
} else if (type == "}" && state.context.prev) {
|
||||||
|
return popContext(state);
|
||||||
|
} else if (type == "@media") {
|
||||||
|
return pushContext(state, stream, "media");
|
||||||
|
} else if (type == "@font-face") {
|
||||||
|
return "font_face_before";
|
||||||
|
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
|
||||||
|
return "keyframes";
|
||||||
|
} else if (type && type.charAt(0) == "@") {
|
||||||
|
return pushContext(state, stream, "at");
|
||||||
|
} else if (type == "hash") {
|
||||||
|
override = "builtin";
|
||||||
|
} else if (type == "word") {
|
||||||
|
override = "tag";
|
||||||
|
} else if (type == "variable-definition") {
|
||||||
|
return "maybeprop";
|
||||||
|
} else if (type == "interpolation") {
|
||||||
|
return pushContext(state, stream, "interpolation");
|
||||||
|
} else if (type == ":") {
|
||||||
|
return "pseudo";
|
||||||
|
} else if (allowNested && type == "(") {
|
||||||
|
return pushContext(state, stream, "parens");
|
||||||
|
}
|
||||||
|
return state.context.type;
|
||||||
|
};
|
||||||
|
|
||||||
|
states.block = function(type, stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
var word = stream.current().toLowerCase();
|
||||||
|
if (propertyKeywords.hasOwnProperty(word)) {
|
||||||
|
override = "property";
|
||||||
|
return "maybeprop";
|
||||||
|
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
|
||||||
|
override = "string-2";
|
||||||
|
return "maybeprop";
|
||||||
|
} else if (allowNested) {
|
||||||
|
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
|
||||||
|
return "block";
|
||||||
|
} else {
|
||||||
|
override += " error";
|
||||||
|
return "maybeprop";
|
||||||
|
}
|
||||||
|
} else if (type == "meta") {
|
||||||
|
return "block";
|
||||||
|
} else if (!allowNested && (type == "hash" || type == "qualifier")) {
|
||||||
|
override = "error";
|
||||||
|
return "block";
|
||||||
|
} else {
|
||||||
|
return states.top(type, stream, state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
states.maybeprop = function(type, stream, state) {
|
||||||
|
if (type == ":") return pushContext(state, stream, "prop");
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.prop = function(type, stream, state) {
|
||||||
|
if (type == ";") return popContext(state);
|
||||||
|
if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
|
||||||
|
if (type == "}" || type == "{") return popAndPass(type, stream, state);
|
||||||
|
if (type == "(") return pushContext(state, stream, "parens");
|
||||||
|
|
||||||
|
if (type == "hash" && !/^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/.test(stream.current())) {
|
||||||
|
override += " error";
|
||||||
|
} else if (type == "word") {
|
||||||
|
wordAsValue(stream);
|
||||||
|
} else if (type == "interpolation") {
|
||||||
|
return pushContext(state, stream, "interpolation");
|
||||||
|
}
|
||||||
|
return "prop";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.propBlock = function(type, _stream, state) {
|
||||||
|
if (type == "}") return popContext(state);
|
||||||
|
if (type == "word") { override = "property"; return "maybeprop"; }
|
||||||
|
return state.context.type;
|
||||||
|
};
|
||||||
|
|
||||||
|
states.parens = function(type, stream, state) {
|
||||||
|
if (type == "{" || type == "}") return popAndPass(type, stream, state);
|
||||||
|
if (type == ")") return popContext(state);
|
||||||
|
if (type == "(") return pushContext(state, stream, "parens");
|
||||||
|
if (type == "word") wordAsValue(stream);
|
||||||
|
return "parens";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.pseudo = function(type, stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
override = "variable-3";
|
||||||
|
return state.context.type;
|
||||||
|
}
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.media = function(type, stream, state) {
|
||||||
|
if (type == "(") return pushContext(state, stream, "media_parens");
|
||||||
|
if (type == "}") return popAndPass(type, stream, state);
|
||||||
|
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
|
||||||
|
|
||||||
|
if (type == "word") {
|
||||||
|
var word = stream.current().toLowerCase();
|
||||||
|
if (word == "only" || word == "not" || word == "and")
|
||||||
|
override = "keyword";
|
||||||
|
else if (mediaTypes.hasOwnProperty(word))
|
||||||
|
override = "attribute";
|
||||||
|
else if (mediaFeatures.hasOwnProperty(word))
|
||||||
|
override = "property";
|
||||||
|
else
|
||||||
|
override = "error";
|
||||||
|
}
|
||||||
|
return state.context.type;
|
||||||
|
};
|
||||||
|
|
||||||
|
states.media_parens = function(type, stream, state) {
|
||||||
|
if (type == ")") return popContext(state);
|
||||||
|
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
|
||||||
|
return states.media(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.font_face_before = function(type, stream, state) {
|
||||||
|
if (type == "{")
|
||||||
|
return pushContext(state, stream, "font_face");
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.font_face = function(type, stream, state) {
|
||||||
|
if (type == "}") return popContext(state);
|
||||||
|
if (type == "word") {
|
||||||
|
if (!fontProperties.hasOwnProperty(stream.current().toLowerCase()))
|
||||||
|
override = "error";
|
||||||
|
else
|
||||||
|
override = "property";
|
||||||
|
return "maybeprop";
|
||||||
|
}
|
||||||
|
return "font_face";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.keyframes = function(type, stream, state) {
|
||||||
|
if (type == "word") { override = "variable"; return "keyframes"; }
|
||||||
|
if (type == "{") return pushContext(state, stream, "top");
|
||||||
|
return pass(type, stream, state);
|
||||||
|
};
|
||||||
|
|
||||||
|
states.at = function(type, stream, state) {
|
||||||
|
if (type == ";") return popContext(state);
|
||||||
|
if (type == "{" || type == "}") return popAndPass(type, stream, state);
|
||||||
|
if (type == "word") override = "tag";
|
||||||
|
else if (type == "hash") override = "builtin";
|
||||||
|
return "at";
|
||||||
|
};
|
||||||
|
|
||||||
|
states.interpolation = function(type, stream, state) {
|
||||||
|
if (type == "}") return popContext(state);
|
||||||
|
if (type == "{" || type == ";") return popAndPass(type, stream, state);
|
||||||
|
if (type != "variable") override = "error";
|
||||||
|
return "interpolation";
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function(base) {
|
||||||
|
return {tokenize: null,
|
||||||
|
state: "top",
|
||||||
|
context: new Context("top", base || 0, null)};
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (!state.tokenize && stream.eatSpace()) return null;
|
||||||
|
var style = (state.tokenize || tokenBase)(stream, state);
|
||||||
|
if (style && typeof style == "object") {
|
||||||
|
type = style[1];
|
||||||
|
style = style[0];
|
||||||
|
}
|
||||||
|
override = style;
|
||||||
|
state.state = states[state.state](type, stream, state);
|
||||||
|
return override;
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
var cx = state.context, ch = textAfter && textAfter.charAt(0);
|
||||||
|
var indent = cx.indent;
|
||||||
|
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
|
||||||
|
if (cx.prev &&
|
||||||
|
(ch == "}" && (cx.type == "block" || cx.type == "top" || cx.type == "interpolation" || cx.type == "font_face") ||
|
||||||
|
ch == ")" && (cx.type == "parens" || cx.type == "media_parens") ||
|
||||||
|
ch == "{" && (cx.type == "at" || cx.type == "media"))) {
|
||||||
|
indent = cx.indent - indentUnit;
|
||||||
|
cx = cx.prev;
|
||||||
|
}
|
||||||
|
return indent;
|
||||||
|
},
|
||||||
|
|
||||||
|
electricChars: "}",
|
||||||
|
blockCommentStart: "/*",
|
||||||
|
blockCommentEnd: "*/",
|
||||||
|
fold: "brace"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function keySet(array) {
|
||||||
|
var keys = {};
|
||||||
|
for (var i = 0; i < array.length; ++i) {
|
||||||
|
keys[array[i]] = true;
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaTypes_ = [
|
||||||
|
"all", "aural", "braille", "handheld", "print", "projection", "screen",
|
||||||
|
"tty", "tv", "embossed"
|
||||||
|
], mediaTypes = keySet(mediaTypes_);
|
||||||
|
|
||||||
|
var mediaFeatures_ = [
|
||||||
|
"width", "min-width", "max-width", "height", "min-height", "max-height",
|
||||||
|
"device-width", "min-device-width", "max-device-width", "device-height",
|
||||||
|
"min-device-height", "max-device-height", "aspect-ratio",
|
||||||
|
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
|
||||||
|
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
|
||||||
|
"max-color", "color-index", "min-color-index", "max-color-index",
|
||||||
|
"monochrome", "min-monochrome", "max-monochrome", "resolution",
|
||||||
|
"min-resolution", "max-resolution", "scan", "grid"
|
||||||
|
], mediaFeatures = keySet(mediaFeatures_);
|
||||||
|
|
||||||
|
var propertyKeywords_ = [
|
||||||
|
"align-content", "align-items", "align-self", "alignment-adjust",
|
||||||
|
"alignment-baseline", "anchor-point", "animation", "animation-delay",
|
||||||
|
"animation-direction", "animation-duration", "animation-fill-mode",
|
||||||
|
"animation-iteration-count", "animation-name", "animation-play-state",
|
||||||
|
"animation-timing-function", "appearance", "azimuth", "backface-visibility",
|
||||||
|
"background", "background-attachment", "background-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",
|
||||||
|
"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", "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-position", "grid-auto-rows", "grid-column", "grid-column-end",
|
||||||
|
"grid-column-start", "grid-row", "grid-row-end", "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", "left", "letter-spacing",
|
||||||
|
"line-break", "line-height", "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",
|
||||||
|
"marker-offset", "marks", "marquee-direction", "marquee-loop",
|
||||||
|
"marquee-play-count", "marquee-speed", "marquee-style", "max-height",
|
||||||
|
"max-width", "min-height", "min-width", "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", "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",
|
||||||
|
"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",
|
||||||
|
"vertical-align", "visibility", "voice-balance", "voice-duration",
|
||||||
|
"voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
|
||||||
|
"voice-volume", "volume", "white-space", "widows", "width", "word-break",
|
||||||
|
"word-spacing", "word-wrap", "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",
|
||||||
|
"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"
|
||||||
|
], propertyKeywords = keySet(propertyKeywords_);
|
||||||
|
|
||||||
|
var nonStandardPropertyKeywords_ = [
|
||||||
|
"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"
|
||||||
|
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
|
||||||
|
|
||||||
|
var colorKeywords_ = [
|
||||||
|
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
|
||||||
|
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
|
||||||
|
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
|
||||||
|
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
|
||||||
|
"darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
|
||||||
|
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
|
||||||
|
"darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
|
||||||
|
"deeppink", "deepskyblue", "dimgray", "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",
|
||||||
|
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
|
||||||
|
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
|
||||||
|
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
|
||||||
|
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
|
||||||
|
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
|
||||||
|
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
|
||||||
|
"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",
|
||||||
|
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
|
||||||
|
"whitesmoke", "yellow", "yellowgreen"
|
||||||
|
], colorKeywords = keySet(colorKeywords_);
|
||||||
|
|
||||||
|
var valueKeywords_ = [
|
||||||
|
"above", "absolute", "activeborder", "activecaption", "afar",
|
||||||
|
"after-white-space", "ahead", "alias", "all", "all-scroll", "alternate",
|
||||||
|
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
|
||||||
|
"arabic-indic", "armenian", "asterisks", "auto", "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", "button", "button-bevel",
|
||||||
|
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian",
|
||||||
|
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
|
||||||
|
"cell", "center", "checkbox", "circle", "cjk-earthly-branch",
|
||||||
|
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
|
||||||
|
"col-resize", "collapse", "column", "compact", "condensed", "contain", "content",
|
||||||
|
"content-box", "context-menu", "continuous", "copy", "cover", "crop",
|
||||||
|
"cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal",
|
||||||
|
"decimal-leading-zero", "default", "default-button", "destination-atop",
|
||||||
|
"destination-in", "destination-out", "destination-over", "devanagari",
|
||||||
|
"disc", "discard", "document", "dot-dash", "dot-dot-dash", "dotted",
|
||||||
|
"double", "down", "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",
|
||||||
|
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
|
||||||
|
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
|
||||||
|
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
|
||||||
|
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et",
|
||||||
|
"ethiopic-halehame-tig", "ew-resize", "expanded", "extra-condensed",
|
||||||
|
"extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes",
|
||||||
|
"forwards", "from", "geometricPrecision", "georgian", "graytext", "groove",
|
||||||
|
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew",
|
||||||
|
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
|
||||||
|
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
|
||||||
|
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
|
||||||
|
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
|
||||||
|
"inline-block", "inline-table", "inset", "inside", "intrinsic", "invert",
|
||||||
|
"italic", "justify", "kannada", "katakana", "katakana-iroha", "keep-all", "khmer",
|
||||||
|
"landscape", "lao", "large", "larger", "left", "level", "lighter",
|
||||||
|
"line-through", "linear", "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", "malayalam", "match",
|
||||||
|
"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", "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", "nw-resize", "nwse-resize", "oblique", "octal", "open-quote",
|
||||||
|
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
|
||||||
|
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
|
||||||
|
"painted", "page", "paused", "persian", "plus-darker", "plus-lighter", "pointer",
|
||||||
|
"polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "push-button",
|
||||||
|
"radio", "read-only", "read-write", "read-write-plaintext-only", "rectangle", "region",
|
||||||
|
"relative", "repeat", "repeat-x", "repeat-y", "reset", "reverse", "rgb", "rgba",
|
||||||
|
"ridge", "right", "round", "row-resize", "rtl", "run-in", "running",
|
||||||
|
"s-resize", "sans-serif", "scroll", "scrollbar", "se-resize", "searchfield",
|
||||||
|
"searchfield-cancel-button", "searchfield-decoration",
|
||||||
|
"searchfield-results-button", "searchfield-results-decoration",
|
||||||
|
"semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
|
||||||
|
"single", "skip-white-space", "slide", "slider-horizontal",
|
||||||
|
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
|
||||||
|
"small", "small-caps", "small-caption", "smaller", "solid", "somali",
|
||||||
|
"source-atop", "source-in", "source-out", "source-over", "space", "square",
|
||||||
|
"square-button", "start", "static", "status-bar", "stretch", "stroke",
|
||||||
|
"sub", "subpixel-antialiased", "super", "sw-resize", "table",
|
||||||
|
"table-caption", "table-cell", "table-column", "table-column-group",
|
||||||
|
"table-footer-group", "table-header-group", "table-row", "table-row-group",
|
||||||
|
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
|
||||||
|
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
|
||||||
|
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
|
||||||
|
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
|
||||||
|
"transparent", "ultra-condensed", "ultra-expanded", "underline", "up",
|
||||||
|
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
|
||||||
|
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
|
||||||
|
"vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
|
||||||
|
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
|
||||||
|
"window", "windowframe", "windowtext", "x-large", "x-small", "xor",
|
||||||
|
"xx-large", "xx-small"
|
||||||
|
], valueKeywords = keySet(valueKeywords_);
|
||||||
|
|
||||||
|
var fontProperties_ = [
|
||||||
|
"font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
|
||||||
|
"font-stretch", "font-weight", "font-style"
|
||||||
|
], fontProperties = keySet(fontProperties_);
|
||||||
|
|
||||||
|
var allWords = mediaTypes_.concat(mediaFeatures_).concat(propertyKeywords_)
|
||||||
|
.concat(nonStandardPropertyKeywords_).concat(colorKeywords_).concat(valueKeywords_);
|
||||||
|
CodeMirror.registerHelper("hintWords", "css", allWords);
|
||||||
|
|
||||||
|
function tokenCComment(stream, state) {
|
||||||
|
var maybeEnd = false, ch;
|
||||||
|
while ((ch = stream.next()) != null) {
|
||||||
|
if (maybeEnd && ch == "/") {
|
||||||
|
state.tokenize = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maybeEnd = (ch == "*");
|
||||||
|
}
|
||||||
|
return ["comment", "comment"];
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenSGMLComment(stream, state) {
|
||||||
|
if (stream.skipTo("-->")) {
|
||||||
|
stream.match("-->");
|
||||||
|
state.tokenize = null;
|
||||||
|
} else {
|
||||||
|
stream.skipToEnd();
|
||||||
|
}
|
||||||
|
return ["comment", "comment"];
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/css", {
|
||||||
|
mediaTypes: mediaTypes,
|
||||||
|
mediaFeatures: mediaFeatures,
|
||||||
|
propertyKeywords: propertyKeywords,
|
||||||
|
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||||
|
colorKeywords: colorKeywords,
|
||||||
|
valueKeywords: valueKeywords,
|
||||||
|
fontProperties: fontProperties,
|
||||||
|
tokenHooks: {
|
||||||
|
"<": function(stream, state) {
|
||||||
|
if (!stream.match("!--")) return false;
|
||||||
|
state.tokenize = tokenSGMLComment;
|
||||||
|
return tokenSGMLComment(stream, state);
|
||||||
|
},
|
||||||
|
"/": function(stream, state) {
|
||||||
|
if (!stream.eat("*")) return false;
|
||||||
|
state.tokenize = tokenCComment;
|
||||||
|
return tokenCComment(stream, state);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "css"
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/x-scss", {
|
||||||
|
mediaTypes: mediaTypes,
|
||||||
|
mediaFeatures: mediaFeatures,
|
||||||
|
propertyKeywords: propertyKeywords,
|
||||||
|
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||||
|
colorKeywords: colorKeywords,
|
||||||
|
valueKeywords: valueKeywords,
|
||||||
|
fontProperties: fontProperties,
|
||||||
|
allowNested: true,
|
||||||
|
tokenHooks: {
|
||||||
|
"/": function(stream, state) {
|
||||||
|
if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ["comment", "comment"];
|
||||||
|
} else if (stream.eat("*")) {
|
||||||
|
state.tokenize = tokenCComment;
|
||||||
|
return tokenCComment(stream, state);
|
||||||
|
} else {
|
||||||
|
return ["operator", "operator"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
":": function(stream) {
|
||||||
|
if (stream.match(/\s*\{/))
|
||||||
|
return [null, "{"];
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
"$": function(stream) {
|
||||||
|
stream.match(/^[\w-]+/);
|
||||||
|
if (stream.match(/^\s*:/, false))
|
||||||
|
return ["variable-2", "variable-definition"];
|
||||||
|
return ["variable-2", "variable"];
|
||||||
|
},
|
||||||
|
"#": function(stream) {
|
||||||
|
if (!stream.eat("{")) return false;
|
||||||
|
return [null, "interpolation"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "css",
|
||||||
|
helperType: "scss"
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/x-less", {
|
||||||
|
mediaTypes: mediaTypes,
|
||||||
|
mediaFeatures: mediaFeatures,
|
||||||
|
propertyKeywords: propertyKeywords,
|
||||||
|
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
|
||||||
|
colorKeywords: colorKeywords,
|
||||||
|
valueKeywords: valueKeywords,
|
||||||
|
fontProperties: fontProperties,
|
||||||
|
allowNested: true,
|
||||||
|
tokenHooks: {
|
||||||
|
"/": function(stream, state) {
|
||||||
|
if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ["comment", "comment"];
|
||||||
|
} else if (stream.eat("*")) {
|
||||||
|
state.tokenize = tokenCComment;
|
||||||
|
return tokenCComment(stream, state);
|
||||||
|
} else {
|
||||||
|
return ["operator", "operator"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@": function(stream) {
|
||||||
|
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
|
||||||
|
stream.eatWhile(/[\w\\\-]/);
|
||||||
|
if (stream.match(/^\s*:/, false))
|
||||||
|
return ["variable-2", "variable-definition"];
|
||||||
|
return ["variable-2", "variable"];
|
||||||
|
},
|
||||||
|
"&": function() {
|
||||||
|
return ["atom", "atom"];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "css",
|
||||||
|
helperType: "less"
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,86 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("htmlembedded", function(config, parserConfig) {
|
||||||
|
|
||||||
|
//config settings
|
||||||
|
var scriptStartRegex = parserConfig.scriptStartRegex || /^<%/i,
|
||||||
|
scriptEndRegex = parserConfig.scriptEndRegex || /^%>/i;
|
||||||
|
|
||||||
|
//inner modes
|
||||||
|
var scriptingMode, htmlMixedMode;
|
||||||
|
|
||||||
|
//tokenizer when in html mode
|
||||||
|
function htmlDispatch(stream, state) {
|
||||||
|
if (stream.match(scriptStartRegex, false)) {
|
||||||
|
state.token=scriptingDispatch;
|
||||||
|
return scriptingMode.token(stream, state.scriptState);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return htmlMixedMode.token(stream, state.htmlState);
|
||||||
|
}
|
||||||
|
|
||||||
|
//tokenizer when in scripting mode
|
||||||
|
function scriptingDispatch(stream, state) {
|
||||||
|
if (stream.match(scriptEndRegex, false)) {
|
||||||
|
state.token=htmlDispatch;
|
||||||
|
return htmlMixedMode.token(stream, state.htmlState);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return scriptingMode.token(stream, state.scriptState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function() {
|
||||||
|
scriptingMode = scriptingMode || CodeMirror.getMode(config, parserConfig.scriptingModeSpec);
|
||||||
|
htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed");
|
||||||
|
return {
|
||||||
|
token : parserConfig.startOpen ? scriptingDispatch : htmlDispatch,
|
||||||
|
htmlState : CodeMirror.startState(htmlMixedMode),
|
||||||
|
scriptState : CodeMirror.startState(scriptingMode)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
return state.token(stream, state);
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
if (state.token == htmlDispatch)
|
||||||
|
return htmlMixedMode.indent(state.htmlState, textAfter);
|
||||||
|
else if (scriptingMode.indent)
|
||||||
|
return scriptingMode.indent(state.scriptState, textAfter);
|
||||||
|
},
|
||||||
|
|
||||||
|
copyState: function(state) {
|
||||||
|
return {
|
||||||
|
token : state.token,
|
||||||
|
htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState),
|
||||||
|
scriptState : CodeMirror.copyState(scriptingMode, state.scriptState)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
innerMode: function(state) {
|
||||||
|
if (state.token == scriptingDispatch) return {state: state.scriptState, mode: scriptingMode};
|
||||||
|
else return {state: state.htmlState, mode: htmlMixedMode};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, "htmlmixed");
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("application/x-ejs", { name: "htmlembedded", scriptingModeSpec:"javascript"});
|
||||||
|
CodeMirror.defineMIME("application/x-aspx", { name: "htmlembedded", scriptingModeSpec:"text/x-csharp"});
|
||||||
|
CodeMirror.defineMIME("application/x-jsp", { name: "htmlembedded", scriptingModeSpec:"text/x-java"});
|
||||||
|
CodeMirror.defineMIME("application/x-erb", { name: "htmlembedded", scriptingModeSpec:"ruby"});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,121 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("htmlmixed", function(config, parserConfig) {
|
||||||
|
var htmlMode = CodeMirror.getMode(config, {name: "xml",
|
||||||
|
htmlMode: true,
|
||||||
|
multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
|
||||||
|
multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag});
|
||||||
|
var cssMode = CodeMirror.getMode(config, "css");
|
||||||
|
|
||||||
|
var scriptTypes = [], scriptTypesConf = parserConfig && parserConfig.scriptTypes;
|
||||||
|
scriptTypes.push({matches: /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i,
|
||||||
|
mode: CodeMirror.getMode(config, "javascript")});
|
||||||
|
if (scriptTypesConf) for (var i = 0; i < scriptTypesConf.length; ++i) {
|
||||||
|
var conf = scriptTypesConf[i];
|
||||||
|
scriptTypes.push({matches: conf.matches, mode: conf.mode && CodeMirror.getMode(config, conf.mode)});
|
||||||
|
}
|
||||||
|
scriptTypes.push({matches: /./,
|
||||||
|
mode: CodeMirror.getMode(config, "text/plain")});
|
||||||
|
|
||||||
|
function html(stream, state) {
|
||||||
|
var tagName = state.htmlState.tagName;
|
||||||
|
if (tagName) tagName = tagName.toLowerCase();
|
||||||
|
var style = htmlMode.token(stream, state.htmlState);
|
||||||
|
if (tagName == "script" && /\btag\b/.test(style) && stream.current() == ">") {
|
||||||
|
// Script block: mode to change to depends on type attribute
|
||||||
|
var scriptType = stream.string.slice(Math.max(0, stream.pos - 100), stream.pos).match(/\btype\s*=\s*("[^"]+"|'[^']+'|\S+)[^<]*$/i);
|
||||||
|
scriptType = scriptType ? scriptType[1] : "";
|
||||||
|
if (scriptType && /[\"\']/.test(scriptType.charAt(0))) scriptType = scriptType.slice(1, scriptType.length - 1);
|
||||||
|
for (var i = 0; i < scriptTypes.length; ++i) {
|
||||||
|
var tp = scriptTypes[i];
|
||||||
|
if (typeof tp.matches == "string" ? scriptType == tp.matches : tp.matches.test(scriptType)) {
|
||||||
|
if (tp.mode) {
|
||||||
|
state.token = script;
|
||||||
|
state.localMode = tp.mode;
|
||||||
|
state.localState = tp.mode.startState && tp.mode.startState(htmlMode.indent(state.htmlState, ""));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tagName == "style" && /\btag\b/.test(style) && stream.current() == ">") {
|
||||||
|
state.token = css;
|
||||||
|
state.localMode = cssMode;
|
||||||
|
state.localState = cssMode.startState(htmlMode.indent(state.htmlState, ""));
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
function maybeBackup(stream, pat, style) {
|
||||||
|
var cur = stream.current();
|
||||||
|
var close = cur.search(pat), m;
|
||||||
|
if (close > -1) stream.backUp(cur.length - close);
|
||||||
|
else if (m = cur.match(/<\/?$/)) {
|
||||||
|
stream.backUp(cur.length);
|
||||||
|
if (!stream.match(pat, false)) stream.match(cur);
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
function script(stream, state) {
|
||||||
|
if (stream.match(/^<\/\s*script\s*>/i, false)) {
|
||||||
|
state.token = html;
|
||||||
|
state.localState = state.localMode = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return maybeBackup(stream, /<\/\s*script\s*>/,
|
||||||
|
state.localMode.token(stream, state.localState));
|
||||||
|
}
|
||||||
|
function css(stream, state) {
|
||||||
|
if (stream.match(/^<\/\s*style\s*>/i, false)) {
|
||||||
|
state.token = html;
|
||||||
|
state.localState = state.localMode = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return maybeBackup(stream, /<\/\s*style\s*>/,
|
||||||
|
cssMode.token(stream, state.localState));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function() {
|
||||||
|
var state = htmlMode.startState();
|
||||||
|
return {token: html, localMode: null, localState: null, htmlState: state};
|
||||||
|
},
|
||||||
|
|
||||||
|
copyState: function(state) {
|
||||||
|
if (state.localState)
|
||||||
|
var local = CodeMirror.copyState(state.localMode, state.localState);
|
||||||
|
return {token: state.token, localMode: state.localMode, localState: local,
|
||||||
|
htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
return state.token(stream, state);
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
if (!state.localMode || /^\s*<\//.test(textAfter))
|
||||||
|
return htmlMode.indent(state.htmlState, textAfter);
|
||||||
|
else if (state.localMode.indent)
|
||||||
|
return state.localMode.indent(state.localState, textAfter);
|
||||||
|
else
|
||||||
|
return CodeMirror.Pass;
|
||||||
|
},
|
||||||
|
|
||||||
|
innerMode: function(state) {
|
||||||
|
return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, "xml", "javascript", "css");
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/html", "htmlmixed");
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,930 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||||
|
var indentUnit = config.indentUnit;
|
||||||
|
var statementIndent = parserConfig.statementIndent;
|
||||||
|
var jsonldMode = parserConfig.jsonld;
|
||||||
|
var jsonMode = parserConfig.json || jsonldMode;
|
||||||
|
var isTS = parserConfig.typescript;
|
||||||
|
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
|
||||||
|
|
||||||
|
// Tokenizer
|
||||||
|
|
||||||
|
var keywords = function(){
|
||||||
|
function kw(type) {return {type: type, style: "keyword"};}
|
||||||
|
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), D = kw("keyword d");
|
||||||
|
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
||||||
|
|
||||||
|
return {
|
||||||
|
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||||
|
"return": D, "break": D, "continue": D, "new": kw("new"), "delete": C, "void": C, "throw": C,
|
||||||
|
"debugger": kw("debugger"), "var": kw("var"), "const": kw("var"), "let": kw("var"),
|
||||||
|
"function": kw("function"), "catch": kw("catch"),
|
||||||
|
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
||||||
|
"in": operator, "typeof": operator, "instanceof": operator,
|
||||||
|
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
|
||||||
|
"this": kw("this"), "class": kw("class"), "super": kw("atom"),
|
||||||
|
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
|
||||||
|
"await": C
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
var isOperatorChar = /[+\-*&%=<>!?|~^@]/;
|
||||||
|
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
|
||||||
|
|
||||||
|
function readRegexp(stream) {
|
||||||
|
var escaped = false, next, inSet = false;
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (!escaped) {
|
||||||
|
if (next == "/" && !inSet) return;
|
||||||
|
if (next == "[") inSet = true;
|
||||||
|
else if (inSet && next == "]") inSet = false;
|
||||||
|
}
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used as scratch variables to communicate multiple values without
|
||||||
|
// consing up tons of objects.
|
||||||
|
var type, content;
|
||||||
|
function ret(tp, style, cont) {
|
||||||
|
type = tp; content = cont;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
function tokenBase(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == '"' || ch == "'") {
|
||||||
|
state.tokenize = tokenString(ch);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else if (ch == "." && stream.match(/^\d[\d_]*(?:[eE][+\-]?[\d_]+)?/)) {
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (ch == "." && stream.match("..")) {
|
||||||
|
return ret("spread", "meta");
|
||||||
|
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
||||||
|
return ret(ch);
|
||||||
|
} else if (ch == "=" && stream.eat(">")) {
|
||||||
|
return ret("=>", "operator");
|
||||||
|
} else if (ch == "0" && stream.match(/^(?:x[\dA-Fa-f_]+|o[0-7_]+|b[01_]+)n?/)) {
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (/\d/.test(ch)) {
|
||||||
|
stream.match(/^[\d_]*(?:n|(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)?/);
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (ch == "/") {
|
||||||
|
if (stream.eat("*")) {
|
||||||
|
state.tokenize = tokenComment;
|
||||||
|
return tokenComment(stream, state);
|
||||||
|
} else if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("comment", "comment");
|
||||||
|
} else if (expressionAllowed(stream, state, 1)) {
|
||||||
|
readRegexp(stream);
|
||||||
|
stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/);
|
||||||
|
return ret("regexp", "string-2");
|
||||||
|
} else {
|
||||||
|
stream.eat("=");
|
||||||
|
return ret("operator", "operator", stream.current());
|
||||||
|
}
|
||||||
|
} else if (ch == "`") {
|
||||||
|
state.tokenize = tokenQuasi;
|
||||||
|
return tokenQuasi(stream, state);
|
||||||
|
} else if (ch == "#") {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("error", "error");
|
||||||
|
} else if (ch == "<" && stream.match("!--") || ch == "-" && stream.match("->")) {
|
||||||
|
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)) {
|
||||||
|
stream.eat(ch)
|
||||||
|
if (ch == ">") stream.eat(ch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret("operator", "operator", stream.current());
|
||||||
|
} else if (wordRE.test(ch)) {
|
||||||
|
stream.eatWhile(wordRE);
|
||||||
|
var word = stream.current()
|
||||||
|
if (state.lastType != ".") {
|
||||||
|
if (keywords.propertyIsEnumerable(word)) {
|
||||||
|
var kw = keywords[word]
|
||||||
|
return ret(kw.type, kw.style, word)
|
||||||
|
}
|
||||||
|
if (word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false))
|
||||||
|
return ret("async", "keyword", word)
|
||||||
|
}
|
||||||
|
return ret("variable", "variable", word)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenString(quote) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var escaped = false, next;
|
||||||
|
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
return ret("jsonld-keyword", "meta");
|
||||||
|
}
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (next == quote && !escaped) break;
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
if (!escaped) state.tokenize = tokenBase;
|
||||||
|
return ret("string", "string");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenComment(stream, state) {
|
||||||
|
var maybeEnd = false, ch;
|
||||||
|
while (ch = stream.next()) {
|
||||||
|
if (ch == "/" && maybeEnd) {
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maybeEnd = (ch == "*");
|
||||||
|
}
|
||||||
|
return ret("comment", "comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenQuasi(stream, state) {
|
||||||
|
var escaped = false, next;
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
return ret("quasi", "string-2", stream.current());
|
||||||
|
}
|
||||||
|
|
||||||
|
var brackets = "([{}])";
|
||||||
|
// This is a crude lookahead trick to try and notice that we're
|
||||||
|
// parsing the argument patterns for a fat-arrow function before we
|
||||||
|
// actually hit the arrow token. It only works if the arrow is on
|
||||||
|
// the same line as the arguments and there's no strange noise
|
||||||
|
// (comments) in between. Fallback is to only notice when we hit the
|
||||||
|
// arrow, and not declare the arguments as locals for the arrow
|
||||||
|
// body.
|
||||||
|
function findFatArrow(stream, state) {
|
||||||
|
if (state.fatArrowAt) state.fatArrowAt = null;
|
||||||
|
var arrow = stream.string.indexOf("=>", stream.start);
|
||||||
|
if (arrow < 0) return;
|
||||||
|
|
||||||
|
if (isTS) { // Try to skip TypeScript return type declarations after the arguments
|
||||||
|
var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
|
||||||
|
if (m) arrow = m.index
|
||||||
|
}
|
||||||
|
|
||||||
|
var depth = 0, sawSomething = false;
|
||||||
|
for (var pos = arrow - 1; pos >= 0; --pos) {
|
||||||
|
var ch = stream.string.charAt(pos);
|
||||||
|
var bracket = brackets.indexOf(ch);
|
||||||
|
if (bracket >= 0 && bracket < 3) {
|
||||||
|
if (!depth) { ++pos; break; }
|
||||||
|
if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
|
||||||
|
} else if (bracket >= 3 && bracket < 6) {
|
||||||
|
++depth;
|
||||||
|
} else if (wordRE.test(ch)) {
|
||||||
|
sawSomething = true;
|
||||||
|
} else if (/["'\/`]/.test(ch)) {
|
||||||
|
for (;; --pos) {
|
||||||
|
if (pos == 0) return
|
||||||
|
var next = stream.string.charAt(pos - 1)
|
||||||
|
if (next == ch && stream.string.charAt(pos - 2) != "\\") { pos--; break }
|
||||||
|
}
|
||||||
|
} else if (sawSomething && !depth) {
|
||||||
|
++pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sawSomething && !depth) state.fatArrowAt = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
|
||||||
|
|
||||||
|
function JSLexical(indented, column, type, align, prev, info) {
|
||||||
|
this.indented = indented;
|
||||||
|
this.column = column;
|
||||||
|
this.type = type;
|
||||||
|
this.prev = prev;
|
||||||
|
this.info = info;
|
||||||
|
if (align != null) this.align = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inScope(state, varname) {
|
||||||
|
for (var v = state.localVars; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
for (var cx = state.context; cx; cx = cx.prev) {
|
||||||
|
for (var v = cx.vars; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJS(state, style, type, content, stream) {
|
||||||
|
var cc = state.cc;
|
||||||
|
// Communicate our context to the combinators.
|
||||||
|
// (Less wasteful than consing up a hundred closures on every call.)
|
||||||
|
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
|
||||||
|
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = true;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
|
||||||
|
if (combinator(type, content)) {
|
||||||
|
while(cc.length && cc[cc.length - 1].lex)
|
||||||
|
cc.pop()();
|
||||||
|
if (cx.marked) return cx.marked;
|
||||||
|
if (type == "variable" && inScope(state, content)) return "variable-2";
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinator utils
|
||||||
|
|
||||||
|
var cx = {state: null, column: null, marked: null, cc: null};
|
||||||
|
function pass() {
|
||||||
|
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
|
||||||
|
}
|
||||||
|
function cont() {
|
||||||
|
pass.apply(null, arguments);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function inList(name, list) {
|
||||||
|
for (var v = list; v; v = v.next) if (v.name == name) return true
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function register(varname) {
|
||||||
|
var state = cx.state;
|
||||||
|
cx.marked = "def";
|
||||||
|
if (state.context) {
|
||||||
|
if (state.lexical.info == "var" && state.context && state.context.block) {
|
||||||
|
// FIXME function decls are also not block scoped
|
||||||
|
var newContext = registerVarScoped(varname, state.context)
|
||||||
|
if (newContext != null) {
|
||||||
|
state.context = newContext
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if (!inList(varname, state.localVars)) {
|
||||||
|
state.localVars = new Var(varname, state.localVars)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fall through means this is global
|
||||||
|
if (parserConfig.globalVars && !inList(varname, state.globalVars))
|
||||||
|
state.globalVars = new Var(varname, state.globalVars)
|
||||||
|
}
|
||||||
|
function registerVarScoped(varname, context) {
|
||||||
|
if (!context) {
|
||||||
|
return null
|
||||||
|
} else if (context.block) {
|
||||||
|
var inner = registerVarScoped(varname, context.prev)
|
||||||
|
if (!inner) return null
|
||||||
|
if (inner == context.prev) return context
|
||||||
|
return new Context(inner, context.vars, true)
|
||||||
|
} else if (inList(varname, context.vars)) {
|
||||||
|
return context
|
||||||
|
} else {
|
||||||
|
return new Context(context.prev, new Var(varname, context.vars), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isModifier(name) {
|
||||||
|
return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinators
|
||||||
|
|
||||||
|
function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block }
|
||||||
|
function Var(name, next) { this.name = name; this.next = next }
|
||||||
|
|
||||||
|
var defaultVars = new Var("this", new Var("arguments", null))
|
||||||
|
function pushcontext() {
|
||||||
|
cx.state.context = new Context(cx.state.context, cx.state.localVars, false)
|
||||||
|
cx.state.localVars = defaultVars
|
||||||
|
}
|
||||||
|
function pushblockcontext() {
|
||||||
|
cx.state.context = new Context(cx.state.context, cx.state.localVars, true)
|
||||||
|
cx.state.localVars = null
|
||||||
|
}
|
||||||
|
function popcontext() {
|
||||||
|
cx.state.localVars = cx.state.context.vars
|
||||||
|
cx.state.context = cx.state.context.prev
|
||||||
|
}
|
||||||
|
popcontext.lex = true
|
||||||
|
function pushlex(type, info) {
|
||||||
|
var result = function() {
|
||||||
|
var state = cx.state, indent = state.indented;
|
||||||
|
if (state.lexical.type == "stat") indent = state.lexical.indented;
|
||||||
|
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
|
||||||
|
indent = outer.indented;
|
||||||
|
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
|
||||||
|
};
|
||||||
|
result.lex = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function poplex() {
|
||||||
|
var state = cx.state;
|
||||||
|
if (state.lexical.prev) {
|
||||||
|
if (state.lexical.type == ")")
|
||||||
|
state.indented = state.lexical.indented;
|
||||||
|
state.lexical = state.lexical.prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poplex.lex = true;
|
||||||
|
|
||||||
|
function expect(wanted) {
|
||||||
|
function exp(type) {
|
||||||
|
if (type == wanted) return cont();
|
||||||
|
else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass();
|
||||||
|
else return cont(exp);
|
||||||
|
};
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function statement(type, value) {
|
||||||
|
if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex);
|
||||||
|
if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
|
||||||
|
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
||||||
|
if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex);
|
||||||
|
if (type == "debugger") return cont(expect(";"));
|
||||||
|
if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext);
|
||||||
|
if (type == ";") return cont();
|
||||||
|
if (type == "if") {
|
||||||
|
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
|
||||||
|
cx.state.cc.pop()();
|
||||||
|
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 == "class" || (isTS && value == "interface")) {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
return cont(pushlex("form", type == "class" ? type : value), className, poplex)
|
||||||
|
}
|
||||||
|
if (type == "variable") {
|
||||||
|
if (isTS && value == "declare") {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
return cont(statement)
|
||||||
|
} else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
if (value == "enum") return cont(enumdef);
|
||||||
|
else if (value == "type") return cont(typename, expect("operator"), typeexpr, expect(";"));
|
||||||
|
else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex)
|
||||||
|
} else if (isTS && value == "namespace") {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
return cont(pushlex("form"), expression, statement, poplex)
|
||||||
|
} else if (isTS && value == "abstract") {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
return cont(statement)
|
||||||
|
} else {
|
||||||
|
return cont(pushlex("stat"), maybelabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext,
|
||||||
|
block, poplex, poplex, popcontext);
|
||||||
|
if (type == "case") return cont(expression, expect(":"));
|
||||||
|
if (type == "default") return cont(expect(":"));
|
||||||
|
if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext);
|
||||||
|
if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
|
||||||
|
if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
|
||||||
|
if (type == "async") return cont(statement)
|
||||||
|
if (value == "@") return cont(expression, statement)
|
||||||
|
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function maybeCatchBinding(type) {
|
||||||
|
if (type == "(") return cont(funarg, expect(")"))
|
||||||
|
}
|
||||||
|
function expression(type, value) {
|
||||||
|
return expressionInner(type, value, false);
|
||||||
|
}
|
||||||
|
function expressionNoComma(type, value) {
|
||||||
|
return expressionInner(type, value, true);
|
||||||
|
}
|
||||||
|
function parenExpr(type) {
|
||||||
|
if (type != "(") return pass()
|
||||||
|
return cont(pushlex(")"), expression, expect(")"), poplex)
|
||||||
|
}
|
||||||
|
function expressionInner(type, value, noComma) {
|
||||||
|
if (cx.state.fatArrowAt == cx.stream.start) {
|
||||||
|
var body = noComma ? arrowBodyNoComma : arrowBody;
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext);
|
||||||
|
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
|
||||||
|
}
|
||||||
|
|
||||||
|
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
|
||||||
|
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
|
||||||
|
if (type == "function") return cont(functiondef, maybeop);
|
||||||
|
if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); }
|
||||||
|
if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression);
|
||||||
|
if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
|
||||||
|
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
|
||||||
|
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
|
||||||
|
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) {
|
||||||
|
if (type.match(/[;\}\)\],]/)) return pass();
|
||||||
|
return pass(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybeoperatorComma(type, value) {
|
||||||
|
if (type == ",") return cont(expression);
|
||||||
|
return maybeoperatorNoComma(type, value, false);
|
||||||
|
}
|
||||||
|
function maybeoperatorNoComma(type, value, noComma) {
|
||||||
|
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
|
||||||
|
var expr = noComma == false ? expression : expressionNoComma;
|
||||||
|
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))
|
||||||
|
return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me);
|
||||||
|
if (value == "?") return cont(expression, expect(":"), expr);
|
||||||
|
return cont(expr);
|
||||||
|
}
|
||||||
|
if (type == "quasi") { return pass(quasi, me); }
|
||||||
|
if (type == ";") return;
|
||||||
|
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
|
||||||
|
if (type == ".") return cont(property, me);
|
||||||
|
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
|
||||||
|
if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) }
|
||||||
|
if (type == "regexp") {
|
||||||
|
cx.state.lastType = cx.marked = "operator"
|
||||||
|
cx.stream.backUp(cx.stream.pos - cx.stream.start - 1)
|
||||||
|
return cont(expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function quasi(type, value) {
|
||||||
|
if (type != "quasi") return pass();
|
||||||
|
if (value.slice(value.length - 2) != "${") return cont(quasi);
|
||||||
|
return cont(expression, continueQuasi);
|
||||||
|
}
|
||||||
|
function continueQuasi(type) {
|
||||||
|
if (type == "}") {
|
||||||
|
cx.marked = "string-2";
|
||||||
|
cx.state.tokenize = tokenQuasi;
|
||||||
|
return cont(quasi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function arrowBody(type) {
|
||||||
|
findFatArrow(cx.stream, cx.state);
|
||||||
|
return pass(type == "{" ? statement : expression);
|
||||||
|
}
|
||||||
|
function arrowBodyNoComma(type) {
|
||||||
|
findFatArrow(cx.stream, cx.state);
|
||||||
|
return pass(type == "{" ? statement : expressionNoComma);
|
||||||
|
}
|
||||||
|
function maybeTarget(noComma) {
|
||||||
|
return function(type) {
|
||||||
|
if (type == ".") return cont(noComma ? targetNoComma : target);
|
||||||
|
else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma)
|
||||||
|
else return pass(noComma ? expressionNoComma : expression);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function target(_, value) {
|
||||||
|
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
|
||||||
|
}
|
||||||
|
function targetNoComma(_, value) {
|
||||||
|
if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
|
||||||
|
}
|
||||||
|
function maybelabel(type) {
|
||||||
|
if (type == ":") return cont(poplex, statement);
|
||||||
|
return pass(maybeoperatorComma, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function property(type) {
|
||||||
|
if (type == "variable") {cx.marked = "property"; return cont();}
|
||||||
|
}
|
||||||
|
function objprop(type, value) {
|
||||||
|
if (type == "async") {
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(objprop);
|
||||||
|
} else if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property";
|
||||||
|
if (value == "get" || value == "set") return cont(getterSetter);
|
||||||
|
var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params
|
||||||
|
if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false)))
|
||||||
|
cx.state.fatArrowAt = cx.stream.pos + m[0].length
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (type == "number" || type == "string") {
|
||||||
|
cx.marked = jsonldMode ? "property" : (cx.style + " property");
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (type == "jsonld-keyword") {
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (isTS && isModifier(value)) {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
return cont(objprop)
|
||||||
|
} else if (type == "[") {
|
||||||
|
return cont(expression, maybetype, expect("]"), afterprop);
|
||||||
|
} else if (type == "spread") {
|
||||||
|
return cont(expressionNoComma, afterprop);
|
||||||
|
} else if (value == "*") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(objprop);
|
||||||
|
} else if (type == ":") {
|
||||||
|
return pass(afterprop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getterSetter(type) {
|
||||||
|
if (type != "variable") return pass(afterprop);
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(functiondef);
|
||||||
|
}
|
||||||
|
function afterprop(type) {
|
||||||
|
if (type == ":") return cont(expressionNoComma);
|
||||||
|
if (type == "(") return pass(functiondef);
|
||||||
|
}
|
||||||
|
function commasep(what, end, sep) {
|
||||||
|
function proceed(type, value) {
|
||||||
|
if (sep ? sep.indexOf(type) > -1 : type == ",") {
|
||||||
|
var lex = cx.state.lexical;
|
||||||
|
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
|
||||||
|
return cont(function(type, value) {
|
||||||
|
if (type == end || value == end) return pass()
|
||||||
|
return pass(what)
|
||||||
|
}, proceed);
|
||||||
|
}
|
||||||
|
if (type == end || value == end) return cont();
|
||||||
|
if (sep && sep.indexOf(";") > -1) return pass(what)
|
||||||
|
return cont(expect(end));
|
||||||
|
}
|
||||||
|
return function(type, value) {
|
||||||
|
if (type == end || value == end) return cont();
|
||||||
|
return pass(what, proceed);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function contCommasep(what, end, info) {
|
||||||
|
for (var i = 3; i < arguments.length; i++)
|
||||||
|
cx.cc.push(arguments[i]);
|
||||||
|
return cont(pushlex(end, info), commasep(what, end), poplex);
|
||||||
|
}
|
||||||
|
function block(type) {
|
||||||
|
if (type == "}") return cont();
|
||||||
|
return pass(statement, block);
|
||||||
|
}
|
||||||
|
function maybetype(type, value) {
|
||||||
|
if (isTS) {
|
||||||
|
if (type == ":") return cont(typeexpr);
|
||||||
|
if (value == "?") return cont(maybetype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function maybetypeOrIn(type, value) {
|
||||||
|
if (isTS && (type == ":" || value == "in")) return cont(typeexpr)
|
||||||
|
}
|
||||||
|
function mayberettype(type) {
|
||||||
|
if (isTS && type == ":") {
|
||||||
|
if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr)
|
||||||
|
else return cont(typeexpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function isKW(_, value) {
|
||||||
|
if (value == "is") {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
return cont()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function typeexpr(type, value) {
|
||||||
|
if (value == "keyof" || value == "typeof" || value == "infer") {
|
||||||
|
cx.marked = "keyword"
|
||||||
|
return cont(value == "typeof" ? expressionNoComma : typeexpr)
|
||||||
|
}
|
||||||
|
if (type == "variable" || value == "void") {
|
||||||
|
cx.marked = "type"
|
||||||
|
return cont(afterType)
|
||||||
|
}
|
||||||
|
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(commasep(typearg, ")"), maybeReturnType, afterType)
|
||||||
|
if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr)
|
||||||
|
}
|
||||||
|
function maybeReturnType(type) {
|
||||||
|
if (type == "=>") return cont(typeexpr)
|
||||||
|
}
|
||||||
|
function typeprop(type, value) {
|
||||||
|
if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property"
|
||||||
|
return cont(typeprop)
|
||||||
|
} else if (value == "?" || type == "number" || type == "string") {
|
||||||
|
return cont(typeprop)
|
||||||
|
} else if (type == ":") {
|
||||||
|
return cont(typeexpr)
|
||||||
|
} else if (type == "[") {
|
||||||
|
return cont(expect("variable"), maybetypeOrIn, expect("]"), typeprop)
|
||||||
|
} else if (type == "(") {
|
||||||
|
return pass(functiondecl, typeprop)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function typearg(type, value) {
|
||||||
|
if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg)
|
||||||
|
if (type == ":") return cont(typeexpr)
|
||||||
|
if (type == "spread") return cont(typearg)
|
||||||
|
return pass(typeexpr)
|
||||||
|
}
|
||||||
|
function afterType(type, value) {
|
||||||
|
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
|
||||||
|
if (value == "|" || type == "." || value == "&") return cont(typeexpr)
|
||||||
|
if (type == "[") return cont(typeexpr, expect("]"), afterType)
|
||||||
|
if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) }
|
||||||
|
if (value == "?") return cont(typeexpr, expect(":"), typeexpr)
|
||||||
|
}
|
||||||
|
function maybeTypeArgs(_, value) {
|
||||||
|
if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
|
||||||
|
}
|
||||||
|
function typeparam() {
|
||||||
|
return pass(typeexpr, maybeTypeDefault)
|
||||||
|
}
|
||||||
|
function maybeTypeDefault(_, value) {
|
||||||
|
if (value == "=") return cont(typeexpr)
|
||||||
|
}
|
||||||
|
function vardef(_, value) {
|
||||||
|
if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)}
|
||||||
|
return pass(pattern, maybetype, maybeAssign, vardefCont);
|
||||||
|
}
|
||||||
|
function pattern(type, value) {
|
||||||
|
if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) }
|
||||||
|
if (type == "variable") { register(value); return cont(); }
|
||||||
|
if (type == "spread") return cont(pattern);
|
||||||
|
if (type == "[") return contCommasep(eltpattern, "]");
|
||||||
|
if (type == "{") return contCommasep(proppattern, "}");
|
||||||
|
}
|
||||||
|
function proppattern(type, value) {
|
||||||
|
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
|
||||||
|
register(value);
|
||||||
|
return cont(maybeAssign);
|
||||||
|
}
|
||||||
|
if (type == "variable") cx.marked = "property";
|
||||||
|
if (type == "spread") return cont(pattern);
|
||||||
|
if (type == "}") return pass();
|
||||||
|
if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern);
|
||||||
|
return cont(expect(":"), pattern, maybeAssign);
|
||||||
|
}
|
||||||
|
function eltpattern() {
|
||||||
|
return pass(pattern, maybeAssign)
|
||||||
|
}
|
||||||
|
function maybeAssign(_type, value) {
|
||||||
|
if (value == "=") return cont(expressionNoComma);
|
||||||
|
}
|
||||||
|
function vardefCont(type) {
|
||||||
|
if (type == ",") return cont(vardef);
|
||||||
|
}
|
||||||
|
function maybeelse(type, value) {
|
||||||
|
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
|
||||||
|
}
|
||||||
|
function forspec(type, value) {
|
||||||
|
if (value == "await") return cont(forspec);
|
||||||
|
if (type == "(") return cont(pushlex(")"), forspec1, poplex);
|
||||||
|
}
|
||||||
|
function forspec1(type) {
|
||||||
|
if (type == "var") return cont(vardef, forspec2);
|
||||||
|
if (type == "variable") return cont(forspec2);
|
||||||
|
return pass(forspec2)
|
||||||
|
}
|
||||||
|
function forspec2(type, value) {
|
||||||
|
if (type == ")") return cont()
|
||||||
|
if (type == ";") return cont(forspec2)
|
||||||
|
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression, forspec2) }
|
||||||
|
return pass(expression, forspec2)
|
||||||
|
}
|
||||||
|
function functiondef(type, value) {
|
||||||
|
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
|
||||||
|
if (type == "variable") {register(value); return cont(functiondef);}
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext);
|
||||||
|
if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef)
|
||||||
|
}
|
||||||
|
function functiondecl(type, value) {
|
||||||
|
if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);}
|
||||||
|
if (type == "variable") {register(value); return cont(functiondecl);}
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext);
|
||||||
|
if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl)
|
||||||
|
}
|
||||||
|
function typename(type, value) {
|
||||||
|
if (type == "keyword" || type == "variable") {
|
||||||
|
cx.marked = "type"
|
||||||
|
return cont(typename)
|
||||||
|
} else if (value == "<") {
|
||||||
|
return cont(pushlex(">"), commasep(typeparam, ">"), poplex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function funarg(type, value) {
|
||||||
|
if (value == "@") cont(expression, funarg)
|
||||||
|
if (type == "spread") return cont(funarg);
|
||||||
|
if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); }
|
||||||
|
if (isTS && type == "this") return cont(maybetype, maybeAssign)
|
||||||
|
return pass(pattern, maybetype, maybeAssign);
|
||||||
|
}
|
||||||
|
function classExpression(type, value) {
|
||||||
|
// Class expressions may have an optional name.
|
||||||
|
if (type == "variable") return className(type, value);
|
||||||
|
return classNameAfter(type, value);
|
||||||
|
}
|
||||||
|
function className(type, value) {
|
||||||
|
if (type == "variable") {register(value); return cont(classNameAfter);}
|
||||||
|
}
|
||||||
|
function classNameAfter(type, value) {
|
||||||
|
if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter)
|
||||||
|
if (value == "extends" || value == "implements" || (isTS && type == ",")) {
|
||||||
|
if (value == "implements") cx.marked = "keyword";
|
||||||
|
return cont(isTS ? typeexpr : expression, classNameAfter);
|
||||||
|
}
|
||||||
|
if (type == "{") return cont(pushlex("}"), classBody, poplex);
|
||||||
|
}
|
||||||
|
function classBody(type, value) {
|
||||||
|
if (type == "async" ||
|
||||||
|
(type == "variable" &&
|
||||||
|
(value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) &&
|
||||||
|
cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(classBody);
|
||||||
|
}
|
||||||
|
if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(isTS ? classfield : functiondef, classBody);
|
||||||
|
}
|
||||||
|
if (type == "number" || type == "string") return cont(isTS ? classfield : functiondef, classBody);
|
||||||
|
if (type == "[")
|
||||||
|
return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody)
|
||||||
|
if (value == "*") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(classBody);
|
||||||
|
}
|
||||||
|
if (isTS && type == "(") return pass(functiondecl, classBody)
|
||||||
|
if (type == ";" || type == ",") return cont(classBody);
|
||||||
|
if (type == "}") return cont();
|
||||||
|
if (value == "@") return cont(expression, classBody)
|
||||||
|
}
|
||||||
|
function classfield(type, value) {
|
||||||
|
if (value == "?") return cont(classfield)
|
||||||
|
if (type == ":") return cont(typeexpr, maybeAssign)
|
||||||
|
if (value == "=") return cont(expressionNoComma)
|
||||||
|
var context = cx.state.lexical.prev, isInterface = context && context.info == "interface"
|
||||||
|
return pass(isInterface ? functiondecl : functiondef)
|
||||||
|
}
|
||||||
|
function afterExport(type, value) {
|
||||||
|
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
|
||||||
|
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
|
||||||
|
if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
|
||||||
|
return pass(statement);
|
||||||
|
}
|
||||||
|
function exportField(type, value) {
|
||||||
|
if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
|
||||||
|
if (type == "variable") return pass(expressionNoComma, exportField);
|
||||||
|
}
|
||||||
|
function afterImport(type) {
|
||||||
|
if (type == "string") return cont();
|
||||||
|
if (type == "(") return pass(expression);
|
||||||
|
return pass(importSpec, maybeMoreImports, maybeFrom);
|
||||||
|
}
|
||||||
|
function importSpec(type, value) {
|
||||||
|
if (type == "{") return contCommasep(importSpec, "}");
|
||||||
|
if (type == "variable") register(value);
|
||||||
|
if (value == "*") cx.marked = "keyword";
|
||||||
|
return cont(maybeAs);
|
||||||
|
}
|
||||||
|
function maybeMoreImports(type) {
|
||||||
|
if (type == ",") return cont(importSpec, maybeMoreImports)
|
||||||
|
}
|
||||||
|
function maybeAs(_type, value) {
|
||||||
|
if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
|
||||||
|
}
|
||||||
|
function maybeFrom(_type, value) {
|
||||||
|
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
|
||||||
|
}
|
||||||
|
function arrayLiteral(type) {
|
||||||
|
if (type == "]") return cont();
|
||||||
|
return pass(commasep(expressionNoComma, "]"));
|
||||||
|
}
|
||||||
|
function enumdef() {
|
||||||
|
return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex)
|
||||||
|
}
|
||||||
|
function enummember() {
|
||||||
|
return pass(pattern, maybeAssign);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isContinuedStatement(state, textAfter) {
|
||||||
|
return state.lastType == "operator" || state.lastType == "," ||
|
||||||
|
isOperatorChar.test(textAfter.charAt(0)) ||
|
||||||
|
/[,.]/.test(textAfter.charAt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function expressionAllowed(stream, state, backUp) {
|
||||||
|
return state.tokenize == tokenBase &&
|
||||||
|
/^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
|
||||||
|
(state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function(basecolumn) {
|
||||||
|
var state = {
|
||||||
|
tokenize: tokenBase,
|
||||||
|
lastType: "sof",
|
||||||
|
cc: [],
|
||||||
|
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
||||||
|
localVars: parserConfig.localVars,
|
||||||
|
context: parserConfig.localVars && new Context(null, null, false),
|
||||||
|
indented: basecolumn || 0
|
||||||
|
};
|
||||||
|
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
|
||||||
|
state.globalVars = parserConfig.globalVars;
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (stream.sol()) {
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = false;
|
||||||
|
state.indented = stream.indentation();
|
||||||
|
findFatArrow(stream, state);
|
||||||
|
}
|
||||||
|
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
|
||||||
|
var style = state.tokenize(stream, state);
|
||||||
|
if (type == "comment") return style;
|
||||||
|
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
|
||||||
|
return parseJS(state, style, type, content, stream);
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
if (state.tokenize == tokenComment) 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;
|
||||||
|
}
|
||||||
|
while ((lexical.type == "stat" || lexical.type == "form") &&
|
||||||
|
(firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
|
||||||
|
(top == maybeoperatorComma || top == maybeoperatorNoComma) &&
|
||||||
|
!/^[,\.=+\-*:?[\(]/.test(textAfter))))
|
||||||
|
lexical = lexical.prev;
|
||||||
|
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
|
||||||
|
lexical = lexical.prev;
|
||||||
|
var type = lexical.type, closing = firstChar == type;
|
||||||
|
|
||||||
|
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0);
|
||||||
|
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||||
|
else if (type == "form") return lexical.indented + indentUnit;
|
||||||
|
else if (type == "stat")
|
||||||
|
return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
|
||||||
|
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
|
||||||
|
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
|
||||||
|
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
|
||||||
|
else return lexical.indented + (closing ? 0 : indentUnit);
|
||||||
|
},
|
||||||
|
|
||||||
|
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
|
||||||
|
blockCommentStart: jsonMode ? null : "/*",
|
||||||
|
blockCommentEnd: jsonMode ? null : "*/",
|
||||||
|
blockCommentContinue: jsonMode ? null : " * ",
|
||||||
|
lineComment: jsonMode ? null : "//",
|
||||||
|
fold: "brace",
|
||||||
|
closeBrackets: "()[]{}''\"\"``",
|
||||||
|
|
||||||
|
helperType: jsonMode ? "json" : "javascript",
|
||||||
|
jsonldMode: jsonldMode,
|
||||||
|
jsonMode: jsonMode,
|
||||||
|
|
||||||
|
expressionAllowed: expressionAllowed,
|
||||||
|
|
||||||
|
skipExpression: function(state) {
|
||||||
|
var top = state.cc[state.cc.length - 1]
|
||||||
|
if (top == expression || top == expressionNoComma) state.cc.pop()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/javascript", "javascript");
|
||||||
|
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("text/typescript", { name: "javascript", typescript: true });
|
||||||
|
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,684 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
// TODO actually recognize syntax of TypeScript constructs
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("javascript", function(config, parserConfig) {
|
||||||
|
var indentUnit = config.indentUnit;
|
||||||
|
var statementIndent = parserConfig.statementIndent;
|
||||||
|
var jsonldMode = parserConfig.jsonld;
|
||||||
|
var jsonMode = parserConfig.json || jsonldMode;
|
||||||
|
var isTS = parserConfig.typescript;
|
||||||
|
var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
|
||||||
|
|
||||||
|
// Tokenizer
|
||||||
|
|
||||||
|
var keywords = function(){
|
||||||
|
function kw(type) {return {type: type, style: "keyword"};}
|
||||||
|
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
|
||||||
|
var operator = kw("operator"), atom = {type: "atom", style: "atom"};
|
||||||
|
|
||||||
|
var jsKeywords = {
|
||||||
|
"if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
|
||||||
|
"return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C, "debugger": C,
|
||||||
|
"var": kw("var"), "const": kw("var"), "let": kw("var"),
|
||||||
|
"function": kw("function"), "catch": kw("catch"),
|
||||||
|
"for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
|
||||||
|
"in": operator, "typeof": operator, "instanceof": operator,
|
||||||
|
"true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
|
||||||
|
"this": kw("this"), "module": kw("module"), "class": kw("class"), "super": kw("atom"),
|
||||||
|
"yield": C, "export": kw("export"), "import": kw("import"), "extends": C
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extend the 'normal' keywords with the TypeScript language extensions
|
||||||
|
if (isTS) {
|
||||||
|
var type = {type: "variable", style: "variable-3"};
|
||||||
|
var tsKeywords = {
|
||||||
|
// object-like things
|
||||||
|
"interface": kw("interface"),
|
||||||
|
"extends": kw("extends"),
|
||||||
|
"constructor": kw("constructor"),
|
||||||
|
|
||||||
|
// scope modifiers
|
||||||
|
"public": kw("public"),
|
||||||
|
"private": kw("private"),
|
||||||
|
"protected": kw("protected"),
|
||||||
|
"static": kw("static"),
|
||||||
|
|
||||||
|
// types
|
||||||
|
"string": type, "number": type, "bool": type, "any": type
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var attr in tsKeywords) {
|
||||||
|
jsKeywords[attr] = tsKeywords[attr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsKeywords;
|
||||||
|
}();
|
||||||
|
|
||||||
|
var isOperatorChar = /[+\-*&%=<>!?|~^]/;
|
||||||
|
var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
|
||||||
|
|
||||||
|
function readRegexp(stream) {
|
||||||
|
var escaped = false, next, inSet = false;
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (!escaped) {
|
||||||
|
if (next == "/" && !inSet) return;
|
||||||
|
if (next == "[") inSet = true;
|
||||||
|
else if (inSet && next == "]") inSet = false;
|
||||||
|
}
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used as scratch variables to communicate multiple values without
|
||||||
|
// consing up tons of objects.
|
||||||
|
var type, content;
|
||||||
|
function ret(tp, style, cont) {
|
||||||
|
type = tp; content = cont;
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
function tokenBase(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == '"' || ch == "'") {
|
||||||
|
state.tokenize = tokenString(ch);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (ch == "." && stream.match("..")) {
|
||||||
|
return ret("spread", "meta");
|
||||||
|
} else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
|
||||||
|
return ret(ch);
|
||||||
|
} else if (ch == "=" && stream.eat(">")) {
|
||||||
|
return ret("=>", "operator");
|
||||||
|
} else if (ch == "0" && stream.eat(/x/i)) {
|
||||||
|
stream.eatWhile(/[\da-f]/i);
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (/\d/.test(ch)) {
|
||||||
|
stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
|
||||||
|
return ret("number", "number");
|
||||||
|
} else if (ch == "/") {
|
||||||
|
if (stream.eat("*")) {
|
||||||
|
state.tokenize = tokenComment;
|
||||||
|
return tokenComment(stream, state);
|
||||||
|
} else if (stream.eat("/")) {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("comment", "comment");
|
||||||
|
} else if (state.lastType == "operator" || state.lastType == "keyword c" ||
|
||||||
|
state.lastType == "sof" || /^[\[{}\(,;:]$/.test(state.lastType)) {
|
||||||
|
readRegexp(stream);
|
||||||
|
stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
||||||
|
return ret("regexp", "string-2");
|
||||||
|
} else {
|
||||||
|
stream.eatWhile(isOperatorChar);
|
||||||
|
return ret("operator", "operator", stream.current());
|
||||||
|
}
|
||||||
|
} else if (ch == "`") {
|
||||||
|
state.tokenize = tokenQuasi;
|
||||||
|
return tokenQuasi(stream, state);
|
||||||
|
} else if (ch == "#") {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return ret("error", "error");
|
||||||
|
} else if (isOperatorChar.test(ch)) {
|
||||||
|
stream.eatWhile(isOperatorChar);
|
||||||
|
return ret("operator", "operator", stream.current());
|
||||||
|
} else if (wordRE.test(ch)) {
|
||||||
|
stream.eatWhile(wordRE);
|
||||||
|
var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
|
||||||
|
return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
|
||||||
|
ret("variable", "variable", word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenString(quote) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var escaped = false, next;
|
||||||
|
if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
return ret("jsonld-keyword", "meta");
|
||||||
|
}
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (next == quote && !escaped) break;
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
if (!escaped) state.tokenize = tokenBase;
|
||||||
|
return ret("string", "string");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenComment(stream, state) {
|
||||||
|
var maybeEnd = false, ch;
|
||||||
|
while (ch = stream.next()) {
|
||||||
|
if (ch == "/" && maybeEnd) {
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
maybeEnd = (ch == "*");
|
||||||
|
}
|
||||||
|
return ret("comment", "comment");
|
||||||
|
}
|
||||||
|
|
||||||
|
function tokenQuasi(stream, state) {
|
||||||
|
var escaped = false, next;
|
||||||
|
while ((next = stream.next()) != null) {
|
||||||
|
if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
|
||||||
|
state.tokenize = tokenBase;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
escaped = !escaped && next == "\\";
|
||||||
|
}
|
||||||
|
return ret("quasi", "string-2", stream.current());
|
||||||
|
}
|
||||||
|
|
||||||
|
var brackets = "([{}])";
|
||||||
|
// This is a crude lookahead trick to try and notice that we're
|
||||||
|
// parsing the argument patterns for a fat-arrow function before we
|
||||||
|
// actually hit the arrow token. It only works if the arrow is on
|
||||||
|
// the same line as the arguments and there's no strange noise
|
||||||
|
// (comments) in between. Fallback is to only notice when we hit the
|
||||||
|
// arrow, and not declare the arguments as locals for the arrow
|
||||||
|
// body.
|
||||||
|
function findFatArrow(stream, state) {
|
||||||
|
if (state.fatArrowAt) state.fatArrowAt = null;
|
||||||
|
var arrow = stream.string.indexOf("=>", stream.start);
|
||||||
|
if (arrow < 0) return;
|
||||||
|
|
||||||
|
var depth = 0, sawSomething = false;
|
||||||
|
for (var pos = arrow - 1; pos >= 0; --pos) {
|
||||||
|
var ch = stream.string.charAt(pos);
|
||||||
|
var bracket = brackets.indexOf(ch);
|
||||||
|
if (bracket >= 0 && bracket < 3) {
|
||||||
|
if (!depth) { ++pos; break; }
|
||||||
|
if (--depth == 0) break;
|
||||||
|
} else if (bracket >= 3 && bracket < 6) {
|
||||||
|
++depth;
|
||||||
|
} else if (wordRE.test(ch)) {
|
||||||
|
sawSomething = true;
|
||||||
|
} else if (sawSomething && !depth) {
|
||||||
|
++pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sawSomething && !depth) state.fatArrowAt = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parser
|
||||||
|
|
||||||
|
var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
|
||||||
|
|
||||||
|
function JSLexical(indented, column, type, align, prev, info) {
|
||||||
|
this.indented = indented;
|
||||||
|
this.column = column;
|
||||||
|
this.type = type;
|
||||||
|
this.prev = prev;
|
||||||
|
this.info = info;
|
||||||
|
if (align != null) this.align = align;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inScope(state, varname) {
|
||||||
|
for (var v = state.localVars; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
for (var cx = state.context; cx; cx = cx.prev) {
|
||||||
|
for (var v = cx.vars; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJS(state, style, type, content, stream) {
|
||||||
|
var cc = state.cc;
|
||||||
|
// Communicate our context to the combinators.
|
||||||
|
// (Less wasteful than consing up a hundred closures on every call.)
|
||||||
|
cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
|
||||||
|
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = true;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
|
||||||
|
if (combinator(type, content)) {
|
||||||
|
while(cc.length && cc[cc.length - 1].lex)
|
||||||
|
cc.pop()();
|
||||||
|
if (cx.marked) return cx.marked;
|
||||||
|
if (type == "variable" && inScope(state, content)) return "variable-2";
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinator utils
|
||||||
|
|
||||||
|
var cx = {state: null, column: null, marked: null, cc: null};
|
||||||
|
function pass() {
|
||||||
|
for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
|
||||||
|
}
|
||||||
|
function cont() {
|
||||||
|
pass.apply(null, arguments);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function register(varname) {
|
||||||
|
function inList(list) {
|
||||||
|
for (var v = list; v; v = v.next)
|
||||||
|
if (v.name == varname) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var state = cx.state;
|
||||||
|
if (state.context) {
|
||||||
|
cx.marked = "def";
|
||||||
|
if (inList(state.localVars)) return;
|
||||||
|
state.localVars = {name: varname, next: state.localVars};
|
||||||
|
} else {
|
||||||
|
if (inList(state.globalVars)) return;
|
||||||
|
if (parserConfig.globalVars)
|
||||||
|
state.globalVars = {name: varname, next: state.globalVars};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combinators
|
||||||
|
|
||||||
|
var defaultVars = {name: "this", next: {name: "arguments"}};
|
||||||
|
function pushcontext() {
|
||||||
|
cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
|
||||||
|
cx.state.localVars = defaultVars;
|
||||||
|
}
|
||||||
|
function popcontext() {
|
||||||
|
cx.state.localVars = cx.state.context.vars;
|
||||||
|
cx.state.context = cx.state.context.prev;
|
||||||
|
}
|
||||||
|
function pushlex(type, info) {
|
||||||
|
var result = function() {
|
||||||
|
var state = cx.state, indent = state.indented;
|
||||||
|
if (state.lexical.type == "stat") indent = state.lexical.indented;
|
||||||
|
else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
|
||||||
|
indent = outer.indented;
|
||||||
|
state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
|
||||||
|
};
|
||||||
|
result.lex = true;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
function poplex() {
|
||||||
|
var state = cx.state;
|
||||||
|
if (state.lexical.prev) {
|
||||||
|
if (state.lexical.type == ")")
|
||||||
|
state.indented = state.lexical.indented;
|
||||||
|
state.lexical = state.lexical.prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
poplex.lex = true;
|
||||||
|
|
||||||
|
function expect(wanted) {
|
||||||
|
function exp(type) {
|
||||||
|
if (type == wanted) return cont();
|
||||||
|
else if (wanted == ";") return pass();
|
||||||
|
else return cont(exp);
|
||||||
|
};
|
||||||
|
return exp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function statement(type, value) {
|
||||||
|
if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
|
||||||
|
if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
|
||||||
|
if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
|
||||||
|
if (type == "{") return cont(pushlex("}"), block, poplex);
|
||||||
|
if (type == ";") return cont();
|
||||||
|
if (type == "if") {
|
||||||
|
if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
|
||||||
|
cx.state.cc.pop()();
|
||||||
|
return cont(pushlex("form"), expression, statement, poplex, maybeelse);
|
||||||
|
}
|
||||||
|
if (type == "function") return cont(functiondef);
|
||||||
|
if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
|
||||||
|
if (type == "variable") return cont(pushlex("stat"), maybelabel);
|
||||||
|
if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
|
||||||
|
block, poplex, poplex);
|
||||||
|
if (type == "case") return cont(expression, expect(":"));
|
||||||
|
if (type == "default") return cont(expect(":"));
|
||||||
|
if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
|
||||||
|
statement, poplex, popcontext);
|
||||||
|
if (type == "module") return cont(pushlex("form"), pushcontext, afterModule, popcontext, poplex);
|
||||||
|
if (type == "class") return cont(pushlex("form"), className, poplex);
|
||||||
|
if (type == "export") return cont(pushlex("form"), afterExport, poplex);
|
||||||
|
if (type == "import") return cont(pushlex("form"), afterImport, poplex);
|
||||||
|
return pass(pushlex("stat"), expression, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function expression(type) {
|
||||||
|
return expressionInner(type, false);
|
||||||
|
}
|
||||||
|
function expressionNoComma(type) {
|
||||||
|
return expressionInner(type, true);
|
||||||
|
}
|
||||||
|
function expressionInner(type, noComma) {
|
||||||
|
if (cx.state.fatArrowAt == cx.stream.start) {
|
||||||
|
var body = noComma ? arrowBodyNoComma : arrowBody;
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
|
||||||
|
else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
|
||||||
|
}
|
||||||
|
|
||||||
|
var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
|
||||||
|
if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
|
||||||
|
if (type == "function") return cont(functiondef, maybeop);
|
||||||
|
if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
|
||||||
|
if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
|
||||||
|
if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
|
||||||
|
if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
|
||||||
|
if (type == "{") return contCommasep(objprop, "}", null, maybeop);
|
||||||
|
if (type == "quasi") { return pass(quasi, maybeop); }
|
||||||
|
return cont();
|
||||||
|
}
|
||||||
|
function maybeexpression(type) {
|
||||||
|
if (type.match(/[;\}\)\],]/)) return pass();
|
||||||
|
return pass(expression);
|
||||||
|
}
|
||||||
|
function maybeexpressionNoComma(type) {
|
||||||
|
if (type.match(/[;\}\)\],]/)) return pass();
|
||||||
|
return pass(expressionNoComma);
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybeoperatorComma(type, value) {
|
||||||
|
if (type == ",") return cont(expression);
|
||||||
|
return maybeoperatorNoComma(type, value, false);
|
||||||
|
}
|
||||||
|
function maybeoperatorNoComma(type, value, noComma) {
|
||||||
|
var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
|
||||||
|
var expr = noComma == false ? expression : expressionNoComma;
|
||||||
|
if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
|
||||||
|
if (type == "operator") {
|
||||||
|
if (/\+\+|--/.test(value)) return cont(me);
|
||||||
|
if (value == "?") return cont(expression, expect(":"), expr);
|
||||||
|
return cont(expr);
|
||||||
|
}
|
||||||
|
if (type == "quasi") { return pass(quasi, me); }
|
||||||
|
if (type == ";") return;
|
||||||
|
if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
|
||||||
|
if (type == ".") return cont(property, me);
|
||||||
|
if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
|
||||||
|
}
|
||||||
|
function quasi(type, value) {
|
||||||
|
if (type != "quasi") return pass();
|
||||||
|
if (value.slice(value.length - 2) != "${") return cont(quasi);
|
||||||
|
return cont(expression, continueQuasi);
|
||||||
|
}
|
||||||
|
function continueQuasi(type) {
|
||||||
|
if (type == "}") {
|
||||||
|
cx.marked = "string-2";
|
||||||
|
cx.state.tokenize = tokenQuasi;
|
||||||
|
return cont(quasi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function arrowBody(type) {
|
||||||
|
findFatArrow(cx.stream, cx.state);
|
||||||
|
return pass(type == "{" ? statement : expression);
|
||||||
|
}
|
||||||
|
function arrowBodyNoComma(type) {
|
||||||
|
findFatArrow(cx.stream, cx.state);
|
||||||
|
return pass(type == "{" ? statement : expressionNoComma);
|
||||||
|
}
|
||||||
|
function maybelabel(type) {
|
||||||
|
if (type == ":") return cont(poplex, statement);
|
||||||
|
return pass(maybeoperatorComma, expect(";"), poplex);
|
||||||
|
}
|
||||||
|
function property(type) {
|
||||||
|
if (type == "variable") {cx.marked = "property"; return cont();}
|
||||||
|
}
|
||||||
|
function objprop(type, value) {
|
||||||
|
if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property";
|
||||||
|
if (value == "get" || value == "set") return cont(getterSetter);
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (type == "number" || type == "string") {
|
||||||
|
cx.marked = jsonldMode ? "property" : (cx.style + " property");
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (type == "jsonld-keyword") {
|
||||||
|
return cont(afterprop);
|
||||||
|
} else if (type == "[") {
|
||||||
|
return cont(expression, expect("]"), afterprop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getterSetter(type) {
|
||||||
|
if (type != "variable") return pass(afterprop);
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont(functiondef);
|
||||||
|
}
|
||||||
|
function afterprop(type) {
|
||||||
|
if (type == ":") return cont(expressionNoComma);
|
||||||
|
if (type == "(") return pass(functiondef);
|
||||||
|
}
|
||||||
|
function commasep(what, end) {
|
||||||
|
function proceed(type) {
|
||||||
|
if (type == ",") {
|
||||||
|
var lex = cx.state.lexical;
|
||||||
|
if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
|
||||||
|
return cont(what, proceed);
|
||||||
|
}
|
||||||
|
if (type == end) return cont();
|
||||||
|
return cont(expect(end));
|
||||||
|
}
|
||||||
|
return function(type) {
|
||||||
|
if (type == end) return cont();
|
||||||
|
return pass(what, proceed);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function contCommasep(what, end, info) {
|
||||||
|
for (var i = 3; i < arguments.length; i++)
|
||||||
|
cx.cc.push(arguments[i]);
|
||||||
|
return cont(pushlex(end, info), commasep(what, end), poplex);
|
||||||
|
}
|
||||||
|
function block(type) {
|
||||||
|
if (type == "}") return cont();
|
||||||
|
return pass(statement, block);
|
||||||
|
}
|
||||||
|
function maybetype(type) {
|
||||||
|
if (isTS && type == ":") return cont(typedef);
|
||||||
|
}
|
||||||
|
function typedef(type) {
|
||||||
|
if (type == "variable"){cx.marked = "variable-3"; return cont();}
|
||||||
|
}
|
||||||
|
function vardef() {
|
||||||
|
return pass(pattern, maybetype, maybeAssign, vardefCont);
|
||||||
|
}
|
||||||
|
function pattern(type, value) {
|
||||||
|
if (type == "variable") { register(value); return cont(); }
|
||||||
|
if (type == "[") return contCommasep(pattern, "]");
|
||||||
|
if (type == "{") return contCommasep(proppattern, "}");
|
||||||
|
}
|
||||||
|
function proppattern(type, value) {
|
||||||
|
if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
|
||||||
|
register(value);
|
||||||
|
return cont(maybeAssign);
|
||||||
|
}
|
||||||
|
if (type == "variable") cx.marked = "property";
|
||||||
|
return cont(expect(":"), pattern, maybeAssign);
|
||||||
|
}
|
||||||
|
function maybeAssign(_type, value) {
|
||||||
|
if (value == "=") return cont(expressionNoComma);
|
||||||
|
}
|
||||||
|
function vardefCont(type) {
|
||||||
|
if (type == ",") return cont(vardef);
|
||||||
|
}
|
||||||
|
function maybeelse(type, value) {
|
||||||
|
if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
|
||||||
|
}
|
||||||
|
function forspec(type) {
|
||||||
|
if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
|
||||||
|
}
|
||||||
|
function forspec1(type) {
|
||||||
|
if (type == "var") return cont(vardef, expect(";"), forspec2);
|
||||||
|
if (type == ";") return cont(forspec2);
|
||||||
|
if (type == "variable") return cont(formaybeinof);
|
||||||
|
return pass(expression, expect(";"), forspec2);
|
||||||
|
}
|
||||||
|
function formaybeinof(_type, value) {
|
||||||
|
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
||||||
|
return cont(maybeoperatorComma, forspec2);
|
||||||
|
}
|
||||||
|
function forspec2(type, value) {
|
||||||
|
if (type == ";") return cont(forspec3);
|
||||||
|
if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
|
||||||
|
return pass(expression, expect(";"), forspec3);
|
||||||
|
}
|
||||||
|
function forspec3(type) {
|
||||||
|
if (type != ")") cont(expression);
|
||||||
|
}
|
||||||
|
function functiondef(type, value) {
|
||||||
|
if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
|
||||||
|
if (type == "variable") {register(value); return cont(functiondef);}
|
||||||
|
if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, statement, popcontext);
|
||||||
|
}
|
||||||
|
function funarg(type) {
|
||||||
|
if (type == "spread") return cont(funarg);
|
||||||
|
return pass(pattern, maybetype);
|
||||||
|
}
|
||||||
|
function className(type, value) {
|
||||||
|
if (type == "variable") {register(value); return cont(classNameAfter);}
|
||||||
|
}
|
||||||
|
function classNameAfter(type, value) {
|
||||||
|
if (value == "extends") return cont(expression, classNameAfter);
|
||||||
|
if (type == "{") return cont(pushlex("}"), classBody, poplex);
|
||||||
|
}
|
||||||
|
function classBody(type, value) {
|
||||||
|
if (type == "variable" || cx.style == "keyword") {
|
||||||
|
cx.marked = "property";
|
||||||
|
if (value == "get" || value == "set") return cont(classGetterSetter, functiondef, classBody);
|
||||||
|
return cont(functiondef, classBody);
|
||||||
|
}
|
||||||
|
if (value == "*") {
|
||||||
|
cx.marked = "keyword";
|
||||||
|
return cont(classBody);
|
||||||
|
}
|
||||||
|
if (type == ";") return cont(classBody);
|
||||||
|
if (type == "}") return cont();
|
||||||
|
}
|
||||||
|
function classGetterSetter(type) {
|
||||||
|
if (type != "variable") return pass();
|
||||||
|
cx.marked = "property";
|
||||||
|
return cont();
|
||||||
|
}
|
||||||
|
function afterModule(type, value) {
|
||||||
|
if (type == "string") return cont(statement);
|
||||||
|
if (type == "variable") { register(value); return cont(maybeFrom); }
|
||||||
|
}
|
||||||
|
function afterExport(_type, value) {
|
||||||
|
if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
|
||||||
|
if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
|
||||||
|
return pass(statement);
|
||||||
|
}
|
||||||
|
function afterImport(type) {
|
||||||
|
if (type == "string") return cont();
|
||||||
|
return pass(importSpec, maybeFrom);
|
||||||
|
}
|
||||||
|
function importSpec(type, value) {
|
||||||
|
if (type == "{") return contCommasep(importSpec, "}");
|
||||||
|
if (type == "variable") register(value);
|
||||||
|
return cont();
|
||||||
|
}
|
||||||
|
function maybeFrom(_type, value) {
|
||||||
|
if (value == "from") { cx.marked = "keyword"; return cont(expression); }
|
||||||
|
}
|
||||||
|
function arrayLiteral(type) {
|
||||||
|
if (type == "]") return cont();
|
||||||
|
return pass(expressionNoComma, maybeArrayComprehension);
|
||||||
|
}
|
||||||
|
function maybeArrayComprehension(type) {
|
||||||
|
if (type == "for") return pass(comprehension, expect("]"));
|
||||||
|
if (type == ",") return cont(commasep(maybeexpressionNoComma, "]"));
|
||||||
|
return pass(commasep(expressionNoComma, "]"));
|
||||||
|
}
|
||||||
|
function comprehension(type) {
|
||||||
|
if (type == "for") return cont(forspec, comprehension);
|
||||||
|
if (type == "if") return cont(expression, comprehension);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function(basecolumn) {
|
||||||
|
var state = {
|
||||||
|
tokenize: tokenBase,
|
||||||
|
lastType: "sof",
|
||||||
|
cc: [],
|
||||||
|
lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
|
||||||
|
localVars: parserConfig.localVars,
|
||||||
|
context: parserConfig.localVars && {vars: parserConfig.localVars},
|
||||||
|
indented: 0
|
||||||
|
};
|
||||||
|
if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
|
||||||
|
state.globalVars = parserConfig.globalVars;
|
||||||
|
return state;
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (stream.sol()) {
|
||||||
|
if (!state.lexical.hasOwnProperty("align"))
|
||||||
|
state.lexical.align = false;
|
||||||
|
state.indented = stream.indentation();
|
||||||
|
findFatArrow(stream, state);
|
||||||
|
}
|
||||||
|
if (state.tokenize != tokenComment && stream.eatSpace()) return null;
|
||||||
|
var style = state.tokenize(stream, state);
|
||||||
|
if (type == "comment") return style;
|
||||||
|
state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
|
||||||
|
return parseJS(state, style, type, content, stream);
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter) {
|
||||||
|
if (state.tokenize == tokenComment) return CodeMirror.Pass;
|
||||||
|
if (state.tokenize != tokenBase) return 0;
|
||||||
|
var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
|
||||||
|
if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
|
||||||
|
lexical = lexical.prev;
|
||||||
|
var type = lexical.type, closing = firstChar == type;
|
||||||
|
|
||||||
|
if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
|
||||||
|
else if (type == "form" && firstChar == "{") return lexical.indented;
|
||||||
|
else if (type == "form") return lexical.indented + indentUnit;
|
||||||
|
else if (type == "stat")
|
||||||
|
return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
|
||||||
|
else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
|
||||||
|
return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
|
||||||
|
else if (lexical.align) return lexical.column + (closing ? 0 : 1);
|
||||||
|
else return lexical.indented + (closing ? 0 : indentUnit);
|
||||||
|
},
|
||||||
|
|
||||||
|
electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
|
||||||
|
blockCommentStart: jsonMode ? null : "/*",
|
||||||
|
blockCommentEnd: jsonMode ? null : "*/",
|
||||||
|
lineComment: jsonMode ? null : "//",
|
||||||
|
fold: "brace",
|
||||||
|
|
||||||
|
helperType: jsonMode ? "json" : "javascript",
|
||||||
|
jsonldMode: jsonldMode,
|
||||||
|
jsonMode: jsonMode
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/javascript", "javascript");
|
||||||
|
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("text/typescript", { name: "javascript", typescript: true });
|
||||||
|
CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,765 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror", require("../xml/xml"), require("../meta")));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror", "../xml/xml", "../meta"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||||
|
|
||||||
|
var htmlFound = CodeMirror.modes.hasOwnProperty("xml");
|
||||||
|
var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");
|
||||||
|
|
||||||
|
function getMode(name) {
|
||||||
|
if (CodeMirror.findModeByName) {
|
||||||
|
var found = CodeMirror.findModeByName(name);
|
||||||
|
if (found) name = found.mime || found.mimes[0];
|
||||||
|
}
|
||||||
|
var mode = CodeMirror.getMode(cmCfg, name);
|
||||||
|
return mode.name == "null" ? null : mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should characters that affect highlighting be highlighted separate?
|
||||||
|
// Does not include characters that will be output (such as `1.` and `-` for lists)
|
||||||
|
if (modeCfg.highlightFormatting === undefined)
|
||||||
|
modeCfg.highlightFormatting = false;
|
||||||
|
|
||||||
|
// Maximum number of nested blockquotes. Set to 0 for infinite nesting.
|
||||||
|
// Excess `>` will emit `error` token.
|
||||||
|
if (modeCfg.maxBlockquoteDepth === undefined)
|
||||||
|
modeCfg.maxBlockquoteDepth = 0;
|
||||||
|
|
||||||
|
// Should underscores in words open/close em/strong?
|
||||||
|
if (modeCfg.underscoresBreakWords === undefined)
|
||||||
|
modeCfg.underscoresBreakWords = true;
|
||||||
|
|
||||||
|
// Turn on fenced code blocks? ("```" to start/end)
|
||||||
|
if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
|
||||||
|
|
||||||
|
// Turn on task lists? ("- [ ] " and "- [x] ")
|
||||||
|
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
|
||||||
|
|
||||||
|
// Turn on strikethrough syntax
|
||||||
|
if (modeCfg.strikethrough === undefined)
|
||||||
|
modeCfg.strikethrough = false;
|
||||||
|
|
||||||
|
var codeDepth = 0;
|
||||||
|
|
||||||
|
var header = 'header'
|
||||||
|
, code = 'comment'
|
||||||
|
, quote = 'quote'
|
||||||
|
, list1 = 'variable-2'
|
||||||
|
, list2 = 'variable-3'
|
||||||
|
, list3 = 'keyword'
|
||||||
|
, hr = 'hr'
|
||||||
|
, image = 'tag'
|
||||||
|
, formatting = 'formatting'
|
||||||
|
, linkinline = 'link'
|
||||||
|
, linkemail = 'link'
|
||||||
|
, linktext = 'link'
|
||||||
|
, linkhref = 'string'
|
||||||
|
, em = 'em'
|
||||||
|
, strong = 'strong'
|
||||||
|
, strikethrough = 'strikethrough';
|
||||||
|
|
||||||
|
var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
|
||||||
|
, ulRE = /^[*\-+]\s+/
|
||||||
|
, olRE = /^[0-9]+\.\s+/
|
||||||
|
, taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
|
||||||
|
, atxHeaderRE = /^#+/
|
||||||
|
, setextHeaderRE = /^(?:\={1,}|-{1,})$/
|
||||||
|
, textRE = /^[^#!\[\]*_\\<>` "'(~]+/;
|
||||||
|
|
||||||
|
function switchInline(stream, state, f) {
|
||||||
|
state.f = state.inline = f;
|
||||||
|
return f(stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchBlock(stream, state, f) {
|
||||||
|
state.f = state.block = f;
|
||||||
|
return f(stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Blocks
|
||||||
|
|
||||||
|
function blankLine(state) {
|
||||||
|
// Reset linkTitle state
|
||||||
|
state.linkTitle = false;
|
||||||
|
// Reset EM state
|
||||||
|
state.em = false;
|
||||||
|
// Reset STRONG state
|
||||||
|
state.strong = false;
|
||||||
|
// Reset strikethrough state
|
||||||
|
state.strikethrough = false;
|
||||||
|
// Reset state.quote
|
||||||
|
state.quote = 0;
|
||||||
|
if (!htmlFound && state.f == htmlBlock) {
|
||||||
|
state.f = inlineNormal;
|
||||||
|
state.block = blockNormal;
|
||||||
|
}
|
||||||
|
// Reset state.trailingSpace
|
||||||
|
state.trailingSpace = 0;
|
||||||
|
state.trailingSpaceNewLine = false;
|
||||||
|
// Mark this line as blank
|
||||||
|
state.thisLineHasContent = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function blockNormal(stream, state) {
|
||||||
|
|
||||||
|
var sol = stream.sol();
|
||||||
|
|
||||||
|
var prevLineIsList = (state.list !== false);
|
||||||
|
if (state.list !== false && state.indentationDiff >= 0) { // Continued list
|
||||||
|
if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
|
||||||
|
state.indentation -= state.indentationDiff;
|
||||||
|
}
|
||||||
|
state.list = null;
|
||||||
|
} else if (state.list !== false && state.indentation > 0) {
|
||||||
|
state.list = null;
|
||||||
|
state.listDepth = Math.floor(state.indentation / 4);
|
||||||
|
} else if (state.list !== false) { // No longer a list
|
||||||
|
state.list = false;
|
||||||
|
state.listDepth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var match = null;
|
||||||
|
if (state.indentationDiff >= 4) {
|
||||||
|
state.indentation -= 4;
|
||||||
|
stream.skipToEnd();
|
||||||
|
return code;
|
||||||
|
} else if (stream.eatSpace()) {
|
||||||
|
return null;
|
||||||
|
} else if (match = stream.match(atxHeaderRE)) {
|
||||||
|
state.header = match[0].length <= 6 ? match[0].length : 6;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "header";
|
||||||
|
state.f = state.inline;
|
||||||
|
return getType(state);
|
||||||
|
} else if (state.prevLineHasContent && (match = stream.match(setextHeaderRE))) {
|
||||||
|
state.header = match[0].charAt(0) == '=' ? 1 : 2;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "header";
|
||||||
|
state.f = state.inline;
|
||||||
|
return getType(state);
|
||||||
|
} else if (stream.eat('>')) {
|
||||||
|
state.indentation++;
|
||||||
|
state.quote = sol ? 1 : state.quote + 1;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "quote";
|
||||||
|
stream.eatSpace();
|
||||||
|
return getType(state);
|
||||||
|
} else if (stream.peek() === '[') {
|
||||||
|
return switchInline(stream, state, footnoteLink);
|
||||||
|
} else if (stream.match(hrRE, true)) {
|
||||||
|
return hr;
|
||||||
|
} else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, false) || stream.match(olRE, false))) {
|
||||||
|
var listType = null;
|
||||||
|
if (stream.match(ulRE, true)) {
|
||||||
|
listType = 'ul';
|
||||||
|
} else {
|
||||||
|
stream.match(olRE, true);
|
||||||
|
listType = 'ol';
|
||||||
|
}
|
||||||
|
state.indentation += 4;
|
||||||
|
state.list = true;
|
||||||
|
state.listDepth++;
|
||||||
|
if (modeCfg.taskLists && stream.match(taskListRE, false)) {
|
||||||
|
state.taskList = true;
|
||||||
|
}
|
||||||
|
state.f = state.inline;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType];
|
||||||
|
return getType(state);
|
||||||
|
} else if (modeCfg.fencedCodeBlocks && stream.match(/^```[ \t]*([\w+#]*)/, true)) {
|
||||||
|
// try switching mode
|
||||||
|
state.localMode = getMode(RegExp.$1);
|
||||||
|
if (state.localMode) state.localState = state.localMode.startState();
|
||||||
|
state.f = state.block = local;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
||||||
|
state.code = true;
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return switchInline(stream, state, state.inline);
|
||||||
|
}
|
||||||
|
|
||||||
|
function htmlBlock(stream, state) {
|
||||||
|
var style = htmlMode.token(stream, state.htmlState);
|
||||||
|
if ((htmlFound && state.htmlState.tagStart === null && !state.htmlState.context) ||
|
||||||
|
(state.md_inside && stream.current().indexOf(">") > -1)) {
|
||||||
|
state.f = inlineNormal;
|
||||||
|
state.block = blockNormal;
|
||||||
|
state.htmlState = null;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
function local(stream, state) {
|
||||||
|
if (stream.sol() && stream.match("```", false)) {
|
||||||
|
state.localMode = state.localState = null;
|
||||||
|
state.f = state.block = leavingLocal;
|
||||||
|
return null;
|
||||||
|
} else if (state.localMode) {
|
||||||
|
return state.localMode.token(stream, state.localState);
|
||||||
|
} else {
|
||||||
|
stream.skipToEnd();
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function leavingLocal(stream, state) {
|
||||||
|
stream.match("```");
|
||||||
|
state.block = blockNormal;
|
||||||
|
state.f = inlineNormal;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "code-block";
|
||||||
|
state.code = true;
|
||||||
|
var returnType = getType(state);
|
||||||
|
state.code = false;
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inline
|
||||||
|
function getType(state) {
|
||||||
|
var styles = [];
|
||||||
|
|
||||||
|
if (state.formatting) {
|
||||||
|
styles.push(formatting);
|
||||||
|
|
||||||
|
if (typeof state.formatting === "string") state.formatting = [state.formatting];
|
||||||
|
|
||||||
|
for (var i = 0; i < state.formatting.length; i++) {
|
||||||
|
styles.push(formatting + "-" + state.formatting[i]);
|
||||||
|
|
||||||
|
if (state.formatting[i] === "header") {
|
||||||
|
styles.push(formatting + "-" + state.formatting[i] + "-" + state.header);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add `formatting-quote` and `formatting-quote-#` for blockquotes
|
||||||
|
// Add `error` instead if the maximum blockquote nesting depth is passed
|
||||||
|
if (state.formatting[i] === "quote") {
|
||||||
|
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
|
||||||
|
styles.push(formatting + "-" + state.formatting[i] + "-" + state.quote);
|
||||||
|
} else {
|
||||||
|
styles.push("error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.taskOpen) {
|
||||||
|
styles.push("meta");
|
||||||
|
return styles.length ? styles.join(' ') : null;
|
||||||
|
}
|
||||||
|
if (state.taskClosed) {
|
||||||
|
styles.push("property");
|
||||||
|
return styles.length ? styles.join(' ') : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.linkHref) {
|
||||||
|
styles.push(linkhref);
|
||||||
|
return styles.length ? styles.join(' ') : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.strong) { styles.push(strong); }
|
||||||
|
if (state.em) { styles.push(em); }
|
||||||
|
if (state.strikethrough) { styles.push(strikethrough); }
|
||||||
|
|
||||||
|
if (state.linkText) { styles.push(linktext); }
|
||||||
|
|
||||||
|
if (state.code) { styles.push(code); }
|
||||||
|
|
||||||
|
if (state.header) { styles.push(header); styles.push(header + "-" + state.header); }
|
||||||
|
|
||||||
|
if (state.quote) {
|
||||||
|
styles.push(quote);
|
||||||
|
|
||||||
|
// Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth
|
||||||
|
if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) {
|
||||||
|
styles.push(quote + "-" + state.quote);
|
||||||
|
} else {
|
||||||
|
styles.push(quote + "-" + modeCfg.maxBlockquoteDepth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.list !== false) {
|
||||||
|
var listMod = (state.listDepth - 1) % 3;
|
||||||
|
if (!listMod) {
|
||||||
|
styles.push(list1);
|
||||||
|
} else if (listMod === 1) {
|
||||||
|
styles.push(list2);
|
||||||
|
} else {
|
||||||
|
styles.push(list3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.trailingSpaceNewLine) {
|
||||||
|
styles.push("trailing-space-new-line");
|
||||||
|
} else if (state.trailingSpace) {
|
||||||
|
styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return styles.length ? styles.join(' ') : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleText(stream, state) {
|
||||||
|
if (stream.match(textRE, true)) {
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inlineNormal(stream, state) {
|
||||||
|
var style = state.text(stream, state);
|
||||||
|
if (typeof style !== 'undefined')
|
||||||
|
return style;
|
||||||
|
|
||||||
|
if (state.list) { // List marker (*, +, -, 1., etc)
|
||||||
|
state.list = null;
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.taskList) {
|
||||||
|
var taskOpen = stream.match(taskListRE, true)[1] !== "x";
|
||||||
|
if (taskOpen) state.taskOpen = true;
|
||||||
|
else state.taskClosed = true;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "task";
|
||||||
|
state.taskList = false;
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.taskOpen = false;
|
||||||
|
state.taskClosed = false;
|
||||||
|
|
||||||
|
if (state.header && stream.match(/^#+$/, true)) {
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "header";
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get sol() value now, before character is consumed
|
||||||
|
var sol = stream.sol();
|
||||||
|
|
||||||
|
var ch = stream.next();
|
||||||
|
|
||||||
|
if (ch === '\\') {
|
||||||
|
stream.next();
|
||||||
|
if (modeCfg.highlightFormatting) {
|
||||||
|
var type = getType(state);
|
||||||
|
return type ? type + " formatting-escape" : "formatting-escape";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches link titles present on next line
|
||||||
|
if (state.linkTitle) {
|
||||||
|
state.linkTitle = false;
|
||||||
|
var matchCh = ch;
|
||||||
|
if (ch === '(') {
|
||||||
|
matchCh = ')';
|
||||||
|
}
|
||||||
|
matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
|
||||||
|
var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
|
||||||
|
if (stream.match(new RegExp(regex), true)) {
|
||||||
|
return linkhref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this block is changed, it may need to be updated in GFM mode
|
||||||
|
if (ch === '`') {
|
||||||
|
var previousFormatting = state.formatting;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "code";
|
||||||
|
var t = getType(state);
|
||||||
|
var before = stream.pos;
|
||||||
|
stream.eatWhile('`');
|
||||||
|
var difference = 1 + stream.pos - before;
|
||||||
|
if (!state.code) {
|
||||||
|
codeDepth = difference;
|
||||||
|
state.code = true;
|
||||||
|
return getType(state);
|
||||||
|
} else {
|
||||||
|
if (difference === codeDepth) { // Must be exact
|
||||||
|
state.code = false;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
state.formatting = previousFormatting;
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
} else if (state.code) {
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
|
||||||
|
stream.match(/\[[^\]]*\]/);
|
||||||
|
state.inline = state.f = linkHref;
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
|
||||||
|
state.linkText = true;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === ']' && state.linkText) {
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||||
|
var type = getType(state);
|
||||||
|
state.linkText = false;
|
||||||
|
state.inline = state.f = linkHref;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
|
||||||
|
state.f = state.inline = linkInline;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||||
|
var type = getType(state);
|
||||||
|
if (type){
|
||||||
|
type += " ";
|
||||||
|
} else {
|
||||||
|
type = "";
|
||||||
|
}
|
||||||
|
return type + linkinline;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
|
||||||
|
state.f = state.inline = linkInline;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||||
|
var type = getType(state);
|
||||||
|
if (type){
|
||||||
|
type += " ";
|
||||||
|
} else {
|
||||||
|
type = "";
|
||||||
|
}
|
||||||
|
return type + linkemail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '<' && stream.match(/^\w/, false)) {
|
||||||
|
if (stream.string.indexOf(">") != -1) {
|
||||||
|
var atts = stream.string.substring(1,stream.string.indexOf(">"));
|
||||||
|
if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
|
||||||
|
state.md_inside = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.backUp(1);
|
||||||
|
state.htmlState = CodeMirror.startState(htmlMode);
|
||||||
|
return switchBlock(stream, state, htmlBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === '<' && stream.match(/^\/\w*?>/)) {
|
||||||
|
state.md_inside = false;
|
||||||
|
return "tag";
|
||||||
|
}
|
||||||
|
|
||||||
|
var ignoreUnderscore = false;
|
||||||
|
if (!modeCfg.underscoresBreakWords) {
|
||||||
|
if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
|
||||||
|
var prevPos = stream.pos - 2;
|
||||||
|
if (prevPos >= 0) {
|
||||||
|
var prevCh = stream.string.charAt(prevPos);
|
||||||
|
if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
|
||||||
|
ignoreUnderscore = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
|
||||||
|
if (sol && stream.peek() === ' ') {
|
||||||
|
// Do nothing, surrounded by newline and space
|
||||||
|
} else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "strong";
|
||||||
|
var t = getType(state);
|
||||||
|
state.strong = false;
|
||||||
|
return t;
|
||||||
|
} else if (!state.strong && stream.eat(ch)) { // Add STRONG
|
||||||
|
state.strong = ch;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "strong";
|
||||||
|
return getType(state);
|
||||||
|
} else if (state.em === ch) { // Remove EM
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "em";
|
||||||
|
var t = getType(state);
|
||||||
|
state.em = false;
|
||||||
|
return t;
|
||||||
|
} else if (!state.em) { // Add EM
|
||||||
|
state.em = ch;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "em";
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
} else if (ch === ' ') {
|
||||||
|
if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
|
||||||
|
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
|
||||||
|
return getType(state);
|
||||||
|
} else { // Not surrounded by spaces, back up pointer
|
||||||
|
stream.backUp(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modeCfg.strikethrough) {
|
||||||
|
if (ch === '~' && stream.eatWhile(ch)) {
|
||||||
|
if (state.strikethrough) {// Remove strikethrough
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
|
||||||
|
var t = getType(state);
|
||||||
|
state.strikethrough = false;
|
||||||
|
return t;
|
||||||
|
} else if (stream.match(/^[^\s]/, false)) {// Add strikethrough
|
||||||
|
state.strikethrough = true;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "strikethrough";
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
} else if (ch === ' ') {
|
||||||
|
if (stream.match(/^~~/, true)) { // Probably surrounded by space
|
||||||
|
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
|
||||||
|
return getType(state);
|
||||||
|
} else { // Not surrounded by spaces, back up pointer
|
||||||
|
stream.backUp(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch === ' ') {
|
||||||
|
if (stream.match(/ +$/, false)) {
|
||||||
|
state.trailingSpace++;
|
||||||
|
} else if (state.trailingSpace) {
|
||||||
|
state.trailingSpaceNewLine = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkInline(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
|
||||||
|
if (ch === ">") {
|
||||||
|
state.f = state.inline = inlineNormal;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||||
|
var type = getType(state);
|
||||||
|
if (type){
|
||||||
|
type += " ";
|
||||||
|
} else {
|
||||||
|
type = "";
|
||||||
|
}
|
||||||
|
return type + linkinline;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.match(/^[^>]+/, true);
|
||||||
|
|
||||||
|
return linkinline;
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkHref(stream, state) {
|
||||||
|
// Check if space, and return NULL if so (to avoid marking the space)
|
||||||
|
if(stream.eatSpace()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch === '(' || ch === '[') {
|
||||||
|
state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]");
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link-string";
|
||||||
|
state.linkHref = true;
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
return 'error';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLinkHrefInside(endChar) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
|
||||||
|
if (ch === endChar) {
|
||||||
|
state.f = state.inline = inlineNormal;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link-string";
|
||||||
|
var returnState = getType(state);
|
||||||
|
state.linkHref = false;
|
||||||
|
return returnState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream.match(inlineRE(endChar), true)) {
|
||||||
|
stream.backUp(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
state.linkHref = true;
|
||||||
|
return getType(state);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function footnoteLink(stream, state) {
|
||||||
|
if (stream.match(/^[^\]]*\]:/, false)) {
|
||||||
|
state.f = footnoteLinkInside;
|
||||||
|
stream.next(); // Consume [
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||||
|
state.linkText = true;
|
||||||
|
return getType(state);
|
||||||
|
}
|
||||||
|
return switchInline(stream, state, inlineNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
function footnoteLinkInside(stream, state) {
|
||||||
|
if (stream.match(/^\]:/, true)) {
|
||||||
|
state.f = state.inline = footnoteUrl;
|
||||||
|
if (modeCfg.highlightFormatting) state.formatting = "link";
|
||||||
|
var returnType = getType(state);
|
||||||
|
state.linkText = false;
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.match(/^[^\]]+/, true);
|
||||||
|
|
||||||
|
return linktext;
|
||||||
|
}
|
||||||
|
|
||||||
|
function footnoteUrl(stream, state) {
|
||||||
|
// Check if space, and return NULL if so (to avoid marking the space)
|
||||||
|
if(stream.eatSpace()){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Match URL
|
||||||
|
stream.match(/^[^\s]+/, true);
|
||||||
|
// Check for link title
|
||||||
|
if (stream.peek() === undefined) { // End of line, set flag to check next line
|
||||||
|
state.linkTitle = true;
|
||||||
|
} else { // More content on line, check if link title
|
||||||
|
stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
|
||||||
|
}
|
||||||
|
state.f = state.inline = inlineNormal;
|
||||||
|
return linkhref;
|
||||||
|
}
|
||||||
|
|
||||||
|
var savedInlineRE = [];
|
||||||
|
function inlineRE(endChar) {
|
||||||
|
if (!savedInlineRE[endChar]) {
|
||||||
|
// Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
|
||||||
|
endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
|
||||||
|
// Match any non-endChar, escaped character, as well as the closing
|
||||||
|
// endChar.
|
||||||
|
savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
|
||||||
|
}
|
||||||
|
return savedInlineRE[endChar];
|
||||||
|
}
|
||||||
|
|
||||||
|
var mode = {
|
||||||
|
startState: function() {
|
||||||
|
return {
|
||||||
|
f: blockNormal,
|
||||||
|
|
||||||
|
prevLineHasContent: false,
|
||||||
|
thisLineHasContent: false,
|
||||||
|
|
||||||
|
block: blockNormal,
|
||||||
|
htmlState: null,
|
||||||
|
indentation: 0,
|
||||||
|
|
||||||
|
inline: inlineNormal,
|
||||||
|
text: handleText,
|
||||||
|
|
||||||
|
formatting: false,
|
||||||
|
linkText: false,
|
||||||
|
linkHref: false,
|
||||||
|
linkTitle: false,
|
||||||
|
em: false,
|
||||||
|
strong: false,
|
||||||
|
header: 0,
|
||||||
|
taskList: false,
|
||||||
|
list: false,
|
||||||
|
listDepth: 0,
|
||||||
|
quote: 0,
|
||||||
|
trailingSpace: 0,
|
||||||
|
trailingSpaceNewLine: false,
|
||||||
|
strikethrough: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
copyState: function(s) {
|
||||||
|
return {
|
||||||
|
f: s.f,
|
||||||
|
|
||||||
|
prevLineHasContent: s.prevLineHasContent,
|
||||||
|
thisLineHasContent: s.thisLineHasContent,
|
||||||
|
|
||||||
|
block: s.block,
|
||||||
|
htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState),
|
||||||
|
indentation: s.indentation,
|
||||||
|
|
||||||
|
localMode: s.localMode,
|
||||||
|
localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
|
||||||
|
|
||||||
|
inline: s.inline,
|
||||||
|
text: s.text,
|
||||||
|
formatting: false,
|
||||||
|
linkTitle: s.linkTitle,
|
||||||
|
em: s.em,
|
||||||
|
strong: s.strong,
|
||||||
|
strikethrough: s.strikethrough,
|
||||||
|
header: s.header,
|
||||||
|
taskList: s.taskList,
|
||||||
|
list: s.list,
|
||||||
|
listDepth: s.listDepth,
|
||||||
|
quote: s.quote,
|
||||||
|
trailingSpace: s.trailingSpace,
|
||||||
|
trailingSpaceNewLine: s.trailingSpaceNewLine,
|
||||||
|
md_inside: s.md_inside
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
|
||||||
|
// Reset state.formatting
|
||||||
|
state.formatting = false;
|
||||||
|
|
||||||
|
if (stream.sol()) {
|
||||||
|
var forceBlankLine = !!state.header;
|
||||||
|
|
||||||
|
// Reset state.header
|
||||||
|
state.header = 0;
|
||||||
|
|
||||||
|
if (stream.match(/^\s*$/, true) || forceBlankLine) {
|
||||||
|
state.prevLineHasContent = false;
|
||||||
|
blankLine(state);
|
||||||
|
return forceBlankLine ? this.token(stream, state) : null;
|
||||||
|
} else {
|
||||||
|
state.prevLineHasContent = state.thisLineHasContent;
|
||||||
|
state.thisLineHasContent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset state.taskList
|
||||||
|
state.taskList = false;
|
||||||
|
|
||||||
|
// Reset state.code
|
||||||
|
state.code = false;
|
||||||
|
|
||||||
|
// Reset state.trailingSpace
|
||||||
|
state.trailingSpace = 0;
|
||||||
|
state.trailingSpaceNewLine = false;
|
||||||
|
|
||||||
|
state.f = state.block;
|
||||||
|
var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
|
||||||
|
var difference = Math.floor((indentation - state.indentation) / 4) * 4;
|
||||||
|
if (difference > 4) difference = 4;
|
||||||
|
var adjustedIndentation = state.indentation + difference;
|
||||||
|
state.indentationDiff = adjustedIndentation - state.indentation;
|
||||||
|
state.indentation = adjustedIndentation;
|
||||||
|
if (indentation > 0) return null;
|
||||||
|
}
|
||||||
|
return state.f(stream, state);
|
||||||
|
},
|
||||||
|
|
||||||
|
innerMode: function(state) {
|
||||||
|
if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode};
|
||||||
|
if (state.localState) return {state: state.localState, mode: state.localMode};
|
||||||
|
return {state: state, mode: mode};
|
||||||
|
},
|
||||||
|
|
||||||
|
blankLine: blankLine,
|
||||||
|
|
||||||
|
getType: getType,
|
||||||
|
|
||||||
|
fold: "markdown"
|
||||||
|
};
|
||||||
|
return mode;
|
||||||
|
}, "xml");
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/x-markdown", "markdown");
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,413 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: https://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var htmlConfig = {
|
||||||
|
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
|
||||||
|
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
|
||||||
|
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
|
||||||
|
'track': true, 'wbr': true, 'menuitem': true},
|
||||||
|
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
|
||||||
|
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
|
||||||
|
'th': true, 'tr': true},
|
||||||
|
contextGrabbers: {
|
||||||
|
'dd': {'dd': true, 'dt': true},
|
||||||
|
'dt': {'dd': true, 'dt': true},
|
||||||
|
'li': {'li': true},
|
||||||
|
'option': {'option': true, 'optgroup': true},
|
||||||
|
'optgroup': {'optgroup': true},
|
||||||
|
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
|
||||||
|
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
|
||||||
|
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
|
||||||
|
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
|
||||||
|
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
|
||||||
|
'rp': {'rp': true, 'rt': true},
|
||||||
|
'rt': {'rp': true, 'rt': true},
|
||||||
|
'tbody': {'tbody': true, 'tfoot': true},
|
||||||
|
'td': {'td': true, 'th': true},
|
||||||
|
'tfoot': {'tbody': true},
|
||||||
|
'th': {'td': true, 'th': true},
|
||||||
|
'thead': {'tbody': true, 'tfoot': true},
|
||||||
|
'tr': {'tr': true}
|
||||||
|
},
|
||||||
|
doNotIndent: {"pre": true},
|
||||||
|
allowUnquoted: true,
|
||||||
|
allowMissing: true,
|
||||||
|
caseFold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
var xmlConfig = {
|
||||||
|
autoSelfClosers: {},
|
||||||
|
implicitlyClosed: {},
|
||||||
|
contextGrabbers: {},
|
||||||
|
doNotIndent: {},
|
||||||
|
allowUnquoted: false,
|
||||||
|
allowMissing: false,
|
||||||
|
allowMissingTagName: false,
|
||||||
|
caseFold: false
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeMirror.defineMode("xml", function(editorConf, config_) {
|
||||||
|
var indentUnit = editorConf.indentUnit
|
||||||
|
var config = {}
|
||||||
|
var defaults = config_.htmlMode ? htmlConfig : xmlConfig
|
||||||
|
for (var prop in defaults) config[prop] = defaults[prop]
|
||||||
|
for (var prop in config_) config[prop] = config_[prop]
|
||||||
|
|
||||||
|
// Return variables for tokenizers
|
||||||
|
var type, setStyle;
|
||||||
|
|
||||||
|
function inText(stream, state) {
|
||||||
|
function chain(parser) {
|
||||||
|
state.tokenize = parser;
|
||||||
|
return parser(stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == "<") {
|
||||||
|
if (stream.eat("!")) {
|
||||||
|
if (stream.eat("[")) {
|
||||||
|
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
|
||||||
|
else return null;
|
||||||
|
} else if (stream.match("--")) {
|
||||||
|
return chain(inBlock("comment", "-->"));
|
||||||
|
} else if (stream.match("DOCTYPE", true, true)) {
|
||||||
|
stream.eatWhile(/[\w\._\-]/);
|
||||||
|
return chain(doctype(1));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (stream.eat("?")) {
|
||||||
|
stream.eatWhile(/[\w\._\-]/);
|
||||||
|
state.tokenize = inBlock("meta", "?>");
|
||||||
|
return "meta";
|
||||||
|
} else {
|
||||||
|
type = stream.eat("/") ? "closeTag" : "openTag";
|
||||||
|
state.tokenize = inTag;
|
||||||
|
return "tag bracket";
|
||||||
|
}
|
||||||
|
} else if (ch == "&") {
|
||||||
|
var ok;
|
||||||
|
if (stream.eat("#")) {
|
||||||
|
if (stream.eat("x")) {
|
||||||
|
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
|
||||||
|
} else {
|
||||||
|
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
|
||||||
|
}
|
||||||
|
return ok ? "atom" : "error";
|
||||||
|
} else {
|
||||||
|
stream.eatWhile(/[^&<]/);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inText.isInText = true;
|
||||||
|
|
||||||
|
function inTag(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
|
||||||
|
state.tokenize = inText;
|
||||||
|
type = ch == ">" ? "endTag" : "selfcloseTag";
|
||||||
|
return "tag bracket";
|
||||||
|
} else if (ch == "=") {
|
||||||
|
type = "equals";
|
||||||
|
return null;
|
||||||
|
} else if (ch == "<") {
|
||||||
|
state.tokenize = inText;
|
||||||
|
state.state = baseState;
|
||||||
|
state.tagName = state.tagStart = null;
|
||||||
|
var next = state.tokenize(stream, state);
|
||||||
|
return next ? next + " tag error" : "tag error";
|
||||||
|
} else if (/[\'\"]/.test(ch)) {
|
||||||
|
state.tokenize = inAttribute(ch);
|
||||||
|
state.stringStartCol = stream.column();
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else {
|
||||||
|
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
|
||||||
|
return "word";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inAttribute(quote) {
|
||||||
|
var closure = function(stream, state) {
|
||||||
|
while (!stream.eol()) {
|
||||||
|
if (stream.next() == quote) {
|
||||||
|
state.tokenize = inTag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "string";
|
||||||
|
};
|
||||||
|
closure.isInAttribute = true;
|
||||||
|
return closure;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inBlock(style, terminator) {
|
||||||
|
return function(stream, state) {
|
||||||
|
while (!stream.eol()) {
|
||||||
|
if (stream.match(terminator)) {
|
||||||
|
state.tokenize = inText;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stream.next();
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doctype(depth) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var ch;
|
||||||
|
while ((ch = stream.next()) != null) {
|
||||||
|
if (ch == "<") {
|
||||||
|
state.tokenize = doctype(depth + 1);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else if (ch == ">") {
|
||||||
|
if (depth == 1) {
|
||||||
|
state.tokenize = inText;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
state.tokenize = doctype(depth - 1);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "meta";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function Context(state, tagName, startOfLine) {
|
||||||
|
this.prev = state.context;
|
||||||
|
this.tagName = tagName;
|
||||||
|
this.indent = state.indented;
|
||||||
|
this.startOfLine = startOfLine;
|
||||||
|
if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
|
||||||
|
this.noIndent = true;
|
||||||
|
}
|
||||||
|
function popContext(state) {
|
||||||
|
if (state.context) state.context = state.context.prev;
|
||||||
|
}
|
||||||
|
function maybePopContext(state, nextTagName) {
|
||||||
|
var parentTagName;
|
||||||
|
while (true) {
|
||||||
|
if (!state.context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parentTagName = state.context.tagName;
|
||||||
|
if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
|
||||||
|
!config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
popContext(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function baseState(type, stream, state) {
|
||||||
|
if (type == "openTag") {
|
||||||
|
state.tagStart = stream.column();
|
||||||
|
return tagNameState;
|
||||||
|
} else if (type == "closeTag") {
|
||||||
|
return closeTagNameState;
|
||||||
|
} else {
|
||||||
|
return baseState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function tagNameState(type, stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
state.tagName = stream.current();
|
||||||
|
setStyle = "tag";
|
||||||
|
return attrState;
|
||||||
|
} else if (config.allowMissingTagName && type == "endTag") {
|
||||||
|
setStyle = "tag bracket";
|
||||||
|
return attrState(type, stream, state);
|
||||||
|
} else {
|
||||||
|
setStyle = "error";
|
||||||
|
return tagNameState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function closeTagNameState(type, stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
var tagName = stream.current();
|
||||||
|
if (state.context && state.context.tagName != tagName &&
|
||||||
|
config.implicitlyClosed.hasOwnProperty(state.context.tagName))
|
||||||
|
popContext(state);
|
||||||
|
if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
|
||||||
|
setStyle = "tag";
|
||||||
|
return closeState;
|
||||||
|
} else {
|
||||||
|
setStyle = "tag error";
|
||||||
|
return closeStateErr;
|
||||||
|
}
|
||||||
|
} else if (config.allowMissingTagName && type == "endTag") {
|
||||||
|
setStyle = "tag bracket";
|
||||||
|
return closeState(type, stream, state);
|
||||||
|
} else {
|
||||||
|
setStyle = "error";
|
||||||
|
return closeStateErr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeState(type, _stream, state) {
|
||||||
|
if (type != "endTag") {
|
||||||
|
setStyle = "error";
|
||||||
|
return closeState;
|
||||||
|
}
|
||||||
|
popContext(state);
|
||||||
|
return baseState;
|
||||||
|
}
|
||||||
|
function closeStateErr(type, stream, state) {
|
||||||
|
setStyle = "error";
|
||||||
|
return closeState(type, stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function attrState(type, _stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
setStyle = "attribute";
|
||||||
|
return attrEqState;
|
||||||
|
} else if (type == "endTag" || type == "selfcloseTag") {
|
||||||
|
var tagName = state.tagName, tagStart = state.tagStart;
|
||||||
|
state.tagName = state.tagStart = null;
|
||||||
|
if (type == "selfcloseTag" ||
|
||||||
|
config.autoSelfClosers.hasOwnProperty(tagName)) {
|
||||||
|
maybePopContext(state, tagName);
|
||||||
|
} else {
|
||||||
|
maybePopContext(state, tagName);
|
||||||
|
state.context = new Context(state, tagName, tagStart == state.indented);
|
||||||
|
}
|
||||||
|
return baseState;
|
||||||
|
}
|
||||||
|
setStyle = "error";
|
||||||
|
return attrState;
|
||||||
|
}
|
||||||
|
function attrEqState(type, stream, state) {
|
||||||
|
if (type == "equals") return attrValueState;
|
||||||
|
if (!config.allowMissing) setStyle = "error";
|
||||||
|
return attrState(type, stream, state);
|
||||||
|
}
|
||||||
|
function attrValueState(type, stream, state) {
|
||||||
|
if (type == "string") return attrContinuedState;
|
||||||
|
if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
|
||||||
|
setStyle = "error";
|
||||||
|
return attrState(type, stream, state);
|
||||||
|
}
|
||||||
|
function attrContinuedState(type, stream, state) {
|
||||||
|
if (type == "string") return attrContinuedState;
|
||||||
|
return attrState(type, stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function(baseIndent) {
|
||||||
|
var state = {tokenize: inText,
|
||||||
|
state: baseState,
|
||||||
|
indented: baseIndent || 0,
|
||||||
|
tagName: null, tagStart: null,
|
||||||
|
context: null}
|
||||||
|
if (baseIndent != null) state.baseIndent = baseIndent
|
||||||
|
return state
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (!state.tagName && stream.sol())
|
||||||
|
state.indented = stream.indentation();
|
||||||
|
|
||||||
|
if (stream.eatSpace()) return null;
|
||||||
|
type = null;
|
||||||
|
var style = state.tokenize(stream, state);
|
||||||
|
if ((style || type) && style != "comment") {
|
||||||
|
setStyle = null;
|
||||||
|
state.state = state.state(type || style, stream, state);
|
||||||
|
if (setStyle)
|
||||||
|
style = setStyle == "error" ? style + " error" : setStyle;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter, fullLine) {
|
||||||
|
var context = state.context;
|
||||||
|
// Indent multi-line strings (e.g. css).
|
||||||
|
if (state.tokenize.isInAttribute) {
|
||||||
|
if (state.tagStart == state.indented)
|
||||||
|
return state.stringStartCol + 1;
|
||||||
|
else
|
||||||
|
return state.indented + indentUnit;
|
||||||
|
}
|
||||||
|
if (context && context.noIndent) return CodeMirror.Pass;
|
||||||
|
if (state.tokenize != inTag && state.tokenize != inText)
|
||||||
|
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
|
||||||
|
// Indent the starts of attribute names.
|
||||||
|
if (state.tagName) {
|
||||||
|
if (config.multilineTagIndentPastTag !== false)
|
||||||
|
return state.tagStart + state.tagName.length + 2;
|
||||||
|
else
|
||||||
|
return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
|
||||||
|
}
|
||||||
|
if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
|
||||||
|
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
|
||||||
|
if (tagAfter && tagAfter[1]) { // Closing tag spotted
|
||||||
|
while (context) {
|
||||||
|
if (context.tagName == tagAfter[2]) {
|
||||||
|
context = context.prev;
|
||||||
|
break;
|
||||||
|
} else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
|
||||||
|
context = context.prev;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tagAfter) { // Opening tag spotted
|
||||||
|
while (context) {
|
||||||
|
var grabbers = config.contextGrabbers[context.tagName];
|
||||||
|
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
|
||||||
|
context = context.prev;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (context && context.prev && !context.startOfLine)
|
||||||
|
context = context.prev;
|
||||||
|
if (context) return context.indent + indentUnit;
|
||||||
|
else return state.baseIndent || 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
electricInput: /<\/[\s\w:]+>$/,
|
||||||
|
blockCommentStart: "<!--",
|
||||||
|
blockCommentEnd: "-->",
|
||||||
|
|
||||||
|
configuration: config.htmlMode ? "html" : "xml",
|
||||||
|
helperType: config.htmlMode ? "html" : "xml",
|
||||||
|
|
||||||
|
skipAttribute: function(state) {
|
||||||
|
if (state.state == attrValueState)
|
||||||
|
state.state = attrState
|
||||||
|
},
|
||||||
|
|
||||||
|
xmlCurrentTag: function(state) {
|
||||||
|
return state.tagName ? {name: state.tagName, close: state.type == "closeTag"} : null
|
||||||
|
},
|
||||||
|
|
||||||
|
xmlCurrentContext: function(state) {
|
||||||
|
var context = []
|
||||||
|
for (var cx = state.context; cx; cx = cx.prev)
|
||||||
|
if (cx.tagName) context.push(cx.tagName)
|
||||||
|
return context.reverse()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/xml", "xml");
|
||||||
|
CodeMirror.defineMIME("application/xml", "xml");
|
||||||
|
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
|
||||||
|
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
|
||||||
|
|
||||||
|
});
|
|
@ -0,0 +1,384 @@
|
||||||
|
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||||
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||||
|
|
||||||
|
(function(mod) {
|
||||||
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||||
|
mod(require("../../lib/codemirror"));
|
||||||
|
else if (typeof define == "function" && define.amd) // AMD
|
||||||
|
define(["../../lib/codemirror"], mod);
|
||||||
|
else // Plain browser env
|
||||||
|
mod(CodeMirror);
|
||||||
|
})(function(CodeMirror) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
CodeMirror.defineMode("xml", function(config, parserConfig) {
|
||||||
|
var indentUnit = config.indentUnit;
|
||||||
|
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
|
||||||
|
var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag;
|
||||||
|
if (multilineTagIndentPastTag == null) multilineTagIndentPastTag = true;
|
||||||
|
|
||||||
|
var Kludges = parserConfig.htmlMode ? {
|
||||||
|
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
|
||||||
|
'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
|
||||||
|
'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
|
||||||
|
'track': true, 'wbr': true, 'menuitem': true},
|
||||||
|
implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
|
||||||
|
'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
|
||||||
|
'th': true, 'tr': true},
|
||||||
|
contextGrabbers: {
|
||||||
|
'dd': {'dd': true, 'dt': true},
|
||||||
|
'dt': {'dd': true, 'dt': true},
|
||||||
|
'li': {'li': true},
|
||||||
|
'option': {'option': true, 'optgroup': true},
|
||||||
|
'optgroup': {'optgroup': true},
|
||||||
|
'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
|
||||||
|
'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
|
||||||
|
'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
|
||||||
|
'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
|
||||||
|
'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
|
||||||
|
'rp': {'rp': true, 'rt': true},
|
||||||
|
'rt': {'rp': true, 'rt': true},
|
||||||
|
'tbody': {'tbody': true, 'tfoot': true},
|
||||||
|
'td': {'td': true, 'th': true},
|
||||||
|
'tfoot': {'tbody': true},
|
||||||
|
'th': {'td': true, 'th': true},
|
||||||
|
'thead': {'tbody': true, 'tfoot': true},
|
||||||
|
'tr': {'tr': true}
|
||||||
|
},
|
||||||
|
doNotIndent: {"pre": true},
|
||||||
|
allowUnquoted: true,
|
||||||
|
allowMissing: true,
|
||||||
|
caseFold: true
|
||||||
|
} : {
|
||||||
|
autoSelfClosers: {},
|
||||||
|
implicitlyClosed: {},
|
||||||
|
contextGrabbers: {},
|
||||||
|
doNotIndent: {},
|
||||||
|
allowUnquoted: false,
|
||||||
|
allowMissing: false,
|
||||||
|
caseFold: false
|
||||||
|
};
|
||||||
|
var alignCDATA = parserConfig.alignCDATA;
|
||||||
|
|
||||||
|
// Return variables for tokenizers
|
||||||
|
var type, setStyle;
|
||||||
|
|
||||||
|
function inText(stream, state) {
|
||||||
|
function chain(parser) {
|
||||||
|
state.tokenize = parser;
|
||||||
|
return parser(stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == "<") {
|
||||||
|
if (stream.eat("!")) {
|
||||||
|
if (stream.eat("[")) {
|
||||||
|
if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
|
||||||
|
else return null;
|
||||||
|
} else if (stream.match("--")) {
|
||||||
|
return chain(inBlock("comment", "-->"));
|
||||||
|
} else if (stream.match("DOCTYPE", true, true)) {
|
||||||
|
stream.eatWhile(/[\w\._\-]/);
|
||||||
|
return chain(doctype(1));
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (stream.eat("?")) {
|
||||||
|
stream.eatWhile(/[\w\._\-]/);
|
||||||
|
state.tokenize = inBlock("meta", "?>");
|
||||||
|
return "meta";
|
||||||
|
} else {
|
||||||
|
type = stream.eat("/") ? "closeTag" : "openTag";
|
||||||
|
state.tokenize = inTag;
|
||||||
|
return "tag bracket";
|
||||||
|
}
|
||||||
|
} else if (ch == "&") {
|
||||||
|
var ok;
|
||||||
|
if (stream.eat("#")) {
|
||||||
|
if (stream.eat("x")) {
|
||||||
|
ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
|
||||||
|
} else {
|
||||||
|
ok = stream.eatWhile(/[\d]/) && stream.eat(";");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
|
||||||
|
}
|
||||||
|
return ok ? "atom" : "error";
|
||||||
|
} else {
|
||||||
|
stream.eatWhile(/[^&<]/);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inTag(stream, state) {
|
||||||
|
var ch = stream.next();
|
||||||
|
if (ch == ">" || (ch == "/" && stream.eat(">"))) {
|
||||||
|
state.tokenize = inText;
|
||||||
|
type = ch == ">" ? "endTag" : "selfcloseTag";
|
||||||
|
return "tag bracket";
|
||||||
|
} else if (ch == "=") {
|
||||||
|
type = "equals";
|
||||||
|
return null;
|
||||||
|
} else if (ch == "<") {
|
||||||
|
state.tokenize = inText;
|
||||||
|
state.state = baseState;
|
||||||
|
state.tagName = state.tagStart = null;
|
||||||
|
var next = state.tokenize(stream, state);
|
||||||
|
return next ? next + " tag error" : "tag error";
|
||||||
|
} else if (/[\'\"]/.test(ch)) {
|
||||||
|
state.tokenize = inAttribute(ch);
|
||||||
|
state.stringStartCol = stream.column();
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else {
|
||||||
|
stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/);
|
||||||
|
return "word";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inAttribute(quote) {
|
||||||
|
var closure = function(stream, state) {
|
||||||
|
while (!stream.eol()) {
|
||||||
|
if (stream.next() == quote) {
|
||||||
|
state.tokenize = inTag;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "string";
|
||||||
|
};
|
||||||
|
closure.isInAttribute = true;
|
||||||
|
return closure;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inBlock(style, terminator) {
|
||||||
|
return function(stream, state) {
|
||||||
|
while (!stream.eol()) {
|
||||||
|
if (stream.match(terminator)) {
|
||||||
|
state.tokenize = inText;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stream.next();
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function doctype(depth) {
|
||||||
|
return function(stream, state) {
|
||||||
|
var ch;
|
||||||
|
while ((ch = stream.next()) != null) {
|
||||||
|
if (ch == "<") {
|
||||||
|
state.tokenize = doctype(depth + 1);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
} else if (ch == ">") {
|
||||||
|
if (depth == 1) {
|
||||||
|
state.tokenize = inText;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
state.tokenize = doctype(depth - 1);
|
||||||
|
return state.tokenize(stream, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "meta";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function Context(state, tagName, startOfLine) {
|
||||||
|
this.prev = state.context;
|
||||||
|
this.tagName = tagName;
|
||||||
|
this.indent = state.indented;
|
||||||
|
this.startOfLine = startOfLine;
|
||||||
|
if (Kludges.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
|
||||||
|
this.noIndent = true;
|
||||||
|
}
|
||||||
|
function popContext(state) {
|
||||||
|
if (state.context) state.context = state.context.prev;
|
||||||
|
}
|
||||||
|
function maybePopContext(state, nextTagName) {
|
||||||
|
var parentTagName;
|
||||||
|
while (true) {
|
||||||
|
if (!state.context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parentTagName = state.context.tagName;
|
||||||
|
if (!Kludges.contextGrabbers.hasOwnProperty(parentTagName) ||
|
||||||
|
!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
popContext(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function baseState(type, stream, state) {
|
||||||
|
if (type == "openTag") {
|
||||||
|
state.tagStart = stream.column();
|
||||||
|
return tagNameState;
|
||||||
|
} else if (type == "closeTag") {
|
||||||
|
return closeTagNameState;
|
||||||
|
} else {
|
||||||
|
return baseState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function tagNameState(type, stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
state.tagName = stream.current();
|
||||||
|
setStyle = "tag";
|
||||||
|
return attrState;
|
||||||
|
} else {
|
||||||
|
setStyle = "error";
|
||||||
|
return tagNameState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function closeTagNameState(type, stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
var tagName = stream.current();
|
||||||
|
if (state.context && state.context.tagName != tagName &&
|
||||||
|
Kludges.implicitlyClosed.hasOwnProperty(state.context.tagName))
|
||||||
|
popContext(state);
|
||||||
|
if (state.context && state.context.tagName == tagName) {
|
||||||
|
setStyle = "tag";
|
||||||
|
return closeState;
|
||||||
|
} else {
|
||||||
|
setStyle = "tag error";
|
||||||
|
return closeStateErr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setStyle = "error";
|
||||||
|
return closeStateErr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeState(type, _stream, state) {
|
||||||
|
if (type != "endTag") {
|
||||||
|
setStyle = "error";
|
||||||
|
return closeState;
|
||||||
|
}
|
||||||
|
popContext(state);
|
||||||
|
return baseState;
|
||||||
|
}
|
||||||
|
function closeStateErr(type, stream, state) {
|
||||||
|
setStyle = "error";
|
||||||
|
return closeState(type, stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function attrState(type, _stream, state) {
|
||||||
|
if (type == "word") {
|
||||||
|
setStyle = "attribute";
|
||||||
|
return attrEqState;
|
||||||
|
} else if (type == "endTag" || type == "selfcloseTag") {
|
||||||
|
var tagName = state.tagName, tagStart = state.tagStart;
|
||||||
|
state.tagName = state.tagStart = null;
|
||||||
|
if (type == "selfcloseTag" ||
|
||||||
|
Kludges.autoSelfClosers.hasOwnProperty(tagName)) {
|
||||||
|
maybePopContext(state, tagName);
|
||||||
|
} else {
|
||||||
|
maybePopContext(state, tagName);
|
||||||
|
state.context = new Context(state, tagName, tagStart == state.indented);
|
||||||
|
}
|
||||||
|
return baseState;
|
||||||
|
}
|
||||||
|
setStyle = "error";
|
||||||
|
return attrState;
|
||||||
|
}
|
||||||
|
function attrEqState(type, stream, state) {
|
||||||
|
if (type == "equals") return attrValueState;
|
||||||
|
if (!Kludges.allowMissing) setStyle = "error";
|
||||||
|
return attrState(type, stream, state);
|
||||||
|
}
|
||||||
|
function attrValueState(type, stream, state) {
|
||||||
|
if (type == "string") return attrContinuedState;
|
||||||
|
if (type == "word" && Kludges.allowUnquoted) {setStyle = "string"; return attrState;}
|
||||||
|
setStyle = "error";
|
||||||
|
return attrState(type, stream, state);
|
||||||
|
}
|
||||||
|
function attrContinuedState(type, stream, state) {
|
||||||
|
if (type == "string") return attrContinuedState;
|
||||||
|
return attrState(type, stream, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
startState: function() {
|
||||||
|
return {tokenize: inText,
|
||||||
|
state: baseState,
|
||||||
|
indented: 0,
|
||||||
|
tagName: null, tagStart: null,
|
||||||
|
context: null};
|
||||||
|
},
|
||||||
|
|
||||||
|
token: function(stream, state) {
|
||||||
|
if (!state.tagName && stream.sol())
|
||||||
|
state.indented = stream.indentation();
|
||||||
|
|
||||||
|
if (stream.eatSpace()) return null;
|
||||||
|
type = null;
|
||||||
|
var style = state.tokenize(stream, state);
|
||||||
|
if ((style || type) && style != "comment") {
|
||||||
|
setStyle = null;
|
||||||
|
state.state = state.state(type || style, stream, state);
|
||||||
|
if (setStyle)
|
||||||
|
style = setStyle == "error" ? style + " error" : setStyle;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
},
|
||||||
|
|
||||||
|
indent: function(state, textAfter, fullLine) {
|
||||||
|
var context = state.context;
|
||||||
|
// Indent multi-line strings (e.g. css).
|
||||||
|
if (state.tokenize.isInAttribute) {
|
||||||
|
if (state.tagStart == state.indented)
|
||||||
|
return state.stringStartCol + 1;
|
||||||
|
else
|
||||||
|
return state.indented + indentUnit;
|
||||||
|
}
|
||||||
|
if (context && context.noIndent) return CodeMirror.Pass;
|
||||||
|
if (state.tokenize != inTag && state.tokenize != inText)
|
||||||
|
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
|
||||||
|
// Indent the starts of attribute names.
|
||||||
|
if (state.tagName) {
|
||||||
|
if (multilineTagIndentPastTag)
|
||||||
|
return state.tagStart + state.tagName.length + 2;
|
||||||
|
else
|
||||||
|
return state.tagStart + indentUnit * multilineTagIndentFactor;
|
||||||
|
}
|
||||||
|
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
|
||||||
|
var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
|
||||||
|
if (tagAfter && tagAfter[1]) { // Closing tag spotted
|
||||||
|
while (context) {
|
||||||
|
if (context.tagName == tagAfter[2]) {
|
||||||
|
context = context.prev;
|
||||||
|
break;
|
||||||
|
} else if (Kludges.implicitlyClosed.hasOwnProperty(context.tagName)) {
|
||||||
|
context = context.prev;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (tagAfter) { // Opening tag spotted
|
||||||
|
while (context) {
|
||||||
|
var grabbers = Kludges.contextGrabbers[context.tagName];
|
||||||
|
if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
|
||||||
|
context = context.prev;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (context && !context.startOfLine)
|
||||||
|
context = context.prev;
|
||||||
|
if (context) return context.indent + indentUnit;
|
||||||
|
else return 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
electricInput: /<\/[\s\w:]+>$/,
|
||||||
|
blockCommentStart: "<!--",
|
||||||
|
blockCommentEnd: "-->",
|
||||||
|
|
||||||
|
configuration: parserConfig.htmlMode ? "html" : "xml",
|
||||||
|
helperType: parserConfig.htmlMode ? "html" : "xml"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeMirror.defineMIME("text/xml", "xml");
|
||||||
|
CodeMirror.defineMIME("application/xml", "xml");
|
||||||
|
if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
|
||||||
|
CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
|
||||||
|
|
||||||
|
});
|
|
@ -485,11 +485,11 @@ $config = array(
|
||||||
//**********************
|
//**********************
|
||||||
//Allowed extensions (lowercase insert)
|
//Allowed extensions (lowercase insert)
|
||||||
//**********************
|
//**********************
|
||||||
'ext_img' => array( 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff','svg', 'ico', 'webp' ), //Images
|
'ext_img' => array( 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff','svg', 'ico', 'webp', 'avif' ), //Images
|
||||||
'ext_file' => array( 'doc', 'docx', 'rtf', 'pdf', 'xls', 'xlsx', 'txt', 'csv', 'html', 'xhtml', 'psd', 'sql', 'log', 'fla', 'xml', 'ade', 'adp', 'mdb', 'accdb', 'ppt', 'pptx', 'odt', 'ots', 'ott', 'odb', 'odg', 'otp', 'otg', 'odf', 'ods', 'odp', 'css', 'ai', 'kmz','dwg', 'dxf', 'hpgl', 'plt', 'spl', 'step', 'stp', 'iges', 'igs', 'sat', 'cgm', 'ics', 'gpx', 'kml', 'ttf', 'eot', 'woff', 'otf', 'woff2', ''), //Files
|
'ext_file' => array( 'doc', 'docx', 'rtf', 'pdf', 'xls', 'xlsx', 'txt', 'csv', 'html', 'xhtml', 'psd', 'sql', 'log', 'fla', 'xml', 'ade', 'adp', 'mdb', 'accdb', 'ppt', 'pptx', 'odt', 'ots', 'ott', 'odb', 'odg', 'otp', 'otg', 'odf', 'ods', 'odp', 'css', 'ai', 'kmz', 'dwg', 'dxf', 'hpgl', 'plt', 'spl', 'step', 'stp', 'iges', 'igs', 'sat', 'cgm', 'ics', 'gpx', 'kml', 'ttf', 'otf', 'woff', 'woff2', ''), //Files
|
||||||
'ext_video' => array( 'mov', 'mpeg', 'm4v', 'mp4', 'avi', 'mpg', 'wma', "flv", "webm" ), //Video
|
'ext_video' => array( 'mov', 'mpeg', 'm4v', 'mp4', 'avi', 'mpg', 'wma', 'webm' ), //Video
|
||||||
'ext_music' => array( 'mp3', 'mpga', 'm4a', 'ac3', 'aiff', 'mid', 'ogg', 'wav' ), //Audio
|
'ext_music' => array( 'mp3', 'mpga', 'm4a', 'ac3', 'aiff', 'mid', 'ogg', 'wav' ), //Audio
|
||||||
'ext_misc' => array( 'zip', 'rar', 'gz', 'tar', 'iso', 'dmg' ), //Archives
|
'ext_misc' => array( '7z', 'zip', 'rar', 'gz', 'tar', 'iso', 'dmg' ), //Archives
|
||||||
|
|
||||||
|
|
||||||
//*********************
|
//*********************
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col12">
|
<div class="col12">
|
||||||
<div class="block">
|
<div class="block">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<div class="row" style="display: flex; flex-wrap: wrap;">
|
<div class="row" style="display: flex; flex-wrap: wrap;">
|
||||||
<div class="col6">
|
<div class="col6">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col6">
|
<div class="col6">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
<div class="row" style="display: flex; flex-wrap: wrap;">
|
<div class="row" style="display: flex; flex-wrap: wrap;">
|
||||||
<div class="col4">
|
<div class="col4">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col4">
|
<div class="col4">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col4">
|
<div class="col4">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
<div class="row" style="display: flex; flex-wrap: wrap;">
|
<div class="row" style="display: flex; flex-wrap: wrap;">
|
||||||
<div class="col3">
|
<div class="col3">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col3">
|
<div class="col3">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col3">
|
<div class="col3">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col3">
|
<div class="col3">
|
||||||
<div class="block" style="height: 100%;">
|
<div class="block" style="height: 100%;">
|
||||||
<h4>Titre du bloc</h4>
|
<div class="blockTitle"><p>Titre du bloc</p></div>
|
||||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam interdum, neque non vulputate hendrerit, arcu turpis dapibus nisl, id scelerisque metus lectus vitae nisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec feugiat dolor et turpis finibus condimentum. Cras sit amet ligula sagittis justo.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
After Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 42 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 99 KiB |
After Width: | Height: | Size: 94 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 101 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 96 KiB |
|
@ -0,0 +1,78 @@
|
||||||
|
/* DayGridView
|
||||||
|
--------------------------------------------------------------------------------------------------*/
|
||||||
|
/* day row structure */
|
||||||
|
.fc-dayGridWeek-view .fc-content-skeleton,
|
||||||
|
.fc-dayGridDay-view .fc-content-skeleton {
|
||||||
|
/* there may be week numbers in these views, so no padding-top */
|
||||||
|
padding-bottom: 1em;
|
||||||
|
/* ensure a space at bottom of cell for user selecting/clicking */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-dayGrid-view .fc-body .fc-row {
|
||||||
|
min-height: 4em;
|
||||||
|
/* ensure that all rows are at least this tall */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* a "rigid" row will take up a constant amount of height because content-skeleton is absolute */
|
||||||
|
.fc-row.fc-rigid {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-row.fc-rigid .fc-content-skeleton {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* week and day number styling */
|
||||||
|
.fc-day-top.fc-other-month {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-dayGrid-view .fc-week-number,
|
||||||
|
.fc-dayGrid-view .fc-day-number {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-dayGrid-view th.fc-week-number,
|
||||||
|
.fc-dayGrid-view th.fc-day-number {
|
||||||
|
padding: 0 2px;
|
||||||
|
/* column headers can't have as much v space */
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-ltr .fc-dayGrid-view .fc-day-top .fc-day-number {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-rtl .fc-dayGrid-view .fc-day-top .fc-day-number {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-ltr .fc-dayGrid-view .fc-day-top .fc-week-number {
|
||||||
|
float: left;
|
||||||
|
border-radius: 0 0 3px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-rtl .fc-dayGrid-view .fc-day-top .fc-week-number {
|
||||||
|
float: right;
|
||||||
|
border-radius: 0 0 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-dayGrid-view .fc-day-top .fc-week-number {
|
||||||
|
min-width: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
color: #808080;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* when week/day number have own column */
|
||||||
|
.fc-dayGrid-view td.fc-week-number {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fc-dayGrid-view td.fc-week-number > * {
|
||||||
|
/* work around the way we do column resizing and ensure a minimum width */
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 1.25em;
|
||||||
|
}
|