WP Maintenance - Version 3.0

Version Description

This version is stable

=

Download this release

Release Info

Developer Florent73
Plugin Icon 128x128 WP Maintenance
Version 3.0
Comparing to
See all releases

Code changes from version 2.8.4 to 3.0

Files changed (101) hide show
  1. classes/countdown.php +93 -0
  2. classes/slider.php +181 -0
  3. classes/wp-maintenance.php +915 -0
  4. css/custom-editor-style.css +5 -0
  5. css/wpm-admin.css +105 -5
  6. images/extension-send-pdf-for-cf7.png +0 -0
  7. images/logo-Extensions.png +0 -0
  8. images/wpm-menu-icon.png +0 -0
  9. wpm_fonctions.php → includes/functions.php +346 -0
  10. includes/shortcodes.php +78 -0
  11. js/codemirror/addon/hint/anyword-hint.js +41 -0
  12. js/codemirror/addon/hint/css-hint.js +60 -0
  13. js/codemirror/addon/hint/html-hint.js +348 -0
  14. js/codemirror/addon/hint/javascript-hint.js +155 -0
  15. js/codemirror/addon/hint/show-hint.css +36 -0
  16. js/codemirror/addon/hint/show-hint.js +438 -0
  17. js/codemirror/addon/hint/sql-hint.js +271 -0
  18. js/codemirror/addon/hint/xml-hint.js +110 -0
  19. js/codemirror/addon/selection/active-line.js +72 -0
  20. js/codemirror/addon/selection/mark-selection.js +118 -0
  21. js/codemirror/addon/selection/selection-pointer.js +98 -0
  22. js/codemirror/codemirror.css +341 -0
  23. js/codemirror/codemirror.js +9113 -0
  24. js/codemirror/css.js +829 -0
  25. js/codemirror/htmlmixed.js +152 -0
  26. js/codemirror/javascript.js +797 -0
  27. js/codemirror/theme/3024-day.css +41 -0
  28. js/codemirror/theme/3024-night.css +39 -0
  29. js/codemirror/theme/abcdef.css +32 -0
  30. js/codemirror/theme/ambiance-mobile.css +5 -0
  31. js/codemirror/theme/ambiance.css +74 -0
  32. js/codemirror/theme/base16-dark.css +38 -0
  33. js/codemirror/theme/base16-light.css +38 -0
  34. js/codemirror/theme/bespin.css +34 -0
  35. js/codemirror/theme/blackboard.css +32 -0
  36. js/codemirror/theme/cobalt.css +25 -0
  37. js/codemirror/theme/colorforth.css +33 -0
  38. js/codemirror/theme/dracula.css +40 -0
  39. js/codemirror/theme/duotone-dark.css +35 -0
  40. js/codemirror/theme/duotone-light.css +36 -0
  41. js/codemirror/theme/eclipse.css +23 -0
  42. js/codemirror/theme/elegant.css +13 -0
  43. js/codemirror/theme/erlang-dark.css +34 -0
  44. js/codemirror/theme/hopscotch.css +34 -0
  45. js/codemirror/theme/icecoder.css +43 -0
  46. js/codemirror/theme/isotope.css +34 -0
  47. js/codemirror/theme/lesser-dark.css +47 -0
  48. js/codemirror/theme/liquibyte.css +95 -0
  49. js/codemirror/theme/material.css +53 -0
  50. js/codemirror/theme/mbo.css +37 -0
  51. js/codemirror/theme/mdn-like.css +46 -0
  52. js/codemirror/theme/midnight.css +45 -0
  53. js/codemirror/theme/monokai.css +36 -0
  54. js/codemirror/theme/neat.css +12 -0
  55. js/codemirror/theme/neo.css +43 -0
  56. js/codemirror/theme/night.css +27 -0
  57. js/codemirror/theme/panda-syntax.css +85 -0
  58. js/codemirror/theme/paraiso-dark.css +38 -0
  59. js/codemirror/theme/paraiso-light.css +38 -0
  60. js/codemirror/theme/pastel-on-dark.css +52 -0
  61. js/codemirror/theme/railscasts.css +34 -0
  62. js/codemirror/theme/rubyblue.css +25 -0
  63. js/codemirror/theme/seti.css +44 -0
  64. js/codemirror/theme/solarized.css +169 -0
  65. js/codemirror/theme/the-matrix.css +30 -0
  66. js/codemirror/theme/tomorrow-night-bright.css +35 -0
  67. js/codemirror/theme/tomorrow-night-eighties.css +38 -0
  68. js/codemirror/theme/ttcn.css +64 -0
  69. js/codemirror/theme/twilight.css +32 -0
  70. js/codemirror/theme/vibrant-ink.css +34 -0
  71. js/codemirror/theme/xq-dark.css +53 -0
  72. js/codemirror/theme/xq-light.css +43 -0
  73. js/codemirror/theme/yeti.css +44 -0
  74. js/codemirror/theme/zenburn.css +37 -0
  75. js/codemirror/vbscript.js +350 -0
  76. js/codemirror/xml.js +394 -0
  77. js/jquery.sticky.js +297 -0
  78. js/wpm-cpt-script.js +1 -1
  79. js/wpm-script.js +50 -0
  80. languages/wp-maintenance-fr_CA.mo +0 -0
  81. languages/wp-maintenance-fr_CA.po +0 -737
  82. languages/wp-maintenance-fr_FR.mo +0 -0
  83. languages/wp-maintenance-fr_FR.po +482 -333
  84. languages/wp-maintenance.pot +397 -186
  85. readme.txt +23 -11
  86. screenshot-1.png +0 -0
  87. screenshot-2.png +0 -0
  88. screenshot-3.png +0 -0
  89. screenshot-4.png +0 -0
  90. screenshot-5.png +0 -0
  91. screenshot-6.png +0 -0
  92. screenshot-7.png +0 -0
  93. uninstall.php +0 -18
  94. views/wp-maintenance-colors.php +238 -0
  95. views/wp-maintenance-countdown.php +196 -0
  96. views/wp-maintenance-css.php +147 -0
  97. views/wp-maintenance-dashboard.php +294 -0
  98. views/wp-maintenance-picture.php +264 -0
  99. views/wp-maintenance-settings.php +143 -0
  100. wp-maintenance-admin.php +0 -917
  101. wp-maintenance.php +2 -508
classes/countdown.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class WPM_Countdown extends WP_maintenance {
5
+
6
+
7
+ var $errors = array();
8
+
9
+ public static function display($date = '') {
10
+
11
+ // Récupère les paramètres sauvegardés
12
+ $paramMMode = wp_maintenance::wpm_get_options();
13
+ $Counter = '';
14
+ /*********** AJOUT COMPTEUR SUIVANT LES PARAMETRES *********/
15
+ if( isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==1 && !empty($date) ) {
16
+
17
+ if( isset($paramMMode['cptdate']) && !empty($paramMMode['cptdate']) ) {
18
+
19
+ if( !isset($paramMMode['disable']) ) { $paramMMode['disable'] = 0; }
20
+ $Counter = '
21
+ <div id="countdown">
22
+ <script language="JavaScript">
23
+ TargetDate = "'.$date.'";
24
+ BackColor = "'.$paramMMode['color_cpt_bg'].'";
25
+ FontSize = "'.$paramMMode['date_cpt_size'].'";
26
+ ForeColor = "'.$paramMMode['color_cpt'].'";
27
+ Disable = "'.$paramMMode['disable'].'";
28
+ UrlDisable = "'.get_option( 'siteurl').'";
29
+ FontFamily = "'.$paramMMode['font_cpt'].'";
30
+ CountActive = true;
31
+ CountStepper = -1;
32
+ LeadingZero = true;
33
+ ';
34
+ $Counter .= " DisplayFormat = '<div id=\"wpm-cpt-day\">%%D%%<br /><span id=\"wpm-cpt-days-span\">".__('Days', 'wp-maintenance')."</span></div><div id=\"wpm-cpt-hours\">%%H%%<br /><span id=\"wpm-cpt-hours-span\">".__('Hours', 'wp-maintenance')."</span></div><div id=\"wpm-cpt-minutes\">%%M%%<br /><span id=\"wpm-cpt-minutes-span\">".__('Minutes', 'wp-maintenance')."</span></div>";
35
+ if( isset($paramMMode['active_cpt_s']) && $paramMMode['active_cpt_s']==1 ) {
36
+ $Counter .= '<div id="wpm-cpt-seconds">%%S%%<br /><span id="wpm-cpt-seconds-span">'.__('Seconds', 'wp-maintenance').'</span></div>';
37
+ }
38
+ $Counter .= "';";
39
+ if( isset($paramMMode['message_cpt_fin']) && $paramMMode['message_cpt_fin']!='' ) {
40
+ $Counter .= '
41
+ FinishMessage = "'.trim( stripslashes( preg_replace("/(\r\n|\n|\r)/", "", $paramMMode['message_cpt_fin']) ) ).'";';
42
+ }
43
+ $Counter .= '
44
+ </script>';
45
+ $Counter .= '
46
+ <script language="JavaScript" src="'.WP_PLUGIN_URL.'/wp-maintenance/js/wpm-cpt-script.js"></script>
47
+ </div>';
48
+ }
49
+ }
50
+
51
+ return $Counter;
52
+ }
53
+
54
+ public static function css() {
55
+
56
+ // Récupère les paramètres sauvegardés
57
+ $paramMMode = wp_maintenance::wpm_get_options();
58
+
59
+ return '
60
+ #wpm-cpt-day, #wpm-cpt-hours, #wpm-cpt-minutes, #wpm-cpt-seconds {}
61
+ .cptR-rec_countdown {';
62
+ if( isset($paramMMode['date_cpt_size']) ) { $wpmStyle .= 'font-size:'.$paramMMode['date_cpt_size'].'px;'; }
63
+ if( isset($paramMMode['font_cpt']) ) { $wpmStyle .= 'font-family: '.wpm_format_font($paramMMode['font_cpt']).', serif;'; }
64
+ $wpmStyle .= '
65
+ }
66
+
67
+ @media screen and (min-width: 200px) and (max-width: 480px) {
68
+
69
+ .cptR-rec_countdown {';
70
+ if( isset($paramMMode['date_cpt_size']) ) { $wpmStyle .= 'font-size:'.($paramMMode['date_cpt_size']*0.6).'px;'; }
71
+ $wpmStyle .= '}
72
+ div.bloc {';
73
+ if( isset($paramMMode['font_bottom_size']) ) { $wpmStyle .= 'font-size: '.($paramMMode['font_bottom_size']*0.8).'px;'; }
74
+ $wpmStyle .= '}
75
+ #wpm-cpt-day, #wpm-cpt-hours, #wpm-cpt-minutes, #wpm-cpt-seconds {
76
+ /*width:20%;*/
77
+ }
78
+
79
+ }
80
+ @media (max-width: 640px) {
81
+ .cptR-rec_countdown {';
82
+ if( isset($paramMMode['date_cpt_size']) ) { $wpmStyle .= 'font-size:'.($paramMMode['date_cpt_size']*0.5).'px;'; }
83
+ $wpmStyle .= '
84
+ text-align:center;
85
+ }
86
+ #wpm-cpt-day, #wpm-cpt-hours, #wpm-cpt-minutes, #wpm-cpt-seconds {
87
+ /*width:20%;*/
88
+ text-align:center;
89
+ }
90
+ }';
91
+ }
92
+
93
+ }
classes/slider.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class WPM_Slider extends WP_maintenance {
5
+
6
+ var $errors = array();
7
+
8
+ public $displaySlider = '';
9
+ public $position = 'belowtext';
10
+ public $slides = '';
11
+
12
+ public static function slider_css() {
13
+
14
+ // Récupère les paramètres sauvegardés
15
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
16
+ $paramMMode = get_option('wp_maintenance_settings');
17
+
18
+ if( isset($paramSliderOptions['slider_width']) ) { $wpmSliderWidth = $paramSliderOptions['slider_width']; } else { $wpmSliderWidth = 50; }
19
+ $addCssSlider = '
20
+ <link rel="stylesheet" href="'.WP_PLUGIN_URL.'/wp-maintenance/css/wpm-slideshow.css">
21
+ <link rel="stylesheet" href="'.WP_PLUGIN_URL.'/wp-maintenance/css/wpm-responsiveslides.css">
22
+ <style type=\'text/css\'>
23
+ .centered-btns_nav { background: transparent url("'.WP_PLUGIN_URL.'/wp-maintenance/images/themes.gif") no-repeat left top; }
24
+ .large-btns_nav { background: #000 url("'.WP_PLUGIN_URL.'/wp-maintenance/images/themes.gif") no-repeat left 50%; }
25
+ .callbacks_container { width: '.$wpmSliderWidth.'%; }
26
+ @media (max-width: 640px) {
27
+ .callbacks_container {
28
+ width: 95%;
29
+ }
30
+ .callbacks_nav {
31
+ top: 57%;
32
+ }
33
+ }
34
+ .callbacks_nav { background: transparent url("'.WP_PLUGIN_URL.'/wp-maintenance/images/themes.gif") no-repeat left top; }
35
+ </style>
36
+
37
+ ';
38
+
39
+ return $addCssSlider;
40
+ }
41
+
42
+ public static function slider_scripts() {
43
+
44
+ $addScriptSlider = '
45
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
46
+ <script src="'.WP_PLUGIN_URL.'/wp-maintenance/js/wpm-responsiveslides.min.js"></script>';
47
+ return $addScriptSlider;
48
+
49
+ }
50
+ public static function slider_functions() {
51
+
52
+ // Récupère les paramètres sauvegardés
53
+ $paramMMode = wp_maintenance::wpm_get_options();
54
+
55
+ if(get_option('wp_maintenance_slider')) { extract(get_option('wp_maintenance_slider')); }
56
+ $paramSlider = get_option('wp_maintenance_slider');
57
+
58
+ if(get_option('wp_maintenance_slider_options')) { extract(get_option('wp_maintenance_slider_options')); }
59
+ $paramSliderOptions = get_option('wp_maintenance_slider_options');
60
+
61
+ if( isset($paramSlider['slider_image']) && !empty($paramSlider['slider_image']) ) {
62
+ $lastKeySlide = key($paramSlider['slider_image']);
63
+ }
64
+
65
+ $wpmSliderAuto = 'true';
66
+ if( isset( $paramSliderOptions['slider_auto'] ) && $paramSliderOptions['slider_auto']!='' ) {
67
+ $wpmSliderAuto = $paramSliderOptions['slider_auto'];
68
+ }
69
+ $wpmSliderSpeed = 500;
70
+ if( isset( $paramSliderOptions['slider_speed'] ) && $paramSliderOptions['slider_speed']!='' ) {
71
+ $wpmSliderSpeed = $paramSliderOptions['slider_speed'];
72
+ }
73
+ $wpmSliderNav = 'false';
74
+ if( isset( $paramSliderOptions['slider_nav'] ) && $paramSliderOptions['slider_nav']!='' ) {
75
+ $wpmSliderNav = $paramSliderOptions['slider_nav'];
76
+ }
77
+
78
+
79
+ $addScriptSlideshow = '
80
+ <script>
81
+ // You can also use "$(window).load(function() {"
82
+ $(function () {';
83
+
84
+ $addScriptSlideshow .= '
85
+ $("#wpmslider").responsiveSlides({
86
+ auto: '.$wpmSliderAuto.',
87
+ pager: false,
88
+ nav: '.$wpmSliderNav.',
89
+ speed: '.$wpmSliderSpeed.',
90
+ prevText: "'.__('Previous', 'wp-maintenance').'",
91
+ nextText: "'.__('Next', 'wp-maintenance').'",
92
+ namespace: "callbacks",';
93
+ $addScriptSlideshow .= "
94
+ before: function () {
95
+ $('.events').append(\"<li>before event fired.</li>\");
96
+ },
97
+ after: function () {
98
+ $('.events').append(\"<li>after event fired.</li>\");
99
+ }
100
+ });";
101
+
102
+ $addScriptSlideshow .= '
103
+ });
104
+ </script>';
105
+
106
+ return $addScriptSlideshow;
107
+ }
108
+
109
+ public static function slidershow($position) {
110
+
111
+ // Récupère les paramètres sauvegardés
112
+ $paramMMode = wp_maintenance::wpm_get_options();
113
+ $positionSlider = '';
114
+
115
+ if( isset($paramMMode['enable_slider']) && $paramMMode['enable_slider']==1 ) {
116
+
117
+ if(get_option('wp_maintenance_slider')) { extract(get_option('wp_maintenance_slider')); }
118
+ $paramSlider = get_option('wp_maintenance_slider');
119
+
120
+ if(get_option('wp_maintenance_slider_options')) { extract(get_option('wp_maintenance_slider_options')); }
121
+ $paramSliderOptions = get_option('wp_maintenance_slider_options');
122
+
123
+ $slides = '
124
+
125
+ <!-- Slideshow 4 -->
126
+ <div class="callbacks_container">
127
+ <ul class="rslides" id="wpmslider">';
128
+ foreach($paramSlider['slider_image'] as $numSlide=>$slide) {
129
+
130
+ if( $paramSlider['slider_image'][$numSlide]['image'] != '' ) {
131
+ $slideImg = '';
132
+ if( isset($paramSlider['slider_image'][$numSlide]['image']) ) {
133
+ $slideImg = $paramSlider['slider_image'][$numSlide]['image'];
134
+ }
135
+ $slideLink = '';
136
+ if( isset($paramSlider['slider_image'][$numSlide]['link']) ) {
137
+ $slideLink = $paramSlider['slider_image'][$numSlide]['link'];
138
+ }
139
+ $slideText = '';
140
+ if( isset($paramSlider['slider_image'][$numSlide]['text']) ) {
141
+ $slideText = stripslashes($paramSlider['slider_image'][$numSlide]['text']);
142
+ }
143
+ $slides .= '
144
+ <li>';
145
+ if( $slideLink!='' && filter_var($slideLink, FILTER_VALIDATE_URL) ) {
146
+ $slides .= '
147
+ <a href="'.$slideLink.'" target="_bank">';
148
+ }
149
+ $slides .= '<img src="'.$slideImg.'" alt="'.$slideText.'" title="'.$slideText.'">';
150
+ if( $slideText!='' ) {
151
+ $slides .= '
152
+ <p class="caption">'.$slideText.'</p>';
153
+ }
154
+ if( $slideLink!='' && filter_var($slideLink, FILTER_VALIDATE_URL) ) {
155
+ $slides .= '</a>';
156
+ }
157
+ $slides .= '
158
+ </li>';
159
+ }
160
+ }
161
+ $slides .= '</ul>
162
+ </div>';
163
+
164
+ $positionSlider = $paramSliderOptions['slider_position'];
165
+
166
+ if( isset($position) && $position!='' ) {
167
+
168
+ if( $positionSlider == $position ) {
169
+ $positionSlider = $slides;
170
+ } else {
171
+ $positionSlider = '';
172
+ }
173
+
174
+ }
175
+
176
+ }
177
+
178
+ return $positionSlider;
179
+ }
180
+
181
+ }
classes/wp-maintenance.php ADDED
@@ -0,0 +1,915 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class WP_maintenance {
4
+
5
+ protected static $instance;
6
+
7
+ public static function init() {
8
+ is_null( self::$instance ) AND self::$instance = new self;
9
+ return self::$instance;
10
+ }
11
+
12
+ public function hooks() {
13
+
14
+ /* Version du plugin */
15
+ $option['wp_maintenance_version'] = WPM_VERSION;
16
+ if( !get_option('wp_maintenance_version') ) {
17
+ add_option('wp_maintenance_version', $option);
18
+ } else if ( get_option('wp_maintenance_version') != WPM_VERSION ) {
19
+ update_option('wp_maintenance_version', WPM_VERSION);
20
+ }
21
+
22
+ add_action( 'admin_menu', array( $this, 'wpm_add_admin') );
23
+ add_filter( 'plugin_action_links', array( $this, 'wpm_plugin_actions'), 10, 2 );
24
+ add_action( 'admin_head', array( $this, 'wpm_admin_head') );
25
+ add_action( 'init', array( $this, 'wpm_date_picker') );
26
+ add_action( 'admin_bar_menu', array( $this, 'wpm_add_menu_admin_bar'), 999 );
27
+ add_action( 'admin_footer', array( $this, 'wpm_print_footer_scripts') );
28
+ add_action( 'template_redirect', array( $this, 'wpm_maintenance_mode') );
29
+ add_editor_style( plugins_url('../css/custom-editor-style.css', __FILE__ ) );
30
+ register_deactivation_hook(__FILE__, 'wpm_uninstall');
31
+
32
+
33
+ }
34
+
35
+ public static function wpm_dashboard_install() {
36
+
37
+ $wpMaintenanceAdminOptions = array(
38
+ 'enable' => 0,
39
+ 'color_bg' => "#f1f1f1",
40
+ 'color_txt' => '#888888',
41
+ 'color_bg_bottom' => '#333333',
42
+ 'color_text_bottom' => '#FFFFFF',
43
+ 'titre_maintenance' => __('This site is down for maintenance', 'wp-maintenance'),
44
+ 'text_maintenance' => __('Come back quickly!', 'wp-maintenance'),
45
+ 'userlimit' => 'administrator',
46
+ 'image' => WP_PLUGIN_URL.'/wp-maintenance/images/default.png',
47
+ 'font_title' => 'PT Sans',
48
+ 'font_title_size' => 40,
49
+ 'font_title_weigth' => 'normal',
50
+ 'font_title_style' => '',
51
+ 'font_text_style' => '',
52
+ 'font_text' => 'Metrophobic',
53
+ 'font_text_size' => 18,
54
+ 'font_text_bottom' => 'PT Sans',
55
+ 'font_text_weigth' => 'normal',
56
+ 'font_bottom_size' => 12,
57
+ 'font_bottom_weigth' => 'normal',
58
+ 'font_bottom_style' => '',
59
+ 'font_cpt' => 'PT Sans',
60
+ 'color_cpt' => '#333333',
61
+ 'enable_demo' => 0,
62
+ 'color_field_text' => '#333333',
63
+ 'color_text_button' => '#ffffff',
64
+ 'color_field_background' => '#F1F1F1',
65
+ 'color_field_border' => '#333333',
66
+ 'color_button_onclick' => '#333333',
67
+ 'color_button_hover' => '#cccccc',
68
+ 'color_button' => '#1e73be',
69
+ 'image_width' => 250,
70
+ 'image_height' => 100,
71
+ 'newletter' => 0,
72
+ 'active_cpt' => 0,
73
+ 'newletter_font_text' => 'PT Sans',
74
+ 'newletter_size' => 18,
75
+ 'newletter_font_style' => '',
76
+ 'newletter_font_weigth' => 'normal',
77
+ 'type_newletter' => 'shortcode',
78
+ 'title_newletter' => '',
79
+ 'code_newletter' => '',
80
+ 'code_analytics' => '',
81
+ 'domain_analytics' => $_SERVER['SERVER_NAME'],
82
+ 'text_bt_maintenance' => '',
83
+ 'add_wplogin' => '',
84
+ 'b_enable_image' => 0,
85
+ 'disable' => 0,
86
+ 'pageperso' => 0,
87
+ 'date_cpt_size' => 40,
88
+ 'color_bg_header' => '#f1f1f1',
89
+ 'add_wplogin_title' => '',
90
+ 'headercode' => '',
91
+ 'message_cpt_fin' => '',
92
+ 'b_repeat_image' => '',
93
+ 'color_cpt_bg' => '',
94
+ 'enable_slider' => 0,
95
+ 'container_active' => 0,
96
+ 'container_color' => '#ffffff',
97
+ 'container_opacity' => '0.5',
98
+ 'container_width' => 80,
99
+ 'dashboard_delete_db' => 'Yes'
100
+
101
+ );
102
+ $getMaintenanceSettings = get_option('wp_maintenance_settings');
103
+ if ( empty($getMaintenanceSettings) ) {
104
+ foreach ($wpMaintenanceAdminOptions as $key => $option) {
105
+ $wpMaintenanceAdminOptions[$key] = $option;
106
+ }
107
+ add_option('wp_maintenance_settings', $wpMaintenanceAdminOptions);
108
+ }
109
+
110
+ if(!get_option('wp_maintenance_active')) { add_option('wp_maintenance_active', 0); }
111
+
112
+ if(!get_option('wp_maintenance_style') or get_option('wp_maintenance_style')=='') {
113
+ add_option('wp_maintenance_style', wpm_print_style());
114
+ }
115
+
116
+ }
117
+
118
+ public static function wpm_dashboard_remove() {
119
+
120
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
121
+ $paramMMode = get_option('wp_maintenance_settings');
122
+
123
+ delete_option('wp_maintenance_active');
124
+
125
+ if( isset($paramMMode['dashboard_delete_db']) && $paramMMode['dashboard_delete_db'] == 'Yes' ) {
126
+
127
+ delete_option('wp_maintenance_settings');
128
+ delete_option('wp_maintenance_version');
129
+ delete_option('wp_maintenance_style');
130
+ delete_option('wp_maintenance_limit');
131
+ delete_option('wp_maintenance_active');
132
+ delete_option('wp_maintenance_social');
133
+ delete_option('wp_maintenance_social_options');
134
+ delete_option('wp_maintenance_social');
135
+ delete_option('wp_maintenance_slider_options');
136
+ delete_option('wp_maintenance_slider');
137
+ }
138
+
139
+ }
140
+
141
+ // Add "Réglages" link on plugins page
142
+ function wpm_plugin_actions( $links, $file ) {
143
+
144
+ if ( $file != WPM_PLUGIN_BASENAME ) {
145
+ return $links;
146
+ } else {
147
+ $wpm_settings_link = '<a href="admin.php?page=wp-maintenance">'
148
+ . esc_html( __( 'Settings', 'wp-maintenance' ) ) . '</a>';
149
+
150
+ array_unshift( $links, $wpm_settings_link );
151
+
152
+ return $links;
153
+ }
154
+ }
155
+
156
+ /* Ajout feuille CSS pour l'admin barre */
157
+ function wpm_admin_head() {
158
+
159
+ global $current_user;
160
+ global $_wp_admin_css_colors;
161
+
162
+ if (isset($_GET['page']) && strpos($_GET['page'], 'wp-maintenance') !==false) {
163
+ echo '<link rel="stylesheet" type="text/css" media="all" href="' .WPM_PLUGIN_URL.'css/wpm-admin.css">';
164
+
165
+ $admin_color = get_user_option( 'admin_color', get_current_user_id() );
166
+ $colors = $_wp_admin_css_colors[$admin_color]->colors;
167
+
168
+ echo '<style>
169
+ a.wpmadashicons:link { text-decoration:none;color: '.$colors[0].'!important; }
170
+ a.wpmadashicons:hover { text-decoration:none;color: '.$colors[2].'!important; }
171
+ .wpmadashicons { color: '.$colors[0].'!important; }
172
+ .wpmadashicons:hover { color: '.$colors[2].'!important; }
173
+ .switch-field input:checked + label { background-color: '.$colors[2].'; }
174
+ #wpadminbar .wpmbackground { background-color: '.$colors[1].'; }
175
+ .wpm-form-field {
176
+ border: 1px solid '.$colors[2].'!important;
177
+ background: #fff;
178
+ -webkit-border-radius: 4px;
179
+ -moz-border-radius: 4px;
180
+ border-radius: 4px;
181
+ color: '.$colors[2].'!important;
182
+ -webkit-box-shadow: rgba(255,255,255,0.4) 0 1px 0, inset rgba(000,000,000,0.7) 0 0px 0px;
183
+ -moz-box-shadow: rgba(255,255,255,0.4) 0 1px 0, inset rgba(000,000,000,0.7) 0 0px 0px;
184
+ box-shadow: rgba(255,255,255,0.4) 0 1px 0, inset rgba(000,000,000,0.7) 0 0px 0px;
185
+ padding:8px;
186
+ /*margin-bottom:20px;*/
187
+ }
188
+ .wpm-form-field:focus {
189
+ background: #fff!important;
190
+ color: '.$colors[0].'!important;
191
+ }
192
+ .switch-field input:checked + label:last-of-type {
193
+ background-color: '.$colors[0].'!important;
194
+ color:#e4e4e4!important;
195
+ }
196
+
197
+
198
+ </style>';
199
+ }
200
+ }
201
+ /* Ajout Notification admin barre */
202
+ function wpm_add_menu_admin_bar( $wp_admin_bar ) {
203
+
204
+ $checkActive = get_option('wp_maintenance_active');
205
+ if( isset($checkActive) && $checkActive==1 && !is_network_admin() ) {
206
+
207
+ $textAdmin = '<img src="'.WPM_PLUGIN_URL.'images/lock.png" style="padding: 6px 0;float:left;margin-right: 6px;">'.__('Maintenance mode activated!', 'wp-maintenance');
208
+
209
+ $args = array(
210
+ 'id' => 'wpm-info', // id of the existing child node (New > Post)
211
+ 'title' => $textAdmin, // alter the title of existing node
212
+ 'href' => 'admin.php?page=wp-maintenance', // Lien du menu
213
+ 'parent' => false, // set parent to false to make it a top level (parent) node
214
+ 'meta' => array(
215
+ 'class' => 'wpmbackground'
216
+ )
217
+ );
218
+ $wp_admin_bar->add_node( $args );
219
+ }
220
+ }
221
+
222
+ /* DATEPICKER */
223
+ function wpm_date_picker() {
224
+
225
+ if (isset($_GET['page']) && strpos($_GET['page'], 'wp-maintenance') !==false) {
226
+ wp_enqueue_script( 'jquery' );
227
+ wp_enqueue_script('jquery-ui-datepicker');
228
+ wp_enqueue_style('jquery-style', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');
229
+ }
230
+
231
+ }
232
+
233
+ function wpm_init_wysiwyg() {
234
+ wp_enqueue_script('editor');
235
+ add_thickbox();
236
+ wp_enqueue_script('media-upload');
237
+ add_action('admin_print_footer_scripts', 'wp_tiny_mce', 25);
238
+ wp_enqueue_script('quicktags');
239
+ }
240
+
241
+ public static function wpm_get_options() {
242
+
243
+ // Récupère les paramètres sauvegardés
244
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
245
+ $paramMMode = get_option('wp_maintenance_settings');
246
+
247
+ return $paramMMode;
248
+ }
249
+
250
+ function wpm_add_admin() {
251
+
252
+ add_menu_page( 'WP Maintenance Settings', 'WP Maintenance', 'manage_options', 'wp-maintenance', array( $this, 'wpm_dashboard_page'), plugins_url( '/wp-maintenance/images/wpm-menu-icon.png' ) );
253
+
254
+ add_submenu_page( 'wp-maintenance', 'WP Maintenance > '.__('General', 'wp-maintenance'), __('General', 'wp-maintenance'), 'manage_options', 'wp-maintenance', array( $this, 'wpm_dashboard_page') );
255
+
256
+ add_submenu_page( 'wp-maintenance', 'WP Maintenance > '.__('Colors & Fonts', 'wp-maintenance'), __('Colors & Fonts', 'wp-maintenance'), 'manage_options', 'wp-maintenance-colors', array( $this, 'wpm_colors_page') );
257
+
258
+ add_submenu_page( 'wp-maintenance', 'WP Maintenance > '.__('Pictures', 'wp-maintenance'), __('Pictures', 'wp-maintenance'), 'manage_options', 'wp-maintenance-picture', array( $this, 'wpm_picture_page') );
259
+
260
+ add_submenu_page( 'wp-maintenance', 'WP Maintenance > '.__('CountDown', 'wp-maintenance'), __('CountDown', 'wp-maintenance'), 'manage_options', 'wp-maintenance-countdown', array( $this, 'wpm_countdown_page') );
261
+
262
+ add_submenu_page( 'wp-maintenance', 'WP Maintenance > '.__('CSS Style', 'wp-maintenance'), __('CSS Style', 'wp-maintenance'), 'manage_options', 'wp-maintenance-css', array( $this, 'wpm_css_page') );
263
+
264
+ add_submenu_page( 'wp-maintenance', 'WP Maintenance > '.__('Settings', 'wp-maintenance'), __('Settings', 'wp-maintenance'), 'manage_options', 'wp-maintenance-settings', array( $this, 'wpm_settings_page') );
265
+
266
+ /*add_submenu_page( 'wp-maintenance', 'WP Maintenance > '.__('About', 'wp-maintenance'), __('About', 'wp-maintenance'), 'manage_options', 'wp-maintenance-about', array( $this, 'wpm_about_page') );*/
267
+
268
+ $wp_maintenanceAdminOptions = array(
269
+ 'enable' => 0,
270
+ 'color_bg' => "#f1f1f1",
271
+ 'color_txt' => '#888888',
272
+ 'color_bg_bottom' => '#333333',
273
+ 'color_text_bottom' => '#FFFFFF',
274
+ 'titre_maintenance' => __('This site is down for maintenance', 'wp-maintenance'),
275
+ 'text_maintenance' => __('Come back quickly!', 'wp-maintenance'),
276
+ 'userlimit' => 'administrator',
277
+ 'image' => WP_PLUGIN_URL.'/wp-maintenance/images/default.png',
278
+ 'font_title' => 'PT Sans',
279
+ 'font_title_size' => 40,
280
+ 'font_title_weigth' => 'normal',
281
+ 'font_title_style' => '',
282
+ 'font_text_style' => '',
283
+ 'font_text' => 'Metrophobic',
284
+ 'font_text_size' => 18,
285
+ 'font_text_bottom' => 'PT Sans',
286
+ 'font_text_weigth' => 'normal',
287
+ 'font_bottom_size' => 12,
288
+ 'font_bottom_weigth' => 'normal',
289
+ 'font_bottom_style' => '',
290
+ 'font_cpt' => 'PT Sans',
291
+ 'color_cpt' => '#333333',
292
+ 'enable_demo' => 0,
293
+ 'color_field_text' => '#333333',
294
+ 'color_text_button' => '#ffffff',
295
+ 'color_field_background' => '#F1F1F1',
296
+ 'color_field_border' => '#333333',
297
+ 'color_button_onclick' => '#333333',
298
+ 'color_button_hover' => '#cccccc',
299
+ 'color_button' => '#1e73be',
300
+ 'image_width' => 250,
301
+ 'image_height' => 100,
302
+ 'newletter' => 0,
303
+ 'active_cpt' => 0,
304
+ 'newletter_font_text' => 'PT Sans',
305
+ 'newletter_size' => 18,
306
+ 'newletter_font_style' => '',
307
+ 'newletter_font_weigth' => 'normal',
308
+ 'type_newletter' => 'shortcode',
309
+ 'title_newletter' => '',
310
+ 'code_newletter' => '',
311
+ 'code_analytics' => '',
312
+ 'domain_analytics' => $_SERVER['SERVER_NAME'],
313
+ 'text_bt_maintenance' => '',
314
+ 'add_wplogin' => '',
315
+ 'b_enable_image' => 0,
316
+ 'disable' => 0,
317
+ 'pageperso' => 0,
318
+ 'date_cpt_size' => 40,
319
+ 'color_bg_header' => '#f1f1f1',
320
+ 'add_wplogin_title' => '',
321
+ 'headercode' => '',
322
+ 'message_cpt_fin' => '',
323
+ 'b_repeat_image' => '',
324
+ 'color_cpt_bg' => '',
325
+ 'enable_slider' => 0,
326
+ 'container_active' => 0,
327
+ 'container_color' => '#ffffff',
328
+ 'container_opacity' => '0.5',
329
+ 'container_width' => 80
330
+
331
+ );
332
+ $getMaintenanceSettings = get_option('wp_maintenance_settings');
333
+ if ( empty($getMaintenanceSettings) ) {
334
+ foreach ($wp_maintenanceAdminOptions as $key => $option) {
335
+ $wp_maintenanceAdminOptions[$key] = $option;
336
+ }
337
+ update_option('wp_maintenance_settings', $wp_maintenanceAdminOptions);
338
+ }
339
+
340
+ if(!get_option('wp_maintenance_active')) { update_option('wp_maintenance_active', 0); }
341
+
342
+ if(!get_option('wp_maintenance_style') or get_option('wp_maintenance_style')=='') {
343
+ update_option('wp_maintenance_style', wpm_print_style());
344
+ }
345
+
346
+ // If you're not including an image upload then you can leave this function call out
347
+ if (isset($_GET['page']) && strpos($_GET['page'], 'wp-maintenance') !==false) {
348
+
349
+ wp_enqueue_script('media-upload');
350
+ wp_enqueue_script('thickbox');
351
+
352
+ wp_register_script('wpm-my-upload', WP_PLUGIN_URL.'/wp-maintenance/js/wpm-script.js', array('jquery','media-upload','thickbox'));
353
+ wp_enqueue_script('wpm-my-upload');
354
+
355
+ wp_enqueue_style('jquery-defaut-style', WPM_PLUGIN_URL.'js/lib/themes/default.css');
356
+ wp_enqueue_style('jquery-date-style', WPM_PLUGIN_URL.'js/lib/themes/default.date.css' );
357
+ wp_enqueue_style('jquery-time-style', WPM_PLUGIN_URL.'js/lib/themes/default.time.css');
358
+ wp_enqueue_style('jquery-fontselect-style', WPM_PLUGIN_URL.'js/fontselect/fontselect.css' );
359
+
360
+ wp_enqueue_style( 'wp-color-picker' );
361
+ wp_enqueue_script( 'my-script-handle', WPM_PLUGIN_URL.'js/wpm-color-options.js', array( 'wp-color-picker' ), false, true );
362
+
363
+ wp_enqueue_style('thickbox');
364
+ wp_enqueue_style('jquery-style', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');
365
+
366
+ //wp_enqueue_script('nomikos_my_plugin_js_comment', site_url('wp-admin/js/comment.js'));
367
+
368
+ /* ****************************************
369
+ * Create a simple CodeMirror instance
370
+ * ****************************************
371
+ */
372
+ // Mode http://codemirror.net/mode/php/index.html
373
+ wp_register_style( 'wpm_codemirror_css', WPM_PLUGIN_URL.'js/codemirror/codemirror.css', false, '1.0.0' );
374
+ wp_enqueue_style( 'wpm_codemirror_css' );
375
+
376
+ wp_register_style( 'wpm_codemirror_theme_css', WPM_PLUGIN_URL.'js/codemirror/theme/material.css', false, '1.0.0' );
377
+ wp_enqueue_style( 'wpm_codemirror_theme_css' );
378
+
379
+ wp_register_script('wpm_codemirror', WPM_PLUGIN_URL.'js/codemirror/codemirror.js', 'jquery', '1.0');
380
+ wp_enqueue_script('wpm_codemirror');
381
+ wp_register_script('wpm_codemirror_css', WPM_PLUGIN_URL.'js/codemirror/css.js', 'jquery', '1.0');
382
+ wp_enqueue_script('wpm_codemirror_css');
383
+
384
+ /* END CODE MIRROR */
385
+
386
+ wp_register_script('wpm_sticky', WPM_PLUGIN_URL.'js/jquery.sticky.js', 'jquery', '1.0');
387
+ wp_enqueue_script('wpm_sticky');
388
+
389
+ // If you're not including an image upload then you can leave this function call out
390
+ wp_enqueue_media();
391
+
392
+ // Now we can localize the script with our data.
393
+ wp_localize_script( 'wpm-my-upload', 'Data', array(
394
+ 'textebutton' => __( 'Choose This Image', 'wp-maintenance' ),
395
+ 'title' => __( 'Choose Image', 'wp-maintenance' ),
396
+ ) );
397
+
398
+ wp_register_script('wpm-admin-fontselect', WPM_PLUGIN_URL.'js/fontselect/jquery.fontselect.min.js' );
399
+ wp_enqueue_script('wpm-admin-fontselect');
400
+
401
+ /*wp_register_script('wpm-admin-settings', plugins_url('../js/wpm-admin-settings.js', __FILE__ ) );
402
+ wp_enqueue_script('wpm-admin-settings');*/
403
+
404
+ }
405
+ }
406
+
407
+ function wpm_dashboard_page() {
408
+
409
+ //must check that the user has the required capability
410
+ if (!current_user_can('manage_options')) {
411
+ wp_die( __("You do not have sufficient privileges to access this page.", 'sponsorpress') );
412
+ }
413
+ include(WPM_DIR."/views/wp-maintenance-dashboard.php");
414
+ }
415
+ function wpm_colors_page() {
416
+
417
+ //must check that the user has the required capability
418
+ if (!current_user_can('manage_options')) {
419
+ wp_die( __("You do not have sufficient privileges to access this page.", 'sponsorpress') );
420
+ }
421
+ include(WPM_DIR."/views/wp-maintenance-colors.php");
422
+ }
423
+ function wpm_css_page() {
424
+
425
+ //must check that the user has the required capability
426
+ if (!current_user_can('manage_options')) {
427
+ wp_die( __("You do not have sufficient privileges to access this page.", 'sponsorpress') );
428
+ }
429
+ include(WPM_DIR."/views/wp-maintenance-css.php");
430
+ }
431
+
432
+ function wpm_picture_page() {
433
+
434
+ //must check that the user has the required capability
435
+ if (!current_user_can('manage_options')) {
436
+ wp_die( __("You do not have sufficient privileges to access this page.", 'sponsorpress') );
437
+ }
438
+ include(WPM_DIR."/views/wp-maintenance-picture.php");
439
+ }
440
+
441
+ function wpm_countdown_page() {
442
+
443
+ //must check that the user has the required capability
444
+ if (!current_user_can('manage_options')) {
445
+ wp_die( __("You do not have sufficient privileges to access this page.", 'sponsorpress') );
446
+ }
447
+ include(WPM_DIR."/views/wp-maintenance-countdown.php");
448
+ }
449
+
450
+ function wpm_settings_page() {
451
+
452
+ //must check that the user has the required capability
453
+ if (!current_user_can('manage_options')) {
454
+ wp_die( __("You do not have sufficient privileges to access this page.", 'sponsorpress') );
455
+ }
456
+ include(WPM_DIR."/views/wp-maintenance-settings.php");
457
+ }
458
+
459
+ /*function wpm_about_page() {
460
+
461
+ //must check that the user has the required capability
462
+ if (!current_user_can('manage_options')) {
463
+ wp_die( __("You do not have sufficient privileges to access this page.", 'sponsorpress') );
464
+ }
465
+ include(WPM_DIR."/views/wp-maintenance-about.php");
466
+ }*/
467
+
468
+ function wpm_print_footer_scripts() {
469
+
470
+ if (isset($_GET['page']) && strpos($_GET['page'], 'wp-maintenance') !==false) {
471
+ wp_register_script('wpm-picker', WPM_PLUGIN_URL.'js/lib/picker.js' );
472
+ wp_enqueue_script('wpm-picker');
473
+ wp_register_script('wpm-datepicker', WPM_PLUGIN_URL.'js/lib/picker.date.js' );
474
+ wp_enqueue_script('wpm-datepicker');
475
+ wp_register_script('wpm-timepicker', WPM_PLUGIN_URL.'js/lib/picker.time.js' );
476
+ wp_enqueue_script('wpm-timepicker');
477
+ wp_register_script('wpm-legacy', WPM_PLUGIN_URL.'js/lib/legacy.js' );
478
+ wp_enqueue_script('wpm-legacy');
479
+ }
480
+ }
481
+
482
+ function wpm_uninstall() {
483
+
484
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
485
+ $paramMMode = get_option('wp_maintenance_settings');
486
+
487
+ if(get_option('wp_maintenance_active')) { delete_option('wp_maintenance_active'); }
488
+
489
+ if( isset($paramMMode['dashboard_delete_db']) && $paramMMode['dashboard_delete_db'] == 'Yes' ) {
490
+ if(get_option('wp_maintenance_settings')) { delete_option('wp_maintenance_settings'); }
491
+ if(get_option('wp_maintenance_version')) { delete_option('wp_maintenance_version'); }
492
+ if(get_option('wp_maintenance_style')) { delete_option('wp_maintenance_style'); }
493
+ if(get_option('wp_maintenance_limit')) { delete_option('wp_maintenance_limit'); }
494
+ if(get_option('wp_maintenance_active')) { delete_option('wp_maintenance_active'); }
495
+ if(get_option('wp_maintenance_social')) { delete_option('wp_maintenance_social'); }
496
+ if(get_option('wp_maintenance_social_options')) { delete_option('wp_maintenance_social_options'); }
497
+ }
498
+
499
+ }
500
+
501
+ /* Mode Maintenance */
502
+ function wpm_maintenance_mode() {
503
+
504
+ global $current_user;
505
+
506
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
507
+ $paramMMode = get_option('wp_maintenance_settings');
508
+
509
+ if( isset($paramMMode) && !empty($paramMMode) ) {
510
+ foreach($paramMMode as $var =>$value) {
511
+ $paramMMode[$var] = ''.$value.'';
512
+ }
513
+ }
514
+
515
+ if(get_option('wp_maintenance_slider')) { extract(get_option('wp_maintenance_slider')); }
516
+ $paramSlider = get_option('wp_maintenance_slider');
517
+
518
+ if(get_option('wp_maintenance_slider_options')) { extract(get_option('wp_maintenance_slider_options')); }
519
+ $paramSliderOptions = get_option('wp_maintenance_slider_options');
520
+
521
+ if(get_option('wp_maintenance_limit')) { extract(get_option('wp_maintenance_limit')); }
522
+ $paramLimit = get_option('wp_maintenance_limit');
523
+ $statusActive = get_option('wp_maintenance_active');
524
+
525
+ // Récupère les ip autorisee
526
+ $paramIpAddress = get_option('wp_maintenance_ipaddresses');
527
+
528
+ if( !isset($paramMMode['active']) ) { $paramMMode['active'] = 0 ; }
529
+ if( !isset($statusActive) ) { update_option('wp_maintenance_active', $paramMMode['active']); }
530
+
531
+ $paramSocialOption = get_option('wp_maintenance_social_options');
532
+
533
+
534
+ /* Désactive le mode maintenance pour les IP définies */
535
+ if( isset($paramIpAddress) ) {
536
+ //$paramIpAddress = explode("\n", $paramIpAddress);
537
+ if( strpos($paramIpAddress, wpm_get_ip())!== false ) {
538
+ $statusActive = 0;
539
+ }
540
+ }
541
+
542
+ /* Désactive le mode maintenance pour les Roles définis */
543
+ if( isset($paramLimit) && count($paramLimit)>1 ) {
544
+ foreach($paramLimit as $limitrole) {
545
+ if( current_user_can($limitrole) == true ) {
546
+ $statusActive = 0;
547
+ }
548
+ }
549
+ }
550
+
551
+ /* Désactive le mode maintenance pour les PAGE ID définies */
552
+ if( isset($paramMMode['id_pages']) ) {
553
+ $listPageId = explode(',', $paramMMode['id_pages']);
554
+ foreach($listPageId as $keyPageId => $valPageId) {
555
+ if( $valPageId == get_the_ID() ) {
556
+ $statusActive = 0;
557
+ }
558
+ //echo 'Status: '.$statusActive.' - Page: '.$valPageId.' - ID:'.get_the_ID().'<br />';
559
+ }
560
+ }
561
+
562
+ /* On désactive le mode maintenance pour les admins */
563
+ if( current_user_can('administrator') == true ) {
564
+ $statusActive = 0;
565
+ }
566
+
567
+ /* on doit retourner 12/31/2020 5:00 AM */
568
+ $dateNow = strtotime(date("Y-m-d H:i:s")) + 3600 * get_option('gmt_offset');
569
+ if( get_option('wp_maintenance_version') <= '2.7.0') {
570
+ $dateFinCpt = strtotime( date($paramMMode['date_cpt_jj'].'-'.$paramMMode['date_cpt_mm'].'-'.$paramMMode['date_cpt_aa'].' '.$paramMMode['date_cpt_hh'].':'.$paramMMode['date_cpt_mn'].':'.$paramMMode['date_cpt_ss']) );
571
+ } else if( isset($paramMMode['cptdate']) && !empty($paramMMode['cptdate']) ) {
572
+ $dateFinCpt = strtotime( date( str_replace('/', '-', $paramMMode['cptdate']).' '.$paramMMode['cpttime'].':00') );
573
+ $dateCpt = date( 'm/d/Y h:i A', strtotime( $paramMMode['cptdate'].' '.$paramMMode['cpttime'] ) );
574
+ } else {
575
+ $dateCpt = '';
576
+ }
577
+
578
+ /* Si on désactive le mode maintenance en fin de compte à rebours */
579
+ if( ( isset($paramMMode['disable']) && $paramMMode['disable']==1 ) && $statusActive == 1 ) {
580
+
581
+ if( $dateNow > $dateFinCpt ) {
582
+ $ChangeStatus = wpm_change_active();
583
+ $statusActive = 0;
584
+ }
585
+
586
+ }
587
+
588
+ if ($statusActive == 1) {
589
+
590
+ if ( file_exists( get_stylesheet_directory() ) ) {
591
+ $urlTpl = get_stylesheet_directory();
592
+ } else {
593
+ $urlTpl = get_template_directory();
594
+ }
595
+
596
+ if( isset($paramMMode['pageperso']) && $paramMMode['pageperso']==1 && file_exists($urlTpl.'/maintenance.php') ) {
597
+
598
+ include_once( $urlTpl.'/maintenance.php' );
599
+ die();
600
+
601
+ } else {
602
+
603
+ $wpmStyle = '';
604
+
605
+ $site_title = get_bloginfo( 'name', 'display' );
606
+ $site_description = get_bloginfo( 'description', 'display' );
607
+
608
+ /* Si container activé */
609
+ if( isset($paramMMode['container_active']) && $paramMMode['container_active'] == 1 ) {
610
+
611
+ if( empty($paramMMode['container_opacity']) ) { $paramMMode['container_opacity'] = 0.5; }
612
+ if( empty($paramMMode['container_width']) ) { $paramMMode['container_width'] = 80; }
613
+ if( empty($paramMMode['container_color']) ) { $paramMMode['container_color'] = '#ffffff'; }
614
+ if( isset($paramMMode['container_color']) ) {
615
+ $paramRGBColor = wpm_hex2rgb($paramMMode['container_color']);
616
+ }
617
+
618
+ $wpmStyle .= '
619
+ #sscontent {
620
+ background-color: rgba('.$paramRGBColor['rouge'].','.$paramRGBColor['vert'].','.$paramRGBColor['bleu'].', '.$paramMMode['container_opacity'].');
621
+ padding:0.8em;
622
+ margin-left:auto;
623
+ margin-right:auto;
624
+ width:'.$paramMMode['container_width'].'%;
625
+ }
626
+ ';
627
+ }
628
+
629
+ /* Défninition des couleurs par défault */
630
+ if( !isset($paramMMode['color_bg']) || $paramMMode['color_bg']=="") { $paramMMode['color_bg'] = "#f1f1f1"; }
631
+ if( !isset($paramMMode['color_txt']) || $paramMMode['color_txt']=="") { $paramMMode['color_txt'] = "#888888"; }
632
+
633
+ /* Traitement de la feuille de style */
634
+ $styleRemplacements = array (
635
+ "#_COLORTXT" => $paramMMode['color_txt'],
636
+ "#_COLORBG" => $paramMMode['color_bg'],
637
+ "#_COLORCPTBG" => $paramMMode['color_cpt_bg'],
638
+ "#_DATESIZE" => $paramMMode['date_cpt_size'],
639
+ "#_COLORCPT" => $paramMMode['color_cpt'],
640
+ "#_COLOR_BG_BT" => $paramMMode['color_bg_bottom'],
641
+ "#_COLOR_TXT_BT" => $paramMMode['color_text_bottom'],
642
+ "#_COLORHEAD" => $paramMMode['color_bg_header'],
643
+ );
644
+ $wpmStyle .= str_replace(array_keys($styleRemplacements), array_values($styleRemplacements), get_option('wp_maintenance_style'));
645
+ if( isset($paramMMode['message_cpt_fin']) && $paramMMode['message_cpt_fin']=='') { $paramMMode['message_cpt_fin'] = '&nbsp;'; }
646
+
647
+
648
+ $template_page = wpm_get_template();
649
+
650
+ $Counter = '';
651
+ $addFormLogin = '';
652
+ $newLetter = '';
653
+
654
+ if( isset($paramMMode['analytics']) && $paramMMode['analytics']!='') {
655
+ $CodeAnalytics = do_shortcode('[wpm_analytics enable="'.$paramMMode['analytics'].'"]');
656
+ } else {
657
+ $CodeAnalytics = '';
658
+ }
659
+ if( isset($paramMMode['headercode']) && $paramMMode['headercode']!='') {
660
+ $HeaderCode = stripslashes($paramMMode['headercode']);
661
+ } else {
662
+ $HeaderCode = '';
663
+ }
664
+ if( isset($paramSocialOption['position']) && $paramSocialOption['position']=='top') {
665
+ $TopSocialIcons = '<div id="header">'.do_shortcode('[wpm_social]').'</div>';
666
+ } else {
667
+ $TopSocialIcons = '';
668
+ }
669
+ if( isset($paramSocialOption['position']) && $paramSocialOption['position']=='bottom') {
670
+ $BottomSocialIcons = do_shortcode('[wpm_social]');
671
+ } else {
672
+ $BottomSocialIcons = '';
673
+ }
674
+ if( isset($paramMMode['image']) && $paramMMode['image'] ) {
675
+ if( ini_get('allow_url_fopen')==1) {
676
+ $image_path = str_replace(get_bloginfo('url'), ABSPATH, $paramMMode['image']);
677
+ list($logoWidth, $logoHeight, $logoType, $logoAttr) = getimagesize($image_path);
678
+ } else {
679
+ $width = 150;
680
+ $height = 80;
681
+ }
682
+ $LogoImage = '<div id="logo"><img src="'.$paramMMode['image'].'" width="'.$logoWidth.'" height="'.$logoHeight.'" alt="'.get_bloginfo( 'name', 'display' ).' '.get_bloginfo( 'description', 'display' ).'" title="'.get_bloginfo( 'name', 'display' ).' '.get_bloginfo( 'description', 'display' ).'" /></div>';
683
+ } else {
684
+ $LogoImage = '';
685
+ }
686
+
687
+ if( isset($paramMMode['text_bt_maintenance']) && $paramMMode['text_bt_maintenance']!='' ) {
688
+ $TextCopyright = stripslashes($paramMMode['text_bt_maintenance']);
689
+ } else {
690
+ $TextCopyright = '';
691
+ }
692
+ if( (isset($paramMMode['add_wplogin']) && $paramMMode['add_wplogin']==1) && (isset($paramMMode['add_wplogin_title']) && $paramMMode['add_wplogin_title']!='') ) {
693
+ $textLogin = str_replace('%DASHBOARD%', '<a href="'.get_admin_url().'">'.__('Dashboard', 'wp-maintenance').'</a>', $paramMMode['add_wplogin_title']);
694
+ $TextCopyright .= '<br />'.$textLogin;
695
+
696
+ }
697
+ if( isset($paramMMode['titre_maintenance']) && $paramMMode['titre_maintenance']!='' ) {
698
+ $Titre = stripslashes($paramMMode['titre_maintenance']);
699
+ } else {
700
+ $Titre = '';
701
+ }
702
+ if( isset($paramMMode['text_maintenance']) && $paramMMode['text_maintenance']!='' ) {
703
+ $Texte = stripslashes($paramMMode['text_maintenance']);
704
+ } else {
705
+ $Texte = '';
706
+ }
707
+ $wysijaStyle = '/* no NEWLETTER Style */';
708
+ if( isset($paramMMode['newletter']) && $paramMMode['newletter']==1 && isset($paramMMode['code_newletter']) && $paramMMode['code_newletter']!='' ) {
709
+
710
+ if( empty($paramMMode['color_field_text']) ) { $paramMMode['color_field_text'] = '#333333'; }
711
+ if( empty($paramMMode['color_text_button']) ) { $paramMMode['color_text_button']= '#ffffff'; }
712
+ if( empty($paramMMode['color_field_background']) ) { $paramMMode['color_field_background']= '#F1F1F1'; }
713
+ if( empty($paramMMode['color_field_border']) ) { $paramMMode['color_field_border']= '#333333'; }
714
+ if( empty($paramMMode['color_button_onclick']) ) { $paramMMode['color_button_onclick']= '#333333'; }
715
+ if( empty($paramMMode['color_button_hover']) ) { $paramMMode['color_button_hover']= '#cccccc'; }
716
+ if( empty($paramMMode['color_button']) ) { $paramMMode['color_button']= '#1e73be'; }
717
+
718
+ $wysijaRemplacements = array (
719
+ "#_COLORTXT" => $paramMMode['color_field_text'],
720
+ "#_COLORBG" => $paramMMode['color_field_background'],
721
+ "#_COLORBORDER" => $paramMMode['color_field_border'],
722
+ "#_COLORBUTTON" => $paramMMode['color_button'],
723
+ "#_COLORTEXTBUTTON" => $paramMMode['color_text_button'],
724
+ "#_COLOR_BTN_HOVER" => $paramMMode['color_button_hover'],
725
+ "#_COLOR_BTN_CLICK" => $paramMMode['color_button_onclick']
726
+ );
727
+
728
+ if( strpos($paramMMode['code_newletter'], 'wysija_form') == 1 ) {
729
+
730
+ $wysijaStyle = str_replace(array_keys($wysijaRemplacements), array_values($wysijaRemplacements), wpm_wysija_style() );
731
+
732
+ } else if( strpos($paramMMode['code_newletter'], 'mc4wp_form') == 1 ) {
733
+
734
+ $wysijaStyle = str_replace(array_keys($wysijaRemplacements), array_values($wysijaRemplacements), wpm_mc4wp_style() );
735
+
736
+ }
737
+ $newLetter = '<div class="wpm_newletter">'.stripslashes($paramMMode['title_newletter']);
738
+ if( isset($paramMMode['type_newletter']) && isset($paramMMode['iframe_newletter']) && $paramMMode['iframe_newletter']!='' && $paramMMode['type_newletter']=='iframe' ) {
739
+ $newLetter .= stripslashes($paramMMode['iframe_newletter']);
740
+ }
741
+ if( isset($paramMMode['type_newletter']) && isset($paramMMode['code_newletter']) && $paramMMode['code_newletter']!='' && $paramMMode['type_newletter']=='shortcode' ) {
742
+ $newLetter .= do_shortcode(stripslashes($paramMMode['code_newletter']));
743
+ }
744
+ $newLetter .= '</div>';
745
+ }
746
+
747
+ $optionBackground = '';
748
+ $addBImage = '';
749
+ if( (isset($paramMMode['b_image']) && $paramMMode['b_image']) && (isset($paramMMode['b_enable_image']) && $paramMMode['b_enable_image']==1) ) {
750
+ if( isset($paramMMode['b_repeat_image']) || $paramMMode['b_repeat_image']=='') { $paramMMode['b_repeat_image'] = 'repeat'; }
751
+ if( isset($paramMMode['b_fixed_image']) && $paramMMode['b_fixed_image']==1 ) {
752
+ $optionBackground = 'background-attachment:fixed;';
753
+ }
754
+ $addBImage = '
755
+ body {
756
+ background-image:url('.$paramMMode['b_image'].');
757
+ background-size: cover;
758
+ -webkit-background-size: cover;
759
+ -moz-background-size: cover;
760
+ -o-background-size: cover;
761
+ background-repeat: '.$paramMMode['b_repeat_image'].';
762
+ '.$optionBackground.'
763
+ }';
764
+ }
765
+ if( isset($paramMMode['b_pattern']) && $paramMMode['b_pattern']>0 && $paramMMode['b_enable_image']==1) {
766
+ $addBImage = '
767
+ body {
768
+ background-image: url('.WP_PLUGIN_URL.'/wp-maintenance/images/pattern'.$paramMMode['b_pattern'].'.png);
769
+ background-repeat: '.$paramMMode['b_repeat_image'].';
770
+ '.$optionBackground.'
771
+ }'; }
772
+
773
+
774
+
775
+ /*********** AJOUT DU STYLE SUIVANT LES PARAMETRES *********/
776
+ $wpmFonts = '
777
+ @import url(https://fonts.googleapis.com/css?family='.str_replace(' ', '+', $paramMMode['font_title']).'|'.str_replace(' ', '+',$paramMMode['font_text']).'|'.str_replace(' ', '+',$paramMMode['font_text_bottom']).'|'.str_replace(' ', '+',$paramMMode['font_cpt']);
778
+ if( isset($paramMMode['newletter_font_text']) && $paramMMode['newletter_font_text'] != '') {
779
+ $wpmFonts .= '|'.str_replace(' ', '+',$paramMMode['newletter_font_text']);
780
+ }
781
+ $wpmFonts .= ');';
782
+
783
+ /* Si on a une couleur de fond */
784
+ if( isset($paramMMode['color_bg']) && $paramMMode['color_bg']!='' ) {
785
+ $wpmStyle .= 'body { background-color: '.$paramMMode['color_bg'].'; }';
786
+ }
787
+
788
+ $wpmStyle .= ''.$addBImage.'
789
+ .wpm_social_icon {
790
+ float:left;
791
+ width:'.$paramSocialOption['size'].'px;
792
+ margin:0px 5px auto;
793
+ }
794
+ .wpm_social ul {
795
+ margin: 10px 0;
796
+ max-width: 100%;
797
+ padding: 0;
798
+ text-align: '.$paramSocialOption['align'].';
799
+ }
800
+ ';
801
+ $wpmStyle .= '
802
+ .wpm_newletter {';
803
+ if( isset($paramMMode['newletter_size']) ) { $wpmStyle .= 'font-size: '.$paramMMode['newletter_size'].'px;'; }
804
+ if( isset($paramMMode['newletter_font_style']) ) { $wpmStyle .= 'font-style: '.$paramMMode['newletter_font_style'].';'; }
805
+ if( isset($paramMMode['newletter_font_weigth']) ) { $wpmStyle .= 'font-weight: '.$paramMMode['newletter_font_weigth'].';'; }
806
+ if( isset($paramMMode['newletter_font_text']) ) { $wpmStyle .= 'font-family: '.wpm_format_font($paramMMode['newletter_font_text']).', serif;'; }
807
+ $wpmStyle .= '}';
808
+
809
+ $wpmStyle .= '
810
+ h3 {';
811
+ if( isset($paramMMode['font_title']) ) { $wpmStyle .= 'font-family: '.wpm_format_font($paramMMode['font_title']).', serif;'; }
812
+ if( isset($paramMMode['font_title_size']) ) { $wpmStyle .= 'font-size: '.$paramMMode['font_title_size'].'px;'; }
813
+ if( isset($paramMMode['font_title_style']) ) { $wpmStyle .= 'font-style: '.$paramMMode['font_title_style'].';'; }
814
+ if( isset($paramMMode['font_title_weigth']) ) { $wpmStyle .= 'font-weight: '.$paramMMode['font_title_weigth'].';'; }
815
+ if( isset($paramMMode['color_txt']) ) { $wpmStyle .= 'color:'.$paramMMode['color_txt'].';'; }
816
+ $wpmStyle .= '
817
+ line-height: 100%;
818
+ text-align:center;
819
+ margin:0.5em auto;
820
+ }
821
+ p {';
822
+ if( isset($paramMMode['font_text']) ) { $wpmStyle .= 'font-family: '.wpm_format_font($paramMMode['font_text']).', serif;'; }
823
+ if( isset($paramMMode['font_text_size']) ) { $wpmStyle .= 'font-size: '.$paramMMode['font_text_size'].'px;'; }
824
+ if( isset($paramMMode['font_text_style']) ) { $wpmStyle .= 'font-style: '.$paramMMode['font_text_style'].';'; }
825
+ if( isset($paramMMode['font_text_weigth']) ) { $wpmStyle .= 'font-weight: '.$paramMMode['font_text_weigth'].';'; }
826
+ if( isset($paramMMode['color_txt']) ) { $wpmStyle .= 'color:'.$paramMMode['color_txt'].';'; }
827
+ $wpmStyle .= '
828
+ line-height: 100%;
829
+ text-align:center;
830
+ margin:0.5em auto;
831
+ padding-left:2%;
832
+ padding-right:2%;
833
+
834
+ }';
835
+ if( (isset($paramMMode['text_bt_maintenance']) && $paramMMode['text_bt_maintenance']!='') or ( (isset($paramMMode['add_wplogin']) && $paramMMode['add_wplogin']==1) && (isset($paramMMode['add_wplogin_title']) && $paramMMode['add_wplogin_title']!='') ) ) {
836
+ $wpmStyle .= '#footer {';
837
+ if( isset($paramMMode['color_bg_bottom']) ) { $wpmStyle .= 'background:'.$paramMMode['color_bg_bottom'].';'; }
838
+ $wpmStyle .= '}';
839
+ }
840
+ $wpmStyle .= '
841
+ div.bloc {';
842
+ if( isset($paramMMode['font_text_bottom']) ) { $wpmStyle .= 'font-family: '.wpm_format_font($paramMMode['font_text_bottom']).', serif;'; }
843
+ if( isset($paramMMode['font_bottom_style']) ) { $wpmStyle .= 'font-style: '.$paramMMode['font_bottom_style'].';'; }
844
+ if( isset($paramMMode['font_bottom_size']) ) { $wpmStyle .= 'font-size: '.$paramMMode['font_bottom_size'].'px;'; }
845
+ if( isset($paramMMode['font_bottom_weigth']) ) { $wpmStyle .= 'font-weight: '.$paramMMode['font_bottom_weigth'].';'; }
846
+ if( isset($paramMMode['color_text_bottom']) ) { $wpmStyle .= 'color: '.$paramMMode['color_text_bottom'].';'; }
847
+ $wpmStyle .= '
848
+ text-decoration:none;
849
+ }
850
+ div.bloc a:link {';
851
+ if( isset($paramMMode['color_text_bottom']) ) { $wpmStyle .= 'color:'.$paramMMode['color_text_bottom'].';'; }
852
+ if( isset($paramMMode['font_bottom_size']) ) { $wpmStyle .= 'font-size: '.$paramMMode['font_bottom_size'].'px;'; }
853
+ $wpmStyle .= '
854
+ text-decoration:none;
855
+ }
856
+ div.bloc a:visited {';
857
+ if( isset($paramMMode['color_text_bottom']) ) { $wpmStyle .= 'color:'.$paramMMode['color_text_bottom'].';'; }
858
+ if( isset($paramMMode['font_bottom_size']) ) { $wpmStyle .= 'font-size: '.$paramMMode['font_bottom_size'].'px;'; }
859
+ $wpmStyle .= '
860
+ text-decoration:none;
861
+ }
862
+ div.bloc a:hover {
863
+ text-decoration:underline;';
864
+ if( isset($paramMMode['font_bottom_size']) ) { $wpmStyle .= 'font-size: '.$paramMMode['font_bottom_size'].'px;'; }
865
+ $wpmStyle .= '
866
+ }
867
+
868
+
869
+
870
+ ';
871
+
872
+ $addCssSlider = WPM_Slider::slider_css();
873
+ $addScriptSlider = WPM_Slider::slider_scripts();
874
+ $addScriptSlideshow = WPM_Slider::slider_functions();
875
+ $Counter = WPM_Countdown::display($dateCpt);
876
+
877
+ $wpmStyle = $wpmStyle.WPM_Countdown::css();
878
+
879
+ $tplRemplacements = array (
880
+ "%TITLE%" => get_bloginfo( 'name', 'display' ).' '.get_bloginfo( 'description', 'display' ),
881
+ "%ANALYTICS%" => $CodeAnalytics,
882
+ "%HEADERCODE%" => $HeaderCode,
883
+ "%ADDSTYLE%" => $wpmStyle,
884
+ "%ADDSTYLEWYSIJA%" => $wysijaStyle,
885
+ "%ADDFONTS%" => $wpmFonts,
886
+ "%TOPSOCIALICON%" => $TopSocialIcons,
887
+ "%BOTTOMSOCIALICON%" => $BottomSocialIcons,
888
+ "%LOGOIMAGE%" => $LogoImage,
889
+ "%COPYRIGHT%" => $TextCopyright,
890
+ "%COUNTER%" =>$Counter,
891
+ "%VERSION%" => WPM_VERSION,
892
+ "%TITRE%" => $Titre,
893
+ "%TEXTE%" => $Texte,
894
+ "%LOGINFORM%" => $addFormLogin,
895
+ "%NEWSLETTER%" => $newLetter,
896
+ "%CSSSLIDER%" => $addCssSlider,
897
+ "%SCRIPTSLIDER%" => $addScriptSlider,
898
+ "%SCRIPTSLIDESHOW%" => $addScriptSlideshow,
899
+ "%SLIDESHOWAL%" => WPM_Slider::slidershow('abovelogo'),
900
+ "%SLIDESHOWBL%" => WPM_Slider::slidershow('belowlogo'),
901
+ "%SLIDESHOWBT%" => WPM_Slider::slidershow('belowtext')
902
+ );
903
+ $template_page = str_replace(array_keys($tplRemplacements), array_values($tplRemplacements), $template_page );
904
+
905
+ $content = $template_page;
906
+ }
907
+ die($content);
908
+ }
909
+
910
+ }
911
+
912
+ }
913
+
914
+
915
+ ?>
css/custom-editor-style.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ body#tinymce.wp-editor {
2
+ font-size: 0.9rem;
3
+ margin: 10px;
4
+ max-width: 100%;
5
+ }
css/wpm-admin.css CHANGED
@@ -1,3 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #wpadminbar .wpmbackground {
2
  background-color: #333;
3
  -webkit-animation-name: blinker;
@@ -46,7 +114,7 @@
46
  -webkit-border-bottom-left-radius:10px;
47
  -moz-border-radius-bottomleft:10px;
48
  border-bottom-left-radius:10px;
49
- text-indent:0;
50
  border:3px solid #656830;
51
  display:inline-block;
52
  color:#ffffff;
@@ -54,16 +122,48 @@ text-indent:0;
54
  font-size:15px;
55
  font-weight:bold;
56
  font-style:normal;
57
- height:50px;
58
  line-height:45px;
59
- width:250px;
60
  text-decoration:none;
61
  text-align:center;
62
  }.wpmclassname:hover {
63
  background-color:#656830;
64
- color:#ffffff;
65
  }.wpmclassname:active {
66
  position:relative;
67
  top:1px;
68
- color:#ffffff;
 
 
 
 
 
 
 
 
 
 
69
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Checkbox animés */
2
+
3
+ /* Fin checkbox animés */
4
+
5
+ .switch-field {
6
+ font-family: "Lucida Grande", Tahoma, Verdana, sans-serif;
7
+ padding-top: 5px;
8
+ padding-bottom: 10px;
9
+ overflow: hidden;
10
+ width: 180px;
11
+ margin-left: auto;
12
+ }
13
+
14
+ .switch-title {
15
+ margin-bottom: 6px;
16
+ }
17
+
18
+ .switch-field input {
19
+ position: absolute !important;
20
+ clip: rect(0, 0, 0, 0);
21
+ height: 1px;
22
+ width: 1px;
23
+ border: 0;
24
+ overflow: hidden;
25
+ }
26
+
27
+ .switch-field label {
28
+ float: left;
29
+ }
30
+
31
+ .switch-field label {
32
+ display: inline-block;
33
+ width: 60px;
34
+ background-color: #e4e4e4;
35
+ color: #333333;
36
+ font-size: 14px;
37
+ font-weight: normal;
38
+ text-align: center;
39
+ text-shadow: none;
40
+ padding: 6px 14px;
41
+ border: 1px solid rgba(0, 0, 0, 0.2);
42
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
43
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
44
+ -webkit-transition: all 0.1s ease-in-out;
45
+ -moz-transition: all 0.1s ease-in-out;
46
+ -ms-transition: all 0.1s ease-in-out;
47
+ -o-transition: all 0.1s ease-in-out;
48
+ transition: all 0.1s ease-in-out;
49
+ }
50
+
51
+ .switch-field label:hover {
52
+ cursor: pointer;
53
+ }
54
+
55
+ .switch-field input:checked + label {
56
+ -webkit-box-shadow: none;
57
+ box-shadow: none;
58
+ color: #e4e4e4;
59
+ }
60
+
61
+ .switch-field label:first-of-type {
62
+ border-radius: 4px 0 0 4px;
63
+ }
64
+
65
+ .switch-field label:last-of-type {
66
+ border-radius: 0 4px 4px 0;
67
+ }
68
+
69
  #wpadminbar .wpmbackground {
70
  background-color: #333;
71
  -webkit-animation-name: blinker;
114
  -webkit-border-bottom-left-radius:10px;
115
  -moz-border-radius-bottomleft:10px;
116
  border-bottom-left-radius:10px;
117
+ text-indent:0;
118
  border:3px solid #656830;
119
  display:inline-block;
120
  color:#ffffff;
122
  font-size:15px;
123
  font-weight:bold;
124
  font-style:normal;
125
+ height:50px;
126
  line-height:45px;
127
+ width:215px;
128
  text-decoration:none;
129
  text-align:center;
130
  }.wpmclassname:hover {
131
  background-color:#656830;
132
+ color:#ffffff;
133
  }.wpmclassname:active {
134
  position:relative;
135
  top:1px;
136
+ color:#ffffff;
137
+ }
138
+ #wpmcontainer-sticky-wrapper { height: 0px!important; }
139
+ #wpmcontainer {
140
+ left: 0;
141
+ padding-left: 160px;
142
+ position: fixed;
143
+ top: 32px;
144
+ width: 100%;
145
+ z-index: 9980;
146
+ background-color: #f1f1f1;
147
  }
148
+ #wpmNotifications {
149
+ color:#ffffff;
150
+ background-color: #a3b745;
151
+ margin-left: auto;
152
+ margin-right: auto;
153
+ width:60%;
154
+ padding: 14px 25px 14px 25px;
155
+ -webkit-border-top-left-radius:10px;
156
+ -moz-border-radius-topleft:10px;
157
+ border-top-left-radius:10px;
158
+ -webkit-border-top-right-radius:10px;
159
+ -moz-border-radius-topright:10px;
160
+ border-top-right-radius:10px;
161
+ -webkit-border-bottom-right-radius:10px;
162
+ -moz-border-radius-bottomright:10px;
163
+ border-bottom-right-radius:10px;
164
+ -webkit-border-bottom-left-radius:10px;
165
+ -moz-border-radius-bottomleft:10px;
166
+ border-bottom-left-radius:10px;
167
+ }
168
+
169
+
images/extension-send-pdf-for-cf7.png ADDED
Binary file
images/logo-Extensions.png ADDED
Binary file
images/wpm-menu-icon.png ADDED
Binary file
wpm_fonctions.php → includes/functions.php RENAMED
@@ -3,6 +3,352 @@
3
  defined( 'ABSPATH' )
4
  or die( 'No direct load ! ' );
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  function wpm_getFontsTab() {
7
  return array("Abel", "Abril Fatface", "Aclonica", "Acme", "Actor", "Adamina", "Advent Pro",
8
  "Aguafina Script", "Aladin", "Aldrich", "Alegreya", "Alegreya SC", "Alex Brush", "Alfa Slab One", "Alice",
3
  defined( 'ABSPATH' )
4
  or die( 'No direct load ! ' );
5
 
6
+ function wpm_get_header( $text = 'Settings', $dashicon = 'dashicons-admin-settings', $update = 0 ) {
7
+
8
+ global $current_user;
9
+ global $_wp_admin_css_colors;
10
+
11
+ $getHeader = '
12
+ <div id="wpmcontainer" role="navigation" class="stickywrapper">
13
+ <div id="divwpmcontainer">
14
+ <div style="float:left;width:67%;margin-left: 20px;">
15
+ <div style="float:left;width:35%;">
16
+ <h2 style="font-size: 23px;font-weight: 400;line-height: 29px;margin-bottom:15px;">
17
+ <span class="dashicons '.$dashicon.'" style="font-size:35px;margin-right:10px;"></span> '.$text.'
18
+ </h2>
19
+ </div>';
20
+ $getHeader .= '<div style="float:left;width: 20%;padding-top: 8px;">
21
+ <div style="text-align:center;border-bottom: 1px solid #ddd;margin-bottom: 5px;">MENU</div><div style="text-align:center;">'.wpm_list_dashicons().'</div>
22
+ </div>';
23
+ $getHeader .= '<div style="float:left;width: 45%;text-align: center;padding-top: 10px;">';
24
+ if( $update == 1 ) {
25
+ $getHeader .= '<div id="wpmNotifications"><strong>'.__('Options saved.', 'wp-maintenance').'</strong></div>';
26
+ $getHeader .= '<script>
27
+ jQuery("#wpmNotifications").delay(4000).fadeOut(2000, function(){
28
+ jQuery(this).remove();
29
+ });
30
+
31
+ </script>';
32
+ }
33
+ $getHeader .= '</div>';
34
+ $getHeader .= '</div>
35
+ <div style="float:left;width:18%;text-align: right;margin-top: 25px;">
36
+ '.get_submit_button( '', 'primary', 'valide_settings', false ).'
37
+ </div><div class="clear"></div>
38
+ </div>
39
+ </div><div class="clear"></div>';
40
+
41
+ return $getHeader;
42
+ }
43
+
44
+ function wpm_list_dashicons() {
45
+
46
+ global $current_user;
47
+ global $_wp_admin_css_colors;
48
+
49
+ $admin_color = get_user_option( 'admin_color', get_current_user_id() );
50
+ $colors = $_wp_admin_css_colors[$admin_color]->colors;
51
+
52
+ $tabOptions = array(
53
+
54
+ 'wp-maintenance' => array(
55
+ 'dashicons' => 'dashicons-admin-settings',
56
+ 'link' => 'wp-maintenance',
57
+ 'text' => __('Go to Generals options', 'wp-maintenance')
58
+ ),
59
+ 'wp-maintenance-colors' => array(
60
+ 'dashicons' => 'dashicons-art',
61
+ 'link' => 'wp-maintenance-colors',
62
+ 'text' => __('Go to Colors and Fonts options', 'wp-maintenance')
63
+ ),
64
+ 'wp-maintenance-picture' => array(
65
+ 'dashicons' => 'dashicons-format-gallery',
66
+ 'link' => 'wp-maintenance-picture',
67
+ 'text' => __('Go to Pictures options', 'wp-maintenance')
68
+ ),
69
+ 'wp-maintenance-countdown' => array(
70
+ 'dashicons' => 'dashicons-clock',
71
+ 'link' => 'wp-maintenance-countdown',
72
+ 'text' => __('Go to Countdown options', 'wp-maintenance')
73
+ ),
74
+ 'wp-maintenance-css' => array(
75
+ 'dashicons' => 'dashicons-media-code',
76
+ 'link' => 'wp-maintenance-css',
77
+ 'text' => __('Go to CSS options', 'wp-maintenance')
78
+ ),
79
+ 'wp-maintenance-settings' => array(
80
+ 'dashicons' => 'dashicons-admin-generic',
81
+ 'link' => 'wp-maintenance-settings',
82
+ 'text' => __('Go to Settings options', 'wp-maintenance')
83
+ )
84
+ );
85
+
86
+ $getDashicons = '';
87
+
88
+ foreach( $tabOptions as $page=>$values) {
89
+
90
+ if (isset($_GET['page']) && $_GET['page']!=$page ) {
91
+
92
+ $getDashicons .= '<a href="'.admin_url().'admin.php?page='.$page.'" alt="'.$tabOptions[$page]['text'].'" title="'.$tabOptions[$page]['text'].'" class="wpmadashicons" onFocus="this.blur()"><span class="dashicons '.$tabOptions[$page]['dashicons'].'" class="wpmdashicons" style="font-size:25px;margin-right:15px;"></span></a>';
93
+
94
+ }
95
+ }
96
+
97
+ return $getDashicons;
98
+ }
99
+
100
+ function wpm_update_settings($tabPost) {
101
+
102
+ // Récupère les paramètres sauvegardés Temporairement
103
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
104
+ $paramTemp = get_option('wp_maintenance_settings');
105
+
106
+ // Je recupère le tableau temporaire des données
107
+ if( isset($paramTemp) && !empty($paramTemp) ) {
108
+ foreach($paramTemp as $variable=>$value) {
109
+ // pour chaque clé du tableau de regarde si elle existe déjà
110
+ if ( array_key_exists($variable, $paramTemp) ) {
111
+ // Si la clé est la même que venant du post je la change
112
+ if( isset($tabPost[$variable]) ) {
113
+ array_fill_keys($paramTemp, $tabPost[$variable]);
114
+ }
115
+ }
116
+ }
117
+ }
118
+
119
+ if( isset($paramTemp) && is_array($paramTemp) ) {
120
+ // Si le tableau temporaire existe je le fusionne avec les données $_POST["wp_maintenance_settings"]
121
+ $paramData = array_merge($paramTemp, $tabPost);
122
+ } else {
123
+ // Sinon je garde le $_POST["wp_maintenance_settings"] en cours
124
+ $paramData = $tabPost;
125
+ }
126
+ if(update_option('wp_maintenance_settings', $paramData)) {
127
+ return true;
128
+ }
129
+ }
130
+
131
+ function wpm_sidebar() {
132
+
133
+ $wpmSidebar = '<div style="float:left;width:24%;">';
134
+
135
+ /* ABOUT */
136
+ $wpmSidebar .= '<div style="border: 1px solid #ddd;background-color:#fff;padding:10px;text-align:center;margin-bottom:5px;">'.__('ABOUT', 'wp-maintenance').'</div>';
137
+
138
+ $wpmSidebar .= '<div style="text-align:justify;background-color:#fff;padding:10px;margin-bottom: 10px;">'.__('This plugin has been developed for you for free by <a href="https://restezconnectes.fr" target="_blank">Florent Maillefaud</a>. It is royalty free, you can take it, modify it, distribute it as you see fit.', 'wp-maintenance').'<br /><br />';
139
+ $wpmSidebar .= ''.__('Visit', 'wp-maintenance').' <a href="https://wpmaintenance.info" target="_blank">WP Maintenance</a>, '.__('try the demo of the plugin, talk about this plugin to your surroundings!', 'wp-maintenance').'<br /><br />';
140
+ /* FAIRE UN DON SUR PAYPAL */
141
+ $wpmSidebar .= ''.__('Support this extension and my other developments (French Paypal):', 'wp-maintenance').'<br /><br />
142
+ <div style="width:220px;margin-left:auto;margin-right:auto;padding:5px;">
143
+ <a href="https://paypal.me/RestezConnectes/10" target="_blank" class="wpmclassname">
144
+ <img src="'.WP_PLUGIN_URL.'/wp-maintenance/images/donate.png" valign="bottom" width="64" /> Donate now!
145
+ </a>
146
+ </div>
147
+ </div>';
148
+ /* FIN FAIRE UN DON */
149
+
150
+ /* END ABOUT */
151
+
152
+ /* DISCOVER*/
153
+ $wpmSidebar .= '<div style="border: 1px solid #ddd;background-color:#fff;padding:10px;text-align:center;margin-bottom:5px;">'.__('DISCOVER', 'wp-maintenance').'</div>';
154
+
155
+ $imagePub = array(
156
+ 'extension-send-pdf-for-cf7.png' => 'https://wordpress.org/plugins/send-pdf-for-contact-form-7/'
157
+ );
158
+
159
+ foreach( $imagePub as $img=>$link ) {
160
+ $wpmSidebar .= '<a href="'.$link.'" target="_blank"><img src="'.WPM_PLUGIN_URL.'/images/'.$img.'" /></a>';
161
+ }
162
+ /* END DISCOVER */
163
+
164
+ $wpmSidebar .= '</div>'; // Div general
165
+ $wpmSidebar .= '<div class="clear"></div>';
166
+
167
+ return $wpmSidebar;
168
+ }
169
+
170
+ function wpm_footer() {
171
+
172
+ $wpmFooter = '
173
+ <div style="margin-top:40px;">
174
+ <a href="https://wpmaintenance.info/" target="_blank">'.__('WP Maintenance','wp-maintenance').'</a> '.__('is brought to you by','wp-maintenance').' <a href="https://restezconnectes.fr/" target="_blank">Restez Connectés</a> - '.__('If you found this plugin useful','wp-maintenance').' <a href="https://wordpress.org/support/view/plugin-reviews/wp-maintenance" target="_blank">'.__('give it 5 &#9733; on WordPress.org','wp-maintenance').'</a>
175
+ </div>
176
+ ';
177
+
178
+ return $wpmFooter;
179
+
180
+ }
181
+
182
+ /* Liste les différents Rôles */
183
+ function wpm_get_roles() {
184
+
185
+ $wp_roles = new WP_Roles();
186
+ $roles = $wp_roles->get_names();
187
+ $roles = array_map( 'translate_user_role', $roles );
188
+
189
+ return $roles;
190
+ }
191
+
192
+ /* Retourne la vraie adresse IP */
193
+ function wpm_get_ip() {
194
+ return (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
195
+ }
196
+
197
+ function wpm_change_active($value = 0) {
198
+
199
+ update_option('wp_maintenance_active', $value);
200
+ $statusActive = get_option('wp_maintenance_active');
201
+ if( isset($statusActive) ) {
202
+ return $statusActive;
203
+ }
204
+ }
205
+
206
+ function wpm_array_value_count ($array) {
207
+ $count = 0;
208
+
209
+ foreach ($array as $key => $value)
210
+ {
211
+ if($value) { $count++; }
212
+ }
213
+
214
+ return $count;
215
+ }
216
+
217
+ function wpm_get_template() {
218
+
219
+ return '
220
+ <!DOCTYPE html>
221
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
222
+ <head>
223
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
224
+ <meta name="viewport" content="width=device-width, user-scalable=yes" />
225
+ <title>%TITLE%</title>
226
+
227
+ <style type=\'text/css\'>
228
+ /* VERSION %VERSION% */
229
+ %ADDFONTS%
230
+ html,
231
+ body {
232
+ margin:0;
233
+ padding:0;
234
+ height:100%;
235
+ font-size:100%;
236
+ }
237
+ #wrapper {
238
+ min-height:100%;
239
+ position:relative;
240
+ }
241
+ #header {
242
+ padding:10px;
243
+ }
244
+ #content {
245
+ padding-bottom:100px; /* Height of the footer element */
246
+ }
247
+ #footer {
248
+ width:100%;
249
+ height:60px;
250
+ line-height:60px;
251
+ position:absolute;
252
+ bottom:0;
253
+ left:0;
254
+ text-align: center;
255
+ }
256
+ #logo {
257
+ max-width: 100%;
258
+ height: auto;
259
+ text-align: center;
260
+ }
261
+ img, object, embed, canvas, video, audio, picture {
262
+ max-width: 100%;
263
+ height: auto;
264
+ }
265
+ div.bloc {
266
+ width:80%; /* largeur du bloc */
267
+ padding:10px; /* aération interne du bloc */
268
+ vertical-align:middle;
269
+ display:inline-block;
270
+ line-height:1.2; /* on rétablit le line-height */
271
+ text-align:center; /* ... et l\'alignement du texte */
272
+ }
273
+ .wpm_social {
274
+ padding: 0 45px;
275
+ text-align: center;
276
+ }
277
+ @media (max-width: 640px) {
278
+ body {
279
+ font-size:1.2rem;
280
+ }
281
+ }
282
+ @media (min-width: 640px) {
283
+ body {
284
+ font-size:1rem;
285
+ }
286
+ }
287
+ @media (min-width:960px) {
288
+ body {
289
+ font-size:1.2rem;
290
+ }
291
+ }
292
+ @media (min-width:1100px) {
293
+ body {
294
+ font-size:1.5rem;
295
+ }
296
+ }
297
+ /* On ajoute les styles */
298
+ %ADDSTYLEWYSIJA%
299
+ %ADDSTYLE%
300
+
301
+ </style>
302
+
303
+ <!--[if lt IE 7]>
304
+ <style type="text/css">
305
+ #wrapper { height:100%; }
306
+ div.bloc { display:inline; /* correctif inline-block*/ }
307
+ div.conteneur > span { zoom:1; /* layout */ }
308
+ </style>
309
+ <![endif]-->
310
+ %ANALYTICS%
311
+ %HEADERCODE%
312
+ %CSSSLIDER%
313
+ %SCRIPTSLIDER%
314
+ %SCRIPTSLIDESHOW%
315
+ </head>
316
+
317
+ <body>
318
+
319
+ <div id="wrapper">
320
+
321
+ %TOPSOCIALICON%
322
+ <!-- #header -->
323
+
324
+ <div id="content">
325
+ %SLIDESHOWAL%
326
+ %LOGOIMAGE%
327
+ %SLIDESHOWBL%
328
+ <div id="sscontent">
329
+ <h3>%TITRE%</h3>
330
+ <p>%TEXTE%</p>
331
+ %SLIDESHOWBT%
332
+ %COUNTER%
333
+ %NEWSLETTER%
334
+ </div>
335
+ %BOTTOMSOCIALICON%
336
+ </div><!-- #content -->
337
+
338
+ <div id="footer">
339
+ <div class="bloc">%COPYRIGHT%</div>
340
+ <span></span>
341
+ </div><!-- #footer -->
342
+
343
+ </div><!-- #wrapper -->
344
+
345
+ </body>
346
+
347
+ </html>
348
+ ';
349
+
350
+ }
351
+
352
  function wpm_getFontsTab() {
353
  return array("Abel", "Abril Fatface", "Aclonica", "Acme", "Actor", "Adamina", "Advent Pro",
354
  "Aguafina Script", "Aladin", "Aldrich", "Alegreya", "Alegreya SC", "Alex Brush", "Alfa Slab One", "Alice",
includes/shortcodes.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' )
4
+ or die( 'No direct load ! ' );
5
+
6
+ function wpm_analytics_shortcode( $atts ) {
7
+
8
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
9
+ $paramMMode = get_option('wp_maintenance_settings');
10
+
11
+ // Attributes
12
+ extract( shortcode_atts(
13
+ array(
14
+ 'enable' => 0,
15
+ 'code' => $paramMMode['code_analytics'],
16
+ 'domain' => ''.$_SERVER['SERVER_NAME'].''
17
+ ), $atts )
18
+ );
19
+
20
+ if( isset($enable) && $enable==1 && $code!='') {
21
+ return "<script>
22
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
23
+ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
24
+ m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
25
+ })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
26
+
27
+ ga('create', '".$code."', '".$domain."');
28
+ ga('send', 'pageview');
29
+
30
+ </script>";
31
+ } else {
32
+ // Code
33
+ return '';
34
+ }
35
+ }
36
+ add_shortcode( 'wpm_analytics', 'wpm_analytics_shortcode' );
37
+
38
+ function wpm_social_shortcode( $atts ) {
39
+
40
+ if(get_option('wp_maintenance_social')) { extract(get_option('wp_maintenance_social')); }
41
+ $paramSocial = get_option('wp_maintenance_social');
42
+ $paramSocialOption = get_option('wp_maintenance_social_options');
43
+ $countSocial = wpm_array_value_count($paramSocial);
44
+ $contentSocial = '';
45
+ // Si on est en mobile on réduit les icones
46
+ if ( wp_is_mobile() ) {
47
+ $paramSocialOption['size'] = 24;
48
+ }
49
+
50
+ // Attributes
51
+ extract( shortcode_atts(
52
+ array(
53
+ 'size' => 48,
54
+ 'enable' => 0
55
+ ), $atts )
56
+ );
57
+ if($paramSocialOption['theme']!='') {
58
+ $srcIcon = get_stylesheet_directory_uri().'/'.$paramSocialOption['theme'].'/';
59
+ $iconSize = 'width='.$paramSocialOption['size'];
60
+ } else {
61
+ $srcIcon = WP_CONTENT_URL.'/plugins/wp-maintenance/socialicons/'.$paramSocialOption['size'].'x'.$paramSocialOption['size'].'/';
62
+ $iconSize = '';
63
+ }
64
+ if( isset($paramSocialOption['enable']) && $paramSocialOption['enable']==1 && $countSocial>=1) {
65
+ $contentSocial .= '<div id="wpm-social-footer" class="wpm_social"><ul class="wpm_horizontal">';
66
+ foreach($paramSocial as $socialName=>$socialUrl) {
67
+ if($socialUrl!='') {
68
+ $contentSocial .= '<li><a href="'.$socialUrl.'" target="_blank"><img src="'.$srcIcon.$socialName.'.png" alt="'.$paramSocialOption['texte'].' '.ucfirst($socialName).'" '.$iconSize.' title="'.$paramSocialOption['texte'].' '.ucfirst($socialName).'" /></a></li>';
69
+ }
70
+ }
71
+ $contentSocial .='</ul></div>';
72
+ return $contentSocial;
73
+ } else {
74
+ // Code
75
+ return '';
76
+ }
77
+ }
78
+ add_shortcode( 'wpm_social', 'wpm_social_shortcode' );
js/codemirror/addon/hint/anyword-hint.js ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var WORD = /[\w$]+/, RANGE = 500;
15
+
16
+ CodeMirror.registerHelper("hint", "anyword", function(editor, options) {
17
+ var word = options && options.word || WORD;
18
+ var range = options && options.range || RANGE;
19
+ var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
20
+ var end = cur.ch, start = end;
21
+ while (start && word.test(curLine.charAt(start - 1))) --start;
22
+ var curWord = start != end && curLine.slice(start, end);
23
+
24
+ var list = options && options.list || [], seen = {};
25
+ var re = new RegExp(word.source, "g");
26
+ for (var dir = -1; dir <= 1; dir += 2) {
27
+ var line = cur.line, endLine = Math.min(Math.max(line + dir * range, editor.firstLine()), editor.lastLine()) + dir;
28
+ for (; line != endLine; line += dir) {
29
+ var text = editor.getLine(line), m;
30
+ while (m = re.exec(text)) {
31
+ if (line == cur.line && m[0] === curWord) continue;
32
+ if ((!curWord || m[0].lastIndexOf(curWord, 0) == 0) && !Object.prototype.hasOwnProperty.call(seen, m[0])) {
33
+ seen[m[0]] = true;
34
+ list.push(m[0]);
35
+ }
36
+ }
37
+ }
38
+ }
39
+ return {list: list, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
40
+ });
41
+ });
js/codemirror/addon/hint/css-hint.js ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("../../mode/css/css"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "../../mode/css/css"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var pseudoClasses = {link: 1, visited: 1, active: 1, hover: 1, focus: 1,
15
+ "first-letter": 1, "first-line": 1, "first-child": 1,
16
+ before: 1, after: 1, lang: 1};
17
+
18
+ CodeMirror.registerHelper("hint", "css", function(cm) {
19
+ var cur = cm.getCursor(), token = cm.getTokenAt(cur);
20
+ var inner = CodeMirror.innerMode(cm.getMode(), token.state);
21
+ if (inner.mode.name != "css") return;
22
+
23
+ if (token.type == "keyword" && "!important".indexOf(token.string) == 0)
24
+ return {list: ["!important"], from: CodeMirror.Pos(cur.line, token.start),
25
+ to: CodeMirror.Pos(cur.line, token.end)};
26
+
27
+ var start = token.start, end = cur.ch, word = token.string.slice(0, end - start);
28
+ if (/[^\w$_-]/.test(word)) {
29
+ word = ""; start = end = cur.ch;
30
+ }
31
+
32
+ var spec = CodeMirror.resolveMode("text/css");
33
+
34
+ var result = [];
35
+ function add(keywords) {
36
+ for (var name in keywords)
37
+ if (!word || name.lastIndexOf(word, 0) == 0)
38
+ result.push(name);
39
+ }
40
+
41
+ var st = inner.state.state;
42
+ if (st == "pseudo" || token.type == "variable-3") {
43
+ add(pseudoClasses);
44
+ } else if (st == "block" || st == "maybeprop") {
45
+ add(spec.propertyKeywords);
46
+ } else if (st == "prop" || st == "parens" || st == "at" || st == "params") {
47
+ add(spec.valueKeywords);
48
+ add(spec.colorKeywords);
49
+ } else if (st == "media" || st == "media_parens") {
50
+ add(spec.mediaTypes);
51
+ add(spec.mediaFeatures);
52
+ }
53
+
54
+ if (result.length) return {
55
+ list: result,
56
+ from: CodeMirror.Pos(cur.line, start),
57
+ to: CodeMirror.Pos(cur.line, end)
58
+ };
59
+ });
60
+ });
js/codemirror/addon/hint/html-hint.js ADDED
@@ -0,0 +1,348 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("./xml-hint"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "./xml-hint"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var langs = "ab aa af ak sq am ar an hy as av ae ay az bm ba eu be bn bh bi bs br bg my ca ch ce ny zh cv kw co cr hr cs da dv nl dz en eo et ee fo fj fi fr ff gl ka de el gn gu ht ha he hz hi ho hu ia id ie ga ig ik io is it iu ja jv kl kn kr ks kk km ki rw ky kv kg ko ku kj la lb lg li ln lo lt lu lv gv mk mg ms ml mt mi mr mh mn na nv nb nd ne ng nn no ii nr oc oj cu om or os pa pi fa pl ps pt qu rm rn ro ru sa sc sd se sm sg sr gd sn si sk sl so st es su sw ss sv ta te tg th ti bo tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa cy wo fy xh yi yo za zu".split(" ");
15
+ var targets = ["_blank", "_self", "_top", "_parent"];
16
+ var charsets = ["ascii", "utf-8", "utf-16", "latin1", "latin1"];
17
+ var methods = ["get", "post", "put", "delete"];
18
+ var encs = ["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"];
19
+ var media = ["all", "screen", "print", "embossed", "braille", "handheld", "print", "projection", "screen", "tty", "tv", "speech",
20
+ "3d-glasses", "resolution [>][<][=] [X]", "device-aspect-ratio: X/Y", "orientation:portrait",
21
+ "orientation:landscape", "device-height: [X]", "device-width: [X]"];
22
+ var s = { attrs: {} }; // Simple tag, reused for a whole lot of tags
23
+
24
+ var data = {
25
+ a: {
26
+ attrs: {
27
+ href: null, ping: null, type: null,
28
+ media: media,
29
+ target: targets,
30
+ hreflang: langs
31
+ }
32
+ },
33
+ abbr: s,
34
+ acronym: s,
35
+ address: s,
36
+ applet: s,
37
+ area: {
38
+ attrs: {
39
+ alt: null, coords: null, href: null, target: null, ping: null,
40
+ media: media, hreflang: langs, type: null,
41
+ shape: ["default", "rect", "circle", "poly"]
42
+ }
43
+ },
44
+ article: s,
45
+ aside: s,
46
+ audio: {
47
+ attrs: {
48
+ src: null, mediagroup: null,
49
+ crossorigin: ["anonymous", "use-credentials"],
50
+ preload: ["none", "metadata", "auto"],
51
+ autoplay: ["", "autoplay"],
52
+ loop: ["", "loop"],
53
+ controls: ["", "controls"]
54
+ }
55
+ },
56
+ b: s,
57
+ base: { attrs: { href: null, target: targets } },
58
+ basefont: s,
59
+ bdi: s,
60
+ bdo: s,
61
+ big: s,
62
+ blockquote: { attrs: { cite: null } },
63
+ body: s,
64
+ br: s,
65
+ button: {
66
+ attrs: {
67
+ form: null, formaction: null, name: null, value: null,
68
+ autofocus: ["", "autofocus"],
69
+ disabled: ["", "autofocus"],
70
+ formenctype: encs,
71
+ formmethod: methods,
72
+ formnovalidate: ["", "novalidate"],
73
+ formtarget: targets,
74
+ type: ["submit", "reset", "button"]
75
+ }
76
+ },
77
+ canvas: { attrs: { width: null, height: null } },
78
+ caption: s,
79
+ center: s,
80
+ cite: s,
81
+ code: s,
82
+ col: { attrs: { span: null } },
83
+ colgroup: { attrs: { span: null } },
84
+ command: {
85
+ attrs: {
86
+ type: ["command", "checkbox", "radio"],
87
+ label: null, icon: null, radiogroup: null, command: null, title: null,
88
+ disabled: ["", "disabled"],
89
+ checked: ["", "checked"]
90
+ }
91
+ },
92
+ data: { attrs: { value: null } },
93
+ datagrid: { attrs: { disabled: ["", "disabled"], multiple: ["", "multiple"] } },
94
+ datalist: { attrs: { data: null } },
95
+ dd: s,
96
+ del: { attrs: { cite: null, datetime: null } },
97
+ details: { attrs: { open: ["", "open"] } },
98
+ dfn: s,
99
+ dir: s,
100
+ div: s,
101
+ dl: s,
102
+ dt: s,
103
+ em: s,
104
+ embed: { attrs: { src: null, type: null, width: null, height: null } },
105
+ eventsource: { attrs: { src: null } },
106
+ fieldset: { attrs: { disabled: ["", "disabled"], form: null, name: null } },
107
+ figcaption: s,
108
+ figure: s,
109
+ font: s,
110
+ footer: s,
111
+ form: {
112
+ attrs: {
113
+ action: null, name: null,
114
+ "accept-charset": charsets,
115
+ autocomplete: ["on", "off"],
116
+ enctype: encs,
117
+ method: methods,
118
+ novalidate: ["", "novalidate"],
119
+ target: targets
120
+ }
121
+ },
122
+ frame: s,
123
+ frameset: s,
124
+ h1: s, h2: s, h3: s, h4: s, h5: s, h6: s,
125
+ head: {
126
+ attrs: {},
127
+ children: ["title", "base", "link", "style", "meta", "script", "noscript", "command"]
128
+ },
129
+ header: s,
130
+ hgroup: s,
131
+ hr: s,
132
+ html: {
133
+ attrs: { manifest: null },
134
+ children: ["head", "body"]
135
+ },
136
+ i: s,
137
+ iframe: {
138
+ attrs: {
139
+ src: null, srcdoc: null, name: null, width: null, height: null,
140
+ sandbox: ["allow-top-navigation", "allow-same-origin", "allow-forms", "allow-scripts"],
141
+ seamless: ["", "seamless"]
142
+ }
143
+ },
144
+ img: {
145
+ attrs: {
146
+ alt: null, src: null, ismap: null, usemap: null, width: null, height: null,
147
+ crossorigin: ["anonymous", "use-credentials"]
148
+ }
149
+ },
150
+ input: {
151
+ attrs: {
152
+ alt: null, dirname: null, form: null, formaction: null,
153
+ height: null, list: null, max: null, maxlength: null, min: null,
154
+ name: null, pattern: null, placeholder: null, size: null, src: null,
155
+ step: null, value: null, width: null,
156
+ accept: ["audio/*", "video/*", "image/*"],
157
+ autocomplete: ["on", "off"],
158
+ autofocus: ["", "autofocus"],
159
+ checked: ["", "checked"],
160
+ disabled: ["", "disabled"],
161
+ formenctype: encs,
162
+ formmethod: methods,
163
+ formnovalidate: ["", "novalidate"],
164
+ formtarget: targets,
165
+ multiple: ["", "multiple"],
166
+ readonly: ["", "readonly"],
167
+ required: ["", "required"],
168
+ type: ["hidden", "text", "search", "tel", "url", "email", "password", "datetime", "date", "month",
169
+ "week", "time", "datetime-local", "number", "range", "color", "checkbox", "radio",
170
+ "file", "submit", "image", "reset", "button"]
171
+ }
172
+ },
173
+ ins: { attrs: { cite: null, datetime: null } },
174
+ kbd: s,
175
+ keygen: {
176
+ attrs: {
177
+ challenge: null, form: null, name: null,
178
+ autofocus: ["", "autofocus"],
179
+ disabled: ["", "disabled"],
180
+ keytype: ["RSA"]
181
+ }
182
+ },
183
+ label: { attrs: { "for": null, form: null } },
184
+ legend: s,
185
+ li: { attrs: { value: null } },
186
+ link: {
187
+ attrs: {
188
+ href: null, type: null,
189
+ hreflang: langs,
190
+ media: media,
191
+ sizes: ["all", "16x16", "16x16 32x32", "16x16 32x32 64x64"]
192
+ }
193
+ },
194
+ map: { attrs: { name: null } },
195
+ mark: s,
196
+ menu: { attrs: { label: null, type: ["list", "context", "toolbar"] } },
197
+ meta: {
198
+ attrs: {
199
+ content: null,
200
+ charset: charsets,
201
+ name: ["viewport", "application-name", "author", "description", "generator", "keywords"],
202
+ "http-equiv": ["content-language", "content-type", "default-style", "refresh"]
203
+ }
204
+ },
205
+ meter: { attrs: { value: null, min: null, low: null, high: null, max: null, optimum: null } },
206
+ nav: s,
207
+ noframes: s,
208
+ noscript: s,
209
+ object: {
210
+ attrs: {
211
+ data: null, type: null, name: null, usemap: null, form: null, width: null, height: null,
212
+ typemustmatch: ["", "typemustmatch"]
213
+ }
214
+ },
215
+ ol: { attrs: { reversed: ["", "reversed"], start: null, type: ["1", "a", "A", "i", "I"] } },
216
+ optgroup: { attrs: { disabled: ["", "disabled"], label: null } },
217
+ option: { attrs: { disabled: ["", "disabled"], label: null, selected: ["", "selected"], value: null } },
218
+ output: { attrs: { "for": null, form: null, name: null } },
219
+ p: s,
220
+ param: { attrs: { name: null, value: null } },
221
+ pre: s,
222
+ progress: { attrs: { value: null, max: null } },
223
+ q: { attrs: { cite: null } },
224
+ rp: s,
225
+ rt: s,
226
+ ruby: s,
227
+ s: s,
228
+ samp: s,
229
+ script: {
230
+ attrs: {
231
+ type: ["text/javascript"],
232
+ src: null,
233
+ async: ["", "async"],
234
+ defer: ["", "defer"],
235
+ charset: charsets
236
+ }
237
+ },
238
+ section: s,
239
+ select: {
240
+ attrs: {
241
+ form: null, name: null, size: null,
242
+ autofocus: ["", "autofocus"],
243
+ disabled: ["", "disabled"],
244
+ multiple: ["", "multiple"]
245
+ }
246
+ },
247
+ small: s,
248
+ source: { attrs: { src: null, type: null, media: null } },
249
+ span: s,
250
+ strike: s,
251
+ strong: s,
252
+ style: {
253
+ attrs: {
254
+ type: ["text/css"],
255
+ media: media,
256
+ scoped: null
257
+ }
258
+ },
259
+ sub: s,
260
+ summary: s,
261
+ sup: s,
262
+ table: s,
263
+ tbody: s,
264
+ td: { attrs: { colspan: null, rowspan: null, headers: null } },
265
+ textarea: {
266
+ attrs: {
267
+ dirname: null, form: null, maxlength: null, name: null, placeholder: null,
268
+ rows: null, cols: null,
269
+ autofocus: ["", "autofocus"],
270
+ disabled: ["", "disabled"],
271
+ readonly: ["", "readonly"],
272
+ required: ["", "required"],
273
+ wrap: ["soft", "hard"]
274
+ }
275
+ },
276
+ tfoot: s,
277
+ th: { attrs: { colspan: null, rowspan: null, headers: null, scope: ["row", "col", "rowgroup", "colgroup"] } },
278
+ thead: s,
279
+ time: { attrs: { datetime: null } },
280
+ title: s,
281
+ tr: s,
282
+ track: {
283
+ attrs: {
284
+ src: null, label: null, "default": null,
285
+ kind: ["subtitles", "captions", "descriptions", "chapters", "metadata"],
286
+ srclang: langs
287
+ }
288
+ },
289
+ tt: s,
290
+ u: s,
291
+ ul: s,
292
+ "var": s,
293
+ video: {
294
+ attrs: {
295
+ src: null, poster: null, width: null, height: null,
296
+ crossorigin: ["anonymous", "use-credentials"],
297
+ preload: ["auto", "metadata", "none"],
298
+ autoplay: ["", "autoplay"],
299
+ mediagroup: ["movie"],
300
+ muted: ["", "muted"],
301
+ controls: ["", "controls"]
302
+ }
303
+ },
304
+ wbr: s
305
+ };
306
+
307
+ var globalAttrs = {
308
+ accesskey: ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"],
309
+ "class": null,
310
+ contenteditable: ["true", "false"],
311
+ contextmenu: null,
312
+ dir: ["ltr", "rtl", "auto"],
313
+ draggable: ["true", "false", "auto"],
314
+ dropzone: ["copy", "move", "link", "string:", "file:"],
315
+ hidden: ["hidden"],
316
+ id: null,
317
+ inert: ["inert"],
318
+ itemid: null,
319
+ itemprop: null,
320
+ itemref: null,
321
+ itemscope: ["itemscope"],
322
+ itemtype: null,
323
+ lang: ["en", "es"],
324
+ spellcheck: ["true", "false"],
325
+ style: null,
326
+ tabindex: ["1", "2", "3", "4", "5", "6", "7", "8", "9"],
327
+ title: null,
328
+ translate: ["yes", "no"],
329
+ onclick: null,
330
+ rel: ["stylesheet", "alternate", "author", "bookmark", "help", "license", "next", "nofollow", "noreferrer", "prefetch", "prev", "search", "tag"]
331
+ };
332
+ function populate(obj) {
333
+ for (var attr in globalAttrs) if (globalAttrs.hasOwnProperty(attr))
334
+ obj.attrs[attr] = globalAttrs[attr];
335
+ }
336
+
337
+ populate(s);
338
+ for (var tag in data) if (data.hasOwnProperty(tag) && data[tag] != s)
339
+ populate(data[tag]);
340
+
341
+ CodeMirror.htmlSchema = data;
342
+ function htmlHint(cm, options) {
343
+ var local = {schemaInfo: data};
344
+ if (options) for (var opt in options) local[opt] = options[opt];
345
+ return CodeMirror.hint.xml(cm, local);
346
+ }
347
+ CodeMirror.registerHelper("hint", "html", htmlHint);
348
+ });
js/codemirror/addon/hint/javascript-hint.js ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ var Pos = CodeMirror.Pos;
13
+
14
+ function forEach(arr, f) {
15
+ for (var i = 0, e = arr.length; i < e; ++i) f(arr[i]);
16
+ }
17
+
18
+ function arrayContains(arr, item) {
19
+ if (!Array.prototype.indexOf) {
20
+ var i = arr.length;
21
+ while (i--) {
22
+ if (arr[i] === item) {
23
+ return true;
24
+ }
25
+ }
26
+ return false;
27
+ }
28
+ return arr.indexOf(item) != -1;
29
+ }
30
+
31
+ function scriptHint(editor, keywords, getToken, options) {
32
+ // Find the token at the cursor
33
+ var cur = editor.getCursor(), token = getToken(editor, cur);
34
+ if (/\b(?:string|comment)\b/.test(token.type)) return;
35
+ token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;
36
+
37
+ // If it's not a 'word-style' token, ignore the token.
38
+ if (!/^[\w$_]*$/.test(token.string)) {
39
+ token = {start: cur.ch, end: cur.ch, string: "", state: token.state,
40
+ type: token.string == "." ? "property" : null};
41
+ } else if (token.end > cur.ch) {
42
+ token.end = cur.ch;
43
+ token.string = token.string.slice(0, cur.ch - token.start);
44
+ }
45
+
46
+ var tprop = token;
47
+ // If it is a property, find out what it is a property of.
48
+ while (tprop.type == "property") {
49
+ tprop = getToken(editor, Pos(cur.line, tprop.start));
50
+ if (tprop.string != ".") return;
51
+ tprop = getToken(editor, Pos(cur.line, tprop.start));
52
+ if (!context) var context = [];
53
+ context.push(tprop);
54
+ }
55
+ return {list: getCompletions(token, context, keywords, options),
56
+ from: Pos(cur.line, token.start),
57
+ to: Pos(cur.line, token.end)};
58
+ }
59
+
60
+ function javascriptHint(editor, options) {
61
+ return scriptHint(editor, javascriptKeywords,
62
+ function (e, cur) {return e.getTokenAt(cur);},
63
+ options);
64
+ };
65
+ CodeMirror.registerHelper("hint", "javascript", javascriptHint);
66
+
67
+ function getCoffeeScriptToken(editor, cur) {
68
+ // This getToken, it is for coffeescript, imitates the behavior of
69
+ // getTokenAt method in javascript.js, that is, returning "property"
70
+ // type and treat "." as indepenent token.
71
+ var token = editor.getTokenAt(cur);
72
+ if (cur.ch == token.start + 1 && token.string.charAt(0) == '.') {
73
+ token.end = token.start;
74
+ token.string = '.';
75
+ token.type = "property";
76
+ }
77
+ else if (/^\.[\w$_]*$/.test(token.string)) {
78
+ token.type = "property";
79
+ token.start++;
80
+ token.string = token.string.replace(/\./, '');
81
+ }
82
+ return token;
83
+ }
84
+
85
+ function coffeescriptHint(editor, options) {
86
+ return scriptHint(editor, coffeescriptKeywords, getCoffeeScriptToken, options);
87
+ }
88
+ CodeMirror.registerHelper("hint", "coffeescript", coffeescriptHint);
89
+
90
+ var stringProps = ("charAt charCodeAt indexOf lastIndexOf substring substr slice trim trimLeft trimRight " +
91
+ "toUpperCase toLowerCase split concat match replace search").split(" ");
92
+ var arrayProps = ("length concat join splice push pop shift unshift slice reverse sort indexOf " +
93
+ "lastIndexOf every some filter forEach map reduce reduceRight ").split(" ");
94
+ var funcProps = "prototype apply call bind".split(" ");
95
+ var javascriptKeywords = ("break case catch continue debugger default delete do else false finally for function " +
96
+ "if in instanceof new null return switch throw true try typeof var void while with").split(" ");
97
+ var coffeescriptKeywords = ("and break catch class continue delete do else extends false finally for " +
98
+ "if in instanceof isnt new no not null of off on or return switch then throw true try typeof until void while with yes").split(" ");
99
+
100
+ function forAllProps(obj, callback) {
101
+ if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {
102
+ for (var name in obj) callback(name)
103
+ } else {
104
+ for (var o = obj; o; o = Object.getPrototypeOf(o))
105
+ Object.getOwnPropertyNames(o).forEach(callback)
106
+ }
107
+ }
108
+
109
+ function getCompletions(token, context, keywords, options) {
110
+ var found = [], start = token.string, global = options && options.globalScope || window;
111
+ function maybeAdd(str) {
112
+ if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
113
+ }
114
+ function gatherCompletions(obj) {
115
+ if (typeof obj == "string") forEach(stringProps, maybeAdd);
116
+ else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
117
+ else if (obj instanceof Function) forEach(funcProps, maybeAdd);
118
+ forAllProps(obj, maybeAdd)
119
+ }
120
+
121
+ if (context && context.length) {
122
+ // If this is a property, see if it belongs to some object we can
123
+ // find in the current environment.
124
+ var obj = context.pop(), base;
125
+ if (obj.type && obj.type.indexOf("variable") === 0) {
126
+ if (options && options.additionalContext)
127
+ base = options.additionalContext[obj.string];
128
+ if (!options || options.useGlobalScope !== false)
129
+ base = base || global[obj.string];
130
+ } else if (obj.type == "string") {
131
+ base = "";
132
+ } else if (obj.type == "atom") {
133
+ base = 1;
134
+ } else if (obj.type == "function") {
135
+ if (global.jQuery != null && (obj.string == '$' || obj.string == 'jQuery') &&
136
+ (typeof global.jQuery == 'function'))
137
+ base = global.jQuery();
138
+ else if (global._ != null && (obj.string == '_') && (typeof global._ == 'function'))
139
+ base = global._();
140
+ }
141
+ while (base != null && context.length)
142
+ base = base[context.pop().string];
143
+ if (base != null) gatherCompletions(base);
144
+ } else {
145
+ // If not, just look in the global object and any local scope
146
+ // (reading into JS mode internals to get at the local and global variables)
147
+ for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
148
+ for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
149
+ if (!options || options.useGlobalScope !== false)
150
+ gatherCompletions(global);
151
+ forEach(keywords, maybeAdd);
152
+ }
153
+ return found;
154
+ }
155
+ });
js/codemirror/addon/hint/show-hint.css ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .CodeMirror-hints {
2
+ position: absolute;
3
+ z-index: 10;
4
+ overflow: hidden;
5
+ list-style: none;
6
+
7
+ margin: 0;
8
+ padding: 2px;
9
+
10
+ -webkit-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
11
+ -moz-box-shadow: 2px 3px 5px rgba(0,0,0,.2);
12
+ box-shadow: 2px 3px 5px rgba(0,0,0,.2);
13
+ border-radius: 3px;
14
+ border: 1px solid silver;
15
+
16
+ background: white;
17
+ font-size: 90%;
18
+ font-family: monospace;
19
+
20
+ max-height: 20em;
21
+ overflow-y: auto;
22
+ }
23
+
24
+ .CodeMirror-hint {
25
+ margin: 0;
26
+ padding: 0 4px;
27
+ border-radius: 2px;
28
+ white-space: pre;
29
+ color: black;
30
+ cursor: pointer;
31
+ }
32
+
33
+ li.CodeMirror-hint-active {
34
+ background: #08f;
35
+ color: white;
36
+ }
js/codemirror/addon/hint/show-hint.js ADDED
@@ -0,0 +1,438 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var HINT_ELEMENT_CLASS = "CodeMirror-hint";
15
+ var ACTIVE_HINT_ELEMENT_CLASS = "CodeMirror-hint-active";
16
+
17
+ // This is the old interface, kept around for now to stay
18
+ // backwards-compatible.
19
+ CodeMirror.showHint = function(cm, getHints, options) {
20
+ if (!getHints) return cm.showHint(options);
21
+ if (options && options.async) getHints.async = true;
22
+ var newOpts = {hint: getHints};
23
+ if (options) for (var prop in options) newOpts[prop] = options[prop];
24
+ return cm.showHint(newOpts);
25
+ };
26
+
27
+ CodeMirror.defineExtension("showHint", function(options) {
28
+ options = parseOptions(this, this.getCursor("start"), options);
29
+ var selections = this.listSelections()
30
+ if (selections.length > 1) return;
31
+ // By default, don't allow completion when something is selected.
32
+ // A hint function can have a `supportsSelection` property to
33
+ // indicate that it can handle selections.
34
+ if (this.somethingSelected()) {
35
+ if (!options.hint.supportsSelection) return;
36
+ // Don't try with cross-line selections
37
+ for (var i = 0; i < selections.length; i++)
38
+ if (selections[i].head.line != selections[i].anchor.line) return;
39
+ }
40
+
41
+ if (this.state.completionActive) this.state.completionActive.close();
42
+ var completion = this.state.completionActive = new Completion(this, options);
43
+ if (!completion.options.hint) return;
44
+
45
+ CodeMirror.signal(this, "startCompletion", this);
46
+ completion.update(true);
47
+ });
48
+
49
+ function Completion(cm, options) {
50
+ this.cm = cm;
51
+ this.options = options;
52
+ this.widget = null;
53
+ this.debounce = 0;
54
+ this.tick = 0;
55
+ this.startPos = this.cm.getCursor("start");
56
+ this.startLen = this.cm.getLine(this.startPos.line).length - this.cm.getSelection().length;
57
+
58
+ var self = this;
59
+ cm.on("cursorActivity", this.activityFunc = function() { self.cursorActivity(); });
60
+ }
61
+
62
+ var requestAnimationFrame = window.requestAnimationFrame || function(fn) {
63
+ return setTimeout(fn, 1000/60);
64
+ };
65
+ var cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
66
+
67
+ Completion.prototype = {
68
+ close: function() {
69
+ if (!this.active()) return;
70
+ this.cm.state.completionActive = null;
71
+ this.tick = null;
72
+ this.cm.off("cursorActivity", this.activityFunc);
73
+
74
+ if (this.widget && this.data) CodeMirror.signal(this.data, "close");
75
+ if (this.widget) this.widget.close();
76
+ CodeMirror.signal(this.cm, "endCompletion", this.cm);
77
+ },
78
+
79
+ active: function() {
80
+ return this.cm.state.completionActive == this;
81
+ },
82
+
83
+ pick: function(data, i) {
84
+ var completion = data.list[i];
85
+ if (completion.hint) completion.hint(this.cm, data, completion);
86
+ else this.cm.replaceRange(getText(completion), completion.from || data.from,
87
+ completion.to || data.to, "complete");
88
+ CodeMirror.signal(data, "pick", completion);
89
+ this.close();
90
+ },
91
+
92
+ cursorActivity: function() {
93
+ if (this.debounce) {
94
+ cancelAnimationFrame(this.debounce);
95
+ this.debounce = 0;
96
+ }
97
+
98
+ var pos = this.cm.getCursor(), line = this.cm.getLine(pos.line);
99
+ if (pos.line != this.startPos.line || line.length - pos.ch != this.startLen - this.startPos.ch ||
100
+ pos.ch < this.startPos.ch || this.cm.somethingSelected() ||
101
+ (pos.ch && this.options.closeCharacters.test(line.charAt(pos.ch - 1)))) {
102
+ this.close();
103
+ } else {
104
+ var self = this;
105
+ this.debounce = requestAnimationFrame(function() {self.update();});
106
+ if (this.widget) this.widget.disable();
107
+ }
108
+ },
109
+
110
+ update: function(first) {
111
+ if (this.tick == null) return
112
+ var self = this, myTick = ++this.tick
113
+ fetchHints(this.options.hint, this.cm, this.options, function(data) {
114
+ if (self.tick == myTick) self.finishUpdate(data, first)
115
+ })
116
+ },
117
+
118
+ finishUpdate: function(data, first) {
119
+ if (this.data) CodeMirror.signal(this.data, "update");
120
+
121
+ var picked = (this.widget && this.widget.picked) || (first && this.options.completeSingle);
122
+ if (this.widget) this.widget.close();
123
+
124
+ if (data && this.data && isNewCompletion(this.data, data)) return;
125
+ this.data = data;
126
+
127
+ if (data && data.list.length) {
128
+ if (picked && data.list.length == 1) {
129
+ this.pick(data, 0);
130
+ } else {
131
+ this.widget = new Widget(this, data);
132
+ CodeMirror.signal(data, "shown");
133
+ }
134
+ }
135
+ }
136
+ };
137
+
138
+ function isNewCompletion(old, nw) {
139
+ var moved = CodeMirror.cmpPos(nw.from, old.from)
140
+ return moved > 0 && old.to.ch - old.from.ch != nw.to.ch - nw.from.ch
141
+ }
142
+
143
+ function parseOptions(cm, pos, options) {
144
+ var editor = cm.options.hintOptions;
145
+ var out = {};
146
+ for (var prop in defaultOptions) out[prop] = defaultOptions[prop];
147
+ if (editor) for (var prop in editor)
148
+ if (editor[prop] !== undefined) out[prop] = editor[prop];
149
+ if (options) for (var prop in options)
150
+ if (options[prop] !== undefined) out[prop] = options[prop];
151
+ if (out.hint.resolve) out.hint = out.hint.resolve(cm, pos)
152
+ return out;
153
+ }
154
+
155
+ function getText(completion) {
156
+ if (typeof completion == "string") return completion;
157
+ else return completion.text;
158
+ }
159
+
160
+ function buildKeyMap(completion, handle) {
161
+ var baseMap = {
162
+ Up: function() {handle.moveFocus(-1);},
163
+ Down: function() {handle.moveFocus(1);},
164
+ PageUp: function() {handle.moveFocus(-handle.menuSize() + 1, true);},
165
+ PageDown: function() {handle.moveFocus(handle.menuSize() - 1, true);},
166
+ Home: function() {handle.setFocus(0);},
167
+ End: function() {handle.setFocus(handle.length - 1);},
168
+ Enter: handle.pick,
169
+ Tab: handle.pick,
170
+ Esc: handle.close
171
+ };
172
+ var custom = completion.options.customKeys;
173
+ var ourMap = custom ? {} : baseMap;
174
+ function addBinding(key, val) {
175
+ var bound;
176
+ if (typeof val != "string")
177
+ bound = function(cm) { return val(cm, handle); };
178
+ // This mechanism is deprecated
179
+ else if (baseMap.hasOwnProperty(val))
180
+ bound = baseMap[val];
181
+ else
182
+ bound = val;
183
+ ourMap[key] = bound;
184
+ }
185
+ if (custom)
186
+ for (var key in custom) if (custom.hasOwnProperty(key))
187
+ addBinding(key, custom[key]);
188
+ var extra = completion.options.extraKeys;
189
+ if (extra)
190
+ for (var key in extra) if (extra.hasOwnProperty(key))
191
+ addBinding(key, extra[key]);
192
+ return ourMap;
193
+ }
194
+
195
+ function getHintElement(hintsElement, el) {
196
+ while (el && el != hintsElement) {
197
+ if (el.nodeName.toUpperCase() === "LI" && el.parentNode == hintsElement) return el;
198
+ el = el.parentNode;
199
+ }
200
+ }
201
+
202
+ function Widget(completion, data) {
203
+ this.completion = completion;
204
+ this.data = data;
205
+ this.picked = false;
206
+ var widget = this, cm = completion.cm;
207
+
208
+ var hints = this.hints = document.createElement("ul");
209
+ hints.className = "CodeMirror-hints";
210
+ this.selectedHint = data.selectedHint || 0;
211
+
212
+ var completions = data.list;
213
+ for (var i = 0; i < completions.length; ++i) {
214
+ var elt = hints.appendChild(document.createElement("li")), cur = completions[i];
215
+ var className = HINT_ELEMENT_CLASS + (i != this.selectedHint ? "" : " " + ACTIVE_HINT_ELEMENT_CLASS);
216
+ if (cur.className != null) className = cur.className + " " + className;
217
+ elt.className = className;
218
+ if (cur.render) cur.render(elt, data, cur);
219
+ else elt.appendChild(document.createTextNode(cur.displayText || getText(cur)));
220
+ elt.hintId = i;
221
+ }
222
+
223
+ var pos = cm.cursorCoords(completion.options.alignWithWord ? data.from : null);
224
+ var left = pos.left, top = pos.bottom, below = true;
225
+ hints.style.left = left + "px";
226
+ hints.style.top = top + "px";
227
+ // If we're at the edge of the screen, then we want the menu to appear on the left of the cursor.
228
+ var winW = window.innerWidth || Math.max(document.body.offsetWidth, document.documentElement.offsetWidth);
229
+ var winH = window.innerHeight || Math.max(document.body.offsetHeight, document.documentElement.offsetHeight);
230
+ (completion.options.container || document.body).appendChild(hints);
231
+ var box = hints.getBoundingClientRect(), overlapY = box.bottom - winH;
232
+ var scrolls = hints.scrollHeight > hints.clientHeight + 1
233
+ var startScroll = cm.getScrollInfo();
234
+
235
+ if (overlapY > 0) {
236
+ var height = box.bottom - box.top, curTop = pos.top - (pos.bottom - box.top);
237
+ if (curTop - height > 0) { // Fits above cursor
238
+ hints.style.top = (top = pos.top - height) + "px";
239
+ below = false;
240
+ } else if (height > winH) {
241
+ hints.style.height = (winH - 5) + "px";
242
+ hints.style.top = (top = pos.bottom - box.top) + "px";
243
+ var cursor = cm.getCursor();
244
+ if (data.from.ch != cursor.ch) {
245
+ pos = cm.cursorCoords(cursor);
246
+ hints.style.left = (left = pos.left) + "px";
247
+ box = hints.getBoundingClientRect();
248
+ }
249
+ }
250
+ }
251
+ var overlapX = box.right - winW;
252
+ if (overlapX > 0) {
253
+ if (box.right - box.left > winW) {
254
+ hints.style.width = (winW - 5) + "px";
255
+ overlapX -= (box.right - box.left) - winW;
256
+ }
257
+ hints.style.left = (left = pos.left - overlapX) + "px";
258
+ }
259
+ if (scrolls) for (var node = hints.firstChild; node; node = node.nextSibling)
260
+ node.style.paddingRight = cm.display.nativeBarWidth + "px"
261
+
262
+ cm.addKeyMap(this.keyMap = buildKeyMap(completion, {
263
+ moveFocus: function(n, avoidWrap) { widget.changeActive(widget.selectedHint + n, avoidWrap); },
264
+ setFocus: function(n) { widget.changeActive(n); },
265
+ menuSize: function() { return widget.screenAmount(); },
266
+ length: completions.length,
267
+ close: function() { completion.close(); },
268
+ pick: function() { widget.pick(); },
269
+ data: data
270
+ }));
271
+
272
+ if (completion.options.closeOnUnfocus) {
273
+ var closingOnBlur;
274
+ cm.on("blur", this.onBlur = function() { closingOnBlur = setTimeout(function() { completion.close(); }, 100); });
275
+ cm.on("focus", this.onFocus = function() { clearTimeout(closingOnBlur); });
276
+ }
277
+
278
+ cm.on("scroll", this.onScroll = function() {
279
+ var curScroll = cm.getScrollInfo(), editor = cm.getWrapperElement().getBoundingClientRect();
280
+ var newTop = top + startScroll.top - curScroll.top;
281
+ var point = newTop - (window.pageYOffset || (document.documentElement || document.body).scrollTop);
282
+ if (!below) point += hints.offsetHeight;
283
+ if (point <= editor.top || point >= editor.bottom) return completion.close();
284
+ hints.style.top = newTop + "px";
285
+ hints.style.left = (left + startScroll.left - curScroll.left) + "px";
286
+ });
287
+
288
+ CodeMirror.on(hints, "dblclick", function(e) {
289
+ var t = getHintElement(hints, e.target || e.srcElement);
290
+ if (t && t.hintId != null) {widget.changeActive(t.hintId); widget.pick();}
291
+ });
292
+
293
+ CodeMirror.on(hints, "click", function(e) {
294
+ var t = getHintElement(hints, e.target || e.srcElement);
295
+ if (t && t.hintId != null) {
296
+ widget.changeActive(t.hintId);
297
+ if (completion.options.completeOnSingleClick) widget.pick();
298
+ }
299
+ });
300
+
301
+ CodeMirror.on(hints, "mousedown", function() {
302
+ setTimeout(function(){cm.focus();}, 20);
303
+ });
304
+
305
+ CodeMirror.signal(data, "select", completions[0], hints.firstChild);
306
+ return true;
307
+ }
308
+
309
+ Widget.prototype = {
310
+ close: function() {
311
+ if (this.completion.widget != this) return;
312
+ this.completion.widget = null;
313
+ this.hints.parentNode.removeChild(this.hints);
314
+ this.completion.cm.removeKeyMap(this.keyMap);
315
+
316
+ var cm = this.completion.cm;
317
+ if (this.completion.options.closeOnUnfocus) {
318
+ cm.off("blur", this.onBlur);
319
+ cm.off("focus", this.onFocus);
320
+ }
321
+ cm.off("scroll", this.onScroll);
322
+ },
323
+
324
+ disable: function() {
325
+ this.completion.cm.removeKeyMap(this.keyMap);
326
+ var widget = this;
327
+ this.keyMap = {Enter: function() { widget.picked = true; }};
328
+ this.completion.cm.addKeyMap(this.keyMap);
329
+ },
330
+
331
+ pick: function() {
332
+ this.completion.pick(this.data, this.selectedHint);
333
+ },
334
+
335
+ changeActive: function(i, avoidWrap) {
336
+ if (i >= this.data.list.length)
337
+ i = avoidWrap ? this.data.list.length - 1 : 0;
338
+ else if (i < 0)
339
+ i = avoidWrap ? 0 : this.data.list.length - 1;
340
+ if (this.selectedHint == i) return;
341
+ var node = this.hints.childNodes[this.selectedHint];
342
+ node.className = node.className.replace(" " + ACTIVE_HINT_ELEMENT_CLASS, "");
343
+ node = this.hints.childNodes[this.selectedHint = i];
344
+ node.className += " " + ACTIVE_HINT_ELEMENT_CLASS;
345
+ if (node.offsetTop < this.hints.scrollTop)
346
+ this.hints.scrollTop = node.offsetTop - 3;
347
+ else if (node.offsetTop + node.offsetHeight > this.hints.scrollTop + this.hints.clientHeight)
348
+ this.hints.scrollTop = node.offsetTop + node.offsetHeight - this.hints.clientHeight + 3;
349
+ CodeMirror.signal(this.data, "select", this.data.list[this.selectedHint], node);
350
+ },
351
+
352
+ screenAmount: function() {
353
+ return Math.floor(this.hints.clientHeight / this.hints.firstChild.offsetHeight) || 1;
354
+ }
355
+ };
356
+
357
+ function applicableHelpers(cm, helpers) {
358
+ if (!cm.somethingSelected()) return helpers
359
+ var result = []
360
+ for (var i = 0; i < helpers.length; i++)
361
+ if (helpers[i].supportsSelection) result.push(helpers[i])
362
+ return result
363
+ }
364
+
365
+ function fetchHints(hint, cm, options, callback) {
366
+ if (hint.async) {
367
+ hint(cm, callback, options)
368
+ } else {
369
+ var result = hint(cm, options)
370
+ if (result && result.then) result.then(callback)
371
+ else callback(result)
372
+ }
373
+ }
374
+
375
+ function resolveAutoHints(cm, pos) {
376
+ var helpers = cm.getHelpers(pos, "hint"), words
377
+ if (helpers.length) {
378
+ var resolved = function(cm, callback, options) {
379
+ var app = applicableHelpers(cm, helpers);
380
+ function run(i) {
381
+ if (i == app.length) return callback(null)
382
+ fetchHints(app[i], cm, options, function(result) {
383
+ if (result && result.list.length > 0) callback(result)
384
+ else run(i + 1)
385
+ })
386
+ }
387
+ run(0)
388
+ }
389
+ resolved.async = true
390
+ resolved.supportsSelection = true
391
+ return resolved
392
+ } else if (words = cm.getHelper(cm.getCursor(), "hintWords")) {
393
+ return function(cm) { return CodeMirror.hint.fromList(cm, {words: words}) }
394
+ } else if (CodeMirror.hint.anyword) {
395
+ return function(cm, options) { return CodeMirror.hint.anyword(cm, options) }
396
+ } else {
397
+ return function() {}
398
+ }
399
+ }
400
+
401
+ CodeMirror.registerHelper("hint", "auto", {
402
+ resolve: resolveAutoHints
403
+ });
404
+
405
+ CodeMirror.registerHelper("hint", "fromList", function(cm, options) {
406
+ var cur = cm.getCursor(), token = cm.getTokenAt(cur);
407
+ var to = CodeMirror.Pos(cur.line, token.end);
408
+ if (token.string && /\w/.test(token.string[token.string.length - 1])) {
409
+ var term = token.string, from = CodeMirror.Pos(cur.line, token.start);
410
+ } else {
411
+ var term = "", from = to;
412
+ }
413
+ var found = [];
414
+ for (var i = 0; i < options.words.length; i++) {
415
+ var word = options.words[i];
416
+ if (word.slice(0, term.length) == term)
417
+ found.push(word);
418
+ }
419
+
420
+ if (found.length) return {list: found, from: from, to: to};
421
+ });
422
+
423
+ CodeMirror.commands.autocomplete = CodeMirror.showHint;
424
+
425
+ var defaultOptions = {
426
+ hint: CodeMirror.hint.auto,
427
+ completeSingle: true,
428
+ alignWithWord: true,
429
+ closeCharacters: /[\s()\[\]{};:>,]/,
430
+ closeOnUnfocus: true,
431
+ completeOnSingleClick: true,
432
+ container: null,
433
+ customKeys: null,
434
+ extraKeys: null
435
+ };
436
+
437
+ CodeMirror.defineOption("hintOptions", null);
438
+ });
js/codemirror/addon/hint/sql-hint.js ADDED
@@ -0,0 +1,271 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("../../mode/sql/sql"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "../../mode/sql/sql"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var tables;
15
+ var defaultTable;
16
+ var keywords;
17
+ var CONS = {
18
+ QUERY_DIV: ";",
19
+ ALIAS_KEYWORD: "AS"
20
+ };
21
+ var Pos = CodeMirror.Pos, cmpPos = CodeMirror.cmpPos;
22
+
23
+ function isArray(val) { return Object.prototype.toString.call(val) == "[object Array]" }
24
+
25
+ function getKeywords(editor) {
26
+ var mode = editor.doc.modeOption;
27
+ if (mode === "sql") mode = "text/x-sql";
28
+ return CodeMirror.resolveMode(mode).keywords;
29
+ }
30
+
31
+ function getText(item) {
32
+ return typeof item == "string" ? item : item.text;
33
+ }
34
+
35
+ function wrapTable(name, value) {
36
+ if (isArray(value)) value = {columns: value}
37
+ if (!value.text) value.text = name
38
+ return value
39
+ }
40
+
41
+ function parseTables(input) {
42
+ var result = {}
43
+ if (isArray(input)) {
44
+ for (var i = input.length - 1; i >= 0; i--) {
45
+ var item = input[i]
46
+ result[getText(item).toUpperCase()] = wrapTable(getText(item), item)
47
+ }
48
+ } else if (input) {
49
+ for (var name in input)
50
+ result[name.toUpperCase()] = wrapTable(name, input[name])
51
+ }
52
+ return result
53
+ }
54
+
55
+ function getTable(name) {
56
+ return tables[name.toUpperCase()]
57
+ }
58
+
59
+ function shallowClone(object) {
60
+ var result = {};
61
+ for (var key in object) if (object.hasOwnProperty(key))
62
+ result[key] = object[key];
63
+ return result;
64
+ }
65
+
66
+ function match(string, word) {
67
+ var len = string.length;
68
+ var sub = getText(word).substr(0, len);
69
+ return string.toUpperCase() === sub.toUpperCase();
70
+ }
71
+
72
+ function addMatches(result, search, wordlist, formatter) {
73
+ if (isArray(wordlist)) {
74
+ for (var i = 0; i < wordlist.length; i++)
75
+ if (match(search, wordlist[i])) result.push(formatter(wordlist[i]))
76
+ } else {
77
+ for (var word in wordlist) if (wordlist.hasOwnProperty(word)) {
78
+ var val = wordlist[word]
79
+ if (!val || val === true)
80
+ val = word
81
+ else
82
+ val = val.displayText ? {text: val.text, displayText: val.displayText} : val.text
83
+ if (match(search, val)) result.push(formatter(val))
84
+ }
85
+ }
86
+ }
87
+
88
+ function cleanName(name) {
89
+ // Get rid name from backticks(`) and preceding dot(.)
90
+ if (name.charAt(0) == ".") {
91
+ name = name.substr(1);
92
+ }
93
+ return name.replace(/`/g, "");
94
+ }
95
+
96
+ function insertBackticks(name) {
97
+ var nameParts = getText(name).split(".");
98
+ for (var i = 0; i < nameParts.length; i++)
99
+ nameParts[i] = "`" + nameParts[i] + "`";
100
+ var escaped = nameParts.join(".");
101
+ if (typeof name == "string") return escaped;
102
+ name = shallowClone(name);
103
+ name.text = escaped;
104
+ return name;
105
+ }
106
+
107
+ function nameCompletion(cur, token, result, editor) {
108
+ // Try to complete table, column names and return start position of completion
109
+ var useBacktick = false;
110
+ var nameParts = [];
111
+ var start = token.start;
112
+ var cont = true;
113
+ while (cont) {
114
+ cont = (token.string.charAt(0) == ".");
115
+ useBacktick = useBacktick || (token.string.charAt(0) == "`");
116
+
117
+ start = token.start;
118
+ nameParts.unshift(cleanName(token.string));
119
+
120
+ token = editor.getTokenAt(Pos(cur.line, token.start));
121
+ if (token.string == ".") {
122
+ cont = true;
123
+ token = editor.getTokenAt(Pos(cur.line, token.start));
124
+ }
125
+ }
126
+
127
+ // Try to complete table names
128
+ var string = nameParts.join(".");
129
+ addMatches(result, string, tables, function(w) {
130
+ return useBacktick ? insertBackticks(w) : w;
131
+ });
132
+
133
+ // Try to complete columns from defaultTable
134
+ addMatches(result, string, defaultTable, function(w) {
135
+ return useBacktick ? insertBackticks(w) : w;
136
+ });
137
+
138
+ // Try to complete columns
139
+ string = nameParts.pop();
140
+ var table = nameParts.join(".");
141
+
142
+ var alias = false;
143
+ var aliasTable = table;
144
+ // Check if table is available. If not, find table by Alias
145
+ if (!getTable(table)) {
146
+ var oldTable = table;
147
+ table = findTableByAlias(table, editor);
148
+ if (table !== oldTable) alias = true;
149
+ }
150
+
151
+ var columns = getTable(table);
152
+ if (columns && columns.columns)
153
+ columns = columns.columns;
154
+
155
+ if (columns) {
156
+ addMatches(result, string, columns, function(w) {
157
+ var tableInsert = table;
158
+ if (alias == true) tableInsert = aliasTable;
159
+ if (typeof w == "string") {
160
+ w = tableInsert + "." + w;
161
+ } else {
162
+ w = shallowClone(w);
163
+ w.text = tableInsert + "." + w.text;
164
+ }
165
+ return useBacktick ? insertBackticks(w) : w;
166
+ });
167
+ }
168
+
169
+ return start;
170
+ }
171
+
172
+ function eachWord(lineText, f) {
173
+ if (!lineText) return;
174
+ var excepted = /[,;]/g;
175
+ var words = lineText.split(" ");
176
+ for (var i = 0; i < words.length; i++) {
177
+ f(words[i]?words[i].replace(excepted, '') : '');
178
+ }
179
+ }
180
+
181
+ function findTableByAlias(alias, editor) {
182
+ var doc = editor.doc;
183
+ var fullQuery = doc.getValue();
184
+ var aliasUpperCase = alias.toUpperCase();
185
+ var previousWord = "";
186
+ var table = "";
187
+ var separator = [];
188
+ var validRange = {
189
+ start: Pos(0, 0),
190
+ end: Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).length)
191
+ };
192
+
193
+ //add separator
194
+ var indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV);
195
+ while(indexOfSeparator != -1) {
196
+ separator.push(doc.posFromIndex(indexOfSeparator));
197
+ indexOfSeparator = fullQuery.indexOf(CONS.QUERY_DIV, indexOfSeparator+1);
198
+ }
199
+ separator.unshift(Pos(0, 0));
200
+ separator.push(Pos(editor.lastLine(), editor.getLineHandle(editor.lastLine()).text.length));
201
+
202
+ //find valid range
203
+ var prevItem = null;
204
+ var current = editor.getCursor()
205
+ for (var i = 0; i < separator.length; i++) {
206
+ if ((prevItem == null || cmpPos(current, prevItem) > 0) && cmpPos(current, separator[i]) <= 0) {
207
+ validRange = {start: prevItem, end: separator[i]};
208
+ break;
209
+ }
210
+ prevItem = separator[i];
211
+ }
212
+
213
+ var query = doc.getRange(validRange.start, validRange.end, false);
214
+
215
+ for (var i = 0; i < query.length; i++) {
216
+ var lineText = query[i];
217
+ eachWord(lineText, function(word) {
218
+ var wordUpperCase = word.toUpperCase();
219
+ if (wordUpperCase === aliasUpperCase && getTable(previousWord))
220
+ table = previousWord;
221
+ if (wordUpperCase !== CONS.ALIAS_KEYWORD)
222
+ previousWord = word;
223
+ });
224
+ if (table) break;
225
+ }
226
+ return table;
227
+ }
228
+
229
+ CodeMirror.registerHelper("hint", "sql", function(editor, options) {
230
+ tables = parseTables(options && options.tables)
231
+ var defaultTableName = options && options.defaultTable;
232
+ var disableKeywords = options && options.disableKeywords;
233
+ defaultTable = defaultTableName && getTable(defaultTableName);
234
+ keywords = getKeywords(editor);
235
+
236
+ if (defaultTableName && !defaultTable)
237
+ defaultTable = findTableByAlias(defaultTableName, editor);
238
+
239
+ defaultTable = defaultTable || [];
240
+
241
+ if (defaultTable.columns)
242
+ defaultTable = defaultTable.columns;
243
+
244
+ var cur = editor.getCursor();
245
+ var result = [];
246
+ var token = editor.getTokenAt(cur), start, end, search;
247
+ if (token.end > cur.ch) {
248
+ token.end = cur.ch;
249
+ token.string = token.string.slice(0, cur.ch - token.start);
250
+ }
251
+
252
+ if (token.string.match(/^[.`\w@]\w*$/)) {
253
+ search = token.string;
254
+ start = token.start;
255
+ end = token.end;
256
+ } else {
257
+ start = end = cur.ch;
258
+ search = "";
259
+ }
260
+ if (search.charAt(0) == "." || search.charAt(0) == "`") {
261
+ start = nameCompletion(cur, token, result, editor);
262
+ } else {
263
+ addMatches(result, search, tables, function(w) {return w;});
264
+ addMatches(result, search, defaultTable, function(w) {return w;});
265
+ if (!disableKeywords)
266
+ addMatches(result, search, keywords, function(w) {return w.toUpperCase();});
267
+ }
268
+
269
+ return {list: result, from: Pos(cur.line, start), to: Pos(cur.line, end)};
270
+ });
271
+ });
js/codemirror/addon/hint/xml-hint.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var Pos = CodeMirror.Pos;
15
+
16
+ function getHints(cm, options) {
17
+ var tags = options && options.schemaInfo;
18
+ var quote = (options && options.quoteChar) || '"';
19
+ if (!tags) return;
20
+ var cur = cm.getCursor(), token = cm.getTokenAt(cur);
21
+ if (token.end > cur.ch) {
22
+ token.end = cur.ch;
23
+ token.string = token.string.slice(0, cur.ch - token.start);
24
+ }
25
+ var inner = CodeMirror.innerMode(cm.getMode(), token.state);
26
+ if (inner.mode.name != "xml") return;
27
+ var result = [], replaceToken = false, prefix;
28
+ var tag = /\btag\b/.test(token.type) && !/>$/.test(token.string);
29
+ var tagName = tag && /^\w/.test(token.string), tagStart;
30
+
31
+ if (tagName) {
32
+ var before = cm.getLine(cur.line).slice(Math.max(0, token.start - 2), token.start);
33
+ var tagType = /<\/$/.test(before) ? "close" : /<$/.test(before) ? "open" : null;
34
+ if (tagType) tagStart = token.start - (tagType == "close" ? 2 : 1);
35
+ } else if (tag && token.string == "<") {
36
+ tagType = "open";
37
+ } else if (tag && token.string == "</") {
38
+ tagType = "close";
39
+ }
40
+
41
+ if (!tag && !inner.state.tagName || tagType) {
42
+ if (tagName)
43
+ prefix = token.string;
44
+ replaceToken = tagType;
45
+ var cx = inner.state.context, curTag = cx && tags[cx.tagName];
46
+ var childList = cx ? curTag && curTag.children : tags["!top"];
47
+ if (childList && tagType != "close") {
48
+ for (var i = 0; i < childList.length; ++i) if (!prefix || childList[i].lastIndexOf(prefix, 0) == 0)
49
+ result.push("<" + childList[i]);
50
+ } else if (tagType != "close") {
51
+ for (var name in tags)
52
+ if (tags.hasOwnProperty(name) && name != "!top" && name != "!attrs" && (!prefix || name.lastIndexOf(prefix, 0) == 0))
53
+ result.push("<" + name);
54
+ }
55
+ if (cx && (!prefix || tagType == "close" && cx.tagName.lastIndexOf(prefix, 0) == 0))
56
+ result.push("</" + cx.tagName + ">");
57
+ } else {
58
+ // Attribute completion
59
+ var curTag = tags[inner.state.tagName], attrs = curTag && curTag.attrs;
60
+ var globalAttrs = tags["!attrs"];
61
+ if (!attrs && !globalAttrs) return;
62
+ if (!attrs) {
63
+ attrs = globalAttrs;
64
+ } else if (globalAttrs) { // Combine tag-local and global attributes
65
+ var set = {};
66
+ for (var nm in globalAttrs) if (globalAttrs.hasOwnProperty(nm)) set[nm] = globalAttrs[nm];
67
+ for (var nm in attrs) if (attrs.hasOwnProperty(nm)) set[nm] = attrs[nm];
68
+ attrs = set;
69
+ }
70
+ if (token.type == "string" || token.string == "=") { // A value
71
+ var before = cm.getRange(Pos(cur.line, Math.max(0, cur.ch - 60)),
72
+ Pos(cur.line, token.type == "string" ? token.start : token.end));
73
+ var atName = before.match(/([^\s\u00a0=<>\"\']+)=$/), atValues;
74
+ if (!atName || !attrs.hasOwnProperty(atName[1]) || !(atValues = attrs[atName[1]])) return;
75
+ if (typeof atValues == 'function') atValues = atValues.call(this, cm); // Functions can be used to supply values for autocomplete widget
76
+ if (token.type == "string") {
77
+ prefix = token.string;
78
+ var n = 0;
79
+ if (/['"]/.test(token.string.charAt(0))) {
80
+ quote = token.string.charAt(0);
81
+ prefix = token.string.slice(1);
82
+ n++;
83
+ }
84
+ var len = token.string.length;
85
+ if (/['"]/.test(token.string.charAt(len - 1))) {
86
+ quote = token.string.charAt(len - 1);
87
+ prefix = token.string.substr(n, len - 2);
88
+ }
89
+ replaceToken = true;
90
+ }
91
+ for (var i = 0; i < atValues.length; ++i) if (!prefix || atValues[i].lastIndexOf(prefix, 0) == 0)
92
+ result.push(quote + atValues[i] + quote);
93
+ } else { // An attribute name
94
+ if (token.type == "attribute") {
95
+ prefix = token.string;
96
+ replaceToken = true;
97
+ }
98
+ for (var attr in attrs) if (attrs.hasOwnProperty(attr) && (!prefix || attr.lastIndexOf(prefix, 0) == 0))
99
+ result.push(attr);
100
+ }
101
+ }
102
+ return {
103
+ list: result,
104
+ from: replaceToken ? Pos(cur.line, tagStart == null ? token.start : tagStart) : cur,
105
+ to: replaceToken ? Pos(cur.line, token.end) : cur
106
+ };
107
+ }
108
+
109
+ CodeMirror.registerHelper("hint", "xml", getHints);
110
+ });
js/codemirror/addon/selection/active-line.js ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+ var WRAP_CLASS = "CodeMirror-activeline";
14
+ var BACK_CLASS = "CodeMirror-activeline-background";
15
+ var GUTT_CLASS = "CodeMirror-activeline-gutter";
16
+
17
+ CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
18
+ var prev = old == CodeMirror.Init ? false : old;
19
+ if (val == prev) return
20
+ if (prev) {
21
+ cm.off("beforeSelectionChange", selectionChange);
22
+ clearActiveLines(cm);
23
+ delete cm.state.activeLines;
24
+ }
25
+ if (val) {
26
+ cm.state.activeLines = [];
27
+ updateActiveLines(cm, cm.listSelections());
28
+ cm.on("beforeSelectionChange", selectionChange);
29
+ }
30
+ });
31
+
32
+ function clearActiveLines(cm) {
33
+ for (var i = 0; i < cm.state.activeLines.length; i++) {
34
+ cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
35
+ cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
36
+ cm.removeLineClass(cm.state.activeLines[i], "gutter", GUTT_CLASS);
37
+ }
38
+ }
39
+
40
+ function sameArray(a, b) {
41
+ if (a.length != b.length) return false;
42
+ for (var i = 0; i < a.length; i++)
43
+ if (a[i] != b[i]) return false;
44
+ return true;
45
+ }
46
+
47
+ function updateActiveLines(cm, ranges) {
48
+ var active = [];
49
+ for (var i = 0; i < ranges.length; i++) {
50
+ var range = ranges[i];
51
+ var option = cm.getOption("styleActiveLine");
52
+ if (typeof option == "object" && option.nonEmpty ? range.anchor.line != range.head.line : !range.empty())
53
+ continue
54
+ var line = cm.getLineHandleVisualStart(range.head.line);
55
+ if (active[active.length - 1] != line) active.push(line);
56
+ }
57
+ if (sameArray(cm.state.activeLines, active)) return;
58
+ cm.operation(function() {
59
+ clearActiveLines(cm);
60
+ for (var i = 0; i < active.length; i++) {
61
+ cm.addLineClass(active[i], "wrap", WRAP_CLASS);
62
+ cm.addLineClass(active[i], "background", BACK_CLASS);
63
+ cm.addLineClass(active[i], "gutter", GUTT_CLASS);
64
+ }
65
+ cm.state.activeLines = active;
66
+ });
67
+ }
68
+
69
+ function selectionChange(cm, sel) {
70
+ updateActiveLines(cm, sel.ranges);
71
+ }
72
+ });
js/codemirror/addon/selection/mark-selection.js ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ // Because sometimes you need to mark the selected *text*.
5
+ //
6
+ // Adds an option 'styleSelectedText' which, when enabled, gives
7
+ // selected text the CSS class given as option value, or
8
+ // "CodeMirror-selectedtext" when the value is not a string.
9
+
10
+ (function(mod) {
11
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
12
+ mod(require("../../lib/codemirror"));
13
+ else if (typeof define == "function" && define.amd) // AMD
14
+ define(["../../lib/codemirror"], mod);
15
+ else // Plain browser env
16
+ mod(CodeMirror);
17
+ })(function(CodeMirror) {
18
+ "use strict";
19
+
20
+ CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) {
21
+ var prev = old && old != CodeMirror.Init;
22
+ if (val && !prev) {
23
+ cm.state.markedSelection = [];
24
+ cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext";
25
+ reset(cm);
26
+ cm.on("cursorActivity", onCursorActivity);
27
+ cm.on("change", onChange);
28
+ } else if (!val && prev) {
29
+ cm.off("cursorActivity", onCursorActivity);
30
+ cm.off("change", onChange);
31
+ clear(cm);
32
+ cm.state.markedSelection = cm.state.markedSelectionStyle = null;
33
+ }
34
+ });
35
+
36
+ function onCursorActivity(cm) {
37
+ cm.operation(function() { update(cm); });
38
+ }
39
+
40
+ function onChange(cm) {
41
+ if (cm.state.markedSelection.length)
42
+ cm.operation(function() { clear(cm); });
43
+ }
44
+
45
+ var CHUNK_SIZE = 8;
46
+ var Pos = CodeMirror.Pos;
47
+ var cmp = CodeMirror.cmpPos;
48
+
49
+ function coverRange(cm, from, to, addAt) {
50
+ if (cmp(from, to) == 0) return;
51
+ var array = cm.state.markedSelection;
52
+ var cls = cm.state.markedSelectionStyle;
53
+ for (var line = from.line;;) {
54
+ var start = line == from.line ? from : Pos(line, 0);
55
+ var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line;
56
+ var end = atEnd ? to : Pos(endLine, 0);
57
+ var mark = cm.markText(start, end, {className: cls});
58
+ if (addAt == null) array.push(mark);
59
+ else array.splice(addAt++, 0, mark);
60
+ if (atEnd) break;
61
+ line = endLine;
62
+ }
63
+ }
64
+
65
+ function clear(cm) {
66
+ var array = cm.state.markedSelection;
67
+ for (var i = 0; i < array.length; ++i) array[i].clear();
68
+ array.length = 0;
69
+ }
70
+
71
+ function reset(cm) {
72
+ clear(cm);
73
+ var ranges = cm.listSelections();
74
+ for (var i = 0; i < ranges.length; i++)
75
+ coverRange(cm, ranges[i].from(), ranges[i].to());
76
+ }
77
+
78
+ function update(cm) {
79
+ if (!cm.somethingSelected()) return clear(cm);
80
+ if (cm.listSelections().length > 1) return reset(cm);
81
+
82
+ var from = cm.getCursor("start"), to = cm.getCursor("end");
83
+
84
+ var array = cm.state.markedSelection;
85
+ if (!array.length) return coverRange(cm, from, to);
86
+
87
+ var coverStart = array[0].find(), coverEnd = array[array.length - 1].find();
88
+ if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE ||
89
+ cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0)
90
+ return reset(cm);
91
+
92
+ while (cmp(from, coverStart.from) > 0) {
93
+ array.shift().clear();
94
+ coverStart = array[0].find();
95
+ }
96
+ if (cmp(from, coverStart.from) < 0) {
97
+ if (coverStart.to.line - from.line < CHUNK_SIZE) {
98
+ array.shift().clear();
99
+ coverRange(cm, from, coverStart.to, 0);
100
+ } else {
101
+ coverRange(cm, from, coverStart.from, 0);
102
+ }
103
+ }
104
+
105
+ while (cmp(to, coverEnd.to) < 0) {
106
+ array.pop().clear();
107
+ coverEnd = array[array.length - 1].find();
108
+ }
109
+ if (cmp(to, coverEnd.to) > 0) {
110
+ if (to.line - coverEnd.from.line < CHUNK_SIZE) {
111
+ array.pop().clear();
112
+ coverRange(cm, coverEnd.from, to);
113
+ } else {
114
+ coverRange(cm, coverEnd.to, to);
115
+ }
116
+ }
117
+ }
118
+ });
js/codemirror/addon/selection/selection-pointer.js ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ CodeMirror.defineOption("selectionPointer", false, function(cm, val) {
15
+ var data = cm.state.selectionPointer;
16
+ if (data) {
17
+ CodeMirror.off(cm.getWrapperElement(), "mousemove", data.mousemove);
18
+ CodeMirror.off(cm.getWrapperElement(), "mouseout", data.mouseout);
19
+ CodeMirror.off(window, "scroll", data.windowScroll);
20
+ cm.off("cursorActivity", reset);
21
+ cm.off("scroll", reset);
22
+ cm.state.selectionPointer = null;
23
+ cm.display.lineDiv.style.cursor = "";
24
+ }
25
+ if (val) {
26
+ data = cm.state.selectionPointer = {
27
+ value: typeof val == "string" ? val : "default",
28
+ mousemove: function(event) { mousemove(cm, event); },
29
+ mouseout: function(event) { mouseout(cm, event); },
30
+ windowScroll: function() { reset(cm); },
31
+ rects: null,
32
+ mouseX: null, mouseY: null,
33
+ willUpdate: false
34
+ };
35
+ CodeMirror.on(cm.getWrapperElement(), "mousemove", data.mousemove);
36
+ CodeMirror.on(cm.getWrapperElement(), "mouseout", data.mouseout);
37
+ CodeMirror.on(window, "scroll", data.windowScroll);
38
+ cm.on("cursorActivity", reset);
39
+ cm.on("scroll", reset);
40
+ }
41
+ });
42
+
43
+ function mousemove(cm, event) {
44
+ var data = cm.state.selectionPointer;
45
+ if (event.buttons == null ? event.which : event.buttons) {
46
+ data.mouseX = data.mouseY = null;
47
+ } else {
48
+ data.mouseX = event.clientX;
49
+ data.mouseY = event.clientY;
50
+ }
51
+ scheduleUpdate(cm);
52
+ }
53
+
54
+ function mouseout(cm, event) {
55
+ if (!cm.getWrapperElement().contains(event.relatedTarget)) {
56
+ var data = cm.state.selectionPointer;
57
+ data.mouseX = data.mouseY = null;
58
+ scheduleUpdate(cm);
59
+ }
60
+ }
61
+
62
+ function reset(cm) {
63
+ cm.state.selectionPointer.rects = null;
64
+ scheduleUpdate(cm);
65
+ }
66
+
67
+ function scheduleUpdate(cm) {
68
+ if (!cm.state.selectionPointer.willUpdate) {
69
+ cm.state.selectionPointer.willUpdate = true;
70
+ setTimeout(function() {
71
+ update(cm);
72
+ cm.state.selectionPointer.willUpdate = false;
73
+ }, 50);
74
+ }
75
+ }
76
+
77
+ function update(cm) {
78
+ var data = cm.state.selectionPointer;
79
+ if (!data) return;
80
+ if (data.rects == null && data.mouseX != null) {
81
+ data.rects = [];
82
+ if (cm.somethingSelected()) {
83
+ for (var sel = cm.display.selectionDiv.firstChild; sel; sel = sel.nextSibling)
84
+ data.rects.push(sel.getBoundingClientRect());
85
+ }
86
+ }
87
+ var inside = false;
88
+ if (data.mouseX != null) for (var i = 0; i < data.rects.length; i++) {
89
+ var rect = data.rects[i];
90
+ if (rect.left <= data.mouseX && rect.right >= data.mouseX &&
91
+ rect.top <= data.mouseY && rect.bottom >= data.mouseY)
92
+ inside = true;
93
+ }
94
+ var cursor = inside ? data.value : "";
95
+ if (cm.display.lineDiv.style.cursor != cursor)
96
+ cm.display.lineDiv.style.cursor = cursor;
97
+ }
98
+ });
js/codemirror/codemirror.css ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* BASICS */
2
+
3
+ .CodeMirror {
4
+ /* Set height, width, borders, and global font properties here */
5
+ font-family: monospace;
6
+ height: 300px;
7
+ color: black;
8
+ }
9
+
10
+ /* PADDING */
11
+
12
+ .CodeMirror-lines {
13
+ padding: 4px 0; /* Vertical padding around content */
14
+ }
15
+ .CodeMirror pre {
16
+ padding: 0 4px; /* Horizontal padding of content */
17
+ }
18
+
19
+ .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
20
+ background-color: white; /* The little square between H and V scrollbars */
21
+ }
22
+
23
+ /* GUTTER */
24
+
25
+ .CodeMirror-gutters {
26
+ border-right: 1px solid #ddd;
27
+ background-color: #f7f7f7;
28
+ white-space: nowrap;
29
+ }
30
+ .CodeMirror-linenumbers {}
31
+ .CodeMirror-linenumber {
32
+ padding: 0 3px 0 5px;
33
+ min-width: 20px;
34
+ text-align: right;
35
+ color: #999;
36
+ white-space: nowrap;
37
+ }
38
+
39
+ .CodeMirror-guttermarker { color: black; }
40
+ .CodeMirror-guttermarker-subtle { color: #999; }
41
+
42
+ /* CURSOR */
43
+
44
+ .CodeMirror-cursor {
45
+ border-left: 1px solid black;
46
+ border-right: none;
47
+ width: 0;
48
+ }
49
+ /* Shown when moving in bi-directional text */
50
+ .CodeMirror div.CodeMirror-secondarycursor {
51
+ border-left: 1px solid silver;
52
+ }
53
+ .cm-fat-cursor .CodeMirror-cursor {
54
+ width: auto;
55
+ border: 0 !important;
56
+ background: #7e7;
57
+ }
58
+ .cm-fat-cursor div.CodeMirror-cursors {
59
+ z-index: 1;
60
+ }
61
+
62
+ .cm-animate-fat-cursor {
63
+ width: auto;
64
+ border: 0;
65
+ -webkit-animation: blink 1.06s steps(1) infinite;
66
+ -moz-animation: blink 1.06s steps(1) infinite;
67
+ animation: blink 1.06s steps(1) infinite;
68
+ background-color: #7e7;
69
+ }
70
+ @-moz-keyframes blink {
71
+ 0% {}
72
+ 50% { background-color: transparent; }
73
+ 100% {}
74
+ }
75
+ @-webkit-keyframes blink {
76
+ 0% {}
77
+ 50% { background-color: transparent; }
78
+ 100% {}
79
+ }
80
+ @keyframes blink {
81
+ 0% {}
82
+ 50% { background-color: transparent; }
83
+ 100% {}
84
+ }
85
+
86
+ /* Can style cursor different in overwrite (non-insert) mode */
87
+ .CodeMirror-overwrite .CodeMirror-cursor {}
88
+
89
+ .cm-tab { display: inline-block; text-decoration: inherit; }
90
+
91
+ .CodeMirror-rulers {
92
+ position: absolute;
93
+ left: 0; right: 0; top: -50px; bottom: -20px;
94
+ overflow: hidden;
95
+ }
96
+ .CodeMirror-ruler {
97
+ border-left: 1px solid #ccc;
98
+ top: 0; bottom: 0;
99
+ position: absolute;
100
+ }
101
+
102
+ /* DEFAULT THEME */
103
+
104
+ .cm-s-default .cm-header {color: blue;}
105
+ .cm-s-default .cm-quote {color: #090;}
106
+ .cm-negative {color: #d44;}
107
+ .cm-positive {color: #292;}
108
+ .cm-header, .cm-strong {font-weight: bold;}
109
+ .cm-em {font-style: italic;}
110
+ .cm-link {text-decoration: underline;}
111
+ .cm-strikethrough {text-decoration: line-through;}
112
+
113
+ .cm-s-default .cm-keyword {color: #708;}
114
+ .cm-s-default .cm-atom {color: #219;}
115
+ .cm-s-default .cm-number {color: #164;}
116
+ .cm-s-default .cm-def {color: #00f;}
117
+ .cm-s-default .cm-variable,
118
+ .cm-s-default .cm-punctuation,
119
+ .cm-s-default .cm-property,
120
+ .cm-s-default .cm-operator {}
121
+ .cm-s-default .cm-variable-2 {color: #05a;}
122
+ .cm-s-default .cm-variable-3 {color: #085;}
123
+ .cm-s-default .cm-comment {color: #a50;}
124
+ .cm-s-default .cm-string {color: #a11;}
125
+ .cm-s-default .cm-string-2 {color: #f50;}
126
+ .cm-s-default .cm-meta {color: #555;}
127
+ .cm-s-default .cm-qualifier {color: #555;}
128
+ .cm-s-default .cm-builtin {color: #30a;}
129
+ .cm-s-default .cm-bracket {color: #997;}
130
+ .cm-s-default .cm-tag {color: #170;}
131
+ .cm-s-default .cm-attribute {color: #00c;}
132
+ .cm-s-default .cm-hr {color: #999;}
133
+ .cm-s-default .cm-link {color: #00c;}
134
+
135
+ .cm-s-default .cm-error {color: #f00;}
136
+ .cm-invalidchar {color: #f00;}
137
+
138
+ .CodeMirror-composing { border-bottom: 2px solid; }
139
+
140
+ /* Default styles for common addons */
141
+
142
+ div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
143
+ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
144
+ .CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
145
+ .CodeMirror-activeline-background {background: #e8f2ff;}
146
+
147
+ /* STOP */
148
+
149
+ /* The rest of this file contains styles related to the mechanics of
150
+ the editor. You probably shouldn't touch them. */
151
+
152
+ .CodeMirror {
153
+ position: relative;
154
+ overflow: hidden;
155
+ background: white;
156
+ }
157
+
158
+ .CodeMirror-scroll {
159
+ overflow: scroll !important; /* Things will break if this is overridden */
160
+ /* 30px is the magic margin used to hide the element's real scrollbars */
161
+ /* See overflow: hidden in .CodeMirror */
162
+ margin-bottom: -30px; margin-right: -30px;
163
+ padding-bottom: 30px;
164
+ height: 100%;
165
+ outline: none; /* Prevent dragging from highlighting the element */
166
+ position: relative;
167
+ }
168
+ .CodeMirror-sizer {
169
+ position: relative;
170
+ border-right: 30px solid transparent;
171
+ }
172
+
173
+ /* The fake, visible scrollbars. Used to force redraw during scrolling
174
+ before actual scrolling happens, thus preventing shaking and
175
+ flickering artifacts. */
176
+ .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
177
+ position: absolute;
178
+ z-index: 6;
179
+ display: none;
180
+ }
181
+ .CodeMirror-vscrollbar {
182
+ right: 0; top: 0;
183
+ overflow-x: hidden;
184
+ overflow-y: scroll;
185
+ }
186
+ .CodeMirror-hscrollbar {
187
+ bottom: 0; left: 0;
188
+ overflow-y: hidden;
189
+ overflow-x: scroll;
190
+ }
191
+ .CodeMirror-scrollbar-filler {
192
+ right: 0; bottom: 0;
193
+ }
194
+ .CodeMirror-gutter-filler {
195
+ left: 0; bottom: 0;
196
+ }
197
+
198
+ .CodeMirror-gutters {
199
+ position: absolute; left: 0; top: 0;
200
+ min-height: 100%;
201
+ z-index: 3;
202
+ }
203
+ .CodeMirror-gutter {
204
+ white-space: normal;
205
+ height: 100%;
206
+ display: inline-block;
207
+ vertical-align: top;
208
+ margin-bottom: -30px;
209
+ }
210
+ .CodeMirror-gutter-wrapper {
211
+ position: absolute;
212
+ z-index: 4;
213
+ background: none !important;
214
+ border: none !important;
215
+ }
216
+ .CodeMirror-gutter-background {
217
+ position: absolute;
218
+ top: 0; bottom: 0;
219
+ z-index: 4;
220
+ }
221
+ .CodeMirror-gutter-elt {
222
+ position: absolute;
223
+ cursor: default;
224
+ z-index: 4;
225
+ }
226
+ .CodeMirror-gutter-wrapper {
227
+ -webkit-user-select: none;
228
+ -moz-user-select: none;
229
+ user-select: none;
230
+ }
231
+
232
+ .CodeMirror-lines {
233
+ cursor: text;
234
+ min-height: 1px; /* prevents collapsing before first draw */
235
+ }
236
+ .CodeMirror pre {
237
+ /* Reset some styles that the rest of the page might have set */
238
+ -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
239
+ border-width: 0;
240
+ background: transparent;
241
+ font-family: inherit;
242
+ font-size: inherit;
243
+ margin: 0;
244
+ white-space: pre;
245
+ word-wrap: normal;
246
+ line-height: inherit;
247
+ color: inherit;
248
+ z-index: 2;
249
+ position: relative;
250
+ overflow: visible;
251
+ -webkit-tap-highlight-color: transparent;
252
+ -webkit-font-variant-ligatures: contextual;
253
+ font-variant-ligatures: contextual;
254
+ }
255
+ .CodeMirror-wrap pre {
256
+ word-wrap: break-word;
257
+ white-space: pre-wrap;
258
+ word-break: normal;
259
+ }
260
+
261
+ .CodeMirror-linebackground {
262
+ position: absolute;
263
+ left: 0; right: 0; top: 0; bottom: 0;
264
+ z-index: 0;
265
+ }
266
+
267
+ .CodeMirror-linewidget {
268
+ position: relative;
269
+ z-index: 2;
270
+ overflow: auto;
271
+ }
272
+
273
+ .CodeMirror-widget {}
274
+
275
+ .CodeMirror-code {
276
+ outline: none;
277
+ }
278
+
279
+ /* Force content-box sizing for the elements where we expect it */
280
+ .CodeMirror-scroll,
281
+ .CodeMirror-sizer,
282
+ .CodeMirror-gutter,
283
+ .CodeMirror-gutters,
284
+ .CodeMirror-linenumber {
285
+ -moz-box-sizing: content-box;
286
+ box-sizing: content-box;
287
+ }
288
+
289
+ .CodeMirror-measure {
290
+ position: absolute;
291
+ width: 100%;
292
+ height: 0;
293
+ overflow: hidden;
294
+ visibility: hidden;
295
+ }
296
+
297
+ .CodeMirror-cursor {
298
+ position: absolute;
299
+ pointer-events: none;
300
+ }
301
+ .CodeMirror-measure pre { position: static; }
302
+
303
+ div.CodeMirror-cursors {
304
+ visibility: hidden;
305
+ position: relative;
306
+ z-index: 3;
307
+ }
308
+ div.CodeMirror-dragcursors {
309
+ visibility: visible;
310
+ }
311
+
312
+ .CodeMirror-focused div.CodeMirror-cursors {
313
+ visibility: visible;
314
+ }
315
+
316
+ .CodeMirror-selected { background: #d9d9d9; }
317
+ .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
318
+ .CodeMirror-crosshair { cursor: crosshair; }
319
+ .CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
320
+ .CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
321
+
322
+ .cm-searching {
323
+ background: #ffa;
324
+ background: rgba(255, 255, 0, .4);
325
+ }
326
+
327
+ /* Used to force a border model for a node */
328
+ .cm-force-border { padding-right: .1px; }
329
+
330
+ @media print {
331
+ /* Hide the cursor when printing */
332
+ .CodeMirror div.CodeMirror-cursors {
333
+ visibility: hidden;
334
+ }
335
+ }
336
+
337
+ /* See issue #2901 */
338
+ .cm-tab-wrap-hack:after { content: ''; }
339
+
340
+ /* Help users use markselection to safely style text background */
341
+ span.CodeMirror-selectedtext { background: none; }
js/codemirror/codemirror.js ADDED
@@ -0,0 +1,9113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ // This is CodeMirror (http://codemirror.net), a code editor
5
+ // implemented in JavaScript on top of the browser's DOM.
6
+ //
7
+ // You can find some technical background for some of the code below
8
+ // at http://marijnhaverbeke.nl/blog/#cm-internals .
9
+
10
+ (function (global, factory) {
11
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
12
+ typeof define === 'function' && define.amd ? define(factory) :
13
+ (global.CodeMirror = factory());
14
+ }(this, (function () { 'use strict';
15
+
16
+ // Kludges for bugs and behavior differences that can't be feature
17
+ // detected are enabled based on userAgent etc sniffing.
18
+ var userAgent = navigator.userAgent
19
+ var platform = navigator.platform
20
+
21
+ var gecko = /gecko\/\d/i.test(userAgent)
22
+ var ie_upto10 = /MSIE \d/.test(userAgent)
23
+ var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent)
24
+ var ie = ie_upto10 || ie_11up
25
+ var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1])
26
+ var webkit = /WebKit\//.test(userAgent)
27
+ var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent)
28
+ var chrome = /Chrome\//.test(userAgent)
29
+ var presto = /Opera\//.test(userAgent)
30
+ var safari = /Apple Computer/.test(navigator.vendor)
31
+ var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent)
32
+ var phantom = /PhantomJS/.test(userAgent)
33
+
34
+ var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent)
35
+ // This is woefully incomplete. Suggestions for alternative methods welcome.
36
+ var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent)
37
+ var mac = ios || /Mac/.test(platform)
38
+ var chromeOS = /\bCrOS\b/.test(userAgent)
39
+ var windows = /win/i.test(platform)
40
+
41
+ var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/)
42
+ if (presto_version) { presto_version = Number(presto_version[1]) }
43
+ if (presto_version && presto_version >= 15) { presto = false; webkit = true }
44
+ // Some browsers use the wrong event properties to signal cmd/ctrl on OS X
45
+ var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11))
46
+ var captureRightClick = gecko || (ie && ie_version >= 9)
47
+
48
+ function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") }
49
+
50
+ var rmClass = function(node, cls) {
51
+ var current = node.className
52
+ var match = classTest(cls).exec(current)
53
+ if (match) {
54
+ var after = current.slice(match.index + match[0].length)
55
+ node.className = current.slice(0, match.index) + (after ? match[1] + after : "")
56
+ }
57
+ }
58
+
59
+ function removeChildren(e) {
60
+ for (var count = e.childNodes.length; count > 0; --count)
61
+ { e.removeChild(e.firstChild) }
62
+ return e
63
+ }
64
+
65
+ function removeChildrenAndAdd(parent, e) {
66
+ return removeChildren(parent).appendChild(e)
67
+ }
68
+
69
+ function elt(tag, content, className, style) {
70
+ var e = document.createElement(tag)
71
+ if (className) { e.className = className }
72
+ if (style) { e.style.cssText = style }
73
+ if (typeof content == "string") { e.appendChild(document.createTextNode(content)) }
74
+ else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]) } }
75
+ return e
76
+ }
77
+
78
+ var range
79
+ if (document.createRange) { range = function(node, start, end, endNode) {
80
+ var r = document.createRange()
81
+ r.setEnd(endNode || node, end)
82
+ r.setStart(node, start)
83
+ return r
84
+ } }
85
+ else { range = function(node, start, end) {
86
+ var r = document.body.createTextRange()
87
+ try { r.moveToElementText(node.parentNode) }
88
+ catch(e) { return r }
89
+ r.collapse(true)
90
+ r.moveEnd("character", end)
91
+ r.moveStart("character", start)
92
+ return r
93
+ } }
94
+
95
+ function contains(parent, child) {
96
+ if (child.nodeType == 3) // Android browser always returns false when child is a textnode
97
+ { child = child.parentNode }
98
+ if (parent.contains)
99
+ { return parent.contains(child) }
100
+ do {
101
+ if (child.nodeType == 11) { child = child.host }
102
+ if (child == parent) { return true }
103
+ } while (child = child.parentNode)
104
+ }
105
+
106
+ function activeElt() {
107
+ // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement.
108
+ // IE < 10 will throw when accessed while the page is loading or in an iframe.
109
+ // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable.
110
+ var activeElement
111
+ try {
112
+ activeElement = document.activeElement
113
+ } catch(e) {
114
+ activeElement = document.body || null
115
+ }
116
+ while (activeElement && activeElement.root && activeElement.root.activeElement)
117
+ { activeElement = activeElement.root.activeElement }
118
+ return activeElement
119
+ }
120
+
121
+ function addClass(node, cls) {
122
+ var current = node.className
123
+ if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls }
124
+ }
125
+ function joinClasses(a, b) {
126
+ var as = a.split(" ")
127
+ for (var i = 0; i < as.length; i++)
128
+ { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i] } }
129
+ return b
130
+ }
131
+
132
+ var selectInput = function(node) { node.select() }
133
+ if (ios) // Mobile Safari apparently has a bug where select() is broken.
134
+ { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length } }
135
+ else if (ie) // Suppress mysterious IE10 errors
136
+ { selectInput = function(node) { try { node.select() } catch(_e) {} } }
137
+
138
+ function bind(f) {
139
+ var args = Array.prototype.slice.call(arguments, 1)
140
+ return function(){return f.apply(null, args)}
141
+ }
142
+
143
+ function copyObj(obj, target, overwrite) {
144
+ if (!target) { target = {} }
145
+ for (var prop in obj)
146
+ { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop)))
147
+ { target[prop] = obj[prop] } }
148
+ return target
149
+ }
150
+
151
+ // Counts the column offset in a string, taking tabs into account.
152
+ // Used mostly to find indentation.
153
+ function countColumn(string, end, tabSize, startIndex, startValue) {
154
+ if (end == null) {
155
+ end = string.search(/[^\s\u00a0]/)
156
+ if (end == -1) { end = string.length }
157
+ }
158
+ for (var i = startIndex || 0, n = startValue || 0;;) {
159
+ var nextTab = string.indexOf("\t", i)
160
+ if (nextTab < 0 || nextTab >= end)
161
+ { return n + (end - i) }
162
+ n += nextTab - i
163
+ n += tabSize - (n % tabSize)
164
+ i = nextTab + 1
165
+ }
166
+ }
167
+
168
+ function Delayed() {this.id = null}
169
+ Delayed.prototype.set = function(ms, f) {
170
+ clearTimeout(this.id)
171
+ this.id = setTimeout(f, ms)
172
+ }
173
+
174
+ function indexOf(array, elt) {
175
+ for (var i = 0; i < array.length; ++i)
176
+ { if (array[i] == elt) { return i } }
177
+ return -1
178
+ }
179
+
180
+ // Number of pixels added to scroller and sizer to hide scrollbar
181
+ var scrollerGap = 30
182
+
183
+ // Returned or thrown by various protocols to signal 'I'm not
184
+ // handling this'.
185
+ var Pass = {toString: function(){return "CodeMirror.Pass"}}
186
+
187
+ // Reused option objects for setSelection & friends
188
+ var sel_dontScroll = {scroll: false};
189
+ var sel_mouse = {origin: "*mouse"};
190
+ var sel_move = {origin: "+move"};
191
+ // The inverse of countColumn -- find the offset that corresponds to
192
+ // a particular column.
193
+ function findColumn(string, goal, tabSize) {
194
+ for (var pos = 0, col = 0;;) {
195
+ var nextTab = string.indexOf("\t", pos)
196
+ if (nextTab == -1) { nextTab = string.length }
197
+ var skipped = nextTab - pos
198
+ if (nextTab == string.length || col + skipped >= goal)
199
+ { return pos + Math.min(skipped, goal - col) }
200
+ col += nextTab - pos
201
+ col += tabSize - (col % tabSize)
202
+ pos = nextTab + 1
203
+ if (col >= goal) { return pos }
204
+ }
205
+ }
206
+
207
+ var spaceStrs = [""]
208
+ function spaceStr(n) {
209
+ while (spaceStrs.length <= n)
210
+ { spaceStrs.push(lst(spaceStrs) + " ") }
211
+ return spaceStrs[n]
212
+ }
213
+
214
+ function lst(arr) { return arr[arr.length-1] }
215
+
216
+ function map(array, f) {
217
+ var out = []
218
+ for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i) }
219
+ return out
220
+ }
221
+
222
+ function insertSorted(array, value, score) {
223
+ var pos = 0, priority = score(value)
224
+ while (pos < array.length && score(array[pos]) <= priority) { pos++ }
225
+ array.splice(pos, 0, value)
226
+ }
227
+
228
+ function nothing() {}
229
+
230
+ function createObj(base, props) {
231
+ var inst
232
+ if (Object.create) {
233
+ inst = Object.create(base)
234
+ } else {
235
+ nothing.prototype = base
236
+ inst = new nothing()
237
+ }
238
+ if (props) { copyObj(props, inst) }
239
+ return inst
240
+ }
241
+
242
+ var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/
243
+ function isWordCharBasic(ch) {
244
+ return /\w/.test(ch) || ch > "\x80" &&
245
+ (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch))
246
+ }
247
+ function isWordChar(ch, helper) {
248
+ if (!helper) { return isWordCharBasic(ch) }
249
+ if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true }
250
+ return helper.test(ch)
251
+ }
252
+
253
+ function isEmpty(obj) {
254
+ for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } }
255
+ return true
256
+ }
257
+
258
+ // Extending unicode characters. A series of a non-extending char +
259
+ // any number of extending chars is treated as a single unit as far
260
+ // as editing and measuring is concerned. This is not fully correct,
261
+ // since some scripts/fonts/browsers also treat other configurations
262
+ // of code points as a group.
263
+ var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/
264
+ function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) }
265
+
266
+ // The display handles the DOM integration, both for input reading
267
+ // and content drawing. It holds references to DOM nodes and
268
+ // display-related state.
269
+
270
+ function Display(place, doc, input) {
271
+ var d = this
272
+ this.input = input
273
+
274
+ // Covers bottom-right square when both scrollbars are present.
275
+ d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler")
276
+ d.scrollbarFiller.setAttribute("cm-not-content", "true")
277
+ // Covers bottom of gutter when coverGutterNextToScrollbar is on
278
+ // and h scrollbar is present.
279
+ d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler")
280
+ d.gutterFiller.setAttribute("cm-not-content", "true")
281
+ // Will contain the actual code, positioned to cover the viewport.
282
+ d.lineDiv = elt("div", null, "CodeMirror-code")
283
+ // Elements are added to these to represent selection and cursors.
284
+ d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1")
285
+ d.cursorDiv = elt("div", null, "CodeMirror-cursors")
286
+ // A visibility: hidden element used to find the size of things.
287
+ d.measure = elt("div", null, "CodeMirror-measure")
288
+ // When lines outside of the viewport are measured, they are drawn in this.
289
+ d.lineMeasure = elt("div", null, "CodeMirror-measure")
290
+ // Wraps everything that needs to exist inside the vertically-padded coordinate system
291
+ d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv],
292
+ null, "position: relative; outline: none")
293
+ // Moved around its parent to cover visible view.
294
+ d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative")
295
+ // Set to the height of the document, allowing scrolling.
296
+ d.sizer = elt("div", [d.mover], "CodeMirror-sizer")
297
+ d.sizerWidth = null
298
+ // Behavior of elts with overflow: auto and padding is
299
+ // inconsistent across browsers. This is used to ensure the
300
+ // scrollable area is big enough.
301
+ d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;")
302
+ // Will contain the gutters, if any.
303
+ d.gutters = elt("div", null, "CodeMirror-gutters")
304
+ d.lineGutter = null
305
+ // Actual scrollable element.
306
+ d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll")
307
+ d.scroller.setAttribute("tabIndex", "-1")
308
+ // The element in which the editor lives.
309
+ d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror")
310
+
311
+ // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported)
312
+ if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0 }
313
+ if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true }
314
+
315
+ if (place) {
316
+ if (place.appendChild) { place.appendChild(d.wrapper) }
317
+ else { place(d.wrapper) }
318
+ }
319
+
320
+ // Current rendered range (may be bigger than the view window).
321
+ d.viewFrom = d.viewTo = doc.first
322
+ d.reportedViewFrom = d.reportedViewTo = doc.first
323
+ // Information about the rendered lines.
324
+ d.view = []
325
+ d.renderedView = null
326
+ // Holds info about a single rendered line when it was rendered
327
+ // for measurement, while not in view.
328
+ d.externalMeasured = null
329
+ // Empty space (in pixels) above the view
330
+ d.viewOffset = 0
331
+ d.lastWrapHeight = d.lastWrapWidth = 0
332
+ d.updateLineNumbers = null
333
+
334
+ d.nativeBarWidth = d.barHeight = d.barWidth = 0
335
+ d.scrollbarsClipped = false
336
+
337
+ // Used to only resize the line number gutter when necessary (when
338
+ // the amount of lines crosses a boundary that makes its width change)
339
+ d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null
340
+ // Set to true when a non-horizontal-scrolling line widget is
341
+ // added. As an optimization, line widget aligning is skipped when
342
+ // this is false.
343
+ d.alignWidgets = false
344
+
345
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null
346
+
347
+ // Tracks the maximum line length so that the horizontal scrollbar
348
+ // can be kept static when scrolling.
349
+ d.maxLine = null
350
+ d.maxLineLength = 0
351
+ d.maxLineChanged = false
352
+
353
+ // Used for measuring wheel scrolling granularity
354
+ d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null
355
+
356
+ // True when shift is held down.
357
+ d.shift = false
358
+
359
+ // Used to track whether anything happened since the context menu
360
+ // was opened.
361
+ d.selForContextMenu = null
362
+
363
+ d.activeTouch = null
364
+
365
+ input.init(d)
366
+ }
367
+
368
+ // Find the line object corresponding to the given line number.
369
+ function getLine(doc, n) {
370
+ n -= doc.first
371
+ if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") }
372
+ var chunk = doc
373
+ while (!chunk.lines) {
374
+ for (var i = 0;; ++i) {
375
+ var child = chunk.children[i], sz = child.chunkSize()
376
+ if (n < sz) { chunk = child; break }
377
+ n -= sz
378
+ }
379
+ }
380
+ return chunk.lines[n]
381
+ }
382
+
383
+ // Get the part of a document between two positions, as an array of
384
+ // strings.
385
+ function getBetween(doc, start, end) {
386
+ var out = [], n = start.line
387
+ doc.iter(start.line, end.line + 1, function (line) {
388
+ var text = line.text
389
+ if (n == end.line) { text = text.slice(0, end.ch) }
390
+ if (n == start.line) { text = text.slice(start.ch) }
391
+ out.push(text)
392
+ ++n
393
+ })
394
+ return out
395
+ }
396
+ // Get the lines between from and to, as array of strings.
397
+ function getLines(doc, from, to) {
398
+ var out = []
399
+ doc.iter(from, to, function (line) { out.push(line.text) }) // iter aborts when callback returns truthy value
400
+ return out
401
+ }
402
+
403
+ // Update the height of a line, propagating the height change
404
+ // upwards to parent nodes.
405
+ function updateLineHeight(line, height) {
406
+ var diff = height - line.height
407
+ if (diff) { for (var n = line; n; n = n.parent) { n.height += diff } }
408
+ }
409
+
410
+ // Given a line object, find its line number by walking up through
411
+ // its parent links.
412
+ function lineNo(line) {
413
+ if (line.parent == null) { return null }
414
+ var cur = line.parent, no = indexOf(cur.lines, line)
415
+ for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) {
416
+ for (var i = 0;; ++i) {
417
+ if (chunk.children[i] == cur) { break }
418
+ no += chunk.children[i].chunkSize()
419
+ }
420
+ }
421
+ return no + cur.first
422
+ }
423
+
424
+ // Find the line at the given vertical position, using the height
425
+ // information in the document tree.
426
+ function lineAtHeight(chunk, h) {
427
+ var n = chunk.first
428
+ outer: do {
429
+ for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) {
430
+ var child = chunk.children[i$1], ch = child.height
431
+ if (h < ch) { chunk = child; continue outer }
432
+ h -= ch
433
+ n += child.chunkSize()
434
+ }
435
+ return n
436
+ } while (!chunk.lines)
437
+ var i = 0
438
+ for (; i < chunk.lines.length; ++i) {
439
+ var line = chunk.lines[i], lh = line.height
440
+ if (h < lh) { break }
441
+ h -= lh
442
+ }
443
+ return n + i
444
+ }
445
+
446
+ function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size}
447
+
448
+ function lineNumberFor(options, i) {
449
+ return String(options.lineNumberFormatter(i + options.firstLineNumber))
450
+ }
451
+
452
+ // A Pos instance represents a position within the text.
453
+ function Pos (line, ch) {
454
+ if (!(this instanceof Pos)) { return new Pos(line, ch) }
455
+ this.line = line; this.ch = ch
456
+ }
457
+
458
+ // Compare two positions, return 0 if they are the same, a negative
459
+ // number when a is less, and a positive number otherwise.
460
+ function cmp(a, b) { return a.line - b.line || a.ch - b.ch }
461
+
462
+ function copyPos(x) {return Pos(x.line, x.ch)}
463
+ function maxPos(a, b) { return cmp(a, b) < 0 ? b : a }
464
+ function minPos(a, b) { return cmp(a, b) < 0 ? a : b }
465
+
466
+ // Most of the external API clips given positions to make sure they
467
+ // actually exist within the document.
468
+ function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))}
469
+ function clipPos(doc, pos) {
470
+ if (pos.line < doc.first) { return Pos(doc.first, 0) }
471
+ var last = doc.first + doc.size - 1
472
+ if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) }
473
+ return clipToLen(pos, getLine(doc, pos.line).text.length)
474
+ }
475
+ function clipToLen(pos, linelen) {
476
+ var ch = pos.ch
477
+ if (ch == null || ch > linelen) { return Pos(pos.line, linelen) }
478
+ else if (ch < 0) { return Pos(pos.line, 0) }
479
+ else { return pos }
480
+ }
481
+ function clipPosArray(doc, array) {
482
+ var out = []
483
+ for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]) }
484
+ return out
485
+ }
486
+
487
+ // Optimize some code when these features are not used.
488
+ var sawReadOnlySpans = false;
489
+ var sawCollapsedSpans = false;
490
+ function seeReadOnlySpans() {
491
+ sawReadOnlySpans = true
492
+ }
493
+
494
+ function seeCollapsedSpans() {
495
+ sawCollapsedSpans = true
496
+ }
497
+
498
+ // TEXTMARKER SPANS
499
+
500
+ function MarkedSpan(marker, from, to) {
501
+ this.marker = marker
502
+ this.from = from; this.to = to
503
+ }
504
+
505
+ // Search an array of spans for a span matching the given marker.
506
+ function getMarkedSpanFor(spans, marker) {
507
+ if (spans) { for (var i = 0; i < spans.length; ++i) {
508
+ var span = spans[i]
509
+ if (span.marker == marker) { return span }
510
+ } }
511
+ }
512
+ // Remove a span from an array, returning undefined if no spans are
513
+ // left (we don't store arrays for lines without spans).
514
+ function removeMarkedSpan(spans, span) {
515
+ var r
516
+ for (var i = 0; i < spans.length; ++i)
517
+ { if (spans[i] != span) { (r || (r = [])).push(spans[i]) } }
518
+ return r
519
+ }
520
+ // Add a span to a line.
521
+ function addMarkedSpan(line, span) {
522
+ line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]
523
+ span.marker.attachLine(line)
524
+ }
525
+
526
+ // Used for the algorithm that adjusts markers for a change in the
527
+ // document. These functions cut an array of spans at a given
528
+ // character position, returning an array of remaining chunks (or
529
+ // undefined if nothing remains).
530
+ function markedSpansBefore(old, startCh, isInsert) {
531
+ var nw
532
+ if (old) { for (var i = 0; i < old.length; ++i) {
533
+ var span = old[i], marker = span.marker
534
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh)
535
+ if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) {
536
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh)
537
+ ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to))
538
+ }
539
+ } }
540
+ return nw
541
+ }
542
+ function markedSpansAfter(old, endCh, isInsert) {
543
+ var nw
544
+ if (old) { for (var i = 0; i < old.length; ++i) {
545
+ var span = old[i], marker = span.marker
546
+ var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh)
547
+ if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) {
548
+ var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh)
549
+ ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh,
550
+ span.to == null ? null : span.to - endCh))
551
+ }
552
+ } }
553
+ return nw
554
+ }
555
+
556
+ // Given a change object, compute the new set of marker spans that
557
+ // cover the line in which the change took place. Removes spans
558
+ // entirely within the change, reconnects spans belonging to the
559
+ // same marker that appear on both sides of the change, and cuts off
560
+ // spans partially within the change. Returns an array of span
561
+ // arrays with one element for each line in (after) the change.
562
+ function stretchSpansOverChange(doc, change) {
563
+ if (change.full) { return null }
564
+ var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans
565
+ var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans
566
+ if (!oldFirst && !oldLast) { return null }
567
+
568
+ var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0
569
+ // Get the spans that 'stick out' on both sides
570
+ var first = markedSpansBefore(oldFirst, startCh, isInsert)
571
+ var last = markedSpansAfter(oldLast, endCh, isInsert)
572
+
573
+ // Next, merge those two ends
574
+ var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0)
575
+ if (first) {
576
+ // Fix up .to properties of first
577
+ for (var i = 0; i < first.length; ++i) {
578
+ var span = first[i]
579
+ if (span.to == null) {
580
+ var found = getMarkedSpanFor(last, span.marker)
581
+ if (!found) { span.to = startCh }
582
+ else if (sameLine) { span.to = found.to == null ? null : found.to + offset }
583
+ }
584
+ }
585
+ }
586
+ if (last) {
587
+ // Fix up .from in last (or move them into first in case of sameLine)
588
+ for (var i$1 = 0; i$1 < last.length; ++i$1) {
589
+ var span$1 = last[i$1]
590
+ if (span$1.to != null) { span$1.to += offset }
591
+ if (span$1.from == null) {
592
+ var found$1 = getMarkedSpanFor(first, span$1.marker)
593
+ if (!found$1) {
594
+ span$1.from = offset
595
+ if (sameLine) { (first || (first = [])).push(span$1) }
596
+ }
597
+ } else {
598
+ span$1.from += offset
599
+ if (sameLine) { (first || (first = [])).push(span$1) }
600
+ }
601
+ }
602
+ }
603
+ // Make sure we didn't create any zero-length spans
604
+ if (first) { first = clearEmptySpans(first) }
605
+ if (last && last != first) { last = clearEmptySpans(last) }
606
+
607
+ var newMarkers = [first]
608
+ if (!sameLine) {
609
+ // Fill gap with whole-line-spans
610
+ var gap = change.text.length - 2, gapMarkers
611
+ if (gap > 0 && first)
612
+ { for (var i$2 = 0; i$2 < first.length; ++i$2)
613
+ { if (first[i$2].to == null)
614
+ { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)) } } }
615
+ for (var i$3 = 0; i$3 < gap; ++i$3)
616
+ { newMarkers.push(gapMarkers) }
617
+ newMarkers.push(last)
618
+ }
619
+ return newMarkers
620
+ }
621
+
622
+ // Remove spans that are empty and don't have a clearWhenEmpty
623
+ // option of false.
624
+ function clearEmptySpans(spans) {
625
+ for (var i = 0; i < spans.length; ++i) {
626
+ var span = spans[i]
627
+ if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false)
628
+ { spans.splice(i--, 1) }
629
+ }
630
+ if (!spans.length) { return null }
631
+ return spans
632
+ }
633
+
634
+ // Used to 'clip' out readOnly ranges when making a change.
635
+ function removeReadOnlyRanges(doc, from, to) {
636
+ var markers = null
637
+ doc.iter(from.line, to.line + 1, function (line) {
638
+ if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
639
+ var mark = line.markedSpans[i].marker
640
+ if (mark.readOnly && (!markers || indexOf(markers, mark) == -1))
641
+ { (markers || (markers = [])).push(mark) }
642
+ } }
643
+ })
644
+ if (!markers) { return null }
645
+ var parts = [{from: from, to: to}]
646
+ for (var i = 0; i < markers.length; ++i) {
647
+ var mk = markers[i], m = mk.find(0)
648
+ for (var j = 0; j < parts.length; ++j) {
649
+ var p = parts[j]
650
+ if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue }
651
+ var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to)
652
+ if (dfrom < 0 || !mk.inclusiveLeft && !dfrom)
653
+ { newParts.push({from: p.from, to: m.from}) }
654
+ if (dto > 0 || !mk.inclusiveRight && !dto)
655
+ { newParts.push({from: m.to, to: p.to}) }
656
+ parts.splice.apply(parts, newParts)
657
+ j += newParts.length - 1
658
+ }
659
+ }
660
+ return parts
661
+ }
662
+
663
+ // Connect or disconnect spans from a line.
664
+ function detachMarkedSpans(line) {
665
+ var spans = line.markedSpans
666
+ if (!spans) { return }
667
+ for (var i = 0; i < spans.length; ++i)
668
+ { spans[i].marker.detachLine(line) }
669
+ line.markedSpans = null
670
+ }
671
+ function attachMarkedSpans(line, spans) {
672
+ if (!spans) { return }
673
+ for (var i = 0; i < spans.length; ++i)
674
+ { spans[i].marker.attachLine(line) }
675
+ line.markedSpans = spans
676
+ }
677
+
678
+ // Helpers used when computing which overlapping collapsed span
679
+ // counts as the larger one.
680
+ function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 }
681
+ function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 }
682
+
683
+ // Returns a number indicating which of two overlapping collapsed
684
+ // spans is larger (and thus includes the other). Falls back to
685
+ // comparing ids when the spans cover exactly the same range.
686
+ function compareCollapsedMarkers(a, b) {
687
+ var lenDiff = a.lines.length - b.lines.length
688
+ if (lenDiff != 0) { return lenDiff }
689
+ var aPos = a.find(), bPos = b.find()
690
+ var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b)
691
+ if (fromCmp) { return -fromCmp }
692
+ var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b)
693
+ if (toCmp) { return toCmp }
694
+ return b.id - a.id
695
+ }
696
+
697
+ // Find out whether a line ends or starts in a collapsed span. If
698
+ // so, return the marker for that span.
699
+ function collapsedSpanAtSide(line, start) {
700
+ var sps = sawCollapsedSpans && line.markedSpans, found
701
+ if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
702
+ sp = sps[i]
703
+ if (sp.marker.collapsed && (start ? sp.from : sp.to) == null &&
704
+ (!found || compareCollapsedMarkers(found, sp.marker) < 0))
705
+ { found = sp.marker }
706
+ } }
707
+ return found
708
+ }
709
+ function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) }
710
+ function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) }
711
+
712
+ // Test whether there exists a collapsed span that partially
713
+ // overlaps (covers the start or end, but not both) of a new span.
714
+ // Such overlap is not allowed.
715
+ function conflictingCollapsedRange(doc, lineNo, from, to, marker) {
716
+ var line = getLine(doc, lineNo)
717
+ var sps = sawCollapsedSpans && line.markedSpans
718
+ if (sps) { for (var i = 0; i < sps.length; ++i) {
719
+ var sp = sps[i]
720
+ if (!sp.marker.collapsed) { continue }
721
+ var found = sp.marker.find(0)
722
+ var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker)
723
+ var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker)
724
+ if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue }
725
+ if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) ||
726
+ fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0))
727
+ { return true }
728
+ } }
729
+ }
730
+
731
+ // A visual line is a line as drawn on the screen. Folding, for
732
+ // example, can cause multiple logical lines to appear on the same
733
+ // visual line. This finds the start of the visual line that the
734
+ // given line is part of (usually that is the line itself).
735
+ function visualLine(line) {
736
+ var merged
737
+ while (merged = collapsedSpanAtStart(line))
738
+ { line = merged.find(-1, true).line }
739
+ return line
740
+ }
741
+
742
+ // Returns an array of logical lines that continue the visual line
743
+ // started by the argument, or undefined if there are no such lines.
744
+ function visualLineContinued(line) {
745
+ var merged, lines
746
+ while (merged = collapsedSpanAtEnd(line)) {
747
+ line = merged.find(1, true).line
748
+ ;(lines || (lines = [])).push(line)
749
+ }
750
+ return lines
751
+ }
752
+
753
+ // Get the line number of the start of the visual line that the
754
+ // given line number is part of.
755
+ function visualLineNo(doc, lineN) {
756
+ var line = getLine(doc, lineN), vis = visualLine(line)
757
+ if (line == vis) { return lineN }
758
+ return lineNo(vis)
759
+ }
760
+
761
+ // Get the line number of the start of the next visual line after
762
+ // the given line.
763
+ function visualLineEndNo(doc, lineN) {
764
+ if (lineN > doc.lastLine()) { return lineN }
765
+ var line = getLine(doc, lineN), merged
766
+ if (!lineIsHidden(doc, line)) { return lineN }
767
+ while (merged = collapsedSpanAtEnd(line))
768
+ { line = merged.find(1, true).line }
769
+ return lineNo(line) + 1
770
+ }
771
+
772
+ // Compute whether a line is hidden. Lines count as hidden when they
773
+ // are part of a visual line that starts with another line, or when
774
+ // they are entirely covered by collapsed, non-widget span.
775
+ function lineIsHidden(doc, line) {
776
+ var sps = sawCollapsedSpans && line.markedSpans
777
+ if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) {
778
+ sp = sps[i]
779
+ if (!sp.marker.collapsed) { continue }
780
+ if (sp.from == null) { return true }
781
+ if (sp.marker.widgetNode) { continue }
782
+ if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp))
783
+ { return true }
784
+ } }
785
+ }
786
+ function lineIsHiddenInner(doc, line, span) {
787
+ if (span.to == null) {
788
+ var end = span.marker.find(1, true)
789
+ return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker))
790
+ }
791
+ if (span.marker.inclusiveRight && span.to == line.text.length)
792
+ { return true }
793
+ for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) {
794
+ sp = line.markedSpans[i]
795
+ if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to &&
796
+ (sp.to == null || sp.to != span.from) &&
797
+ (sp.marker.inclusiveLeft || span.marker.inclusiveRight) &&
798
+ lineIsHiddenInner(doc, line, sp)) { return true }
799
+ }
800
+ }
801
+
802
+ // Find the height above the given line.
803
+ function heightAtLine(lineObj) {
804
+ lineObj = visualLine(lineObj)
805
+
806
+ var h = 0, chunk = lineObj.parent
807
+ for (var i = 0; i < chunk.lines.length; ++i) {
808
+ var line = chunk.lines[i]
809
+ if (line == lineObj) { break }
810
+ else { h += line.height }
811
+ }
812
+ for (var p = chunk.parent; p; chunk = p, p = chunk.parent) {
813
+ for (var i$1 = 0; i$1 < p.children.length; ++i$1) {
814
+ var cur = p.children[i$1]
815
+ if (cur == chunk) { break }
816
+ else { h += cur.height }
817
+ }
818
+ }
819
+ return h
820
+ }
821
+
822
+ // Compute the character length of a line, taking into account
823
+ // collapsed ranges (see markText) that might hide parts, and join
824
+ // other lines onto it.
825
+ function lineLength(line) {
826
+ if (line.height == 0) { return 0 }
827
+ var len = line.text.length, merged, cur = line
828
+ while (merged = collapsedSpanAtStart(cur)) {
829
+ var found = merged.find(0, true)
830
+ cur = found.from.line
831
+ len += found.from.ch - found.to.ch
832
+ }
833
+ cur = line
834
+ while (merged = collapsedSpanAtEnd(cur)) {
835
+ var found$1 = merged.find(0, true)
836
+ len -= cur.text.length - found$1.from.ch
837
+ cur = found$1.to.line
838
+ len += cur.text.length - found$1.to.ch
839
+ }
840
+ return len
841
+ }
842
+
843
+ // Find the longest line in the document.
844
+ function findMaxLine(cm) {
845
+ var d = cm.display, doc = cm.doc
846
+ d.maxLine = getLine(doc, doc.first)
847
+ d.maxLineLength = lineLength(d.maxLine)
848
+ d.maxLineChanged = true
849
+ doc.iter(function (line) {
850
+ var len = lineLength(line)
851
+ if (len > d.maxLineLength) {
852
+ d.maxLineLength = len
853
+ d.maxLine = line
854
+ }
855
+ })
856
+ }
857
+
858
+ // BIDI HELPERS
859
+
860
+ function iterateBidiSections(order, from, to, f) {
861
+ if (!order) { return f(from, to, "ltr") }
862
+ var found = false
863
+ for (var i = 0; i < order.length; ++i) {
864
+ var part = order[i]
865
+ if (part.from < to && part.to > from || from == to && part.to == from) {
866
+ f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr")
867
+ found = true
868
+ }
869
+ }
870
+ if (!found) { f(from, to, "ltr") }
871
+ }
872
+
873
+ function bidiLeft(part) { return part.level % 2 ? part.to : part.from }
874
+ function bidiRight(part) { return part.level % 2 ? part.from : part.to }
875
+
876
+ function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0 }
877
+ function lineRight(line) {
878
+ var order = getOrder(line)
879
+ if (!order) { return line.text.length }
880
+ return bidiRight(lst(order))
881
+ }
882
+
883
+ function compareBidiLevel(order, a, b) {
884
+ var linedir = order[0].level
885
+ if (a == linedir) { return true }
886
+ if (b == linedir) { return false }
887
+ return a < b
888
+ }
889
+
890
+ var bidiOther = null
891
+ function getBidiPartAt(order, pos) {
892
+ var found
893
+ bidiOther = null
894
+ for (var i = 0; i < order.length; ++i) {
895
+ var cur = order[i]
896
+ if (cur.from < pos && cur.to > pos) { return i }
897
+ if ((cur.from == pos || cur.to == pos)) {
898
+ if (found == null) {
899
+ found = i
900
+ } else if (compareBidiLevel(order, cur.level, order[found].level)) {
901
+ if (cur.from != cur.to) { bidiOther = found }
902
+ return i
903
+ } else {
904
+ if (cur.from != cur.to) { bidiOther = i }
905
+ return found
906
+ }
907
+ }
908
+ }
909
+ return found
910
+ }
911
+
912
+ function moveInLine(line, pos, dir, byUnit) {
913
+ if (!byUnit) { return pos + dir }
914
+ do { pos += dir }
915
+ while (pos > 0 && isExtendingChar(line.text.charAt(pos)))
916
+ return pos
917
+ }
918
+
919
+ // This is needed in order to move 'visually' through bi-directional
920
+ // text -- i.e., pressing left should make the cursor go left, even
921
+ // when in RTL text. The tricky part is the 'jumps', where RTL and
922
+ // LTR text touch each other. This often requires the cursor offset
923
+ // to move more than one unit, in order to visually move one unit.
924
+ function moveVisually(line, start, dir, byUnit) {
925
+ var bidi = getOrder(line)
926
+ if (!bidi) { return moveLogically(line, start, dir, byUnit) }
927
+ var pos = getBidiPartAt(bidi, start), part = bidi[pos]
928
+ var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit)
929
+
930
+ for (;;) {
931
+ if (target > part.from && target < part.to) { return target }
932
+ if (target == part.from || target == part.to) {
933
+ if (getBidiPartAt(bidi, target) == pos) { return target }
934
+ part = bidi[pos += dir]
935
+ return (dir > 0) == part.level % 2 ? part.to : part.from
936
+ } else {
937
+ part = bidi[pos += dir]
938
+ if (!part) { return null }
939
+ if ((dir > 0) == part.level % 2)
940
+ { target = moveInLine(line, part.to, -1, byUnit) }
941
+ else
942
+ { target = moveInLine(line, part.from, 1, byUnit) }
943
+ }
944
+ }
945
+ }
946
+
947
+ function moveLogically(line, start, dir, byUnit) {
948
+ var target = start + dir
949
+ if (byUnit) { while (target > 0 && isExtendingChar(line.text.charAt(target))) { target += dir } }
950
+ return target < 0 || target > line.text.length ? null : target
951
+ }
952
+
953
+ // Bidirectional ordering algorithm
954
+ // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
955
+ // that this (partially) implements.
956
+
957
+ // One-char codes used for character types:
958
+ // L (L): Left-to-Right
959
+ // R (R): Right-to-Left
960
+ // r (AL): Right-to-Left Arabic
961
+ // 1 (EN): European Number
962
+ // + (ES): European Number Separator
963
+ // % (ET): European Number Terminator
964
+ // n (AN): Arabic Number
965
+ // , (CS): Common Number Separator
966
+ // m (NSM): Non-Spacing Mark
967
+ // b (BN): Boundary Neutral
968
+ // s (B): Paragraph Separator
969
+ // t (S): Segment Separator
970
+ // w (WS): Whitespace
971
+ // N (ON): Other Neutrals
972
+
973
+ // Returns null if characters are ordered as they appear
974
+ // (left-to-right), or an array of sections ({from, to, level}
975
+ // objects) in the order in which they occur visually.
976
+ var bidiOrdering = (function() {
977
+ // Character types for codepoints 0 to 0xff
978
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"
979
+ // Character types for codepoints 0x600 to 0x6f9
980
+ var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"
981
+ function charType(code) {
982
+ if (code <= 0xf7) { return lowTypes.charAt(code) }
983
+ else if (0x590 <= code && code <= 0x5f4) { return "R" }
984
+ else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) }
985
+ else if (0x6ee <= code && code <= 0x8ac) { return "r" }
986
+ else if (0x2000 <= code && code <= 0x200b) { return "w" }
987
+ else if (code == 0x200c) { return "b" }
988
+ else { return "L" }
989
+ }
990
+
991
+ var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/
992
+ var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/
993
+ // Browsers seem to always treat the boundaries of block elements as being L.
994
+ var outerType = "L"
995
+
996
+ function BidiSpan(level, from, to) {
997
+ this.level = level
998
+ this.from = from; this.to = to
999
+ }
1000
+
1001
+ return function(str) {
1002
+ if (!bidiRE.test(str)) { return false }
1003
+ var len = str.length, types = []
1004
+ for (var i = 0; i < len; ++i)
1005
+ { types.push(charType(str.charCodeAt(i))) }
1006
+
1007
+ // W1. Examine each non-spacing mark (NSM) in the level run, and
1008
+ // change the type of the NSM to the type of the previous
1009
+ // character. If the NSM is at the start of the level run, it will
1010
+ // get the type of sor.
1011
+ for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) {
1012
+ var type = types[i$1]
1013
+ if (type == "m") { types[i$1] = prev }
1014
+ else { prev = type }
1015
+ }
1016
+
1017
+ // W2. Search backwards from each instance of a European number
1018
+ // until the first strong type (R, L, AL, or sor) is found. If an
1019
+ // AL is found, change the type of the European number to Arabic
1020
+ // number.
1021
+ // W3. Change all ALs to R.
1022
+ for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) {
1023
+ var type$1 = types[i$2]
1024
+ if (type$1 == "1" && cur == "r") { types[i$2] = "n" }
1025
+ else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R" } }
1026
+ }
1027
+
1028
+ // W4. A single European separator between two European numbers
1029
+ // changes to a European number. A single common separator between
1030
+ // two numbers of the same type changes to that type.
1031
+ for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) {
1032
+ var type$2 = types[i$3]
1033
+ if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1" }
1034
+ else if (type$2 == "," && prev$1 == types[i$3+1] &&
1035
+ (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1 }
1036
+ prev$1 = type$2
1037
+ }
1038
+
1039
+ // W5. A sequence of European terminators adjacent to European
1040
+ // numbers changes to all European numbers.
1041
+ // W6. Otherwise, separators and terminators change to Other
1042
+ // Neutral.
1043
+ for (var i$4 = 0; i$4 < len; ++i$4) {
1044
+ var type$3 = types[i$4]
1045
+ if (type$3 == ",") { types[i$4] = "N" }
1046
+ else if (type$3 == "%") {
1047
+ var end = (void 0)
1048
+ for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {}
1049
+ var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"
1050
+ for (var j = i$4; j < end; ++j) { types[j] = replace }
1051
+ i$4 = end - 1
1052
+ }
1053
+ }
1054
+
1055
+ // W7. Search backwards from each instance of a European number
1056
+ // until the first strong type (R, L, or sor) is found. If an L is
1057
+ // found, then change the type of the European number to L.
1058
+ for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) {
1059
+ var type$4 = types[i$5]
1060
+ if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L" }
1061
+ else if (isStrong.test(type$4)) { cur$1 = type$4 }
1062
+ }
1063
+
1064
+ // N1. A sequence of neutrals takes the direction of the
1065
+ // surrounding strong text if the text on both sides has the same
1066
+ // direction. European and Arabic numbers act as if they were R in
1067
+ // terms of their influence on neutrals. Start-of-level-run (sor)
1068
+ // and end-of-level-run (eor) are used at level run boundaries.
1069
+ // N2. Any remaining neutrals take the embedding direction.
1070
+ for (var i$6 = 0; i$6 < len; ++i$6) {
1071
+ if (isNeutral.test(types[i$6])) {
1072
+ var end$1 = (void 0)
1073
+ for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {}
1074
+ var before = (i$6 ? types[i$6-1] : outerType) == "L"
1075
+ var after = (end$1 < len ? types[end$1] : outerType) == "L"
1076
+ var replace$1 = before || after ? "L" : "R"
1077
+ for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1 }
1078
+ i$6 = end$1 - 1
1079
+ }
1080
+ }
1081
+
1082
+ // Here we depart from the documented algorithm, in order to avoid
1083
+ // building up an actual levels array. Since there are only three
1084
+ // levels (0, 1, 2) in an implementation that doesn't take
1085
+ // explicit embedding into account, we can build up the order on
1086
+ // the fly, without following the level-based algorithm.
1087
+ var order = [], m
1088
+ for (var i$7 = 0; i$7 < len;) {
1089
+ if (countsAsLeft.test(types[i$7])) {
1090
+ var start = i$7
1091
+ for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {}
1092
+ order.push(new BidiSpan(0, start, i$7))
1093
+ } else {
1094
+ var pos = i$7, at = order.length
1095
+ for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {}
1096
+ for (var j$2 = pos; j$2 < i$7;) {
1097
+ if (countsAsNum.test(types[j$2])) {
1098
+ if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)) }
1099
+ var nstart = j$2
1100
+ for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {}
1101
+ order.splice(at, 0, new BidiSpan(2, nstart, j$2))
1102
+ pos = j$2
1103
+ } else { ++j$2 }
1104
+ }
1105
+ if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)) }
1106
+ }
1107
+ }
1108
+ if (order[0].level == 1 && (m = str.match(/^\s+/))) {
1109
+ order[0].from = m[0].length
1110
+ order.unshift(new BidiSpan(0, 0, m[0].length))
1111
+ }
1112
+ if (lst(order).level == 1 && (m = str.match(/\s+$/))) {
1113
+ lst(order).to -= m[0].length
1114
+ order.push(new BidiSpan(0, len - m[0].length, len))
1115
+ }
1116
+ if (order[0].level == 2)
1117
+ { order.unshift(new BidiSpan(1, order[0].to, order[0].to)) }
1118
+ if (order[0].level != lst(order).level)
1119
+ { order.push(new BidiSpan(order[0].level, len, len)) }
1120
+
1121
+ return order
1122
+ }
1123
+ })()
1124
+
1125
+ // Get the bidi ordering for the given line (and cache it). Returns
1126
+ // false for lines that are fully left-to-right, and an array of
1127
+ // BidiSpan objects otherwise.
1128
+ function getOrder(line) {
1129
+ var order = line.order
1130
+ if (order == null) { order = line.order = bidiOrdering(line.text) }
1131
+ return order
1132
+ }
1133
+
1134
+ // EVENT HANDLING
1135
+
1136
+ // Lightweight event framework. on/off also work on DOM nodes,
1137
+ // registering native DOM handlers.
1138
+
1139
+ var noHandlers = []
1140
+
1141
+ var on = function(emitter, type, f) {
1142
+ if (emitter.addEventListener) {
1143
+ emitter.addEventListener(type, f, false)
1144
+ } else if (emitter.attachEvent) {
1145
+ emitter.attachEvent("on" + type, f)
1146
+ } else {
1147
+ var map = emitter._handlers || (emitter._handlers = {})
1148
+ map[type] = (map[type] || noHandlers).concat(f)
1149
+ }
1150
+ }
1151
+
1152
+ function getHandlers(emitter, type) {
1153
+ return emitter._handlers && emitter._handlers[type] || noHandlers
1154
+ }
1155
+
1156
+ function off(emitter, type, f) {
1157
+ if (emitter.removeEventListener) {
1158
+ emitter.removeEventListener(type, f, false)
1159
+ } else if (emitter.detachEvent) {
1160
+ emitter.detachEvent("on" + type, f)
1161
+ } else {
1162
+ var map = emitter._handlers, arr = map && map[type]
1163
+ if (arr) {
1164
+ var index = indexOf(arr, f)
1165
+ if (index > -1)
1166
+ { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)) }
1167
+ }
1168
+ }
1169
+ }
1170
+
1171
+ function signal(emitter, type /*, values...*/) {
1172
+ var handlers = getHandlers(emitter, type)
1173
+ if (!handlers.length) { return }
1174
+ var args = Array.prototype.slice.call(arguments, 2)
1175
+ for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args) }
1176
+ }
1177
+
1178
+ // The DOM events that CodeMirror handles can be overridden by
1179
+ // registering a (non-DOM) handler on the editor for the event name,
1180
+ // and preventDefault-ing the event in that handler.
1181
+ function signalDOMEvent(cm, e, override) {
1182
+ if (typeof e == "string")
1183
+ { e = {type: e, preventDefault: function() { this.defaultPrevented = true }} }
1184
+ signal(cm, override || e.type, cm, e)
1185
+ return e_defaultPrevented(e) || e.codemirrorIgnore
1186
+ }
1187
+
1188
+ function signalCursorActivity(cm) {
1189
+ var arr = cm._handlers && cm._handlers.cursorActivity
1190
+ if (!arr) { return }
1191
+ var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = [])
1192
+ for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1)
1193
+ { set.push(arr[i]) } }
1194
+ }
1195
+
1196
+ function hasHandler(emitter, type) {
1197
+ return getHandlers(emitter, type).length > 0
1198
+ }
1199
+
1200
+ // Add on and off methods to a constructor's prototype, to make
1201
+ // registering events on such objects more convenient.
1202
+ function eventMixin(ctor) {
1203
+ ctor.prototype.on = function(type, f) {on(this, type, f)}
1204
+ ctor.prototype.off = function(type, f) {off(this, type, f)}
1205
+ }
1206
+
1207
+ // Due to the fact that we still support jurassic IE versions, some
1208
+ // compatibility wrappers are needed.
1209
+
1210
+ function e_preventDefault(e) {
1211
+ if (e.preventDefault) { e.preventDefault() }
1212
+ else { e.returnValue = false }
1213
+ }
1214
+ function e_stopPropagation(e) {
1215
+ if (e.stopPropagation) { e.stopPropagation() }
1216
+ else { e.cancelBubble = true }
1217
+ }
1218
+ function e_defaultPrevented(e) {
1219
+ return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false
1220
+ }
1221
+ function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)}
1222
+
1223
+ function e_target(e) {return e.target || e.srcElement}
1224
+ function e_button(e) {
1225
+ var b = e.which
1226
+ if (b == null) {
1227
+ if (e.button & 1) { b = 1 }
1228
+ else if (e.button & 2) { b = 3 }
1229
+ else if (e.button & 4) { b = 2 }
1230
+ }
1231
+ if (mac && e.ctrlKey && b == 1) { b = 3 }
1232
+ return b
1233
+ }
1234
+
1235
+ // Detect drag-and-drop
1236
+ var dragAndDrop = function() {
1237
+ // There is *some* kind of drag-and-drop support in IE6-8, but I
1238
+ // couldn't get it to work yet.
1239
+ if (ie && ie_version < 9) { return false }
1240
+ var div = elt('div')
1241
+ return "draggable" in div || "dragDrop" in div
1242
+ }()
1243
+
1244
+ var zwspSupported
1245
+ function zeroWidthElement(measure) {
1246
+ if (zwspSupported == null) {
1247
+ var test = elt("span", "\u200b")
1248
+ removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")]))
1249
+ if (measure.firstChild.offsetHeight != 0)
1250
+ { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8) }
1251
+ }
1252
+ var node = zwspSupported ? elt("span", "\u200b") :
1253
+ elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px")
1254
+ node.setAttribute("cm-text", "")
1255
+ return node
1256
+ }
1257
+
1258
+ // Feature-detect IE's crummy client rect reporting for bidi text
1259
+ var badBidiRects
1260
+ function hasBadBidiRects(measure) {
1261
+ if (badBidiRects != null) { return badBidiRects }
1262
+ var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA"))
1263
+ var r0 = range(txt, 0, 1).getBoundingClientRect()
1264
+ var r1 = range(txt, 1, 2).getBoundingClientRect()
1265
+ removeChildren(measure)
1266
+ if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780)
1267
+ return badBidiRects = (r1.right - r0.right < 3)
1268
+ }
1269
+
1270
+ // See if "".split is the broken IE version, if so, provide an
1271
+ // alternative way to split lines.
1272
+ var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) {
1273
+ var pos = 0, result = [], l = string.length
1274
+ while (pos <= l) {
1275
+ var nl = string.indexOf("\n", pos)
1276
+ if (nl == -1) { nl = string.length }
1277
+ var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl)
1278
+ var rt = line.indexOf("\r")
1279
+ if (rt != -1) {
1280
+ result.push(line.slice(0, rt))
1281
+ pos += rt + 1
1282
+ } else {
1283
+ result.push(line)
1284
+ pos = nl + 1
1285
+ }
1286
+ }
1287
+ return result
1288
+ } : function (string) { return string.split(/\r\n?|\n/); }
1289
+
1290
+ var hasSelection = window.getSelection ? function (te) {
1291
+ try { return te.selectionStart != te.selectionEnd }
1292
+ catch(e) { return false }
1293
+ } : function (te) {
1294
+ var range
1295
+ try {range = te.ownerDocument.selection.createRange()}
1296
+ catch(e) {}
1297
+ if (!range || range.parentElement() != te) { return false }
1298
+ return range.compareEndPoints("StartToEnd", range) != 0
1299
+ }
1300
+
1301
+ var hasCopyEvent = (function () {
1302
+ var e = elt("div")
1303
+ if ("oncopy" in e) { return true }
1304
+ e.setAttribute("oncopy", "return;")
1305
+ return typeof e.oncopy == "function"
1306
+ })()
1307
+
1308
+ var badZoomedRects = null
1309
+ function hasBadZoomedRects(measure) {
1310
+ if (badZoomedRects != null) { return badZoomedRects }
1311
+ var node = removeChildrenAndAdd(measure, elt("span", "x"))
1312
+ var normal = node.getBoundingClientRect()
1313
+ var fromRange = range(node, 0, 1).getBoundingClientRect()
1314
+ return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1
1315
+ }
1316
+
1317
+ var modes = {};
1318
+ var mimeModes = {};
1319
+ // Extra arguments are stored as the mode's dependencies, which is
1320
+ // used by (legacy) mechanisms like loadmode.js to automatically
1321
+ // load a mode. (Preferred mechanism is the require/define calls.)
1322
+ function defineMode(name, mode) {
1323
+ if (arguments.length > 2)
1324
+ { mode.dependencies = Array.prototype.slice.call(arguments, 2) }
1325
+ modes[name] = mode
1326
+ }
1327
+
1328
+ function defineMIME(mime, spec) {
1329
+ mimeModes[mime] = spec
1330
+ }
1331
+
1332
+ // Given a MIME type, a {name, ...options} config object, or a name
1333
+ // string, return a mode config object.
1334
+ function resolveMode(spec) {
1335
+ if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) {
1336
+ spec = mimeModes[spec]
1337
+ } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) {
1338
+ var found = mimeModes[spec.name]
1339
+ if (typeof found == "string") { found = {name: found} }
1340
+ spec = createObj(found, spec)
1341
+ spec.name = found.name
1342
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) {
1343
+ return resolveMode("application/xml")
1344
+ } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) {
1345
+ return resolveMode("application/json")
1346
+ }
1347
+ if (typeof spec == "string") { return {name: spec} }
1348
+ else { return spec || {name: "null"} }
1349
+ }
1350
+
1351
+ // Given a mode spec (anything that resolveMode accepts), find and
1352
+ // initialize an actual mode object.
1353
+ function getMode(options, spec) {
1354
+ spec = resolveMode(spec)
1355
+ var mfactory = modes[spec.name]
1356
+ if (!mfactory) { return getMode(options, "text/plain") }
1357
+ var modeObj = mfactory(options, spec)
1358
+ if (modeExtensions.hasOwnProperty(spec.name)) {
1359
+ var exts = modeExtensions[spec.name]
1360
+ for (var prop in exts) {
1361
+ if (!exts.hasOwnProperty(prop)) { continue }
1362
+ if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop] }
1363
+ modeObj[prop] = exts[prop]
1364
+ }
1365
+ }
1366
+ modeObj.name = spec.name
1367
+ if (spec.helperType) { modeObj.helperType = spec.helperType }
1368
+ if (spec.modeProps) { for (var prop$1 in spec.modeProps)
1369
+ { modeObj[prop$1] = spec.modeProps[prop$1] } }
1370
+
1371
+ return modeObj
1372
+ }
1373
+
1374
+ // This can be used to attach properties to mode objects from
1375
+ // outside the actual mode definition.
1376
+ var modeExtensions = {}
1377
+ function extendMode(mode, properties) {
1378
+ var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {})
1379
+ copyObj(properties, exts)
1380
+ }
1381
+
1382
+ function copyState(mode, state) {
1383
+ if (state === true) { return state }
1384
+ if (mode.copyState) { return mode.copyState(state) }
1385
+ var nstate = {}
1386
+ for (var n in state) {
1387
+ var val = state[n]
1388
+ if (val instanceof Array) { val = val.concat([]) }
1389
+ nstate[n] = val
1390
+ }
1391
+ return nstate
1392
+ }
1393
+
1394
+ // Given a mode and a state (for that mode), find the inner mode and
1395
+ // state at the position that the state refers to.
1396
+ function innerMode(mode, state) {
1397
+ var info
1398
+ while (mode.innerMode) {
1399
+ info = mode.innerMode(state)
1400
+ if (!info || info.mode == mode) { break }
1401
+ state = info.state
1402
+ mode = info.mode
1403
+ }
1404
+ return info || {mode: mode, state: state}
1405
+ }
1406
+
1407
+ function startState(mode, a1, a2) {
1408
+ return mode.startState ? mode.startState(a1, a2) : true
1409
+ }
1410
+
1411
+ // STRING STREAM
1412
+
1413
+ // Fed to the mode parsers, provides helper functions to make
1414
+ // parsers more succinct.
1415
+
1416
+ var StringStream = function(string, tabSize) {
1417
+ this.pos = this.start = 0
1418
+ this.string = string
1419
+ this.tabSize = tabSize || 8
1420
+ this.lastColumnPos = this.lastColumnValue = 0
1421
+ this.lineStart = 0
1422
+ }
1423
+
1424
+ StringStream.prototype = {
1425
+ eol: function() {return this.pos >= this.string.length},
1426
+ sol: function() {return this.pos == this.lineStart},
1427
+ peek: function() {return this.string.charAt(this.pos) || undefined},
1428
+ next: function() {
1429
+ if (this.pos < this.string.length)
1430
+ { return this.string.charAt(this.pos++) }
1431
+ },
1432
+ eat: function(match) {
1433
+ var ch = this.string.charAt(this.pos)
1434
+ var ok
1435
+ if (typeof match == "string") { ok = ch == match }
1436
+ else { ok = ch && (match.test ? match.test(ch) : match(ch)) }
1437
+ if (ok) {++this.pos; return ch}
1438
+ },
1439
+ eatWhile: function(match) {
1440
+ var start = this.pos
1441
+ while (this.eat(match)){}
1442
+ return this.pos > start
1443
+ },
1444
+ eatSpace: function() {
1445
+ var this$1 = this;
1446
+
1447
+ var start = this.pos
1448
+ while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos }
1449
+ return this.pos > start
1450
+ },
1451
+ skipToEnd: function() {this.pos = this.string.length},
1452
+ skipTo: function(ch) {
1453
+ var found = this.string.indexOf(ch, this.pos)
1454
+ if (found > -1) {this.pos = found; return true}
1455
+ },
1456
+ backUp: function(n) {this.pos -= n},
1457
+ column: function() {
1458
+ if (this.lastColumnPos < this.start) {
1459
+ this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue)
1460
+ this.lastColumnPos = this.start
1461
+ }
1462
+ return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
1463
+ },
1464
+ indentation: function() {
1465
+ return countColumn(this.string, null, this.tabSize) -
1466
+ (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0)
1467
+ },
1468
+ match: function(pattern, consume, caseInsensitive) {
1469
+ if (typeof pattern == "string") {
1470
+ var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }
1471
+ var substr = this.string.substr(this.pos, pattern.length)
1472
+ if (cased(substr) == cased(pattern)) {
1473
+ if (consume !== false) { this.pos += pattern.length }
1474
+ return true
1475
+ }
1476
+ } else {
1477
+ var match = this.string.slice(this.pos).match(pattern)
1478
+ if (match && match.index > 0) { return null }
1479
+ if (match && consume !== false) { this.pos += match[0].length }
1480
+ return match
1481
+ }
1482
+ },
1483
+ current: function(){return this.string.slice(this.start, this.pos)},
1484
+ hideFirstChars: function(n, inner) {
1485
+ this.lineStart += n
1486
+ try { return inner() }
1487
+ finally { this.lineStart -= n }
1488
+ }
1489
+ }
1490
+
1491
+ // Compute a style array (an array starting with a mode generation
1492
+ // -- for invalidation -- followed by pairs of end positions and
1493
+ // style strings), which is used to highlight the tokens on the
1494
+ // line.
1495
+ function highlightLine(cm, line, state, forceToEnd) {
1496
+ // A styles array always starts with a number identifying the
1497
+ // mode/overlays that it is based on (for easy invalidation).
1498
+ var st = [cm.state.modeGen], lineClasses = {}
1499
+ // Compute the base array of styles
1500
+ runMode(cm, line.text, cm.doc.mode, state, function (end, style) { return st.push(end, style); },
1501
+ lineClasses, forceToEnd)
1502
+
1503
+ // Run overlays, adjust style array.
1504
+ var loop = function ( o ) {
1505
+ var overlay = cm.state.overlays[o], i = 1, at = 0
1506
+ runMode(cm, line.text, overlay.mode, true, function (end, style) {
1507
+ var start = i
1508
+ // Ensure there's a token end at the current position, and that i points at it
1509
+ while (at < end) {
1510
+ var i_end = st[i]
1511
+ if (i_end > end)
1512
+ { st.splice(i, 1, end, st[i+1], i_end) }
1513
+ i += 2
1514
+ at = Math.min(end, i_end)
1515
+ }
1516
+ if (!style) { return }
1517
+ if (overlay.opaque) {
1518
+ st.splice(start, i - start, end, "overlay " + style)
1519
+ i = start + 2
1520
+ } else {
1521
+ for (; start < i; start += 2) {
1522
+ var cur = st[start+1]
1523
+ st[start+1] = (cur ? cur + " " : "") + "overlay " + style
1524
+ }
1525
+ }
1526
+ }, lineClasses)
1527
+ };
1528
+
1529
+ for (var o = 0; o < cm.state.overlays.length; ++o) loop( o );
1530
+
1531
+ return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null}
1532
+ }
1533
+
1534
+ function getLineStyles(cm, line, updateFrontier) {
1535
+ if (!line.styles || line.styles[0] != cm.state.modeGen) {
1536
+ var state = getStateBefore(cm, lineNo(line))
1537
+ var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state)
1538
+ line.stateAfter = state
1539
+ line.styles = result.styles
1540
+ if (result.classes) { line.styleClasses = result.classes }
1541
+ else if (line.styleClasses) { line.styleClasses = null }
1542
+ if (updateFrontier === cm.doc.frontier) { cm.doc.frontier++ }
1543
+ }
1544
+ return line.styles
1545
+ }
1546
+
1547
+ function getStateBefore(cm, n, precise) {
1548
+ var doc = cm.doc, display = cm.display
1549
+ if (!doc.mode.startState) { return true }
1550
+ var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter
1551
+ if (!state) { state = startState(doc.mode) }
1552
+ else { state = copyState(doc.mode, state) }
1553
+ doc.iter(pos, n, function (line) {
1554
+ processLine(cm, line.text, state)
1555
+ var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo
1556
+ line.stateAfter = save ? copyState(doc.mode, state) : null
1557
+ ++pos
1558
+ })
1559
+ if (precise) { doc.frontier = pos }
1560
+ return state
1561
+ }
1562
+
1563
+ // Lightweight form of highlight -- proceed over this line and
1564
+ // update state, but don't save a style array. Used for lines that
1565
+ // aren't currently visible.
1566
+ function processLine(cm, text, state, startAt) {
1567
+ var mode = cm.doc.mode
1568
+ var stream = new StringStream(text, cm.options.tabSize)
1569
+ stream.start = stream.pos = startAt || 0
1570
+ if (text == "") { callBlankLine(mode, state) }
1571
+ while (!stream.eol()) {
1572
+ readToken(mode, stream, state)
1573
+ stream.start = stream.pos
1574
+ }
1575
+ }
1576
+
1577
+ function callBlankLine(mode, state) {
1578
+ if (mode.blankLine) { return mode.blankLine(state) }
1579
+ if (!mode.innerMode) { return }
1580
+ var inner = innerMode(mode, state)
1581
+ if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) }
1582
+ }
1583
+
1584
+ function readToken(mode, stream, state, inner) {
1585
+ for (var i = 0; i < 10; i++) {
1586
+ if (inner) { inner[0] = innerMode(mode, state).mode }
1587
+ var style = mode.token(stream, state)
1588
+ if (stream.pos > stream.start) { return style }
1589
+ }
1590
+ throw new Error("Mode " + mode.name + " failed to advance stream.")
1591
+ }
1592
+
1593
+ // Utility for getTokenAt and getLineTokens
1594
+ function takeToken(cm, pos, precise, asArray) {
1595
+ var getObj = function (copy) { return ({
1596
+ start: stream.start, end: stream.pos,
1597
+ string: stream.current(),
1598
+ type: style || null,
1599
+ state: copy ? copyState(doc.mode, state) : state
1600
+ }); }
1601
+
1602
+ var doc = cm.doc, mode = doc.mode, style
1603
+ pos = clipPos(doc, pos)
1604
+ var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise)
1605
+ var stream = new StringStream(line.text, cm.options.tabSize), tokens
1606
+ if (asArray) { tokens = [] }
1607
+ while ((asArray || stream.pos < pos.ch) && !stream.eol()) {
1608
+ stream.start = stream.pos
1609
+ style = readToken(mode, stream, state)
1610
+ if (asArray) { tokens.push(getObj(true)) }
1611
+ }
1612
+ return asArray ? tokens : getObj()
1613
+ }
1614
+
1615
+ function extractLineClasses(type, output) {
1616
+ if (type) { for (;;) {
1617
+ var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/)
1618
+ if (!lineClass) { break }
1619
+ type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length)
1620
+ var prop = lineClass[1] ? "bgClass" : "textClass"
1621
+ if (output[prop] == null)
1622
+ { output[prop] = lineClass[2] }
1623
+ else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop]))
1624
+ { output[prop] += " " + lineClass[2] }
1625
+ } }
1626
+ return type
1627
+ }
1628
+
1629
+ // Run the given mode's parser over a line, calling f for each token.
1630
+ function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) {
1631
+ var flattenSpans = mode.flattenSpans
1632
+ if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans }
1633
+ var curStart = 0, curStyle = null
1634
+ var stream = new StringStream(text, cm.options.tabSize), style
1635
+ var inner = cm.options.addModeClass && [null]
1636
+ if (text == "") { extractLineClasses(callBlankLine(mode, state), lineClasses) }
1637
+ while (!stream.eol()) {
1638
+ if (stream.pos > cm.options.maxHighlightLength) {
1639
+ flattenSpans = false
1640
+ if (forceToEnd) { processLine(cm, text, state, stream.pos) }
1641
+ stream.pos = text.length
1642
+ style = null
1643
+ } else {
1644
+ style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses)
1645
+ }
1646
+ if (inner) {
1647
+ var mName = inner[0].name
1648
+ if (mName) { style = "m-" + (style ? mName + " " + style : mName) }
1649
+ }
1650
+ if (!flattenSpans || curStyle != style) {
1651
+ while (curStart < stream.start) {
1652
+ curStart = Math.min(stream.start, curStart + 5000)
1653
+ f(curStart, curStyle)
1654
+ }
1655
+ curStyle = style
1656
+ }
1657
+ stream.start = stream.pos
1658
+ }
1659
+ while (curStart < stream.pos) {
1660
+ // Webkit seems to refuse to render text nodes longer than 57444
1661
+ // characters, and returns inaccurate measurements in nodes
1662
+ // starting around 5000 chars.
1663
+ var pos = Math.min(stream.pos, curStart + 5000)
1664
+ f(pos, curStyle)
1665
+ curStart = pos
1666
+ }
1667
+ }
1668
+
1669
+ // Finds the line to start with when starting a parse. Tries to
1670
+ // find a line with a stateAfter, so that it can start with a
1671
+ // valid state. If that fails, it returns the line with the
1672
+ // smallest indentation, which tends to need the least context to
1673
+ // parse correctly.
1674
+ function findStartLine(cm, n, precise) {
1675
+ var minindent, minline, doc = cm.doc
1676
+ var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100)
1677
+ for (var search = n; search > lim; --search) {
1678
+ if (search <= doc.first) { return doc.first }
1679
+ var line = getLine(doc, search - 1)
1680
+ if (line.stateAfter && (!precise || search <= doc.frontier)) { return search }
1681
+ var indented = countColumn(line.text, null, cm.options.tabSize)
1682
+ if (minline == null || minindent > indented) {
1683
+ minline = search - 1
1684
+ minindent = indented
1685
+ }
1686
+ }
1687
+ return minline
1688
+ }
1689
+
1690
+ // LINE DATA STRUCTURE
1691
+
1692
+ // Line objects. These hold state related to a line, including
1693
+ // highlighting info (the styles array).
1694
+ function Line(text, markedSpans, estimateHeight) {
1695
+ this.text = text
1696
+ attachMarkedSpans(this, markedSpans)
1697
+ this.height = estimateHeight ? estimateHeight(this) : 1
1698
+ }
1699
+ eventMixin(Line)
1700
+ Line.prototype.lineNo = function() { return lineNo(this) }
1701
+
1702
+ // Change the content (text, markers) of a line. Automatically
1703
+ // invalidates cached information and tries to re-estimate the
1704
+ // line's height.
1705
+ function updateLine(line, text, markedSpans, estimateHeight) {
1706
+ line.text = text
1707
+ if (line.stateAfter) { line.stateAfter = null }
1708
+ if (line.styles) { line.styles = null }
1709
+ if (line.order != null) { line.order = null }
1710
+ detachMarkedSpans(line)
1711
+ attachMarkedSpans(line, markedSpans)
1712
+ var estHeight = estimateHeight ? estimateHeight(line) : 1
1713
+ if (estHeight != line.height) { updateLineHeight(line, estHeight) }
1714
+ }
1715
+
1716
+ // Detach a line from the document tree and its markers.
1717
+ function cleanUpLine(line) {
1718
+ line.parent = null
1719
+ detachMarkedSpans(line)
1720
+ }
1721
+
1722
+ // Convert a style as returned by a mode (either null, or a string
1723
+ // containing one or more styles) to a CSS style. This is cached,
1724
+ // and also looks for line-wide styles.
1725
+ var styleToClassCache = {};
1726
+ var styleToClassCacheWithMode = {};
1727
+ function interpretTokenStyle(style, options) {
1728
+ if (!style || /^\s*$/.test(style)) { return null }
1729
+ var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache
1730
+ return cache[style] ||
1731
+ (cache[style] = style.replace(/\S+/g, "cm-$&"))
1732
+ }
1733
+
1734
+ // Render the DOM representation of the text of a line. Also builds
1735
+ // up a 'line map', which points at the DOM nodes that represent
1736
+ // specific stretches of text, and is used by the measuring code.
1737
+ // The returned object contains the DOM node, this map, and
1738
+ // information about line-wide styles that were set by the mode.
1739
+ function buildLineContent(cm, lineView) {
1740
+ // The padding-right forces the element to have a 'border', which
1741
+ // is needed on Webkit to be able to get line-level bounding
1742
+ // rectangles for it (in measureChar).
1743
+ var content = elt("span", null, null, webkit ? "padding-right: .1px" : null)
1744
+ var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content,
1745
+ col: 0, pos: 0, cm: cm,
1746
+ trailingSpace: false,
1747
+ splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")}
1748
+ // hide from accessibility tree
1749
+ content.setAttribute("role", "presentation")
1750
+ builder.pre.setAttribute("role", "presentation")
1751
+ lineView.measure = {}
1752
+
1753
+ // Iterate over the logical lines that make up this visual line.
1754
+ for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) {
1755
+ var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0)
1756
+ builder.pos = 0
1757
+ builder.addToken = buildToken
1758
+ // Optionally wire in some hacks into the token-rendering
1759
+ // algorithm, to deal with browser quirks.
1760
+ if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line)))
1761
+ { builder.addToken = buildTokenBadBidi(builder.addToken, order) }
1762
+ builder.map = []
1763
+ var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line)
1764
+ insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate))
1765
+ if (line.styleClasses) {
1766
+ if (line.styleClasses.bgClass)
1767
+ { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "") }
1768
+ if (line.styleClasses.textClass)
1769
+ { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "") }
1770
+ }
1771
+
1772
+ // Ensure at least a single node is present, for measuring.
1773
+ if (builder.map.length == 0)
1774
+ { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))) }
1775
+
1776
+ // Store the map and a cache object for the current logical line
1777
+ if (i == 0) {
1778
+ lineView.measure.map = builder.map
1779
+ lineView.measure.cache = {}
1780
+ } else {
1781
+ ;(lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map)
1782
+ ;(lineView.measure.caches || (lineView.measure.caches = [])).push({})
1783
+ }
1784
+ }
1785
+
1786
+ // See issue #2901
1787
+ if (webkit) {
1788
+ var last = builder.content.lastChild
1789
+ if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab")))
1790
+ { builder.content.className = "cm-tab-wrap-hack" }
1791
+ }
1792
+
1793
+ signal(cm, "renderLine", cm, lineView.line, builder.pre)
1794
+ if (builder.pre.className)
1795
+ { builder.textClass = joinClasses(builder.pre.className, builder.textClass || "") }
1796
+
1797
+ return builder
1798
+ }
1799
+
1800
+ function defaultSpecialCharPlaceholder(ch) {
1801
+ var token = elt("span", "\u2022", "cm-invalidchar")
1802
+ token.title = "\\u" + ch.charCodeAt(0).toString(16)
1803
+ token.setAttribute("aria-label", token.title)
1804
+ return token
1805
+ }
1806
+
1807
+ // Build up the DOM representation for a single token, and add it to
1808
+ // the line map. Takes care to render special characters separately.
1809
+ function buildToken(builder, text, style, startStyle, endStyle, title, css) {
1810
+ if (!text) { return }
1811
+ var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text
1812
+ var special = builder.cm.state.specialChars, mustWrap = false
1813
+ var content
1814
+ if (!special.test(text)) {
1815
+ builder.col += text.length
1816
+ content = document.createTextNode(displayText)
1817
+ builder.map.push(builder.pos, builder.pos + text.length, content)
1818
+ if (ie && ie_version < 9) { mustWrap = true }
1819
+ builder.pos += text.length
1820
+ } else {
1821
+ content = document.createDocumentFragment()
1822
+ var pos = 0
1823
+ while (true) {
1824
+ special.lastIndex = pos
1825
+ var m = special.exec(text)
1826
+ var skipped = m ? m.index - pos : text.length - pos
1827
+ if (skipped) {
1828
+ var txt = document.createTextNode(displayText.slice(pos, pos + skipped))
1829
+ if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])) }
1830
+ else { content.appendChild(txt) }
1831
+ builder.map.push(builder.pos, builder.pos + skipped, txt)
1832
+ builder.col += skipped
1833
+ builder.pos += skipped
1834
+ }
1835
+ if (!m) { break }
1836
+ pos += skipped + 1
1837
+ var txt$1 = (void 0)
1838
+ if (m[0] == "\t") {
1839
+ var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize
1840
+ txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab"))
1841
+ txt$1.setAttribute("role", "presentation")
1842
+ txt$1.setAttribute("cm-text", "\t")
1843
+ builder.col += tabWidth
1844
+ } else if (m[0] == "\r" || m[0] == "\n") {
1845
+ txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar"))
1846
+ txt$1.setAttribute("cm-text", m[0])
1847
+ builder.col += 1
1848
+ } else {
1849
+ txt$1 = builder.cm.options.specialCharPlaceholder(m[0])
1850
+ txt$1.setAttribute("cm-text", m[0])
1851
+ if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])) }
1852
+ else { content.appendChild(txt$1) }
1853
+ builder.col += 1
1854
+ }
1855
+ builder.map.push(builder.pos, builder.pos + 1, txt$1)
1856
+ builder.pos++
1857
+ }
1858
+ }
1859
+ builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32
1860
+ if (style || startStyle || endStyle || mustWrap || css) {
1861
+ var fullStyle = style || ""
1862
+ if (startStyle) { fullStyle += startStyle }
1863
+ if (endStyle) { fullStyle += endStyle }
1864
+ var token = elt("span", [content], fullStyle, css)
1865
+ if (title) { token.title = title }
1866
+ return builder.content.appendChild(token)
1867
+ }
1868
+ builder.content.appendChild(content)
1869
+ }
1870
+
1871
+ function splitSpaces(text, trailingBefore) {
1872
+ if (text.length > 1 && !/ /.test(text)) { return text }
1873
+ var spaceBefore = trailingBefore, result = ""
1874
+ for (var i = 0; i < text.length; i++) {
1875
+ var ch = text.charAt(i)
1876
+ if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32))
1877
+ { ch = "\u00a0" }
1878
+ result += ch
1879
+ spaceBefore = ch == " "
1880
+ }
1881
+ return result
1882
+ }
1883
+
1884
+ // Work around nonsense dimensions being reported for stretches of
1885
+ // right-to-left text.
1886
+ function buildTokenBadBidi(inner, order) {
1887
+ return function (builder, text, style, startStyle, endStyle, title, css) {
1888
+ style = style ? style + " cm-force-border" : "cm-force-border"
1889
+ var start = builder.pos, end = start + text.length
1890
+ for (;;) {
1891
+ // Find the part that overlaps with the start of this text
1892
+ var part = (void 0)
1893
+ for (var i = 0; i < order.length; i++) {
1894
+ part = order[i]
1895
+ if (part.to > start && part.from <= start) { break }
1896
+ }
1897
+ if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, title, css) }
1898
+ inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css)
1899
+ startStyle = null
1900
+ text = text.slice(part.to - start)
1901
+ start = part.to
1902
+ }
1903
+ }
1904
+ }
1905
+
1906
+ function buildCollapsedSpan(builder, size, marker, ignoreWidget) {
1907
+ var widget = !ignoreWidget && marker.widgetNode
1908
+ if (widget) { builder.map.push(builder.pos, builder.pos + size, widget) }
1909
+ if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) {
1910
+ if (!widget)
1911
+ { widget = builder.content.appendChild(document.createElement("span")) }
1912
+ widget.setAttribute("cm-marker", marker.id)
1913
+ }
1914
+ if (widget) {
1915
+ builder.cm.display.input.setUneditable(widget)
1916
+ builder.content.appendChild(widget)
1917
+ }
1918
+ builder.pos += size
1919
+ builder.trailingSpace = false
1920
+ }
1921
+
1922
+ // Outputs a number of spans to make up a line, taking highlighting
1923
+ // and marked text into account.
1924
+ function insertLineContent(line, builder, styles) {
1925
+ var spans = line.markedSpans, allText = line.text, at = 0
1926
+ if (!spans) {
1927
+ for (var i$1 = 1; i$1 < styles.length; i$1+=2)
1928
+ { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)) }
1929
+ return
1930
+ }
1931
+
1932
+ var len = allText.length, pos = 0, i = 1, text = "", style, css
1933
+ var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed
1934
+ for (;;) {
1935
+ if (nextChange == pos) { // Update current marker set
1936
+ spanStyle = spanEndStyle = spanStartStyle = title = css = ""
1937
+ collapsed = null; nextChange = Infinity
1938
+ var foundBookmarks = [], endStyles = (void 0)
1939
+ for (var j = 0; j < spans.length; ++j) {
1940
+ var sp = spans[j], m = sp.marker
1941
+ if (m.type == "bookmark" && sp.from == pos && m.widgetNode) {
1942
+ foundBookmarks.push(m)
1943
+ } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) {
1944
+ if (sp.to != null && sp.to != pos && nextChange > sp.to) {
1945
+ nextChange = sp.to
1946
+ spanEndStyle = ""
1947
+ }
1948
+ if (m.className) { spanStyle += " " + m.className }
1949
+ if (m.css) { css = (css ? css + ";" : "") + m.css }
1950
+ if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle }
1951
+ if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to) }
1952
+ if (m.title && !title) { title = m.title }
1953
+ if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0))
1954
+ { collapsed = sp }
1955
+ } else if (sp.from > pos && nextChange > sp.from) {
1956
+ nextChange = sp.from
1957
+ }
1958
+ }
1959
+ if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2)
1960
+ { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1] } } }
1961
+
1962
+ if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2)
1963
+ { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]) } }
1964
+ if (collapsed && (collapsed.from || 0) == pos) {
1965
+ buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos,
1966
+ collapsed.marker, collapsed.from == null)
1967
+ if (collapsed.to == null) { return }
1968
+ if (collapsed.to == pos) { collapsed = false }
1969
+ }
1970
+ }
1971
+ if (pos >= len) { break }
1972
+
1973
+ var upto = Math.min(len, nextChange)
1974
+ while (true) {
1975
+ if (text) {
1976
+ var end = pos + text.length
1977
+ if (!collapsed) {
1978
+ var tokenText = end > upto ? text.slice(0, upto - pos) : text
1979
+ builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle,
1980
+ spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css)
1981
+ }
1982
+ if (end >= upto) {text = text.slice(upto - pos); pos = upto; break}
1983
+ pos = end
1984
+ spanStartStyle = ""
1985
+ }
1986
+ text = allText.slice(at, at = styles[i++])
1987
+ style = interpretTokenStyle(styles[i++], builder.cm.options)
1988
+ }
1989
+ }
1990
+ }
1991
+
1992
+
1993
+ // These objects are used to represent the visible (currently drawn)
1994
+ // part of the document. A LineView may correspond to multiple
1995
+ // logical lines, if those are connected by collapsed ranges.
1996
+ function LineView(doc, line, lineN) {
1997
+ // The starting line
1998
+ this.line = line
1999
+ // Continuing lines, if any
2000
+ this.rest = visualLineContinued(line)
2001
+ // Number of logical lines in this visual line
2002
+ this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1
2003
+ this.node = this.text = null
2004
+ this.hidden = lineIsHidden(doc, line)
2005
+ }
2006
+
2007
+ // Create a range of LineView objects for the given lines.
2008
+ function buildViewArray(cm, from, to) {
2009
+ var array = [], nextPos
2010
+ for (var pos = from; pos < to; pos = nextPos) {
2011
+ var view = new LineView(cm.doc, getLine(cm.doc, pos), pos)
2012
+ nextPos = pos + view.size
2013
+ array.push(view)
2014
+ }
2015
+ return array
2016
+ }
2017
+
2018
+ var operationGroup = null
2019
+
2020
+ function pushOperation(op) {
2021
+ if (operationGroup) {
2022
+ operationGroup.ops.push(op)
2023
+ } else {
2024
+ op.ownsGroup = operationGroup = {
2025
+ ops: [op],
2026
+ delayedCallbacks: []
2027
+ }
2028
+ }
2029
+ }
2030
+
2031
+ function fireCallbacksForOps(group) {
2032
+ // Calls delayed callbacks and cursorActivity handlers until no
2033
+ // new ones appear
2034
+ var callbacks = group.delayedCallbacks, i = 0
2035
+ do {
2036
+ for (; i < callbacks.length; i++)
2037
+ { callbacks[i].call(null) }
2038
+ for (var j = 0; j < group.ops.length; j++) {
2039
+ var op = group.ops[j]
2040
+ if (op.cursorActivityHandlers)
2041
+ { while (op.cursorActivityCalled < op.cursorActivityHandlers.length)
2042
+ { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm) } }
2043
+ }
2044
+ } while (i < callbacks.length)
2045
+ }
2046
+
2047
+ function finishOperation(op, endCb) {
2048
+ var group = op.ownsGroup
2049
+ if (!group) { return }
2050
+
2051
+ try { fireCallbacksForOps(group) }
2052
+ finally {
2053
+ operationGroup = null
2054
+ endCb(group)
2055
+ }
2056
+ }
2057
+
2058
+ var orphanDelayedCallbacks = null
2059
+
2060
+ // Often, we want to signal events at a point where we are in the
2061
+ // middle of some work, but don't want the handler to start calling
2062
+ // other methods on the editor, which might be in an inconsistent
2063
+ // state or simply not expect any other events to happen.
2064
+ // signalLater looks whether there are any handlers, and schedules
2065
+ // them to be executed when the last operation ends, or, if no
2066
+ // operation is active, when a timeout fires.
2067
+ function signalLater(emitter, type /*, values...*/) {
2068
+ var arr = getHandlers(emitter, type)
2069
+ if (!arr.length) { return }
2070
+ var args = Array.prototype.slice.call(arguments, 2), list
2071
+ if (operationGroup) {
2072
+ list = operationGroup.delayedCallbacks
2073
+ } else if (orphanDelayedCallbacks) {
2074
+ list = orphanDelayedCallbacks
2075
+ } else {
2076
+ list = orphanDelayedCallbacks = []
2077
+ setTimeout(fireOrphanDelayed, 0)
2078
+ }
2079
+ var loop = function ( i ) {
2080
+ list.push(function () { return arr[i].apply(null, args); })
2081
+ };
2082
+
2083
+ for (var i = 0; i < arr.length; ++i)
2084
+ loop( i );
2085
+ }
2086
+
2087
+ function fireOrphanDelayed() {
2088
+ var delayed = orphanDelayedCallbacks
2089
+ orphanDelayedCallbacks = null
2090
+ for (var i = 0; i < delayed.length; ++i) { delayed[i]() }
2091
+ }
2092
+
2093
+ // When an aspect of a line changes, a string is added to
2094
+ // lineView.changes. This updates the relevant part of the line's
2095
+ // DOM structure.
2096
+ function updateLineForChanges(cm, lineView, lineN, dims) {
2097
+ for (var j = 0; j < lineView.changes.length; j++) {
2098
+ var type = lineView.changes[j]
2099
+ if (type == "text") { updateLineText(cm, lineView) }
2100
+ else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims) }
2101
+ else if (type == "class") { updateLineClasses(lineView) }
2102
+ else if (type == "widget") { updateLineWidgets(cm, lineView, dims) }
2103
+ }
2104
+ lineView.changes = null
2105
+ }
2106
+
2107
+ // Lines with gutter elements, widgets or a background class need to
2108
+ // be wrapped, and have the extra elements added to the wrapper div
2109
+ function ensureLineWrapped(lineView) {
2110
+ if (lineView.node == lineView.text) {
2111
+ lineView.node = elt("div", null, null, "position: relative")
2112
+ if (lineView.text.parentNode)
2113
+ { lineView.text.parentNode.replaceChild(lineView.node, lineView.text) }
2114
+ lineView.node.appendChild(lineView.text)
2115
+ if (ie && ie_version < 8) { lineView.node.style.zIndex = 2 }
2116
+ }
2117
+ return lineView.node
2118
+ }
2119
+
2120
+ function updateLineBackground(lineView) {
2121
+ var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass
2122
+ if (cls) { cls += " CodeMirror-linebackground" }
2123
+ if (lineView.background) {
2124
+ if (cls) { lineView.background.className = cls }
2125
+ else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null }
2126
+ } else if (cls) {
2127
+ var wrap = ensureLineWrapped(lineView)
2128
+ lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild)
2129
+ }
2130
+ }
2131
+
2132
+ // Wrapper around buildLineContent which will reuse the structure
2133
+ // in display.externalMeasured when possible.
2134
+ function getLineContent(cm, lineView) {
2135
+ var ext = cm.display.externalMeasured
2136
+ if (ext && ext.line == lineView.line) {
2137
+ cm.display.externalMeasured = null
2138
+ lineView.measure = ext.measure
2139
+ return ext.built
2140
+ }
2141
+ return buildLineContent(cm, lineView)
2142
+ }
2143
+
2144
+ // Redraw the line's text. Interacts with the background and text
2145
+ // classes because the mode may output tokens that influence these
2146
+ // classes.
2147
+ function updateLineText(cm, lineView) {
2148
+ var cls = lineView.text.className
2149
+ var built = getLineContent(cm, lineView)
2150
+ if (lineView.text == lineView.node) { lineView.node = built.pre }
2151
+ lineView.text.parentNode.replaceChild(built.pre, lineView.text)
2152
+ lineView.text = built.pre
2153
+ if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) {
2154
+ lineView.bgClass = built.bgClass
2155
+ lineView.textClass = built.textClass
2156
+ updateLineClasses(lineView)
2157
+ } else if (cls) {
2158
+ lineView.text.className = cls
2159
+ }
2160
+ }
2161
+
2162
+ function updateLineClasses(lineView) {
2163
+ updateLineBackground(lineView)
2164
+ if (lineView.line.wrapClass)
2165
+ { ensureLineWrapped(lineView).className = lineView.line.wrapClass }
2166
+ else if (lineView.node != lineView.text)
2167
+ { lineView.node.className = "" }
2168
+ var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass
2169
+ lineView.text.className = textClass || ""
2170
+ }
2171
+
2172
+ function updateLineGutter(cm, lineView, lineN, dims) {
2173
+ if (lineView.gutter) {
2174
+ lineView.node.removeChild(lineView.gutter)
2175
+ lineView.gutter = null
2176
+ }
2177
+ if (lineView.gutterBackground) {
2178
+ lineView.node.removeChild(lineView.gutterBackground)
2179
+ lineView.gutterBackground = null
2180
+ }
2181
+ if (lineView.line.gutterClass) {
2182
+ var wrap = ensureLineWrapped(lineView)
2183
+ lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass,
2184
+ ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px"))
2185
+ wrap.insertBefore(lineView.gutterBackground, lineView.text)
2186
+ }
2187
+ var markers = lineView.line.gutterMarkers
2188
+ if (cm.options.lineNumbers || markers) {
2189
+ var wrap$1 = ensureLineWrapped(lineView)
2190
+ var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px"))
2191
+ cm.display.input.setUneditable(gutterWrap)
2192
+ wrap$1.insertBefore(gutterWrap, lineView.text)
2193
+ if (lineView.line.gutterClass)
2194
+ { gutterWrap.className += " " + lineView.line.gutterClass }
2195
+ if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"]))
2196
+ { lineView.lineNumber = gutterWrap.appendChild(
2197
+ elt("div", lineNumberFor(cm.options, lineN),
2198
+ "CodeMirror-linenumber CodeMirror-gutter-elt",
2199
+ ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))) }
2200
+ if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) {
2201
+ var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id]
2202
+ if (found)
2203
+ { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt",
2204
+ ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))) }
2205
+ } }
2206
+ }
2207
+ }
2208
+
2209
+ function updateLineWidgets(cm, lineView, dims) {
2210
+ if (lineView.alignable) { lineView.alignable = null }
2211
+ for (var node = lineView.node.firstChild, next = (void 0); node; node = next) {
2212
+ next = node.nextSibling
2213
+ if (node.className == "CodeMirror-linewidget")
2214
+ { lineView.node.removeChild(node) }
2215
+ }
2216
+ insertLineWidgets(cm, lineView, dims)
2217
+ }
2218
+
2219
+ // Build a line's DOM representation from scratch
2220
+ function buildLineElement(cm, lineView, lineN, dims) {
2221
+ var built = getLineContent(cm, lineView)
2222
+ lineView.text = lineView.node = built.pre
2223
+ if (built.bgClass) { lineView.bgClass = built.bgClass }
2224
+ if (built.textClass) { lineView.textClass = built.textClass }
2225
+
2226
+ updateLineClasses(lineView)
2227
+ updateLineGutter(cm, lineView, lineN, dims)
2228
+ insertLineWidgets(cm, lineView, dims)
2229
+ return lineView.node
2230
+ }
2231
+
2232
+ // A lineView may contain multiple logical lines (when merged by
2233
+ // collapsed spans). The widgets for all of them need to be drawn.
2234
+ function insertLineWidgets(cm, lineView, dims) {
2235
+ insertLineWidgetsFor(cm, lineView.line, lineView, dims, true)
2236
+ if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
2237
+ { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false) } }
2238
+ }
2239
+
2240
+ function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) {
2241
+ if (!line.widgets) { return }
2242
+ var wrap = ensureLineWrapped(lineView)
2243
+ for (var i = 0, ws = line.widgets; i < ws.length; ++i) {
2244
+ var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget")
2245
+ if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true") }
2246
+ positionLineWidget(widget, node, lineView, dims)
2247
+ cm.display.input.setUneditable(node)
2248
+ if (allowAbove && widget.above)
2249
+ { wrap.insertBefore(node, lineView.gutter || lineView.text) }
2250
+ else
2251
+ { wrap.appendChild(node) }
2252
+ signalLater(widget, "redraw")
2253
+ }
2254
+ }
2255
+
2256
+ function positionLineWidget(widget, node, lineView, dims) {
2257
+ if (widget.noHScroll) {
2258
+ ;(lineView.alignable || (lineView.alignable = [])).push(node)
2259
+ var width = dims.wrapperWidth
2260
+ node.style.left = dims.fixedPos + "px"
2261
+ if (!widget.coverGutter) {
2262
+ width -= dims.gutterTotalWidth
2263
+ node.style.paddingLeft = dims.gutterTotalWidth + "px"
2264
+ }
2265
+ node.style.width = width + "px"
2266
+ }
2267
+ if (widget.coverGutter) {
2268
+ node.style.zIndex = 5
2269
+ node.style.position = "relative"
2270
+ if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px" }
2271
+ }
2272
+ }
2273
+
2274
+ function widgetHeight(widget) {
2275
+ if (widget.height != null) { return widget.height }
2276
+ var cm = widget.doc.cm
2277
+ if (!cm) { return 0 }
2278
+ if (!contains(document.body, widget.node)) {
2279
+ var parentStyle = "position: relative;"
2280
+ if (widget.coverGutter)
2281
+ { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;" }
2282
+ if (widget.noHScroll)
2283
+ { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;" }
2284
+ removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle))
2285
+ }
2286
+ return widget.height = widget.node.parentNode.offsetHeight
2287
+ }
2288
+
2289
+ // Return true when the given mouse event happened in a widget
2290
+ function eventInWidget(display, e) {
2291
+ for (var n = e_target(e); n != display.wrapper; n = n.parentNode) {
2292
+ if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") ||
2293
+ (n.parentNode == display.sizer && n != display.mover))
2294
+ { return true }
2295
+ }
2296
+ }
2297
+
2298
+ // POSITION MEASUREMENT
2299
+
2300
+ function paddingTop(display) {return display.lineSpace.offsetTop}
2301
+ function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight}
2302
+ function paddingH(display) {
2303
+ if (display.cachedPaddingH) { return display.cachedPaddingH }
2304
+ var e = removeChildrenAndAdd(display.measure, elt("pre", "x"))
2305
+ var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle
2306
+ var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}
2307
+ if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data }
2308
+ return data
2309
+ }
2310
+
2311
+ function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth }
2312
+ function displayWidth(cm) {
2313
+ return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth
2314
+ }
2315
+ function displayHeight(cm) {
2316
+ return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight
2317
+ }
2318
+
2319
+ // Ensure the lineView.wrapping.heights array is populated. This is
2320
+ // an array of bottom offsets for the lines that make up a drawn
2321
+ // line. When lineWrapping is on, there might be more than one
2322
+ // height.
2323
+ function ensureLineHeights(cm, lineView, rect) {
2324
+ var wrapping = cm.options.lineWrapping
2325
+ var curWidth = wrapping && displayWidth(cm)
2326
+ if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) {
2327
+ var heights = lineView.measure.heights = []
2328
+ if (wrapping) {
2329
+ lineView.measure.width = curWidth
2330
+ var rects = lineView.text.firstChild.getClientRects()
2331
+ for (var i = 0; i < rects.length - 1; i++) {
2332
+ var cur = rects[i], next = rects[i + 1]
2333
+ if (Math.abs(cur.bottom - next.bottom) > 2)
2334
+ { heights.push((cur.bottom + next.top) / 2 - rect.top) }
2335
+ }
2336
+ }
2337
+ heights.push(rect.bottom - rect.top)
2338
+ }
2339
+ }
2340
+
2341
+ // Find a line map (mapping character offsets to text nodes) and a
2342
+ // measurement cache for the given line number. (A line view might
2343
+ // contain multiple lines when collapsed ranges are present.)
2344
+ function mapFromLineView(lineView, line, lineN) {
2345
+ if (lineView.line == line)
2346
+ { return {map: lineView.measure.map, cache: lineView.measure.cache} }
2347
+ for (var i = 0; i < lineView.rest.length; i++)
2348
+ { if (lineView.rest[i] == line)
2349
+ { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } }
2350
+ for (var i$1 = 0; i$1 < lineView.rest.length; i$1++)
2351
+ { if (lineNo(lineView.rest[i$1]) > lineN)
2352
+ { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } }
2353
+ }
2354
+
2355
+ // Render a line into the hidden node display.externalMeasured. Used
2356
+ // when measurement is needed for a line that's not in the viewport.
2357
+ function updateExternalMeasurement(cm, line) {
2358
+ line = visualLine(line)
2359
+ var lineN = lineNo(line)
2360
+ var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN)
2361
+ view.lineN = lineN
2362
+ var built = view.built = buildLineContent(cm, view)
2363
+ view.text = built.pre
2364
+ removeChildrenAndAdd(cm.display.lineMeasure, built.pre)
2365
+ return view
2366
+ }
2367
+
2368
+ // Get a {top, bottom, left, right} box (in line-local coordinates)
2369
+ // for a given character.
2370
+ function measureChar(cm, line, ch, bias) {
2371
+ return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias)
2372
+ }
2373
+
2374
+ // Find a line view that corresponds to the given line number.
2375
+ function findViewForLine(cm, lineN) {
2376
+ if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo)
2377
+ { return cm.display.view[findViewIndex(cm, lineN)] }
2378
+ var ext = cm.display.externalMeasured
2379
+ if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size)
2380
+ { return ext }
2381
+ }
2382
+
2383
+ // Measurement can be split in two steps, the set-up work that
2384
+ // applies to the whole line, and the measurement of the actual
2385
+ // character. Functions like coordsChar, that need to do a lot of
2386
+ // measurements in a row, can thus ensure that the set-up work is
2387
+ // only done once.
2388
+ function prepareMeasureForLine(cm, line) {
2389
+ var lineN = lineNo(line)
2390
+ var view = findViewForLine(cm, lineN)
2391
+ if (view && !view.text) {
2392
+ view = null
2393
+ } else if (view && view.changes) {
2394
+ updateLineForChanges(cm, view, lineN, getDimensions(cm))
2395
+ cm.curOp.forceUpdate = true
2396
+ }
2397
+ if (!view)
2398
+ { view = updateExternalMeasurement(cm, line) }
2399
+
2400
+ var info = mapFromLineView(view, line, lineN)
2401
+ return {
2402
+ line: line, view: view, rect: null,
2403
+ map: info.map, cache: info.cache, before: info.before,
2404
+ hasHeights: false
2405
+ }
2406
+ }
2407
+
2408
+ // Given a prepared measurement object, measures the position of an
2409
+ // actual character (or fetches it from the cache).
2410
+ function measureCharPrepared(cm, prepared, ch, bias, varHeight) {
2411
+ if (prepared.before) { ch = -1 }
2412
+ var key = ch + (bias || ""), found
2413
+ if (prepared.cache.hasOwnProperty(key)) {
2414
+ found = prepared.cache[key]
2415
+ } else {
2416
+ if (!prepared.rect)
2417
+ { prepared.rect = prepared.view.text.getBoundingClientRect() }
2418
+ if (!prepared.hasHeights) {
2419
+ ensureLineHeights(cm, prepared.view, prepared.rect)
2420
+ prepared.hasHeights = true
2421
+ }
2422
+ found = measureCharInner(cm, prepared, ch, bias)
2423
+ if (!found.bogus) { prepared.cache[key] = found }
2424
+ }
2425
+ return {left: found.left, right: found.right,
2426
+ top: varHeight ? found.rtop : found.top,
2427
+ bottom: varHeight ? found.rbottom : found.bottom}
2428
+ }
2429
+
2430
+ var nullRect = {left: 0, right: 0, top: 0, bottom: 0}
2431
+
2432
+ function nodeAndOffsetInLineMap(map, ch, bias) {
2433
+ var node, start, end, collapse, mStart, mEnd
2434
+ // First, search the line map for the text node corresponding to,
2435
+ // or closest to, the target character.
2436
+ for (var i = 0; i < map.length; i += 3) {
2437
+ mStart = map[i]
2438
+ mEnd = map[i + 1]
2439
+ if (ch < mStart) {
2440
+ start = 0; end = 1
2441
+ collapse = "left"
2442
+ } else if (ch < mEnd) {
2443
+ start = ch - mStart
2444
+ end = start + 1
2445
+ } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) {
2446
+ end = mEnd - mStart
2447
+ start = end - 1
2448
+ if (ch >= mEnd) { collapse = "right" }
2449
+ }
2450
+ if (start != null) {
2451
+ node = map[i + 2]
2452
+ if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right"))
2453
+ { collapse = bias }
2454
+ if (bias == "left" && start == 0)
2455
+ { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) {
2456
+ node = map[(i -= 3) + 2]
2457
+ collapse = "left"
2458
+ } }
2459
+ if (bias == "right" && start == mEnd - mStart)
2460
+ { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) {
2461
+ node = map[(i += 3) + 2]
2462
+ collapse = "right"
2463
+ } }
2464
+ break
2465
+ }
2466
+ }
2467
+ return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd}
2468
+ }
2469
+
2470
+ function getUsefulRect(rects, bias) {
2471
+ var rect = nullRect
2472
+ if (bias == "left") { for (var i = 0; i < rects.length; i++) {
2473
+ if ((rect = rects[i]).left != rect.right) { break }
2474
+ } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) {
2475
+ if ((rect = rects[i$1]).left != rect.right) { break }
2476
+ } }
2477
+ return rect
2478
+ }
2479
+
2480
+ function measureCharInner(cm, prepared, ch, bias) {
2481
+ var place = nodeAndOffsetInLineMap(prepared.map, ch, bias)
2482
+ var node = place.node, start = place.start, end = place.end, collapse = place.collapse
2483
+
2484
+ var rect
2485
+ if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates.
2486
+ for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned
2487
+ while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start }
2488
+ while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end }
2489
+ if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart)
2490
+ { rect = node.parentNode.getBoundingClientRect() }
2491
+ else
2492
+ { rect = getUsefulRect(range(node, start, end).getClientRects(), bias) }
2493
+ if (rect.left || rect.right || start == 0) { break }
2494
+ end = start
2495
+ start = start - 1
2496
+ collapse = "right"
2497
+ }
2498
+ if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect) }
2499
+ } else { // If it is a widget, simply get the box for the whole widget.
2500
+ if (start > 0) { collapse = bias = "right" }
2501
+ var rects
2502
+ if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1)
2503
+ { rect = rects[bias == "right" ? rects.length - 1 : 0] }
2504
+ else
2505
+ { rect = node.getBoundingClientRect() }
2506
+ }
2507
+ if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) {
2508
+ var rSpan = node.parentNode.getClientRects()[0]
2509
+ if (rSpan)
2510
+ { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom} }
2511
+ else
2512
+ { rect = nullRect }
2513
+ }
2514
+
2515
+ var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top
2516
+ var mid = (rtop + rbot) / 2
2517
+ var heights = prepared.view.measure.heights
2518
+ var i = 0
2519
+ for (; i < heights.length - 1; i++)
2520
+ { if (mid < heights[i]) { break } }
2521
+ var top = i ? heights[i - 1] : 0, bot = heights[i]
2522
+ var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left,
2523
+ right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left,
2524
+ top: top, bottom: bot}
2525
+ if (!rect.left && !rect.right) { result.bogus = true }
2526
+ if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot }
2527
+
2528
+ return result
2529
+ }
2530
+
2531
+ // Work around problem with bounding client rects on ranges being
2532
+ // returned incorrectly when zoomed on IE10 and below.
2533
+ function maybeUpdateRectForZooming(measure, rect) {
2534
+ if (!window.screen || screen.logicalXDPI == null ||
2535
+ screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure))
2536
+ { return rect }
2537
+ var scaleX = screen.logicalXDPI / screen.deviceXDPI
2538
+ var scaleY = screen.logicalYDPI / screen.deviceYDPI
2539
+ return {left: rect.left * scaleX, right: rect.right * scaleX,
2540
+ top: rect.top * scaleY, bottom: rect.bottom * scaleY}
2541
+ }
2542
+
2543
+ function clearLineMeasurementCacheFor(lineView) {
2544
+ if (lineView.measure) {
2545
+ lineView.measure.cache = {}
2546
+ lineView.measure.heights = null
2547
+ if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++)
2548
+ { lineView.measure.caches[i] = {} } }
2549
+ }
2550
+ }
2551
+
2552
+ function clearLineMeasurementCache(cm) {
2553
+ cm.display.externalMeasure = null
2554
+ removeChildren(cm.display.lineMeasure)
2555
+ for (var i = 0; i < cm.display.view.length; i++)
2556
+ { clearLineMeasurementCacheFor(cm.display.view[i]) }
2557
+ }
2558
+
2559
+ function clearCaches(cm) {
2560
+ clearLineMeasurementCache(cm)
2561
+ cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null
2562
+ if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true }
2563
+ cm.display.lineNumChars = null
2564
+ }
2565
+
2566
+ function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft }
2567
+ function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop }
2568
+
2569
+ // Converts a {top, bottom, left, right} box from line-local
2570
+ // coordinates into another coordinate system. Context may be one of
2571
+ // "line", "div" (display.lineDiv), "local"./null (editor), "window",
2572
+ // or "page".
2573
+ function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) {
2574
+ if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) {
2575
+ var size = widgetHeight(lineObj.widgets[i])
2576
+ rect.top += size; rect.bottom += size
2577
+ } } }
2578
+ if (context == "line") { return rect }
2579
+ if (!context) { context = "local" }
2580
+ var yOff = heightAtLine(lineObj)
2581
+ if (context == "local") { yOff += paddingTop(cm.display) }
2582
+ else { yOff -= cm.display.viewOffset }
2583
+ if (context == "page" || context == "window") {
2584
+ var lOff = cm.display.lineSpace.getBoundingClientRect()
2585
+ yOff += lOff.top + (context == "window" ? 0 : pageScrollY())
2586
+ var xOff = lOff.left + (context == "window" ? 0 : pageScrollX())
2587
+ rect.left += xOff; rect.right += xOff
2588
+ }
2589
+ rect.top += yOff; rect.bottom += yOff
2590
+ return rect
2591
+ }
2592
+
2593
+ // Coverts a box from "div" coords to another coordinate system.
2594
+ // Context may be "window", "page", "div", or "local"./null.
2595
+ function fromCoordSystem(cm, coords, context) {
2596
+ if (context == "div") { return coords }
2597
+ var left = coords.left, top = coords.top
2598
+ // First move into "page" coordinate system
2599
+ if (context == "page") {
2600
+ left -= pageScrollX()
2601
+ top -= pageScrollY()
2602
+ } else if (context == "local" || !context) {
2603
+ var localBox = cm.display.sizer.getBoundingClientRect()
2604
+ left += localBox.left
2605
+ top += localBox.top
2606
+ }
2607
+
2608
+ var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect()
2609
+ return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top}
2610
+ }
2611
+
2612
+ function charCoords(cm, pos, context, lineObj, bias) {
2613
+ if (!lineObj) { lineObj = getLine(cm.doc, pos.line) }
2614
+ return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context)
2615
+ }
2616
+
2617
+ // Returns a box for a given cursor position, which may have an
2618
+ // 'other' property containing the position of the secondary cursor
2619
+ // on a bidi boundary.
2620
+ function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) {
2621
+ lineObj = lineObj || getLine(cm.doc, pos.line)
2622
+ if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) }
2623
+ function get(ch, right) {
2624
+ var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight)
2625
+ if (right) { m.left = m.right; } else { m.right = m.left }
2626
+ return intoCoordSystem(cm, lineObj, m, context)
2627
+ }
2628
+ function getBidi(ch, partPos) {
2629
+ var part = order[partPos], right = part.level % 2
2630
+ if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) {
2631
+ part = order[--partPos]
2632
+ ch = bidiRight(part) - (part.level % 2 ? 0 : 1)
2633
+ right = true
2634
+ } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) {
2635
+ part = order[++partPos]
2636
+ ch = bidiLeft(part) - part.level % 2
2637
+ right = false
2638
+ }
2639
+ if (right && ch == part.to && ch > part.from) { return get(ch - 1) }
2640
+ return get(ch, right)
2641
+ }
2642
+ var order = getOrder(lineObj), ch = pos.ch
2643
+ if (!order) { return get(ch) }
2644
+ var partPos = getBidiPartAt(order, ch)
2645
+ var val = getBidi(ch, partPos)
2646
+ if (bidiOther != null) { val.other = getBidi(ch, bidiOther) }
2647
+ return val
2648
+ }
2649
+
2650
+ // Used to cheaply estimate the coordinates for a position. Used for
2651
+ // intermediate scroll updates.
2652
+ function estimateCoords(cm, pos) {
2653
+ var left = 0
2654
+ pos = clipPos(cm.doc, pos)
2655
+ if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch }
2656
+ var lineObj = getLine(cm.doc, pos.line)
2657
+ var top = heightAtLine(lineObj) + paddingTop(cm.display)
2658
+ return {left: left, right: left, top: top, bottom: top + lineObj.height}
2659
+ }
2660
+
2661
+ // Positions returned by coordsChar contain some extra information.
2662
+ // xRel is the relative x position of the input coordinates compared
2663
+ // to the found position (so xRel > 0 means the coordinates are to
2664
+ // the right of the character position, for example). When outside
2665
+ // is true, that means the coordinates lie outside the line's
2666
+ // vertical range.
2667
+ function PosWithInfo(line, ch, outside, xRel) {
2668
+ var pos = Pos(line, ch)
2669
+ pos.xRel = xRel
2670
+ if (outside) { pos.outside = true }
2671
+ return pos
2672
+ }
2673
+
2674
+ // Compute the character position closest to the given coordinates.
2675
+ // Input must be lineSpace-local ("div" coordinate system).
2676
+ function coordsChar(cm, x, y) {
2677
+ var doc = cm.doc
2678
+ y += cm.display.viewOffset
2679
+ if (y < 0) { return PosWithInfo(doc.first, 0, true, -1) }
2680
+ var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1
2681
+ if (lineN > last)
2682
+ { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1) }
2683
+ if (x < 0) { x = 0 }
2684
+
2685
+ var lineObj = getLine(doc, lineN)
2686
+ for (;;) {
2687
+ var found = coordsCharInner(cm, lineObj, lineN, x, y)
2688
+ var merged = collapsedSpanAtEnd(lineObj)
2689
+ var mergedPos = merged && merged.find(0, true)
2690
+ if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0))
2691
+ { lineN = lineNo(lineObj = mergedPos.to.line) }
2692
+ else
2693
+ { return found }
2694
+ }
2695
+ }
2696
+
2697
+ function coordsCharInner(cm, lineObj, lineNo, x, y) {
2698
+ var innerOff = y - heightAtLine(lineObj)
2699
+ var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth
2700
+ var preparedMeasure = prepareMeasureForLine(cm, lineObj)
2701
+
2702
+ function getX(ch) {
2703
+ var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure)
2704
+ wrongLine = true
2705
+ if (innerOff > sp.bottom) { return sp.left - adjust }
2706
+ else if (innerOff < sp.top) { return sp.left + adjust }
2707
+ else { wrongLine = false }
2708
+ return sp.left
2709
+ }
2710
+
2711
+ var bidi = getOrder(lineObj), dist = lineObj.text.length
2712
+ var from = lineLeft(lineObj), to = lineRight(lineObj)
2713
+ var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine
2714
+
2715
+ if (x > toX) { return PosWithInfo(lineNo, to, toOutside, 1) }
2716
+ // Do a binary search between these bounds.
2717
+ for (;;) {
2718
+ if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) {
2719
+ var ch = x < fromX || x - fromX <= toX - x ? from : to
2720
+ var outside = ch == from ? fromOutside : toOutside
2721
+ var xDiff = x - (ch == from ? fromX : toX)
2722
+ // This is a kludge to handle the case where the coordinates
2723
+ // are after a line-wrapped line. We should replace it with a
2724
+ // more general handling of cursor positions around line
2725
+ // breaks. (Issue #4078)
2726
+ if (toOutside && !bidi && !/\s/.test(lineObj.text.charAt(ch)) && xDiff > 0 &&
2727
+ ch < lineObj.text.length && preparedMeasure.view.measure.heights.length > 1) {
2728
+ var charSize = measureCharPrepared(cm, preparedMeasure, ch, "right")
2729
+ if (innerOff <= charSize.bottom && innerOff >= charSize.top && Math.abs(x - charSize.right) < xDiff) {
2730
+ outside = false
2731
+ ch++
2732
+ xDiff = x - charSize.right
2733
+ }
2734
+ }
2735
+ while (isExtendingChar(lineObj.text.charAt(ch))) { ++ch }
2736
+ var pos = PosWithInfo(lineNo, ch, outside, xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0)
2737
+ return pos
2738
+ }
2739
+ var step = Math.ceil(dist / 2), middle = from + step
2740
+ if (bidi) {
2741
+ middle = from
2742
+ for (var i = 0; i < step; ++i) { middle = moveVisually(lineObj, middle, 1) }
2743
+ }
2744
+ var middleX = getX(middle)
2745
+ if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) { toX += 1000; } dist = step}
2746
+ else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step}
2747
+ }
2748
+ }
2749
+
2750
+ var measureText
2751
+ // Compute the default text height.
2752
+ function textHeight(display) {
2753
+ if (display.cachedTextHeight != null) { return display.cachedTextHeight }
2754
+ if (measureText == null) {
2755
+ measureText = elt("pre")
2756
+ // Measure a bunch of lines, for browsers that compute
2757
+ // fractional heights.
2758
+ for (var i = 0; i < 49; ++i) {
2759
+ measureText.appendChild(document.createTextNode("x"))
2760
+ measureText.appendChild(elt("br"))
2761
+ }
2762
+ measureText.appendChild(document.createTextNode("x"))
2763
+ }
2764
+ removeChildrenAndAdd(display.measure, measureText)
2765
+ var height = measureText.offsetHeight / 50
2766
+ if (height > 3) { display.cachedTextHeight = height }
2767
+ removeChildren(display.measure)
2768
+ return height || 1
2769
+ }
2770
+
2771
+ // Compute the default character width.
2772
+ function charWidth(display) {
2773
+ if (display.cachedCharWidth != null) { return display.cachedCharWidth }
2774
+ var anchor = elt("span", "xxxxxxxxxx")
2775
+ var pre = elt("pre", [anchor])
2776
+ removeChildrenAndAdd(display.measure, pre)
2777
+ var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10
2778
+ if (width > 2) { display.cachedCharWidth = width }
2779
+ return width || 10
2780
+ }
2781
+
2782
+ // Do a bulk-read of the DOM positions and sizes needed to draw the
2783
+ // view, so that we don't interleave reading and writing to the DOM.
2784
+ function getDimensions(cm) {
2785
+ var d = cm.display, left = {}, width = {}
2786
+ var gutterLeft = d.gutters.clientLeft
2787
+ for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) {
2788
+ left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft
2789
+ width[cm.options.gutters[i]] = n.clientWidth
2790
+ }
2791
+ return {fixedPos: compensateForHScroll(d),
2792
+ gutterTotalWidth: d.gutters.offsetWidth,
2793
+ gutterLeft: left,
2794
+ gutterWidth: width,
2795
+ wrapperWidth: d.wrapper.clientWidth}
2796
+ }
2797
+
2798
+ // Computes display.scroller.scrollLeft + display.gutters.offsetWidth,
2799
+ // but using getBoundingClientRect to get a sub-pixel-accurate
2800
+ // result.
2801
+ function compensateForHScroll(display) {
2802
+ return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left
2803
+ }
2804
+
2805
+ // Returns a function that estimates the height of a line, to use as
2806
+ // first approximation until the line becomes visible (and is thus
2807
+ // properly measurable).
2808
+ function estimateHeight(cm) {
2809
+ var th = textHeight(cm.display), wrapping = cm.options.lineWrapping
2810
+ var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3)
2811
+ return function (line) {
2812
+ if (lineIsHidden(cm.doc, line)) { return 0 }
2813
+
2814
+ var widgetsHeight = 0
2815
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) {
2816
+ if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height }
2817
+ } }
2818
+
2819
+ if (wrapping)
2820
+ { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th }
2821
+ else
2822
+ { return widgetsHeight + th }
2823
+ }
2824
+ }
2825
+
2826
+ function estimateLineHeights(cm) {
2827
+ var doc = cm.doc, est = estimateHeight(cm)
2828
+ doc.iter(function (line) {
2829
+ var estHeight = est(line)
2830
+ if (estHeight != line.height) { updateLineHeight(line, estHeight) }
2831
+ })
2832
+ }
2833
+
2834
+ // Given a mouse event, find the corresponding position. If liberal
2835
+ // is false, it checks whether a gutter or scrollbar was clicked,
2836
+ // and returns null if it was. forRect is used by rectangular
2837
+ // selections, and tries to estimate a character position even for
2838
+ // coordinates beyond the right of the text.
2839
+ function posFromMouse(cm, e, liberal, forRect) {
2840
+ var display = cm.display
2841
+ if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null }
2842
+
2843
+ var x, y, space = display.lineSpace.getBoundingClientRect()
2844
+ // Fails unpredictably on IE[67] when mouse is dragged around quickly.
2845
+ try { x = e.clientX - space.left; y = e.clientY - space.top }
2846
+ catch (e) { return null }
2847
+ var coords = coordsChar(cm, x, y), line
2848
+ if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) {
2849
+ var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length
2850
+ coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff))
2851
+ }
2852
+ return coords
2853
+ }
2854
+
2855
+ // Find the view element corresponding to a given line. Return null
2856
+ // when the line isn't visible.
2857
+ function findViewIndex(cm, n) {
2858
+ if (n >= cm.display.viewTo) { return null }
2859
+ n -= cm.display.viewFrom
2860
+ if (n < 0) { return null }
2861
+ var view = cm.display.view
2862
+ for (var i = 0; i < view.length; i++) {
2863
+ n -= view[i].size
2864
+ if (n < 0) { return i }
2865
+ }
2866
+ }
2867
+
2868
+ function updateSelection(cm) {
2869
+ cm.display.input.showSelection(cm.display.input.prepareSelection())
2870
+ }
2871
+
2872
+ function prepareSelection(cm, primary) {
2873
+ var doc = cm.doc, result = {}
2874
+ var curFragment = result.cursors = document.createDocumentFragment()
2875
+ var selFragment = result.selection = document.createDocumentFragment()
2876
+
2877
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
2878
+ if (primary === false && i == doc.sel.primIndex) { continue }
2879
+ var range = doc.sel.ranges[i]
2880
+ if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue }
2881
+ var collapsed = range.empty()
2882
+ if (collapsed || cm.options.showCursorWhenSelecting)
2883
+ { drawSelectionCursor(cm, range.head, curFragment) }
2884
+ if (!collapsed)
2885
+ { drawSelectionRange(cm, range, selFragment) }
2886
+ }
2887
+ return result
2888
+ }
2889
+
2890
+ // Draws a cursor for the given range
2891
+ function drawSelectionCursor(cm, head, output) {
2892
+ var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine)
2893
+
2894
+ var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor"))
2895
+ cursor.style.left = pos.left + "px"
2896
+ cursor.style.top = pos.top + "px"
2897
+ cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"
2898
+
2899
+ if (pos.other) {
2900
+ // Secondary cursor, shown when on a 'jump' in bi-directional text
2901
+ var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor"))
2902
+ otherCursor.style.display = ""
2903
+ otherCursor.style.left = pos.other.left + "px"
2904
+ otherCursor.style.top = pos.other.top + "px"
2905
+ otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"
2906
+ }
2907
+ }
2908
+
2909
+ // Draws the given range as a highlighted selection
2910
+ function drawSelectionRange(cm, range, output) {
2911
+ var display = cm.display, doc = cm.doc
2912
+ var fragment = document.createDocumentFragment()
2913
+ var padding = paddingH(cm.display), leftSide = padding.left
2914
+ var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right
2915
+
2916
+ function add(left, top, width, bottom) {
2917
+ if (top < 0) { top = 0 }
2918
+ top = Math.round(top)
2919
+ bottom = Math.round(bottom)
2920
+ fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px")))
2921
+ }
2922
+
2923
+ function drawForLine(line, fromArg, toArg) {
2924
+ var lineObj = getLine(doc, line)
2925
+ var lineLen = lineObj.text.length
2926
+ var start, end
2927
+ function coords(ch, bias) {
2928
+ return charCoords(cm, Pos(line, ch), "div", lineObj, bias)
2929
+ }
2930
+
2931
+ iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) {
2932
+ var leftPos = coords(from, "left"), rightPos, left, right
2933
+ if (from == to) {
2934
+ rightPos = leftPos
2935
+ left = right = leftPos.left
2936
+ } else {
2937
+ rightPos = coords(to - 1, "right")
2938
+ if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp }
2939
+ left = leftPos.left
2940
+ right = rightPos.right
2941
+ }
2942
+ if (fromArg == null && from == 0) { left = leftSide }
2943
+ if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part
2944
+ add(left, leftPos.top, null, leftPos.bottom)
2945
+ left = leftSide
2946
+ if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top) }
2947
+ }
2948
+ if (toArg == null && to == lineLen) { right = rightSide }
2949
+ if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left)
2950
+ { start = leftPos }
2951
+ if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right)
2952
+ { end = rightPos }
2953
+ if (left < leftSide + 1) { left = leftSide }
2954
+ add(left, rightPos.top, right - left, rightPos.bottom)
2955
+ })
2956
+ return {start: start, end: end}
2957
+ }
2958
+
2959
+ var sFrom = range.from(), sTo = range.to()
2960
+ if (sFrom.line == sTo.line) {
2961
+ drawForLine(sFrom.line, sFrom.ch, sTo.ch)
2962
+ } else {
2963
+ var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line)
2964
+ var singleVLine = visualLine(fromLine) == visualLine(toLine)
2965
+ var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end
2966
+ var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start
2967
+ if (singleVLine) {
2968
+ if (leftEnd.top < rightStart.top - 2) {
2969
+ add(leftEnd.right, leftEnd.top, null, leftEnd.bottom)
2970
+ add(leftSide, rightStart.top, rightStart.left, rightStart.bottom)
2971
+ } else {
2972
+ add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom)
2973
+ }
2974
+ }
2975
+ if (leftEnd.bottom < rightStart.top)
2976
+ { add(leftSide, leftEnd.bottom, null, rightStart.top) }
2977
+ }
2978
+
2979
+ output.appendChild(fragment)
2980
+ }
2981
+
2982
+ // Cursor-blinking
2983
+ function restartBlink(cm) {
2984
+ if (!cm.state.focused) { return }
2985
+ var display = cm.display
2986
+ clearInterval(display.blinker)
2987
+ var on = true
2988
+ display.cursorDiv.style.visibility = ""
2989
+ if (cm.options.cursorBlinkRate > 0)
2990
+ { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; },
2991
+ cm.options.cursorBlinkRate) }
2992
+ else if (cm.options.cursorBlinkRate < 0)
2993
+ { display.cursorDiv.style.visibility = "hidden" }
2994
+ }
2995
+
2996
+ function ensureFocus(cm) {
2997
+ if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm) }
2998
+ }
2999
+
3000
+ function delayBlurEvent(cm) {
3001
+ cm.state.delayingBlurEvent = true
3002
+ setTimeout(function () { if (cm.state.delayingBlurEvent) {
3003
+ cm.state.delayingBlurEvent = false
3004
+ onBlur(cm)
3005
+ } }, 100)
3006
+ }
3007
+
3008
+ function onFocus(cm, e) {
3009
+ if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false }
3010
+
3011
+ if (cm.options.readOnly == "nocursor") { return }
3012
+ if (!cm.state.focused) {
3013
+ signal(cm, "focus", cm, e)
3014
+ cm.state.focused = true
3015
+ addClass(cm.display.wrapper, "CodeMirror-focused")
3016
+ // This test prevents this from firing when a context
3017
+ // menu is closed (since the input reset would kill the
3018
+ // select-all detection hack)
3019
+ if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) {
3020
+ cm.display.input.reset()
3021
+ if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20) } // Issue #1730
3022
+ }
3023
+ cm.display.input.receivedFocus()
3024
+ }
3025
+ restartBlink(cm)
3026
+ }
3027
+ function onBlur(cm, e) {
3028
+ if (cm.state.delayingBlurEvent) { return }
3029
+
3030
+ if (cm.state.focused) {
3031
+ signal(cm, "blur", cm, e)
3032
+ cm.state.focused = false
3033
+ rmClass(cm.display.wrapper, "CodeMirror-focused")
3034
+ }
3035
+ clearInterval(cm.display.blinker)
3036
+ setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false } }, 150)
3037
+ }
3038
+
3039
+ // Re-align line numbers and gutter marks to compensate for
3040
+ // horizontal scrolling.
3041
+ function alignHorizontally(cm) {
3042
+ var display = cm.display, view = display.view
3043
+ if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return }
3044
+ var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft
3045
+ var gutterW = display.gutters.offsetWidth, left = comp + "px"
3046
+ for (var i = 0; i < view.length; i++) { if (!view[i].hidden) {
3047
+ if (cm.options.fixedGutter) {
3048
+ if (view[i].gutter)
3049
+ { view[i].gutter.style.left = left }
3050
+ if (view[i].gutterBackground)
3051
+ { view[i].gutterBackground.style.left = left }
3052
+ }
3053
+ var align = view[i].alignable
3054
+ if (align) { for (var j = 0; j < align.length; j++)
3055
+ { align[j].style.left = left } }
3056
+ } }
3057
+ if (cm.options.fixedGutter)
3058
+ { display.gutters.style.left = (comp + gutterW) + "px" }
3059
+ }
3060
+
3061
+ // Used to ensure that the line number gutter is still the right
3062
+ // size for the current document size. Returns true when an update
3063
+ // is needed.
3064
+ function maybeUpdateLineNumberWidth(cm) {
3065
+ if (!cm.options.lineNumbers) { return false }
3066
+ var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display
3067
+ if (last.length != display.lineNumChars) {
3068
+ var test = display.measure.appendChild(elt("div", [elt("div", last)],
3069
+ "CodeMirror-linenumber CodeMirror-gutter-elt"))
3070
+ var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW
3071
+ display.lineGutter.style.width = ""
3072
+ display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1
3073
+ display.lineNumWidth = display.lineNumInnerWidth + padding
3074
+ display.lineNumChars = display.lineNumInnerWidth ? last.length : -1
3075
+ display.lineGutter.style.width = display.lineNumWidth + "px"
3076
+ updateGutterSpace(cm)
3077
+ return true
3078
+ }
3079
+ return false
3080
+ }
3081
+
3082
+ // Read the actual heights of the rendered lines, and update their
3083
+ // stored heights to match.
3084
+ function updateHeightsInViewport(cm) {
3085
+ var display = cm.display
3086
+ var prevBottom = display.lineDiv.offsetTop
3087
+ for (var i = 0; i < display.view.length; i++) {
3088
+ var cur = display.view[i], height = (void 0)
3089
+ if (cur.hidden) { continue }
3090
+ if (ie && ie_version < 8) {
3091
+ var bot = cur.node.offsetTop + cur.node.offsetHeight
3092
+ height = bot - prevBottom
3093
+ prevBottom = bot
3094
+ } else {
3095
+ var box = cur.node.getBoundingClientRect()
3096
+ height = box.bottom - box.top
3097
+ }
3098
+ var diff = cur.line.height - height
3099
+ if (height < 2) { height = textHeight(display) }
3100
+ if (diff > .001 || diff < -.001) {
3101
+ updateLineHeight(cur.line, height)
3102
+ updateWidgetHeight(cur.line)
3103
+ if (cur.rest) { for (var j = 0; j < cur.rest.length; j++)
3104
+ { updateWidgetHeight(cur.rest[j]) } }
3105
+ }
3106
+ }
3107
+ }
3108
+
3109
+ // Read and store the height of line widgets associated with the
3110
+ // given line.
3111
+ function updateWidgetHeight(line) {
3112
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i)
3113
+ { line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight } }
3114
+ }
3115
+
3116
+ // Compute the lines that are visible in a given viewport (defaults
3117
+ // the the current scroll position). viewport may contain top,
3118
+ // height, and ensure (see op.scrollToPos) properties.
3119
+ function visibleLines(display, doc, viewport) {
3120
+ var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop
3121
+ top = Math.floor(top - paddingTop(display))
3122
+ var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight
3123
+
3124
+ var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom)
3125
+ // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
3126
+ // forces those lines into the viewport (if possible).
3127
+ if (viewport && viewport.ensure) {
3128
+ var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line
3129
+ if (ensureFrom < from) {
3130
+ from = ensureFrom
3131
+ to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)
3132
+ } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
3133
+ from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight)
3134
+ to = ensureTo
3135
+ }
3136
+ }
3137
+ return {from: from, to: Math.max(to, from + 1)}
3138
+ }
3139
+
3140
+ // Sync the scrollable area and scrollbars, ensure the viewport
3141
+ // covers the visible area.
3142
+ function setScrollTop(cm, val) {
3143
+ if (Math.abs(cm.doc.scrollTop - val) < 2) { return }
3144
+ cm.doc.scrollTop = val
3145
+ if (!gecko) { updateDisplaySimple(cm, {top: val}) }
3146
+ if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val }
3147
+ cm.display.scrollbars.setScrollTop(val)
3148
+ if (gecko) { updateDisplaySimple(cm) }
3149
+ startWorker(cm, 100)
3150
+ }
3151
+ // Sync scroller and scrollbar, ensure the gutter elements are
3152
+ // aligned.
3153
+ function setScrollLeft(cm, val, isScroller) {
3154
+ if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) { return }
3155
+ val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)
3156
+ cm.doc.scrollLeft = val
3157
+ alignHorizontally(cm)
3158
+ if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val }
3159
+ cm.display.scrollbars.setScrollLeft(val)
3160
+ }
3161
+
3162
+ // Since the delta values reported on mouse wheel events are
3163
+ // unstandardized between browsers and even browser versions, and
3164
+ // generally horribly unpredictable, this code starts by measuring
3165
+ // the scroll effect that the first few mouse wheel events have,
3166
+ // and, from that, detects the way it can convert deltas to pixel
3167
+ // offsets afterwards.
3168
+ //
3169
+ // The reason we want to know the amount a wheel event will scroll
3170
+ // is that it gives us a chance to update the display before the
3171
+ // actual scrolling happens, reducing flickering.
3172
+
3173
+ var wheelSamples = 0;
3174
+ var wheelPixelsPerUnit = null;
3175
+ // Fill in a browser-detected starting value on browsers where we
3176
+ // know one. These don't have to be accurate -- the result of them
3177
+ // being wrong would just be a slight flicker on the first wheel
3178
+ // scroll (if it is large enough).
3179
+ if (ie) { wheelPixelsPerUnit = -.53 }
3180
+ else if (gecko) { wheelPixelsPerUnit = 15 }
3181
+ else if (chrome) { wheelPixelsPerUnit = -.7 }
3182
+ else if (safari) { wheelPixelsPerUnit = -1/3 }
3183
+
3184
+ function wheelEventDelta(e) {
3185
+ var dx = e.wheelDeltaX, dy = e.wheelDeltaY
3186
+ if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail }
3187
+ if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail }
3188
+ else if (dy == null) { dy = e.wheelDelta }
3189
+ return {x: dx, y: dy}
3190
+ }
3191
+ function wheelEventPixels(e) {
3192
+ var delta = wheelEventDelta(e)
3193
+ delta.x *= wheelPixelsPerUnit
3194
+ delta.y *= wheelPixelsPerUnit
3195
+ return delta
3196
+ }
3197
+
3198
+ function onScrollWheel(cm, e) {
3199
+ var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y
3200
+
3201
+ var display = cm.display, scroll = display.scroller
3202
+ // Quit if there's nothing to scroll here
3203
+ var canScrollX = scroll.scrollWidth > scroll.clientWidth
3204
+ var canScrollY = scroll.scrollHeight > scroll.clientHeight
3205
+ if (!(dx && canScrollX || dy && canScrollY)) { return }
3206
+
3207
+ // Webkit browsers on OS X abort momentum scrolls when the target
3208
+ // of the scroll event is removed from the scrollable element.
3209
+ // This hack (see related code in patchDisplay) makes sure the
3210
+ // element is kept around.
3211
+ if (dy && mac && webkit) {
3212
+ outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) {
3213
+ for (var i = 0; i < view.length; i++) {
3214
+ if (view[i].node == cur) {
3215
+ cm.display.currentWheelTarget = cur
3216
+ break outer
3217
+ }
3218
+ }
3219
+ }
3220
+ }
3221
+
3222
+ // On some browsers, horizontal scrolling will cause redraws to
3223
+ // happen before the gutter has been realigned, causing it to
3224
+ // wriggle around in a most unseemly way. When we have an
3225
+ // estimated pixels/delta value, we just handle horizontal
3226
+ // scrolling entirely here. It'll be slightly off from native, but
3227
+ // better than glitching out.
3228
+ if (dx && !gecko && !presto && wheelPixelsPerUnit != null) {
3229
+ if (dy && canScrollY)
3230
+ { setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))) }
3231
+ setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth)))
3232
+ // Only prevent default scrolling if vertical scrolling is
3233
+ // actually possible. Otherwise, it causes vertical scroll
3234
+ // jitter on OSX trackpads when deltaX is small and deltaY
3235
+ // is large (issue #3579)
3236
+ if (!dy || (dy && canScrollY))
3237
+ { e_preventDefault(e) }
3238
+ display.wheelStartX = null // Abort measurement, if in progress
3239
+ return
3240
+ }
3241
+
3242
+ // 'Project' the visible viewport to cover the area that is being
3243
+ // scrolled into view (if we know enough to estimate it).
3244
+ if (dy && wheelPixelsPerUnit != null) {
3245
+ var pixels = dy * wheelPixelsPerUnit
3246
+ var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight
3247
+ if (pixels < 0) { top = Math.max(0, top + pixels - 50) }
3248
+ else { bot = Math.min(cm.doc.height, bot + pixels + 50) }
3249
+ updateDisplaySimple(cm, {top: top, bottom: bot})
3250
+ }
3251
+
3252
+ if (wheelSamples < 20) {
3253
+ if (display.wheelStartX == null) {
3254
+ display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop
3255
+ display.wheelDX = dx; display.wheelDY = dy
3256
+ setTimeout(function () {
3257
+ if (display.wheelStartX == null) { return }
3258
+ var movedX = scroll.scrollLeft - display.wheelStartX
3259
+ var movedY = scroll.scrollTop - display.wheelStartY
3260
+ var sample = (movedY && display.wheelDY && movedY / display.wheelDY) ||
3261
+ (movedX && display.wheelDX && movedX / display.wheelDX)
3262
+ display.wheelStartX = display.wheelStartY = null
3263
+ if (!sample) { return }
3264
+ wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1)
3265
+ ++wheelSamples
3266
+ }, 200)
3267
+ } else {
3268
+ display.wheelDX += dx; display.wheelDY += dy
3269
+ }
3270
+ }
3271
+ }
3272
+
3273
+ // SCROLLBARS
3274
+
3275
+ // Prepare DOM reads needed to update the scrollbars. Done in one
3276
+ // shot to minimize update/measure roundtrips.
3277
+ function measureForScrollbars(cm) {
3278
+ var d = cm.display, gutterW = d.gutters.offsetWidth
3279
+ var docH = Math.round(cm.doc.height + paddingVert(cm.display))
3280
+ return {
3281
+ clientHeight: d.scroller.clientHeight,
3282
+ viewHeight: d.wrapper.clientHeight,
3283
+ scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth,
3284
+ viewWidth: d.wrapper.clientWidth,
3285
+ barLeft: cm.options.fixedGutter ? gutterW : 0,
3286
+ docHeight: docH,
3287
+ scrollHeight: docH + scrollGap(cm) + d.barHeight,
3288
+ nativeBarWidth: d.nativeBarWidth,
3289
+ gutterWidth: gutterW
3290
+ }
3291
+ }
3292
+
3293
+ var NativeScrollbars = function(place, scroll, cm) {
3294
+ this.cm = cm
3295
+ var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar")
3296
+ var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar")
3297
+ place(vert); place(horiz)
3298
+
3299
+ on(vert, "scroll", function () {
3300
+ if (vert.clientHeight) { scroll(vert.scrollTop, "vertical") }
3301
+ })
3302
+ on(horiz, "scroll", function () {
3303
+ if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal") }
3304
+ })
3305
+
3306
+ this.checkedZeroWidth = false
3307
+ // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8).
3308
+ if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px" }
3309
+ };
3310
+
3311
+ NativeScrollbars.prototype.update = function (measure) {
3312
+ var needsH = measure.scrollWidth > measure.clientWidth + 1
3313
+ var needsV = measure.scrollHeight > measure.clientHeight + 1
3314
+ var sWidth = measure.nativeBarWidth
3315
+
3316
+ if (needsV) {
3317
+ this.vert.style.display = "block"
3318
+ this.vert.style.bottom = needsH ? sWidth + "px" : "0"
3319
+ var totalHeight = measure.viewHeight - (needsH ? sWidth : 0)
3320
+ // A bug in IE8 can cause this value to be negative, so guard it.
3321
+ this.vert.firstChild.style.height =
3322
+ Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"
3323
+ } else {
3324
+ this.vert.style.display = ""
3325
+ this.vert.firstChild.style.height = "0"
3326
+ }
3327
+
3328
+ if (needsH) {
3329
+ this.horiz.style.display = "block"
3330
+ this.horiz.style.right = needsV ? sWidth + "px" : "0"
3331
+ this.horiz.style.left = measure.barLeft + "px"
3332
+ var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0)
3333
+ this.horiz.firstChild.style.width =
3334
+ (measure.scrollWidth - measure.clientWidth + totalWidth) + "px"
3335
+ } else {
3336
+ this.horiz.style.display = ""
3337
+ this.horiz.firstChild.style.width = "0"
3338
+ }
3339
+
3340
+ if (!this.checkedZeroWidth && measure.clientHeight > 0) {
3341
+ if (sWidth == 0) { this.zeroWidthHack() }
3342
+ this.checkedZeroWidth = true
3343
+ }
3344
+
3345
+ return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0}
3346
+ };
3347
+
3348
+ NativeScrollbars.prototype.setScrollLeft = function (pos) {
3349
+ if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos }
3350
+ if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz) }
3351
+ };
3352
+
3353
+ NativeScrollbars.prototype.setScrollTop = function (pos) {
3354
+ if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos }
3355
+ if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert) }
3356
+ };
3357
+
3358
+ NativeScrollbars.prototype.zeroWidthHack = function () {
3359
+ var w = mac && !mac_geMountainLion ? "12px" : "18px"
3360
+ this.horiz.style.height = this.vert.style.width = w
3361
+ this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"
3362
+ this.disableHoriz = new Delayed
3363
+ this.disableVert = new Delayed
3364
+ };
3365
+
3366
+ NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay) {
3367
+ bar.style.pointerEvents = "auto"
3368
+ function maybeDisable() {
3369
+ // To find out whether the scrollbar is still visible, we
3370
+ // check whether the element under the pixel in the bottom
3371
+ // left corner of the scrollbar box is the scrollbar box
3372
+ // itself (when the bar is still visible) or its filler child
3373
+ // (when the bar is hidden). If it is still visible, we keep
3374
+ // it enabled, if it's hidden, we disable pointer events.
3375
+ var box = bar.getBoundingClientRect()
3376
+ var elt = document.elementFromPoint(box.left + 1, box.bottom - 1)
3377
+ if (elt != bar) { bar.style.pointerEvents = "none" }
3378
+ else { delay.set(1000, maybeDisable) }
3379
+ }
3380
+ delay.set(1000, maybeDisable)
3381
+ };
3382
+
3383
+ NativeScrollbars.prototype.clear = function () {
3384
+ var parent = this.horiz.parentNode
3385
+ parent.removeChild(this.horiz)
3386
+ parent.removeChild(this.vert)
3387
+ };
3388
+
3389
+ var NullScrollbars = function () {};
3390
+
3391
+ NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} };
3392
+ NullScrollbars.prototype.setScrollLeft = function () {};
3393
+ NullScrollbars.prototype.setScrollTop = function () {};
3394
+ NullScrollbars.prototype.clear = function () {};
3395
+
3396
+ function updateScrollbars(cm, measure) {
3397
+ if (!measure) { measure = measureForScrollbars(cm) }
3398
+ var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight
3399
+ updateScrollbarsInner(cm, measure)
3400
+ for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) {
3401
+ if (startWidth != cm.display.barWidth && cm.options.lineWrapping)
3402
+ { updateHeightsInViewport(cm) }
3403
+ updateScrollbarsInner(cm, measureForScrollbars(cm))
3404
+ startWidth = cm.display.barWidth; startHeight = cm.display.barHeight
3405
+ }
3406
+ }
3407
+
3408
+ // Re-synchronize the fake scrollbars with the actual size of the
3409
+ // content.
3410
+ function updateScrollbarsInner(cm, measure) {
3411
+ var d = cm.display
3412
+ var sizes = d.scrollbars.update(measure)
3413
+
3414
+ d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"
3415
+ d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"
3416
+ d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"
3417
+
3418
+ if (sizes.right && sizes.bottom) {
3419
+ d.scrollbarFiller.style.display = "block"
3420
+ d.scrollbarFiller.style.height = sizes.bottom + "px"
3421
+ d.scrollbarFiller.style.width = sizes.right + "px"
3422
+ } else { d.scrollbarFiller.style.display = "" }
3423
+ if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) {
3424
+ d.gutterFiller.style.display = "block"
3425
+ d.gutterFiller.style.height = sizes.bottom + "px"
3426
+ d.gutterFiller.style.width = measure.gutterWidth + "px"
3427
+ } else { d.gutterFiller.style.display = "" }
3428
+ }
3429
+
3430
+ var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}
3431
+
3432
+ function initScrollbars(cm) {
3433
+ if (cm.display.scrollbars) {
3434
+ cm.display.scrollbars.clear()
3435
+ if (cm.display.scrollbars.addClass)
3436
+ { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass) }
3437
+ }
3438
+
3439
+ cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) {
3440
+ cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller)
3441
+ // Prevent clicks in the scrollbars from killing focus
3442
+ on(node, "mousedown", function () {
3443
+ if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0) }
3444
+ })
3445
+ node.setAttribute("cm-not-content", "true")
3446
+ }, function (pos, axis) {
3447
+ if (axis == "horizontal") { setScrollLeft(cm, pos) }
3448
+ else { setScrollTop(cm, pos) }
3449
+ }, cm)
3450
+ if (cm.display.scrollbars.addClass)
3451
+ { addClass(cm.display.wrapper, cm.display.scrollbars.addClass) }
3452
+ }
3453
+
3454
+ // SCROLLING THINGS INTO VIEW
3455
+
3456
+ // If an editor sits on the top or bottom of the window, partially
3457
+ // scrolled out of view, this ensures that the cursor is visible.
3458
+ function maybeScrollWindow(cm, coords) {
3459
+ if (signalDOMEvent(cm, "scrollCursorIntoView")) { return }
3460
+
3461
+ var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null
3462
+ if (coords.top + box.top < 0) { doScroll = true }
3463
+ else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false }
3464
+ if (doScroll != null && !phantom) {
3465
+ var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (coords.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (coords.left) + "px; width: 2px;"))
3466
+ cm.display.lineSpace.appendChild(scrollNode)
3467
+ scrollNode.scrollIntoView(doScroll)
3468
+ cm.display.lineSpace.removeChild(scrollNode)
3469
+ }
3470
+ }
3471
+
3472
+ // Scroll a given position into view (immediately), verifying that
3473
+ // it actually became visible (as line heights are accurately
3474
+ // measured, the position of something may 'drift' during drawing).
3475
+ function scrollPosIntoView(cm, pos, end, margin) {
3476
+ if (margin == null) { margin = 0 }
3477
+ var coords
3478
+ for (var limit = 0; limit < 5; limit++) {
3479
+ var changed = false
3480
+ coords = cursorCoords(cm, pos)
3481
+ var endCoords = !end || end == pos ? coords : cursorCoords(cm, end)
3482
+ var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left),
3483
+ Math.min(coords.top, endCoords.top) - margin,
3484
+ Math.max(coords.left, endCoords.left),
3485
+ Math.max(coords.bottom, endCoords.bottom) + margin)
3486
+ var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft
3487
+ if (scrollPos.scrollTop != null) {
3488
+ setScrollTop(cm, scrollPos.scrollTop)
3489
+ if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true }
3490
+ }
3491
+ if (scrollPos.scrollLeft != null) {
3492
+ setScrollLeft(cm, scrollPos.scrollLeft)
3493
+ if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true }
3494
+ }
3495
+ if (!changed) { break }
3496
+ }
3497
+ return coords
3498
+ }
3499
+
3500
+ // Scroll a given set of coordinates into view (immediately).
3501
+ function scrollIntoView(cm, x1, y1, x2, y2) {
3502
+ var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2)
3503
+ if (scrollPos.scrollTop != null) { setScrollTop(cm, scrollPos.scrollTop) }
3504
+ if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft) }
3505
+ }
3506
+
3507
+ // Calculate a new scroll position needed to scroll the given
3508
+ // rectangle into view. Returns an object with scrollTop and
3509
+ // scrollLeft properties. When these are undefined, the
3510
+ // vertical/horizontal position does not need to be adjusted.
3511
+ function calculateScrollPos(cm, x1, y1, x2, y2) {
3512
+ var display = cm.display, snapMargin = textHeight(cm.display)
3513
+ if (y1 < 0) { y1 = 0 }
3514
+ var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop
3515
+ var screen = displayHeight(cm), result = {}
3516
+ if (y2 - y1 > screen) { y2 = y1 + screen }
3517
+ var docBottom = cm.doc.height + paddingVert(display)
3518
+ var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin
3519
+ if (y1 < screentop) {
3520
+ result.scrollTop = atTop ? 0 : y1
3521
+ } else if (y2 > screentop + screen) {
3522
+ var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen)
3523
+ if (newTop != screentop) { result.scrollTop = newTop }
3524
+ }
3525
+
3526
+ var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft
3527
+ var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0)
3528
+ var tooWide = x2 - x1 > screenw
3529
+ if (tooWide) { x2 = x1 + screenw }
3530
+ if (x1 < 10)
3531
+ { result.scrollLeft = 0 }
3532
+ else if (x1 < screenleft)
3533
+ { result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)) }
3534
+ else if (x2 > screenw + screenleft - 3)
3535
+ { result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw }
3536
+ return result
3537
+ }
3538
+
3539
+ // Store a relative adjustment to the scroll position in the current
3540
+ // operation (to be applied when the operation finishes).
3541
+ function addToScrollPos(cm, left, top) {
3542
+ if (left != null || top != null) { resolveScrollToPos(cm) }
3543
+ if (left != null)
3544
+ { cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left }
3545
+ if (top != null)
3546
+ { cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top }
3547
+ }
3548
+
3549
+ // Make sure that at the end of the operation the current cursor is
3550
+ // shown.
3551
+ function ensureCursorVisible(cm) {
3552
+ resolveScrollToPos(cm)
3553
+ var cur = cm.getCursor(), from = cur, to = cur
3554
+ if (!cm.options.lineWrapping) {
3555
+ from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur
3556
+ to = Pos(cur.line, cur.ch + 1)
3557
+ }
3558
+ cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true}
3559
+ }
3560
+
3561
+ // When an operation has its scrollToPos property set, and another
3562
+ // scroll action is applied before the end of the operation, this
3563
+ // 'simulates' scrolling that position into view in a cheap way, so
3564
+ // that the effect of intermediate scroll commands is not ignored.
3565
+ function resolveScrollToPos(cm) {
3566
+ var range = cm.curOp.scrollToPos
3567
+ if (range) {
3568
+ cm.curOp.scrollToPos = null
3569
+ var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to)
3570
+ var sPos = calculateScrollPos(cm, Math.min(from.left, to.left),
3571
+ Math.min(from.top, to.top) - range.margin,
3572
+ Math.max(from.right, to.right),
3573
+ Math.max(from.bottom, to.bottom) + range.margin)
3574
+ cm.scrollTo(sPos.scrollLeft, sPos.scrollTop)
3575
+ }
3576
+ }
3577
+
3578
+ // Operations are used to wrap a series of changes to the editor
3579
+ // state in such a way that each change won't have to update the
3580
+ // cursor and display (which would be awkward, slow, and
3581
+ // error-prone). Instead, display updates are batched and then all
3582
+ // combined and executed at once.
3583
+
3584
+ var nextOpId = 0
3585
+ // Start a new operation.
3586
+ function startOperation(cm) {
3587
+ cm.curOp = {
3588
+ cm: cm,
3589
+ viewChanged: false, // Flag that indicates that lines might need to be redrawn
3590
+ startHeight: cm.doc.height, // Used to detect need to update scrollbar
3591
+ forceUpdate: false, // Used to force a redraw
3592
+ updateInput: null, // Whether to reset the input textarea
3593
+ typing: false, // Whether this reset should be careful to leave existing text (for compositing)
3594
+ changeObjs: null, // Accumulated changes, for firing change events
3595
+ cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on
3596
+ cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already
3597
+ selectionChanged: false, // Whether the selection needs to be redrawn
3598
+ updateMaxLine: false, // Set when the widest line needs to be determined anew
3599
+ scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
3600
+ scrollToPos: null, // Used to scroll to a specific position
3601
+ focus: false,
3602
+ id: ++nextOpId // Unique ID
3603
+ }
3604
+ pushOperation(cm.curOp)
3605
+ }
3606
+
3607
+ // Finish an operation, updating the display and signalling delayed events
3608
+ function endOperation(cm) {
3609
+ var op = cm.curOp
3610
+ finishOperation(op, function (group) {
3611
+ for (var i = 0; i < group.ops.length; i++)
3612
+ { group.ops[i].cm.curOp = null }
3613
+ endOperations(group)
3614
+ })
3615
+ }
3616
+
3617
+ // The DOM updates done when an operation finishes are batched so
3618
+ // that the minimum number of relayouts are required.
3619
+ function endOperations(group) {
3620
+ var ops = group.ops
3621
+ for (var i = 0; i < ops.length; i++) // Read DOM
3622
+ { endOperation_R1(ops[i]) }
3623
+ for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe)
3624
+ { endOperation_W1(ops[i$1]) }
3625
+ for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM
3626
+ { endOperation_R2(ops[i$2]) }
3627
+ for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe)
3628
+ { endOperation_W2(ops[i$3]) }
3629
+ for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM
3630
+ { endOperation_finish(ops[i$4]) }
3631
+ }
3632
+
3633
+ function endOperation_R1(op) {
3634
+ var cm = op.cm, display = cm.display
3635
+ maybeClipScrollbars(cm)
3636
+ if (op.updateMaxLine) { findMaxLine(cm) }
3637
+
3638
+ op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null ||
3639
+ op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom ||
3640
+ op.scrollToPos.to.line >= display.viewTo) ||
3641
+ display.maxLineChanged && cm.options.lineWrapping
3642
+ op.update = op.mustUpdate &&
3643
+ new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate)
3644
+ }
3645
+
3646
+ function endOperation_W1(op) {
3647
+ op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update)
3648
+ }
3649
+
3650
+ function endOperation_R2(op) {
3651
+ var cm = op.cm, display = cm.display
3652
+ if (op.updatedDisplay) { updateHeightsInViewport(cm) }
3653
+
3654
+ op.barMeasure = measureForScrollbars(cm)
3655
+
3656
+ // If the max line changed since it was last measured, measure it,
3657
+ // and ensure the document's width matches it.
3658
+ // updateDisplay_W2 will use these properties to do the actual resizing
3659
+ if (display.maxLineChanged && !cm.options.lineWrapping) {
3660
+ op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3
3661
+ cm.display.sizerWidth = op.adjustWidthTo
3662
+ op.barMeasure.scrollWidth =
3663
+ Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth)
3664
+ op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm))
3665
+ }
3666
+
3667
+ if (op.updatedDisplay || op.selectionChanged)
3668
+ { op.preparedSelection = display.input.prepareSelection(op.focus) }
3669
+ }
3670
+
3671
+ function endOperation_W2(op) {
3672
+ var cm = op.cm
3673
+
3674
+ if (op.adjustWidthTo != null) {
3675
+ cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"
3676
+ if (op.maxScrollLeft < cm.doc.scrollLeft)
3677
+ { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) }
3678
+ cm.display.maxLineChanged = false
3679
+ }
3680
+
3681
+ var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus())
3682
+ if (op.preparedSelection)
3683
+ { cm.display.input.showSelection(op.preparedSelection, takeFocus) }
3684
+ if (op.updatedDisplay || op.startHeight != cm.doc.height)
3685
+ { updateScrollbars(cm, op.barMeasure) }
3686
+ if (op.updatedDisplay)
3687
+ { setDocumentHeight(cm, op.barMeasure) }
3688
+
3689
+ if (op.selectionChanged) { restartBlink(cm) }
3690
+
3691
+ if (cm.state.focused && op.updateInput)
3692
+ { cm.display.input.reset(op.typing) }
3693
+ if (takeFocus) { ensureFocus(op.cm) }
3694
+ }
3695
+
3696
+ function endOperation_finish(op) {
3697
+ var cm = op.cm, display = cm.display, doc = cm.doc
3698
+
3699
+ if (op.updatedDisplay) { postUpdateDisplay(cm, op.update) }
3700
+
3701
+ // Abort mouse wheel delta measurement, when scrolling explicitly
3702
+ if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos))
3703
+ { display.wheelStartX = display.wheelStartY = null }
3704
+
3705
+ // Propagate the scroll position to the actual DOM scroller
3706
+ if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) {
3707
+ doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop))
3708
+ display.scrollbars.setScrollTop(doc.scrollTop)
3709
+ display.scroller.scrollTop = doc.scrollTop
3710
+ }
3711
+ if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) {
3712
+ doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft))
3713
+ display.scrollbars.setScrollLeft(doc.scrollLeft)
3714
+ display.scroller.scrollLeft = doc.scrollLeft
3715
+ alignHorizontally(cm)
3716
+ }
3717
+ // If we need to scroll a specific position into view, do so.
3718
+ if (op.scrollToPos) {
3719
+ var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from),
3720
+ clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin)
3721
+ if (op.scrollToPos.isCursor && cm.state.focused) { maybeScrollWindow(cm, coords) }
3722
+ }
3723
+
3724
+ // Fire events for markers that are hidden/unidden by editing or
3725
+ // undoing
3726
+ var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers
3727
+ if (hidden) { for (var i = 0; i < hidden.length; ++i)
3728
+ { if (!hidden[i].lines.length) { signal(hidden[i], "hide") } } }
3729
+ if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1)
3730
+ { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide") } } }
3731
+
3732
+ if (display.wrapper.offsetHeight)
3733
+ { doc.scrollTop = cm.display.scroller.scrollTop }
3734
+
3735
+ // Fire change events, and delayed event handlers
3736
+ if (op.changeObjs)
3737
+ { signal(cm, "changes", cm, op.changeObjs) }
3738
+ if (op.update)
3739
+ { op.update.finish() }
3740
+ }
3741
+
3742
+ // Run the given function in an operation
3743
+ function runInOp(cm, f) {
3744
+ if (cm.curOp) { return f() }
3745
+ startOperation(cm)
3746
+ try { return f() }
3747
+ finally { endOperation(cm) }
3748
+ }
3749
+ // Wraps a function in an operation. Returns the wrapped function.
3750
+ function operation(cm, f) {
3751
+ return function() {
3752
+ if (cm.curOp) { return f.apply(cm, arguments) }
3753
+ startOperation(cm)
3754
+ try { return f.apply(cm, arguments) }
3755
+ finally { endOperation(cm) }
3756
+ }
3757
+ }
3758
+ // Used to add methods to editor and doc instances, wrapping them in
3759
+ // operations.
3760
+ function methodOp(f) {
3761
+ return function() {
3762
+ if (this.curOp) { return f.apply(this, arguments) }
3763
+ startOperation(this)
3764
+ try { return f.apply(this, arguments) }
3765
+ finally { endOperation(this) }
3766
+ }
3767
+ }
3768
+ function docMethodOp(f) {
3769
+ return function() {
3770
+ var cm = this.cm
3771
+ if (!cm || cm.curOp) { return f.apply(this, arguments) }
3772
+ startOperation(cm)
3773
+ try { return f.apply(this, arguments) }
3774
+ finally { endOperation(cm) }
3775
+ }
3776
+ }
3777
+
3778
+ // Updates the display.view data structure for a given change to the
3779
+ // document. From and to are in pre-change coordinates. Lendiff is
3780
+ // the amount of lines added or subtracted by the change. This is
3781
+ // used for changes that span multiple lines, or change the way
3782
+ // lines are divided into visual lines. regLineChange (below)
3783
+ // registers single-line changes.
3784
+ function regChange(cm, from, to, lendiff) {
3785
+ if (from == null) { from = cm.doc.first }
3786
+ if (to == null) { to = cm.doc.first + cm.doc.size }
3787
+ if (!lendiff) { lendiff = 0 }
3788
+
3789
+ var display = cm.display
3790
+ if (lendiff && to < display.viewTo &&
3791
+ (display.updateLineNumbers == null || display.updateLineNumbers > from))
3792
+ { display.updateLineNumbers = from }
3793
+
3794
+ cm.curOp.viewChanged = true
3795
+
3796
+ if (from >= display.viewTo) { // Change after
3797
+ if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo)
3798
+ { resetView(cm) }
3799
+ } else if (to <= display.viewFrom) { // Change before
3800
+ if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) {
3801
+ resetView(cm)
3802
+ } else {
3803
+ display.viewFrom += lendiff
3804
+ display.viewTo += lendiff
3805
+ }
3806
+ } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap
3807
+ resetView(cm)
3808
+ } else if (from <= display.viewFrom) { // Top overlap
3809
+ var cut = viewCuttingPoint(cm, to, to + lendiff, 1)
3810
+ if (cut) {
3811
+ display.view = display.view.slice(cut.index)
3812
+ display.viewFrom = cut.lineN
3813
+ display.viewTo += lendiff
3814
+ } else {
3815
+ resetView(cm)
3816
+ }
3817
+ } else if (to >= display.viewTo) { // Bottom overlap
3818
+ var cut$1 = viewCuttingPoint(cm, from, from, -1)
3819
+ if (cut$1) {
3820
+ display.view = display.view.slice(0, cut$1.index)
3821
+ display.viewTo = cut$1.lineN
3822
+ } else {
3823
+ resetView(cm)
3824
+ }
3825
+ } else { // Gap in the middle
3826
+ var cutTop = viewCuttingPoint(cm, from, from, -1)
3827
+ var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1)
3828
+ if (cutTop && cutBot) {
3829
+ display.view = display.view.slice(0, cutTop.index)
3830
+ .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN))
3831
+ .concat(display.view.slice(cutBot.index))
3832
+ display.viewTo += lendiff
3833
+ } else {
3834
+ resetView(cm)
3835
+ }
3836
+ }
3837
+
3838
+ var ext = display.externalMeasured
3839
+ if (ext) {
3840
+ if (to < ext.lineN)
3841
+ { ext.lineN += lendiff }
3842
+ else if (from < ext.lineN + ext.size)
3843
+ { display.externalMeasured = null }
3844
+ }
3845
+ }
3846
+
3847
+ // Register a change to a single line. Type must be one of "text",
3848
+ // "gutter", "class", "widget"
3849
+ function regLineChange(cm, line, type) {
3850
+ cm.curOp.viewChanged = true
3851
+ var display = cm.display, ext = cm.display.externalMeasured
3852
+ if (ext && line >= ext.lineN && line < ext.lineN + ext.size)
3853
+ { display.externalMeasured = null }
3854
+
3855
+ if (line < display.viewFrom || line >= display.viewTo) { return }
3856
+ var lineView = display.view[findViewIndex(cm, line)]
3857
+ if (lineView.node == null) { return }
3858
+ var arr = lineView.changes || (lineView.changes = [])
3859
+ if (indexOf(arr, type) == -1) { arr.push(type) }
3860
+ }
3861
+
3862
+ // Clear the view.
3863
+ function resetView(cm) {
3864
+ cm.display.viewFrom = cm.display.viewTo = cm.doc.first
3865
+ cm.display.view = []
3866
+ cm.display.viewOffset = 0
3867
+ }
3868
+
3869
+ function viewCuttingPoint(cm, oldN, newN, dir) {
3870
+ var index = findViewIndex(cm, oldN), diff, view = cm.display.view
3871
+ if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size)
3872
+ { return {index: index, lineN: newN} }
3873
+ var n = cm.display.viewFrom
3874
+ for (var i = 0; i < index; i++)
3875
+ { n += view[i].size }
3876
+ if (n != oldN) {
3877
+ if (dir > 0) {
3878
+ if (index == view.length - 1) { return null }
3879
+ diff = (n + view[index].size) - oldN
3880
+ index++
3881
+ } else {
3882
+ diff = n - oldN
3883
+ }
3884
+ oldN += diff; newN += diff
3885
+ }
3886
+ while (visualLineNo(cm.doc, newN) != newN) {
3887
+ if (index == (dir < 0 ? 0 : view.length - 1)) { return null }
3888
+ newN += dir * view[index - (dir < 0 ? 1 : 0)].size
3889
+ index += dir
3890
+ }
3891
+ return {index: index, lineN: newN}
3892
+ }
3893
+
3894
+ // Force the view to cover a given range, adding empty view element
3895
+ // or clipping off existing ones as needed.
3896
+ function adjustView(cm, from, to) {
3897
+ var display = cm.display, view = display.view
3898
+ if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) {
3899
+ display.view = buildViewArray(cm, from, to)
3900
+ display.viewFrom = from
3901
+ } else {
3902
+ if (display.viewFrom > from)
3903
+ { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view) }
3904
+ else if (display.viewFrom < from)
3905
+ { display.view = display.view.slice(findViewIndex(cm, from)) }
3906
+ display.viewFrom = from
3907
+ if (display.viewTo < to)
3908
+ { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)) }
3909
+ else if (display.viewTo > to)
3910
+ { display.view = display.view.slice(0, findViewIndex(cm, to)) }
3911
+ }
3912
+ display.viewTo = to
3913
+ }
3914
+
3915
+ // Count the number of lines in the view whose DOM representation is
3916
+ // out of date (or nonexistent).
3917
+ function countDirtyView(cm) {
3918
+ var view = cm.display.view, dirty = 0
3919
+ for (var i = 0; i < view.length; i++) {
3920
+ var lineView = view[i]
3921
+ if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty }
3922
+ }
3923
+ return dirty
3924
+ }
3925
+
3926
+ // HIGHLIGHT WORKER
3927
+
3928
+ function startWorker(cm, time) {
3929
+ if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo)
3930
+ { cm.state.highlight.set(time, bind(highlightWorker, cm)) }
3931
+ }
3932
+
3933
+ function highlightWorker(cm) {
3934
+ var doc = cm.doc
3935
+ if (doc.frontier < doc.first) { doc.frontier = doc.first }
3936
+ if (doc.frontier >= cm.display.viewTo) { return }
3937
+ var end = +new Date + cm.options.workTime
3938
+ var state = copyState(doc.mode, getStateBefore(cm, doc.frontier))
3939
+ var changedLines = []
3940
+
3941
+ doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) {
3942
+ if (doc.frontier >= cm.display.viewFrom) { // Visible
3943
+ var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength
3944
+ var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true)
3945
+ line.styles = highlighted.styles
3946
+ var oldCls = line.styleClasses, newCls = highlighted.classes
3947
+ if (newCls) { line.styleClasses = newCls }
3948
+ else if (oldCls) { line.styleClasses = null }
3949
+ var ischange = !oldStyles || oldStyles.length != line.styles.length ||
3950
+ oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass)
3951
+ for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i] }
3952
+ if (ischange) { changedLines.push(doc.frontier) }
3953
+ line.stateAfter = tooLong ? state : copyState(doc.mode, state)
3954
+ } else {
3955
+ if (line.text.length <= cm.options.maxHighlightLength)
3956
+ { processLine(cm, line.text, state) }
3957
+ line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null
3958
+ }
3959
+ ++doc.frontier
3960
+ if (+new Date > end) {
3961
+ startWorker(cm, cm.options.workDelay)
3962
+ return true
3963
+ }
3964
+ })
3965
+ if (changedLines.length) { runInOp(cm, function () {
3966
+ for (var i = 0; i < changedLines.length; i++)
3967
+ { regLineChange(cm, changedLines[i], "text") }
3968
+ }) }
3969
+ }
3970
+
3971
+ // DISPLAY DRAWING
3972
+
3973
+ var DisplayUpdate = function(cm, viewport, force) {
3974
+ var display = cm.display
3975
+
3976
+ this.viewport = viewport
3977
+ // Store some values that we'll need later (but don't want to force a relayout for)
3978
+ this.visible = visibleLines(display, cm.doc, viewport)
3979
+ this.editorIsHidden = !display.wrapper.offsetWidth
3980
+ this.wrapperHeight = display.wrapper.clientHeight
3981
+ this.wrapperWidth = display.wrapper.clientWidth
3982
+ this.oldDisplayWidth = displayWidth(cm)
3983
+ this.force = force
3984
+ this.dims = getDimensions(cm)
3985
+ this.events = []
3986
+ };
3987
+
3988
+ DisplayUpdate.prototype.signal = function (emitter, type) {
3989
+ if (hasHandler(emitter, type))
3990
+ { this.events.push(arguments) }
3991
+ };
3992
+ DisplayUpdate.prototype.finish = function () {
3993
+ var this$1 = this;
3994
+
3995
+ for (var i = 0; i < this.events.length; i++)
3996
+ { signal.apply(null, this$1.events[i]) }
3997
+ };
3998
+
3999
+ function maybeClipScrollbars(cm) {
4000
+ var display = cm.display
4001
+ if (!display.scrollbarsClipped && display.scroller.offsetWidth) {
4002
+ display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth
4003
+ display.heightForcer.style.height = scrollGap(cm) + "px"
4004
+ display.sizer.style.marginBottom = -display.nativeBarWidth + "px"
4005
+ display.sizer.style.borderRightWidth = scrollGap(cm) + "px"
4006
+ display.scrollbarsClipped = true
4007
+ }
4008
+ }
4009
+
4010
+ // Does the actual updating of the line display. Bails out
4011
+ // (returning false) when there is nothing to be done and forced is
4012
+ // false.
4013
+ function updateDisplayIfNeeded(cm, update) {
4014
+ var display = cm.display, doc = cm.doc
4015
+
4016
+ if (update.editorIsHidden) {
4017
+ resetView(cm)
4018
+ return false
4019
+ }
4020
+
4021
+ // Bail out if the visible area is already rendered and nothing changed.
4022
+ if (!update.force &&
4023
+ update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo &&
4024
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) &&
4025
+ display.renderedView == display.view && countDirtyView(cm) == 0)
4026
+ { return false }
4027
+
4028
+ if (maybeUpdateLineNumberWidth(cm)) {
4029
+ resetView(cm)
4030
+ update.dims = getDimensions(cm)
4031
+ }
4032
+
4033
+ // Compute a suitable new viewport (from & to)
4034
+ var end = doc.first + doc.size
4035
+ var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first)
4036
+ var to = Math.min(end, update.visible.to + cm.options.viewportMargin)
4037
+ if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom) }
4038
+ if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo) }
4039
+ if (sawCollapsedSpans) {
4040
+ from = visualLineNo(cm.doc, from)
4041
+ to = visualLineEndNo(cm.doc, to)
4042
+ }
4043
+
4044
+ var different = from != display.viewFrom || to != display.viewTo ||
4045
+ display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth
4046
+ adjustView(cm, from, to)
4047
+
4048
+ display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom))
4049
+ // Position the mover div to align with the current scroll position
4050
+ cm.display.mover.style.top = display.viewOffset + "px"
4051
+
4052
+ var toUpdate = countDirtyView(cm)
4053
+ if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view &&
4054
+ (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo))
4055
+ { return false }
4056
+
4057
+ // For big changes, we hide the enclosing element during the
4058
+ // update, since that speeds up the operations on most browsers.
4059
+ var focused = activeElt()
4060
+ if (toUpdate > 4) { display.lineDiv.style.display = "none" }
4061
+ patchDisplay(cm, display.updateLineNumbers, update.dims)
4062
+ if (toUpdate > 4) { display.lineDiv.style.display = "" }
4063
+ display.renderedView = display.view
4064
+ // There might have been a widget with a focused element that got
4065
+ // hidden or updated, if so re-focus it.
4066
+ if (focused && activeElt() != focused && focused.offsetHeight) { focused.focus() }
4067
+
4068
+ // Prevent selection and cursors from interfering with the scroll
4069
+ // width and height.
4070
+ removeChildren(display.cursorDiv)
4071
+ removeChildren(display.selectionDiv)
4072
+ display.gutters.style.height = display.sizer.style.minHeight = 0
4073
+
4074
+ if (different) {
4075
+ display.lastWrapHeight = update.wrapperHeight
4076
+ display.lastWrapWidth = update.wrapperWidth
4077
+ startWorker(cm, 400)
4078
+ }
4079
+
4080
+ display.updateLineNumbers = null
4081
+
4082
+ return true
4083
+ }
4084
+
4085
+ function postUpdateDisplay(cm, update) {
4086
+ var viewport = update.viewport
4087
+
4088
+ for (var first = true;; first = false) {
4089
+ if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) {
4090
+ // Clip forced viewport to actual scrollable area.
4091
+ if (viewport && viewport.top != null)
4092
+ { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)} }
4093
+ // Updated line heights might result in the drawn area not
4094
+ // actually covering the viewport. Keep looping until it does.
4095
+ update.visible = visibleLines(cm.display, cm.doc, viewport)
4096
+ if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo)
4097
+ { break }
4098
+ }
4099
+ if (!updateDisplayIfNeeded(cm, update)) { break }
4100
+ updateHeightsInViewport(cm)
4101
+ var barMeasure = measureForScrollbars(cm)
4102
+ updateSelection(cm)
4103
+ updateScrollbars(cm, barMeasure)
4104
+ setDocumentHeight(cm, barMeasure)
4105
+ }
4106
+
4107
+ update.signal(cm, "update", cm)
4108
+ if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) {
4109
+ update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo)
4110
+ cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo
4111
+ }
4112
+ }
4113
+
4114
+ function updateDisplaySimple(cm, viewport) {
4115
+ var update = new DisplayUpdate(cm, viewport)
4116
+ if (updateDisplayIfNeeded(cm, update)) {
4117
+ updateHeightsInViewport(cm)
4118
+ postUpdateDisplay(cm, update)
4119
+ var barMeasure = measureForScrollbars(cm)
4120
+ updateSelection(cm)
4121
+ updateScrollbars(cm, barMeasure)
4122
+ setDocumentHeight(cm, barMeasure)
4123
+ update.finish()
4124
+ }
4125
+ }
4126
+
4127
+ // Sync the actual display DOM structure with display.view, removing
4128
+ // nodes for lines that are no longer in view, and creating the ones
4129
+ // that are not there yet, and updating the ones that are out of
4130
+ // date.
4131
+ function patchDisplay(cm, updateNumbersFrom, dims) {
4132
+ var display = cm.display, lineNumbers = cm.options.lineNumbers
4133
+ var container = display.lineDiv, cur = container.firstChild
4134
+
4135
+ function rm(node) {
4136
+ var next = node.nextSibling
4137
+ // Works around a throw-scroll bug in OS X Webkit
4138
+ if (webkit && mac && cm.display.currentWheelTarget == node)
4139
+ { node.style.display = "none" }
4140
+ else
4141
+ { node.parentNode.removeChild(node) }
4142
+ return next
4143
+ }
4144
+
4145
+ var view = display.view, lineN = display.viewFrom
4146
+ // Loop over the elements in the view, syncing cur (the DOM nodes
4147
+ // in display.lineDiv) with the view as we go.
4148
+ for (var i = 0; i < view.length; i++) {
4149
+ var lineView = view[i]
4150
+ if (lineView.hidden) {
4151
+ } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet
4152
+ var node = buildLineElement(cm, lineView, lineN, dims)
4153
+ container.insertBefore(node, cur)
4154
+ } else { // Already drawn
4155
+ while (cur != lineView.node) { cur = rm(cur) }
4156
+ var updateNumber = lineNumbers && updateNumbersFrom != null &&
4157
+ updateNumbersFrom <= lineN && lineView.lineNumber
4158
+ if (lineView.changes) {
4159
+ if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false }
4160
+ updateLineForChanges(cm, lineView, lineN, dims)
4161
+ }
4162
+ if (updateNumber) {
4163
+ removeChildren(lineView.lineNumber)
4164
+ lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN)))
4165
+ }
4166
+ cur = lineView.node.nextSibling
4167
+ }
4168
+ lineN += lineView.size
4169
+ }
4170
+ while (cur) { cur = rm(cur) }
4171
+ }
4172
+
4173
+ function updateGutterSpace(cm) {
4174
+ var width = cm.display.gutters.offsetWidth
4175
+ cm.display.sizer.style.marginLeft = width + "px"
4176
+ }
4177
+
4178
+ function setDocumentHeight(cm, measure) {
4179
+ cm.display.sizer.style.minHeight = measure.docHeight + "px"
4180
+ cm.display.heightForcer.style.top = measure.docHeight + "px"
4181
+ cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"
4182
+ }
4183
+
4184
+ // Rebuild the gutter elements, ensure the margin to the left of the
4185
+ // code matches their width.
4186
+ function updateGutters(cm) {
4187
+ var gutters = cm.display.gutters, specs = cm.options.gutters
4188
+ removeChildren(gutters)
4189
+ var i = 0
4190
+ for (; i < specs.length; ++i) {
4191
+ var gutterClass = specs[i]
4192
+ var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass))
4193
+ if (gutterClass == "CodeMirror-linenumbers") {
4194
+ cm.display.lineGutter = gElt
4195
+ gElt.style.width = (cm.display.lineNumWidth || 1) + "px"
4196
+ }
4197
+ }
4198
+ gutters.style.display = i ? "" : "none"
4199
+ updateGutterSpace(cm)
4200
+ }
4201
+
4202
+ // Make sure the gutters options contains the element
4203
+ // "CodeMirror-linenumbers" when the lineNumbers option is true.
4204
+ function setGuttersForLineNumbers(options) {
4205
+ var found = indexOf(options.gutters, "CodeMirror-linenumbers")
4206
+ if (found == -1 && options.lineNumbers) {
4207
+ options.gutters = options.gutters.concat(["CodeMirror-linenumbers"])
4208
+ } else if (found > -1 && !options.lineNumbers) {
4209
+ options.gutters = options.gutters.slice(0)
4210
+ options.gutters.splice(found, 1)
4211
+ }
4212
+ }
4213
+
4214
+ // Selection objects are immutable. A new one is created every time
4215
+ // the selection changes. A selection is one or more non-overlapping
4216
+ // (and non-touching) ranges, sorted, and an integer that indicates
4217
+ // which one is the primary selection (the one that's scrolled into
4218
+ // view, that getCursor returns, etc).
4219
+ function Selection(ranges, primIndex) {
4220
+ this.ranges = ranges
4221
+ this.primIndex = primIndex
4222
+ }
4223
+
4224
+ Selection.prototype = {
4225
+ primary: function() { return this.ranges[this.primIndex] },
4226
+ equals: function(other) {
4227
+ var this$1 = this;
4228
+
4229
+ if (other == this) { return true }
4230
+ if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false }
4231
+ for (var i = 0; i < this.ranges.length; i++) {
4232
+ var here = this$1.ranges[i], there = other.ranges[i]
4233
+ if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) { return false }
4234
+ }
4235
+ return true
4236
+ },
4237
+ deepCopy: function() {
4238
+ var this$1 = this;
4239
+
4240
+ var out = []
4241
+ for (var i = 0; i < this.ranges.length; i++)
4242
+ { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)) }
4243
+ return new Selection(out, this.primIndex)
4244
+ },
4245
+ somethingSelected: function() {
4246
+ var this$1 = this;
4247
+
4248
+ for (var i = 0; i < this.ranges.length; i++)
4249
+ { if (!this$1.ranges[i].empty()) { return true } }
4250
+ return false
4251
+ },
4252
+ contains: function(pos, end) {
4253
+ var this$1 = this;
4254
+
4255
+ if (!end) { end = pos }
4256
+ for (var i = 0; i < this.ranges.length; i++) {
4257
+ var range = this$1.ranges[i]
4258
+ if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0)
4259
+ { return i }
4260
+ }
4261
+ return -1
4262
+ }
4263
+ }
4264
+
4265
+ function Range(anchor, head) {
4266
+ this.anchor = anchor; this.head = head
4267
+ }
4268
+
4269
+ Range.prototype = {
4270
+ from: function() { return minPos(this.anchor, this.head) },
4271
+ to: function() { return maxPos(this.anchor, this.head) },
4272
+ empty: function() {
4273
+ return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch
4274
+ }
4275
+ }
4276
+
4277
+ // Take an unsorted, potentially overlapping set of ranges, and
4278
+ // build a selection out of it. 'Consumes' ranges array (modifying
4279
+ // it).
4280
+ function normalizeSelection(ranges, primIndex) {
4281
+ var prim = ranges[primIndex]
4282
+ ranges.sort(function (a, b) { return cmp(a.from(), b.from()); })
4283
+ primIndex = indexOf(ranges, prim)
4284
+ for (var i = 1; i < ranges.length; i++) {
4285
+ var cur = ranges[i], prev = ranges[i - 1]
4286
+ if (cmp(prev.to(), cur.from()) >= 0) {
4287
+ var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to())
4288
+ var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head
4289
+ if (i <= primIndex) { --primIndex }
4290
+ ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to))
4291
+ }
4292
+ }
4293
+ return new Selection(ranges, primIndex)
4294
+ }
4295
+
4296
+ function simpleSelection(anchor, head) {
4297
+ return new Selection([new Range(anchor, head || anchor)], 0)
4298
+ }
4299
+
4300
+ // Compute the position of the end of a change (its 'to' property
4301
+ // refers to the pre-change end).
4302
+ function changeEnd(change) {
4303
+ if (!change.text) { return change.to }
4304
+ return Pos(change.from.line + change.text.length - 1,
4305
+ lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0))
4306
+ }
4307
+
4308
+ // Adjust a position to refer to the post-change position of the
4309
+ // same text, or the end of the change if the change covers it.
4310
+ function adjustForChange(pos, change) {
4311
+ if (cmp(pos, change.from) < 0) { return pos }
4312
+ if (cmp(pos, change.to) <= 0) { return changeEnd(change) }
4313
+
4314
+ var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch
4315
+ if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch }
4316
+ return Pos(line, ch)
4317
+ }
4318
+
4319
+ function computeSelAfterChange(doc, change) {
4320
+ var out = []
4321
+ for (var i = 0; i < doc.sel.ranges.length; i++) {
4322
+ var range = doc.sel.ranges[i]
4323
+ out.push(new Range(adjustForChange(range.anchor, change),
4324
+ adjustForChange(range.head, change)))
4325
+ }
4326
+ return normalizeSelection(out, doc.sel.primIndex)
4327
+ }
4328
+
4329
+ function offsetPos(pos, old, nw) {
4330
+ if (pos.line == old.line)
4331
+ { return Pos(nw.line, pos.ch - old.ch + nw.ch) }
4332
+ else
4333
+ { return Pos(nw.line + (pos.line - old.line), pos.ch) }
4334
+ }
4335
+
4336
+ // Used by replaceSelections to allow moving the selection to the
4337
+ // start or around the replaced test. Hint may be "start" or "around".
4338
+ function computeReplacedSel(doc, changes, hint) {
4339
+ var out = []
4340
+ var oldPrev = Pos(doc.first, 0), newPrev = oldPrev
4341
+ for (var i = 0; i < changes.length; i++) {
4342
+ var change = changes[i]
4343
+ var from = offsetPos(change.from, oldPrev, newPrev)
4344
+ var to = offsetPos(changeEnd(change), oldPrev, newPrev)
4345
+ oldPrev = change.to
4346
+ newPrev = to
4347
+ if (hint == "around") {
4348
+ var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0
4349
+ out[i] = new Range(inv ? to : from, inv ? from : to)
4350
+ } else {
4351
+ out[i] = new Range(from, from)
4352
+ }
4353
+ }
4354
+ return new Selection(out, doc.sel.primIndex)
4355
+ }
4356
+
4357
+ // Used to get the editor into a consistent state again when options change.
4358
+
4359
+ function loadMode(cm) {
4360
+ cm.doc.mode = getMode(cm.options, cm.doc.modeOption)
4361
+ resetModeState(cm)
4362
+ }
4363
+
4364
+ function resetModeState(cm) {
4365
+ cm.doc.iter(function (line) {
4366
+ if (line.stateAfter) { line.stateAfter = null }
4367
+ if (line.styles) { line.styles = null }
4368
+ })
4369
+ cm.doc.frontier = cm.doc.first
4370
+ startWorker(cm, 100)
4371
+ cm.state.modeGen++
4372
+ if (cm.curOp) { regChange(cm) }
4373
+ }
4374
+
4375
+ // DOCUMENT DATA STRUCTURE
4376
+
4377
+ // By default, updates that start and end at the beginning of a line
4378
+ // are treated specially, in order to make the association of line
4379
+ // widgets and marker elements with the text behave more intuitive.
4380
+ function isWholeLineUpdate(doc, change) {
4381
+ return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" &&
4382
+ (!doc.cm || doc.cm.options.wholeLineUpdateBefore)
4383
+ }
4384
+
4385
+ // Perform a change on the document data structure.
4386
+ function updateDoc(doc, change, markedSpans, estimateHeight) {
4387
+ function spansFor(n) {return markedSpans ? markedSpans[n] : null}
4388
+ function update(line, text, spans) {
4389
+ updateLine(line, text, spans, estimateHeight)
4390
+ signalLater(line, "change", line, change)
4391
+ }
4392
+ function linesFor(start, end) {
4393
+ var result = []
4394
+ for (var i = start; i < end; ++i)
4395
+ { result.push(new Line(text[i], spansFor(i), estimateHeight)) }
4396
+ return result
4397
+ }
4398
+
4399
+ var from = change.from, to = change.to, text = change.text
4400
+ var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line)
4401
+ var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line
4402
+
4403
+ // Adjust the line structure
4404
+ if (change.full) {
4405
+ doc.insert(0, linesFor(0, text.length))
4406
+ doc.remove(text.length, doc.size - text.length)
4407
+ } else if (isWholeLineUpdate(doc, change)) {
4408
+ // This is a whole-line replace. Treated specially to make
4409
+ // sure line objects move the way they are supposed to.
4410
+ var added = linesFor(0, text.length - 1)
4411
+ update(lastLine, lastLine.text, lastSpans)
4412
+ if (nlines) { doc.remove(from.line, nlines) }
4413
+ if (added.length) { doc.insert(from.line, added) }
4414
+ } else if (firstLine == lastLine) {
4415
+ if (text.length == 1) {
4416
+ update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans)
4417
+ } else {
4418
+ var added$1 = linesFor(1, text.length - 1)
4419
+ added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight))
4420
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0))
4421
+ doc.insert(from.line + 1, added$1)
4422
+ }
4423
+ } else if (text.length == 1) {
4424
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0))
4425
+ doc.remove(from.line + 1, nlines)
4426
+ } else {
4427
+ update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0))
4428
+ update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans)
4429
+ var added$2 = linesFor(1, text.length - 1)
4430
+ if (nlines > 1) { doc.remove(from.line + 1, nlines - 1) }
4431
+ doc.insert(from.line + 1, added$2)
4432
+ }
4433
+
4434
+ signalLater(doc, "change", doc, change)
4435
+ }
4436
+
4437
+ // Call f for all linked documents.
4438
+ function linkedDocs(doc, f, sharedHistOnly) {
4439
+ function propagate(doc, skip, sharedHist) {
4440
+ if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) {
4441
+ var rel = doc.linked[i]
4442
+ if (rel.doc == skip) { continue }
4443
+ var shared = sharedHist && rel.sharedHist
4444
+ if (sharedHistOnly && !shared) { continue }
4445
+ f(rel.doc, shared)
4446
+ propagate(rel.doc, doc, shared)
4447
+ } }
4448
+ }
4449
+ propagate(doc, null, true)
4450
+ }
4451
+
4452
+ // Attach a document to an editor.
4453
+ function attachDoc(cm, doc) {
4454
+ if (doc.cm) { throw new Error("This document is already in use.") }
4455
+ cm.doc = doc
4456
+ doc.cm = cm
4457
+ estimateLineHeights(cm)
4458
+ loadMode(cm)
4459
+ if (!cm.options.lineWrapping) { findMaxLine(cm) }
4460
+ cm.options.mode = doc.modeOption
4461
+ regChange(cm)
4462
+ }
4463
+
4464
+ function History(startGen) {
4465
+ // Arrays of change events and selections. Doing something adds an
4466
+ // event to done and clears undo. Undoing moves events from done
4467
+ // to undone, redoing moves them in the other direction.
4468
+ this.done = []; this.undone = []
4469
+ this.undoDepth = Infinity
4470
+ // Used to track when changes can be merged into a single undo
4471
+ // event
4472
+ this.lastModTime = this.lastSelTime = 0
4473
+ this.lastOp = this.lastSelOp = null
4474
+ this.lastOrigin = this.lastSelOrigin = null
4475
+ // Used by the isClean() method
4476
+ this.generation = this.maxGeneration = startGen || 1
4477
+ }
4478
+
4479
+ // Create a history change event from an updateDoc-style change
4480
+ // object.
4481
+ function historyChangeFromChange(doc, change) {
4482
+ var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}
4483
+ attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1)
4484
+ linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true)
4485
+ return histChange
4486
+ }
4487
+
4488
+ // Pop all selection events off the end of a history array. Stop at
4489
+ // a change event.
4490
+ function clearSelectionEvents(array) {
4491
+ while (array.length) {
4492
+ var last = lst(array)
4493
+ if (last.ranges) { array.pop() }
4494
+ else { break }
4495
+ }
4496
+ }
4497
+
4498
+ // Find the top change event in the history. Pop off selection
4499
+ // events that are in the way.
4500
+ function lastChangeEvent(hist, force) {
4501
+ if (force) {
4502
+ clearSelectionEvents(hist.done)
4503
+ return lst(hist.done)
4504
+ } else if (hist.done.length && !lst(hist.done).ranges) {
4505
+ return lst(hist.done)
4506
+ } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) {
4507
+ hist.done.pop()
4508
+ return lst(hist.done)
4509
+ }
4510
+ }
4511
+
4512
+ // Register a change in the history. Merges changes that are within
4513
+ // a single operation, or are close together with an origin that
4514
+ // allows merging (starting with "+") into a single event.
4515
+ function addChangeToHistory(doc, change, selAfter, opId) {
4516
+ var hist = doc.history
4517
+ hist.undone.length = 0
4518
+ var time = +new Date, cur
4519
+ var last
4520
+
4521
+ if ((hist.lastOp == opId ||
4522
+ hist.lastOrigin == change.origin && change.origin &&
4523
+ ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) ||
4524
+ change.origin.charAt(0) == "*")) &&
4525
+ (cur = lastChangeEvent(hist, hist.lastOp == opId))) {
4526
+ // Merge this change into the last event
4527
+ last = lst(cur.changes)
4528
+ if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) {
4529
+ // Optimized case for simple insertion -- don't want to add
4530
+ // new changesets for every character typed
4531
+ last.to = changeEnd(change)
4532
+ } else {
4533
+ // Add new sub-event
4534
+ cur.changes.push(historyChangeFromChange(doc, change))
4535
+ }
4536
+ } else {
4537
+ // Can not be merged, start a new event.
4538
+ var before = lst(hist.done)
4539
+ if (!before || !before.ranges)
4540
+ { pushSelectionToHistory(doc.sel, hist.done) }
4541
+ cur = {changes: [historyChangeFromChange(doc, change)],
4542
+ generation: hist.generation}
4543
+ hist.done.push(cur)
4544
+ while (hist.done.length > hist.undoDepth) {
4545
+ hist.done.shift()
4546
+ if (!hist.done[0].ranges) { hist.done.shift() }
4547
+ }
4548
+ }
4549
+ hist.done.push(selAfter)
4550
+ hist.generation = ++hist.maxGeneration
4551
+ hist.lastModTime = hist.lastSelTime = time
4552
+ hist.lastOp = hist.lastSelOp = opId
4553
+ hist.lastOrigin = hist.lastSelOrigin = change.origin
4554
+
4555
+ if (!last) { signal(doc, "historyAdded") }
4556
+ }
4557
+
4558
+ function selectionEventCanBeMerged(doc, origin, prev, sel) {
4559
+ var ch = origin.charAt(0)
4560
+ return ch == "*" ||
4561
+ ch == "+" &&
4562
+ prev.ranges.length == sel.ranges.length &&
4563
+ prev.somethingSelected() == sel.somethingSelected() &&
4564
+ new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500)
4565
+ }
4566
+
4567
+ // Called whenever the selection changes, sets the new selection as
4568
+ // the pending selection in the history, and pushes the old pending
4569
+ // selection into the 'done' array when it was significantly
4570
+ // different (in number of selected ranges, emptiness, or time).
4571
+ function addSelectionToHistory(doc, sel, opId, options) {
4572
+ var hist = doc.history, origin = options && options.origin
4573
+
4574
+ // A new event is started when the previous origin does not match
4575
+ // the current, or the origins don't allow matching. Origins
4576
+ // starting with * are always merged, those starting with + are
4577
+ // merged when similar and close together in time.
4578
+ if (opId == hist.lastSelOp ||
4579
+ (origin && hist.lastSelOrigin == origin &&
4580
+ (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin ||
4581
+ selectionEventCanBeMerged(doc, origin, lst(hist.done), sel))))
4582
+ { hist.done[hist.done.length - 1] = sel }
4583
+ else
4584
+ { pushSelectionToHistory(sel, hist.done) }
4585
+
4586
+ hist.lastSelTime = +new Date
4587
+ hist.lastSelOrigin = origin
4588
+ hist.lastSelOp = opId
4589
+ if (options && options.clearRedo !== false)
4590
+ { clearSelectionEvents(hist.undone) }
4591
+ }
4592
+
4593
+ function pushSelectionToHistory(sel, dest) {
4594
+ var top = lst(dest)
4595
+ if (!(top && top.ranges && top.equals(sel)))
4596
+ { dest.push(sel) }
4597
+ }
4598
+
4599
+ // Used to store marked span information in the history.
4600
+ function attachLocalSpans(doc, change, from, to) {
4601
+ var existing = change["spans_" + doc.id], n = 0
4602
+ doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) {
4603
+ if (line.markedSpans)
4604
+ { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans }
4605
+ ++n
4606
+ })
4607
+ }
4608
+
4609
+ // When un/re-doing restores text containing marked spans, those
4610
+ // that have been explicitly cleared should not be restored.
4611
+ function removeClearedSpans(spans) {
4612
+ if (!spans) { return null }
4613
+ var out
4614
+ for (var i = 0; i < spans.length; ++i) {
4615
+ if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i) } }
4616
+ else if (out) { out.push(spans[i]) }
4617
+ }
4618
+ return !out ? spans : out.length ? out : null
4619
+ }
4620
+
4621
+ // Retrieve and filter the old marked spans stored in a change event.
4622
+ function getOldSpans(doc, change) {
4623
+ var found = change["spans_" + doc.id]
4624
+ if (!found) { return null }
4625
+ var nw = []
4626
+ for (var i = 0; i < change.text.length; ++i)
4627
+ { nw.push(removeClearedSpans(found[i])) }
4628
+ return nw
4629
+ }
4630
+
4631
+ // Used for un/re-doing changes from the history. Combines the
4632
+ // result of computing the existing spans with the set of spans that
4633
+ // existed in the history (so that deleting around a span and then
4634
+ // undoing brings back the span).
4635
+ function mergeOldSpans(doc, change) {
4636
+ var old = getOldSpans(doc, change)
4637
+ var stretched = stretchSpansOverChange(doc, change)
4638
+ if (!old) { return stretched }
4639
+ if (!stretched) { return old }
4640
+
4641
+ for (var i = 0; i < old.length; ++i) {
4642
+ var oldCur = old[i], stretchCur = stretched[i]
4643
+ if (oldCur && stretchCur) {
4644
+ spans: for (var j = 0; j < stretchCur.length; ++j) {
4645
+ var span = stretchCur[j]
4646
+ for (var k = 0; k < oldCur.length; ++k)
4647
+ { if (oldCur[k].marker == span.marker) { continue spans } }
4648
+ oldCur.push(span)
4649
+ }
4650
+ } else if (stretchCur) {
4651
+ old[i] = stretchCur
4652
+ }
4653
+ }
4654
+ return old
4655
+ }
4656
+
4657
+ // Used both to provide a JSON-safe object in .getHistory, and, when
4658
+ // detaching a document, to split the history in two
4659
+ function copyHistoryArray(events, newGroup, instantiateSel) {
4660
+ var copy = []
4661
+ for (var i = 0; i < events.length; ++i) {
4662
+ var event = events[i]
4663
+ if (event.ranges) {
4664
+ copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event)
4665
+ continue
4666
+ }
4667
+ var changes = event.changes, newChanges = []
4668
+ copy.push({changes: newChanges})
4669
+ for (var j = 0; j < changes.length; ++j) {
4670
+ var change = changes[j], m = (void 0)
4671
+ newChanges.push({from: change.from, to: change.to, text: change.text})
4672
+ if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) {
4673
+ if (indexOf(newGroup, Number(m[1])) > -1) {
4674
+ lst(newChanges)[prop] = change[prop]
4675
+ delete change[prop]
4676
+ }
4677
+ } } }
4678
+ }
4679
+ }
4680
+ return copy
4681
+ }
4682
+
4683
+ // The 'scroll' parameter given to many of these indicated whether
4684
+ // the new cursor position should be scrolled into view after
4685
+ // modifying the selection.
4686
+
4687
+ // If shift is held or the extend flag is set, extends a range to
4688
+ // include a given position (and optionally a second position).
4689
+ // Otherwise, simply returns the range between the given positions.
4690
+ // Used for cursor motion and such.
4691
+ function extendRange(doc, range, head, other) {
4692
+ if (doc.cm && doc.cm.display.shift || doc.extend) {
4693
+ var anchor = range.anchor
4694
+ if (other) {
4695
+ var posBefore = cmp(head, anchor) < 0
4696
+ if (posBefore != (cmp(other, anchor) < 0)) {
4697
+ anchor = head
4698
+ head = other
4699
+ } else if (posBefore != (cmp(head, other) < 0)) {
4700
+ head = other
4701
+ }
4702
+ }
4703
+ return new Range(anchor, head)
4704
+ } else {
4705
+ return new Range(other || head, head)
4706
+ }
4707
+ }
4708
+
4709
+ // Extend the primary selection range, discard the rest.
4710
+ function extendSelection(doc, head, other, options) {
4711
+ setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options)
4712
+ }
4713
+
4714
+ // Extend all selections (pos is an array of selections with length
4715
+ // equal the number of selections)
4716
+ function extendSelections(doc, heads, options) {
4717
+ var out = []
4718
+ for (var i = 0; i < doc.sel.ranges.length; i++)
4719
+ { out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null) }
4720
+ var newSel = normalizeSelection(out, doc.sel.primIndex)
4721
+ setSelection(doc, newSel, options)
4722
+ }
4723
+
4724
+ // Updates a single range in the selection.
4725
+ function replaceOneSelection(doc, i, range, options) {
4726
+ var ranges = doc.sel.ranges.slice(0)
4727
+ ranges[i] = range
4728
+ setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options)
4729
+ }
4730
+
4731
+ // Reset the selection to a single range.
4732
+ function setSimpleSelection(doc, anchor, head, options) {
4733
+ setSelection(doc, simpleSelection(anchor, head), options)
4734
+ }
4735
+
4736
+ // Give beforeSelectionChange handlers a change to influence a
4737
+ // selection update.
4738
+ function filterSelectionChange(doc, sel, options) {
4739
+ var obj = {
4740
+ ranges: sel.ranges,
4741
+ update: function(ranges) {
4742
+ var this$1 = this;
4743
+
4744
+ this.ranges = []
4745
+ for (var i = 0; i < ranges.length; i++)
4746
+ { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor),
4747
+ clipPos(doc, ranges[i].head)) }
4748
+ },
4749
+ origin: options && options.origin
4750
+ }
4751
+ signal(doc, "beforeSelectionChange", doc, obj)
4752
+ if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj) }
4753
+ if (obj.ranges != sel.ranges) { return normalizeSelection(obj.ranges, obj.ranges.length - 1) }
4754
+ else { return sel }
4755
+ }
4756
+
4757
+ function setSelectionReplaceHistory(doc, sel, options) {
4758
+ var done = doc.history.done, last = lst(done)
4759
+ if (last && last.ranges) {
4760
+ done[done.length - 1] = sel
4761
+ setSelectionNoUndo(doc, sel, options)
4762
+ } else {
4763
+ setSelection(doc, sel, options)
4764
+ }
4765
+ }
4766
+
4767
+ // Set a new selection.
4768
+ function setSelection(doc, sel, options) {
4769
+ setSelectionNoUndo(doc, sel, options)
4770
+ addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options)
4771
+ }
4772
+
4773
+ function setSelectionNoUndo(doc, sel, options) {
4774
+ if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange"))
4775
+ { sel = filterSelectionChange(doc, sel, options) }
4776
+
4777
+ var bias = options && options.bias ||
4778
+ (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1)
4779
+ setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true))
4780
+
4781
+ if (!(options && options.scroll === false) && doc.cm)
4782
+ { ensureCursorVisible(doc.cm) }
4783
+ }
4784
+
4785
+ function setSelectionInner(doc, sel) {
4786
+ if (sel.equals(doc.sel)) { return }
4787
+
4788
+ doc.sel = sel
4789
+
4790
+ if (doc.cm) {
4791
+ doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true
4792
+ signalCursorActivity(doc.cm)
4793
+ }
4794
+ signalLater(doc, "cursorActivity", doc)
4795
+ }
4796
+
4797
+ // Verify that the selection does not partially select any atomic
4798
+ // marked ranges.
4799
+ function reCheckSelection(doc) {
4800
+ setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll)
4801
+ }
4802
+
4803
+ // Return a selection that does not partially select any atomic
4804
+ // ranges.
4805
+ function skipAtomicInSelection(doc, sel, bias, mayClear) {
4806
+ var out
4807
+ for (var i = 0; i < sel.ranges.length; i++) {
4808
+ var range = sel.ranges[i]
4809
+ var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]
4810
+ var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear)
4811
+ var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear)
4812
+ if (out || newAnchor != range.anchor || newHead != range.head) {
4813
+ if (!out) { out = sel.ranges.slice(0, i) }
4814
+ out[i] = new Range(newAnchor, newHead)
4815
+ }
4816
+ }
4817
+ return out ? normalizeSelection(out, sel.primIndex) : sel
4818
+ }
4819
+
4820
+ function skipAtomicInner(doc, pos, oldPos, dir, mayClear) {
4821
+ var line = getLine(doc, pos.line)
4822
+ if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) {
4823
+ var sp = line.markedSpans[i], m = sp.marker
4824
+ if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) &&
4825
+ (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) {
4826
+ if (mayClear) {
4827
+ signal(m, "beforeCursorEnter")
4828
+ if (m.explicitlyCleared) {
4829
+ if (!line.markedSpans) { break }
4830
+ else {--i; continue}
4831
+ }
4832
+ }
4833
+ if (!m.atomic) { continue }
4834
+
4835
+ if (oldPos) {
4836
+ var near = m.find(dir < 0 ? 1 : -1), diff = (void 0)
4837
+ if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft)
4838
+ { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null) }
4839
+ if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0))
4840
+ { return skipAtomicInner(doc, near, pos, dir, mayClear) }
4841
+ }
4842
+
4843
+ var far = m.find(dir < 0 ? -1 : 1)
4844
+ if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight)
4845
+ { far = movePos(doc, far, dir, far.line == pos.line ? line : null) }
4846
+ return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null
4847
+ }
4848
+ } }
4849
+ return pos
4850
+ }
4851
+
4852
+ // Ensure a given position is not inside an atomic range.
4853
+ function skipAtomic(doc, pos, oldPos, bias, mayClear) {
4854
+ var dir = bias || 1
4855
+ var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) ||
4856
+ (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) ||
4857
+ skipAtomicInner(doc, pos, oldPos, -dir, mayClear) ||
4858
+ (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true))
4859
+ if (!found) {
4860
+ doc.cantEdit = true
4861
+ return Pos(doc.first, 0)
4862
+ }
4863
+ return found
4864
+ }
4865
+
4866
+ function movePos(doc, pos, dir, line) {
4867
+ if (dir < 0 && pos.ch == 0) {
4868
+ if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) }
4869
+ else { return null }
4870
+ } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) {
4871
+ if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) }
4872
+ else { return null }
4873
+ } else {
4874
+ return new Pos(pos.line, pos.ch + dir)
4875
+ }
4876
+ }
4877
+
4878
+ function selectAll(cm) {
4879
+ cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll)
4880
+ }
4881
+
4882
+ // UPDATING
4883
+
4884
+ // Allow "beforeChange" event handlers to influence a change
4885
+ function filterChange(doc, change, update) {
4886
+ var obj = {
4887
+ canceled: false,
4888
+ from: change.from,
4889
+ to: change.to,
4890
+ text: change.text,
4891
+ origin: change.origin,
4892
+ cancel: function () { return obj.canceled = true; }
4893
+ }
4894
+ if (update) { obj.update = function (from, to, text, origin) {
4895
+ if (from) { obj.from = clipPos(doc, from) }
4896
+ if (to) { obj.to = clipPos(doc, to) }
4897
+ if (text) { obj.text = text }
4898
+ if (origin !== undefined) { obj.origin = origin }
4899
+ } }
4900
+ signal(doc, "beforeChange", doc, obj)
4901
+ if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj) }
4902
+
4903
+ if (obj.canceled) { return null }
4904
+ return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin}
4905
+ }
4906
+
4907
+ // Apply a change to a document, and add it to the document's
4908
+ // history, and propagating it to all linked documents.
4909
+ function makeChange(doc, change, ignoreReadOnly) {
4910
+ if (doc.cm) {
4911
+ if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) }
4912
+ if (doc.cm.state.suppressEdits) { return }
4913
+ }
4914
+
4915
+ if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) {
4916
+ change = filterChange(doc, change, true)
4917
+ if (!change) { return }
4918
+ }
4919
+
4920
+ // Possibly split or suppress the update based on the presence
4921
+ // of read-only spans in its range.
4922
+ var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to)
4923
+ if (split) {
4924
+ for (var i = split.length - 1; i >= 0; --i)
4925
+ { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}) }
4926
+ } else {
4927
+ makeChangeInner(doc, change)
4928
+ }
4929
+ }
4930
+
4931
+ function makeChangeInner(doc, change) {
4932
+ if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return }
4933
+ var selAfter = computeSelAfterChange(doc, change)
4934
+ addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN)
4935
+
4936
+ makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change))
4937
+ var rebased = []
4938
+
4939
+ linkedDocs(doc, function (doc, sharedHist) {
4940
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
4941
+ rebaseHist(doc.history, change)
4942
+ rebased.push(doc.history)
4943
+ }
4944
+ makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change))
4945
+ })
4946
+ }
4947
+
4948
+ // Revert a change stored in a document's history.
4949
+ function makeChangeFromHistory(doc, type, allowSelectionOnly) {
4950
+ if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return }
4951
+
4952
+ var hist = doc.history, event, selAfter = doc.sel
4953
+ var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done
4954
+
4955
+ // Verify that there is a useable event (so that ctrl-z won't
4956
+ // needlessly clear selection events)
4957
+ var i = 0
4958
+ for (; i < source.length; i++) {
4959
+ event = source[i]
4960
+ if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges)
4961
+ { break }
4962
+ }
4963
+ if (i == source.length) { return }
4964
+ hist.lastOrigin = hist.lastSelOrigin = null
4965
+
4966
+ for (;;) {
4967
+ event = source.pop()
4968
+ if (event.ranges) {
4969
+ pushSelectionToHistory(event, dest)
4970
+ if (allowSelectionOnly && !event.equals(doc.sel)) {
4971
+ setSelection(doc, event, {clearRedo: false})
4972
+ return
4973
+ }
4974
+ selAfter = event
4975
+ }
4976
+ else { break }
4977
+ }
4978
+
4979
+ // Build up a reverse change object to add to the opposite history
4980
+ // stack (redo when undoing, and vice versa).
4981
+ var antiChanges = []
4982
+ pushSelectionToHistory(selAfter, dest)
4983
+ dest.push({changes: antiChanges, generation: hist.generation})
4984
+ hist.generation = event.generation || ++hist.maxGeneration
4985
+
4986
+ var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")
4987
+
4988
+ var loop = function ( i ) {
4989
+ var change = event.changes[i]
4990
+ change.origin = type
4991
+ if (filter && !filterChange(doc, change, false)) {
4992
+ source.length = 0
4993
+ return {}
4994
+ }
4995
+
4996
+ antiChanges.push(historyChangeFromChange(doc, change))
4997
+
4998
+ var after = i ? computeSelAfterChange(doc, change) : lst(source)
4999
+ makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change))
5000
+ if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}) }
5001
+ var rebased = []
5002
+
5003
+ // Propagate to the linked documents
5004
+ linkedDocs(doc, function (doc, sharedHist) {
5005
+ if (!sharedHist && indexOf(rebased, doc.history) == -1) {
5006
+ rebaseHist(doc.history, change)
5007
+ rebased.push(doc.history)
5008
+ }
5009
+ makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change))
5010
+ })
5011
+ };
5012
+
5013
+ for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) {
5014
+ var returned = loop( i$1 );
5015
+
5016
+ if ( returned ) return returned.v;
5017
+ }
5018
+ }
5019
+
5020
+ // Sub-views need their line numbers shifted when text is added
5021
+ // above or below them in the parent document.
5022
+ function shiftDoc(doc, distance) {
5023
+ if (distance == 0) { return }
5024
+ doc.first += distance
5025
+ doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range(
5026
+ Pos(range.anchor.line + distance, range.anchor.ch),
5027
+ Pos(range.head.line + distance, range.head.ch)
5028
+ ); }), doc.sel.primIndex)
5029
+ if (doc.cm) {
5030
+ regChange(doc.cm, doc.first, doc.first - distance, distance)
5031
+ for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++)
5032
+ { regLineChange(doc.cm, l, "gutter") }
5033
+ }
5034
+ }
5035
+
5036
+ // More lower-level change function, handling only a single document
5037
+ // (not linked ones).
5038
+ function makeChangeSingleDoc(doc, change, selAfter, spans) {
5039
+ if (doc.cm && !doc.cm.curOp)
5040
+ { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) }
5041
+
5042
+ if (change.to.line < doc.first) {
5043
+ shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line))
5044
+ return
5045
+ }
5046
+ if (change.from.line > doc.lastLine()) { return }
5047
+
5048
+ // Clip the change to the size of this doc
5049
+ if (change.from.line < doc.first) {
5050
+ var shift = change.text.length - 1 - (doc.first - change.from.line)
5051
+ shiftDoc(doc, shift)
5052
+ change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch),
5053
+ text: [lst(change.text)], origin: change.origin}
5054
+ }
5055
+ var last = doc.lastLine()
5056
+ if (change.to.line > last) {
5057
+ change = {from: change.from, to: Pos(last, getLine(doc, last).text.length),
5058
+ text: [change.text[0]], origin: change.origin}
5059
+ }
5060
+
5061
+ change.removed = getBetween(doc, change.from, change.to)
5062
+
5063
+ if (!selAfter) { selAfter = computeSelAfterChange(doc, change) }
5064
+ if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans) }
5065
+ else { updateDoc(doc, change, spans) }
5066
+ setSelectionNoUndo(doc, selAfter, sel_dontScroll)
5067
+ }
5068
+
5069
+ // Handle the interaction of a change to a document with the editor
5070
+ // that this document is part of.
5071
+ function makeChangeSingleDocInEditor(cm, change, spans) {
5072
+ var doc = cm.doc, display = cm.display, from = change.from, to = change.to
5073
+
5074
+ var recomputeMaxLength = false, checkWidthStart = from.line
5075
+ if (!cm.options.lineWrapping) {
5076
+ checkWidthStart = lineNo(visualLine(getLine(doc, from.line)))
5077
+ doc.iter(checkWidthStart, to.line + 1, function (line) {
5078
+ if (line == display.maxLine) {
5079
+ recomputeMaxLength = true
5080
+ return true
5081
+ }
5082
+ })
5083
+ }
5084
+
5085
+ if (doc.sel.contains(change.from, change.to) > -1)
5086
+ { signalCursorActivity(cm) }
5087
+
5088
+ updateDoc(doc, change, spans, estimateHeight(cm))
5089
+
5090
+ if (!cm.options.lineWrapping) {
5091
+ doc.iter(checkWidthStart, from.line + change.text.length, function (line) {
5092
+ var len = lineLength(line)
5093
+ if (len > display.maxLineLength) {
5094
+ display.maxLine = line
5095
+ display.maxLineLength = len
5096
+ display.maxLineChanged = true
5097
+ recomputeMaxLength = false
5098
+ }
5099
+ })
5100
+ if (recomputeMaxLength) { cm.curOp.updateMaxLine = true }
5101
+ }
5102
+
5103
+ // Adjust frontier, schedule worker
5104
+ doc.frontier = Math.min(doc.frontier, from.line)
5105
+ startWorker(cm, 400)
5106
+
5107
+ var lendiff = change.text.length - (to.line - from.line) - 1
5108
+ // Remember that these lines changed, for updating the display
5109
+ if (change.full)
5110
+ { regChange(cm) }
5111
+ else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change))
5112
+ { regLineChange(cm, from.line, "text") }
5113
+ else
5114
+ { regChange(cm, from.line, to.line + 1, lendiff) }
5115
+
5116
+ var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change")
5117
+ if (changeHandler || changesHandler) {
5118
+ var obj = {
5119
+ from: from, to: to,
5120
+ text: change.text,
5121
+ removed: change.removed,
5122
+ origin: change.origin
5123
+ }
5124
+ if (changeHandler) { signalLater(cm, "change", cm, obj) }
5125
+ if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) }
5126
+ }
5127
+ cm.display.selForContextMenu = null
5128
+ }
5129
+
5130
+ function replaceRange(doc, code, from, to, origin) {
5131
+ if (!to) { to = from }
5132
+ if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp }
5133
+ if (typeof code == "string") { code = doc.splitLines(code) }
5134
+ makeChange(doc, {from: from, to: to, text: code, origin: origin})
5135
+ }
5136
+
5137
+ // Rebasing/resetting history to deal with externally-sourced changes
5138
+
5139
+ function rebaseHistSelSingle(pos, from, to, diff) {
5140
+ if (to < pos.line) {
5141
+ pos.line += diff
5142
+ } else if (from < pos.line) {
5143
+ pos.line = from
5144
+ pos.ch = 0
5145
+ }
5146
+ }
5147
+
5148
+ // Tries to rebase an array of history events given a change in the
5149
+ // document. If the change touches the same lines as the event, the
5150
+ // event, and everything 'behind' it, is discarded. If the change is
5151
+ // before the event, the event's positions are updated. Uses a
5152
+ // copy-on-write scheme for the positions, to avoid having to
5153
+ // reallocate them all on every rebase, but also avoid problems with
5154
+ // shared position objects being unsafely updated.
5155
+ function rebaseHistArray(array, from, to, diff) {
5156
+ for (var i = 0; i < array.length; ++i) {
5157
+ var sub = array[i], ok = true
5158
+ if (sub.ranges) {
5159
+ if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true }
5160
+ for (var j = 0; j < sub.ranges.length; j++) {
5161
+ rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff)
5162
+ rebaseHistSelSingle(sub.ranges[j].head, from, to, diff)
5163
+ }
5164
+ continue
5165
+ }
5166
+ for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) {
5167
+ var cur = sub.changes[j$1]
5168
+ if (to < cur.from.line) {
5169
+ cur.from = Pos(cur.from.line + diff, cur.from.ch)
5170
+ cur.to = Pos(cur.to.line + diff, cur.to.ch)
5171
+ } else if (from <= cur.to.line) {
5172
+ ok = false
5173
+ break
5174
+ }
5175
+ }
5176
+ if (!ok) {
5177
+ array.splice(0, i + 1)
5178
+ i = 0
5179
+ }
5180
+ }
5181
+ }
5182
+
5183
+ function rebaseHist(hist, change) {
5184
+ var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1
5185
+ rebaseHistArray(hist.done, from, to, diff)
5186
+ rebaseHistArray(hist.undone, from, to, diff)
5187
+ }
5188
+
5189
+ // Utility for applying a change to a line by handle or number,
5190
+ // returning the number and optionally registering the line as
5191
+ // changed.
5192
+ function changeLine(doc, handle, changeType, op) {
5193
+ var no = handle, line = handle
5194
+ if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)) }
5195
+ else { no = lineNo(handle) }
5196
+ if (no == null) { return null }
5197
+ if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType) }
5198
+ return line
5199
+ }
5200
+
5201
+ // The document is represented as a BTree consisting of leaves, with
5202
+ // chunk of lines in them, and branches, with up to ten leaves or
5203
+ // other branch nodes below them. The top node is always a branch
5204
+ // node, and is the document object itself (meaning it has
5205
+ // additional methods and properties).
5206
+ //
5207
+ // All nodes have parent links. The tree is used both to go from
5208
+ // line numbers to line objects, and to go from objects to numbers.
5209
+ // It also indexes by height, and is used to convert between height
5210
+ // and line object, and to find the total height of the document.
5211
+ //
5212
+ // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html
5213
+
5214
+ function LeafChunk(lines) {
5215
+ var this$1 = this;
5216
+
5217
+ this.lines = lines
5218
+ this.parent = null
5219
+ var height = 0
5220
+ for (var i = 0; i < lines.length; ++i) {
5221
+ lines[i].parent = this$1
5222
+ height += lines[i].height
5223
+ }
5224
+ this.height = height
5225
+ }
5226
+
5227
+ LeafChunk.prototype = {
5228
+ chunkSize: function() { return this.lines.length },
5229
+ // Remove the n lines at offset 'at'.
5230
+ removeInner: function(at, n) {
5231
+ var this$1 = this;
5232
+
5233
+ for (var i = at, e = at + n; i < e; ++i) {
5234
+ var line = this$1.lines[i]
5235
+ this$1.height -= line.height
5236
+ cleanUpLine(line)
5237
+ signalLater(line, "delete")
5238
+ }
5239
+ this.lines.splice(at, n)
5240
+ },
5241
+ // Helper used to collapse a small branch into a single leaf.
5242
+ collapse: function(lines) {
5243
+ lines.push.apply(lines, this.lines)
5244
+ },
5245
+ // Insert the given array of lines at offset 'at', count them as
5246
+ // having the given height.
5247
+ insertInner: function(at, lines, height) {
5248
+ var this$1 = this;
5249
+
5250
+ this.height += height
5251
+ this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at))
5252
+ for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1 }
5253
+ },
5254
+ // Used to iterate over a part of the tree.
5255
+ iterN: function(at, n, op) {
5256
+ var this$1 = this;
5257
+
5258
+ for (var e = at + n; at < e; ++at)
5259
+ { if (op(this$1.lines[at])) { return true } }
5260
+ }
5261
+ }
5262
+
5263
+ function BranchChunk(children) {
5264
+ var this$1 = this;
5265
+
5266
+ this.children = children
5267
+ var size = 0, height = 0
5268
+ for (var i = 0; i < children.length; ++i) {
5269
+ var ch = children[i]
5270
+ size += ch.chunkSize(); height += ch.height
5271
+ ch.parent = this$1
5272
+ }
5273
+ this.size = size
5274
+ this.height = height
5275
+ this.parent = null
5276
+ }
5277
+
5278
+ BranchChunk.prototype = {
5279
+ chunkSize: function() { return this.size },
5280
+ removeInner: function(at, n) {
5281
+ var this$1 = this;
5282
+
5283
+ this.size -= n
5284
+ for (var i = 0; i < this.children.length; ++i) {
5285
+ var child = this$1.children[i], sz = child.chunkSize()
5286
+ if (at < sz) {
5287
+ var rm = Math.min(n, sz - at), oldHeight = child.height
5288
+ child.removeInner(at, rm)
5289
+ this$1.height -= oldHeight - child.height
5290
+ if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null }
5291
+ if ((n -= rm) == 0) { break }
5292
+ at = 0
5293
+ } else { at -= sz }
5294
+ }
5295
+ // If the result is smaller than 25 lines, ensure that it is a
5296
+ // single leaf node.
5297
+ if (this.size - n < 25 &&
5298
+ (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) {
5299
+ var lines = []
5300
+ this.collapse(lines)
5301
+ this.children = [new LeafChunk(lines)]
5302
+ this.children[0].parent = this
5303
+ }
5304
+ },
5305
+ collapse: function(lines) {
5306
+ var this$1 = this;
5307
+
5308
+ for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines) }
5309
+ },
5310
+ insertInner: function(at, lines, height) {
5311
+ var this$1 = this;
5312
+
5313
+ this.size += lines.length
5314
+ this.height += height
5315
+ for (var i = 0; i < this.children.length; ++i) {
5316
+ var child = this$1.children[i], sz = child.chunkSize()
5317
+ if (at <= sz) {
5318
+ child.insertInner(at, lines, height)
5319
+ if (child.lines && child.lines.length > 50) {
5320
+ // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced.
5321
+ // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest.
5322
+ var remaining = child.lines.length % 25 + 25
5323
+ for (var pos = remaining; pos < child.lines.length;) {
5324
+ var leaf = new LeafChunk(child.lines.slice(pos, pos += 25))
5325
+ child.height -= leaf.height
5326
+ this$1.children.splice(++i, 0, leaf)
5327
+ leaf.parent = this$1
5328
+ }
5329
+ child.lines = child.lines.slice(0, remaining)
5330
+ this$1.maybeSpill()
5331
+ }
5332
+ break
5333
+ }
5334
+ at -= sz
5335
+ }
5336
+ },
5337
+ // When a node has grown, check whether it should be split.
5338
+ maybeSpill: function() {
5339
+ if (this.children.length <= 10) { return }
5340
+ var me = this
5341
+ do {
5342
+ var spilled = me.children.splice(me.children.length - 5, 5)
5343
+ var sibling = new BranchChunk(spilled)
5344
+ if (!me.parent) { // Become the parent node
5345
+ var copy = new BranchChunk(me.children)
5346
+ copy.parent = me
5347
+ me.children = [copy, sibling]
5348
+ me = copy
5349
+ } else {
5350
+ me.size -= sibling.size
5351
+ me.height -= sibling.height
5352
+ var myIndex = indexOf(me.parent.children, me)
5353
+ me.parent.children.splice(myIndex + 1, 0, sibling)
5354
+ }
5355
+ sibling.parent = me.parent
5356
+ } while (me.children.length > 10)
5357
+ me.parent.maybeSpill()
5358
+ },
5359
+ iterN: function(at, n, op) {
5360
+ var this$1 = this;
5361
+
5362
+ for (var i = 0; i < this.children.length; ++i) {
5363
+ var child = this$1.children[i], sz = child.chunkSize()
5364
+ if (at < sz) {
5365
+ var used = Math.min(n, sz - at)
5366
+ if (child.iterN(at, used, op)) { return true }
5367
+ if ((n -= used) == 0) { break }
5368
+ at = 0
5369
+ } else { at -= sz }
5370
+ }
5371
+ }
5372
+ }
5373
+
5374
+ // Line widgets are block elements displayed above or below a line.
5375
+
5376
+ function LineWidget(doc, node, options) {
5377
+ var this$1 = this;
5378
+
5379
+ if (options) { for (var opt in options) { if (options.hasOwnProperty(opt))
5380
+ { this$1[opt] = options[opt] } } }
5381
+ this.doc = doc
5382
+ this.node = node
5383
+ }
5384
+ eventMixin(LineWidget)
5385
+
5386
+ function adjustScrollWhenAboveVisible(cm, line, diff) {
5387
+ if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop))
5388
+ { addToScrollPos(cm, null, diff) }
5389
+ }
5390
+
5391
+ LineWidget.prototype.clear = function() {
5392
+ var this$1 = this;
5393
+
5394
+ var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line)
5395
+ if (no == null || !ws) { return }
5396
+ for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1) } }
5397
+ if (!ws.length) { line.widgets = null }
5398
+ var height = widgetHeight(this)
5399
+ updateLineHeight(line, Math.max(0, line.height - height))
5400
+ if (cm) { runInOp(cm, function () {
5401
+ adjustScrollWhenAboveVisible(cm, line, -height)
5402
+ regLineChange(cm, no, "widget")
5403
+ }) }
5404
+ }
5405
+ LineWidget.prototype.changed = function() {
5406
+ var oldH = this.height, cm = this.doc.cm, line = this.line
5407
+ this.height = null
5408
+ var diff = widgetHeight(this) - oldH
5409
+ if (!diff) { return }
5410
+ updateLineHeight(line, line.height + diff)
5411
+ if (cm) { runInOp(cm, function () {
5412
+ cm.curOp.forceUpdate = true
5413
+ adjustScrollWhenAboveVisible(cm, line, diff)
5414
+ }) }
5415
+ }
5416
+
5417
+ function addLineWidget(doc, handle, node, options) {
5418
+ var widget = new LineWidget(doc, node, options)
5419
+ var cm = doc.cm
5420
+ if (cm && widget.noHScroll) { cm.display.alignWidgets = true }
5421
+ changeLine(doc, handle, "widget", function (line) {
5422
+ var widgets = line.widgets || (line.widgets = [])
5423
+ if (widget.insertAt == null) { widgets.push(widget) }
5424
+ else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget) }
5425
+ widget.line = line
5426
+ if (cm && !lineIsHidden(doc, line)) {
5427
+ var aboveVisible = heightAtLine(line) < doc.scrollTop
5428
+ updateLineHeight(line, line.height + widgetHeight(widget))
5429
+ if (aboveVisible) { addToScrollPos(cm, null, widget.height) }
5430
+ cm.curOp.forceUpdate = true
5431
+ }
5432
+ return true
5433
+ })
5434
+ return widget
5435
+ }
5436
+
5437
+ // TEXTMARKERS
5438
+
5439
+ // Created with markText and setBookmark methods. A TextMarker is a
5440
+ // handle that can be used to clear or find a marked position in the
5441
+ // document. Line objects hold arrays (markedSpans) containing
5442
+ // {from, to, marker} object pointing to such marker objects, and
5443
+ // indicating that such a marker is present on that line. Multiple
5444
+ // lines may point to the same marker when it spans across lines.
5445
+ // The spans will have null for their from/to properties when the
5446
+ // marker continues beyond the start/end of the line. Markers have
5447
+ // links back to the lines they currently touch.
5448
+
5449
+ // Collapsed markers have unique ids, in order to be able to order
5450
+ // them, which is needed for uniquely determining an outer marker
5451
+ // when they overlap (they may nest, but not partially overlap).
5452
+ var nextMarkerId = 0
5453
+
5454
+ function TextMarker(doc, type) {
5455
+ this.lines = []
5456
+ this.type = type
5457
+ this.doc = doc
5458
+ this.id = ++nextMarkerId
5459
+ }
5460
+ eventMixin(TextMarker)
5461
+
5462
+ // Clear the marker.
5463
+ TextMarker.prototype.clear = function() {
5464
+ var this$1 = this;
5465
+
5466
+ if (this.explicitlyCleared) { return }
5467
+ var cm = this.doc.cm, withOp = cm && !cm.curOp
5468
+ if (withOp) { startOperation(cm) }
5469
+ if (hasHandler(this, "clear")) {
5470
+ var found = this.find()
5471
+ if (found) { signalLater(this, "clear", found.from, found.to) }
5472
+ }
5473
+ var min = null, max = null
5474
+ for (var i = 0; i < this.lines.length; ++i) {
5475
+ var line = this$1.lines[i]
5476
+ var span = getMarkedSpanFor(line.markedSpans, this$1)
5477
+ if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text") }
5478
+ else if (cm) {
5479
+ if (span.to != null) { max = lineNo(line) }
5480
+ if (span.from != null) { min = lineNo(line) }
5481
+ }
5482
+ line.markedSpans = removeMarkedSpan(line.markedSpans, span)
5483
+ if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm)
5484
+ { updateLineHeight(line, textHeight(cm.display)) }
5485
+ }
5486
+ if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) {
5487
+ var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual)
5488
+ if (len > cm.display.maxLineLength) {
5489
+ cm.display.maxLine = visual
5490
+ cm.display.maxLineLength = len
5491
+ cm.display.maxLineChanged = true
5492
+ }
5493
+ } }
5494
+
5495
+ if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1) }
5496
+ this.lines.length = 0
5497
+ this.explicitlyCleared = true
5498
+ if (this.atomic && this.doc.cantEdit) {
5499
+ this.doc.cantEdit = false
5500
+ if (cm) { reCheckSelection(cm.doc) }
5501
+ }
5502
+ if (cm) { signalLater(cm, "markerCleared", cm, this) }
5503
+ if (withOp) { endOperation(cm) }
5504
+ if (this.parent) { this.parent.clear() }
5505
+ }
5506
+
5507
+ // Find the position of the marker in the document. Returns a {from,
5508
+ // to} object by default. Side can be passed to get a specific side
5509
+ // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the
5510
+ // Pos objects returned contain a line object, rather than a line
5511
+ // number (used to prevent looking up the same line twice).
5512
+ TextMarker.prototype.find = function(side, lineObj) {
5513
+ var this$1 = this;
5514
+
5515
+ if (side == null && this.type == "bookmark") { side = 1 }
5516
+ var from, to
5517
+ for (var i = 0; i < this.lines.length; ++i) {
5518
+ var line = this$1.lines[i]
5519
+ var span = getMarkedSpanFor(line.markedSpans, this$1)
5520
+ if (span.from != null) {
5521
+ from = Pos(lineObj ? line : lineNo(line), span.from)
5522
+ if (side == -1) { return from }
5523
+ }
5524
+ if (span.to != null) {
5525
+ to = Pos(lineObj ? line : lineNo(line), span.to)
5526
+ if (side == 1) { return to }
5527
+ }
5528
+ }
5529
+ return from && {from: from, to: to}
5530
+ }
5531
+
5532
+ // Signals that the marker's widget changed, and surrounding layout
5533
+ // should be recomputed.
5534
+ TextMarker.prototype.changed = function() {
5535
+ var pos = this.find(-1, true), widget = this, cm = this.doc.cm
5536
+ if (!pos || !cm) { return }
5537
+ runInOp(cm, function () {
5538
+ var line = pos.line, lineN = lineNo(pos.line)
5539
+ var view = findViewForLine(cm, lineN)
5540
+ if (view) {
5541
+ clearLineMeasurementCacheFor(view)
5542
+ cm.curOp.selectionChanged = cm.curOp.forceUpdate = true
5543
+ }
5544
+ cm.curOp.updateMaxLine = true
5545
+ if (!lineIsHidden(widget.doc, line) && widget.height != null) {
5546
+ var oldHeight = widget.height
5547
+ widget.height = null
5548
+ var dHeight = widgetHeight(widget) - oldHeight
5549
+ if (dHeight)
5550
+ { updateLineHeight(line, line.height + dHeight) }
5551
+ }
5552
+ })
5553
+ }
5554
+
5555
+ TextMarker.prototype.attachLine = function(line) {
5556
+ if (!this.lines.length && this.doc.cm) {
5557
+ var op = this.doc.cm.curOp
5558
+ if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1)
5559
+ { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this) }
5560
+ }
5561
+ this.lines.push(line)
5562
+ }
5563
+ TextMarker.prototype.detachLine = function(line) {
5564
+ this.lines.splice(indexOf(this.lines, line), 1)
5565
+ if (!this.lines.length && this.doc.cm) {
5566
+ var op = this.doc.cm.curOp
5567
+ ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this)
5568
+ }
5569
+ }
5570
+
5571
+ // Create a marker, wire it up to the right lines, and
5572
+ function markText(doc, from, to, options, type) {
5573
+ // Shared markers (across linked documents) are handled separately
5574
+ // (markTextShared will call out to this again, once per
5575
+ // document).
5576
+ if (options && options.shared) { return markTextShared(doc, from, to, options, type) }
5577
+ // Ensure we are in an operation.
5578
+ if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) }
5579
+
5580
+ var marker = new TextMarker(doc, type), diff = cmp(from, to)
5581
+ if (options) { copyObj(options, marker, false) }
5582
+ // Don't connect empty markers unless clearWhenEmpty is false
5583
+ if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false)
5584
+ { return marker }
5585
+ if (marker.replacedWith) {
5586
+ // Showing up as a widget implies collapsed (widget replaces text)
5587
+ marker.collapsed = true
5588
+ marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget")
5589
+ marker.widgetNode.setAttribute("role", "presentation") // hide from accessibility tree
5590
+ if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true") }
5591
+ if (options.insertLeft) { marker.widgetNode.insertLeft = true }
5592
+ }
5593
+ if (marker.collapsed) {
5594
+ if (conflictingCollapsedRange(doc, from.line, from, to, marker) ||
5595
+ from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker))
5596
+ { throw new Error("Inserting collapsed marker partially overlapping an existing one") }
5597
+ seeCollapsedSpans()
5598
+ }
5599
+
5600
+ if (marker.addToHistory)
5601
+ { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN) }
5602
+
5603
+ var curLine = from.line, cm = doc.cm, updateMaxLine
5604
+ doc.iter(curLine, to.line + 1, function (line) {
5605
+ if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine)
5606
+ { updateMaxLine = true }
5607
+ if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0) }
5608
+ addMarkedSpan(line, new MarkedSpan(marker,
5609
+ curLine == from.line ? from.ch : null,
5610
+ curLine == to.line ? to.ch : null))
5611
+ ++curLine
5612
+ })
5613
+ // lineIsHidden depends on the presence of the spans, so needs a second pass
5614
+ if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) {
5615
+ if (lineIsHidden(doc, line)) { updateLineHeight(line, 0) }
5616
+ }) }
5617
+
5618
+ if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }) }
5619
+
5620
+ if (marker.readOnly) {
5621
+ seeReadOnlySpans()
5622
+ if (doc.history.done.length || doc.history.undone.length)
5623
+ { doc.clearHistory() }
5624
+ }
5625
+ if (marker.collapsed) {
5626
+ marker.id = ++nextMarkerId
5627
+ marker.atomic = true
5628
+ }
5629
+ if (cm) {
5630
+ // Sync editor state
5631
+ if (updateMaxLine) { cm.curOp.updateMaxLine = true }
5632
+ if (marker.collapsed)
5633
+ { regChange(cm, from.line, to.line + 1) }
5634
+ else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css)
5635
+ { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text") } }
5636
+ if (marker.atomic) { reCheckSelection(cm.doc) }
5637
+ signalLater(cm, "markerAdded", cm, marker)
5638
+ }
5639
+ return marker
5640
+ }
5641
+
5642
+ // SHARED TEXTMARKERS
5643
+
5644
+ // A shared marker spans multiple linked documents. It is
5645
+ // implemented as a meta-marker-object controlling multiple normal
5646
+ // markers.
5647
+ function SharedTextMarker(markers, primary) {
5648
+ var this$1 = this;
5649
+
5650
+ this.markers = markers
5651
+ this.primary = primary
5652
+ for (var i = 0; i < markers.length; ++i)
5653
+ { markers[i].parent = this$1 }
5654
+ }
5655
+ eventMixin(SharedTextMarker)
5656
+
5657
+ SharedTextMarker.prototype.clear = function() {
5658
+ var this$1 = this;
5659
+
5660
+ if (this.explicitlyCleared) { return }
5661
+ this.explicitlyCleared = true
5662
+ for (var i = 0; i < this.markers.length; ++i)
5663
+ { this$1.markers[i].clear() }
5664
+ signalLater(this, "clear")
5665
+ }
5666
+ SharedTextMarker.prototype.find = function(side, lineObj) {
5667
+ return this.primary.find(side, lineObj)
5668
+ }
5669
+
5670
+ function markTextShared(doc, from, to, options, type) {
5671
+ options = copyObj(options)
5672
+ options.shared = false
5673
+ var markers = [markText(doc, from, to, options, type)], primary = markers[0]
5674
+ var widget = options.widgetNode
5675
+ linkedDocs(doc, function (doc) {
5676
+ if (widget) { options.widgetNode = widget.cloneNode(true) }
5677
+ markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type))
5678
+ for (var i = 0; i < doc.linked.length; ++i)
5679
+ { if (doc.linked[i].isParent) { return } }
5680
+ primary = lst(markers)
5681
+ })
5682
+ return new SharedTextMarker(markers, primary)
5683
+ }
5684
+
5685
+ function findSharedMarkers(doc) {
5686
+ return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; })
5687
+ }
5688
+
5689
+ function copySharedMarkers(doc, markers) {
5690
+ for (var i = 0; i < markers.length; i++) {
5691
+ var marker = markers[i], pos = marker.find()
5692
+ var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to)
5693
+ if (cmp(mFrom, mTo)) {
5694
+ var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type)
5695
+ marker.markers.push(subMark)
5696
+ subMark.parent = marker
5697
+ }
5698
+ }
5699
+ }
5700
+
5701
+ function detachSharedMarkers(markers) {
5702
+ var loop = function ( i ) {
5703
+ var marker = markers[i], linked = [marker.primary.doc]
5704
+ linkedDocs(marker.primary.doc, function (d) { return linked.push(d); })
5705
+ for (var j = 0; j < marker.markers.length; j++) {
5706
+ var subMarker = marker.markers[j]
5707
+ if (indexOf(linked, subMarker.doc) == -1) {
5708
+ subMarker.parent = null
5709
+ marker.markers.splice(j--, 1)
5710
+ }
5711
+ }
5712
+ };
5713
+
5714
+ for (var i = 0; i < markers.length; i++) loop( i );
5715
+ }
5716
+
5717
+ var nextDocId = 0
5718
+ var Doc = function(text, mode, firstLine, lineSep) {
5719
+ if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep) }
5720
+ if (firstLine == null) { firstLine = 0 }
5721
+
5722
+ BranchChunk.call(this, [new LeafChunk([new Line("", null)])])
5723
+ this.first = firstLine
5724
+ this.scrollTop = this.scrollLeft = 0
5725
+ this.cantEdit = false
5726
+ this.cleanGeneration = 1
5727
+ this.frontier = firstLine
5728
+ var start = Pos(firstLine, 0)
5729
+ this.sel = simpleSelection(start)
5730
+ this.history = new History(null)
5731
+ this.id = ++nextDocId
5732
+ this.modeOption = mode
5733
+ this.lineSep = lineSep
5734
+ this.extend = false
5735
+
5736
+ if (typeof text == "string") { text = this.splitLines(text) }
5737
+ updateDoc(this, {from: start, to: start, text: text})
5738
+ setSelection(this, simpleSelection(start), sel_dontScroll)
5739
+ }
5740
+
5741
+ Doc.prototype = createObj(BranchChunk.prototype, {
5742
+ constructor: Doc,
5743
+ // Iterate over the document. Supports two forms -- with only one
5744
+ // argument, it calls that for each line in the document. With
5745
+ // three, it iterates over the range given by the first two (with
5746
+ // the second being non-inclusive).
5747
+ iter: function(from, to, op) {
5748
+ if (op) { this.iterN(from - this.first, to - from, op) }
5749
+ else { this.iterN(this.first, this.first + this.size, from) }
5750
+ },
5751
+
5752
+ // Non-public interface for adding and removing lines.
5753
+ insert: function(at, lines) {
5754
+ var height = 0
5755
+ for (var i = 0; i < lines.length; ++i) { height += lines[i].height }
5756
+ this.insertInner(at - this.first, lines, height)
5757
+ },
5758
+ remove: function(at, n) { this.removeInner(at - this.first, n) },
5759
+
5760
+ // From here, the methods are part of the public interface. Most
5761
+ // are also available from CodeMirror (editor) instances.
5762
+
5763
+ getValue: function(lineSep) {
5764
+ var lines = getLines(this, this.first, this.first + this.size)
5765
+ if (lineSep === false) { return lines }
5766
+ return lines.join(lineSep || this.lineSeparator())
5767
+ },
5768
+ setValue: docMethodOp(function(code) {
5769
+ var top = Pos(this.first, 0), last = this.first + this.size - 1
5770
+ makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length),
5771
+ text: this.splitLines(code), origin: "setValue", full: true}, true)
5772
+ setSelection(this, simpleSelection(top))
5773
+ }),
5774
+ replaceRange: function(code, from, to, origin) {
5775
+ from = clipPos(this, from)
5776
+ to = to ? clipPos(this, to) : from
5777
+ replaceRange(this, code, from, to, origin)
5778
+ },
5779
+ getRange: function(from, to, lineSep) {
5780
+ var lines = getBetween(this, clipPos(this, from), clipPos(this, to))
5781
+ if (lineSep === false) { return lines }
5782
+ return lines.join(lineSep || this.lineSeparator())
5783
+ },
5784
+
5785
+ getLine: function(line) {var l = this.getLineHandle(line); return l && l.text},
5786
+
5787
+ getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }},
5788
+ getLineNumber: function(line) {return lineNo(line)},
5789
+
5790
+ getLineHandleVisualStart: function(line) {
5791
+ if (typeof line == "number") { line = getLine(this, line) }
5792
+ return visualLine(line)
5793
+ },
5794
+
5795
+ lineCount: function() {return this.size},
5796
+ firstLine: function() {return this.first},
5797
+ lastLine: function() {return this.first + this.size - 1},
5798
+
5799
+ clipPos: function(pos) {return clipPos(this, pos)},
5800
+
5801
+ getCursor: function(start) {
5802
+ var range = this.sel.primary(), pos
5803
+ if (start == null || start == "head") { pos = range.head }
5804
+ else if (start == "anchor") { pos = range.anchor }
5805
+ else if (start == "end" || start == "to" || start === false) { pos = range.to() }
5806
+ else { pos = range.from() }
5807
+ return pos
5808
+ },
5809
+ listSelections: function() { return this.sel.ranges },
5810
+ somethingSelected: function() {return this.sel.somethingSelected()},
5811
+
5812
+ setCursor: docMethodOp(function(line, ch, options) {
5813
+ setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options)
5814
+ }),
5815
+ setSelection: docMethodOp(function(anchor, head, options) {
5816
+ setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options)
5817
+ }),
5818
+ extendSelection: docMethodOp(function(head, other, options) {
5819
+ extendSelection(this, clipPos(this, head), other && clipPos(this, other), options)
5820
+ }),
5821
+ extendSelections: docMethodOp(function(heads, options) {
5822
+ extendSelections(this, clipPosArray(this, heads), options)
5823
+ }),
5824
+ extendSelectionsBy: docMethodOp(function(f, options) {
5825
+ var heads = map(this.sel.ranges, f)
5826
+ extendSelections(this, clipPosArray(this, heads), options)
5827
+ }),
5828
+ setSelections: docMethodOp(function(ranges, primary, options) {
5829
+ var this$1 = this;
5830
+
5831
+ if (!ranges.length) { return }
5832
+ var out = []
5833
+ for (var i = 0; i < ranges.length; i++)
5834
+ { out[i] = new Range(clipPos(this$1, ranges[i].anchor),
5835
+ clipPos(this$1, ranges[i].head)) }
5836
+ if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex) }
5837
+ setSelection(this, normalizeSelection(out, primary), options)
5838
+ }),
5839
+ addSelection: docMethodOp(function(anchor, head, options) {
5840
+ var ranges = this.sel.ranges.slice(0)
5841
+ ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor)))
5842
+ setSelection(this, normalizeSelection(ranges, ranges.length - 1), options)
5843
+ }),
5844
+
5845
+ getSelection: function(lineSep) {
5846
+ var this$1 = this;
5847
+
5848
+ var ranges = this.sel.ranges, lines
5849
+ for (var i = 0; i < ranges.length; i++) {
5850
+ var sel = getBetween(this$1, ranges[i].from(), ranges[i].to())
5851
+ lines = lines ? lines.concat(sel) : sel
5852
+ }
5853
+ if (lineSep === false) { return lines }
5854
+ else { return lines.join(lineSep || this.lineSeparator()) }
5855
+ },
5856
+ getSelections: function(lineSep) {
5857
+ var this$1 = this;
5858
+
5859
+ var parts = [], ranges = this.sel.ranges
5860
+ for (var i = 0; i < ranges.length; i++) {
5861
+ var sel = getBetween(this$1, ranges[i].from(), ranges[i].to())
5862
+ if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()) }
5863
+ parts[i] = sel
5864
+ }
5865
+ return parts
5866
+ },
5867
+ replaceSelection: function(code, collapse, origin) {
5868
+ var dup = []
5869
+ for (var i = 0; i < this.sel.ranges.length; i++)
5870
+ { dup[i] = code }
5871
+ this.replaceSelections(dup, collapse, origin || "+input")
5872
+ },
5873
+ replaceSelections: docMethodOp(function(code, collapse, origin) {
5874
+ var this$1 = this;
5875
+
5876
+ var changes = [], sel = this.sel
5877
+ for (var i = 0; i < sel.ranges.length; i++) {
5878
+ var range = sel.ranges[i]
5879
+ changes[i] = {from: range.from(), to: range.to(), text: this$1.splitLines(code[i]), origin: origin}
5880
+ }
5881
+ var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse)
5882
+ for (var i$1 = changes.length - 1; i$1 >= 0; i$1--)
5883
+ { makeChange(this$1, changes[i$1]) }
5884
+ if (newSel) { setSelectionReplaceHistory(this, newSel) }
5885
+ else if (this.cm) { ensureCursorVisible(this.cm) }
5886
+ }),
5887
+ undo: docMethodOp(function() {makeChangeFromHistory(this, "undo")}),
5888
+ redo: docMethodOp(function() {makeChangeFromHistory(this, "redo")}),
5889
+ undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true)}),
5890
+ redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true)}),
5891
+
5892
+ setExtending: function(val) {this.extend = val},
5893
+ getExtending: function() {return this.extend},
5894
+
5895
+ historySize: function() {
5896
+ var hist = this.history, done = 0, undone = 0
5897
+ for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done } }
5898
+ for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone } }
5899
+ return {undo: done, redo: undone}
5900
+ },
5901
+ clearHistory: function() {this.history = new History(this.history.maxGeneration)},
5902
+
5903
+ markClean: function() {
5904
+ this.cleanGeneration = this.changeGeneration(true)
5905
+ },
5906
+ changeGeneration: function(forceSplit) {
5907
+ if (forceSplit)
5908
+ { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null }
5909
+ return this.history.generation
5910
+ },
5911
+ isClean: function (gen) {
5912
+ return this.history.generation == (gen || this.cleanGeneration)
5913
+ },
5914
+
5915
+ getHistory: function() {
5916
+ return {done: copyHistoryArray(this.history.done),
5917
+ undone: copyHistoryArray(this.history.undone)}
5918
+ },
5919
+ setHistory: function(histData) {
5920
+ var hist = this.history = new History(this.history.maxGeneration)
5921
+ hist.done = copyHistoryArray(histData.done.slice(0), null, true)
5922
+ hist.undone = copyHistoryArray(histData.undone.slice(0), null, true)
5923
+ },
5924
+
5925
+ setGutterMarker: docMethodOp(function(line, gutterID, value) {
5926
+ return changeLine(this, line, "gutter", function (line) {
5927
+ var markers = line.gutterMarkers || (line.gutterMarkers = {})
5928
+ markers[gutterID] = value
5929
+ if (!value && isEmpty(markers)) { line.gutterMarkers = null }
5930
+ return true
5931
+ })
5932
+ }),
5933
+
5934
+ clearGutter: docMethodOp(function(gutterID) {
5935
+ var this$1 = this;
5936
+
5937
+ this.iter(function (line) {
5938
+ if (line.gutterMarkers && line.gutterMarkers[gutterID]) {
5939
+ changeLine(this$1, line, "gutter", function () {
5940
+ line.gutterMarkers[gutterID] = null
5941
+ if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null }
5942
+ return true
5943
+ })
5944
+ }
5945
+ })
5946
+ }),
5947
+
5948
+ lineInfo: function(line) {
5949
+ var n
5950
+ if (typeof line == "number") {
5951
+ if (!isLine(this, line)) { return null }
5952
+ n = line
5953
+ line = getLine(this, line)
5954
+ if (!line) { return null }
5955
+ } else {
5956
+ n = lineNo(line)
5957
+ if (n == null) { return null }
5958
+ }
5959
+ return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers,
5960
+ textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass,
5961
+ widgets: line.widgets}
5962
+ },
5963
+
5964
+ addLineClass: docMethodOp(function(handle, where, cls) {
5965
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
5966
+ var prop = where == "text" ? "textClass"
5967
+ : where == "background" ? "bgClass"
5968
+ : where == "gutter" ? "gutterClass" : "wrapClass"
5969
+ if (!line[prop]) { line[prop] = cls }
5970
+ else if (classTest(cls).test(line[prop])) { return false }
5971
+ else { line[prop] += " " + cls }
5972
+ return true
5973
+ })
5974
+ }),
5975
+ removeLineClass: docMethodOp(function(handle, where, cls) {
5976
+ return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) {
5977
+ var prop = where == "text" ? "textClass"
5978
+ : where == "background" ? "bgClass"
5979
+ : where == "gutter" ? "gutterClass" : "wrapClass"
5980
+ var cur = line[prop]
5981
+ if (!cur) { return false }
5982
+ else if (cls == null) { line[prop] = null }
5983
+ else {
5984
+ var found = cur.match(classTest(cls))
5985
+ if (!found) { return false }
5986
+ var end = found.index + found[0].length
5987
+ line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null
5988
+ }
5989
+ return true
5990
+ })
5991
+ }),
5992
+
5993
+ addLineWidget: docMethodOp(function(handle, node, options) {
5994
+ return addLineWidget(this, handle, node, options)
5995
+ }),
5996
+ removeLineWidget: function(widget) { widget.clear() },
5997
+
5998
+ markText: function(from, to, options) {
5999
+ return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range")
6000
+ },
6001
+ setBookmark: function(pos, options) {
6002
+ var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
6003
+ insertLeft: options && options.insertLeft,
6004
+ clearWhenEmpty: false, shared: options && options.shared,
6005
+ handleMouseEvents: options && options.handleMouseEvents}
6006
+ pos = clipPos(this, pos)
6007
+ return markText(this, pos, pos, realOpts, "bookmark")
6008
+ },
6009
+ findMarksAt: function(pos) {
6010
+ pos = clipPos(this, pos)
6011
+ var markers = [], spans = getLine(this, pos.line).markedSpans
6012
+ if (spans) { for (var i = 0; i < spans.length; ++i) {
6013
+ var span = spans[i]
6014
+ if ((span.from == null || span.from <= pos.ch) &&
6015
+ (span.to == null || span.to >= pos.ch))
6016
+ { markers.push(span.marker.parent || span.marker) }
6017
+ } }
6018
+ return markers
6019
+ },
6020
+ findMarks: function(from, to, filter) {
6021
+ from = clipPos(this, from); to = clipPos(this, to)
6022
+ var found = [], lineNo = from.line
6023
+ this.iter(from.line, to.line + 1, function (line) {
6024
+ var spans = line.markedSpans
6025
+ if (spans) { for (var i = 0; i < spans.length; i++) {
6026
+ var span = spans[i]
6027
+ if (!(span.to != null && lineNo == from.line && from.ch >= span.to ||
6028
+ span.from == null && lineNo != from.line ||
6029
+ span.from != null && lineNo == to.line && span.from >= to.ch) &&
6030
+ (!filter || filter(span.marker)))
6031
+ { found.push(span.marker.parent || span.marker) }
6032
+ } }
6033
+ ++lineNo
6034
+ })
6035
+ return found
6036
+ },
6037
+ getAllMarks: function() {
6038
+ var markers = []
6039
+ this.iter(function (line) {
6040
+ var sps = line.markedSpans
6041
+ if (sps) { for (var i = 0; i < sps.length; ++i)
6042
+ { if (sps[i].from != null) { markers.push(sps[i].marker) } } }
6043
+ })
6044
+ return markers
6045
+ },
6046
+
6047
+ posFromIndex: function(off) {
6048
+ var ch, lineNo = this.first, sepSize = this.lineSeparator().length
6049
+ this.iter(function (line) {
6050
+ var sz = line.text.length + sepSize
6051
+ if (sz > off) { ch = off; return true }
6052
+ off -= sz
6053
+ ++lineNo
6054
+ })
6055
+ return clipPos(this, Pos(lineNo, ch))
6056
+ },
6057
+ indexFromPos: function (coords) {
6058
+ coords = clipPos(this, coords)
6059
+ var index = coords.ch
6060
+ if (coords.line < this.first || coords.ch < 0) { return 0 }
6061
+ var sepSize = this.lineSeparator().length
6062
+ this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value
6063
+ index += line.text.length + sepSize
6064
+ })
6065
+ return index
6066
+ },
6067
+
6068
+ copy: function(copyHistory) {
6069
+ var doc = new Doc(getLines(this, this.first, this.first + this.size),
6070
+ this.modeOption, this.first, this.lineSep)
6071
+ doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft
6072
+ doc.sel = this.sel
6073
+ doc.extend = false
6074
+ if (copyHistory) {
6075
+ doc.history.undoDepth = this.history.undoDepth
6076
+ doc.setHistory(this.getHistory())
6077
+ }
6078
+ return doc
6079
+ },
6080
+
6081
+ linkedDoc: function(options) {
6082
+ if (!options) { options = {} }
6083
+ var from = this.first, to = this.first + this.size
6084
+ if (options.from != null && options.from > from) { from = options.from }
6085
+ if (options.to != null && options.to < to) { to = options.to }
6086
+ var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep)
6087
+ if (options.sharedHist) { copy.history = this.history
6088
+ ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist})
6089
+ copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]
6090
+ copySharedMarkers(copy, findSharedMarkers(this))
6091
+ return copy
6092
+ },
6093
+ unlinkDoc: function(other) {
6094
+ var this$1 = this;
6095
+
6096
+ if (other instanceof CodeMirror) { other = other.doc }
6097
+ if (this.linked) { for (var i = 0; i < this.linked.length; ++i) {
6098
+ var link = this$1.linked[i]
6099
+ if (link.doc != other) { continue }
6100
+ this$1.linked.splice(i, 1)
6101
+ other.unlinkDoc(this$1)
6102
+ detachSharedMarkers(findSharedMarkers(this$1))
6103
+ break
6104
+ } }
6105
+ // If the histories were shared, split them again
6106
+ if (other.history == this.history) {
6107
+ var splitIds = [other.id]
6108
+ linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true)
6109
+ other.history = new History(null)
6110
+ other.history.done = copyHistoryArray(this.history.done, splitIds)
6111
+ other.history.undone = copyHistoryArray(this.history.undone, splitIds)
6112
+ }
6113
+ },
6114
+ iterLinkedDocs: function(f) {linkedDocs(this, f)},
6115
+
6116
+ getMode: function() {return this.mode},
6117
+ getEditor: function() {return this.cm},
6118
+
6119
+ splitLines: function(str) {
6120
+ if (this.lineSep) { return str.split(this.lineSep) }
6121
+ return splitLinesAuto(str)
6122
+ },
6123
+ lineSeparator: function() { return this.lineSep || "\n" }
6124
+ })
6125
+
6126
+ // Public alias.
6127
+ Doc.prototype.eachLine = Doc.prototype.iter
6128
+
6129
+ // Kludge to work around strange IE behavior where it'll sometimes
6130
+ // re-fire a series of drag-related events right after the drop (#1551)
6131
+ var lastDrop = 0
6132
+
6133
+ function onDrop(e) {
6134
+ var cm = this
6135
+ clearDragCursor(cm)
6136
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e))
6137
+ { return }
6138
+ e_preventDefault(e)
6139
+ if (ie) { lastDrop = +new Date }
6140
+ var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files
6141
+ if (!pos || cm.isReadOnly()) { return }
6142
+ // Might be a file drop, in which case we simply extract the text
6143
+ // and insert it.
6144
+ if (files && files.length && window.FileReader && window.File) {
6145
+ var n = files.length, text = Array(n), read = 0
6146
+ var loadFile = function (file, i) {
6147
+ if (cm.options.allowDropFileTypes &&
6148
+ indexOf(cm.options.allowDropFileTypes, file.type) == -1)
6149
+ { return }
6150
+
6151
+ var reader = new FileReader
6152
+ reader.onload = operation(cm, function () {
6153
+ var content = reader.result
6154
+ if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = "" }
6155
+ text[i] = content
6156
+ if (++read == n) {
6157
+ pos = clipPos(cm.doc, pos)
6158
+ var change = {from: pos, to: pos,
6159
+ text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())),
6160
+ origin: "paste"}
6161
+ makeChange(cm.doc, change)
6162
+ setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change)))
6163
+ }
6164
+ })
6165
+ reader.readAsText(file)
6166
+ }
6167
+ for (var i = 0; i < n; ++i) { loadFile(files[i], i) }
6168
+ } else { // Normal drop
6169
+ // Don't do a replace if the drop happened inside of the selected text.
6170
+ if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) {
6171
+ cm.state.draggingText(e)
6172
+ // Ensure the editor is re-focused
6173
+ setTimeout(function () { return cm.display.input.focus(); }, 20)
6174
+ return
6175
+ }
6176
+ try {
6177
+ var text$1 = e.dataTransfer.getData("Text")
6178
+ if (text$1) {
6179
+ var selected
6180
+ if (cm.state.draggingText && !cm.state.draggingText.copy)
6181
+ { selected = cm.listSelections() }
6182
+ setSelectionNoUndo(cm.doc, simpleSelection(pos, pos))
6183
+ if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1)
6184
+ { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag") } }
6185
+ cm.replaceSelection(text$1, "around", "paste")
6186
+ cm.display.input.focus()
6187
+ }
6188
+ }
6189
+ catch(e){}
6190
+ }
6191
+ }
6192
+
6193
+ function onDragStart(cm, e) {
6194
+ if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return }
6195
+ if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return }
6196
+
6197
+ e.dataTransfer.setData("Text", cm.getSelection())
6198
+ e.dataTransfer.effectAllowed = "copyMove"
6199
+
6200
+ // Use dummy image instead of default browsers image.
6201
+ // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there.
6202
+ if (e.dataTransfer.setDragImage && !safari) {
6203
+ var img = elt("img", null, null, "position: fixed; left: 0; top: 0;")
6204
+ img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
6205
+ if (presto) {
6206
+ img.width = img.height = 1
6207
+ cm.display.wrapper.appendChild(img)
6208
+ // Force a relayout, or Opera won't use our image for some obscure reason
6209
+ img._top = img.offsetTop
6210
+ }
6211
+ e.dataTransfer.setDragImage(img, 0, 0)
6212
+ if (presto) { img.parentNode.removeChild(img) }
6213
+ }
6214
+ }
6215
+
6216
+ function onDragOver(cm, e) {
6217
+ var pos = posFromMouse(cm, e)
6218
+ if (!pos) { return }
6219
+ var frag = document.createDocumentFragment()
6220
+ drawSelectionCursor(cm, pos, frag)
6221
+ if (!cm.display.dragCursor) {
6222
+ cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors")
6223
+ cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv)
6224
+ }
6225
+ removeChildrenAndAdd(cm.display.dragCursor, frag)
6226
+ }
6227
+
6228
+ function clearDragCursor(cm) {
6229
+ if (cm.display.dragCursor) {
6230
+ cm.display.lineSpace.removeChild(cm.display.dragCursor)
6231
+ cm.display.dragCursor = null
6232
+ }
6233
+ }
6234
+
6235
+ // These must be handled carefully, because naively registering a
6236
+ // handler for each editor will cause the editors to never be
6237
+ // garbage collected.
6238
+
6239
+ function forEachCodeMirror(f) {
6240
+ if (!document.body.getElementsByClassName) { return }
6241
+ var byClass = document.body.getElementsByClassName("CodeMirror")
6242
+ for (var i = 0; i < byClass.length; i++) {
6243
+ var cm = byClass[i].CodeMirror
6244
+ if (cm) { f(cm) }
6245
+ }
6246
+ }
6247
+
6248
+ var globalsRegistered = false
6249
+ function ensureGlobalHandlers() {
6250
+ if (globalsRegistered) { return }
6251
+ registerGlobalHandlers()
6252
+ globalsRegistered = true
6253
+ }
6254
+ function registerGlobalHandlers() {
6255
+ // When the window resizes, we need to refresh active editors.
6256
+ var resizeTimer
6257
+ on(window, "resize", function () {
6258
+ if (resizeTimer == null) { resizeTimer = setTimeout(function () {
6259
+ resizeTimer = null
6260
+ forEachCodeMirror(onResize)
6261
+ }, 100) }
6262
+ })
6263
+ // When the window loses focus, we want to show the editor as blurred
6264
+ on(window, "blur", function () { return forEachCodeMirror(onBlur); })
6265
+ }
6266
+ // Called when the window resizes
6267
+ function onResize(cm) {
6268
+ var d = cm.display
6269
+ if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth)
6270
+ { return }
6271
+ // Might be a text scaling operation, clear size caches.
6272
+ d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null
6273
+ d.scrollbarsClipped = false
6274
+ cm.setSize()
6275
+ }
6276
+
6277
+ var keyNames = {
6278
+ 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt",
6279
+ 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End",
6280
+ 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert",
6281
+ 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod",
6282
+ 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete",
6283
+ 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\",
6284
+ 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete",
6285
+ 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert"
6286
+ }
6287
+
6288
+ // Number keys
6289
+ for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i) }
6290
+ // Alphabetic keys
6291
+ for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1) }
6292
+ // Function keys
6293
+ for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2 }
6294
+
6295
+ var keyMap = {}
6296
+
6297
+ keyMap.basic = {
6298
+ "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown",
6299
+ "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown",
6300
+ "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore",
6301
+ "Tab": "defaultTab", "Shift-Tab": "indentAuto",
6302
+ "Enter": "newlineAndIndent", "Insert": "toggleOverwrite",
6303
+ "Esc": "singleSelection"
6304
+ }
6305
+ // Note that the save and find-related commands aren't defined by
6306
+ // default. User code or addons can define them. Unknown commands
6307
+ // are simply ignored.
6308
+ keyMap.pcDefault = {
6309
+ "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo",
6310
+ "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown",
6311
+ "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd",
6312
+ "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find",
6313
+ "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll",
6314
+ "Ctrl-[": "indentLess", "Ctrl-]": "indentMore",
6315
+ "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection",
6316
+ fallthrough: "basic"
6317
+ }
6318
+ // Very basic readline/emacs-style bindings, which are standard on Mac.
6319
+ keyMap.emacsy = {
6320
+ "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown",
6321
+ "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
6322
+ "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore",
6323
+ "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars",
6324
+ "Ctrl-O": "openLine"
6325
+ }
6326
+ keyMap.macDefault = {
6327
+ "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo",
6328
+ "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft",
6329
+ "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore",
6330
+ "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find",
6331
+ "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll",
6332
+ "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight",
6333
+ "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd",
6334
+ fallthrough: ["basic", "emacsy"]
6335
+ }
6336
+ keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault
6337
+
6338
+ // KEYMAP DISPATCH
6339
+
6340
+ function normalizeKeyName(name) {
6341
+ var parts = name.split(/-(?!$)/)
6342
+ name = parts[parts.length - 1]
6343
+ var alt, ctrl, shift, cmd
6344
+ for (var i = 0; i < parts.length - 1; i++) {
6345
+ var mod = parts[i]
6346
+ if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true }
6347
+ else if (/^a(lt)?$/i.test(mod)) { alt = true }
6348
+ else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true }
6349
+ else if (/^s(hift)?$/i.test(mod)) { shift = true }
6350
+ else { throw new Error("Unrecognized modifier name: " + mod) }
6351
+ }
6352
+ if (alt) { name = "Alt-" + name }
6353
+ if (ctrl) { name = "Ctrl-" + name }
6354
+ if (cmd) { name = "Cmd-" + name }
6355
+ if (shift) { name = "Shift-" + name }
6356
+ return name
6357
+ }
6358
+
6359
+ // This is a kludge to keep keymaps mostly working as raw objects
6360
+ // (backwards compatibility) while at the same time support features
6361
+ // like normalization and multi-stroke key bindings. It compiles a
6362
+ // new normalized keymap, and then updates the old object to reflect
6363
+ // this.
6364
+ function normalizeKeyMap(keymap) {
6365
+ var copy = {}
6366
+ for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) {
6367
+ var value = keymap[keyname]
6368
+ if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue }
6369
+ if (value == "...") { delete keymap[keyname]; continue }
6370
+
6371
+ var keys = map(keyname.split(" "), normalizeKeyName)
6372
+ for (var i = 0; i < keys.length; i++) {
6373
+ var val = (void 0), name = (void 0)
6374
+ if (i == keys.length - 1) {
6375
+ name = keys.join(" ")
6376
+ val = value
6377
+ } else {
6378
+ name = keys.slice(0, i + 1).join(" ")
6379
+ val = "..."
6380
+ }
6381
+ var prev = copy[name]
6382
+ if (!prev) { copy[name] = val }
6383
+ else if (prev != val) { throw new Error("Inconsistent bindings for " + name) }
6384
+ }
6385
+ delete keymap[keyname]
6386
+ } }
6387
+ for (var prop in copy) { keymap[prop] = copy[prop] }
6388
+ return keymap
6389
+ }
6390
+
6391
+ function lookupKey(key, map, handle, context) {
6392
+ map = getKeyMap(map)
6393
+ var found = map.call ? map.call(key, context) : map[key]
6394
+ if (found === false) { return "nothing" }
6395
+ if (found === "...") { return "multi" }
6396
+ if (found != null && handle(found)) { return "handled" }
6397
+
6398
+ if (map.fallthrough) {
6399
+ if (Object.prototype.toString.call(map.fallthrough) != "[object Array]")
6400
+ { return lookupKey(key, map.fallthrough, handle, context) }
6401
+ for (var i = 0; i < map.fallthrough.length; i++) {
6402
+ var result = lookupKey(key, map.fallthrough[i], handle, context)
6403
+ if (result) { return result }
6404
+ }
6405
+ }
6406
+ }
6407
+
6408
+ // Modifier key presses don't count as 'real' key presses for the
6409
+ // purpose of keymap fallthrough.
6410
+ function isModifierKey(value) {
6411
+ var name = typeof value == "string" ? value : keyNames[value.keyCode]
6412
+ return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"
6413
+ }
6414
+
6415
+ // Look up the name of a key as indicated by an event object.
6416
+ function keyName(event, noShift) {
6417
+ if (presto && event.keyCode == 34 && event["char"]) { return false }
6418
+ var base = keyNames[event.keyCode], name = base
6419
+ if (name == null || event.altGraphKey) { return false }
6420
+ if (event.altKey && base != "Alt") { name = "Alt-" + name }
6421
+ if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name }
6422
+ if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name }
6423
+ if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name }
6424
+ return name
6425
+ }
6426
+
6427
+ function getKeyMap(val) {
6428
+ return typeof val == "string" ? keyMap[val] : val
6429
+ }
6430
+
6431
+ // Helper for deleting text near the selection(s), used to implement
6432
+ // backspace, delete, and similar functionality.
6433
+ function deleteNearSelection(cm, compute) {
6434
+ var ranges = cm.doc.sel.ranges, kill = []
6435
+ // Build up a set of ranges to kill first, merging overlapping
6436
+ // ranges.
6437
+ for (var i = 0; i < ranges.length; i++) {
6438
+ var toKill = compute(ranges[i])
6439
+ while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) {
6440
+ var replaced = kill.pop()
6441
+ if (cmp(replaced.from, toKill.from) < 0) {
6442
+ toKill.from = replaced.from
6443
+ break
6444
+ }
6445
+ }
6446
+ kill.push(toKill)
6447
+ }
6448
+ // Next, remove those actual ranges.
6449
+ runInOp(cm, function () {
6450
+ for (var i = kill.length - 1; i >= 0; i--)
6451
+ { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") }
6452
+ ensureCursorVisible(cm)
6453
+ })
6454
+ }
6455
+
6456
+ // Commands are parameter-less actions that can be performed on an
6457
+ // editor, mostly used for keybindings.
6458
+ var commands = {
6459
+ selectAll: selectAll,
6460
+ singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); },
6461
+ killLine: function (cm) { return deleteNearSelection(cm, function (range) {
6462
+ if (range.empty()) {
6463
+ var len = getLine(cm.doc, range.head.line).text.length
6464
+ if (range.head.ch == len && range.head.line < cm.lastLine())
6465
+ { return {from: range.head, to: Pos(range.head.line + 1, 0)} }
6466
+ else
6467
+ { return {from: range.head, to: Pos(range.head.line, len)} }
6468
+ } else {
6469
+ return {from: range.from(), to: range.to()}
6470
+ }
6471
+ }); },
6472
+ deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({
6473
+ from: Pos(range.from().line, 0),
6474
+ to: clipPos(cm.doc, Pos(range.to().line + 1, 0))
6475
+ }); }); },
6476
+ delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({
6477
+ from: Pos(range.from().line, 0), to: range.from()
6478
+ }); }); },
6479
+ delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) {
6480
+ var top = cm.charCoords(range.head, "div").top + 5
6481
+ var leftPos = cm.coordsChar({left: 0, top: top}, "div")
6482
+ return {from: leftPos, to: range.from()}
6483
+ }); },
6484
+ delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) {
6485
+ var top = cm.charCoords(range.head, "div").top + 5
6486
+ var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
6487
+ return {from: range.from(), to: rightPos }
6488
+ }); },
6489
+ undo: function (cm) { return cm.undo(); },
6490
+ redo: function (cm) { return cm.redo(); },
6491
+ undoSelection: function (cm) { return cm.undoSelection(); },
6492
+ redoSelection: function (cm) { return cm.redoSelection(); },
6493
+ goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); },
6494
+ goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); },
6495
+ goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); },
6496
+ {origin: "+move", bias: 1}
6497
+ ); },
6498
+ goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); },
6499
+ {origin: "+move", bias: 1}
6500
+ ); },
6501
+ goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); },
6502
+ {origin: "+move", bias: -1}
6503
+ ); },
6504
+ goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) {
6505
+ var top = cm.charCoords(range.head, "div").top + 5
6506
+ return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div")
6507
+ }, sel_move); },
6508
+ goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) {
6509
+ var top = cm.charCoords(range.head, "div").top + 5
6510
+ return cm.coordsChar({left: 0, top: top}, "div")
6511
+ }, sel_move); },
6512
+ goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) {
6513
+ var top = cm.charCoords(range.head, "div").top + 5
6514
+ var pos = cm.coordsChar({left: 0, top: top}, "div")
6515
+ if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) }
6516
+ return pos
6517
+ }, sel_move); },
6518
+ goLineUp: function (cm) { return cm.moveV(-1, "line"); },
6519
+ goLineDown: function (cm) { return cm.moveV(1, "line"); },
6520
+ goPageUp: function (cm) { return cm.moveV(-1, "page"); },
6521
+ goPageDown: function (cm) { return cm.moveV(1, "page"); },
6522
+ goCharLeft: function (cm) { return cm.moveH(-1, "char"); },
6523
+ goCharRight: function (cm) { return cm.moveH(1, "char"); },
6524
+ goColumnLeft: function (cm) { return cm.moveH(-1, "column"); },
6525
+ goColumnRight: function (cm) { return cm.moveH(1, "column"); },
6526
+ goWordLeft: function (cm) { return cm.moveH(-1, "word"); },
6527
+ goGroupRight: function (cm) { return cm.moveH(1, "group"); },
6528
+ goGroupLeft: function (cm) { return cm.moveH(-1, "group"); },
6529
+ goWordRight: function (cm) { return cm.moveH(1, "word"); },
6530
+ delCharBefore: function (cm) { return cm.deleteH(-1, "char"); },
6531
+ delCharAfter: function (cm) { return cm.deleteH(1, "char"); },
6532
+ delWordBefore: function (cm) { return cm.deleteH(-1, "word"); },
6533
+ delWordAfter: function (cm) { return cm.deleteH(1, "word"); },
6534
+ delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); },
6535
+ delGroupAfter: function (cm) { return cm.deleteH(1, "group"); },
6536
+ indentAuto: function (cm) { return cm.indentSelection("smart"); },
6537
+ indentMore: function (cm) { return cm.indentSelection("add"); },
6538
+ indentLess: function (cm) { return cm.indentSelection("subtract"); },
6539
+ insertTab: function (cm) { return cm.replaceSelection("\t"); },
6540
+ insertSoftTab: function (cm) {
6541
+ var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize
6542
+ for (var i = 0; i < ranges.length; i++) {
6543
+ var pos = ranges[i].from()
6544
+ var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize)
6545
+ spaces.push(spaceStr(tabSize - col % tabSize))
6546
+ }
6547
+ cm.replaceSelections(spaces)
6548
+ },
6549
+ defaultTab: function (cm) {
6550
+ if (cm.somethingSelected()) { cm.indentSelection("add") }
6551
+ else { cm.execCommand("insertTab") }
6552
+ },
6553
+ // Swap the two chars left and right of each selection's head.
6554
+ // Move cursor behind the two swapped characters afterwards.
6555
+ //
6556
+ // Doesn't consider line feeds a character.
6557
+ // Doesn't scan more than one line above to find a character.
6558
+ // Doesn't do anything on an empty line.
6559
+ // Doesn't do anything with non-empty selections.
6560
+ transposeChars: function (cm) { return runInOp(cm, function () {
6561
+ var ranges = cm.listSelections(), newSel = []
6562
+ for (var i = 0; i < ranges.length; i++) {
6563
+ if (!ranges[i].empty()) { continue }
6564
+ var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text
6565
+ if (line) {
6566
+ if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1) }
6567
+ if (cur.ch > 0) {
6568
+ cur = new Pos(cur.line, cur.ch + 1)
6569
+ cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2),
6570
+ Pos(cur.line, cur.ch - 2), cur, "+transpose")
6571
+ } else if (cur.line > cm.doc.first) {
6572
+ var prev = getLine(cm.doc, cur.line - 1).text
6573
+ if (prev) {
6574
+ cur = new Pos(cur.line, 1)
6575
+ cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() +
6576
+ prev.charAt(prev.length - 1),
6577
+ Pos(cur.line - 1, prev.length - 1), cur, "+transpose")
6578
+ }
6579
+ }
6580
+ }
6581
+ newSel.push(new Range(cur, cur))
6582
+ }
6583
+ cm.setSelections(newSel)
6584
+ }); },
6585
+ newlineAndIndent: function (cm) { return runInOp(cm, function () {
6586
+ var sels = cm.listSelections()
6587
+ for (var i = sels.length - 1; i >= 0; i--)
6588
+ { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input") }
6589
+ sels = cm.listSelections()
6590
+ for (var i$1 = 0; i$1 < sels.length; i$1++)
6591
+ { cm.indentLine(sels[i$1].from().line, null, true) }
6592
+ ensureCursorVisible(cm)
6593
+ }); },
6594
+ openLine: function (cm) { return cm.replaceSelection("\n", "start"); },
6595
+ toggleOverwrite: function (cm) { return cm.toggleOverwrite(); }
6596
+ }
6597
+
6598
+
6599
+ function lineStart(cm, lineN) {
6600
+ var line = getLine(cm.doc, lineN)
6601
+ var visual = visualLine(line)
6602
+ if (visual != line) { lineN = lineNo(visual) }
6603
+ var order = getOrder(visual)
6604
+ var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual)
6605
+ return Pos(lineN, ch)
6606
+ }
6607
+ function lineEnd(cm, lineN) {
6608
+ var merged, line = getLine(cm.doc, lineN)
6609
+ while (merged = collapsedSpanAtEnd(line)) {
6610
+ line = merged.find(1, true).line
6611
+ lineN = null
6612
+ }
6613
+ var order = getOrder(line)
6614
+ var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line)
6615
+ return Pos(lineN == null ? lineNo(line) : lineN, ch)
6616
+ }
6617
+ function lineStartSmart(cm, pos) {
6618
+ var start = lineStart(cm, pos.line)
6619
+ var line = getLine(cm.doc, start.line)
6620
+ var order = getOrder(line)
6621
+ if (!order || order[0].level == 0) {
6622
+ var firstNonWS = Math.max(0, line.text.search(/\S/))
6623
+ var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch
6624
+ return Pos(start.line, inWS ? 0 : firstNonWS)
6625
+ }
6626
+ return start
6627
+ }
6628
+
6629
+ // Run a handler that was bound to a key.
6630
+ function doHandleBinding(cm, bound, dropShift) {
6631
+ if (typeof bound == "string") {
6632
+ bound = commands[bound]
6633
+ if (!bound) { return false }
6634
+ }
6635
+ // Ensure previous input has been read, so that the handler sees a
6636
+ // consistent view of the document
6637
+ cm.display.input.ensurePolled()
6638
+ var prevShift = cm.display.shift, done = false
6639
+ try {
6640
+ if (cm.isReadOnly()) { cm.state.suppressEdits = true }
6641
+ if (dropShift) { cm.display.shift = false }
6642
+ done = bound(cm) != Pass
6643
+ } finally {
6644
+ cm.display.shift = prevShift
6645
+ cm.state.suppressEdits = false
6646
+ }
6647
+ return done
6648
+ }
6649
+
6650
+ function lookupKeyForEditor(cm, name, handle) {
6651
+ for (var i = 0; i < cm.state.keyMaps.length; i++) {
6652
+ var result = lookupKey(name, cm.state.keyMaps[i], handle, cm)
6653
+ if (result) { return result }
6654
+ }
6655
+ return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm))
6656
+ || lookupKey(name, cm.options.keyMap, handle, cm)
6657
+ }
6658
+
6659
+ var stopSeq = new Delayed
6660
+ function dispatchKey(cm, name, e, handle) {
6661
+ var seq = cm.state.keySeq
6662
+ if (seq) {
6663
+ if (isModifierKey(name)) { return "handled" }
6664
+ stopSeq.set(50, function () {
6665
+ if (cm.state.keySeq == seq) {
6666
+ cm.state.keySeq = null
6667
+ cm.display.input.reset()
6668
+ }
6669
+ })
6670
+ name = seq + " " + name
6671
+ }
6672
+ var result = lookupKeyForEditor(cm, name, handle)
6673
+
6674
+ if (result == "multi")
6675
+ { cm.state.keySeq = name }
6676
+ if (result == "handled")
6677
+ { signalLater(cm, "keyHandled", cm, name, e) }
6678
+
6679
+ if (result == "handled" || result == "multi") {
6680
+ e_preventDefault(e)
6681
+ restartBlink(cm)
6682
+ }
6683
+
6684
+ if (seq && !result && /\'$/.test(name)) {
6685
+ e_preventDefault(e)
6686
+ return true
6687
+ }
6688
+ return !!result
6689
+ }
6690
+
6691
+ // Handle a key from the keydown event.
6692
+ function handleKeyBinding(cm, e) {
6693
+ var name = keyName(e, true)
6694
+ if (!name) { return false }
6695
+
6696
+ if (e.shiftKey && !cm.state.keySeq) {
6697
+ // First try to resolve full name (including 'Shift-'). Failing
6698
+ // that, see if there is a cursor-motion command (starting with
6699
+ // 'go') bound to the keyname without 'Shift-'.
6700
+ return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); })
6701
+ || dispatchKey(cm, name, e, function (b) {
6702
+ if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion)
6703
+ { return doHandleBinding(cm, b) }
6704
+ })
6705
+ } else {
6706
+ return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); })
6707
+ }
6708
+ }
6709
+
6710
+ // Handle a key from the keypress event
6711
+ function handleCharBinding(cm, e, ch) {
6712
+ return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); })
6713
+ }
6714
+
6715
+ var lastStoppedKey = null
6716
+ function onKeyDown(e) {
6717
+ var cm = this
6718
+ cm.curOp.focus = activeElt()
6719
+ if (signalDOMEvent(cm, e)) { return }
6720
+ // IE does strange things with escape.
6721
+ if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false }
6722
+ var code = e.keyCode
6723
+ cm.display.shift = code == 16 || e.shiftKey
6724
+ var handled = handleKeyBinding(cm, e)
6725
+ if (presto) {
6726
+ lastStoppedKey = handled ? code : null
6727
+ // Opera has no cut event... we try to at least catch the key combo
6728
+ if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey))
6729
+ { cm.replaceSelection("", null, "cut") }
6730
+ }
6731
+
6732
+ // Turn mouse into crosshair when Alt is held on Mac.
6733
+ if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className))
6734
+ { showCrossHair(cm) }
6735
+ }
6736
+
6737
+ function showCrossHair(cm) {
6738
+ var lineDiv = cm.display.lineDiv
6739
+ addClass(lineDiv, "CodeMirror-crosshair")
6740
+
6741
+ function up(e) {
6742
+ if (e.keyCode == 18 || !e.altKey) {
6743
+ rmClass(lineDiv, "CodeMirror-crosshair")
6744
+ off(document, "keyup", up)
6745
+ off(document, "mouseover", up)
6746
+ }
6747
+ }
6748
+ on(document, "keyup", up)
6749
+ on(document, "mouseover", up)
6750
+ }
6751
+
6752
+ function onKeyUp(e) {
6753
+ if (e.keyCode == 16) { this.doc.sel.shift = false }
6754
+ signalDOMEvent(this, e)
6755
+ }
6756
+
6757
+ function onKeyPress(e) {
6758
+ var cm = this
6759
+ if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return }
6760
+ var keyCode = e.keyCode, charCode = e.charCode
6761
+ if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return}
6762
+ if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return }
6763
+ var ch = String.fromCharCode(charCode == null ? keyCode : charCode)
6764
+ // Some browsers fire keypress events for backspace
6765
+ if (ch == "\x08") { return }
6766
+ if (handleCharBinding(cm, e, ch)) { return }
6767
+ cm.display.input.onKeyPress(e)
6768
+ }
6769
+
6770
+ // A mouse down can be a single click, double click, triple click,
6771
+ // start of selection drag, start of text drag, new cursor
6772
+ // (ctrl-click), rectangle drag (alt-drag), or xwin
6773
+ // middle-click-paste. Or it might be a click on something we should
6774
+ // not interfere with, such as a scrollbar or widget.
6775
+ function onMouseDown(e) {
6776
+ var cm = this, display = cm.display
6777
+ if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return }
6778
+ display.input.ensurePolled()
6779
+ display.shift = e.shiftKey
6780
+
6781
+ if (eventInWidget(display, e)) {
6782
+ if (!webkit) {
6783
+ // Briefly turn off draggability, to allow widgets to do
6784
+ // normal dragging things.
6785
+ display.scroller.draggable = false
6786
+ setTimeout(function () { return display.scroller.draggable = true; }, 100)
6787
+ }
6788
+ return
6789
+ }
6790
+ if (clickInGutter(cm, e)) { return }
6791
+ var start = posFromMouse(cm, e)
6792
+ window.focus()
6793
+
6794
+ switch (e_button(e)) {
6795
+ case 1:
6796
+ // #3261: make sure, that we're not starting a second selection
6797
+ if (cm.state.selectingText)
6798
+ { cm.state.selectingText(e) }
6799
+ else if (start)
6800
+ { leftButtonDown(cm, e, start) }
6801
+ else if (e_target(e) == display.scroller)
6802
+ { e_preventDefault(e) }
6803
+ break
6804
+ case 2:
6805
+ if (webkit) { cm.state.lastMiddleDown = +new Date }
6806
+ if (start) { extendSelection(cm.doc, start) }
6807
+ setTimeout(function () { return display.input.focus(); }, 20)
6808
+ e_preventDefault(e)
6809
+ break
6810
+ case 3:
6811
+ if (captureRightClick) { onContextMenu(cm, e) }
6812
+ else { delayBlurEvent(cm) }
6813
+ break
6814
+ }
6815
+ }
6816
+
6817
+ var lastClick;
6818
+ var lastDoubleClick;
6819
+ function leftButtonDown(cm, e, start) {
6820
+ if (ie) { setTimeout(bind(ensureFocus, cm), 0) }
6821
+ else { cm.curOp.focus = activeElt() }
6822
+
6823
+ var now = +new Date, type
6824
+ if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) {
6825
+ type = "triple"
6826
+ } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) {
6827
+ type = "double"
6828
+ lastDoubleClick = {time: now, pos: start}
6829
+ } else {
6830
+ type = "single"
6831
+ lastClick = {time: now, pos: start}
6832
+ }
6833
+
6834
+ var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained
6835
+ if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() &&
6836
+ type == "single" && (contained = sel.contains(start)) > -1 &&
6837
+ (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) &&
6838
+ (cmp(contained.to(), start) > 0 || start.xRel < 0))
6839
+ { leftButtonStartDrag(cm, e, start, modifier) }
6840
+ else
6841
+ { leftButtonSelect(cm, e, start, type, modifier) }
6842
+ }
6843
+
6844
+ // Start a text drag. When it ends, see if any dragging actually
6845
+ // happen, and treat as a click if it didn't.
6846
+ function leftButtonStartDrag(cm, e, start, modifier) {
6847
+ var display = cm.display, startTime = +new Date
6848
+ var dragEnd = operation(cm, function (e2) {
6849
+ if (webkit) { display.scroller.draggable = false }
6850
+ cm.state.draggingText = false
6851
+ off(document, "mouseup", dragEnd)
6852
+ off(display.scroller, "drop", dragEnd)
6853
+ if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) {
6854
+ e_preventDefault(e2)
6855
+ if (!modifier && +new Date - 200 < startTime)
6856
+ { extendSelection(cm.doc, start) }
6857
+ // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081)
6858
+ if (webkit || ie && ie_version == 9)
6859
+ { setTimeout(function () {document.body.focus(); display.input.focus()}, 20) }
6860
+ else
6861
+ { display.input.focus() }
6862
+ }
6863
+ })
6864
+ // Let the drag handler handle this.
6865
+ if (webkit) { display.scroller.draggable = true }
6866
+ cm.state.draggingText = dragEnd
6867
+ dragEnd.copy = mac ? e.altKey : e.ctrlKey
6868
+ // IE's approach to draggable
6869
+ if (display.scroller.dragDrop) { display.scroller.dragDrop() }
6870
+ on(document, "mouseup", dragEnd)
6871
+ on(display.scroller, "drop", dragEnd)
6872
+ }
6873
+
6874
+ // Normal selection, as opposed to text dragging.
6875
+ function leftButtonSelect(cm, e, start, type, addNew) {
6876
+ var display = cm.display, doc = cm.doc
6877
+ e_preventDefault(e)
6878
+
6879
+ var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges
6880
+ if (addNew && !e.shiftKey) {
6881
+ ourIndex = doc.sel.contains(start)
6882
+ if (ourIndex > -1)
6883
+ { ourRange = ranges[ourIndex] }
6884
+ else
6885
+ { ourRange = new Range(start, start) }
6886
+ } else {
6887
+ ourRange = doc.sel.primary()
6888
+ ourIndex = doc.sel.primIndex
6889
+ }
6890
+
6891
+ if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) {
6892
+ type = "rect"
6893
+ if (!addNew) { ourRange = new Range(start, start) }
6894
+ start = posFromMouse(cm, e, true, true)
6895
+ ourIndex = -1
6896
+ } else if (type == "double") {
6897
+ var word = cm.findWordAt(start)
6898
+ if (cm.display.shift || doc.extend)
6899
+ { ourRange = extendRange(doc, ourRange, word.anchor, word.head) }
6900
+ else
6901
+ { ourRange = word }
6902
+ } else if (type == "triple") {
6903
+ var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0)))
6904
+ if (cm.display.shift || doc.extend)
6905
+ { ourRange = extendRange(doc, ourRange, line.anchor, line.head) }
6906
+ else
6907
+ { ourRange = line }
6908
+ } else {
6909
+ ourRange = extendRange(doc, ourRange, start)
6910
+ }
6911
+
6912
+ if (!addNew) {
6913
+ ourIndex = 0
6914
+ setSelection(doc, new Selection([ourRange], 0), sel_mouse)
6915
+ startSel = doc.sel
6916
+ } else if (ourIndex == -1) {
6917
+ ourIndex = ranges.length
6918
+ setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex),
6919
+ {scroll: false, origin: "*mouse"})
6920
+ } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) {
6921
+ setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0),
6922
+ {scroll: false, origin: "*mouse"})
6923
+ startSel = doc.sel
6924
+ } else {
6925
+ replaceOneSelection(doc, ourIndex, ourRange, sel_mouse)
6926
+ }
6927
+
6928
+ var lastPos = start
6929
+ function extendTo(pos) {
6930
+ if (cmp(lastPos, pos) == 0) { return }
6931
+ lastPos = pos
6932
+
6933
+ if (type == "rect") {
6934
+ var ranges = [], tabSize = cm.options.tabSize
6935
+ var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize)
6936
+ var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize)
6937
+ var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol)
6938
+ for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line));
6939
+ line <= end; line++) {
6940
+ var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize)
6941
+ if (left == right)
6942
+ { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))) }
6943
+ else if (text.length > leftPos)
6944
+ { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))) }
6945
+ }
6946
+ if (!ranges.length) { ranges.push(new Range(start, start)) }
6947
+ setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex),
6948
+ {origin: "*mouse", scroll: false})
6949
+ cm.scrollIntoView(pos)
6950
+ } else {
6951
+ var oldRange = ourRange
6952
+ var anchor = oldRange.anchor, head = pos
6953
+ if (type != "single") {
6954
+ var range
6955
+ if (type == "double")
6956
+ { range = cm.findWordAt(pos) }
6957
+ else
6958
+ { range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))) }
6959
+ if (cmp(range.anchor, anchor) > 0) {
6960
+ head = range.head
6961
+ anchor = minPos(oldRange.from(), range.anchor)
6962
+ } else {
6963
+ head = range.anchor
6964
+ anchor = maxPos(oldRange.to(), range.head)
6965
+ }
6966
+ }
6967
+ var ranges$1 = startSel.ranges.slice(0)
6968
+ ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head)
6969
+ setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse)
6970
+ }
6971
+ }
6972
+
6973
+ var editorSize = display.wrapper.getBoundingClientRect()
6974
+ // Used to ensure timeout re-tries don't fire when another extend
6975
+ // happened in the meantime (clearTimeout isn't reliable -- at
6976
+ // least on Chrome, the timeouts still happen even when cleared,
6977
+ // if the clear happens after their scheduled firing time).
6978
+ var counter = 0
6979
+
6980
+ function extend(e) {
6981
+ var curCount = ++counter
6982
+ var cur = posFromMouse(cm, e, true, type == "rect")
6983
+ if (!cur) { return }
6984
+ if (cmp(cur, lastPos) != 0) {
6985
+ cm.curOp.focus = activeElt()
6986
+ extendTo(cur)
6987
+ var visible = visibleLines(display, doc)
6988
+ if (cur.line >= visible.to || cur.line < visible.from)
6989
+ { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e) }}), 150) }
6990
+ } else {
6991
+ var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0
6992
+ if (outside) { setTimeout(operation(cm, function () {
6993
+ if (counter != curCount) { return }
6994
+ display.scroller.scrollTop += outside
6995
+ extend(e)
6996
+ }), 50) }
6997
+ }
6998
+ }
6999
+
7000
+ function done(e) {
7001
+ cm.state.selectingText = false
7002
+ counter = Infinity
7003
+ e_preventDefault(e)
7004
+ display.input.focus()
7005
+ off(document, "mousemove", move)
7006
+ off(document, "mouseup", up)
7007
+ doc.history.lastSelOrigin = null
7008
+ }
7009
+
7010
+ var move = operation(cm, function (e) {
7011
+ if (!e_button(e)) { done(e) }
7012
+ else { extend(e) }
7013
+ })
7014
+ var up = operation(cm, done)
7015
+ cm.state.selectingText = up
7016
+ on(document, "mousemove", move)
7017
+ on(document, "mouseup", up)
7018
+ }
7019
+
7020
+
7021
+ // Determines whether an event happened in the gutter, and fires the
7022
+ // handlers for the corresponding event.
7023
+ function gutterEvent(cm, e, type, prevent) {
7024
+ var mX, mY
7025
+ try { mX = e.clientX; mY = e.clientY }
7026
+ catch(e) { return false }
7027
+ if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false }
7028
+ if (prevent) { e_preventDefault(e) }
7029
+
7030
+ var display = cm.display
7031
+ var lineBox = display.lineDiv.getBoundingClientRect()
7032
+
7033
+ if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) }
7034
+ mY -= lineBox.top - display.viewOffset
7035
+
7036
+ for (var i = 0; i < cm.options.gutters.length; ++i) {
7037
+ var g = display.gutters.childNodes[i]
7038
+ if (g && g.getBoundingClientRect().right >= mX) {
7039
+ var line = lineAtHeight(cm.doc, mY)
7040
+ var gutter = cm.options.gutters[i]
7041
+ signal(cm, type, cm, line, gutter, e)
7042
+ return e_defaultPrevented(e)
7043
+ }
7044
+ }
7045
+ }
7046
+
7047
+ function clickInGutter(cm, e) {
7048
+ return gutterEvent(cm, e, "gutterClick", true)
7049
+ }
7050
+
7051
+ // CONTEXT MENU HANDLING
7052
+
7053
+ // To make the context menu work, we need to briefly unhide the
7054
+ // textarea (making it as unobtrusive as possible) to let the
7055
+ // right-click take effect on it.
7056
+ function onContextMenu(cm, e) {
7057
+ if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return }
7058
+ if (signalDOMEvent(cm, e, "contextmenu")) { return }
7059
+ cm.display.input.onContextMenu(e)
7060
+ }
7061
+
7062
+ function contextMenuInGutter(cm, e) {
7063
+ if (!hasHandler(cm, "gutterContextMenu")) { return false }
7064
+ return gutterEvent(cm, e, "gutterContextMenu", false)
7065
+ }
7066
+
7067
+ function themeChanged(cm) {
7068
+ cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") +
7069
+ cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-")
7070
+ clearCaches(cm)
7071
+ }
7072
+
7073
+ var Init = {toString: function(){return "CodeMirror.Init"}}
7074
+
7075
+ var defaults = {}
7076
+ var optionHandlers = {}
7077
+
7078
+ function defineOptions(CodeMirror) {
7079
+ var optionHandlers = CodeMirror.optionHandlers
7080
+
7081
+ function option(name, deflt, handle, notOnInit) {
7082
+ CodeMirror.defaults[name] = deflt
7083
+ if (handle) { optionHandlers[name] =
7084
+ notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old) }} : handle }
7085
+ }
7086
+
7087
+ CodeMirror.defineOption = option
7088
+
7089
+ // Passed to option handlers when there is no old value.
7090
+ CodeMirror.Init = Init
7091
+
7092
+ // These two are, on init, called from the constructor because they
7093
+ // have to be initialized before the editor can start at all.
7094
+ option("value", "", function (cm, val) { return cm.setValue(val); }, true)
7095
+ option("mode", null, function (cm, val) {
7096
+ cm.doc.modeOption = val
7097
+ loadMode(cm)
7098
+ }, true)
7099
+
7100
+ option("indentUnit", 2, loadMode, true)
7101
+ option("indentWithTabs", false)
7102
+ option("smartIndent", true)
7103
+ option("tabSize", 4, function (cm) {
7104
+ resetModeState(cm)
7105
+ clearCaches(cm)
7106
+ regChange(cm)
7107
+ }, true)
7108
+ option("lineSeparator", null, function (cm, val) {
7109
+ cm.doc.lineSep = val
7110
+ if (!val) { return }
7111
+ var newBreaks = [], lineNo = cm.doc.first
7112
+ cm.doc.iter(function (line) {
7113
+ for (var pos = 0;;) {
7114
+ var found = line.text.indexOf(val, pos)
7115
+ if (found == -1) { break }
7116
+ pos = found + val.length
7117
+ newBreaks.push(Pos(lineNo, found))
7118
+ }
7119
+ lineNo++
7120
+ })
7121
+ for (var i = newBreaks.length - 1; i >= 0; i--)
7122
+ { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) }
7123
+ })
7124
+ option("specialChars", /[\u0000-\u001f\u007f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) {
7125
+ cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g")
7126
+ if (old != Init) { cm.refresh() }
7127
+ })
7128
+ option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true)
7129
+ option("electricChars", true)
7130
+ option("inputStyle", mobile ? "contenteditable" : "textarea", function () {
7131
+ throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME
7132
+ }, true)
7133
+ option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true)
7134
+ option("rtlMoveVisually", !windows)
7135
+ option("wholeLineUpdateBefore", true)
7136
+
7137
+ option("theme", "default", function (cm) {
7138
+ themeChanged(cm)
7139
+ guttersChanged(cm)
7140
+ }, true)
7141
+ option("keyMap", "default", function (cm, val, old) {
7142
+ var next = getKeyMap(val)
7143
+ var prev = old != Init && getKeyMap(old)
7144
+ if (prev && prev.detach) { prev.detach(cm, next) }
7145
+ if (next.attach) { next.attach(cm, prev || null) }
7146
+ })
7147
+ option("extraKeys", null)
7148
+
7149
+ option("lineWrapping", false, wrappingChanged, true)
7150
+ option("gutters", [], function (cm) {
7151
+ setGuttersForLineNumbers(cm.options)
7152
+ guttersChanged(cm)
7153
+ }, true)
7154
+ option("fixedGutter", true, function (cm, val) {
7155
+ cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"
7156
+ cm.refresh()
7157
+ }, true)
7158
+ option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true)
7159
+ option("scrollbarStyle", "native", function (cm) {
7160
+ initScrollbars(cm)
7161
+ updateScrollbars(cm)
7162
+ cm.display.scrollbars.setScrollTop(cm.doc.scrollTop)
7163
+ cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft)
7164
+ }, true)
7165
+ option("lineNumbers", false, function (cm) {
7166
+ setGuttersForLineNumbers(cm.options)
7167
+ guttersChanged(cm)
7168
+ }, true)
7169
+ option("firstLineNumber", 1, guttersChanged, true)
7170
+ option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true)
7171
+ option("showCursorWhenSelecting", false, updateSelection, true)
7172
+
7173
+ option("resetSelectionOnContextMenu", true)
7174
+ option("lineWiseCopyCut", true)
7175
+
7176
+ option("readOnly", false, function (cm, val) {
7177
+ if (val == "nocursor") {
7178
+ onBlur(cm)
7179
+ cm.display.input.blur()
7180
+ cm.display.disabled = true
7181
+ } else {
7182
+ cm.display.disabled = false
7183
+ }
7184
+ cm.display.input.readOnlyChanged(val)
7185
+ })
7186
+ option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset() }}, true)
7187
+ option("dragDrop", true, dragDropChanged)
7188
+ option("allowDropFileTypes", null)
7189
+
7190
+ option("cursorBlinkRate", 530)
7191
+ option("cursorScrollMargin", 0)
7192
+ option("cursorHeight", 1, updateSelection, true)
7193
+ option("singleCursorHeightPerLine", true, updateSelection, true)
7194
+ option("workTime", 100)
7195
+ option("workDelay", 100)
7196
+ option("flattenSpans", true, resetModeState, true)
7197
+ option("addModeClass", false, resetModeState, true)
7198
+ option("pollInterval", 100)
7199
+ option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; })
7200
+ option("historyEventDelay", 1250)
7201
+ option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true)
7202
+ option("maxHighlightLength", 10000, resetModeState, true)
7203
+ option("moveInputWithCursor", true, function (cm, val) {
7204
+ if (!val) { cm.display.input.resetPosition() }
7205
+ })
7206
+
7207
+ option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; })
7208
+ option("autofocus", null)
7209
+ }
7210
+
7211
+ function guttersChanged(cm) {
7212
+ updateGutters(cm)
7213
+ regChange(cm)
7214
+ alignHorizontally(cm)
7215
+ }
7216
+
7217
+ function dragDropChanged(cm, value, old) {
7218
+ var wasOn = old && old != Init
7219
+ if (!value != !wasOn) {
7220
+ var funcs = cm.display.dragFunctions
7221
+ var toggle = value ? on : off
7222
+ toggle(cm.display.scroller, "dragstart", funcs.start)
7223
+ toggle(cm.display.scroller, "dragenter", funcs.enter)
7224
+ toggle(cm.display.scroller, "dragover", funcs.over)
7225
+ toggle(cm.display.scroller, "dragleave", funcs.leave)
7226
+ toggle(cm.display.scroller, "drop", funcs.drop)
7227
+ }
7228
+ }
7229
+
7230
+ function wrappingChanged(cm) {
7231
+ if (cm.options.lineWrapping) {
7232
+ addClass(cm.display.wrapper, "CodeMirror-wrap")
7233
+ cm.display.sizer.style.minWidth = ""
7234
+ cm.display.sizerWidth = null
7235
+ } else {
7236
+ rmClass(cm.display.wrapper, "CodeMirror-wrap")
7237
+ findMaxLine(cm)
7238
+ }
7239
+ estimateLineHeights(cm)
7240
+ regChange(cm)
7241
+ clearCaches(cm)
7242
+ setTimeout(function () { return updateScrollbars(cm); }, 100)
7243
+ }
7244
+
7245
+ // A CodeMirror instance represents an editor. This is the object
7246
+ // that user code is usually dealing with.
7247
+
7248
+ function CodeMirror(place, options) {
7249
+ var this$1 = this;
7250
+
7251
+ if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) }
7252
+
7253
+ this.options = options = options ? copyObj(options) : {}
7254
+ // Determine effective options based on given values and defaults.
7255
+ copyObj(defaults, options, false)
7256
+ setGuttersForLineNumbers(options)
7257
+
7258
+ var doc = options.value
7259
+ if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator) }
7260
+ this.doc = doc
7261
+
7262
+ var input = new CodeMirror.inputStyles[options.inputStyle](this)
7263
+ var display = this.display = new Display(place, doc, input)
7264
+ display.wrapper.CodeMirror = this
7265
+ updateGutters(this)
7266
+ themeChanged(this)
7267
+ if (options.lineWrapping)
7268
+ { this.display.wrapper.className += " CodeMirror-wrap" }
7269
+ initScrollbars(this)
7270
+
7271
+ this.state = {
7272
+ keyMaps: [], // stores maps added by addKeyMap
7273
+ overlays: [], // highlighting overlays, as added by addOverlay
7274
+ modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info
7275
+ overwrite: false,
7276
+ delayingBlurEvent: false,
7277
+ focused: false,
7278
+ suppressEdits: false, // used to disable editing during key handlers when in readOnly mode
7279
+ pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll
7280
+ selectingText: false,
7281
+ draggingText: false,
7282
+ highlight: new Delayed(), // stores highlight worker timeout
7283
+ keySeq: null, // Unfinished key sequence
7284
+ specialChars: null
7285
+ }
7286
+
7287
+ if (options.autofocus && !mobile) { display.input.focus() }
7288
+
7289
+ // Override magic textarea content restore that IE sometimes does
7290
+ // on our hidden textarea on reload
7291
+ if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20) }
7292
+
7293
+ registerEventHandlers(this)
7294
+ ensureGlobalHandlers()
7295
+
7296
+ startOperation(this)
7297
+ this.curOp.forceUpdate = true
7298
+ attachDoc(this, doc)
7299
+
7300
+ if ((options.autofocus && !mobile) || this.hasFocus())
7301
+ { setTimeout(bind(onFocus, this), 20) }
7302
+ else
7303
+ { onBlur(this) }
7304
+
7305
+ for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt))
7306
+ { optionHandlers[opt](this$1, options[opt], Init) } }
7307
+ maybeUpdateLineNumberWidth(this)
7308
+ if (options.finishInit) { options.finishInit(this) }
7309
+ for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1) }
7310
+ endOperation(this)
7311
+ // Suppress optimizelegibility in Webkit, since it breaks text
7312
+ // measuring on line wrapping boundaries.
7313
+ if (webkit && options.lineWrapping &&
7314
+ getComputedStyle(display.lineDiv).textRendering == "optimizelegibility")
7315
+ { display.lineDiv.style.textRendering = "auto" }
7316
+ }
7317
+
7318
+ // The default configuration options.
7319
+ CodeMirror.defaults = defaults
7320
+ // Functions to run when options are changed.
7321
+ CodeMirror.optionHandlers = optionHandlers
7322
+
7323
+ // Attach the necessary event handlers when initializing the editor
7324
+ function registerEventHandlers(cm) {
7325
+ var d = cm.display
7326
+ on(d.scroller, "mousedown", operation(cm, onMouseDown))
7327
+ // Older IE's will not fire a second mousedown for a double click
7328
+ if (ie && ie_version < 11)
7329
+ { on(d.scroller, "dblclick", operation(cm, function (e) {
7330
+ if (signalDOMEvent(cm, e)) { return }
7331
+ var pos = posFromMouse(cm, e)
7332
+ if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return }
7333
+ e_preventDefault(e)
7334
+ var word = cm.findWordAt(pos)
7335
+ extendSelection(cm.doc, word.anchor, word.head)
7336
+ })) }
7337
+ else
7338
+ { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }) }
7339
+ // Some browsers fire contextmenu *after* opening the menu, at
7340
+ // which point we can't mess with it anymore. Context menu is
7341
+ // handled in onMouseDown for these browsers.
7342
+ if (!captureRightClick) { on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }) }
7343
+
7344
+ // Used to suppress mouse event handling when a touch happens
7345
+ var touchFinished, prevTouch = {end: 0}
7346
+ function finishTouch() {
7347
+ if (d.activeTouch) {
7348
+ touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000)
7349
+ prevTouch = d.activeTouch
7350
+ prevTouch.end = +new Date
7351
+ }
7352
+ }
7353
+ function isMouseLikeTouchEvent(e) {
7354
+ if (e.touches.length != 1) { return false }
7355
+ var touch = e.touches[0]
7356
+ return touch.radiusX <= 1 && touch.radiusY <= 1
7357
+ }
7358
+ function farAway(touch, other) {
7359
+ if (other.left == null) { return true }
7360
+ var dx = other.left - touch.left, dy = other.top - touch.top
7361
+ return dx * dx + dy * dy > 20 * 20
7362
+ }
7363
+ on(d.scroller, "touchstart", function (e) {
7364
+ if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) {
7365
+ d.input.ensurePolled()
7366
+ clearTimeout(touchFinished)
7367
+ var now = +new Date
7368
+ d.activeTouch = {start: now, moved: false,
7369
+ prev: now - prevTouch.end <= 300 ? prevTouch : null}
7370
+ if (e.touches.length == 1) {
7371
+ d.activeTouch.left = e.touches[0].pageX
7372
+ d.activeTouch.top = e.touches[0].pageY
7373
+ }
7374
+ }
7375
+ })
7376
+ on(d.scroller, "touchmove", function () {
7377
+ if (d.activeTouch) { d.activeTouch.moved = true }
7378
+ })
7379
+ on(d.scroller, "touchend", function (e) {
7380
+ var touch = d.activeTouch
7381
+ if (touch && !eventInWidget(d, e) && touch.left != null &&
7382
+ !touch.moved && new Date - touch.start < 300) {
7383
+ var pos = cm.coordsChar(d.activeTouch, "page"), range
7384
+ if (!touch.prev || farAway(touch, touch.prev)) // Single tap
7385
+ { range = new Range(pos, pos) }
7386
+ else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap
7387
+ { range = cm.findWordAt(pos) }
7388
+ else // Triple tap
7389
+ { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) }
7390
+ cm.setSelection(range.anchor, range.head)
7391
+ cm.focus()
7392
+ e_preventDefault(e)
7393
+ }
7394
+ finishTouch()
7395
+ })
7396
+ on(d.scroller, "touchcancel", finishTouch)
7397
+
7398
+ // Sync scrolling between fake scrollbars and real scrollable
7399
+ // area, ensure viewport is updated when scrolling.
7400
+ on(d.scroller, "scroll", function () {
7401
+ if (d.scroller.clientHeight) {
7402
+ setScrollTop(cm, d.scroller.scrollTop)
7403
+ setScrollLeft(cm, d.scroller.scrollLeft, true)
7404
+ signal(cm, "scroll", cm)
7405
+ }
7406
+ })
7407
+
7408
+ // Listen to wheel events in order to try and update the viewport on time.
7409
+ on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); })
7410
+ on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); })
7411
+
7412
+ // Prevent wrapper from ever scrolling
7413
+ on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; })
7414
+
7415
+ d.dragFunctions = {
7416
+ enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e) }},
7417
+ over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }},
7418
+ start: function (e) { return onDragStart(cm, e); },
7419
+ drop: operation(cm, onDrop),
7420
+ leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }}
7421
+ }
7422
+
7423
+ var inp = d.input.getField()
7424
+ on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); })
7425
+ on(inp, "keydown", operation(cm, onKeyDown))
7426
+ on(inp, "keypress", operation(cm, onKeyPress))
7427
+ on(inp, "focus", function (e) { return onFocus(cm, e); })
7428
+ on(inp, "blur", function (e) { return onBlur(cm, e); })
7429
+ }
7430
+
7431
+ var initHooks = []
7432
+ CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }
7433
+
7434
+ // Indent the given line. The how parameter can be "smart",
7435
+ // "add"/null, "subtract", or "prev". When aggressive is false
7436
+ // (typically set to true for forced single-line indents), empty
7437
+ // lines are not indented, and places where the mode returns Pass
7438
+ // are left alone.
7439
+ function indentLine(cm, n, how, aggressive) {
7440
+ var doc = cm.doc, state
7441
+ if (how == null) { how = "add" }
7442
+ if (how == "smart") {
7443
+ // Fall back to "prev" when the mode doesn't have an indentation
7444
+ // method.
7445
+ if (!doc.mode.indent) { how = "prev" }
7446
+ else { state = getStateBefore(cm, n) }
7447
+ }
7448
+
7449
+ var tabSize = cm.options.tabSize
7450
+ var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize)
7451
+ if (line.stateAfter) { line.stateAfter = null }
7452
+ var curSpaceString = line.text.match(/^\s*/)[0], indentation
7453
+ if (!aggressive && !/\S/.test(line.text)) {
7454
+ indentation = 0
7455
+ how = "not"
7456
+ } else if (how == "smart") {
7457
+ indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text)
7458
+ if (indentation == Pass || indentation > 150) {
7459
+ if (!aggressive) { return }
7460
+ how = "prev"
7461
+ }
7462
+ }
7463
+ if (how == "prev") {
7464
+ if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize) }
7465
+ else { indentation = 0 }
7466
+ } else if (how == "add") {
7467
+ indentation = curSpace + cm.options.indentUnit
7468
+ } else if (how == "subtract") {
7469
+ indentation = curSpace - cm.options.indentUnit
7470
+ } else if (typeof how == "number") {
7471
+ indentation = curSpace + how
7472
+ }
7473
+ indentation = Math.max(0, indentation)
7474
+
7475
+ var indentString = "", pos = 0
7476
+ if (cm.options.indentWithTabs)
7477
+ { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t"} }
7478
+ if (pos < indentation) { indentString += spaceStr(indentation - pos) }
7479
+
7480
+ if (indentString != curSpaceString) {
7481
+ replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input")
7482
+ line.stateAfter = null
7483
+ return true
7484
+ } else {
7485
+ // Ensure that, if the cursor was in the whitespace at the start
7486
+ // of the line, it is moved to the end of that space.
7487
+ for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) {
7488
+ var range = doc.sel.ranges[i$1]
7489
+ if (range.head.line == n && range.head.ch < curSpaceString.length) {
7490
+ var pos$1 = Pos(n, curSpaceString.length)
7491
+ replaceOneSelection(doc, i$1, new Range(pos$1, pos$1))
7492
+ break
7493
+ }
7494
+ }
7495
+ }
7496
+ }
7497
+
7498
+ // This will be set to a {lineWise: bool, text: [string]} object, so
7499
+ // that, when pasting, we know what kind of selections the copied
7500
+ // text was made out of.
7501
+ var lastCopied = null
7502
+
7503
+ function setLastCopied(newLastCopied) {
7504
+ lastCopied = newLastCopied
7505
+ }
7506
+
7507
+ function applyTextInput(cm, inserted, deleted, sel, origin) {
7508
+ var doc = cm.doc
7509
+ cm.display.shift = false
7510
+ if (!sel) { sel = doc.sel }
7511
+
7512
+ var paste = cm.state.pasteIncoming || origin == "paste"
7513
+ var textLines = splitLinesAuto(inserted), multiPaste = null
7514
+ // When pasing N lines into N selections, insert one line per selection
7515
+ if (paste && sel.ranges.length > 1) {
7516
+ if (lastCopied && lastCopied.text.join("\n") == inserted) {
7517
+ if (sel.ranges.length % lastCopied.text.length == 0) {
7518
+ multiPaste = []
7519
+ for (var i = 0; i < lastCopied.text.length; i++)
7520
+ { multiPaste.push(doc.splitLines(lastCopied.text[i])) }
7521
+ }
7522
+ } else if (textLines.length == sel.ranges.length) {
7523
+ multiPaste = map(textLines, function (l) { return [l]; })
7524
+ }
7525
+ }
7526
+
7527
+ var updateInput
7528
+ // Normal behavior is to insert the new text into every selection
7529
+ for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) {
7530
+ var range = sel.ranges[i$1]
7531
+ var from = range.from(), to = range.to()
7532
+ if (range.empty()) {
7533
+ if (deleted && deleted > 0) // Handle deletion
7534
+ { from = Pos(from.line, from.ch - deleted) }
7535
+ else if (cm.state.overwrite && !paste) // Handle overwrite
7536
+ { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)) }
7537
+ else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted)
7538
+ { from = to = Pos(from.line, 0) }
7539
+ }
7540
+ updateInput = cm.curOp.updateInput
7541
+ var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines,
7542
+ origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")}
7543
+ makeChange(cm.doc, changeEvent)
7544
+ signalLater(cm, "inputRead", cm, changeEvent)
7545
+ }
7546
+ if (inserted && !paste)
7547
+ { triggerElectric(cm, inserted) }
7548
+
7549
+ ensureCursorVisible(cm)
7550
+ cm.curOp.updateInput = updateInput
7551
+ cm.curOp.typing = true
7552
+ cm.state.pasteIncoming = cm.state.cutIncoming = false
7553
+ }
7554
+
7555
+ function handlePaste(e, cm) {
7556
+ var pasted = e.clipboardData && e.clipboardData.getData("Text")
7557
+ if (pasted) {
7558
+ e.preventDefault()
7559
+ if (!cm.isReadOnly() && !cm.options.disableInput)
7560
+ { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }) }
7561
+ return true
7562
+ }
7563
+ }
7564
+
7565
+ function triggerElectric(cm, inserted) {
7566
+ // When an 'electric' character is inserted, immediately trigger a reindent
7567
+ if (!cm.options.electricChars || !cm.options.smartIndent) { return }
7568
+ var sel = cm.doc.sel
7569
+
7570
+ for (var i = sel.ranges.length - 1; i >= 0; i--) {
7571
+ var range = sel.ranges[i]
7572
+ if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue }
7573
+ var mode = cm.getModeAt(range.head)
7574
+ var indented = false
7575
+ if (mode.electricChars) {
7576
+ for (var j = 0; j < mode.electricChars.length; j++)
7577
+ { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) {
7578
+ indented = indentLine(cm, range.head.line, "smart")
7579
+ break
7580
+ } }
7581
+ } else if (mode.electricInput) {
7582
+ if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch)))
7583
+ { indented = indentLine(cm, range.head.line, "smart") }
7584
+ }
7585
+ if (indented) { signalLater(cm, "electricInput", cm, range.head.line) }
7586
+ }
7587
+ }
7588
+
7589
+ function copyableRanges(cm) {
7590
+ var text = [], ranges = []
7591
+ for (var i = 0; i < cm.doc.sel.ranges.length; i++) {
7592
+ var line = cm.doc.sel.ranges[i].head.line
7593
+ var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}
7594
+ ranges.push(lineRange)
7595
+ text.push(cm.getRange(lineRange.anchor, lineRange.head))
7596
+ }
7597
+ return {text: text, ranges: ranges}
7598
+ }
7599
+
7600
+ function disableBrowserMagic(field, spellcheck) {
7601
+ field.setAttribute("autocorrect", "off")
7602
+ field.setAttribute("autocapitalize", "off")
7603
+ field.setAttribute("spellcheck", !!spellcheck)
7604
+ }
7605
+
7606
+ function hiddenTextarea() {
7607
+ var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none")
7608
+ var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;")
7609
+ // The textarea is kept positioned near the cursor to prevent the
7610
+ // fact that it'll be scrolled into view on input from scrolling
7611
+ // our fake cursor out of view. On webkit, when wrap=off, paste is
7612
+ // very slow. So make the area wide instead.
7613
+ if (webkit) { te.style.width = "1000px" }
7614
+ else { te.setAttribute("wrap", "off") }
7615
+ // If border: 0; -- iOS fails to open keyboard (issue #1287)
7616
+ if (ios) { te.style.border = "1px solid black" }
7617
+ disableBrowserMagic(te)
7618
+ return div
7619
+ }
7620
+
7621
+ // The publicly visible API. Note that methodOp(f) means
7622
+ // 'wrap f in an operation, performed on its `this` parameter'.
7623
+
7624
+ // This is not the complete set of editor methods. Most of the
7625
+ // methods defined on the Doc type are also injected into
7626
+ // CodeMirror.prototype, for backwards compatibility and
7627
+ // convenience.
7628
+
7629
+ function addEditorMethods(CodeMirror) {
7630
+ var optionHandlers = CodeMirror.optionHandlers
7631
+
7632
+ var helpers = CodeMirror.helpers = {}
7633
+
7634
+ CodeMirror.prototype = {
7635
+ constructor: CodeMirror,
7636
+ focus: function(){window.focus(); this.display.input.focus()},
7637
+
7638
+ setOption: function(option, value) {
7639
+ var options = this.options, old = options[option]
7640
+ if (options[option] == value && option != "mode") { return }
7641
+ options[option] = value
7642
+ if (optionHandlers.hasOwnProperty(option))
7643
+ { operation(this, optionHandlers[option])(this, value, old) }
7644
+ signal(this, "optionChange", this, option)
7645
+ },
7646
+
7647
+ getOption: function(option) {return this.options[option]},
7648
+ getDoc: function() {return this.doc},
7649
+
7650
+ addKeyMap: function(map, bottom) {
7651
+ this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map))
7652
+ },
7653
+ removeKeyMap: function(map) {
7654
+ var maps = this.state.keyMaps
7655
+ for (var i = 0; i < maps.length; ++i)
7656
+ { if (maps[i] == map || maps[i].name == map) {
7657
+ maps.splice(i, 1)
7658
+ return true
7659
+ } }
7660
+ },
7661
+
7662
+ addOverlay: methodOp(function(spec, options) {
7663
+ var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec)
7664
+ if (mode.startState) { throw new Error("Overlays may not be stateful.") }
7665
+ insertSorted(this.state.overlays,
7666
+ {mode: mode, modeSpec: spec, opaque: options && options.opaque,
7667
+ priority: (options && options.priority) || 0},
7668
+ function (overlay) { return overlay.priority; })
7669
+ this.state.modeGen++
7670
+ regChange(this)
7671
+ }),
7672
+ removeOverlay: methodOp(function(spec) {
7673
+ var this$1 = this;
7674
+
7675
+ var overlays = this.state.overlays
7676
+ for (var i = 0; i < overlays.length; ++i) {
7677
+ var cur = overlays[i].modeSpec
7678
+ if (cur == spec || typeof spec == "string" && cur.name == spec) {
7679
+ overlays.splice(i, 1)
7680
+ this$1.state.modeGen++
7681
+ regChange(this$1)
7682
+ return
7683
+ }
7684
+ }
7685
+ }),
7686
+
7687
+ indentLine: methodOp(function(n, dir, aggressive) {
7688
+ if (typeof dir != "string" && typeof dir != "number") {
7689
+ if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev" }
7690
+ else { dir = dir ? "add" : "subtract" }
7691
+ }
7692
+ if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive) }
7693
+ }),
7694
+ indentSelection: methodOp(function(how) {
7695
+ var this$1 = this;
7696
+
7697
+ var ranges = this.doc.sel.ranges, end = -1
7698
+ for (var i = 0; i < ranges.length; i++) {
7699
+ var range = ranges[i]
7700
+ if (!range.empty()) {
7701
+ var from = range.from(), to = range.to()
7702
+ var start = Math.max(end, from.line)
7703
+ end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1
7704
+ for (var j = start; j < end; ++j)
7705
+ { indentLine(this$1, j, how) }
7706
+ var newRanges = this$1.doc.sel.ranges
7707
+ if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0)
7708
+ { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll) }
7709
+ } else if (range.head.line > end) {
7710
+ indentLine(this$1, range.head.line, how, true)
7711
+ end = range.head.line
7712
+ if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1) }
7713
+ }
7714
+ }
7715
+ }),
7716
+
7717
+ // Fetch the parser token for a given character. Useful for hacks
7718
+ // that want to inspect the mode state (say, for completion).
7719
+ getTokenAt: function(pos, precise) {
7720
+ return takeToken(this, pos, precise)
7721
+ },
7722
+
7723
+ getLineTokens: function(line, precise) {
7724
+ return takeToken(this, Pos(line), precise, true)
7725
+ },
7726
+
7727
+ getTokenTypeAt: function(pos) {
7728
+ pos = clipPos(this.doc, pos)
7729
+ var styles = getLineStyles(this, getLine(this.doc, pos.line))
7730
+ var before = 0, after = (styles.length - 1) / 2, ch = pos.ch
7731
+ var type
7732
+ if (ch == 0) { type = styles[2] }
7733
+ else { for (;;) {
7734
+ var mid = (before + after) >> 1
7735
+ if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid }
7736
+ else if (styles[mid * 2 + 1] < ch) { before = mid + 1 }
7737
+ else { type = styles[mid * 2 + 2]; break }
7738
+ } }
7739
+ var cut = type ? type.indexOf("overlay ") : -1
7740
+ return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1)
7741
+ },
7742
+
7743
+ getModeAt: function(pos) {
7744
+ var mode = this.doc.mode
7745
+ if (!mode.innerMode) { return mode }
7746
+ return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode
7747
+ },
7748
+
7749
+ getHelper: function(pos, type) {
7750
+ return this.getHelpers(pos, type)[0]
7751
+ },
7752
+
7753
+ getHelpers: function(pos, type) {
7754
+ var this$1 = this;
7755
+
7756
+ var found = []
7757
+ if (!helpers.hasOwnProperty(type)) { return found }
7758
+ var help = helpers[type], mode = this.getModeAt(pos)
7759
+ if (typeof mode[type] == "string") {
7760
+ if (help[mode[type]]) { found.push(help[mode[type]]) }
7761
+ } else if (mode[type]) {
7762
+ for (var i = 0; i < mode[type].length; i++) {
7763
+ var val = help[mode[type][i]]
7764
+ if (val) { found.push(val) }
7765
+ }
7766
+ } else if (mode.helperType && help[mode.helperType]) {
7767
+ found.push(help[mode.helperType])
7768
+ } else if (help[mode.name]) {
7769
+ found.push(help[mode.name])
7770
+ }
7771
+ for (var i$1 = 0; i$1 < help._global.length; i$1++) {
7772
+ var cur = help._global[i$1]
7773
+ if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1)
7774
+ { found.push(cur.val) }
7775
+ }
7776
+ return found
7777
+ },
7778
+
7779
+ getStateAfter: function(line, precise) {
7780
+ var doc = this.doc
7781
+ line = clipLine(doc, line == null ? doc.first + doc.size - 1: line)
7782
+ return getStateBefore(this, line + 1, precise)
7783
+ },
7784
+
7785
+ cursorCoords: function(start, mode) {
7786
+ var pos, range = this.doc.sel.primary()
7787
+ if (start == null) { pos = range.head }
7788
+ else if (typeof start == "object") { pos = clipPos(this.doc, start) }
7789
+ else { pos = start ? range.from() : range.to() }
7790
+ return cursorCoords(this, pos, mode || "page")
7791
+ },
7792
+
7793
+ charCoords: function(pos, mode) {
7794
+ return charCoords(this, clipPos(this.doc, pos), mode || "page")
7795
+ },
7796
+
7797
+ coordsChar: function(coords, mode) {
7798
+ coords = fromCoordSystem(this, coords, mode || "page")
7799
+ return coordsChar(this, coords.left, coords.top)
7800
+ },
7801
+
7802
+ lineAtHeight: function(height, mode) {
7803
+ height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top
7804
+ return lineAtHeight(this.doc, height + this.display.viewOffset)
7805
+ },
7806
+ heightAtLine: function(line, mode, includeWidgets) {
7807
+ var end = false, lineObj
7808
+ if (typeof line == "number") {
7809
+ var last = this.doc.first + this.doc.size - 1
7810
+ if (line < this.doc.first) { line = this.doc.first }
7811
+ else if (line > last) { line = last; end = true }
7812
+ lineObj = getLine(this.doc, line)
7813
+ } else {
7814
+ lineObj = line
7815
+ }
7816
+ return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets).top +
7817
+ (end ? this.doc.height - heightAtLine(lineObj) : 0)
7818
+ },
7819
+
7820
+ defaultTextHeight: function() { return textHeight(this.display) },
7821
+ defaultCharWidth: function() { return charWidth(this.display) },
7822
+
7823
+ getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}},
7824
+
7825
+ addWidget: function(pos, node, scroll, vert, horiz) {
7826
+ var display = this.display
7827
+ pos = cursorCoords(this, clipPos(this.doc, pos))
7828
+ var top = pos.bottom, left = pos.left
7829
+ node.style.position = "absolute"
7830
+ node.setAttribute("cm-ignore-events", "true")
7831
+ this.display.input.setUneditable(node)
7832
+ display.sizer.appendChild(node)
7833
+ if (vert == "over") {
7834
+ top = pos.top
7835
+ } else if (vert == "above" || vert == "near") {
7836
+ var vspace = Math.max(display.wrapper.clientHeight, this.doc.height),
7837
+ hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth)
7838
+ // Default to positioning above (if specified and possible); otherwise default to positioning below
7839
+ if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight)
7840
+ { top = pos.top - node.offsetHeight }
7841
+ else if (pos.bottom + node.offsetHeight <= vspace)
7842
+ { top = pos.bottom }
7843
+ if (left + node.offsetWidth > hspace)
7844
+ { left = hspace - node.offsetWidth }
7845
+ }
7846
+ node.style.top = top + "px"
7847
+ node.style.left = node.style.right = ""
7848
+ if (horiz == "right") {
7849
+ left = display.sizer.clientWidth - node.offsetWidth
7850
+ node.style.right = "0px"
7851
+ } else {
7852
+ if (horiz == "left") { left = 0 }
7853
+ else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2 }
7854
+ node.style.left = left + "px"
7855
+ }
7856
+ if (scroll)
7857
+ { scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight) }
7858
+ },
7859
+
7860
+ triggerOnKeyDown: methodOp(onKeyDown),
7861
+ triggerOnKeyPress: methodOp(onKeyPress),
7862
+ triggerOnKeyUp: onKeyUp,
7863
+
7864
+ execCommand: function(cmd) {
7865
+ if (commands.hasOwnProperty(cmd))
7866
+ { return commands[cmd].call(null, this) }
7867
+ },
7868
+
7869
+ triggerElectric: methodOp(function(text) { triggerElectric(this, text) }),
7870
+
7871
+ findPosH: function(from, amount, unit, visually) {
7872
+ var this$1 = this;
7873
+
7874
+ var dir = 1
7875
+ if (amount < 0) { dir = -1; amount = -amount }
7876
+ var cur = clipPos(this.doc, from)
7877
+ for (var i = 0; i < amount; ++i) {
7878
+ cur = findPosH(this$1.doc, cur, dir, unit, visually)
7879
+ if (cur.hitSide) { break }
7880
+ }
7881
+ return cur
7882
+ },
7883
+
7884
+ moveH: methodOp(function(dir, unit) {
7885
+ var this$1 = this;
7886
+
7887
+ this.extendSelectionsBy(function (range) {
7888
+ if (this$1.display.shift || this$1.doc.extend || range.empty())
7889
+ { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) }
7890
+ else
7891
+ { return dir < 0 ? range.from() : range.to() }
7892
+ }, sel_move)
7893
+ }),
7894
+
7895
+ deleteH: methodOp(function(dir, unit) {
7896
+ var sel = this.doc.sel, doc = this.doc
7897
+ if (sel.somethingSelected())
7898
+ { doc.replaceSelection("", null, "+delete") }
7899
+ else
7900
+ { deleteNearSelection(this, function (range) {
7901
+ var other = findPosH(doc, range.head, dir, unit, false)
7902
+ return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other}
7903
+ }) }
7904
+ }),
7905
+
7906
+ findPosV: function(from, amount, unit, goalColumn) {
7907
+ var this$1 = this;
7908
+
7909
+ var dir = 1, x = goalColumn
7910
+ if (amount < 0) { dir = -1; amount = -amount }
7911
+ var cur = clipPos(this.doc, from)
7912
+ for (var i = 0; i < amount; ++i) {
7913
+ var coords = cursorCoords(this$1, cur, "div")
7914
+ if (x == null) { x = coords.left }
7915
+ else { coords.left = x }
7916
+ cur = findPosV(this$1, coords, dir, unit)
7917
+ if (cur.hitSide) { break }
7918
+ }
7919
+ return cur
7920
+ },
7921
+
7922
+ moveV: methodOp(function(dir, unit) {
7923
+ var this$1 = this;
7924
+
7925
+ var doc = this.doc, goals = []
7926
+ var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected()
7927
+ doc.extendSelectionsBy(function (range) {
7928
+ if (collapse)
7929
+ { return dir < 0 ? range.from() : range.to() }
7930
+ var headPos = cursorCoords(this$1, range.head, "div")
7931
+ if (range.goalColumn != null) { headPos.left = range.goalColumn }
7932
+ goals.push(headPos.left)
7933
+ var pos = findPosV(this$1, headPos, dir, unit)
7934
+ if (unit == "page" && range == doc.sel.primary())
7935
+ { addToScrollPos(this$1, null, charCoords(this$1, pos, "div").top - headPos.top) }
7936
+ return pos
7937
+ }, sel_move)
7938
+ if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++)
7939
+ { doc.sel.ranges[i].goalColumn = goals[i] } }
7940
+ }),
7941
+
7942
+ // Find the word at the given position (as returned by coordsChar).
7943
+ findWordAt: function(pos) {
7944
+ var doc = this.doc, line = getLine(doc, pos.line).text
7945
+ var start = pos.ch, end = pos.ch
7946
+ if (line) {
7947
+ var helper = this.getHelper(pos, "wordChars")
7948
+ if ((pos.xRel < 0 || end == line.length) && start) { --start; } else { ++end }
7949
+ var startChar = line.charAt(start)
7950
+ var check = isWordChar(startChar, helper)
7951
+ ? function (ch) { return isWordChar(ch, helper); }
7952
+ : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); }
7953
+ : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }
7954
+ while (start > 0 && check(line.charAt(start - 1))) { --start }
7955
+ while (end < line.length && check(line.charAt(end))) { ++end }
7956
+ }
7957
+ return new Range(Pos(pos.line, start), Pos(pos.line, end))
7958
+ },
7959
+
7960
+ toggleOverwrite: function(value) {
7961
+ if (value != null && value == this.state.overwrite) { return }
7962
+ if (this.state.overwrite = !this.state.overwrite)
7963
+ { addClass(this.display.cursorDiv, "CodeMirror-overwrite") }
7964
+ else
7965
+ { rmClass(this.display.cursorDiv, "CodeMirror-overwrite") }
7966
+
7967
+ signal(this, "overwriteToggle", this, this.state.overwrite)
7968
+ },
7969
+ hasFocus: function() { return this.display.input.getField() == activeElt() },
7970
+ isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) },
7971
+
7972
+ scrollTo: methodOp(function(x, y) {
7973
+ if (x != null || y != null) { resolveScrollToPos(this) }
7974
+ if (x != null) { this.curOp.scrollLeft = x }
7975
+ if (y != null) { this.curOp.scrollTop = y }
7976
+ }),
7977
+ getScrollInfo: function() {
7978
+ var scroller = this.display.scroller
7979
+ return {left: scroller.scrollLeft, top: scroller.scrollTop,
7980
+ height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight,
7981
+ width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth,
7982
+ clientHeight: displayHeight(this), clientWidth: displayWidth(this)}
7983
+ },
7984
+
7985
+ scrollIntoView: methodOp(function(range, margin) {
7986
+ if (range == null) {
7987
+ range = {from: this.doc.sel.primary().head, to: null}
7988
+ if (margin == null) { margin = this.options.cursorScrollMargin }
7989
+ } else if (typeof range == "number") {
7990
+ range = {from: Pos(range, 0), to: null}
7991
+ } else if (range.from == null) {
7992
+ range = {from: range, to: null}
7993
+ }
7994
+ if (!range.to) { range.to = range.from }
7995
+ range.margin = margin || 0
7996
+
7997
+ if (range.from.line != null) {
7998
+ resolveScrollToPos(this)
7999
+ this.curOp.scrollToPos = range
8000
+ } else {
8001
+ var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left),
8002
+ Math.min(range.from.top, range.to.top) - range.margin,
8003
+ Math.max(range.from.right, range.to.right),
8004
+ Math.max(range.from.bottom, range.to.bottom) + range.margin)
8005
+ this.scrollTo(sPos.scrollLeft, sPos.scrollTop)
8006
+ }
8007
+ }),
8008
+
8009
+ setSize: methodOp(function(width, height) {
8010
+ var this$1 = this;
8011
+
8012
+ var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }
8013
+ if (width != null) { this.display.wrapper.style.width = interpret(width) }
8014
+ if (height != null) { this.display.wrapper.style.height = interpret(height) }
8015
+ if (this.options.lineWrapping) { clearLineMeasurementCache(this) }
8016
+ var lineNo = this.display.viewFrom
8017
+ this.doc.iter(lineNo, this.display.viewTo, function (line) {
8018
+ if (line.widgets) { for (var i = 0; i < line.widgets.length; i++)
8019
+ { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } }
8020
+ ++lineNo
8021
+ })
8022
+ this.curOp.forceUpdate = true
8023
+ signal(this, "refresh", this)
8024
+ }),
8025
+
8026
+ operation: function(f){return runInOp(this, f)},
8027
+
8028
+ refresh: methodOp(function() {
8029
+ var oldHeight = this.display.cachedTextHeight
8030
+ regChange(this)
8031
+ this.curOp.forceUpdate = true
8032
+ clearCaches(this)
8033
+ this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop)
8034
+ updateGutterSpace(this)
8035
+ if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5)
8036
+ { estimateLineHeights(this) }
8037
+ signal(this, "refresh", this)
8038
+ }),
8039
+
8040
+ swapDoc: methodOp(function(doc) {
8041
+ var old = this.doc
8042
+ old.cm = null
8043
+ attachDoc(this, doc)
8044
+ clearCaches(this)
8045
+ this.display.input.reset()
8046
+ this.scrollTo(doc.scrollLeft, doc.scrollTop)
8047
+ this.curOp.forceScroll = true
8048
+ signalLater(this, "swapDoc", this, old)
8049
+ return old
8050
+ }),
8051
+
8052
+ getInputField: function(){return this.display.input.getField()},
8053
+ getWrapperElement: function(){return this.display.wrapper},
8054
+ getScrollerElement: function(){return this.display.scroller},
8055
+ getGutterElement: function(){return this.display.gutters}
8056
+ }
8057
+ eventMixin(CodeMirror)
8058
+
8059
+ CodeMirror.registerHelper = function(type, name, value) {
8060
+ if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []} }
8061
+ helpers[type][name] = value
8062
+ }
8063
+ CodeMirror.registerGlobalHelper = function(type, name, predicate, value) {
8064
+ CodeMirror.registerHelper(type, name, value)
8065
+ helpers[type]._global.push({pred: predicate, val: value})
8066
+ }
8067
+ }
8068
+
8069
+ // Used for horizontal relative motion. Dir is -1 or 1 (left or
8070
+ // right), unit can be "char", "column" (like char, but doesn't
8071
+ // cross line boundaries), "word" (across next word), or "group" (to
8072
+ // the start of next group of word or non-word-non-whitespace
8073
+ // chars). The visually param controls whether, in right-to-left
8074
+ // text, direction 1 means to move towards the next index in the
8075
+ // string, or towards the character to the right of the current
8076
+ // position. The resulting position will have a hitSide=true
8077
+ // property if it reached the end of the document.
8078
+ function findPosH(doc, pos, dir, unit, visually) {
8079
+ var line = pos.line, ch = pos.ch, origDir = dir
8080
+ var lineObj = getLine(doc, line)
8081
+ function findNextLine() {
8082
+ var l = line + dir
8083
+ if (l < doc.first || l >= doc.first + doc.size) { return false }
8084
+ line = l
8085
+ return lineObj = getLine(doc, l)
8086
+ }
8087
+ function moveOnce(boundToLine) {
8088
+ var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true)
8089
+ if (next == null) {
8090
+ if (!boundToLine && findNextLine()) {
8091
+ if (visually) { ch = (dir < 0 ? lineRight : lineLeft)(lineObj) }
8092
+ else { ch = dir < 0 ? lineObj.text.length : 0 }
8093
+ } else { return false }
8094
+ } else { ch = next }
8095
+ return true
8096
+ }
8097
+
8098
+ if (unit == "char") {
8099
+ moveOnce()
8100
+ } else if (unit == "column") {
8101
+ moveOnce(true)
8102
+ } else if (unit == "word" || unit == "group") {
8103
+ var sawType = null, group = unit == "group"
8104
+ var helper = doc.cm && doc.cm.getHelper(pos, "wordChars")
8105
+ for (var first = true;; first = false) {
8106
+ if (dir < 0 && !moveOnce(!first)) { break }
8107
+ var cur = lineObj.text.charAt(ch) || "\n"
8108
+ var type = isWordChar(cur, helper) ? "w"
8109
+ : group && cur == "\n" ? "n"
8110
+ : !group || /\s/.test(cur) ? null
8111
+ : "p"
8112
+ if (group && !first && !type) { type = "s" }
8113
+ if (sawType && sawType != type) {
8114
+ if (dir < 0) {dir = 1; moveOnce()}
8115
+ break
8116
+ }
8117
+
8118
+ if (type) { sawType = type }
8119
+ if (dir > 0 && !moveOnce(!first)) { break }
8120
+ }
8121
+ }
8122
+ var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true)
8123
+ if (!cmp(pos, result)) { result.hitSide = true }
8124
+ return result
8125
+ }
8126
+
8127
+ // For relative vertical movement. Dir may be -1 or 1. Unit can be
8128
+ // "page" or "line". The resulting position will have a hitSide=true
8129
+ // property if it reached the end of the document.
8130
+ function findPosV(cm, pos, dir, unit) {
8131
+ var doc = cm.doc, x = pos.left, y
8132
+ if (unit == "page") {
8133
+ var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight)
8134
+ var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3)
8135
+ y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount
8136
+
8137
+ } else if (unit == "line") {
8138
+ y = dir > 0 ? pos.bottom + 3 : pos.top - 3
8139
+ }
8140
+ var target
8141
+ for (;;) {
8142
+ target = coordsChar(cm, x, y)
8143
+ if (!target.outside) { break }
8144
+ if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break }
8145
+ y += dir * 5
8146
+ }
8147
+ return target
8148
+ }
8149
+
8150
+ // CONTENTEDITABLE INPUT STYLE
8151
+
8152
+ var ContentEditableInput = function(cm) {
8153
+ this.cm = cm
8154
+ this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null
8155
+ this.polling = new Delayed()
8156
+ this.composing = null
8157
+ this.gracePeriod = false
8158
+ this.readDOMTimeout = null
8159
+ };
8160
+
8161
+ ContentEditableInput.prototype.init = function (display) {
8162
+ var this$1 = this;
8163
+
8164
+ var input = this, cm = input.cm
8165
+ var div = input.div = display.lineDiv
8166
+ disableBrowserMagic(div, cm.options.spellcheck)
8167
+
8168
+ on(div, "paste", function (e) {
8169
+ if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
8170
+ // IE doesn't fire input events, so we schedule a read for the pasted content in this way
8171
+ if (ie_version <= 11) { setTimeout(operation(cm, function () {
8172
+ if (!input.pollContent()) { regChange(cm) }
8173
+ }), 20) }
8174
+ })
8175
+
8176
+ on(div, "compositionstart", function (e) {
8177
+ this$1.composing = {data: e.data, done: false}
8178
+ })
8179
+ on(div, "compositionupdate", function (e) {
8180
+ if (!this$1.composing) { this$1.composing = {data: e.data, done: false} }
8181
+ })
8182
+ on(div, "compositionend", function (e) {
8183
+ if (this$1.composing) {
8184
+ if (e.data != this$1.composing.data) { this$1.readFromDOMSoon() }
8185
+ this$1.composing.done = true
8186
+ }
8187
+ })
8188
+
8189
+ on(div, "touchstart", function () { return input.forceCompositionEnd(); })
8190
+
8191
+ on(div, "input", function () {
8192
+ if (!this$1.composing) { this$1.readFromDOMSoon() }
8193
+ })
8194
+
8195
+ function onCopyCut(e) {
8196
+ if (signalDOMEvent(cm, e)) { return }
8197
+ if (cm.somethingSelected()) {
8198
+ setLastCopied({lineWise: false, text: cm.getSelections()})
8199
+ if (e.type == "cut") { cm.replaceSelection("", null, "cut") }
8200
+ } else if (!cm.options.lineWiseCopyCut) {
8201
+ return
8202
+ } else {
8203
+ var ranges = copyableRanges(cm)
8204
+ setLastCopied({lineWise: true, text: ranges.text})
8205
+ if (e.type == "cut") {
8206
+ cm.operation(function () {
8207
+ cm.setSelections(ranges.ranges, 0, sel_dontScroll)
8208
+ cm.replaceSelection("", null, "cut")
8209
+ })
8210
+ }
8211
+ }
8212
+ if (e.clipboardData) {
8213
+ e.clipboardData.clearData()
8214
+ var content = lastCopied.text.join("\n")
8215
+ // iOS exposes the clipboard API, but seems to discard content inserted into it
8216
+ e.clipboardData.setData("Text", content)
8217
+ if (e.clipboardData.getData("Text") == content) {
8218
+ e.preventDefault()
8219
+ return
8220
+ }
8221
+ }
8222
+ // Old-fashioned briefly-focus-a-textarea hack
8223
+ var kludge = hiddenTextarea(), te = kludge.firstChild
8224
+ cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild)
8225
+ te.value = lastCopied.text.join("\n")
8226
+ var hadFocus = document.activeElement
8227
+ selectInput(te)
8228
+ setTimeout(function () {
8229
+ cm.display.lineSpace.removeChild(kludge)
8230
+ hadFocus.focus()
8231
+ if (hadFocus == div) { input.showPrimarySelection() }
8232
+ }, 50)
8233
+ }
8234
+ on(div, "copy", onCopyCut)
8235
+ on(div, "cut", onCopyCut)
8236
+ };
8237
+
8238
+ ContentEditableInput.prototype.prepareSelection = function () {
8239
+ var result = prepareSelection(this.cm, false)
8240
+ result.focus = this.cm.state.focused
8241
+ return result
8242
+ };
8243
+
8244
+ ContentEditableInput.prototype.showSelection = function (info, takeFocus) {
8245
+ if (!info || !this.cm.display.view.length) { return }
8246
+ if (info.focus || takeFocus) { this.showPrimarySelection() }
8247
+ this.showMultipleSelections(info)
8248
+ };
8249
+
8250
+ ContentEditableInput.prototype.showPrimarySelection = function () {
8251
+ var sel = window.getSelection(), prim = this.cm.doc.sel.primary()
8252
+ var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset)
8253
+ var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset)
8254
+ if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad &&
8255
+ cmp(minPos(curAnchor, curFocus), prim.from()) == 0 &&
8256
+ cmp(maxPos(curAnchor, curFocus), prim.to()) == 0)
8257
+ { return }
8258
+
8259
+ var start = posToDOM(this.cm, prim.from())
8260
+ var end = posToDOM(this.cm, prim.to())
8261
+ if (!start && !end) { return }
8262
+
8263
+ var view = this.cm.display.view
8264
+ var old = sel.rangeCount && sel.getRangeAt(0)
8265
+ if (!start) {
8266
+ start = {node: view[0].measure.map[2], offset: 0}
8267
+ } else if (!end) { // FIXME dangerously hacky
8268
+ var measure = view[view.length - 1].measure
8269
+ var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map
8270
+ end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}
8271
+ }
8272
+
8273
+ var rng
8274
+ try { rng = range(start.node, start.offset, end.offset, end.node) }
8275
+ catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible
8276
+ if (rng) {
8277
+ if (!gecko && this.cm.state.focused) {
8278
+ sel.collapse(start.node, start.offset)
8279
+ if (!rng.collapsed) {
8280
+ sel.removeAllRanges()
8281
+ sel.addRange(rng)
8282
+ }
8283
+ } else {
8284
+ sel.removeAllRanges()
8285
+ sel.addRange(rng)
8286
+ }
8287
+ if (old && sel.anchorNode == null) { sel.addRange(old) }
8288
+ else if (gecko) { this.startGracePeriod() }
8289
+ }
8290
+ this.rememberSelection()
8291
+ };
8292
+
8293
+ ContentEditableInput.prototype.startGracePeriod = function () {
8294
+ var this$1 = this;
8295
+
8296
+ clearTimeout(this.gracePeriod)
8297
+ this.gracePeriod = setTimeout(function () {
8298
+ this$1.gracePeriod = false
8299
+ if (this$1.selectionChanged())
8300
+ { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }) }
8301
+ }, 20)
8302
+ };
8303
+
8304
+ ContentEditableInput.prototype.showMultipleSelections = function (info) {
8305
+ removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors)
8306
+ removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection)
8307
+ };
8308
+
8309
+ ContentEditableInput.prototype.rememberSelection = function () {
8310
+ var sel = window.getSelection()
8311
+ this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset
8312
+ this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset
8313
+ };
8314
+
8315
+ ContentEditableInput.prototype.selectionInEditor = function () {
8316
+ var sel = window.getSelection()
8317
+ if (!sel.rangeCount) { return false }
8318
+ var node = sel.getRangeAt(0).commonAncestorContainer
8319
+ return contains(this.div, node)
8320
+ };
8321
+
8322
+ ContentEditableInput.prototype.focus = function () {
8323
+ if (this.cm.options.readOnly != "nocursor") {
8324
+ if (!this.selectionInEditor())
8325
+ { this.showSelection(this.prepareSelection(), true) }
8326
+ this.div.focus()
8327
+ }
8328
+ };
8329
+ ContentEditableInput.prototype.blur = function () { this.div.blur() };
8330
+ ContentEditableInput.prototype.getField = function () { return this.div };
8331
+
8332
+ ContentEditableInput.prototype.supportsTouch = function () { return true };
8333
+
8334
+ ContentEditableInput.prototype.receivedFocus = function () {
8335
+ var input = this
8336
+ if (this.selectionInEditor())
8337
+ { this.pollSelection() }
8338
+ else
8339
+ { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }) }
8340
+
8341
+ function poll() {
8342
+ if (input.cm.state.focused) {
8343
+ input.pollSelection()
8344
+ input.polling.set(input.cm.options.pollInterval, poll)
8345
+ }
8346
+ }
8347
+ this.polling.set(this.cm.options.pollInterval, poll)
8348
+ };
8349
+
8350
+ ContentEditableInput.prototype.selectionChanged = function () {
8351
+ var sel = window.getSelection()
8352
+ return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset ||
8353
+ sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset
8354
+ };
8355
+
8356
+ ContentEditableInput.prototype.pollSelection = function () {
8357
+ if (!this.composing && this.readDOMTimeout == null && !this.gracePeriod && this.selectionChanged()) {
8358
+ var sel = window.getSelection(), cm = this.cm
8359
+ this.rememberSelection()
8360
+ var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset)
8361
+ var head = domToPos(cm, sel.focusNode, sel.focusOffset)
8362
+ if (anchor && head) { runInOp(cm, function () {
8363
+ setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll)
8364
+ if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true }
8365
+ }) }
8366
+ }
8367
+ };
8368
+
8369
+ ContentEditableInput.prototype.pollContent = function () {
8370
+ if (this.readDOMTimeout != null) {
8371
+ clearTimeout(this.readDOMTimeout)
8372
+ this.readDOMTimeout = null
8373
+ }
8374
+
8375
+ var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary()
8376
+ var from = sel.from(), to = sel.to()
8377
+ if (from.ch == 0 && from.line > cm.firstLine())
8378
+ { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length) }
8379
+ if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine())
8380
+ { to = Pos(to.line + 1, 0) }
8381
+ if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false }
8382
+
8383
+ var fromIndex, fromLine, fromNode
8384
+ if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) {
8385
+ fromLine = lineNo(display.view[0].line)
8386
+ fromNode = display.view[0].node
8387
+ } else {
8388
+ fromLine = lineNo(display.view[fromIndex].line)
8389
+ fromNode = display.view[fromIndex - 1].node.nextSibling
8390
+ }
8391
+ var toIndex = findViewIndex(cm, to.line)
8392
+ var toLine, toNode
8393
+ if (toIndex == display.view.length - 1) {
8394
+ toLine = display.viewTo - 1
8395
+ toNode = display.lineDiv.lastChild
8396
+ } else {
8397
+ toLine = lineNo(display.view[toIndex + 1].line) - 1
8398
+ toNode = display.view[toIndex + 1].node.previousSibling
8399
+ }
8400
+
8401
+ if (!fromNode) { return false }
8402
+ var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine))
8403
+ var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length))
8404
+ while (newText.length > 1 && oldText.length > 1) {
8405
+ if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine-- }
8406
+ else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++ }
8407
+ else { break }
8408
+ }
8409
+
8410
+ var cutFront = 0, cutEnd = 0
8411
+ var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length)
8412
+ while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront))
8413
+ { ++cutFront }
8414
+ var newBot = lst(newText), oldBot = lst(oldText)
8415
+ var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0),
8416
+ oldBot.length - (oldText.length == 1 ? cutFront : 0))
8417
+ while (cutEnd < maxCutEnd &&
8418
+ newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1))
8419
+ { ++cutEnd }
8420
+
8421
+ newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "")
8422
+ newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "")
8423
+
8424
+ var chFrom = Pos(fromLine, cutFront)
8425
+ var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0)
8426
+ if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) {
8427
+ replaceRange(cm.doc, newText, chFrom, chTo, "+input")
8428
+ return true
8429
+ }
8430
+ };
8431
+
8432
+ ContentEditableInput.prototype.ensurePolled = function () {
8433
+ this.forceCompositionEnd()
8434
+ };
8435
+ ContentEditableInput.prototype.reset = function () {
8436
+ this.forceCompositionEnd()
8437
+ };
8438
+ ContentEditableInput.prototype.forceCompositionEnd = function () {
8439
+ if (!this.composing) { return }
8440
+ clearTimeout(this.readDOMTimeout)
8441
+ this.composing = null
8442
+ if (!this.pollContent()) { regChange(this.cm) }
8443
+ this.div.blur()
8444
+ this.div.focus()
8445
+ };
8446
+ ContentEditableInput.prototype.readFromDOMSoon = function () {
8447
+ var this$1 = this;
8448
+
8449
+ if (this.readDOMTimeout != null) { return }
8450
+ this.readDOMTimeout = setTimeout(function () {
8451
+ this$1.readDOMTimeout = null
8452
+ if (this$1.composing) {
8453
+ if (this$1.composing.done) { this$1.composing = null }
8454
+ else { return }
8455
+ }
8456
+ if (this$1.cm.isReadOnly() || !this$1.pollContent())
8457
+ { runInOp(this$1.cm, function () { return regChange(this$1.cm); }) }
8458
+ }, 80)
8459
+ };
8460
+
8461
+ ContentEditableInput.prototype.setUneditable = function (node) {
8462
+ node.contentEditable = "false"
8463
+ };
8464
+
8465
+ ContentEditableInput.prototype.onKeyPress = function (e) {
8466
+ e.preventDefault()
8467
+ if (!this.cm.isReadOnly())
8468
+ { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) }
8469
+ };
8470
+
8471
+ ContentEditableInput.prototype.readOnlyChanged = function (val) {
8472
+ this.div.contentEditable = String(val != "nocursor")
8473
+ };
8474
+
8475
+ ContentEditableInput.prototype.onContextMenu = function () {};
8476
+ ContentEditableInput.prototype.resetPosition = function () {};
8477
+
8478
+ ContentEditableInput.prototype.needsContentAttribute = true
8479
+
8480
+ function posToDOM(cm, pos) {
8481
+ var view = findViewForLine(cm, pos.line)
8482
+ if (!view || view.hidden) { return null }
8483
+ var line = getLine(cm.doc, pos.line)
8484
+ var info = mapFromLineView(view, line, pos.line)
8485
+
8486
+ var order = getOrder(line), side = "left"
8487
+ if (order) {
8488
+ var partPos = getBidiPartAt(order, pos.ch)
8489
+ side = partPos % 2 ? "right" : "left"
8490
+ }
8491
+ var result = nodeAndOffsetInLineMap(info.map, pos.ch, side)
8492
+ result.offset = result.collapse == "right" ? result.end : result.start
8493
+ return result
8494
+ }
8495
+
8496
+ function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos }
8497
+
8498
+ function domTextBetween(cm, from, to, fromLine, toLine) {
8499
+ var text = "", closing = false, lineSep = cm.doc.lineSeparator()
8500
+ function recognizeMarker(id) { return function (marker) { return marker.id == id; } }
8501
+ function walk(node) {
8502
+ if (node.nodeType == 1) {
8503
+ var cmText = node.getAttribute("cm-text")
8504
+ if (cmText != null) {
8505
+ if (cmText == "") { text += node.textContent.replace(/\u200b/g, "") }
8506
+ else { text += cmText }
8507
+ return
8508
+ }
8509
+ var markerID = node.getAttribute("cm-marker"), range
8510
+ if (markerID) {
8511
+ var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID))
8512
+ if (found.length && (range = found[0].find()))
8513
+ { text += getBetween(cm.doc, range.from, range.to).join(lineSep) }
8514
+ return
8515
+ }
8516
+ if (node.getAttribute("contenteditable") == "false") { return }
8517
+ for (var i = 0; i < node.childNodes.length; i++)
8518
+ { walk(node.childNodes[i]) }
8519
+ if (/^(pre|div|p)$/i.test(node.nodeName))
8520
+ { closing = true }
8521
+ } else if (node.nodeType == 3) {
8522
+ var val = node.nodeValue
8523
+ if (!val) { return }
8524
+ if (closing) {
8525
+ text += lineSep
8526
+ closing = false
8527
+ }
8528
+ text += val
8529
+ }
8530
+ }
8531
+ for (;;) {
8532
+ walk(from)
8533
+ if (from == to) { break }
8534
+ from = from.nextSibling
8535
+ }
8536
+ return text
8537
+ }
8538
+
8539
+ function domToPos(cm, node, offset) {
8540
+ var lineNode
8541
+ if (node == cm.display.lineDiv) {
8542
+ lineNode = cm.display.lineDiv.childNodes[offset]
8543
+ if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) }
8544
+ node = null; offset = 0
8545
+ } else {
8546
+ for (lineNode = node;; lineNode = lineNode.parentNode) {
8547
+ if (!lineNode || lineNode == cm.display.lineDiv) { return null }
8548
+ if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break }
8549
+ }
8550
+ }
8551
+ for (var i = 0; i < cm.display.view.length; i++) {
8552
+ var lineView = cm.display.view[i]
8553
+ if (lineView.node == lineNode)
8554
+ { return locateNodeInLineView(lineView, node, offset) }
8555
+ }
8556
+ }
8557
+
8558
+ function locateNodeInLineView(lineView, node, offset) {
8559
+ var wrapper = lineView.text.firstChild, bad = false
8560
+ if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) }
8561
+ if (node == wrapper) {
8562
+ bad = true
8563
+ node = wrapper.childNodes[offset]
8564
+ offset = 0
8565
+ if (!node) {
8566
+ var line = lineView.rest ? lst(lineView.rest) : lineView.line
8567
+ return badPos(Pos(lineNo(line), line.text.length), bad)
8568
+ }
8569
+ }
8570
+
8571
+ var textNode = node.nodeType == 3 ? node : null, topNode = node
8572
+ if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) {
8573
+ textNode = node.firstChild
8574
+ if (offset) { offset = textNode.nodeValue.length }
8575
+ }
8576
+ while (topNode.parentNode != wrapper) { topNode = topNode.parentNode }
8577
+ var measure = lineView.measure, maps = measure.maps
8578
+
8579
+ function find(textNode, topNode, offset) {
8580
+ for (var i = -1; i < (maps ? maps.length : 0); i++) {
8581
+ var map = i < 0 ? measure.map : maps[i]
8582
+ for (var j = 0; j < map.length; j += 3) {
8583
+ var curNode = map[j + 2]
8584
+ if (curNode == textNode || curNode == topNode) {
8585
+ var line = lineNo(i < 0 ? lineView.line : lineView.rest[i])
8586
+ var ch = map[j] + offset
8587
+ if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)] }
8588
+ return Pos(line, ch)
8589
+ }
8590
+ }
8591
+ }
8592
+ }
8593
+ var found = find(textNode, topNode, offset)
8594
+ if (found) { return badPos(found, bad) }
8595
+
8596
+ // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems
8597
+ for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) {
8598
+ found = find(after, after.firstChild, 0)
8599
+ if (found)
8600
+ { return badPos(Pos(found.line, found.ch - dist), bad) }
8601
+ else
8602
+ { dist += after.textContent.length }
8603
+ }
8604
+ for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) {
8605
+ found = find(before, before.firstChild, -1)
8606
+ if (found)
8607
+ { return badPos(Pos(found.line, found.ch + dist$1), bad) }
8608
+ else
8609
+ { dist$1 += before.textContent.length }
8610
+ }
8611
+ }
8612
+
8613
+ // TEXTAREA INPUT STYLE
8614
+
8615
+ var TextareaInput = function(cm) {
8616
+ this.cm = cm
8617
+ // See input.poll and input.reset
8618
+ this.prevInput = ""
8619
+
8620
+ // Flag that indicates whether we expect input to appear real soon
8621
+ // now (after some event like 'keypress' or 'input') and are
8622
+ // polling intensively.
8623
+ this.pollingFast = false
8624
+ // Self-resetting timeout for the poller
8625
+ this.polling = new Delayed()
8626
+ // Tracks when input.reset has punted to just putting a short
8627
+ // string into the textarea instead of the full selection.
8628
+ this.inaccurateSelection = false
8629
+ // Used to work around IE issue with selection being forgotten when focus moves away from textarea
8630
+ this.hasSelection = false
8631
+ this.composing = null
8632
+ };
8633
+
8634
+ TextareaInput.prototype.init = function (display) {
8635
+ var this$1 = this;
8636
+
8637
+ var input = this, cm = this.cm
8638
+
8639
+ // Wraps and hides input textarea
8640
+ var div = this.wrapper = hiddenTextarea()
8641
+ // The semihidden textarea that is focused when the editor is
8642
+ // focused, and receives input.
8643
+ var te = this.textarea = div.firstChild
8644
+ display.wrapper.insertBefore(div, display.wrapper.firstChild)
8645
+
8646
+ // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore)
8647
+ if (ios) { te.style.width = "0px" }
8648
+
8649
+ on(te, "input", function () {
8650
+ if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null }
8651
+ input.poll()
8652
+ })
8653
+
8654
+ on(te, "paste", function (e) {
8655
+ if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return }
8656
+
8657
+ cm.state.pasteIncoming = true
8658
+ input.fastPoll()
8659
+ })
8660
+
8661
+ function prepareCopyCut(e) {
8662
+ if (signalDOMEvent(cm, e)) { return }
8663
+ if (cm.somethingSelected()) {
8664
+ setLastCopied({lineWise: false, text: cm.getSelections()})
8665
+ if (input.inaccurateSelection) {
8666
+ input.prevInput = ""
8667
+ input.inaccurateSelection = false
8668
+ te.value = lastCopied.text.join("\n")
8669
+ selectInput(te)
8670
+ }
8671
+ } else if (!cm.options.lineWiseCopyCut) {
8672
+ return
8673
+ } else {
8674
+ var ranges = copyableRanges(cm)
8675
+ setLastCopied({lineWise: true, text: ranges.text})
8676
+ if (e.type == "cut") {
8677
+ cm.setSelections(ranges.ranges, null, sel_dontScroll)
8678
+ } else {
8679
+ input.prevInput = ""
8680
+ te.value = ranges.text.join("\n")
8681
+ selectInput(te)
8682
+ }
8683
+ }
8684
+ if (e.type == "cut") { cm.state.cutIncoming = true }
8685
+ }
8686
+ on(te, "cut", prepareCopyCut)
8687
+ on(te, "copy", prepareCopyCut)
8688
+
8689
+ on(display.scroller, "paste", function (e) {
8690
+ if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return }
8691
+ cm.state.pasteIncoming = true
8692
+ input.focus()
8693
+ })
8694
+
8695
+ // Prevent normal selection in the editor (we handle our own)
8696
+ on(display.lineSpace, "selectstart", function (e) {
8697
+ if (!eventInWidget(display, e)) { e_preventDefault(e) }
8698
+ })
8699
+
8700
+ on(te, "compositionstart", function () {
8701
+ var start = cm.getCursor("from")
8702
+ if (input.composing) { input.composing.range.clear() }
8703
+ input.composing = {
8704
+ start: start,
8705
+ range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"})
8706
+ }
8707
+ })
8708
+ on(te, "compositionend", function () {
8709
+ if (input.composing) {
8710
+ input.poll()
8711
+ input.composing.range.clear()
8712
+ input.composing = null
8713
+ }
8714
+ })
8715
+ };
8716
+
8717
+ TextareaInput.prototype.prepareSelection = function () {
8718
+ // Redraw the selection and/or cursor
8719
+ var cm = this.cm, display = cm.display, doc = cm.doc
8720
+ var result = prepareSelection(cm)
8721
+
8722
+ // Move the hidden textarea near the cursor to prevent scrolling artifacts
8723
+ if (cm.options.moveInputWithCursor) {
8724
+ var headPos = cursorCoords(cm, doc.sel.primary().head, "div")
8725
+ var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect()
8726
+ result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10,
8727
+ headPos.top + lineOff.top - wrapOff.top))
8728
+ result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10,
8729
+ headPos.left + lineOff.left - wrapOff.left))
8730
+ }
8731
+
8732
+ return result
8733
+ };
8734
+
8735
+ TextareaInput.prototype.showSelection = function (drawn) {
8736
+ var cm = this.cm, display = cm.display
8737
+ removeChildrenAndAdd(display.cursorDiv, drawn.cursors)
8738
+ removeChildrenAndAdd(display.selectionDiv, drawn.selection)
8739
+ if (drawn.teTop != null) {
8740
+ this.wrapper.style.top = drawn.teTop + "px"
8741
+ this.wrapper.style.left = drawn.teLeft + "px"
8742
+ }
8743
+ };
8744
+
8745
+ // Reset the input to correspond to the selection (or to be empty,
8746
+ // when not typing and nothing is selected)
8747
+ TextareaInput.prototype.reset = function (typing) {
8748
+ if (this.contextMenuPending) { return }
8749
+ var minimal, selected, cm = this.cm, doc = cm.doc
8750
+ if (cm.somethingSelected()) {
8751
+ this.prevInput = ""
8752
+ var range = doc.sel.primary()
8753
+ minimal = hasCopyEvent &&
8754
+ (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000)
8755
+ var content = minimal ? "-" : selected || cm.getSelection()
8756
+ this.textarea.value = content
8757
+ if (cm.state.focused) { selectInput(this.textarea) }
8758
+ if (ie && ie_version >= 9) { this.hasSelection = content }
8759
+ } else if (!typing) {
8760
+ this.prevInput = this.textarea.value = ""
8761
+ if (ie && ie_version >= 9) { this.hasSelection = null }
8762
+ }
8763
+ this.inaccurateSelection = minimal
8764
+ };
8765
+
8766
+ TextareaInput.prototype.getField = function () { return this.textarea };
8767
+
8768
+ TextareaInput.prototype.supportsTouch = function () { return false };
8769
+
8770
+ TextareaInput.prototype.focus = function () {
8771
+ if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) {
8772
+ try { this.textarea.focus() }
8773
+ catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM
8774
+ }
8775
+ };
8776
+
8777
+ TextareaInput.prototype.blur = function () { this.textarea.blur() };
8778
+
8779
+ TextareaInput.prototype.resetPosition = function () {
8780
+ this.wrapper.style.top = this.wrapper.style.left = 0
8781
+ };
8782
+
8783
+ TextareaInput.prototype.receivedFocus = function () { this.slowPoll() };
8784
+
8785
+ // Poll for input changes, using the normal rate of polling. This
8786
+ // runs as long as the editor is focused.
8787
+ TextareaInput.prototype.slowPoll = function () {
8788
+ var this$1 = this;
8789
+
8790
+ if (this.pollingFast) { return }
8791
+ this.polling.set(this.cm.options.pollInterval, function () {
8792
+ this$1.poll()
8793
+ if (this$1.cm.state.focused) { this$1.slowPoll() }
8794
+ })
8795
+ };
8796
+
8797
+ // When an event has just come in that is likely to add or change
8798
+ // something in the input textarea, we poll faster, to ensure that
8799
+ // the change appears on the screen quickly.
8800
+ TextareaInput.prototype.fastPoll = function () {
8801
+ var missed = false, input = this
8802
+ input.pollingFast = true
8803
+ function p() {
8804
+ var changed = input.poll()
8805
+ if (!changed && !missed) {missed = true; input.polling.set(60, p)}
8806
+ else {input.pollingFast = false; input.slowPoll()}
8807
+ }
8808
+ input.polling.set(20, p)
8809
+ };
8810
+
8811
+ // Read input from the textarea, and update the document to match.
8812
+ // When something is selected, it is present in the textarea, and
8813
+ // selected (unless it is huge, in which case a placeholder is
8814
+ // used). When nothing is selected, the cursor sits after previously
8815
+ // seen text (can be empty), which is stored in prevInput (we must
8816
+ // not reset the textarea when typing, because that breaks IME).
8817
+ TextareaInput.prototype.poll = function () {
8818
+ var this$1 = this;
8819
+
8820
+ var cm = this.cm, input = this.textarea, prevInput = this.prevInput
8821
+ // Since this is called a *lot*, try to bail out as cheaply as
8822
+ // possible when it is clear that nothing happened. hasSelection
8823
+ // will be the case when there is a lot of text in the textarea,
8824
+ // in which case reading its value would be expensive.
8825
+ if (this.contextMenuPending || !cm.state.focused ||
8826
+ (hasSelection(input) && !prevInput && !this.composing) ||
8827
+ cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq)
8828
+ { return false }
8829
+
8830
+ var text = input.value
8831
+ // If nothing changed, bail.
8832
+ if (text == prevInput && !cm.somethingSelected()) { return false }
8833
+ // Work around nonsensical selection resetting in IE9/10, and
8834
+ // inexplicable appearance of private area unicode characters on
8835
+ // some key combos in Mac (#2689).
8836
+ if (ie && ie_version >= 9 && this.hasSelection === text ||
8837
+ mac && /[\uf700-\uf7ff]/.test(text)) {
8838
+ cm.display.input.reset()
8839
+ return false
8840
+ }
8841
+
8842
+ if (cm.doc.sel == cm.display.selForContextMenu) {
8843
+ var first = text.charCodeAt(0)
8844
+ if (first == 0x200b && !prevInput) { prevInput = "\u200b" }
8845
+ if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") }
8846
+ }
8847
+ // Find the part of the input that is actually new
8848
+ var same = 0, l = Math.min(prevInput.length, text.length)
8849
+ while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same }
8850
+
8851
+ runInOp(cm, function () {
8852
+ applyTextInput(cm, text.slice(same), prevInput.length - same,
8853
+ null, this$1.composing ? "*compose" : null)
8854
+
8855
+ // Don't leave long text in the textarea, since it makes further polling slow
8856
+ if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = "" }
8857
+ else { this$1.prevInput = text }
8858
+
8859
+ if (this$1.composing) {
8860
+ this$1.composing.range.clear()
8861
+ this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"),
8862
+ {className: "CodeMirror-composing"})
8863
+ }
8864
+ })
8865
+ return true
8866
+ };
8867
+
8868
+ TextareaInput.prototype.ensurePolled = function () {
8869
+ if (this.pollingFast && this.poll()) { this.pollingFast = false }
8870
+ };
8871
+
8872
+ TextareaInput.prototype.onKeyPress = function () {
8873
+ if (ie && ie_version >= 9) { this.hasSelection = null }
8874
+ this.fastPoll()
8875
+ };
8876
+
8877
+ TextareaInput.prototype.onContextMenu = function (e) {
8878
+ var input = this, cm = input.cm, display = cm.display, te = input.textarea
8879
+ var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop
8880
+ if (!pos || presto) { return } // Opera is difficult.
8881
+
8882
+ // Reset the current text selection only if the click is done outside of the selection
8883
+ // and 'resetSelectionOnContextMenu' option is true.
8884
+ var reset = cm.options.resetSelectionOnContextMenu
8885
+ if (reset && cm.doc.sel.contains(pos) == -1)
8886
+ { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll) }
8887
+
8888
+ var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText
8889
+ input.wrapper.style.cssText = "position: absolute"
8890
+ var wrapperBox = input.wrapper.getBoundingClientRect()
8891
+ te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"
8892
+ var oldScrollY
8893
+ if (webkit) { oldScrollY = window.scrollY } // Work around Chrome issue (#2712)
8894
+ display.input.focus()
8895
+ if (webkit) { window.scrollTo(null, oldScrollY) }
8896
+ display.input.reset()
8897
+ // Adds "Select all" to context menu in FF
8898
+ if (!cm.somethingSelected()) { te.value = input.prevInput = " " }
8899
+ input.contextMenuPending = true
8900
+ display.selForContextMenu = cm.doc.sel
8901
+ clearTimeout(display.detectingSelectAll)
8902
+
8903
+ // Select-all will be greyed out if there's nothing to select, so
8904
+ // this adds a zero-width space so that we can later check whether
8905
+ // it got selected.
8906
+ function prepareSelectAllHack() {
8907
+ if (te.selectionStart != null) {
8908
+ var selected = cm.somethingSelected()
8909
+ var extval = "\u200b" + (selected ? te.value : "")
8910
+ te.value = "\u21da" // Used to catch context-menu undo
8911
+ te.value = extval
8912
+ input.prevInput = selected ? "" : "\u200b"
8913
+ te.selectionStart = 1; te.selectionEnd = extval.length
8914
+ // Re-set this, in case some other handler touched the
8915
+ // selection in the meantime.
8916
+ display.selForContextMenu = cm.doc.sel
8917
+ }
8918
+ }
8919
+ function rehide() {
8920
+ input.contextMenuPending = false
8921
+ input.wrapper.style.cssText = oldWrapperCSS
8922
+ te.style.cssText = oldCSS
8923
+ if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos) }
8924
+
8925
+ // Try to detect the user choosing select-all
8926
+ if (te.selectionStart != null) {
8927
+ if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack() }
8928
+ var i = 0, poll = function () {
8929
+ if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 &&
8930
+ te.selectionEnd > 0 && input.prevInput == "\u200b")
8931
+ { operation(cm, selectAll)(cm) }
8932
+ else if (i++ < 10) { display.detectingSelectAll = setTimeout(poll, 500) }
8933
+ else { display.input.reset() }
8934
+ }
8935
+ display.detectingSelectAll = setTimeout(poll, 200)
8936
+ }
8937
+ }
8938
+
8939
+ if (ie && ie_version >= 9) { prepareSelectAllHack() }
8940
+ if (captureRightClick) {
8941
+ e_stop(e)
8942
+ var mouseup = function () {
8943
+ off(window, "mouseup", mouseup)
8944
+ setTimeout(rehide, 20)
8945
+ }
8946
+ on(window, "mouseup", mouseup)
8947
+ } else {
8948
+ setTimeout(rehide, 50)
8949
+ }
8950
+ };
8951
+
8952
+ TextareaInput.prototype.readOnlyChanged = function (val) {
8953
+ if (!val) { this.reset() }
8954
+ };
8955
+
8956
+ TextareaInput.prototype.setUneditable = function () {};
8957
+
8958
+ TextareaInput.prototype.needsContentAttribute = false
8959
+
8960
+ function fromTextArea(textarea, options) {
8961
+ options = options ? copyObj(options) : {}
8962
+ options.value = textarea.value
8963
+ if (!options.tabindex && textarea.tabIndex)
8964
+ { options.tabindex = textarea.tabIndex }
8965
+ if (!options.placeholder && textarea.placeholder)
8966
+ { options.placeholder = textarea.placeholder }
8967
+ // Set autofocus to true if this textarea is focused, or if it has
8968
+ // autofocus and no other element is focused.
8969
+ if (options.autofocus == null) {
8970
+ var hasFocus = activeElt()
8971
+ options.autofocus = hasFocus == textarea ||
8972
+ textarea.getAttribute("autofocus") != null && hasFocus == document.body
8973
+ }
8974
+
8975
+ function save() {textarea.value = cm.getValue()}
8976
+
8977
+ var realSubmit
8978
+ if (textarea.form) {
8979
+ on(textarea.form, "submit", save)
8980
+ // Deplorable hack to make the submit method do the right thing.
8981
+ if (!options.leaveSubmitMethodAlone) {
8982
+ var form = textarea.form
8983
+ realSubmit = form.submit
8984
+ try {
8985
+ var wrappedSubmit = form.submit = function () {
8986
+ save()
8987
+ form.submit = realSubmit
8988
+ form.submit()
8989
+ form.submit = wrappedSubmit
8990
+ }
8991
+ } catch(e) {}
8992
+ }
8993
+ }
8994
+
8995
+ options.finishInit = function (cm) {
8996
+ cm.save = save
8997
+ cm.getTextArea = function () { return textarea; }
8998
+ cm.toTextArea = function () {
8999
+ cm.toTextArea = isNaN // Prevent this from being ran twice
9000
+ save()
9001
+ textarea.parentNode.removeChild(cm.getWrapperElement())
9002
+ textarea.style.display = ""
9003
+ if (textarea.form) {
9004
+ off(textarea.form, "submit", save)
9005
+ if (typeof textarea.form.submit == "function")
9006
+ { textarea.form.submit = realSubmit }
9007
+ }
9008
+ }
9009
+ }
9010
+
9011
+ textarea.style.display = "none"
9012
+ var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); },
9013
+ options)
9014
+ return cm
9015
+ }
9016
+
9017
+ function addLegacyProps(CodeMirror) {
9018
+ CodeMirror.off = off
9019
+ CodeMirror.on = on
9020
+ CodeMirror.wheelEventPixels = wheelEventPixels
9021
+ CodeMirror.Doc = Doc
9022
+ CodeMirror.splitLines = splitLinesAuto
9023
+ CodeMirror.countColumn = countColumn
9024
+ CodeMirror.findColumn = findColumn
9025
+ CodeMirror.isWordChar = isWordCharBasic
9026
+ CodeMirror.Pass = Pass
9027
+ CodeMirror.signal = signal
9028
+ CodeMirror.Line = Line
9029
+ CodeMirror.changeEnd = changeEnd
9030
+ CodeMirror.scrollbarModel = scrollbarModel
9031
+ CodeMirror.Pos = Pos
9032
+ CodeMirror.cmpPos = cmp
9033
+ CodeMirror.modes = modes
9034
+ CodeMirror.mimeModes = mimeModes
9035
+ CodeMirror.resolveMode = resolveMode
9036
+ CodeMirror.getMode = getMode
9037
+ CodeMirror.modeExtensions = modeExtensions
9038
+ CodeMirror.extendMode = extendMode
9039
+ CodeMirror.copyState = copyState
9040
+ CodeMirror.startState = startState
9041
+ CodeMirror.innerMode = innerMode
9042
+ CodeMirror.commands = commands
9043
+ CodeMirror.keyMap = keyMap
9044
+ CodeMirror.keyName = keyName
9045
+ CodeMirror.isModifierKey = isModifierKey
9046
+ CodeMirror.lookupKey = lookupKey
9047
+ CodeMirror.normalizeKeyMap = normalizeKeyMap
9048
+ CodeMirror.StringStream = StringStream
9049
+ CodeMirror.SharedTextMarker = SharedTextMarker
9050
+ CodeMirror.TextMarker = TextMarker
9051
+ CodeMirror.LineWidget = LineWidget
9052
+ CodeMirror.e_preventDefault = e_preventDefault
9053
+ CodeMirror.e_stopPropagation = e_stopPropagation
9054
+ CodeMirror.e_stop = e_stop
9055
+ CodeMirror.addClass = addClass
9056
+ CodeMirror.contains = contains
9057
+ CodeMirror.rmClass = rmClass
9058
+ CodeMirror.keyNames = keyNames
9059
+ }
9060
+
9061
+ // EDITOR CONSTRUCTOR
9062
+
9063
+ defineOptions(CodeMirror)
9064
+
9065
+ addEditorMethods(CodeMirror)
9066
+
9067
+ // Set up methods on CodeMirror's prototype to redirect to the editor's document.
9068
+ var dontDelegate = "iter insert remove copy getEditor constructor".split(" ")
9069
+ for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0)
9070
+ { CodeMirror.prototype[prop] = (function(method) {
9071
+ return function() {return method.apply(this.doc, arguments)}
9072
+ })(Doc.prototype[prop]) } }
9073
+
9074
+ eventMixin(Doc)
9075
+
9076
+ // INPUT HANDLING
9077
+
9078
+ CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}
9079
+
9080
+ // MODE DEFINITION AND QUERYING
9081
+
9082
+ // Extra arguments are stored as the mode's dependencies, which is
9083
+ // used by (legacy) mechanisms like loadmode.js to automatically
9084
+ // load a mode. (Preferred mechanism is the require/define calls.)
9085
+ CodeMirror.defineMode = function(name/*, mode, …*/) {
9086
+ if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name }
9087
+ defineMode.apply(this, arguments)
9088
+ }
9089
+
9090
+ CodeMirror.defineMIME = defineMIME
9091
+
9092
+ // Minimal default mode.
9093
+ CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); })
9094
+ CodeMirror.defineMIME("text/plain", "null")
9095
+
9096
+ // EXTENSIONS
9097
+
9098
+ CodeMirror.defineExtension = function (name, func) {
9099
+ CodeMirror.prototype[name] = func
9100
+ }
9101
+ CodeMirror.defineDocExtension = function (name, func) {
9102
+ Doc.prototype[name] = func
9103
+ }
9104
+
9105
+ CodeMirror.fromTextArea = fromTextArea
9106
+
9107
+ addLegacyProps(CodeMirror)
9108
+
9109
+ CodeMirror.version = "5.23.0"
9110
+
9111
+ return CodeMirror;
9112
+
9113
+ })));
js/codemirror/css.js ADDED
@@ -0,0 +1,829 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ CodeMirror.defineMode("css", function(config, parserConfig) {
15
+ var inline = parserConfig.inline
16
+ if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
17
+
18
+ var indentUnit = config.indentUnit,
19
+ tokenHooks = parserConfig.tokenHooks,
20
+ documentTypes = parserConfig.documentTypes || {},
21
+ mediaTypes = parserConfig.mediaTypes || {},
22
+ mediaFeatures = parserConfig.mediaFeatures || {},
23
+ mediaValueKeywords = parserConfig.mediaValueKeywords || {},
24
+ propertyKeywords = parserConfig.propertyKeywords || {},
25
+ nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
26
+ fontProperties = parserConfig.fontProperties || {},
27
+ counterDescriptors = parserConfig.counterDescriptors || {},
28
+ colorKeywords = parserConfig.colorKeywords || {},
29
+ valueKeywords = parserConfig.valueKeywords || {},
30
+ allowNested = parserConfig.allowNested,
31
+ lineComment = parserConfig.lineComment,
32
+ supportsAtComponent = parserConfig.supportsAtComponent === true;
33
+
34
+ var type, override;
35
+ function ret(style, tp) { type = tp; return style; }
36
+
37
+ // Tokenizers
38
+
39
+ function tokenBase(stream, state) {
40
+ var ch = stream.next();
41
+ if (tokenHooks[ch]) {
42
+ var result = tokenHooks[ch](stream, state);
43
+ if (result !== false) return result;
44
+ }
45
+ if (ch == "@") {
46
+ stream.eatWhile(/[\w\\\-]/);
47
+ return ret("def", stream.current());
48
+ } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
49
+ return ret(null, "compare");
50
+ } else if (ch == "\"" || ch == "'") {
51
+ state.tokenize = tokenString(ch);
52
+ return state.tokenize(stream, state);
53
+ } else if (ch == "#") {
54
+ stream.eatWhile(/[\w\\\-]/);
55
+ return ret("atom", "hash");
56
+ } else if (ch == "!") {
57
+ stream.match(/^\s*\w*/);
58
+ return ret("keyword", "important");
59
+ } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
60
+ stream.eatWhile(/[\w.%]/);
61
+ return ret("number", "unit");
62
+ } else if (ch === "-") {
63
+ if (/[\d.]/.test(stream.peek())) {
64
+ stream.eatWhile(/[\w.%]/);
65
+ return ret("number", "unit");
66
+ } else if (stream.match(/^-[\w\\\-]+/)) {
67
+ stream.eatWhile(/[\w\\\-]/);
68
+ if (stream.match(/^\s*:/, false))
69
+ return ret("variable-2", "variable-definition");
70
+ return ret("variable-2", "variable");
71
+ } else if (stream.match(/^\w+-/)) {
72
+ return ret("meta", "meta");
73
+ }
74
+ } else if (/[,+>*\/]/.test(ch)) {
75
+ return ret(null, "select-op");
76
+ } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
77
+ return ret("qualifier", "qualifier");
78
+ } else if (/[:;{}\[\]\(\)]/.test(ch)) {
79
+ return ret(null, ch);
80
+ } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) ||
81
+ (ch == "d" && stream.match("omain(")) ||
82
+ (ch == "r" && stream.match("egexp("))) {
83
+ stream.backUp(1);
84
+ state.tokenize = tokenParenthesized;
85
+ return ret("property", "word");
86
+ } else if (/[\w\\\-]/.test(ch)) {
87
+ stream.eatWhile(/[\w\\\-]/);
88
+ return ret("property", "word");
89
+ } else {
90
+ return ret(null, null);
91
+ }
92
+ }
93
+
94
+ function tokenString(quote) {
95
+ return function(stream, state) {
96
+ var escaped = false, ch;
97
+ while ((ch = stream.next()) != null) {
98
+ if (ch == quote && !escaped) {
99
+ if (quote == ")") stream.backUp(1);
100
+ break;
101
+ }
102
+ escaped = !escaped && ch == "\\";
103
+ }
104
+ if (ch == quote || !escaped && quote != ")") state.tokenize = null;
105
+ return ret("string", "string");
106
+ };
107
+ }
108
+
109
+ function tokenParenthesized(stream, state) {
110
+ stream.next(); // Must be '('
111
+ if (!stream.match(/\s*[\"\')]/, false))
112
+ state.tokenize = tokenString(")");
113
+ else
114
+ state.tokenize = null;
115
+ return ret(null, "(");
116
+ }
117
+
118
+ // Context management
119
+
120
+ function Context(type, indent, prev) {
121
+ this.type = type;
122
+ this.indent = indent;
123
+ this.prev = prev;
124
+ }
125
+
126
+ function pushContext(state, stream, type, indent) {
127
+ state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
128
+ return type;
129
+ }
130
+
131
+ function popContext(state) {
132
+ if (state.context.prev)
133
+ state.context = state.context.prev;
134
+ return state.context.type;
135
+ }
136
+
137
+ function pass(type, stream, state) {
138
+ return states[state.context.type](type, stream, state);
139
+ }
140
+ function popAndPass(type, stream, state, n) {
141
+ for (var i = n || 1; i > 0; i--)
142
+ state.context = state.context.prev;
143
+ return pass(type, stream, state);
144
+ }
145
+
146
+ // Parser
147
+
148
+ function wordAsValue(stream) {
149
+ var word = stream.current().toLowerCase();
150
+ if (valueKeywords.hasOwnProperty(word))
151
+ override = "atom";
152
+ else if (colorKeywords.hasOwnProperty(word))
153
+ override = "keyword";
154
+ else
155
+ override = "variable";
156
+ }
157
+
158
+ var states = {};
159
+
160
+ states.top = function(type, stream, state) {
161
+ if (type == "{") {
162
+ return pushContext(state, stream, "block");
163
+ } else if (type == "}" && state.context.prev) {
164
+ return popContext(state);
165
+ } else if (supportsAtComponent && /@component/.test(type)) {
166
+ return pushContext(state, stream, "atComponentBlock");
167
+ } else if (/^@(-moz-)?document$/.test(type)) {
168
+ return pushContext(state, stream, "documentTypes");
169
+ } else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) {
170
+ return pushContext(state, stream, "atBlock");
171
+ } else if (/^@(font-face|counter-style)/.test(type)) {
172
+ state.stateArg = type;
173
+ return "restricted_atBlock_before";
174
+ } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) {
175
+ return "keyframes";
176
+ } else if (type && type.charAt(0) == "@") {
177
+ return pushContext(state, stream, "at");
178
+ } else if (type == "hash") {
179
+ override = "builtin";
180
+ } else if (type == "word") {
181
+ override = "tag";
182
+ } else if (type == "variable-definition") {
183
+ return "maybeprop";
184
+ } else if (type == "interpolation") {
185
+ return pushContext(state, stream, "interpolation");
186
+ } else if (type == ":") {
187
+ return "pseudo";
188
+ } else if (allowNested && type == "(") {
189
+ return pushContext(state, stream, "parens");
190
+ }
191
+ return state.context.type;
192
+ };
193
+
194
+ states.block = function(type, stream, state) {
195
+ if (type == "word") {
196
+ var word = stream.current().toLowerCase();
197
+ if (propertyKeywords.hasOwnProperty(word)) {
198
+ override = "property";
199
+ return "maybeprop";
200
+ } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
201
+ override = "string-2";
202
+ return "maybeprop";
203
+ } else if (allowNested) {
204
+ override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
205
+ return "block";
206
+ } else {
207
+ override += " error";
208
+ return "maybeprop";
209
+ }
210
+ } else if (type == "meta") {
211
+ return "block";
212
+ } else if (!allowNested && (type == "hash" || type == "qualifier")) {
213
+ override = "error";
214
+ return "block";
215
+ } else {
216
+ return states.top(type, stream, state);
217
+ }
218
+ };
219
+
220
+ states.maybeprop = function(type, stream, state) {
221
+ if (type == ":") return pushContext(state, stream, "prop");
222
+ return pass(type, stream, state);
223
+ };
224
+
225
+ states.prop = function(type, stream, state) {
226
+ if (type == ";") return popContext(state);
227
+ if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
228
+ if (type == "}" || type == "{") return popAndPass(type, stream, state);
229
+ if (type == "(") return pushContext(state, stream, "parens");
230
+
231
+ if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) {
232
+ override += " error";
233
+ } else if (type == "word") {
234
+ wordAsValue(stream);
235
+ } else if (type == "interpolation") {
236
+ return pushContext(state, stream, "interpolation");
237
+ }
238
+ return "prop";
239
+ };
240
+
241
+ states.propBlock = function(type, _stream, state) {
242
+ if (type == "}") return popContext(state);
243
+ if (type == "word") { override = "property"; return "maybeprop"; }
244
+ return state.context.type;
245
+ };
246
+
247
+ states.parens = function(type, stream, state) {
248
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
249
+ if (type == ")") return popContext(state);
250
+ if (type == "(") return pushContext(state, stream, "parens");
251
+ if (type == "interpolation") return pushContext(state, stream, "interpolation");
252
+ if (type == "word") wordAsValue(stream);
253
+ return "parens";
254
+ };
255
+
256
+ states.pseudo = function(type, stream, state) {
257
+ if (type == "word") {
258
+ override = "variable-3";
259
+ return state.context.type;
260
+ }
261
+ return pass(type, stream, state);
262
+ };
263
+
264
+ states.documentTypes = function(type, stream, state) {
265
+ if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
266
+ override = "tag";
267
+ return state.context.type;
268
+ } else {
269
+ return states.atBlock(type, stream, state);
270
+ }
271
+ };
272
+
273
+ states.atBlock = function(type, stream, state) {
274
+ if (type == "(") return pushContext(state, stream, "atBlock_parens");
275
+ if (type == "}" || type == ";") return popAndPass(type, stream, state);
276
+ if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
277
+
278
+ if (type == "interpolation") return pushContext(state, stream, "interpolation");
279
+
280
+ if (type == "word") {
281
+ var word = stream.current().toLowerCase();
282
+ if (word == "only" || word == "not" || word == "and" || word == "or")
283
+ override = "keyword";
284
+ else if (mediaTypes.hasOwnProperty(word))
285
+ override = "attribute";
286
+ else if (mediaFeatures.hasOwnProperty(word))
287
+ override = "property";
288
+ else if (mediaValueKeywords.hasOwnProperty(word))
289
+ override = "keyword";
290
+ else if (propertyKeywords.hasOwnProperty(word))
291
+ override = "property";
292
+ else if (nonStandardPropertyKeywords.hasOwnProperty(word))
293
+ override = "string-2";
294
+ else if (valueKeywords.hasOwnProperty(word))
295
+ override = "atom";
296
+ else if (colorKeywords.hasOwnProperty(word))
297
+ override = "keyword";
298
+ else
299
+ override = "error";
300
+ }
301
+ return state.context.type;
302
+ };
303
+
304
+ states.atComponentBlock = function(type, stream, state) {
305
+ if (type == "}")
306
+ return popAndPass(type, stream, state);
307
+ if (type == "{")
308
+ return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
309
+ if (type == "word")
310
+ override = "error";
311
+ return state.context.type;
312
+ };
313
+
314
+ states.atBlock_parens = function(type, stream, state) {
315
+ if (type == ")") return popContext(state);
316
+ if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
317
+ return states.atBlock(type, stream, state);
318
+ };
319
+
320
+ states.restricted_atBlock_before = function(type, stream, state) {
321
+ if (type == "{")
322
+ return pushContext(state, stream, "restricted_atBlock");
323
+ if (type == "word" && state.stateArg == "@counter-style") {
324
+ override = "variable";
325
+ return "restricted_atBlock_before";
326
+ }
327
+ return pass(type, stream, state);
328
+ };
329
+
330
+ states.restricted_atBlock = function(type, stream, state) {
331
+ if (type == "}") {
332
+ state.stateArg = null;
333
+ return popContext(state);
334
+ }
335
+ if (type == "word") {
336
+ if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
337
+ (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
338
+ override = "error";
339
+ else
340
+ override = "property";
341
+ return "maybeprop";
342
+ }
343
+ return "restricted_atBlock";
344
+ };
345
+
346
+ states.keyframes = function(type, stream, state) {
347
+ if (type == "word") { override = "variable"; return "keyframes"; }
348
+ if (type == "{") return pushContext(state, stream, "top");
349
+ return pass(type, stream, state);
350
+ };
351
+
352
+ states.at = function(type, stream, state) {
353
+ if (type == ";") return popContext(state);
354
+ if (type == "{" || type == "}") return popAndPass(type, stream, state);
355
+ if (type == "word") override = "tag";
356
+ else if (type == "hash") override = "builtin";
357
+ return "at";
358
+ };
359
+
360
+ states.interpolation = function(type, stream, state) {
361
+ if (type == "}") return popContext(state);
362
+ if (type == "{" || type == ";") return popAndPass(type, stream, state);
363
+ if (type == "word") override = "variable";
364
+ else if (type != "variable" && type != "(" && type != ")") override = "error";
365
+ return "interpolation";
366
+ };
367
+
368
+ return {
369
+ startState: function(base) {
370
+ return {tokenize: null,
371
+ state: inline ? "block" : "top",
372
+ stateArg: null,
373
+ context: new Context(inline ? "block" : "top", base || 0, null)};
374
+ },
375
+
376
+ token: function(stream, state) {
377
+ if (!state.tokenize && stream.eatSpace()) return null;
378
+ var style = (state.tokenize || tokenBase)(stream, state);
379
+ if (style && typeof style == "object") {
380
+ type = style[1];
381
+ style = style[0];
382
+ }
383
+ override = style;
384
+ state.state = states[state.state](type, stream, state);
385
+ return override;
386
+ },
387
+
388
+ indent: function(state, textAfter) {
389
+ var cx = state.context, ch = textAfter && textAfter.charAt(0);
390
+ var indent = cx.indent;
391
+ if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
392
+ if (cx.prev) {
393
+ if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
394
+ cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
395
+ // Resume indentation from parent context.
396
+ cx = cx.prev;
397
+ indent = cx.indent;
398
+ } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
399
+ ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
400
+ // Dedent relative to current context.
401
+ indent = Math.max(0, cx.indent - indentUnit);
402
+ cx = cx.prev;
403
+ }
404
+ }
405
+ return indent;
406
+ },
407
+
408
+ electricChars: "}",
409
+ blockCommentStart: "/*",
410
+ blockCommentEnd: "*/",
411
+ lineComment: lineComment,
412
+ fold: "brace"
413
+ };
414
+ });
415
+
416
+ function keySet(array) {
417
+ var keys = {};
418
+ for (var i = 0; i < array.length; ++i) {
419
+ keys[array[i].toLowerCase()] = true;
420
+ }
421
+ return keys;
422
+ }
423
+
424
+ var documentTypes_ = [
425
+ "domain", "regexp", "url", "url-prefix"
426
+ ], documentTypes = keySet(documentTypes_);
427
+
428
+ var mediaTypes_ = [
429
+ "all", "aural", "braille", "handheld", "print", "projection", "screen",
430
+ "tty", "tv", "embossed"
431
+ ], mediaTypes = keySet(mediaTypes_);
432
+
433
+ var mediaFeatures_ = [
434
+ "width", "min-width", "max-width", "height", "min-height", "max-height",
435
+ "device-width", "min-device-width", "max-device-width", "device-height",
436
+ "min-device-height", "max-device-height", "aspect-ratio",
437
+ "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
438
+ "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
439
+ "max-color", "color-index", "min-color-index", "max-color-index",
440
+ "monochrome", "min-monochrome", "max-monochrome", "resolution",
441
+ "min-resolution", "max-resolution", "scan", "grid", "orientation",
442
+ "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
443
+ "pointer", "any-pointer", "hover", "any-hover"
444
+ ], mediaFeatures = keySet(mediaFeatures_);
445
+
446
+ var mediaValueKeywords_ = [
447
+ "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
448
+ "interlace", "progressive"
449
+ ], mediaValueKeywords = keySet(mediaValueKeywords_);
450
+
451
+ var propertyKeywords_ = [
452
+ "align-content", "align-items", "align-self", "alignment-adjust",
453
+ "alignment-baseline", "anchor-point", "animation", "animation-delay",
454
+ "animation-direction", "animation-duration", "animation-fill-mode",
455
+ "animation-iteration-count", "animation-name", "animation-play-state",
456
+ "animation-timing-function", "appearance", "azimuth", "backface-visibility",
457
+ "background", "background-attachment", "background-blend-mode", "background-clip",
458
+ "background-color", "background-image", "background-origin", "background-position",
459
+ "background-repeat", "background-size", "baseline-shift", "binding",
460
+ "bleed", "bookmark-label", "bookmark-level", "bookmark-state",
461
+ "bookmark-target", "border", "border-bottom", "border-bottom-color",
462
+ "border-bottom-left-radius", "border-bottom-right-radius",
463
+ "border-bottom-style", "border-bottom-width", "border-collapse",
464
+ "border-color", "border-image", "border-image-outset",
465
+ "border-image-repeat", "border-image-slice", "border-image-source",
466
+ "border-image-width", "border-left", "border-left-color",
467
+ "border-left-style", "border-left-width", "border-radius", "border-right",
468
+ "border-right-color", "border-right-style", "border-right-width",
469
+ "border-spacing", "border-style", "border-top", "border-top-color",
470
+ "border-top-left-radius", "border-top-right-radius", "border-top-style",
471
+ "border-top-width", "border-width", "bottom", "box-decoration-break",
472
+ "box-shadow", "box-sizing", "break-after", "break-before", "break-inside",
473
+ "caption-side", "clear", "clip", "color", "color-profile", "column-count",
474
+ "column-fill", "column-gap", "column-rule", "column-rule-color",
475
+ "column-rule-style", "column-rule-width", "column-span", "column-width",
476
+ "columns", "content", "counter-increment", "counter-reset", "crop", "cue",
477
+ "cue-after", "cue-before", "cursor", "direction", "display",
478
+ "dominant-baseline", "drop-initial-after-adjust",
479
+ "drop-initial-after-align", "drop-initial-before-adjust",
480
+ "drop-initial-before-align", "drop-initial-size", "drop-initial-value",
481
+ "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis",
482
+ "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap",
483
+ "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings",
484
+ "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust",
485
+ "font-stretch", "font-style", "font-synthesis", "font-variant",
486
+ "font-variant-alternates", "font-variant-caps", "font-variant-east-asian",
487
+ "font-variant-ligatures", "font-variant-numeric", "font-variant-position",
488
+ "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow",
489
+ "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap",
490
+ "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap",
491
+ "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns",
492
+ "grid-template-rows", "hanging-punctuation", "height", "hyphens",
493
+ "icon", "image-orientation", "image-rendering", "image-resolution",
494
+ "inline-box-align", "justify-content", "left", "letter-spacing",
495
+ "line-break", "line-height", "line-stacking", "line-stacking-ruby",
496
+ "line-stacking-shift", "line-stacking-strategy", "list-style",
497
+ "list-style-image", "list-style-position", "list-style-type", "margin",
498
+ "margin-bottom", "margin-left", "margin-right", "margin-top",
499
+ "marks", "marquee-direction", "marquee-loop",
500
+ "marquee-play-count", "marquee-speed", "marquee-style", "max-height",
501
+ "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index",
502
+ "nav-left", "nav-right", "nav-up", "object-fit", "object-position",
503
+ "opacity", "order", "orphans", "outline",
504
+ "outline-color", "outline-offset", "outline-style", "outline-width",
505
+ "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y",
506
+ "padding", "padding-bottom", "padding-left", "padding-right", "padding-top",
507
+ "page", "page-break-after", "page-break-before", "page-break-inside",
508
+ "page-policy", "pause", "pause-after", "pause-before", "perspective",
509
+ "perspective-origin", "pitch", "pitch-range", "play-during", "position",
510
+ "presentation-level", "punctuation-trim", "quotes", "region-break-after",
511
+ "region-break-before", "region-break-inside", "region-fragment",
512
+ "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness",
513
+ "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang",
514
+ "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin",
515
+ "shape-outside", "size", "speak", "speak-as", "speak-header",
516
+ "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set",
517
+ "tab-size", "table-layout", "target", "target-name", "target-new",
518
+ "target-position", "text-align", "text-align-last", "text-decoration",
519
+ "text-decoration-color", "text-decoration-line", "text-decoration-skip",
520
+ "text-decoration-style", "text-emphasis", "text-emphasis-color",
521
+ "text-emphasis-position", "text-emphasis-style", "text-height",
522
+ "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow",
523
+ "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position",
524
+ "text-wrap", "top", "transform", "transform-origin", "transform-style",
525
+ "transition", "transition-delay", "transition-duration",
526
+ "transition-property", "transition-timing-function", "unicode-bidi",
527
+ "user-select", "vertical-align", "visibility", "voice-balance", "voice-duration",
528
+ "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress",
529
+ "voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break",
530
+ "word-spacing", "word-wrap", "z-index",
531
+ // SVG-specific
532
+ "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
533
+ "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
534
+ "color-interpolation", "color-interpolation-filters",
535
+ "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
536
+ "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke",
537
+ "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
538
+ "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
539
+ "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
540
+ "glyph-orientation-vertical", "text-anchor", "writing-mode"
541
+ ], propertyKeywords = keySet(propertyKeywords_);
542
+
543
+ var nonStandardPropertyKeywords_ = [
544
+ "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
545
+ "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
546
+ "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside",
547
+ "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
548
+ "searchfield-results-decoration", "zoom"
549
+ ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
550
+
551
+ var fontProperties_ = [
552
+ "font-family", "src", "unicode-range", "font-variant", "font-feature-settings",
553
+ "font-stretch", "font-weight", "font-style"
554
+ ], fontProperties = keySet(fontProperties_);
555
+
556
+ var counterDescriptors_ = [
557
+ "additive-symbols", "fallback", "negative", "pad", "prefix", "range",
558
+ "speak-as", "suffix", "symbols", "system"
559
+ ], counterDescriptors = keySet(counterDescriptors_);
560
+
561
+ var colorKeywords_ = [
562
+ "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
563
+ "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
564
+ "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
565
+ "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
566
+ "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen",
567
+ "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
568
+ "darkslateblue", "darkslategray", "darkturquoise", "darkviolet",
569
+ "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick",
570
+ "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
571
+ "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
572
+ "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
573
+ "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
574
+ "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink",
575
+ "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray",
576
+ "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
577
+ "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
578
+ "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
579
+ "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
580
+ "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
581
+ "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
582
+ "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
583
+ "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
584
+ "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
585
+ "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan",
586
+ "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
587
+ "whitesmoke", "yellow", "yellowgreen"
588
+ ], colorKeywords = keySet(colorKeywords_);
589
+
590
+ var valueKeywords_ = [
591
+ "above", "absolute", "activeborder", "additive", "activecaption", "afar",
592
+ "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
593
+ "always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
594
+ "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
595
+ "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary",
596
+ "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box",
597
+ "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel",
598
+ "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
599
+ "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
600
+ "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
601
+ "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
602
+ "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
603
+ "compact", "condensed", "contain", "content", "contents",
604
+ "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop",
605
+ "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
606
+ "decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
607
+ "destination-in", "destination-out", "destination-over", "devanagari", "difference",
608
+ "disc", "discard", "disclosure-closed", "disclosure-open", "document",
609
+ "dot-dash", "dot-dot-dash",
610
+ "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
611
+ "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
612
+ "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
613
+ "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
614
+ "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
615
+ "ethiopic-halehame-gez", "ethiopic-halehame-om-et",
616
+ "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
617
+ "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
618
+ "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
619
+ "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
620
+ "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove",
621
+ "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
622
+ "help", "hidden", "hide", "higher", "highlight", "highlighttext",
623
+ "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore",
624
+ "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
625
+ "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
626
+ "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
627
+ "italic", "japanese-formal", "japanese-informal", "justify", "kannada",
628
+ "katakana", "katakana-iroha", "keep-all", "khmer",
629
+ "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
630
+ "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
631
+ "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
632
+ "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
633
+ "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
634
+ "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d",
635
+ "media-controls-background", "media-current-time-display",
636
+ "media-fullscreen-button", "media-mute-button", "media-play-button",
637
+ "media-return-to-realtime-button", "media-rewind-button",
638
+ "media-seek-back-button", "media-seek-forward-button", "media-slider",
639
+ "media-sliderthumb", "media-time-remaining-display", "media-volume-slider",
640
+ "media-volume-slider-container", "media-volume-sliderthumb", "medium",
641
+ "menu", "menulist", "menulist-button", "menulist-text",
642
+ "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic",
643
+ "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize",
644
+ "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
645
+ "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
646
+ "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
647
+ "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
648
+ "outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
649
+ "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter",
650
+ "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
651
+ "progress", "push-button", "radial-gradient", "radio", "read-only",
652
+ "read-write", "read-write-plaintext-only", "rectangle", "region",
653
+ "relative", "repeat", "repeating-linear-gradient",
654
+ "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse",
655
+ "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
656
+ "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
657
+ "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
658
+ "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
659
+ "searchfield-cancel-button", "searchfield-decoration",
660
+ "searchfield-results-button", "searchfield-results-decoration",
661
+ "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama",
662
+ "simp-chinese-formal", "simp-chinese-informal", "single",
663
+ "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
664
+ "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
665
+ "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
666
+ "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square",
667
+ "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub",
668
+ "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table",
669
+ "table-caption", "table-cell", "table-column", "table-column-group",
670
+ "table-footer-group", "table-header-group", "table-row", "table-row-group",
671
+ "tamil",
672
+ "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
673
+ "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
674
+ "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
675
+ "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
676
+ "trad-chinese-formal", "trad-chinese-informal", "transform",
677
+ "translate", "translate3d", "translateX", "translateY", "translateZ",
678
+ "transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up",
679
+ "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
680
+ "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
681
+ "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted",
682
+ "visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
683
+ "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
684
+ "xx-large", "xx-small"
685
+ ], valueKeywords = keySet(valueKeywords_);
686
+
687
+ var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
688
+ .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
689
+ .concat(valueKeywords_);
690
+ CodeMirror.registerHelper("hintWords", "css", allWords);
691
+
692
+ function tokenCComment(stream, state) {
693
+ var maybeEnd = false, ch;
694
+ while ((ch = stream.next()) != null) {
695
+ if (maybeEnd && ch == "/") {
696
+ state.tokenize = null;
697
+ break;
698
+ }
699
+ maybeEnd = (ch == "*");
700
+ }
701
+ return ["comment", "comment"];
702
+ }
703
+
704
+ CodeMirror.defineMIME("text/css", {
705
+ documentTypes: documentTypes,
706
+ mediaTypes: mediaTypes,
707
+ mediaFeatures: mediaFeatures,
708
+ mediaValueKeywords: mediaValueKeywords,
709
+ propertyKeywords: propertyKeywords,
710
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
711
+ fontProperties: fontProperties,
712
+ counterDescriptors: counterDescriptors,
713
+ colorKeywords: colorKeywords,
714
+ valueKeywords: valueKeywords,
715
+ tokenHooks: {
716
+ "/": function(stream, state) {
717
+ if (!stream.eat("*")) return false;
718
+ state.tokenize = tokenCComment;
719
+ return tokenCComment(stream, state);
720
+ }
721
+ },
722
+ name: "css"
723
+ });
724
+
725
+ CodeMirror.defineMIME("text/x-scss", {
726
+ mediaTypes: mediaTypes,
727
+ mediaFeatures: mediaFeatures,
728
+ mediaValueKeywords: mediaValueKeywords,
729
+ propertyKeywords: propertyKeywords,
730
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
731
+ colorKeywords: colorKeywords,
732
+ valueKeywords: valueKeywords,
733
+ fontProperties: fontProperties,
734
+ allowNested: true,
735
+ lineComment: "//",
736
+ tokenHooks: {
737
+ "/": function(stream, state) {
738
+ if (stream.eat("/")) {
739
+ stream.skipToEnd();
740
+ return ["comment", "comment"];
741
+ } else if (stream.eat("*")) {
742
+ state.tokenize = tokenCComment;
743
+ return tokenCComment(stream, state);
744
+ } else {
745
+ return ["operator", "operator"];
746
+ }
747
+ },
748
+ ":": function(stream) {
749
+ if (stream.match(/\s*\{/))
750
+ return [null, "{"];
751
+ return false;
752
+ },
753
+ "$": function(stream) {
754
+ stream.match(/^[\w-]+/);
755
+ if (stream.match(/^\s*:/, false))
756
+ return ["variable-2", "variable-definition"];
757
+ return ["variable-2", "variable"];
758
+ },
759
+ "#": function(stream) {
760
+ if (!stream.eat("{")) return false;
761
+ return [null, "interpolation"];
762
+ }
763
+ },
764
+ name: "css",
765
+ helperType: "scss"
766
+ });
767
+
768
+ CodeMirror.defineMIME("text/x-less", {
769
+ mediaTypes: mediaTypes,
770
+ mediaFeatures: mediaFeatures,
771
+ mediaValueKeywords: mediaValueKeywords,
772
+ propertyKeywords: propertyKeywords,
773
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
774
+ colorKeywords: colorKeywords,
775
+ valueKeywords: valueKeywords,
776
+ fontProperties: fontProperties,
777
+ allowNested: true,
778
+ lineComment: "//",
779
+ tokenHooks: {
780
+ "/": function(stream, state) {
781
+ if (stream.eat("/")) {
782
+ stream.skipToEnd();
783
+ return ["comment", "comment"];
784
+ } else if (stream.eat("*")) {
785
+ state.tokenize = tokenCComment;
786
+ return tokenCComment(stream, state);
787
+ } else {
788
+ return ["operator", "operator"];
789
+ }
790
+ },
791
+ "@": function(stream) {
792
+ if (stream.eat("{")) return [null, "interpolation"];
793
+ if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false;
794
+ stream.eatWhile(/[\w\\\-]/);
795
+ if (stream.match(/^\s*:/, false))
796
+ return ["variable-2", "variable-definition"];
797
+ return ["variable-2", "variable"];
798
+ },
799
+ "&": function() {
800
+ return ["atom", "atom"];
801
+ }
802
+ },
803
+ name: "css",
804
+ helperType: "less"
805
+ });
806
+
807
+ CodeMirror.defineMIME("text/x-gss", {
808
+ documentTypes: documentTypes,
809
+ mediaTypes: mediaTypes,
810
+ mediaFeatures: mediaFeatures,
811
+ propertyKeywords: propertyKeywords,
812
+ nonStandardPropertyKeywords: nonStandardPropertyKeywords,
813
+ fontProperties: fontProperties,
814
+ counterDescriptors: counterDescriptors,
815
+ colorKeywords: colorKeywords,
816
+ valueKeywords: valueKeywords,
817
+ supportsAtComponent: true,
818
+ tokenHooks: {
819
+ "/": function(stream, state) {
820
+ if (!stream.eat("*")) return false;
821
+ state.tokenize = tokenCComment;
822
+ return tokenCComment(stream, state);
823
+ }
824
+ },
825
+ name: "css",
826
+ helperType: "gss"
827
+ });
828
+
829
+ });
js/codemirror/htmlmixed.js ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var defaultTags = {
15
+ script: [
16
+ ["lang", /(javascript|babel)/i, "javascript"],
17
+ ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"],
18
+ ["type", /./, "text/plain"],
19
+ [null, null, "javascript"]
20
+ ],
21
+ style: [
22
+ ["lang", /^css$/i, "css"],
23
+ ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"],
24
+ ["type", /./, "text/plain"],
25
+ [null, null, "css"]
26
+ ]
27
+ };
28
+
29
+ function maybeBackup(stream, pat, style) {
30
+ var cur = stream.current(), close = cur.search(pat);
31
+ if (close > -1) {
32
+ stream.backUp(cur.length - close);
33
+ } else if (cur.match(/<\/?$/)) {
34
+ stream.backUp(cur.length);
35
+ if (!stream.match(pat, false)) stream.match(cur);
36
+ }
37
+ return style;
38
+ }
39
+
40
+ var attrRegexpCache = {};
41
+ function getAttrRegexp(attr) {
42
+ var regexp = attrRegexpCache[attr];
43
+ if (regexp) return regexp;
44
+ return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*");
45
+ }
46
+
47
+ function getAttrValue(text, attr) {
48
+ var match = text.match(getAttrRegexp(attr))
49
+ return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : ""
50
+ }
51
+
52
+ function getTagRegexp(tagName, anchored) {
53
+ return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i");
54
+ }
55
+
56
+ function addTags(from, to) {
57
+ for (var tag in from) {
58
+ var dest = to[tag] || (to[tag] = []);
59
+ var source = from[tag];
60
+ for (var i = source.length - 1; i >= 0; i--)
61
+ dest.unshift(source[i])
62
+ }
63
+ }
64
+
65
+ function findMatchingMode(tagInfo, tagText) {
66
+ for (var i = 0; i < tagInfo.length; i++) {
67
+ var spec = tagInfo[i];
68
+ if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2];
69
+ }
70
+ }
71
+
72
+ CodeMirror.defineMode("htmlmixed", function (config, parserConfig) {
73
+ var htmlMode = CodeMirror.getMode(config, {
74
+ name: "xml",
75
+ htmlMode: true,
76
+ multilineTagIndentFactor: parserConfig.multilineTagIndentFactor,
77
+ multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag
78
+ });
79
+
80
+ var tags = {};
81
+ var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes;
82
+ addTags(defaultTags, tags);
83
+ if (configTags) addTags(configTags, tags);
84
+ if (configScript) for (var i = configScript.length - 1; i >= 0; i--)
85
+ tags.script.unshift(["type", configScript[i].matches, configScript[i].mode])
86
+
87
+ function html(stream, state) {
88
+ var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName
89
+ if (tag && !/[<>\s\/]/.test(stream.current()) &&
90
+ (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) &&
91
+ tags.hasOwnProperty(tagName)) {
92
+ state.inTag = tagName + " "
93
+ } else if (state.inTag && tag && />$/.test(stream.current())) {
94
+ var inTag = /^([\S]+) (.*)/.exec(state.inTag)
95
+ state.inTag = null
96
+ var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2])
97
+ var mode = CodeMirror.getMode(config, modeSpec)
98
+ var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false);
99
+ state.token = function (stream, state) {
100
+ if (stream.match(endTagA, false)) {
101
+ state.token = html;
102
+ state.localState = state.localMode = null;
103
+ return null;
104
+ }
105
+ return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState));
106
+ };
107
+ state.localMode = mode;
108
+ state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, ""));
109
+ } else if (state.inTag) {
110
+ state.inTag += stream.current()
111
+ if (stream.eol()) state.inTag += " "
112
+ }
113
+ return style;
114
+ };
115
+
116
+ return {
117
+ startState: function () {
118
+ var state = CodeMirror.startState(htmlMode);
119
+ return {token: html, inTag: null, localMode: null, localState: null, htmlState: state};
120
+ },
121
+
122
+ copyState: function (state) {
123
+ var local;
124
+ if (state.localState) {
125
+ local = CodeMirror.copyState(state.localMode, state.localState);
126
+ }
127
+ return {token: state.token, inTag: state.inTag,
128
+ localMode: state.localMode, localState: local,
129
+ htmlState: CodeMirror.copyState(htmlMode, state.htmlState)};
130
+ },
131
+
132
+ token: function (stream, state) {
133
+ return state.token(stream, state);
134
+ },
135
+
136
+ indent: function (state, textAfter) {
137
+ if (!state.localMode || /^\s*<\//.test(textAfter))
138
+ return htmlMode.indent(state.htmlState, textAfter);
139
+ else if (state.localMode.indent)
140
+ return state.localMode.indent(state.localState, textAfter);
141
+ else
142
+ return CodeMirror.Pass;
143
+ },
144
+
145
+ innerMode: function (state) {
146
+ return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode};
147
+ }
148
+ };
149
+ }, "xml", "javascript", "css");
150
+
151
+ CodeMirror.defineMIME("text/html", "htmlmixed");
152
+ });
js/codemirror/javascript.js ADDED
@@ -0,0 +1,797 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ function expressionAllowed(stream, state, backUp) {
15
+ return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) ||
16
+ (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0))))
17
+ }
18
+
19
+ CodeMirror.defineMode("javascript", function(config, parserConfig) {
20
+ var indentUnit = config.indentUnit;
21
+ var statementIndent = parserConfig.statementIndent;
22
+ var jsonldMode = parserConfig.jsonld;
23
+ var jsonMode = parserConfig.json || jsonldMode;
24
+ var isTS = parserConfig.typescript;
25
+ var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/;
26
+
27
+ // Tokenizer
28
+
29
+ var keywords = function(){
30
+ function kw(type) {return {type: type, style: "keyword"};}
31
+ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
32
+ var operator = kw("operator"), atom = {type: "atom", style: "atom"};
33
+
34
+ var jsKeywords = {
35
+ "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
36
+ "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C,
37
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
38
+ "function": kw("function"), "catch": kw("catch"),
39
+ "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
40
+ "in": operator, "typeof": operator, "instanceof": operator,
41
+ "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
42
+ "this": kw("this"), "class": kw("class"), "super": kw("atom"),
43
+ "yield": C, "export": kw("export"), "import": kw("import"), "extends": C,
44
+ "await": C, "async": kw("async")
45
+ };
46
+
47
+ // Extend the 'normal' keywords with the TypeScript language extensions
48
+ if (isTS) {
49
+ var type = {type: "variable", style: "variable-3"};
50
+ var tsKeywords = {
51
+ // object-like things
52
+ "interface": kw("class"),
53
+ "implements": C,
54
+ "namespace": C,
55
+ "module": kw("module"),
56
+ "enum": kw("module"),
57
+ "type": kw("type"),
58
+
59
+ // scope modifiers
60
+ "public": kw("modifier"),
61
+ "private": kw("modifier"),
62
+ "protected": kw("modifier"),
63
+ "abstract": kw("modifier"),
64
+
65
+ // operators
66
+ "as": operator,
67
+
68
+ // types
69
+ "string": type, "number": type, "boolean": type, "any": type
70
+ };
71
+
72
+ for (var attr in tsKeywords) {
73
+ jsKeywords[attr] = tsKeywords[attr];
74
+ }
75
+ }
76
+
77
+ return jsKeywords;
78
+ }();
79
+
80
+ var isOperatorChar = /[+\-*&%=<>!?|~^]/;
81
+ var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/;
82
+
83
+ function readRegexp(stream) {
84
+ var escaped = false, next, inSet = false;
85
+ while ((next = stream.next()) != null) {
86
+ if (!escaped) {
87
+ if (next == "/" && !inSet) return;
88
+ if (next == "[") inSet = true;
89
+ else if (inSet && next == "]") inSet = false;
90
+ }
91
+ escaped = !escaped && next == "\\";
92
+ }
93
+ }
94
+
95
+ // Used as scratch variables to communicate multiple values without
96
+ // consing up tons of objects.
97
+ var type, content;
98
+ function ret(tp, style, cont) {
99
+ type = tp; content = cont;
100
+ return style;
101
+ }
102
+ function tokenBase(stream, state) {
103
+ var ch = stream.next();
104
+ if (ch == '"' || ch == "'") {
105
+ state.tokenize = tokenString(ch);
106
+ return state.tokenize(stream, state);
107
+ } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) {
108
+ return ret("number", "number");
109
+ } else if (ch == "." && stream.match("..")) {
110
+ return ret("spread", "meta");
111
+ } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
112
+ return ret(ch);
113
+ } else if (ch == "=" && stream.eat(">")) {
114
+ return ret("=>", "operator");
115
+ } else if (ch == "0" && stream.eat(/x/i)) {
116
+ stream.eatWhile(/[\da-f]/i);
117
+ return ret("number", "number");
118
+ } else if (ch == "0" && stream.eat(/o/i)) {
119
+ stream.eatWhile(/[0-7]/i);
120
+ return ret("number", "number");
121
+ } else if (ch == "0" && stream.eat(/b/i)) {
122
+ stream.eatWhile(/[01]/i);
123
+ return ret("number", "number");
124
+ } else if (/\d/.test(ch)) {
125
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
126
+ return ret("number", "number");
127
+ } else if (ch == "/") {
128
+ if (stream.eat("*")) {
129
+ state.tokenize = tokenComment;
130
+ return tokenComment(stream, state);
131
+ } else if (stream.eat("/")) {
132
+ stream.skipToEnd();
133
+ return ret("comment", "comment");
134
+ } else if (expressionAllowed(stream, state, 1)) {
135
+ readRegexp(stream);
136
+ stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/);
137
+ return ret("regexp", "string-2");
138
+ } else {
139
+ stream.eatWhile(isOperatorChar);
140
+ return ret("operator", "operator", stream.current());
141
+ }
142
+ } else if (ch == "`") {
143
+ state.tokenize = tokenQuasi;
144
+ return tokenQuasi(stream, state);
145
+ } else if (ch == "#") {
146
+ stream.skipToEnd();
147
+ return ret("error", "error");
148
+ } else if (isOperatorChar.test(ch)) {
149
+ if (ch != ">" || !state.lexical || state.lexical.type != ">")
150
+ stream.eatWhile(isOperatorChar);
151
+ return ret("operator", "operator", stream.current());
152
+ } else if (wordRE.test(ch)) {
153
+ stream.eatWhile(wordRE);
154
+ var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
155
+ return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
156
+ ret("variable", "variable", word);
157
+ }
158
+ }
159
+
160
+ function tokenString(quote) {
161
+ return function(stream, state) {
162
+ var escaped = false, next;
163
+ if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){
164
+ state.tokenize = tokenBase;
165
+ return ret("jsonld-keyword", "meta");
166
+ }
167
+ while ((next = stream.next()) != null) {
168
+ if (next == quote && !escaped) break;
169
+ escaped = !escaped && next == "\\";
170
+ }
171
+ if (!escaped) state.tokenize = tokenBase;
172
+ return ret("string", "string");
173
+ };
174
+ }
175
+
176
+ function tokenComment(stream, state) {
177
+ var maybeEnd = false, ch;
178
+ while (ch = stream.next()) {
179
+ if (ch == "/" && maybeEnd) {
180
+ state.tokenize = tokenBase;
181
+ break;
182
+ }
183
+ maybeEnd = (ch == "*");
184
+ }
185
+ return ret("comment", "comment");
186
+ }
187
+
188
+ function tokenQuasi(stream, state) {
189
+ var escaped = false, next;
190
+ while ((next = stream.next()) != null) {
191
+ if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) {
192
+ state.tokenize = tokenBase;
193
+ break;
194
+ }
195
+ escaped = !escaped && next == "\\";
196
+ }
197
+ return ret("quasi", "string-2", stream.current());
198
+ }
199
+
200
+ var brackets = "([{}])";
201
+ // This is a crude lookahead trick to try and notice that we're
202
+ // parsing the argument patterns for a fat-arrow function before we
203
+ // actually hit the arrow token. It only works if the arrow is on
204
+ // the same line as the arguments and there's no strange noise
205
+ // (comments) in between. Fallback is to only notice when we hit the
206
+ // arrow, and not declare the arguments as locals for the arrow
207
+ // body.
208
+ function findFatArrow(stream, state) {
209
+ if (state.fatArrowAt) state.fatArrowAt = null;
210
+ var arrow = stream.string.indexOf("=>", stream.start);
211
+ if (arrow < 0) return;
212
+
213
+ if (isTS) { // Try to skip TypeScript return type declarations after the arguments
214
+ var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow))
215
+ if (m) arrow = m.index
216
+ }
217
+
218
+ var depth = 0, sawSomething = false;
219
+ for (var pos = arrow - 1; pos >= 0; --pos) {
220
+ var ch = stream.string.charAt(pos);
221
+ var bracket = brackets.indexOf(ch);
222
+ if (bracket >= 0 && bracket < 3) {
223
+ if (!depth) { ++pos; break; }
224
+ if (--depth == 0) { if (ch == "(") sawSomething = true; break; }
225
+ } else if (bracket >= 3 && bracket < 6) {
226
+ ++depth;
227
+ } else if (wordRE.test(ch)) {
228
+ sawSomething = true;
229
+ } else if (/["'\/]/.test(ch)) {
230
+ return;
231
+ } else if (sawSomething && !depth) {
232
+ ++pos;
233
+ break;
234
+ }
235
+ }
236
+ if (sawSomething && !depth) state.fatArrowAt = pos;
237
+ }
238
+
239
+ // Parser
240
+
241
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true};
242
+
243
+ function JSLexical(indented, column, type, align, prev, info) {
244
+ this.indented = indented;
245
+ this.column = column;
246
+ this.type = type;
247
+ this.prev = prev;
248
+ this.info = info;
249
+ if (align != null) this.align = align;
250
+ }
251
+
252
+ function inScope(state, varname) {
253
+ for (var v = state.localVars; v; v = v.next)
254
+ if (v.name == varname) return true;
255
+ for (var cx = state.context; cx; cx = cx.prev) {
256
+ for (var v = cx.vars; v; v = v.next)
257
+ if (v.name == varname) return true;
258
+ }
259
+ }
260
+
261
+ function parseJS(state, style, type, content, stream) {
262
+ var cc = state.cc;
263
+ // Communicate our context to the combinators.
264
+ // (Less wasteful than consing up a hundred closures on every call.)
265
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style;
266
+
267
+ if (!state.lexical.hasOwnProperty("align"))
268
+ state.lexical.align = true;
269
+
270
+ while(true) {
271
+ var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
272
+ if (combinator(type, content)) {
273
+ while(cc.length && cc[cc.length - 1].lex)
274
+ cc.pop()();
275
+ if (cx.marked) return cx.marked;
276
+ if (type == "variable" && inScope(state, content)) return "variable-2";
277
+ return style;
278
+ }
279
+ }
280
+ }
281
+
282
+ // Combinator utils
283
+
284
+ var cx = {state: null, column: null, marked: null, cc: null};
285
+ function pass() {
286
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
287
+ }
288
+ function cont() {
289
+ pass.apply(null, arguments);
290
+ return true;
291
+ }
292
+ function register(varname) {
293
+ function inList(list) {
294
+ for (var v = list; v; v = v.next)
295
+ if (v.name == varname) return true;
296
+ return false;
297
+ }
298
+ var state = cx.state;
299
+ cx.marked = "def";
300
+ if (state.context) {
301
+ if (inList(state.localVars)) return;
302
+ state.localVars = {name: varname, next: state.localVars};
303
+ } else {
304
+ if (inList(state.globalVars)) return;
305
+ if (parserConfig.globalVars)
306
+ state.globalVars = {name: varname, next: state.globalVars};
307
+ }
308
+ }
309
+
310
+ // Combinators
311
+
312
+ var defaultVars = {name: "this", next: {name: "arguments"}};
313
+ function pushcontext() {
314
+ cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
315
+ cx.state.localVars = defaultVars;
316
+ }
317
+ function popcontext() {
318
+ cx.state.localVars = cx.state.context.vars;
319
+ cx.state.context = cx.state.context.prev;
320
+ }
321
+ function pushlex(type, info) {
322
+ var result = function() {
323
+ var state = cx.state, indent = state.indented;
324
+ if (state.lexical.type == "stat") indent = state.lexical.indented;
325
+ else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev)
326
+ indent = outer.indented;
327
+ state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
328
+ };
329
+ result.lex = true;
330
+ return result;
331
+ }
332
+ function poplex() {
333
+ var state = cx.state;
334
+ if (state.lexical.prev) {
335
+ if (state.lexical.type == ")")
336
+ state.indented = state.lexical.indented;
337
+ state.lexical = state.lexical.prev;
338
+ }
339
+ }
340
+ poplex.lex = true;
341
+
342
+ function expect(wanted) {
343
+ function exp(type) {
344
+ if (type == wanted) return cont();
345
+ else if (wanted == ";") return pass();
346
+ else return cont(exp);
347
+ };
348
+ return exp;
349
+ }
350
+
351
+ function statement(type, value) {
352
+ if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex);
353
+ if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex);
354
+ if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
355
+ if (type == "{") return cont(pushlex("}"), block, poplex);
356
+ if (type == ";") return cont();
357
+ if (type == "if") {
358
+ if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex)
359
+ cx.state.cc.pop()();
360
+ return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse);
361
+ }
362
+ if (type == "function") return cont(functiondef);
363
+ if (type == "for") return cont(pushlex("form"), forspec, statement, poplex);
364
+ if (type == "variable") return cont(pushlex("stat"), maybelabel);
365
+ if (type == "switch") return cont(pushlex("form"), parenExpr, pushlex("}", "switch"), expect("{"),
366
+ block, poplex, poplex);
367
+ if (type == "case") return cont(expression, expect(":"));
368
+ if (type == "default") return cont(expect(":"));
369
+ if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
370
+ statement, poplex, popcontext);
371
+ if (type == "class") return cont(pushlex("form"), className, poplex);
372
+ if (type == "export") return cont(pushlex("stat"), afterExport, poplex);
373
+ if (type == "import") return cont(pushlex("stat"), afterImport, poplex);
374
+ if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex)
375
+ if (type == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";"));
376
+ if (type == "async") return cont(statement)
377
+ return pass(pushlex("stat"), expression, expect(";"), poplex);
378
+ }
379
+ function expression(type) {
380
+ return expressionInner(type, false);
381
+ }
382
+ function expressionNoComma(type) {
383
+ return expressionInner(type, true);
384
+ }
385
+ function parenExpr(type) {
386
+ if (type != "(") return pass()
387
+ return cont(pushlex(")"), expression, expect(")"), poplex)
388
+ }
389
+ function expressionInner(type, noComma) {
390
+ if (cx.state.fatArrowAt == cx.stream.start) {
391
+ var body = noComma ? arrowBodyNoComma : arrowBody;
392
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext);
393
+ else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext);
394
+ }
395
+
396
+ var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
397
+ if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
398
+ if (type == "function") return cont(functiondef, maybeop);
399
+ if (type == "class") return cont(pushlex("form"), classExpression, poplex);
400
+ if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
401
+ if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
402
+ if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
403
+ if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop);
404
+ if (type == "{") return contCommasep(objprop, "}", null, maybeop);
405
+ if (type == "quasi") return pass(quasi, maybeop);
406
+ if (type == "new") return cont(maybeTarget(noComma));
407
+ return cont();
408
+ }
409
+ function maybeexpression(type) {
410
+ if (type.match(/[;\}\)\],]/)) return pass();
411
+ return pass(expression);
412
+ }
413
+ function maybeexpressionNoComma(type) {
414
+ if (type.match(/[;\}\)\],]/)) return pass();
415
+ return pass(expressionNoComma);
416
+ }
417
+
418
+ function maybeoperatorComma(type, value) {
419
+ if (type == ",") return cont(expression);
420
+ return maybeoperatorNoComma(type, value, false);
421
+ }
422
+ function maybeoperatorNoComma(type, value, noComma) {
423
+ var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma;
424
+ var expr = noComma == false ? expression : expressionNoComma;
425
+ if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext);
426
+ if (type == "operator") {
427
+ if (/\+\+|--/.test(value)) return cont(me);
428
+ if (value == "?") return cont(expression, expect(":"), expr);
429
+ return cont(expr);
430
+ }
431
+ if (type == "quasi") { return pass(quasi, me); }
432
+ if (type == ";") return;
433
+ if (type == "(") return contCommasep(expressionNoComma, ")", "call", me);
434
+ if (type == ".") return cont(property, me);
435
+ if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me);
436
+ }
437
+ function quasi(type, value) {
438
+ if (type != "quasi") return pass();
439
+ if (value.slice(value.length - 2) != "${") return cont(quasi);
440
+ return cont(expression, continueQuasi);
441
+ }
442
+ function continueQuasi(type) {
443
+ if (type == "}") {
444
+ cx.marked = "string-2";
445
+ cx.state.tokenize = tokenQuasi;
446
+ return cont(quasi);
447
+ }
448
+ }
449
+ function arrowBody(type) {
450
+ findFatArrow(cx.stream, cx.state);
451
+ return pass(type == "{" ? statement : expression);
452
+ }
453
+ function arrowBodyNoComma(type) {
454
+ findFatArrow(cx.stream, cx.state);
455
+ return pass(type == "{" ? statement : expressionNoComma);
456
+ }
457
+ function maybeTarget(noComma) {
458
+ return function(type) {
459
+ if (type == ".") return cont(noComma ? targetNoComma : target);
460
+ else return pass(noComma ? expressionNoComma : expression);
461
+ };
462
+ }
463
+ function target(_, value) {
464
+ if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); }
465
+ }
466
+ function targetNoComma(_, value) {
467
+ if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); }
468
+ }
469
+ function maybelabel(type) {
470
+ if (type == ":") return cont(poplex, statement);
471
+ return pass(maybeoperatorComma, expect(";"), poplex);
472
+ }
473
+ function property(type) {
474
+ if (type == "variable") {cx.marked = "property"; return cont();}
475
+ }
476
+ function objprop(type, value) {
477
+ if (type == "async") {
478
+ cx.marked = "property";
479
+ return cont(objprop);
480
+ } else if (type == "variable" || cx.style == "keyword") {
481
+ cx.marked = "property";
482
+ if (value == "get" || value == "set") return cont(getterSetter);
483
+ return cont(afterprop);
484
+ } else if (type == "number" || type == "string") {
485
+ cx.marked = jsonldMode ? "property" : (cx.style + " property");
486
+ return cont(afterprop);
487
+ } else if (type == "jsonld-keyword") {
488
+ return cont(afterprop);
489
+ } else if (type == "modifier") {
490
+ return cont(objprop)
491
+ } else if (type == "[") {
492
+ return cont(expression, expect("]"), afterprop);
493
+ } else if (type == "spread") {
494
+ return cont(expression);
495
+ } else if (type == ":") {
496
+ return pass(afterprop)
497
+ }
498
+ }
499
+ function getterSetter(type) {
500
+ if (type != "variable") return pass(afterprop);
501
+ cx.marked = "property";
502
+ return cont(functiondef);
503
+ }
504
+ function afterprop(type) {
505
+ if (type == ":") return cont(expressionNoComma);
506
+ if (type == "(") return pass(functiondef);
507
+ }
508
+ function commasep(what, end, sep) {
509
+ function proceed(type, value) {
510
+ if (sep ? sep.indexOf(type) > -1 : type == ",") {
511
+ var lex = cx.state.lexical;
512
+ if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
513
+ return cont(function(type, value) {
514
+ if (type == end || value == end) return pass()
515
+ return pass(what)
516
+ }, proceed);
517
+ }
518
+ if (type == end || value == end) return cont();
519
+ return cont(expect(end));
520
+ }
521
+ return function(type, value) {
522
+ if (type == end || value == end) return cont();
523
+ return pass(what, proceed);
524
+ };
525
+ }
526
+ function contCommasep(what, end, info) {
527
+ for (var i = 3; i < arguments.length; i++)
528
+ cx.cc.push(arguments[i]);
529
+ return cont(pushlex(end, info), commasep(what, end), poplex);
530
+ }
531
+ function block(type) {
532
+ if (type == "}") return cont();
533
+ return pass(statement, block);
534
+ }
535
+ function maybetype(type, value) {
536
+ if (isTS) {
537
+ if (type == ":") return cont(typeexpr);
538
+ if (value == "?") return cont(maybetype);
539
+ }
540
+ }
541
+ function typeexpr(type) {
542
+ if (type == "variable") {cx.marked = "variable-3"; return cont(afterType);}
543
+ if (type == "string" || type == "number" || type == "atom") return cont(afterType);
544
+ if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex)
545
+ if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType)
546
+ }
547
+ function maybeReturnType(type) {
548
+ if (type == "=>") return cont(typeexpr)
549
+ }
550
+ function typeprop(type, value) {
551
+ if (type == "variable" || cx.style == "keyword") {
552
+ cx.marked = "property"
553
+ return cont(typeprop)
554
+ } else if (value == "?") {
555
+ return cont(typeprop)
556
+ } else if (type == ":") {
557
+ return cont(typeexpr)
558
+ }
559
+ }
560
+ function typearg(type) {
561
+ if (type == "variable") return cont(typearg)
562
+ else if (type == ":") return cont(typeexpr)
563
+ }
564
+ function afterType(type, value) {
565
+ if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType)
566
+ if (value == "|" || type == ".") return cont(typeexpr)
567
+ if (type == "[") return cont(expect("]"), afterType)
568
+ }
569
+ function vardef() {
570
+ return pass(pattern, maybetype, maybeAssign, vardefCont);
571
+ }
572
+ function pattern(type, value) {
573
+ if (type == "modifier") return cont(pattern)
574
+ if (type == "variable") { register(value); return cont(); }
575
+ if (type == "spread") return cont(pattern);
576
+ if (type == "[") return contCommasep(pattern, "]");
577
+ if (type == "{") return contCommasep(proppattern, "}");
578
+ }
579
+ function proppattern(type, value) {
580
+ if (type == "variable" && !cx.stream.match(/^\s*:/, false)) {
581
+ register(value);
582
+ return cont(maybeAssign);
583
+ }
584
+ if (type == "variable") cx.marked = "property";
585
+ if (type == "spread") return cont(pattern);
586
+ if (type == "}") return pass();
587
+ return cont(expect(":"), pattern, maybeAssign);
588
+ }
589
+ function maybeAssign(_type, value) {
590
+ if (value == "=") return cont(expressionNoComma);
591
+ }
592
+ function vardefCont(type) {
593
+ if (type == ",") return cont(vardef);
594
+ }
595
+ function maybeelse(type, value) {
596
+ if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex);
597
+ }
598
+ function forspec(type) {
599
+ if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex);
600
+ }
601
+ function forspec1(type) {
602
+ if (type == "var") return cont(vardef, expect(";"), forspec2);
603
+ if (type == ";") return cont(forspec2);
604
+ if (type == "variable") return cont(formaybeinof);
605
+ return pass(expression, expect(";"), forspec2);
606
+ }
607
+ function formaybeinof(_type, value) {
608
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
609
+ return cont(maybeoperatorComma, forspec2);
610
+ }
611
+ function forspec2(type, value) {
612
+ if (type == ";") return cont(forspec3);
613
+ if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); }
614
+ return pass(expression, expect(";"), forspec3);
615
+ }
616
+ function forspec3(type) {
617
+ if (type != ")") cont(expression);
618
+ }
619
+ function functiondef(type, value) {
620
+ if (value == "*") {cx.marked = "keyword"; return cont(functiondef);}
621
+ if (type == "variable") {register(value); return cont(functiondef);}
622
+ if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext);
623
+ }
624
+ function funarg(type) {
625
+ if (type == "spread") return cont(funarg);
626
+ return pass(pattern, maybetype, maybeAssign);
627
+ }
628
+ function classExpression(type, value) {
629
+ // Class expressions may have an optional name.
630
+ if (type == "variable") return className(type, value);
631
+ return classNameAfter(type, value);
632
+ }
633
+ function className(type, value) {
634
+ if (type == "variable") {register(value); return cont(classNameAfter);}
635
+ }
636
+ function classNameAfter(type, value) {
637
+ if (value == "extends" || value == "implements") return cont(isTS ? typeexpr : expression, classNameAfter);
638
+ if (type == "{") return cont(pushlex("}"), classBody, poplex);
639
+ }
640
+ function classBody(type, value) {
641
+ if (type == "variable" || cx.style == "keyword") {
642
+ if ((value == "static" || value == "get" || value == "set" ||
643
+ (isTS && (value == "public" || value == "private" || value == "protected" || value == "readonly" || value == "abstract"))) &&
644
+ cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) {
645
+ cx.marked = "keyword";
646
+ return cont(classBody);
647
+ }
648
+ cx.marked = "property";
649
+ return cont(isTS ? classfield : functiondef, classBody);
650
+ }
651
+ if (value == "*") {
652
+ cx.marked = "keyword";
653
+ return cont(classBody);
654
+ }
655
+ if (type == ";") return cont(classBody);
656
+ if (type == "}") return cont();
657
+ }
658
+ function classfield(type, value) {
659
+ if (value == "?") return cont(classfield)
660
+ if (type == ":") return cont(typeexpr, maybeAssign)
661
+ return pass(functiondef)
662
+ }
663
+ function afterExport(type, value) {
664
+ if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); }
665
+ if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); }
666
+ if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";"));
667
+ return pass(statement);
668
+ }
669
+ function exportField(type, value) {
670
+ if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); }
671
+ if (type == "variable") return pass(expressionNoComma, exportField);
672
+ }
673
+ function afterImport(type) {
674
+ if (type == "string") return cont();
675
+ return pass(importSpec, maybeMoreImports, maybeFrom);
676
+ }
677
+ function importSpec(type, value) {
678
+ if (type == "{") return contCommasep(importSpec, "}");
679
+ if (type == "variable") register(value);
680
+ if (value == "*") cx.marked = "keyword";
681
+ return cont(maybeAs);
682
+ }
683
+ function maybeMoreImports(type) {
684
+ if (type == ",") return cont(importSpec, maybeMoreImports)
685
+ }
686
+ function maybeAs(_type, value) {
687
+ if (value == "as") { cx.marked = "keyword"; return cont(importSpec); }
688
+ }
689
+ function maybeFrom(_type, value) {
690
+ if (value == "from") { cx.marked = "keyword"; return cont(expression); }
691
+ }
692
+ function arrayLiteral(type) {
693
+ if (type == "]") return cont();
694
+ return pass(commasep(expressionNoComma, "]"));
695
+ }
696
+
697
+ function isContinuedStatement(state, textAfter) {
698
+ return state.lastType == "operator" || state.lastType == "," ||
699
+ isOperatorChar.test(textAfter.charAt(0)) ||
700
+ /[,.]/.test(textAfter.charAt(0));
701
+ }
702
+
703
+ // Interface
704
+
705
+ return {
706
+ startState: function(basecolumn) {
707
+ var state = {
708
+ tokenize: tokenBase,
709
+ lastType: "sof",
710
+ cc: [],
711
+ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
712
+ localVars: parserConfig.localVars,
713
+ context: parserConfig.localVars && {vars: parserConfig.localVars},
714
+ indented: basecolumn || 0
715
+ };
716
+ if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
717
+ state.globalVars = parserConfig.globalVars;
718
+ return state;
719
+ },
720
+
721
+ token: function(stream, state) {
722
+ if (stream.sol()) {
723
+ if (!state.lexical.hasOwnProperty("align"))
724
+ state.lexical.align = false;
725
+ state.indented = stream.indentation();
726
+ findFatArrow(stream, state);
727
+ }
728
+ if (state.tokenize != tokenComment && stream.eatSpace()) return null;
729
+ var style = state.tokenize(stream, state);
730
+ if (type == "comment") return style;
731
+ state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
732
+ return parseJS(state, style, type, content, stream);
733
+ },
734
+
735
+ indent: function(state, textAfter) {
736
+ if (state.tokenize == tokenComment) return CodeMirror.Pass;
737
+ if (state.tokenize != tokenBase) return 0;
738
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top
739
+ // Kludge to prevent 'maybelse' from blocking lexical scope pops
740
+ if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) {
741
+ var c = state.cc[i];
742
+ if (c == poplex) lexical = lexical.prev;
743
+ else if (c != maybeelse) break;
744
+ }
745
+ while ((lexical.type == "stat" || lexical.type == "form") &&
746
+ (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) &&
747
+ (top == maybeoperatorComma || top == maybeoperatorNoComma) &&
748
+ !/^[,\.=+\-*:?[\(]/.test(textAfter))))
749
+ lexical = lexical.prev;
750
+ if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
751
+ lexical = lexical.prev;
752
+ var type = lexical.type, closing = firstChar == type;
753
+
754
+ if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0);
755
+ else if (type == "form" && firstChar == "{") return lexical.indented;
756
+ else if (type == "form") return lexical.indented + indentUnit;
757
+ else if (type == "stat")
758
+ return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0);
759
+ else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
760
+ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
761
+ else if (lexical.align) return lexical.column + (closing ? 0 : 1);
762
+ else return lexical.indented + (closing ? 0 : indentUnit);
763
+ },
764
+
765
+ electricInput: /^\s*(?:case .*?:|default:|\{|\})$/,
766
+ blockCommentStart: jsonMode ? null : "/*",
767
+ blockCommentEnd: jsonMode ? null : "*/",
768
+ lineComment: jsonMode ? null : "//",
769
+ fold: "brace",
770
+ closeBrackets: "()[]{}''\"\"``",
771
+
772
+ helperType: jsonMode ? "json" : "javascript",
773
+ jsonldMode: jsonldMode,
774
+ jsonMode: jsonMode,
775
+
776
+ expressionAllowed: expressionAllowed,
777
+ skipExpression: function(state) {
778
+ var top = state.cc[state.cc.length - 1]
779
+ if (top == expression || top == expressionNoComma) state.cc.pop()
780
+ }
781
+ };
782
+ });
783
+
784
+ CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/);
785
+
786
+ CodeMirror.defineMIME("text/javascript", "javascript");
787
+ CodeMirror.defineMIME("text/ecmascript", "javascript");
788
+ CodeMirror.defineMIME("application/javascript", "javascript");
789
+ CodeMirror.defineMIME("application/x-javascript", "javascript");
790
+ CodeMirror.defineMIME("application/ecmascript", "javascript");
791
+ CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
792
+ CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
793
+ CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
794
+ CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
795
+ CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
796
+
797
+ });
js/codemirror/theme/3024-day.css ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: 3024 day
4
+ Author: Jan T. Sott (http://github.com/idleberg)
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-3024-day.CodeMirror { background: #f7f7f7; color: #3a3432; }
12
+ .cm-s-3024-day div.CodeMirror-selected { background: #d6d5d4; }
13
+
14
+ .cm-s-3024-day .CodeMirror-line::selection, .cm-s-3024-day .CodeMirror-line > span::selection, .cm-s-3024-day .CodeMirror-line > span > span::selection { background: #d6d5d4; }
15
+ .cm-s-3024-day .CodeMirror-line::-moz-selection, .cm-s-3024-day .CodeMirror-line > span::-moz-selection, .cm-s-3024-day .CodeMirror-line > span > span::selection { background: #d9d9d9; }
16
+
17
+ .cm-s-3024-day .CodeMirror-gutters { background: #f7f7f7; border-right: 0px; }
18
+ .cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; }
19
+ .cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; }
20
+ .cm-s-3024-day .CodeMirror-linenumber { color: #807d7c; }
21
+
22
+ .cm-s-3024-day .CodeMirror-cursor { border-left: 1px solid #5c5855; }
23
+
24
+ .cm-s-3024-day span.cm-comment { color: #cdab53; }
25
+ .cm-s-3024-day span.cm-atom { color: #a16a94; }
26
+ .cm-s-3024-day span.cm-number { color: #a16a94; }
27
+
28
+ .cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute { color: #01a252; }
29
+ .cm-s-3024-day span.cm-keyword { color: #db2d20; }
30
+ .cm-s-3024-day span.cm-string { color: #fded02; }
31
+
32
+ .cm-s-3024-day span.cm-variable { color: #01a252; }
33
+ .cm-s-3024-day span.cm-variable-2 { color: #01a0e4; }
34
+ .cm-s-3024-day span.cm-def { color: #e8bbd0; }
35
+ .cm-s-3024-day span.cm-bracket { color: #3a3432; }
36
+ .cm-s-3024-day span.cm-tag { color: #db2d20; }
37
+ .cm-s-3024-day span.cm-link { color: #a16a94; }
38
+ .cm-s-3024-day span.cm-error { background: #db2d20; color: #5c5855; }
39
+
40
+ .cm-s-3024-day .CodeMirror-activeline-background { background: #e8f2ff; }
41
+ .cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important; }
js/codemirror/theme/3024-night.css ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: 3024 night
4
+ Author: Jan T. Sott (http://github.com/idleberg)
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-3024-night.CodeMirror { background: #090300; color: #d6d5d4; }
12
+ .cm-s-3024-night div.CodeMirror-selected { background: #3a3432; }
13
+ .cm-s-3024-night .CodeMirror-line::selection, .cm-s-3024-night .CodeMirror-line > span::selection, .cm-s-3024-night .CodeMirror-line > span > span::selection { background: rgba(58, 52, 50, .99); }
14
+ .cm-s-3024-night .CodeMirror-line::-moz-selection, .cm-s-3024-night .CodeMirror-line > span::-moz-selection, .cm-s-3024-night .CodeMirror-line > span > span::-moz-selection { background: rgba(58, 52, 50, .99); }
15
+ .cm-s-3024-night .CodeMirror-gutters { background: #090300; border-right: 0px; }
16
+ .cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; }
17
+ .cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; }
18
+ .cm-s-3024-night .CodeMirror-linenumber { color: #5c5855; }
19
+
20
+ .cm-s-3024-night .CodeMirror-cursor { border-left: 1px solid #807d7c; }
21
+
22
+ .cm-s-3024-night span.cm-comment { color: #cdab53; }
23
+ .cm-s-3024-night span.cm-atom { color: #a16a94; }
24
+ .cm-s-3024-night span.cm-number { color: #a16a94; }
25
+
26
+ .cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute { color: #01a252; }
27
+ .cm-s-3024-night span.cm-keyword { color: #db2d20; }
28
+ .cm-s-3024-night span.cm-string { color: #fded02; }
29
+
30
+ .cm-s-3024-night span.cm-variable { color: #01a252; }
31
+ .cm-s-3024-night span.cm-variable-2 { color: #01a0e4; }
32
+ .cm-s-3024-night span.cm-def { color: #e8bbd0; }
33
+ .cm-s-3024-night span.cm-bracket { color: #d6d5d4; }
34
+ .cm-s-3024-night span.cm-tag { color: #db2d20; }
35
+ .cm-s-3024-night span.cm-link { color: #a16a94; }
36
+ .cm-s-3024-night span.cm-error { background: #db2d20; color: #807d7c; }
37
+
38
+ .cm-s-3024-night .CodeMirror-activeline-background { background: #2F2F2F; }
39
+ .cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/abcdef.css ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-abcdef.CodeMirror { background: #0f0f0f; color: #defdef; }
2
+ .cm-s-abcdef div.CodeMirror-selected { background: #515151; }
3
+ .cm-s-abcdef .CodeMirror-line::selection, .cm-s-abcdef .CodeMirror-line > span::selection, .cm-s-abcdef .CodeMirror-line > span > span::selection { background: rgba(56, 56, 56, 0.99); }
4
+ .cm-s-abcdef .CodeMirror-line::-moz-selection, .cm-s-abcdef .CodeMirror-line > span::-moz-selection, .cm-s-abcdef .CodeMirror-line > span > span::-moz-selection { background: rgba(56, 56, 56, 0.99); }
5
+ .cm-s-abcdef .CodeMirror-gutters { background: #555; border-right: 2px solid #314151; }
6
+ .cm-s-abcdef .CodeMirror-guttermarker { color: #222; }
7
+ .cm-s-abcdef .CodeMirror-guttermarker-subtle { color: azure; }
8
+ .cm-s-abcdef .CodeMirror-linenumber { color: #FFFFFF; }
9
+ .cm-s-abcdef .CodeMirror-cursor { border-left: 1px solid #00FF00; }
10
+
11
+ .cm-s-abcdef span.cm-keyword { color: darkgoldenrod; font-weight: bold; }
12
+ .cm-s-abcdef span.cm-atom { color: #77F; }
13
+ .cm-s-abcdef span.cm-number { color: violet; }
14
+ .cm-s-abcdef span.cm-def { color: #fffabc; }
15
+ .cm-s-abcdef span.cm-variable { color: #abcdef; }
16
+ .cm-s-abcdef span.cm-variable-2 { color: #cacbcc; }
17
+ .cm-s-abcdef span.cm-variable-3 { color: #def; }
18
+ .cm-s-abcdef span.cm-property { color: #fedcba; }
19
+ .cm-s-abcdef span.cm-operator { color: #ff0; }
20
+ .cm-s-abcdef span.cm-comment { color: #7a7b7c; font-style: italic;}
21
+ .cm-s-abcdef span.cm-string { color: #2b4; }
22
+ .cm-s-abcdef span.cm-meta { color: #C9F; }
23
+ .cm-s-abcdef span.cm-qualifier { color: #FFF700; }
24
+ .cm-s-abcdef span.cm-builtin { color: #30aabc; }
25
+ .cm-s-abcdef span.cm-bracket { color: #8a8a8a; }
26
+ .cm-s-abcdef span.cm-tag { color: #FFDD44; }
27
+ .cm-s-abcdef span.cm-attribute { color: #DDFF00; }
28
+ .cm-s-abcdef span.cm-error { color: #FF0000; }
29
+ .cm-s-abcdef span.cm-header { color: aquamarine; font-weight: bold; }
30
+ .cm-s-abcdef span.cm-link { color: blueviolet; }
31
+
32
+ .cm-s-abcdef .CodeMirror-activeline-background { background: #314151; }
js/codemirror/theme/ambiance-mobile.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ .cm-s-ambiance.CodeMirror {
2
+ -webkit-box-shadow: none;
3
+ -moz-box-shadow: none;
4
+ box-shadow: none;
5
+ }
js/codemirror/theme/ambiance.css ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* ambiance theme for codemirror */
2
+
3
+ /* Color scheme */
4
+
5
+ .cm-s-ambiance .cm-header { color: blue; }
6
+ .cm-s-ambiance .cm-quote { color: #24C2C7; }
7
+
8
+ .cm-s-ambiance .cm-keyword { color: #cda869; }
9
+ .cm-s-ambiance .cm-atom { color: #CF7EA9; }
10
+ .cm-s-ambiance .cm-number { color: #78CF8A; }
11
+ .cm-s-ambiance .cm-def { color: #aac6e3; }
12
+ .cm-s-ambiance .cm-variable { color: #ffb795; }
13
+ .cm-s-ambiance .cm-variable-2 { color: #eed1b3; }
14
+ .cm-s-ambiance .cm-variable-3 { color: #faded3; }
15
+ .cm-s-ambiance .cm-property { color: #eed1b3; }
16
+ .cm-s-ambiance .cm-operator { color: #fa8d6a; }
17
+ .cm-s-ambiance .cm-comment { color: #555; font-style:italic; }
18
+ .cm-s-ambiance .cm-string { color: #8f9d6a; }
19
+ .cm-s-ambiance .cm-string-2 { color: #9d937c; }
20
+ .cm-s-ambiance .cm-meta { color: #D2A8A1; }
21
+ .cm-s-ambiance .cm-qualifier { color: yellow; }
22
+ .cm-s-ambiance .cm-builtin { color: #9999cc; }
23
+ .cm-s-ambiance .cm-bracket { color: #24C2C7; }
24
+ .cm-s-ambiance .cm-tag { color: #fee4ff; }
25
+ .cm-s-ambiance .cm-attribute { color: #9B859D; }
26
+ .cm-s-ambiance .cm-hr { color: pink; }
27
+ .cm-s-ambiance .cm-link { color: #F4C20B; }
28
+ .cm-s-ambiance .cm-special { color: #FF9D00; }
29
+ .cm-s-ambiance .cm-error { color: #AF2018; }
30
+
31
+ .cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; }
32
+ .cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; }
33
+
34
+ .cm-s-ambiance div.CodeMirror-selected { background: rgba(255, 255, 255, 0.15); }
35
+ .cm-s-ambiance.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
36
+ .cm-s-ambiance .CodeMirror-line::selection, .cm-s-ambiance .CodeMirror-line > span::selection, .cm-s-ambiance .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
37
+ .cm-s-ambiance .CodeMirror-line::-moz-selection, .cm-s-ambiance .CodeMirror-line > span::-moz-selection, .cm-s-ambiance .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
38
+
39
+ /* Editor styling */
40
+
41
+ .cm-s-ambiance.CodeMirror {
42
+ line-height: 1.40em;
43
+ color: #E6E1DC;
44
+ background-color: #202020;
45
+ -webkit-box-shadow: inset 0 0 10px black;
46
+ -moz-box-shadow: inset 0 0 10px black;
47
+ box-shadow: inset 0 0 10px black;
48
+ }
49
+
50
+ .cm-s-ambiance .CodeMirror-gutters {
51
+ background: #3D3D3D;
52
+ border-right: 1px solid #4D4D4D;
53
+ box-shadow: 0 10px 20px black;
54
+ }
55
+
56
+ .cm-s-ambiance .CodeMirror-linenumber {
57
+ text-shadow: 0px 1px 1px #4d4d4d;
58
+ color: #111;
59
+ padding: 0 5px;
60
+ }
61
+
62
+ .cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; }
63
+ .cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; }
64
+
65
+ .cm-s-ambiance .CodeMirror-cursor { border-left: 1px solid #7991E8; }
66
+
67
+ .cm-s-ambiance .CodeMirror-activeline-background {
68
+ background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031);
69
+ }
70
+
71
+ .cm-s-ambiance.CodeMirror,
72
+ .cm-s-ambiance .CodeMirror-gutters {
73
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC");
74
+ }
js/codemirror/theme/base16-dark.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Base16 Default Dark
4
+ Author: Chris Kempson (http://chriskempson.com)
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-base16-dark.CodeMirror { background: #151515; color: #e0e0e0; }
12
+ .cm-s-base16-dark div.CodeMirror-selected { background: #303030; }
13
+ .cm-s-base16-dark .CodeMirror-line::selection, .cm-s-base16-dark .CodeMirror-line > span::selection, .cm-s-base16-dark .CodeMirror-line > span > span::selection { background: rgba(48, 48, 48, .99); }
14
+ .cm-s-base16-dark .CodeMirror-line::-moz-selection, .cm-s-base16-dark .CodeMirror-line > span::-moz-selection, .cm-s-base16-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(48, 48, 48, .99); }
15
+ .cm-s-base16-dark .CodeMirror-gutters { background: #151515; border-right: 0px; }
16
+ .cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; }
17
+ .cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; }
18
+ .cm-s-base16-dark .CodeMirror-linenumber { color: #505050; }
19
+ .cm-s-base16-dark .CodeMirror-cursor { border-left: 1px solid #b0b0b0; }
20
+
21
+ .cm-s-base16-dark span.cm-comment { color: #8f5536; }
22
+ .cm-s-base16-dark span.cm-atom { color: #aa759f; }
23
+ .cm-s-base16-dark span.cm-number { color: #aa759f; }
24
+
25
+ .cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute { color: #90a959; }
26
+ .cm-s-base16-dark span.cm-keyword { color: #ac4142; }
27
+ .cm-s-base16-dark span.cm-string { color: #f4bf75; }
28
+
29
+ .cm-s-base16-dark span.cm-variable { color: #90a959; }
30
+ .cm-s-base16-dark span.cm-variable-2 { color: #6a9fb5; }
31
+ .cm-s-base16-dark span.cm-def { color: #d28445; }
32
+ .cm-s-base16-dark span.cm-bracket { color: #e0e0e0; }
33
+ .cm-s-base16-dark span.cm-tag { color: #ac4142; }
34
+ .cm-s-base16-dark span.cm-link { color: #aa759f; }
35
+ .cm-s-base16-dark span.cm-error { background: #ac4142; color: #b0b0b0; }
36
+
37
+ .cm-s-base16-dark .CodeMirror-activeline-background { background: #202020; }
38
+ .cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/base16-light.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Base16 Default Light
4
+ Author: Chris Kempson (http://chriskempson.com)
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-base16-light.CodeMirror { background: #f5f5f5; color: #202020; }
12
+ .cm-s-base16-light div.CodeMirror-selected { background: #e0e0e0; }
13
+ .cm-s-base16-light .CodeMirror-line::selection, .cm-s-base16-light .CodeMirror-line > span::selection, .cm-s-base16-light .CodeMirror-line > span > span::selection { background: #e0e0e0; }
14
+ .cm-s-base16-light .CodeMirror-line::-moz-selection, .cm-s-base16-light .CodeMirror-line > span::-moz-selection, .cm-s-base16-light .CodeMirror-line > span > span::-moz-selection { background: #e0e0e0; }
15
+ .cm-s-base16-light .CodeMirror-gutters { background: #f5f5f5; border-right: 0px; }
16
+ .cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; }
17
+ .cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; }
18
+ .cm-s-base16-light .CodeMirror-linenumber { color: #b0b0b0; }
19
+ .cm-s-base16-light .CodeMirror-cursor { border-left: 1px solid #505050; }
20
+
21
+ .cm-s-base16-light span.cm-comment { color: #8f5536; }
22
+ .cm-s-base16-light span.cm-atom { color: #aa759f; }
23
+ .cm-s-base16-light span.cm-number { color: #aa759f; }
24
+
25
+ .cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute { color: #90a959; }
26
+ .cm-s-base16-light span.cm-keyword { color: #ac4142; }
27
+ .cm-s-base16-light span.cm-string { color: #f4bf75; }
28
+
29
+ .cm-s-base16-light span.cm-variable { color: #90a959; }
30
+ .cm-s-base16-light span.cm-variable-2 { color: #6a9fb5; }
31
+ .cm-s-base16-light span.cm-def { color: #d28445; }
32
+ .cm-s-base16-light span.cm-bracket { color: #202020; }
33
+ .cm-s-base16-light span.cm-tag { color: #ac4142; }
34
+ .cm-s-base16-light span.cm-link { color: #aa759f; }
35
+ .cm-s-base16-light span.cm-error { background: #ac4142; color: #505050; }
36
+
37
+ .cm-s-base16-light .CodeMirror-activeline-background { background: #DDDCDC; }
38
+ .cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/bespin.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Bespin
4
+ Author: Mozilla / Jan T. Sott
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-bespin.CodeMirror {background: #28211c; color: #9d9b97;}
12
+ .cm-s-bespin div.CodeMirror-selected {background: #36312e !important;}
13
+ .cm-s-bespin .CodeMirror-gutters {background: #28211c; border-right: 0px;}
14
+ .cm-s-bespin .CodeMirror-linenumber {color: #666666;}
15
+ .cm-s-bespin .CodeMirror-cursor {border-left: 1px solid #797977 !important;}
16
+
17
+ .cm-s-bespin span.cm-comment {color: #937121;}
18
+ .cm-s-bespin span.cm-atom {color: #9b859d;}
19
+ .cm-s-bespin span.cm-number {color: #9b859d;}
20
+
21
+ .cm-s-bespin span.cm-property, .cm-s-bespin span.cm-attribute {color: #54be0d;}
22
+ .cm-s-bespin span.cm-keyword {color: #cf6a4c;}
23
+ .cm-s-bespin span.cm-string {color: #f9ee98;}
24
+
25
+ .cm-s-bespin span.cm-variable {color: #54be0d;}
26
+ .cm-s-bespin span.cm-variable-2 {color: #5ea6ea;}
27
+ .cm-s-bespin span.cm-def {color: #cf7d34;}
28
+ .cm-s-bespin span.cm-error {background: #cf6a4c; color: #797977;}
29
+ .cm-s-bespin span.cm-bracket {color: #9d9b97;}
30
+ .cm-s-bespin span.cm-tag {color: #cf6a4c;}
31
+ .cm-s-bespin span.cm-link {color: #9b859d;}
32
+
33
+ .cm-s-bespin .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
34
+ .cm-s-bespin .CodeMirror-activeline-background { background: #404040; }
js/codemirror/theme/blackboard.css ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Port of TextMate's Blackboard theme */
2
+
3
+ .cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; }
4
+ .cm-s-blackboard div.CodeMirror-selected { background: #253B76; }
5
+ .cm-s-blackboard .CodeMirror-line::selection, .cm-s-blackboard .CodeMirror-line > span::selection, .cm-s-blackboard .CodeMirror-line > span > span::selection { background: rgba(37, 59, 118, .99); }
6
+ .cm-s-blackboard .CodeMirror-line::-moz-selection, .cm-s-blackboard .CodeMirror-line > span::-moz-selection, .cm-s-blackboard .CodeMirror-line > span > span::-moz-selection { background: rgba(37, 59, 118, .99); }
7
+ .cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; }
8
+ .cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; }
9
+ .cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; }
10
+ .cm-s-blackboard .CodeMirror-linenumber { color: #888; }
11
+ .cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7; }
12
+
13
+ .cm-s-blackboard .cm-keyword { color: #FBDE2D; }
14
+ .cm-s-blackboard .cm-atom { color: #D8FA3C; }
15
+ .cm-s-blackboard .cm-number { color: #D8FA3C; }
16
+ .cm-s-blackboard .cm-def { color: #8DA6CE; }
17
+ .cm-s-blackboard .cm-variable { color: #FF6400; }
18
+ .cm-s-blackboard .cm-operator { color: #FBDE2D; }
19
+ .cm-s-blackboard .cm-comment { color: #AEAEAE; }
20
+ .cm-s-blackboard .cm-string { color: #61CE3C; }
21
+ .cm-s-blackboard .cm-string-2 { color: #61CE3C; }
22
+ .cm-s-blackboard .cm-meta { color: #D8FA3C; }
23
+ .cm-s-blackboard .cm-builtin { color: #8DA6CE; }
24
+ .cm-s-blackboard .cm-tag { color: #8DA6CE; }
25
+ .cm-s-blackboard .cm-attribute { color: #8DA6CE; }
26
+ .cm-s-blackboard .cm-header { color: #FF6400; }
27
+ .cm-s-blackboard .cm-hr { color: #AEAEAE; }
28
+ .cm-s-blackboard .cm-link { color: #8DA6CE; }
29
+ .cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; }
30
+
31
+ .cm-s-blackboard .CodeMirror-activeline-background { background: #3C3636; }
32
+ .cm-s-blackboard .CodeMirror-matchingbracket { outline:1px solid grey;color:white !important; }
js/codemirror/theme/cobalt.css ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-cobalt.CodeMirror { background: #002240; color: white; }
2
+ .cm-s-cobalt div.CodeMirror-selected { background: #b36539; }
3
+ .cm-s-cobalt .CodeMirror-line::selection, .cm-s-cobalt .CodeMirror-line > span::selection, .cm-s-cobalt .CodeMirror-line > span > span::selection { background: rgba(179, 101, 57, .99); }
4
+ .cm-s-cobalt .CodeMirror-line::-moz-selection, .cm-s-cobalt .CodeMirror-line > span::-moz-selection, .cm-s-cobalt .CodeMirror-line > span > span::-moz-selection { background: rgba(179, 101, 57, .99); }
5
+ .cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
6
+ .cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; }
7
+ .cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
8
+ .cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; }
9
+ .cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white; }
10
+
11
+ .cm-s-cobalt span.cm-comment { color: #08f; }
12
+ .cm-s-cobalt span.cm-atom { color: #845dc4; }
13
+ .cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; }
14
+ .cm-s-cobalt span.cm-keyword { color: #ffee80; }
15
+ .cm-s-cobalt span.cm-string { color: #3ad900; }
16
+ .cm-s-cobalt span.cm-meta { color: #ff9d00; }
17
+ .cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; }
18
+ .cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; }
19
+ .cm-s-cobalt span.cm-bracket { color: #d8d8d8; }
20
+ .cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; }
21
+ .cm-s-cobalt span.cm-link { color: #845dc4; }
22
+ .cm-s-cobalt span.cm-error { color: #9d1e15; }
23
+
24
+ .cm-s-cobalt .CodeMirror-activeline-background { background: #002D57; }
25
+ .cm-s-cobalt .CodeMirror-matchingbracket { outline:1px solid grey;color:white !important; }
js/codemirror/theme/colorforth.css ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-colorforth.CodeMirror { background: #000000; color: #f8f8f8; }
2
+ .cm-s-colorforth .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
3
+ .cm-s-colorforth .CodeMirror-guttermarker { color: #FFBD40; }
4
+ .cm-s-colorforth .CodeMirror-guttermarker-subtle { color: #78846f; }
5
+ .cm-s-colorforth .CodeMirror-linenumber { color: #bababa; }
6
+ .cm-s-colorforth .CodeMirror-cursor { border-left: 1px solid white; }
7
+
8
+ .cm-s-colorforth span.cm-comment { color: #ededed; }
9
+ .cm-s-colorforth span.cm-def { color: #ff1c1c; font-weight:bold; }
10
+ .cm-s-colorforth span.cm-keyword { color: #ffd900; }
11
+ .cm-s-colorforth span.cm-builtin { color: #00d95a; }
12
+ .cm-s-colorforth span.cm-variable { color: #73ff00; }
13
+ .cm-s-colorforth span.cm-string { color: #007bff; }
14
+ .cm-s-colorforth span.cm-number { color: #00c4ff; }
15
+ .cm-s-colorforth span.cm-atom { color: #606060; }
16
+
17
+ .cm-s-colorforth span.cm-variable-2 { color: #EEE; }
18
+ .cm-s-colorforth span.cm-variable-3 { color: #DDD; }
19
+ .cm-s-colorforth span.cm-property {}
20
+ .cm-s-colorforth span.cm-operator {}
21
+
22
+ .cm-s-colorforth span.cm-meta { color: yellow; }
23
+ .cm-s-colorforth span.cm-qualifier { color: #FFF700; }
24
+ .cm-s-colorforth span.cm-bracket { color: #cc7; }
25
+ .cm-s-colorforth span.cm-tag { color: #FFBD40; }
26
+ .cm-s-colorforth span.cm-attribute { color: #FFF700; }
27
+ .cm-s-colorforth span.cm-error { color: #f00; }
28
+
29
+ .cm-s-colorforth div.CodeMirror-selected { background: #333d53; }
30
+
31
+ .cm-s-colorforth span.cm-compilation { background: rgba(255, 255, 255, 0.12); }
32
+
33
+ .cm-s-colorforth .CodeMirror-activeline-background { background: #253540; }
js/codemirror/theme/dracula.css ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: dracula
4
+ Author: Michael Kaminsky (http://github.com/mkaminsky11)
5
+
6
+ Original dracula color scheme by Zeno Rocha (https://github.com/zenorocha/dracula-theme)
7
+
8
+ */
9
+
10
+
11
+ .cm-s-dracula.CodeMirror, .cm-s-dracula .CodeMirror-gutters {
12
+ background-color: #282a36 !important;
13
+ color: #f8f8f2 !important;
14
+ border: none;
15
+ }
16
+ .cm-s-dracula .CodeMirror-gutters { color: #282a36; }
17
+ .cm-s-dracula .CodeMirror-cursor { border-left: solid thin #f8f8f0; }
18
+ .cm-s-dracula .CodeMirror-linenumber { color: #6D8A88; }
19
+ .cm-s-dracula .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
20
+ .cm-s-dracula .CodeMirror-line::selection, .cm-s-dracula .CodeMirror-line > span::selection, .cm-s-dracula .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
21
+ .cm-s-dracula .CodeMirror-line::-moz-selection, .cm-s-dracula .CodeMirror-line > span::-moz-selection, .cm-s-dracula .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
22
+ .cm-s-dracula span.cm-comment { color: #6272a4; }
23
+ .cm-s-dracula span.cm-string, .cm-s-dracula span.cm-string-2 { color: #f1fa8c; }
24
+ .cm-s-dracula span.cm-number { color: #bd93f9; }
25
+ .cm-s-dracula span.cm-variable { color: #50fa7b; }
26
+ .cm-s-dracula span.cm-variable-2 { color: white; }
27
+ .cm-s-dracula span.cm-def { color: #50fa7b; }
28
+ .cm-s-dracula span.cm-operator { color: #ff79c6; }
29
+ .cm-s-dracula span.cm-keyword { color: #ff79c6; }
30
+ .cm-s-dracula span.cm-atom { color: #bd93f9; }
31
+ .cm-s-dracula span.cm-meta { color: #f8f8f2; }
32
+ .cm-s-dracula span.cm-tag { color: #ff79c6; }
33
+ .cm-s-dracula span.cm-attribute { color: #50fa7b; }
34
+ .cm-s-dracula span.cm-qualifier { color: #50fa7b; }
35
+ .cm-s-dracula span.cm-property { color: #66d9ef; }
36
+ .cm-s-dracula span.cm-builtin { color: #50fa7b; }
37
+ .cm-s-dracula span.cm-variable-3 { color: #ffb86c; }
38
+
39
+ .cm-s-dracula .CodeMirror-activeline-background { background: rgba(255,255,255,0.1); }
40
+ .cm-s-dracula .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/duotone-dark.css ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Name: DuoTone-Dark
3
+ Author: by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes)
4
+
5
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg), adapted by Bram de Haan (https://github.com/atelierbram/)
6
+ */
7
+
8
+ .cm-s-duotone-dark.CodeMirror { background: #2a2734; color: #6c6783; }
9
+ .cm-s-duotone-dark div.CodeMirror-selected { background: #545167!important; }
10
+ .cm-s-duotone-dark .CodeMirror-gutters { background: #2a2734; border-right: 0px; }
11
+ .cm-s-duotone-dark .CodeMirror-linenumber { color: #545167; }
12
+
13
+ /* begin cursor */
14
+ .cm-s-duotone-dark .CodeMirror-cursor { border-left: 1px solid #ffad5c; /* border-left: 1px solid #ffad5c80; */ border-right: .5em solid #ffad5c; /* border-right: .5em solid #ffad5c80; */ opacity: .5; }
15
+ .cm-s-duotone-dark .CodeMirror-activeline-background { background: #363342; /* background: #36334280; */ opacity: .5;}
16
+ .cm-s-duotone-dark .cm-fat-cursor .CodeMirror-cursor { background: #ffad5c; /* background: #ffad5c80; */ opacity: .5;}
17
+ /* end cursor */
18
+
19
+ .cm-s-duotone-dark span.cm-atom, .cm-s-duotone-dark span.cm-number, .cm-s-duotone-dark span.cm-keyword, .cm-s-duotone-dark span.cm-variable, .cm-s-duotone-dark span.cm-attribute, .cm-s-duotone-dark span.cm-quote, .cm-s-duotone-dark span.cm-hr, .cm-s-duotone-dark span.cm-link { color: #ffcc99; }
20
+
21
+ .cm-s-duotone-dark span.cm-property { color: #9a86fd; }
22
+ .cm-s-duotone-dark span.cm-punctuation, .cm-s-duotone-dark span.cm-unit, .cm-s-duotone-dark span.cm-negative { color: #e09142; }
23
+ .cm-s-duotone-dark span.cm-string { color: #ffb870; }
24
+ .cm-s-duotone-dark span.cm-operator { color: #ffad5c; }
25
+ .cm-s-duotone-dark span.cm-positive { color: #6a51e6; }
26
+
27
+ .cm-s-duotone-dark span.cm-variable-2, .cm-s-duotone-dark span.cm-variable-3, .cm-s-duotone-dark span.cm-string-2, .cm-s-duotone-dark span.cm-url { color: #7a63ee; }
28
+ .cm-s-duotone-dark span.cm-def, .cm-s-duotone-dark span.cm-tag, .cm-s-duotone-dark span.cm-builtin, .cm-s-duotone-dark span.cm-qualifier, .cm-s-duotone-dark span.cm-header, .cm-s-duotone-dark span.cm-em { color: #eeebff; }
29
+ .cm-s-duotone-dark span.cm-bracket, .cm-s-duotone-dark span.cm-comment { color: #6c6783; }
30
+
31
+ /* using #f00 red for errors, don't think any of the colorscheme variables will stand out enough, ... maybe by giving it a background-color ... */
32
+ .cm-s-duotone-dark span.cm-error, .cm-s-duotone-dark span.cm-invalidchar { color: #f00; }
33
+
34
+ .cm-s-duotone-dark span.cm-header { font-weight: normal; }
35
+ .cm-s-duotone-dark .CodeMirror-matchingbracket { text-decoration: underline; color: #eeebff !important; }
js/codemirror/theme/duotone-light.css ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Name: DuoTone-Light
3
+ Author: by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes)
4
+
5
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg), adapted by Bram de Haan (https://github.com/atelierbram/)
6
+ */
7
+
8
+ .cm-s-duotone-light.CodeMirror { background: #faf8f5; color: #b29762; }
9
+ .cm-s-duotone-light div.CodeMirror-selected { background: #e3dcce !important; }
10
+ .cm-s-duotone-light .CodeMirror-gutters { background: #faf8f5; border-right: 0px; }
11
+ .cm-s-duotone-light .CodeMirror-linenumber { color: #cdc4b1; }
12
+
13
+ /* begin cursor */
14
+ .cm-s-duotone-light .CodeMirror-cursor { border-left: 1px solid #93abdc; /* border-left: 1px solid #93abdc80; */ border-right: .5em solid #93abdc; /* border-right: .5em solid #93abdc80; */ opacity: .5; }
15
+ .cm-s-duotone-light .CodeMirror-activeline-background { background: #e3dcce; /* background: #e3dcce80; */ opacity: .5; }
16
+ .cm-s-duotone-light .cm-fat-cursor .CodeMirror-cursor { background: #93abdc; /* #93abdc80; */ opacity: .5; }
17
+ /* end cursor */
18
+
19
+ .cm-s-duotone-light span.cm-atom, .cm-s-duotone-light span.cm-number, .cm-s-duotone-light span.cm-keyword, .cm-s-duotone-light span.cm-variable, .cm-s-duotone-light span.cm-attribute, .cm-s-duotone-light span.cm-quote, .cm-s-duotone-light-light span.cm-hr, .cm-s-duotone-light-light span.cm-link { color: #063289; }
20
+
21
+ .cm-s-duotone-light span.cm-property { color: #b29762; }
22
+ .cm-s-duotone-light span.cm-punctuation, .cm-s-duotone-light span.cm-unit, .cm-s-duotone-light span.cm-negative { color: #063289; }
23
+ .cm-s-duotone-light span.cm-string, .cm-s-duotone-light span.cm-operator { color: #1659df; }
24
+ .cm-s-duotone-light span.cm-positive { color: #896724; }
25
+
26
+ .cm-s-duotone-light span.cm-variable-2, .cm-s-duotone-light span.cm-variable-3, .cm-s-duotone-light span.cm-string-2, .cm-s-duotone-light span.cm-url { color: #896724; }
27
+ .cm-s-duotone-light span.cm-def, .cm-s-duotone-light span.cm-tag, .cm-s-duotone-light span.cm-builtin, .cm-s-duotone-light span.cm-qualifier, .cm-s-duotone-light span.cm-header, .cm-s-duotone-light span.cm-em { color: #2d2006; }
28
+ .cm-s-duotone-light span.cm-bracket, .cm-s-duotone-light span.cm-comment { color: #b6ad9a; }
29
+
30
+ /* using #f00 red for errors, don't think any of the colorscheme variables will stand out enough, ... maybe by giving it a background-color ... */
31
+ /* .cm-s-duotone-light span.cm-error { background: #896724; color: #728fcb; } */
32
+ .cm-s-duotone-light span.cm-error, .cm-s-duotone-light span.cm-invalidchar { color: #f00; }
33
+
34
+ .cm-s-duotone-light span.cm-header { font-weight: normal; }
35
+ .cm-s-duotone-light .CodeMirror-matchingbracket { text-decoration: underline; color: #faf8f5 !important; }
36
+
js/codemirror/theme/eclipse.css ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-eclipse span.cm-meta { color: #FF1717; }
2
+ .cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; }
3
+ .cm-s-eclipse span.cm-atom { color: #219; }
4
+ .cm-s-eclipse span.cm-number { color: #164; }
5
+ .cm-s-eclipse span.cm-def { color: #00f; }
6
+ .cm-s-eclipse span.cm-variable { color: black; }
7
+ .cm-s-eclipse span.cm-variable-2 { color: #0000C0; }
8
+ .cm-s-eclipse span.cm-variable-3 { color: #0000C0; }
9
+ .cm-s-eclipse span.cm-property { color: black; }
10
+ .cm-s-eclipse span.cm-operator { color: black; }
11
+ .cm-s-eclipse span.cm-comment { color: #3F7F5F; }
12
+ .cm-s-eclipse span.cm-string { color: #2A00FF; }
13
+ .cm-s-eclipse span.cm-string-2 { color: #f50; }
14
+ .cm-s-eclipse span.cm-qualifier { color: #555; }
15
+ .cm-s-eclipse span.cm-builtin { color: #30a; }
16
+ .cm-s-eclipse span.cm-bracket { color: #cc7; }
17
+ .cm-s-eclipse span.cm-tag { color: #170; }
18
+ .cm-s-eclipse span.cm-attribute { color: #00c; }
19
+ .cm-s-eclipse span.cm-link { color: #219; }
20
+ .cm-s-eclipse span.cm-error { color: #f00; }
21
+
22
+ .cm-s-eclipse .CodeMirror-activeline-background { background: #e8f2ff; }
23
+ .cm-s-eclipse .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }
js/codemirror/theme/elegant.css ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom { color: #762; }
2
+ .cm-s-elegant span.cm-comment { color: #262; font-style: italic; line-height: 1em; }
3
+ .cm-s-elegant span.cm-meta { color: #555; font-style: italic; line-height: 1em; }
4
+ .cm-s-elegant span.cm-variable { color: black; }
5
+ .cm-s-elegant span.cm-variable-2 { color: #b11; }
6
+ .cm-s-elegant span.cm-qualifier { color: #555; }
7
+ .cm-s-elegant span.cm-keyword { color: #730; }
8
+ .cm-s-elegant span.cm-builtin { color: #30a; }
9
+ .cm-s-elegant span.cm-link { color: #762; }
10
+ .cm-s-elegant span.cm-error { background-color: #fdd; }
11
+
12
+ .cm-s-elegant .CodeMirror-activeline-background { background: #e8f2ff; }
13
+ .cm-s-elegant .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }
js/codemirror/theme/erlang-dark.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-erlang-dark.CodeMirror { background: #002240; color: white; }
2
+ .cm-s-erlang-dark div.CodeMirror-selected { background: #b36539; }
3
+ .cm-s-erlang-dark .CodeMirror-line::selection, .cm-s-erlang-dark .CodeMirror-line > span::selection, .cm-s-erlang-dark .CodeMirror-line > span > span::selection { background: rgba(179, 101, 57, .99); }
4
+ .cm-s-erlang-dark .CodeMirror-line::-moz-selection, .cm-s-erlang-dark .CodeMirror-line > span::-moz-selection, .cm-s-erlang-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(179, 101, 57, .99); }
5
+ .cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
6
+ .cm-s-erlang-dark .CodeMirror-guttermarker { color: white; }
7
+ .cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
8
+ .cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; }
9
+ .cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white; }
10
+
11
+ .cm-s-erlang-dark span.cm-quote { color: #ccc; }
12
+ .cm-s-erlang-dark span.cm-atom { color: #f133f1; }
13
+ .cm-s-erlang-dark span.cm-attribute { color: #ff80e1; }
14
+ .cm-s-erlang-dark span.cm-bracket { color: #ff9d00; }
15
+ .cm-s-erlang-dark span.cm-builtin { color: #eaa; }
16
+ .cm-s-erlang-dark span.cm-comment { color: #77f; }
17
+ .cm-s-erlang-dark span.cm-def { color: #e7a; }
18
+ .cm-s-erlang-dark span.cm-keyword { color: #ffee80; }
19
+ .cm-s-erlang-dark span.cm-meta { color: #50fefe; }
20
+ .cm-s-erlang-dark span.cm-number { color: #ffd0d0; }
21
+ .cm-s-erlang-dark span.cm-operator { color: #d55; }
22
+ .cm-s-erlang-dark span.cm-property { color: #ccc; }
23
+ .cm-s-erlang-dark span.cm-qualifier { color: #ccc; }
24
+ .cm-s-erlang-dark span.cm-special { color: #ffbbbb; }
25
+ .cm-s-erlang-dark span.cm-string { color: #3ad900; }
26
+ .cm-s-erlang-dark span.cm-string-2 { color: #ccc; }
27
+ .cm-s-erlang-dark span.cm-tag { color: #9effff; }
28
+ .cm-s-erlang-dark span.cm-variable { color: #50fe50; }
29
+ .cm-s-erlang-dark span.cm-variable-2 { color: #e0e; }
30
+ .cm-s-erlang-dark span.cm-variable-3 { color: #ccc; }
31
+ .cm-s-erlang-dark span.cm-error { color: #9d1e15; }
32
+
33
+ .cm-s-erlang-dark .CodeMirror-activeline-background { background: #013461; }
34
+ .cm-s-erlang-dark .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }
js/codemirror/theme/hopscotch.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Hopscotch
4
+ Author: Jan T. Sott
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-hopscotch.CodeMirror {background: #322931; color: #d5d3d5;}
12
+ .cm-s-hopscotch div.CodeMirror-selected {background: #433b42 !important;}
13
+ .cm-s-hopscotch .CodeMirror-gutters {background: #322931; border-right: 0px;}
14
+ .cm-s-hopscotch .CodeMirror-linenumber {color: #797379;}
15
+ .cm-s-hopscotch .CodeMirror-cursor {border-left: 1px solid #989498 !important;}
16
+
17
+ .cm-s-hopscotch span.cm-comment {color: #b33508;}
18
+ .cm-s-hopscotch span.cm-atom {color: #c85e7c;}
19
+ .cm-s-hopscotch span.cm-number {color: #c85e7c;}
20
+
21
+ .cm-s-hopscotch span.cm-property, .cm-s-hopscotch span.cm-attribute {color: #8fc13e;}
22
+ .cm-s-hopscotch span.cm-keyword {color: #dd464c;}
23
+ .cm-s-hopscotch span.cm-string {color: #fdcc59;}
24
+
25
+ .cm-s-hopscotch span.cm-variable {color: #8fc13e;}
26
+ .cm-s-hopscotch span.cm-variable-2 {color: #1290bf;}
27
+ .cm-s-hopscotch span.cm-def {color: #fd8b19;}
28
+ .cm-s-hopscotch span.cm-error {background: #dd464c; color: #989498;}
29
+ .cm-s-hopscotch span.cm-bracket {color: #d5d3d5;}
30
+ .cm-s-hopscotch span.cm-tag {color: #dd464c;}
31
+ .cm-s-hopscotch span.cm-link {color: #c85e7c;}
32
+
33
+ .cm-s-hopscotch .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
34
+ .cm-s-hopscotch .CodeMirror-activeline-background { background: #302020; }
js/codemirror/theme/icecoder.css ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ ICEcoder default theme by Matt Pass, used in code editor available at https://icecoder.net
3
+ */
4
+
5
+ .cm-s-icecoder { color: #666; background: #1d1d1b; }
6
+
7
+ .cm-s-icecoder span.cm-keyword { color: #eee; font-weight:bold; } /* off-white 1 */
8
+ .cm-s-icecoder span.cm-atom { color: #e1c76e; } /* yellow */
9
+ .cm-s-icecoder span.cm-number { color: #6cb5d9; } /* blue */
10
+ .cm-s-icecoder span.cm-def { color: #b9ca4a; } /* green */
11
+
12
+ .cm-s-icecoder span.cm-variable { color: #6cb5d9; } /* blue */
13
+ .cm-s-icecoder span.cm-variable-2 { color: #cc1e5c; } /* pink */
14
+ .cm-s-icecoder span.cm-variable-3 { color: #f9602c; } /* orange */
15
+
16
+ .cm-s-icecoder span.cm-property { color: #eee; } /* off-white 1 */
17
+ .cm-s-icecoder span.cm-operator { color: #9179bb; } /* purple */
18
+ .cm-s-icecoder span.cm-comment { color: #97a3aa; } /* grey-blue */
19
+
20
+ .cm-s-icecoder span.cm-string { color: #b9ca4a; } /* green */
21
+ .cm-s-icecoder span.cm-string-2 { color: #6cb5d9; } /* blue */
22
+
23
+ .cm-s-icecoder span.cm-meta { color: #555; } /* grey */
24
+
25
+ .cm-s-icecoder span.cm-qualifier { color: #555; } /* grey */
26
+ .cm-s-icecoder span.cm-builtin { color: #214e7b; } /* bright blue */
27
+ .cm-s-icecoder span.cm-bracket { color: #cc7; } /* grey-yellow */
28
+
29
+ .cm-s-icecoder span.cm-tag { color: #e8e8e8; } /* off-white 2 */
30
+ .cm-s-icecoder span.cm-attribute { color: #099; } /* teal */
31
+
32
+ .cm-s-icecoder span.cm-header { color: #6a0d6a; } /* purple-pink */
33
+ .cm-s-icecoder span.cm-quote { color: #186718; } /* dark green */
34
+ .cm-s-icecoder span.cm-hr { color: #888; } /* mid-grey */
35
+ .cm-s-icecoder span.cm-link { color: #e1c76e; } /* yellow */
36
+ .cm-s-icecoder span.cm-error { color: #d00; } /* red */
37
+
38
+ .cm-s-icecoder .CodeMirror-cursor { border-left: 1px solid white; }
39
+ .cm-s-icecoder div.CodeMirror-selected { color: #fff; background: #037; }
40
+ .cm-s-icecoder .CodeMirror-gutters { background: #1d1d1b; min-width: 41px; border-right: 0; }
41
+ .cm-s-icecoder .CodeMirror-linenumber { color: #555; cursor: default; }
42
+ .cm-s-icecoder .CodeMirror-matchingbracket { color: #fff !important; background: #555 !important; }
43
+ .cm-s-icecoder .CodeMirror-activeline-background { background: #000; }
js/codemirror/theme/isotope.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Isotope
4
+ Author: David Desandro / Jan T. Sott
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-isotope.CodeMirror {background: #000000; color: #e0e0e0;}
12
+ .cm-s-isotope div.CodeMirror-selected {background: #404040 !important;}
13
+ .cm-s-isotope .CodeMirror-gutters {background: #000000; border-right: 0px;}
14
+ .cm-s-isotope .CodeMirror-linenumber {color: #808080;}
15
+ .cm-s-isotope .CodeMirror-cursor {border-left: 1px solid #c0c0c0 !important;}
16
+
17
+ .cm-s-isotope span.cm-comment {color: #3300ff;}
18
+ .cm-s-isotope span.cm-atom {color: #cc00ff;}
19
+ .cm-s-isotope span.cm-number {color: #cc00ff;}
20
+
21
+ .cm-s-isotope span.cm-property, .cm-s-isotope span.cm-attribute {color: #33ff00;}
22
+ .cm-s-isotope span.cm-keyword {color: #ff0000;}
23
+ .cm-s-isotope span.cm-string {color: #ff0099;}
24
+
25
+ .cm-s-isotope span.cm-variable {color: #33ff00;}
26
+ .cm-s-isotope span.cm-variable-2 {color: #0066ff;}
27
+ .cm-s-isotope span.cm-def {color: #ff9900;}
28
+ .cm-s-isotope span.cm-error {background: #ff0000; color: #c0c0c0;}
29
+ .cm-s-isotope span.cm-bracket {color: #e0e0e0;}
30
+ .cm-s-isotope span.cm-tag {color: #ff0000;}
31
+ .cm-s-isotope span.cm-link {color: #cc00ff;}
32
+
33
+ .cm-s-isotope .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
34
+ .cm-s-isotope .CodeMirror-activeline-background { background: #202020; }
js/codemirror/theme/lesser-dark.css ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ http://lesscss.org/ dark theme
3
+ Ported to CodeMirror by Peter Kroon
4
+ */
5
+ .cm-s-lesser-dark {
6
+ line-height: 1.3em;
7
+ }
8
+ .cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; }
9
+ .cm-s-lesser-dark div.CodeMirror-selected { background: #45443B; } /* 33322B*/
10
+ .cm-s-lesser-dark .CodeMirror-line::selection, .cm-s-lesser-dark .CodeMirror-line > span::selection, .cm-s-lesser-dark .CodeMirror-line > span > span::selection { background: rgba(69, 68, 59, .99); }
11
+ .cm-s-lesser-dark .CodeMirror-line::-moz-selection, .cm-s-lesser-dark .CodeMirror-line > span::-moz-selection, .cm-s-lesser-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(69, 68, 59, .99); }
12
+ .cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white; }
13
+ .cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/
14
+
15
+ .cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
16
+
17
+ .cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; }
18
+ .cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; }
19
+ .cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; }
20
+ .cm-s-lesser-dark .CodeMirror-linenumber { color: #777; }
21
+
22
+ .cm-s-lesser-dark span.cm-header { color: #a0a; }
23
+ .cm-s-lesser-dark span.cm-quote { color: #090; }
24
+ .cm-s-lesser-dark span.cm-keyword { color: #599eff; }
25
+ .cm-s-lesser-dark span.cm-atom { color: #C2B470; }
26
+ .cm-s-lesser-dark span.cm-number { color: #B35E4D; }
27
+ .cm-s-lesser-dark span.cm-def { color: white; }
28
+ .cm-s-lesser-dark span.cm-variable { color:#D9BF8C; }
29
+ .cm-s-lesser-dark span.cm-variable-2 { color: #669199; }
30
+ .cm-s-lesser-dark span.cm-variable-3 { color: white; }
31
+ .cm-s-lesser-dark span.cm-property { color: #92A75C; }
32
+ .cm-s-lesser-dark span.cm-operator { color: #92A75C; }
33
+ .cm-s-lesser-dark span.cm-comment { color: #666; }
34
+ .cm-s-lesser-dark span.cm-string { color: #BCD279; }
35
+ .cm-s-lesser-dark span.cm-string-2 { color: #f50; }
36
+ .cm-s-lesser-dark span.cm-meta { color: #738C73; }
37
+ .cm-s-lesser-dark span.cm-qualifier { color: #555; }
38
+ .cm-s-lesser-dark span.cm-builtin { color: #ff9e59; }
39
+ .cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; }
40
+ .cm-s-lesser-dark span.cm-tag { color: #669199; }
41
+ .cm-s-lesser-dark span.cm-attribute { color: #00c; }
42
+ .cm-s-lesser-dark span.cm-hr { color: #999; }
43
+ .cm-s-lesser-dark span.cm-link { color: #00c; }
44
+ .cm-s-lesser-dark span.cm-error { color: #9d1e15; }
45
+
46
+ .cm-s-lesser-dark .CodeMirror-activeline-background { background: #3C3A3A; }
47
+ .cm-s-lesser-dark .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }
js/codemirror/theme/liquibyte.css ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-liquibyte.CodeMirror {
2
+ background-color: #000;
3
+ color: #fff;
4
+ line-height: 1.2em;
5
+ font-size: 1em;
6
+ }
7
+ .cm-s-liquibyte .CodeMirror-focused .cm-matchhighlight {
8
+ text-decoration: underline;
9
+ text-decoration-color: #0f0;
10
+ text-decoration-style: wavy;
11
+ }
12
+ .cm-s-liquibyte .cm-trailingspace {
13
+ text-decoration: line-through;
14
+ text-decoration-color: #f00;
15
+ text-decoration-style: dotted;
16
+ }
17
+ .cm-s-liquibyte .cm-tab {
18
+ text-decoration: line-through;
19
+ text-decoration-color: #404040;
20
+ text-decoration-style: dotted;
21
+ }
22
+ .cm-s-liquibyte .CodeMirror-gutters { background-color: #262626; border-right: 1px solid #505050; padding-right: 0.8em; }
23
+ .cm-s-liquibyte .CodeMirror-gutter-elt div { font-size: 1.2em; }
24
+ .cm-s-liquibyte .CodeMirror-guttermarker { }
25
+ .cm-s-liquibyte .CodeMirror-guttermarker-subtle { }
26
+ .cm-s-liquibyte .CodeMirror-linenumber { color: #606060; padding-left: 0; }
27
+ .cm-s-liquibyte .CodeMirror-cursor { border-left: 1px solid #eee; }
28
+
29
+ .cm-s-liquibyte span.cm-comment { color: #008000; }
30
+ .cm-s-liquibyte span.cm-def { color: #ffaf40; font-weight: bold; }
31
+ .cm-s-liquibyte span.cm-keyword { color: #c080ff; font-weight: bold; }
32
+ .cm-s-liquibyte span.cm-builtin { color: #ffaf40; font-weight: bold; }
33
+ .cm-s-liquibyte span.cm-variable { color: #5967ff; font-weight: bold; }
34
+ .cm-s-liquibyte span.cm-string { color: #ff8000; }
35
+ .cm-s-liquibyte span.cm-number { color: #0f0; font-weight: bold; }
36
+ .cm-s-liquibyte span.cm-atom { color: #bf3030; font-weight: bold; }
37
+
38
+ .cm-s-liquibyte span.cm-variable-2 { color: #007f7f; font-weight: bold; }
39
+ .cm-s-liquibyte span.cm-variable-3 { color: #c080ff; font-weight: bold; }
40
+ .cm-s-liquibyte span.cm-property { color: #999; font-weight: bold; }
41
+ .cm-s-liquibyte span.cm-operator { color: #fff; }
42
+
43
+ .cm-s-liquibyte span.cm-meta { color: #0f0; }
44
+ .cm-s-liquibyte span.cm-qualifier { color: #fff700; font-weight: bold; }
45
+ .cm-s-liquibyte span.cm-bracket { color: #cc7; }
46
+ .cm-s-liquibyte span.cm-tag { color: #ff0; font-weight: bold; }
47
+ .cm-s-liquibyte span.cm-attribute { color: #c080ff; font-weight: bold; }
48
+ .cm-s-liquibyte span.cm-error { color: #f00; }
49
+
50
+ .cm-s-liquibyte div.CodeMirror-selected { background-color: rgba(255, 0, 0, 0.25); }
51
+
52
+ .cm-s-liquibyte span.cm-compilation { background-color: rgba(255, 255, 255, 0.12); }
53
+
54
+ .cm-s-liquibyte .CodeMirror-activeline-background { background-color: rgba(0, 255, 0, 0.15); }
55
+
56
+ /* Default styles for common addons */
57
+ .cm-s-liquibyte .CodeMirror span.CodeMirror-matchingbracket { color: #0f0; font-weight: bold; }
58
+ .cm-s-liquibyte .CodeMirror span.CodeMirror-nonmatchingbracket { color: #f00; font-weight: bold; }
59
+ .CodeMirror-matchingtag { background-color: rgba(150, 255, 0, .3); }
60
+ /* Scrollbars */
61
+ /* Simple */
62
+ .cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div:hover, div.CodeMirror-simplescroll-vertical div:hover {
63
+ background-color: rgba(80, 80, 80, .7);
64
+ }
65
+ .cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div, div.CodeMirror-simplescroll-vertical div {
66
+ background-color: rgba(80, 80, 80, .3);
67
+ border: 1px solid #404040;
68
+ border-radius: 5px;
69
+ }
70
+ .cm-s-liquibyte div.CodeMirror-simplescroll-vertical div {
71
+ border-top: 1px solid #404040;
72
+ border-bottom: 1px solid #404040;
73
+ }
74
+ .cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div {
75
+ border-left: 1px solid #404040;
76
+ border-right: 1px solid #404040;
77
+ }
78
+ .cm-s-liquibyte div.CodeMirror-simplescroll-vertical {
79
+ background-color: #262626;
80
+ }
81
+ .cm-s-liquibyte div.CodeMirror-simplescroll-horizontal {
82
+ background-color: #262626;
83
+ border-top: 1px solid #404040;
84
+ }
85
+ /* Overlay */
86
+ .cm-s-liquibyte div.CodeMirror-overlayscroll-horizontal div, div.CodeMirror-overlayscroll-vertical div {
87
+ background-color: #404040;
88
+ border-radius: 5px;
89
+ }
90
+ .cm-s-liquibyte div.CodeMirror-overlayscroll-vertical div {
91
+ border: 1px solid #404040;
92
+ }
93
+ .cm-s-liquibyte div.CodeMirror-overlayscroll-horizontal div {
94
+ border: 1px solid #404040;
95
+ }
js/codemirror/theme/material.css ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: material
4
+ Author: Michael Kaminsky (http://github.com/mkaminsky11)
5
+
6
+ Original material color scheme by Mattia Astorino (https://github.com/equinusocio/material-theme)
7
+
8
+ */
9
+
10
+ .cm-s-material.CodeMirror {
11
+ background-color: #263238;
12
+ color: rgba(233, 237, 237, 1);
13
+ }
14
+ .cm-s-material .CodeMirror-gutters {
15
+ background: #263238;
16
+ color: rgb(83,127,126);
17
+ border: none;
18
+ }
19
+ .cm-s-material .CodeMirror-guttermarker, .cm-s-material .CodeMirror-guttermarker-subtle, .cm-s-material .CodeMirror-linenumber { color: rgb(83,127,126); }
20
+ .cm-s-material .CodeMirror-cursor { border-left: 1px solid #f8f8f0; }
21
+ .cm-s-material div.CodeMirror-selected { background: rgba(255, 255, 255, 0.15); }
22
+ .cm-s-material.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
23
+ .cm-s-material .CodeMirror-line::selection, .cm-s-material .CodeMirror-line > span::selection, .cm-s-material .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
24
+ .cm-s-material .CodeMirror-line::-moz-selection, .cm-s-material .CodeMirror-line > span::-moz-selection, .cm-s-material .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
25
+
26
+ .cm-s-material .CodeMirror-activeline-background { background: rgba(0, 0, 0, 0); }
27
+ .cm-s-material .cm-keyword { color: rgba(199, 146, 234, 1); }
28
+ .cm-s-material .cm-operator { color: rgba(233, 237, 237, 1); }
29
+ .cm-s-material .cm-variable-2 { color: #80CBC4; }
30
+ .cm-s-material .cm-variable-3 { color: #82B1FF; }
31
+ .cm-s-material .cm-builtin { color: #DECB6B; }
32
+ .cm-s-material .cm-atom { color: #F77669; }
33
+ .cm-s-material .cm-number { color: #F77669; }
34
+ .cm-s-material .cm-def { color: rgba(233, 237, 237, 1); }
35
+ .cm-s-material .cm-string { color: #C3E88D; }
36
+ .cm-s-material .cm-string-2 { color: #80CBC4; }
37
+ .cm-s-material .cm-comment { color: #546E7A; }
38
+ .cm-s-material .cm-variable { color: #82B1FF; }
39
+ .cm-s-material .cm-tag { color: #80CBC4; }
40
+ .cm-s-material .cm-meta { color: #80CBC4; }
41
+ .cm-s-material .cm-attribute { color: #FFCB6B; }
42
+ .cm-s-material .cm-property { color: #80CBAE; }
43
+ .cm-s-material .cm-qualifier { color: #DECB6B; }
44
+ .cm-s-material .cm-variable-3 { color: #DECB6B; }
45
+ .cm-s-material .cm-tag { color: rgba(255, 83, 112, 1); }
46
+ .cm-s-material .cm-error {
47
+ color: rgba(255, 255, 255, 1.0);
48
+ background-color: #EC5F67;
49
+ }
50
+ .cm-s-material .CodeMirror-matchingbracket {
51
+ text-decoration: underline;
52
+ color: white !important;
53
+ }
js/codemirror/theme/mbo.css ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /****************************************************************/
2
+ /* Based on mbonaci's Brackets mbo theme */
3
+ /* https://github.com/mbonaci/global/blob/master/Mbo.tmTheme */
4
+ /* Create your own: http://tmtheme-editor.herokuapp.com */
5
+ /****************************************************************/
6
+
7
+ .cm-s-mbo.CodeMirror { background: #2c2c2c; color: #ffffec; }
8
+ .cm-s-mbo div.CodeMirror-selected { background: #716C62; }
9
+ .cm-s-mbo .CodeMirror-line::selection, .cm-s-mbo .CodeMirror-line > span::selection, .cm-s-mbo .CodeMirror-line > span > span::selection { background: rgba(113, 108, 98, .99); }
10
+ .cm-s-mbo .CodeMirror-line::-moz-selection, .cm-s-mbo .CodeMirror-line > span::-moz-selection, .cm-s-mbo .CodeMirror-line > span > span::-moz-selection { background: rgba(113, 108, 98, .99); }
11
+ .cm-s-mbo .CodeMirror-gutters { background: #4e4e4e; border-right: 0px; }
12
+ .cm-s-mbo .CodeMirror-guttermarker { color: white; }
13
+ .cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; }
14
+ .cm-s-mbo .CodeMirror-linenumber { color: #dadada; }
15
+ .cm-s-mbo .CodeMirror-cursor { border-left: 1px solid #ffffec; }
16
+
17
+ .cm-s-mbo span.cm-comment { color: #95958a; }
18
+ .cm-s-mbo span.cm-atom { color: #00a8c6; }
19
+ .cm-s-mbo span.cm-number { color: #00a8c6; }
20
+
21
+ .cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute { color: #9ddfe9; }
22
+ .cm-s-mbo span.cm-keyword { color: #ffb928; }
23
+ .cm-s-mbo span.cm-string { color: #ffcf6c; }
24
+ .cm-s-mbo span.cm-string.cm-property { color: #ffffec; }
25
+
26
+ .cm-s-mbo span.cm-variable { color: #ffffec; }
27
+ .cm-s-mbo span.cm-variable-2 { color: #00a8c6; }
28
+ .cm-s-mbo span.cm-def { color: #ffffec; }
29
+ .cm-s-mbo span.cm-bracket { color: #fffffc; font-weight: bold; }
30
+ .cm-s-mbo span.cm-tag { color: #9ddfe9; }
31
+ .cm-s-mbo span.cm-link { color: #f54b07; }
32
+ .cm-s-mbo span.cm-error { border-bottom: #636363; color: #ffffec; }
33
+ .cm-s-mbo span.cm-qualifier { color: #ffffec; }
34
+
35
+ .cm-s-mbo .CodeMirror-activeline-background { background: #494b41; }
36
+ .cm-s-mbo .CodeMirror-matchingbracket { color: #ffb928 !important; }
37
+ .cm-s-mbo .CodeMirror-matchingtag { background: rgba(255, 255, 255, .37); }
js/codemirror/theme/mdn-like.css ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ MDN-LIKE Theme - Mozilla
3
+ Ported to CodeMirror by Peter Kroon <plakroon@gmail.com>
4
+ Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues
5
+ GitHub: @peterkroon
6
+
7
+ The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation
8
+
9
+ */
10
+ .cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; }
11
+ .cm-s-mdn-like div.CodeMirror-selected { background: #cfc; }
12
+ .cm-s-mdn-like .CodeMirror-line::selection, .cm-s-mdn-like .CodeMirror-line > span::selection, .cm-s-mdn-like .CodeMirror-line > span > span::selection { background: #cfc; }
13
+ .cm-s-mdn-like .CodeMirror-line::-moz-selection, .cm-s-mdn-like .CodeMirror-line > span::-moz-selection, .cm-s-mdn-like .CodeMirror-line > span > span::-moz-selection { background: #cfc; }
14
+
15
+ .cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; }
16
+ .cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; padding-left: 8px; }
17
+ .cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; }
18
+
19
+ .cm-s-mdn-like .cm-keyword { color: #6262FF; }
20
+ .cm-s-mdn-like .cm-atom { color: #F90; }
21
+ .cm-s-mdn-like .cm-number { color: #ca7841; }
22
+ .cm-s-mdn-like .cm-def { color: #8DA6CE; }
23
+ .cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; }
24
+ .cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; }
25
+
26
+ .cm-s-mdn-like .cm-variable { color: #07a; }
27
+ .cm-s-mdn-like .cm-property { color: #905; }
28
+ .cm-s-mdn-like .cm-qualifier { color: #690; }
29
+
30
+ .cm-s-mdn-like .cm-operator { color: #cda869; }
31
+ .cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; }
32
+ .cm-s-mdn-like .cm-string { color:#07a; font-style:italic; }
33
+ .cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/
34
+ .cm-s-mdn-like .cm-meta { color: #000; } /*?*/
35
+ .cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/
36
+ .cm-s-mdn-like .cm-tag { color: #997643; }
37
+ .cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/
38
+ .cm-s-mdn-like .cm-header { color: #FF6400; }
39
+ .cm-s-mdn-like .cm-hr { color: #AEAEAE; }
40
+ .cm-s-mdn-like .cm-link { color:#ad9361; font-style:italic; text-decoration:none; }
41
+ .cm-s-mdn-like .cm-error { border-bottom: 1px solid red; }
42
+
43
+ div.cm-s-mdn-like .CodeMirror-activeline-background { background: #efefff; }
44
+ div.cm-s-mdn-like span.CodeMirror-matchingbracket { outline:1px solid grey; color: inherit; }
45
+
46
+ .cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFcAAAAyCAYAAAAp8UeFAAAHvklEQVR42s2b63bcNgyEQZCSHCdt2vd/0tWF7I+Q6XgMXiTtuvU5Pl57ZQKkKHzEAOtF5KeIJBGJ8uvL599FRFREZhFx8DeXv8trn68RuGaC8TRfo3SNp9dlDDHedyLyTUTeRWStXKPZrjtpZxaRw5hPqozRs1N8/enzIiQRWcCgy4MUA0f+XWliDhyL8Lfyvx7ei/Ae3iQFHyw7U/59pQVIMEEPEz0G7XiwdRjzSfC3UTtz9vchIntxvry5iMgfIhJoEflOz2CQr3F5h/HfeFe+GTdLaKcu9L8LTeQb/R/7GgbsfKedyNdoHsN31uRPWrfZ5wsj/NzzRQHuToIdU3ahwnsKPxXCjJITuOsi7XLc7SG/v5GdALs7wf8JjTFiB5+QvTEfRyGOfX3Lrx8wxyQi3sNq46O7QahQiCsRFgqddjBouVEHOKDgXAQHD9gJCr5sMKkEdjwsarG/ww3BMHBU7OBjXnzdyY7SfCxf5/z6ATccrwlKuwC/jhznnPF4CgVzhhVf4xp2EixcBActO75iZ8/fM9zAs2OMzKdslgXWJ9XG8PQoOAMA5fGcsvORgv0doBXyHrCwfLJAOwo71QLNkb8n2Pl6EWiR7OCibtkPaz4Kc/0NNAze2gju3zOwekALDaCFPI5vjPFmgGY5AZqyGEvH1x7QfIb8YtxMnA/b+QQ0aQDAwc6JMFg8CbQZ4qoYEEHbRwNojuK3EHwd7VALSgq+MNDKzfT58T8qdpADrgW0GmgcAS1lhzztJmkAzcPNOQbsWEALBDSlMKUG0Eq4CLAQWvEVQ9WU57gZJwZtgPO3r9oBTQ9WO8TjqXINx8R0EYpiZEUWOF3FxkbJkgU9B2f41YBrIj5ZfsQa0M5kTgiAAqM3ShXLgu8XMqcrQBvJ0CL5pnTsfMB13oB8athpAq2XOQmcGmoACCLydx7nToa23ATaSIY2ichfOdPTGxlasXMLaL0MLZAOwAKIM+y8CmicobGdCcbbK9DzN+yYGVoNNI5iUKTMyYOjPse4A8SM1MmcXgU0toOq1yO/v8FOxlASyc7TgeYaAMBJHcY1CcCwGI/TK4AmDbDyKYBBtFUkRwto8gygiQEaByFgJ00BH2M8JWwQS1nafDXQCidWyOI8AcjDCSjCLk8ngObuAm3JAHAdubAmOaK06V8MNEsKPJOhobSprwQa6gD7DclRQdqcwL4zxqgBrQcabUiBLclRDKAlWp+etPkBaNMA0AKlrHwTdEByZAA4GM+SNluSY6wAzcMNewxmgig5Ks0nkrSpBvSaQHMdKTBAnLojOdYyGpQ254602ZILPdTD1hdlggdIm74jbTp8vDwF5ZYUeLWGJpWsh6XNyXgcYwVoJQTEhhTYkxzZjiU5npU2TaB979TQehlaAVq4kaGpiPwwwLkYUuBbQwocyQTv1tA0+1UFWoJF3iv1oq+qoSk8EQdJmwHkziIF7oOZk14EGitibAdjLYYK78H5vZOhtWpoI0ATGHs0Q8OMb4Ey+2bU2UYztCtA0wFAs7TplGLRVQCcqaFdGSPCeTI1QNIC52iWNzof6Uib7xjEp07mNNoUYmVosVItHrHzRlLgBn9LFyRHaQCtVUMbtTNhoXWiTOO9k/V8BdAc1Oq0ArSQs6/5SU0hckNy9NnXqQY0PGYo5dWJ7nINaN6o958FWin27aBaWRka1r5myvLOAm0j30eBJqCxHLReVclxhxOEN2JfDWjxBtAC7MIH1fVaGdoOp4qJYDgKtKPSFNID2gSnGldrCqkFZ+5UeQXQBIRrSwocbdZYQT/2LwRahBPBXoHrB8nxaGROST62DKUbQOMMzZIC9abkuELfQzQALWTnDNAm8KHWFOJgJ5+SHIvTPcmx1xQyZRhNL5Qci689aXMEaN/uNIWkEwDAvFpOZmgsBaaGnbs1NPa1Jm32gBZAIh1pCtG7TSH4aE0y1uVY4uqoFPisGlpP2rSA5qTecWn5agK6BzSpgAyD+wFaqhnYoSZ1Vwr8CmlTQbrcO3ZaX0NAEyMbYaAlyquFoLKK3SPby9CeVUPThrSJmkCAE0CrKUQadi4DrdSlWhmah0YL9z9vClH59YGbHx1J8VZTyAjQepJjmXwAKTDQI3omc3p1U4gDUf6RfcdYfrUp5ClAi2J3Ba6UOXGo+K+bQrjjssitG2SJzshaLwMtXgRagUNpYYoVkMSBLM+9GGiJZMvduG6DRZ4qc04DMPtQQxOjEtACmhO7K1AbNbQDEggZyJwscFpAGwENhoBeUwh3bWolhe8BTYVKxQEWrSUn/uhcM5KhvUu/+eQu0Lzhi+VrK0PrZZNDQKs9cpYUuFYgMVpD4/NxenJTiMCNqdUEUf1qZWjppLT5qSkkUZbCwkbZMSuVnu80hfSkzRbQeqCZSAh6huR4VtoM2gHAlLf72smuWgE+VV7XpE25Ab2WFDgyhnSuKbs4GuGzCjR+tIoUuMFg3kgcWKLTwRqanJQ2W00hAsenfaApRC42hbCvK1SlE0HtE9BGgneJO+ELamitD1YjjOYnNYVcraGhtKkW0EqVVeDx733I2NH581k1NNxNLG0i0IJ8/NjVaOZ0tYZ2Vtr0Xv7tPV3hkWp9EFkgS/J0vosngTaSoaG06WHi+xObQkaAdlbanP8B2+2l0f90LmUAAAAASUVORK5CYII=); }
js/codemirror/theme/midnight.css ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */
2
+
3
+ /*<!--match-->*/
4
+ .cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; }
5
+ .cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; }
6
+
7
+ /*<!--activeline-->*/
8
+ .cm-s-midnight .CodeMirror-activeline-background { background: #253540; }
9
+
10
+ .cm-s-midnight.CodeMirror {
11
+ background: #0F192A;
12
+ color: #D1EDFF;
13
+ }
14
+
15
+ .cm-s-midnight.CodeMirror { border-top: 1px solid black; border-bottom: 1px solid black; }
16
+
17
+ .cm-s-midnight div.CodeMirror-selected { background: #314D67; }
18
+ .cm-s-midnight .CodeMirror-line::selection, .cm-s-midnight .CodeMirror-line > span::selection, .cm-s-midnight .CodeMirror-line > span > span::selection { background: rgba(49, 77, 103, .99); }
19
+ .cm-s-midnight .CodeMirror-line::-moz-selection, .cm-s-midnight .CodeMirror-line > span::-moz-selection, .cm-s-midnight .CodeMirror-line > span > span::-moz-selection { background: rgba(49, 77, 103, .99); }
20
+ .cm-s-midnight .CodeMirror-gutters { background: #0F192A; border-right: 1px solid; }
21
+ .cm-s-midnight .CodeMirror-guttermarker { color: white; }
22
+ .cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
23
+ .cm-s-midnight .CodeMirror-linenumber { color: #D0D0D0; }
24
+ .cm-s-midnight .CodeMirror-cursor { border-left: 1px solid #F8F8F0; }
25
+
26
+ .cm-s-midnight span.cm-comment { color: #428BDD; }
27
+ .cm-s-midnight span.cm-atom { color: #AE81FF; }
28
+ .cm-s-midnight span.cm-number { color: #D1EDFF; }
29
+
30
+ .cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute { color: #A6E22E; }
31
+ .cm-s-midnight span.cm-keyword { color: #E83737; }
32
+ .cm-s-midnight span.cm-string { color: #1DC116; }
33
+
34
+ .cm-s-midnight span.cm-variable { color: #FFAA3E; }
35
+ .cm-s-midnight span.cm-variable-2 { color: #FFAA3E; }
36
+ .cm-s-midnight span.cm-def { color: #4DD; }
37
+ .cm-s-midnight span.cm-bracket { color: #D1EDFF; }
38
+ .cm-s-midnight span.cm-tag { color: #449; }
39
+ .cm-s-midnight span.cm-link { color: #AE81FF; }
40
+ .cm-s-midnight span.cm-error { background: #F92672; color: #F8F8F0; }
41
+
42
+ .cm-s-midnight .CodeMirror-matchingbracket {
43
+ text-decoration: underline;
44
+ color: white !important;
45
+ }
js/codemirror/theme/monokai.css ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Based on Sublime Text's Monokai theme */
2
+
3
+ .cm-s-monokai.CodeMirror { background: #272822; color: #f8f8f2; }
4
+ .cm-s-monokai div.CodeMirror-selected { background: #49483E; }
5
+ .cm-s-monokai .CodeMirror-line::selection, .cm-s-monokai .CodeMirror-line > span::selection, .cm-s-monokai .CodeMirror-line > span > span::selection { background: rgba(73, 72, 62, .99); }
6
+ .cm-s-monokai .CodeMirror-line::-moz-selection, .cm-s-monokai .CodeMirror-line > span::-moz-selection, .cm-s-monokai .CodeMirror-line > span > span::-moz-selection { background: rgba(73, 72, 62, .99); }
7
+ .cm-s-monokai .CodeMirror-gutters { background: #272822; border-right: 0px; }
8
+ .cm-s-monokai .CodeMirror-guttermarker { color: white; }
9
+ .cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
10
+ .cm-s-monokai .CodeMirror-linenumber { color: #d0d0d0; }
11
+ .cm-s-monokai .CodeMirror-cursor { border-left: 1px solid #f8f8f0; }
12
+
13
+ .cm-s-monokai span.cm-comment { color: #75715e; }
14
+ .cm-s-monokai span.cm-atom { color: #ae81ff; }
15
+ .cm-s-monokai span.cm-number { color: #ae81ff; }
16
+
17
+ .cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute { color: #a6e22e; }
18
+ .cm-s-monokai span.cm-keyword { color: #f92672; }
19
+ .cm-s-monokai span.cm-builtin { color: #66d9ef; }
20
+ .cm-s-monokai span.cm-string { color: #e6db74; }
21
+
22
+ .cm-s-monokai span.cm-variable { color: #f8f8f2; }
23
+ .cm-s-monokai span.cm-variable-2 { color: #9effff; }
24
+ .cm-s-monokai span.cm-variable-3 { color: #66d9ef; }
25
+ .cm-s-monokai span.cm-def { color: #fd971f; }
26
+ .cm-s-monokai span.cm-bracket { color: #f8f8f2; }
27
+ .cm-s-monokai span.cm-tag { color: #f92672; }
28
+ .cm-s-monokai span.cm-header { color: #ae81ff; }
29
+ .cm-s-monokai span.cm-link { color: #ae81ff; }
30
+ .cm-s-monokai span.cm-error { background: #f92672; color: #f8f8f0; }
31
+
32
+ .cm-s-monokai .CodeMirror-activeline-background { background: #373831; }
33
+ .cm-s-monokai .CodeMirror-matchingbracket {
34
+ text-decoration: underline;
35
+ color: white !important;
36
+ }
js/codemirror/theme/neat.css ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-neat span.cm-comment { color: #a86; }
2
+ .cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; }
3
+ .cm-s-neat span.cm-string { color: #a22; }
4
+ .cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; }
5
+ .cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; }
6
+ .cm-s-neat span.cm-variable { color: black; }
7
+ .cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; }
8
+ .cm-s-neat span.cm-meta { color: #555; }
9
+ .cm-s-neat span.cm-link { color: #3a3; }
10
+
11
+ .cm-s-neat .CodeMirror-activeline-background { background: #e8f2ff; }
12
+ .cm-s-neat .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; }
js/codemirror/theme/neo.css ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* neo theme for codemirror */
2
+
3
+ /* Color scheme */
4
+
5
+ .cm-s-neo.CodeMirror {
6
+ background-color:#ffffff;
7
+ color:#2e383c;
8
+ line-height:1.4375;
9
+ }
10
+ .cm-s-neo .cm-comment { color:#75787b; }
11
+ .cm-s-neo .cm-keyword, .cm-s-neo .cm-property { color:#1d75b3; }
12
+ .cm-s-neo .cm-atom,.cm-s-neo .cm-number { color:#75438a; }
13
+ .cm-s-neo .cm-node,.cm-s-neo .cm-tag { color:#9c3328; }
14
+ .cm-s-neo .cm-string { color:#b35e14; }
15
+ .cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier { color:#047d65; }
16
+
17
+
18
+ /* Editor styling */
19
+
20
+ .cm-s-neo pre {
21
+ padding:0;
22
+ }
23
+
24
+ .cm-s-neo .CodeMirror-gutters {
25
+ border:none;
26
+ border-right:10px solid transparent;
27
+ background-color:transparent;
28
+ }
29
+
30
+ .cm-s-neo .CodeMirror-linenumber {
31
+ padding:0;
32
+ color:#e0e2e5;
33
+ }
34
+
35
+ .cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; }
36
+ .cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; }
37
+
38
+ .cm-s-neo .CodeMirror-cursor {
39
+ width: auto;
40
+ border: 0;
41
+ background: rgba(155,157,162,0.37);
42
+ z-index: 1;
43
+ }
js/codemirror/theme/night.css ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Loosely based on the Midnight Textmate theme */
2
+
3
+ .cm-s-night.CodeMirror { background: #0a001f; color: #f8f8f8; }
4
+ .cm-s-night div.CodeMirror-selected { background: #447; }
5
+ .cm-s-night .CodeMirror-line::selection, .cm-s-night .CodeMirror-line > span::selection, .cm-s-night .CodeMirror-line > span > span::selection { background: rgba(68, 68, 119, .99); }
6
+ .cm-s-night .CodeMirror-line::-moz-selection, .cm-s-night .CodeMirror-line > span::-moz-selection, .cm-s-night .CodeMirror-line > span > span::-moz-selection { background: rgba(68, 68, 119, .99); }
7
+ .cm-s-night .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
8
+ .cm-s-night .CodeMirror-guttermarker { color: white; }
9
+ .cm-s-night .CodeMirror-guttermarker-subtle { color: #bbb; }
10
+ .cm-s-night .CodeMirror-linenumber { color: #f8f8f8; }
11
+ .cm-s-night .CodeMirror-cursor { border-left: 1px solid white; }
12
+
13
+ .cm-s-night span.cm-comment { color: #8900d1; }
14
+ .cm-s-night span.cm-atom { color: #845dc4; }
15
+ .cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; }
16
+ .cm-s-night span.cm-keyword { color: #599eff; }
17
+ .cm-s-night span.cm-string { color: #37f14a; }
18
+ .cm-s-night span.cm-meta { color: #7678e2; }
19
+ .cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; }
20
+ .cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; }
21
+ .cm-s-night span.cm-bracket { color: #8da6ce; }
22
+ .cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; }
23
+ .cm-s-night span.cm-link { color: #845dc4; }
24
+ .cm-s-night span.cm-error { color: #9d1e15; }
25
+
26
+ .cm-s-night .CodeMirror-activeline-background { background: #1C005A; }
27
+ .cm-s-night .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }
js/codemirror/theme/panda-syntax.css ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Name: Panda Syntax
3
+ Author: Siamak Mokhtari (http://github.com/siamak/)
4
+ CodeMirror template by Siamak Mokhtari (https://github.com/siamak/atom-panda-syntax)
5
+ */
6
+ .cm-s-panda-syntax {
7
+ background: #292A2B;
8
+ color: #E6E6E6;
9
+ line-height: 1.5;
10
+ font-family: 'Operator Mono', 'Source Sans Pro', Menlo, Monaco, Consolas, Courier New, monospace;
11
+ }
12
+ .cm-s-panda-syntax .CodeMirror-cursor { border-color: #ff2c6d; }
13
+ .cm-s-panda-syntax .CodeMirror-activeline-background {
14
+ background: rgba(99, 123, 156, 0.1);
15
+ }
16
+ .cm-s-panda-syntax .CodeMirror-selected {
17
+ background: #FFF;
18
+ }
19
+ .cm-s-panda-syntax .cm-comment {
20
+ font-style: italic;
21
+ color: #676B79;
22
+ }
23
+ .cm-s-panda-syntax .cm-operator {
24
+ color: #f3f3f3;
25
+ }
26
+ .cm-s-panda-syntax .cm-string {
27
+ color: #19F9D8;
28
+ }
29
+ .cm-s-panda-syntax .cm-string-2 {
30
+ color: #FFB86C;
31
+ }
32
+
33
+ .cm-s-panda-syntax .cm-tag {
34
+ color: #ff2c6d;
35
+ }
36
+ .cm-s-panda-syntax .cm-meta {
37
+ color: #b084eb;
38
+ }
39
+
40
+ .cm-s-panda-syntax .cm-number {
41
+ color: #FFB86C;
42
+ }
43
+ .cm-s-panda-syntax .cm-atom {
44
+ color: #ff2c6d;
45
+ }
46
+ .cm-s-panda-syntax .cm-keyword {
47
+ color: #FF75B5;
48
+ }
49
+ .cm-s-panda-syntax .cm-variable {
50
+ color: #ffb86c;
51
+ }
52
+ .cm-s-panda-syntax .cm-variable-2 {
53
+ color: #ff9ac1;
54
+ }
55
+ .cm-s-panda-syntax .cm-variable-3 {
56
+ color: #ff9ac1;
57
+ }
58
+
59
+ .cm-s-panda-syntax .cm-def {
60
+ color: #e6e6e6;
61
+ }
62
+ .cm-s-panda-syntax .cm-property {
63
+ color: #f3f3f3;
64
+ }
65
+ .cm-s-panda-syntax .cm-unit {
66
+ color: #ffb86c;
67
+ }
68
+
69
+ .cm-s-panda-syntax .cm-attribute {
70
+ color: #ffb86c;
71
+ }
72
+
73
+ .cm-s-panda-syntax .CodeMirror-matchingbracket {
74
+ border-bottom: 1px dotted #19F9D8;
75
+ padding-bottom: 2px;
76
+ color: #e6e6e6;
77
+ }
78
+ .cm-s-panda-syntax .CodeMirror-gutters {
79
+ background: #292a2b;
80
+ border-right-color: rgba(255, 255, 255, 0.1);
81
+ }
82
+ .cm-s-panda-syntax .CodeMirror-linenumber {
83
+ color: #e6e6e6;
84
+ opacity: 0.6;
85
+ }
js/codemirror/theme/paraiso-dark.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Paraíso (Dark)
4
+ Author: Jan T. Sott
5
+
6
+ Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
7
+ Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
8
+
9
+ */
10
+
11
+ .cm-s-paraiso-dark.CodeMirror { background: #2f1e2e; color: #b9b6b0; }
12
+ .cm-s-paraiso-dark div.CodeMirror-selected { background: #41323f; }
13
+ .cm-s-paraiso-dark .CodeMirror-line::selection, .cm-s-paraiso-dark .CodeMirror-line > span::selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::selection { background: rgba(65, 50, 63, .99); }
14
+ .cm-s-paraiso-dark .CodeMirror-line::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(65, 50, 63, .99); }
15
+ .cm-s-paraiso-dark .CodeMirror-gutters { background: #2f1e2e; border-right: 0px; }
16
+ .cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; }
17
+ .cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; }
18
+ .cm-s-paraiso-dark .CodeMirror-linenumber { color: #776e71; }
19
+ .cm-s-paraiso-dark .CodeMirror-cursor { border-left: 1px solid #8d8687; }
20
+
21
+ .cm-s-paraiso-dark span.cm-comment { color: #e96ba8; }
22
+ .cm-s-paraiso-dark span.cm-atom { color: #815ba4; }
23
+ .cm-s-paraiso-dark span.cm-number { color: #815ba4; }
24
+
25
+ .cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute { color: #48b685; }
26
+ .cm-s-paraiso-dark span.cm-keyword { color: #ef6155; }
27
+ .cm-s-paraiso-dark span.cm-string { color: #fec418; }
28
+
29
+ .cm-s-paraiso-dark span.cm-variable { color: #48b685; }
30
+ .cm-s-paraiso-dark span.cm-variable-2 { color: #06b6ef; }
31
+ .cm-s-paraiso-dark span.cm-def { color: #f99b15; }
32
+ .cm-s-paraiso-dark span.cm-bracket { color: #b9b6b0; }
33
+ .cm-s-paraiso-dark span.cm-tag { color: #ef6155; }
34
+ .cm-s-paraiso-dark span.cm-link { color: #815ba4; }
35
+ .cm-s-paraiso-dark span.cm-error { background: #ef6155; color: #8d8687; }
36
+
37
+ .cm-s-paraiso-dark .CodeMirror-activeline-background { background: #4D344A; }
38
+ .cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/paraiso-light.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Paraíso (Light)
4
+ Author: Jan T. Sott
5
+
6
+ Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror)
7
+ Inspired by the art of Rubens LP (http://www.rubenslp.com.br)
8
+
9
+ */
10
+
11
+ .cm-s-paraiso-light.CodeMirror { background: #e7e9db; color: #41323f; }
12
+ .cm-s-paraiso-light div.CodeMirror-selected { background: #b9b6b0; }
13
+ .cm-s-paraiso-light .CodeMirror-line::selection, .cm-s-paraiso-light .CodeMirror-line > span::selection, .cm-s-paraiso-light .CodeMirror-line > span > span::selection { background: #b9b6b0; }
14
+ .cm-s-paraiso-light .CodeMirror-line::-moz-selection, .cm-s-paraiso-light .CodeMirror-line > span::-moz-selection, .cm-s-paraiso-light .CodeMirror-line > span > span::-moz-selection { background: #b9b6b0; }
15
+ .cm-s-paraiso-light .CodeMirror-gutters { background: #e7e9db; border-right: 0px; }
16
+ .cm-s-paraiso-light .CodeMirror-guttermarker { color: black; }
17
+ .cm-s-paraiso-light .CodeMirror-guttermarker-subtle { color: #8d8687; }
18
+ .cm-s-paraiso-light .CodeMirror-linenumber { color: #8d8687; }
19
+ .cm-s-paraiso-light .CodeMirror-cursor { border-left: 1px solid #776e71; }
20
+
21
+ .cm-s-paraiso-light span.cm-comment { color: #e96ba8; }
22
+ .cm-s-paraiso-light span.cm-atom { color: #815ba4; }
23
+ .cm-s-paraiso-light span.cm-number { color: #815ba4; }
24
+
25
+ .cm-s-paraiso-light span.cm-property, .cm-s-paraiso-light span.cm-attribute { color: #48b685; }
26
+ .cm-s-paraiso-light span.cm-keyword { color: #ef6155; }
27
+ .cm-s-paraiso-light span.cm-string { color: #fec418; }
28
+
29
+ .cm-s-paraiso-light span.cm-variable { color: #48b685; }
30
+ .cm-s-paraiso-light span.cm-variable-2 { color: #06b6ef; }
31
+ .cm-s-paraiso-light span.cm-def { color: #f99b15; }
32
+ .cm-s-paraiso-light span.cm-bracket { color: #41323f; }
33
+ .cm-s-paraiso-light span.cm-tag { color: #ef6155; }
34
+ .cm-s-paraiso-light span.cm-link { color: #815ba4; }
35
+ .cm-s-paraiso-light span.cm-error { background: #ef6155; color: #776e71; }
36
+
37
+ .cm-s-paraiso-light .CodeMirror-activeline-background { background: #CFD1C4; }
38
+ .cm-s-paraiso-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/pastel-on-dark.css ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Pastel On Dark theme ported from ACE editor
3
+ * @license MIT
4
+ * @copyright AtomicPages LLC 2014
5
+ * @author Dennis Thompson, AtomicPages LLC
6
+ * @version 1.1
7
+ * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme
8
+ */
9
+
10
+ .cm-s-pastel-on-dark.CodeMirror {
11
+ background: #2c2827;
12
+ color: #8F938F;
13
+ line-height: 1.5;
14
+ }
15
+ .cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2); }
16
+ .cm-s-pastel-on-dark .CodeMirror-line::selection, .cm-s-pastel-on-dark .CodeMirror-line > span::selection, .cm-s-pastel-on-dark .CodeMirror-line > span > span::selection { background: rgba(221,240,255,0.2); }
17
+ .cm-s-pastel-on-dark .CodeMirror-line::-moz-selection, .cm-s-pastel-on-dark .CodeMirror-line > span::-moz-selection, .cm-s-pastel-on-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(221,240,255,0.2); }
18
+
19
+ .cm-s-pastel-on-dark .CodeMirror-gutters {
20
+ background: #34302f;
21
+ border-right: 0px;
22
+ padding: 0 3px;
23
+ }
24
+ .cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; }
25
+ .cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; }
26
+ .cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; }
27
+ .cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7; }
28
+ .cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; }
29
+ .cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; }
30
+ .cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; }
31
+ .cm-s-pastel-on-dark span.cm-property { color: #8F938F; }
32
+ .cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; }
33
+ .cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; }
34
+ .cm-s-pastel-on-dark span.cm-string { color: #66A968; }
35
+ .cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; }
36
+ .cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; }
37
+ .cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; }
38
+ .cm-s-pastel-on-dark span.cm-def { color: #757aD8; }
39
+ .cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; }
40
+ .cm-s-pastel-on-dark span.cm-tag { color: #C1C144; }
41
+ .cm-s-pastel-on-dark span.cm-link { color: #ae81ff; }
42
+ .cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; }
43
+ .cm-s-pastel-on-dark span.cm-error {
44
+ background: #757aD8;
45
+ color: #f8f8f0;
46
+ }
47
+ .cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031); }
48
+ .cm-s-pastel-on-dark .CodeMirror-matchingbracket {
49
+ border: 1px solid rgba(255,255,255,0.25);
50
+ color: #8F938F !important;
51
+ margin: -1px -1px 0 -1px;
52
+ }
js/codemirror/theme/railscasts.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Railscasts
4
+ Author: Ryan Bates (http://railscasts.com)
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-railscasts.CodeMirror {background: #2b2b2b; color: #f4f1ed;}
12
+ .cm-s-railscasts div.CodeMirror-selected {background: #272935 !important;}
13
+ .cm-s-railscasts .CodeMirror-gutters {background: #2b2b2b; border-right: 0px;}
14
+ .cm-s-railscasts .CodeMirror-linenumber {color: #5a647e;}
15
+ .cm-s-railscasts .CodeMirror-cursor {border-left: 1px solid #d4cfc9 !important;}
16
+
17
+ .cm-s-railscasts span.cm-comment {color: #bc9458;}
18
+ .cm-s-railscasts span.cm-atom {color: #b6b3eb;}
19
+ .cm-s-railscasts span.cm-number {color: #b6b3eb;}
20
+
21
+ .cm-s-railscasts span.cm-property, .cm-s-railscasts span.cm-attribute {color: #a5c261;}
22
+ .cm-s-railscasts span.cm-keyword {color: #da4939;}
23
+ .cm-s-railscasts span.cm-string {color: #ffc66d;}
24
+
25
+ .cm-s-railscasts span.cm-variable {color: #a5c261;}
26
+ .cm-s-railscasts span.cm-variable-2 {color: #6d9cbe;}
27
+ .cm-s-railscasts span.cm-def {color: #cc7833;}
28
+ .cm-s-railscasts span.cm-error {background: #da4939; color: #d4cfc9;}
29
+ .cm-s-railscasts span.cm-bracket {color: #f4f1ed;}
30
+ .cm-s-railscasts span.cm-tag {color: #da4939;}
31
+ .cm-s-railscasts span.cm-link {color: #b6b3eb;}
32
+
33
+ .cm-s-railscasts .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
34
+ .cm-s-railscasts .CodeMirror-activeline-background { background: #303040; }
js/codemirror/theme/rubyblue.css ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-rubyblue.CodeMirror { background: #112435; color: white; }
2
+ .cm-s-rubyblue div.CodeMirror-selected { background: #38566F; }
3
+ .cm-s-rubyblue .CodeMirror-line::selection, .cm-s-rubyblue .CodeMirror-line > span::selection, .cm-s-rubyblue .CodeMirror-line > span > span::selection { background: rgba(56, 86, 111, 0.99); }
4
+ .cm-s-rubyblue .CodeMirror-line::-moz-selection, .cm-s-rubyblue .CodeMirror-line > span::-moz-selection, .cm-s-rubyblue .CodeMirror-line > span > span::-moz-selection { background: rgba(56, 86, 111, 0.99); }
5
+ .cm-s-rubyblue .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; }
6
+ .cm-s-rubyblue .CodeMirror-guttermarker { color: white; }
7
+ .cm-s-rubyblue .CodeMirror-guttermarker-subtle { color: #3E7087; }
8
+ .cm-s-rubyblue .CodeMirror-linenumber { color: white; }
9
+ .cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white; }
10
+
11
+ .cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; }
12
+ .cm-s-rubyblue span.cm-atom { color: #F4C20B; }
13
+ .cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; }
14
+ .cm-s-rubyblue span.cm-keyword { color: #F0F; }
15
+ .cm-s-rubyblue span.cm-string { color: #F08047; }
16
+ .cm-s-rubyblue span.cm-meta { color: #F0F; }
17
+ .cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; }
18
+ .cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; }
19
+ .cm-s-rubyblue span.cm-bracket { color: #F0F; }
20
+ .cm-s-rubyblue span.cm-link { color: #F4C20B; }
21
+ .cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; }
22
+ .cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; }
23
+ .cm-s-rubyblue span.cm-error { color: #AF2018; }
24
+
25
+ .cm-s-rubyblue .CodeMirror-activeline-background { background: #173047; }
js/codemirror/theme/seti.css ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: seti
4
+ Author: Michael Kaminsky (http://github.com/mkaminsky11)
5
+
6
+ Original seti color scheme by Jesse Weed (https://github.com/jesseweed/seti-syntax)
7
+
8
+ */
9
+
10
+
11
+ .cm-s-seti.CodeMirror {
12
+ background-color: #151718 !important;
13
+ color: #CFD2D1 !important;
14
+ border: none;
15
+ }
16
+ .cm-s-seti .CodeMirror-gutters {
17
+ color: #404b53;
18
+ background-color: #0E1112;
19
+ border: none;
20
+ }
21
+ .cm-s-seti .CodeMirror-cursor { border-left: solid thin #f8f8f0; }
22
+ .cm-s-seti .CodeMirror-linenumber { color: #6D8A88; }
23
+ .cm-s-seti.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); }
24
+ .cm-s-seti .CodeMirror-line::selection, .cm-s-seti .CodeMirror-line > span::selection, .cm-s-seti .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); }
25
+ .cm-s-seti .CodeMirror-line::-moz-selection, .cm-s-seti .CodeMirror-line > span::-moz-selection, .cm-s-seti .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); }
26
+ .cm-s-seti span.cm-comment { color: #41535b; }
27
+ .cm-s-seti span.cm-string, .cm-s-seti span.cm-string-2 { color: #55b5db; }
28
+ .cm-s-seti span.cm-number { color: #cd3f45; }
29
+ .cm-s-seti span.cm-variable { color: #55b5db; }
30
+ .cm-s-seti span.cm-variable-2 { color: #a074c4; }
31
+ .cm-s-seti span.cm-def { color: #55b5db; }
32
+ .cm-s-seti span.cm-keyword { color: #ff79c6; }
33
+ .cm-s-seti span.cm-operator { color: #9fca56; }
34
+ .cm-s-seti span.cm-keyword { color: #e6cd69; }
35
+ .cm-s-seti span.cm-atom { color: #cd3f45; }
36
+ .cm-s-seti span.cm-meta { color: #55b5db; }
37
+ .cm-s-seti span.cm-tag { color: #55b5db; }
38
+ .cm-s-seti span.cm-attribute { color: #9fca56; }
39
+ .cm-s-seti span.cm-qualifier { color: #9fca56; }
40
+ .cm-s-seti span.cm-property { color: #a074c4; }
41
+ .cm-s-seti span.cm-variable-3 { color: #9fca56; }
42
+ .cm-s-seti span.cm-builtin { color: #9fca56; }
43
+ .cm-s-seti .CodeMirror-activeline-background { background: #101213; }
44
+ .cm-s-seti .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/solarized.css ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Solarized theme for code-mirror
3
+ http://ethanschoonover.com/solarized
4
+ */
5
+
6
+ /*
7
+ Solarized color palette
8
+ http://ethanschoonover.com/solarized/img/solarized-palette.png
9
+ */
10
+
11
+ .solarized.base03 { color: #002b36; }
12
+ .solarized.base02 { color: #073642; }
13
+ .solarized.base01 { color: #586e75; }
14
+ .solarized.base00 { color: #657b83; }
15
+ .solarized.base0 { color: #839496; }
16
+ .solarized.base1 { color: #93a1a1; }
17
+ .solarized.base2 { color: #eee8d5; }
18
+ .solarized.base3 { color: #fdf6e3; }
19
+ .solarized.solar-yellow { color: #b58900; }
20
+ .solarized.solar-orange { color: #cb4b16; }
21
+ .solarized.solar-red { color: #dc322f; }
22
+ .solarized.solar-magenta { color: #d33682; }
23
+ .solarized.solar-violet { color: #6c71c4; }
24
+ .solarized.solar-blue { color: #268bd2; }
25
+ .solarized.solar-cyan { color: #2aa198; }
26
+ .solarized.solar-green { color: #859900; }
27
+
28
+ /* Color scheme for code-mirror */
29
+
30
+ .cm-s-solarized {
31
+ line-height: 1.45em;
32
+ color-profile: sRGB;
33
+ rendering-intent: auto;
34
+ }
35
+ .cm-s-solarized.cm-s-dark {
36
+ color: #839496;
37
+ background-color: #002b36;
38
+ text-shadow: #002b36 0 1px;
39
+ }
40
+ .cm-s-solarized.cm-s-light {
41
+ background-color: #fdf6e3;
42
+ color: #657b83;
43
+ text-shadow: #eee8d5 0 1px;
44
+ }
45
+
46
+ .cm-s-solarized .CodeMirror-widget {
47
+ text-shadow: none;
48
+ }
49
+
50
+ .cm-s-solarized .cm-header { color: #586e75; }
51
+ .cm-s-solarized .cm-quote { color: #93a1a1; }
52
+
53
+ .cm-s-solarized .cm-keyword { color: #cb4b16; }
54
+ .cm-s-solarized .cm-atom { color: #d33682; }
55
+ .cm-s-solarized .cm-number { color: #d33682; }
56
+ .cm-s-solarized .cm-def { color: #2aa198; }
57
+
58
+ .cm-s-solarized .cm-variable { color: #839496; }
59
+ .cm-s-solarized .cm-variable-2 { color: #b58900; }
60
+ .cm-s-solarized .cm-variable-3 { color: #6c71c4; }
61
+
62
+ .cm-s-solarized .cm-property { color: #2aa198; }
63
+ .cm-s-solarized .cm-operator { color: #6c71c4; }
64
+
65
+ .cm-s-solarized .cm-comment { color: #586e75; font-style:italic; }
66
+
67
+ .cm-s-solarized .cm-string { color: #859900; }
68
+ .cm-s-solarized .cm-string-2 { color: #b58900; }
69
+
70
+ .cm-s-solarized .cm-meta { color: #859900; }
71
+ .cm-s-solarized .cm-qualifier { color: #b58900; }
72
+ .cm-s-solarized .cm-builtin { color: #d33682; }
73
+ .cm-s-solarized .cm-bracket { color: #cb4b16; }
74
+ .cm-s-solarized .CodeMirror-matchingbracket { color: #859900; }
75
+ .cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; }
76
+ .cm-s-solarized .cm-tag { color: #93a1a1; }
77
+ .cm-s-solarized .cm-attribute { color: #2aa198; }
78
+ .cm-s-solarized .cm-hr {
79
+ color: transparent;
80
+ border-top: 1px solid #586e75;
81
+ display: block;
82
+ }
83
+ .cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; }
84
+ .cm-s-solarized .cm-special { color: #6c71c4; }
85
+ .cm-s-solarized .cm-em {
86
+ color: #999;
87
+ text-decoration: underline;
88
+ text-decoration-style: dotted;
89
+ }
90
+ .cm-s-solarized .cm-strong { color: #eee; }
91
+ .cm-s-solarized .cm-error,
92
+ .cm-s-solarized .cm-invalidchar {
93
+ color: #586e75;
94
+ border-bottom: 1px dotted #dc322f;
95
+ }
96
+
97
+ .cm-s-solarized.cm-s-dark div.CodeMirror-selected { background: #073642; }
98
+ .cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); }
99
+ .cm-s-solarized.cm-s-dark .CodeMirror-line::-moz-selection, .cm-s-dark .CodeMirror-line > span::-moz-selection, .cm-s-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(7, 54, 66, 0.99); }
100
+
101
+ .cm-s-solarized.cm-s-light div.CodeMirror-selected { background: #eee8d5; }
102
+ .cm-s-solarized.cm-s-light .CodeMirror-line::selection, .cm-s-light .CodeMirror-line > span::selection, .cm-s-light .CodeMirror-line > span > span::selection { background: #eee8d5; }
103
+ .cm-s-solarized.cm-s-light .CodeMirror-line::-moz-selection, .cm-s-ligh .CodeMirror-line > span::-moz-selection, .cm-s-ligh .CodeMirror-line > span > span::-moz-selection { background: #eee8d5; }
104
+
105
+ /* Editor styling */
106
+
107
+
108
+
109
+ /* Little shadow on the view-port of the buffer view */
110
+ .cm-s-solarized.CodeMirror {
111
+ -moz-box-shadow: inset 7px 0 12px -6px #000;
112
+ -webkit-box-shadow: inset 7px 0 12px -6px #000;
113
+ box-shadow: inset 7px 0 12px -6px #000;
114
+ }
115
+
116
+ /* Remove gutter border */
117
+ .cm-s-solarized .CodeMirror-gutters {
118
+ border-right: 0;
119
+ }
120
+
121
+ /* Gutter colors and line number styling based of color scheme (dark / light) */
122
+
123
+ /* Dark */
124
+ .cm-s-solarized.cm-s-dark .CodeMirror-gutters {
125
+ background-color: #073642;
126
+ }
127
+
128
+ .cm-s-solarized.cm-s-dark .CodeMirror-linenumber {
129
+ color: #586e75;
130
+ text-shadow: #021014 0 -1px;
131
+ }
132
+
133
+ /* Light */
134
+ .cm-s-solarized.cm-s-light .CodeMirror-gutters {
135
+ background-color: #eee8d5;
136
+ }
137
+
138
+ .cm-s-solarized.cm-s-light .CodeMirror-linenumber {
139
+ color: #839496;
140
+ }
141
+
142
+ /* Common */
143
+ .cm-s-solarized .CodeMirror-linenumber {
144
+ padding: 0 5px;
145
+ }
146
+ .cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; }
147
+ .cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; }
148
+ .cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; }
149
+
150
+ .cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text {
151
+ color: #586e75;
152
+ }
153
+
154
+ /* Cursor */
155
+ .cm-s-solarized .CodeMirror-cursor { border-left: 1px solid #819090; }
156
+
157
+ /* Fat cursor */
158
+ .cm-s-solarized.cm-s-light.cm-fat-cursor .CodeMirror-cursor { background: #77ee77; }
159
+ .cm-s-solarized.cm-s-light .cm-animate-fat-cursor { background-color: #77ee77; }
160
+ .cm-s-solarized.cm-s-dark.cm-fat-cursor .CodeMirror-cursor { background: #586e75; }
161
+ .cm-s-solarized.cm-s-dark .cm-animate-fat-cursor { background-color: #586e75; }
162
+
163
+ /* Active line */
164
+ .cm-s-solarized.cm-s-dark .CodeMirror-activeline-background {
165
+ background: rgba(255, 255, 255, 0.06);
166
+ }
167
+ .cm-s-solarized.cm-s-light .CodeMirror-activeline-background {
168
+ background: rgba(0, 0, 0, 0.06);
169
+ }
js/codemirror/theme/the-matrix.css ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-the-matrix.CodeMirror { background: #000000; color: #00FF00; }
2
+ .cm-s-the-matrix div.CodeMirror-selected { background: #2D2D2D; }
3
+ .cm-s-the-matrix .CodeMirror-line::selection, .cm-s-the-matrix .CodeMirror-line > span::selection, .cm-s-the-matrix .CodeMirror-line > span > span::selection { background: rgba(45, 45, 45, 0.99); }
4
+ .cm-s-the-matrix .CodeMirror-line::-moz-selection, .cm-s-the-matrix .CodeMirror-line > span::-moz-selection, .cm-s-the-matrix .CodeMirror-line > span > span::-moz-selection { background: rgba(45, 45, 45, 0.99); }
5
+ .cm-s-the-matrix .CodeMirror-gutters { background: #060; border-right: 2px solid #00FF00; }
6
+ .cm-s-the-matrix .CodeMirror-guttermarker { color: #0f0; }
7
+ .cm-s-the-matrix .CodeMirror-guttermarker-subtle { color: white; }
8
+ .cm-s-the-matrix .CodeMirror-linenumber { color: #FFFFFF; }
9
+ .cm-s-the-matrix .CodeMirror-cursor { border-left: 1px solid #00FF00; }
10
+
11
+ .cm-s-the-matrix span.cm-keyword { color: #008803; font-weight: bold; }
12
+ .cm-s-the-matrix span.cm-atom { color: #3FF; }
13
+ .cm-s-the-matrix span.cm-number { color: #FFB94F; }
14
+ .cm-s-the-matrix span.cm-def { color: #99C; }
15
+ .cm-s-the-matrix span.cm-variable { color: #F6C; }
16
+ .cm-s-the-matrix span.cm-variable-2 { color: #C6F; }
17
+ .cm-s-the-matrix span.cm-variable-3 { color: #96F; }
18
+ .cm-s-the-matrix span.cm-property { color: #62FFA0; }
19
+ .cm-s-the-matrix span.cm-operator { color: #999; }
20
+ .cm-s-the-matrix span.cm-comment { color: #CCCCCC; }
21
+ .cm-s-the-matrix span.cm-string { color: #39C; }
22
+ .cm-s-the-matrix span.cm-meta { color: #C9F; }
23
+ .cm-s-the-matrix span.cm-qualifier { color: #FFF700; }
24
+ .cm-s-the-matrix span.cm-builtin { color: #30a; }
25
+ .cm-s-the-matrix span.cm-bracket { color: #cc7; }
26
+ .cm-s-the-matrix span.cm-tag { color: #FFBD40; }
27
+ .cm-s-the-matrix span.cm-attribute { color: #FFF700; }
28
+ .cm-s-the-matrix span.cm-error { color: #FF0000; }
29
+
30
+ .cm-s-the-matrix .CodeMirror-activeline-background { background: #040; }
js/codemirror/theme/tomorrow-night-bright.css ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Tomorrow Night - Bright
4
+ Author: Chris Kempson
5
+
6
+ Port done by Gerard Braad <me@gbraad.nl>
7
+
8
+ */
9
+
10
+ .cm-s-tomorrow-night-bright.CodeMirror { background: #000000; color: #eaeaea; }
11
+ .cm-s-tomorrow-night-bright div.CodeMirror-selected { background: #424242; }
12
+ .cm-s-tomorrow-night-bright .CodeMirror-gutters { background: #000000; border-right: 0px; }
13
+ .cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; }
14
+ .cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; }
15
+ .cm-s-tomorrow-night-bright .CodeMirror-linenumber { color: #424242; }
16
+ .cm-s-tomorrow-night-bright .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }
17
+
18
+ .cm-s-tomorrow-night-bright span.cm-comment { color: #d27b53; }
19
+ .cm-s-tomorrow-night-bright span.cm-atom { color: #a16a94; }
20
+ .cm-s-tomorrow-night-bright span.cm-number { color: #a16a94; }
21
+
22
+ .cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute { color: #99cc99; }
23
+ .cm-s-tomorrow-night-bright span.cm-keyword { color: #d54e53; }
24
+ .cm-s-tomorrow-night-bright span.cm-string { color: #e7c547; }
25
+
26
+ .cm-s-tomorrow-night-bright span.cm-variable { color: #b9ca4a; }
27
+ .cm-s-tomorrow-night-bright span.cm-variable-2 { color: #7aa6da; }
28
+ .cm-s-tomorrow-night-bright span.cm-def { color: #e78c45; }
29
+ .cm-s-tomorrow-night-bright span.cm-bracket { color: #eaeaea; }
30
+ .cm-s-tomorrow-night-bright span.cm-tag { color: #d54e53; }
31
+ .cm-s-tomorrow-night-bright span.cm-link { color: #a16a94; }
32
+ .cm-s-tomorrow-night-bright span.cm-error { background: #d54e53; color: #6A6A6A; }
33
+
34
+ .cm-s-tomorrow-night-bright .CodeMirror-activeline-background { background: #2a2a2a; }
35
+ .cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/tomorrow-night-eighties.css ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: Tomorrow Night - Eighties
4
+ Author: Chris Kempson
5
+
6
+ CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7
+ Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
+
9
+ */
10
+
11
+ .cm-s-tomorrow-night-eighties.CodeMirror { background: #000000; color: #CCCCCC; }
12
+ .cm-s-tomorrow-night-eighties div.CodeMirror-selected { background: #2D2D2D; }
13
+ .cm-s-tomorrow-night-eighties .CodeMirror-line::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::selection { background: rgba(45, 45, 45, 0.99); }
14
+ .cm-s-tomorrow-night-eighties .CodeMirror-line::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::-moz-selection { background: rgba(45, 45, 45, 0.99); }
15
+ .cm-s-tomorrow-night-eighties .CodeMirror-gutters { background: #000000; border-right: 0px; }
16
+ .cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; }
17
+ .cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; }
18
+ .cm-s-tomorrow-night-eighties .CodeMirror-linenumber { color: #515151; }
19
+ .cm-s-tomorrow-night-eighties .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }
20
+
21
+ .cm-s-tomorrow-night-eighties span.cm-comment { color: #d27b53; }
22
+ .cm-s-tomorrow-night-eighties span.cm-atom { color: #a16a94; }
23
+ .cm-s-tomorrow-night-eighties span.cm-number { color: #a16a94; }
24
+
25
+ .cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute { color: #99cc99; }
26
+ .cm-s-tomorrow-night-eighties span.cm-keyword { color: #f2777a; }
27
+ .cm-s-tomorrow-night-eighties span.cm-string { color: #ffcc66; }
28
+
29
+ .cm-s-tomorrow-night-eighties span.cm-variable { color: #99cc99; }
30
+ .cm-s-tomorrow-night-eighties span.cm-variable-2 { color: #6699cc; }
31
+ .cm-s-tomorrow-night-eighties span.cm-def { color: #f99157; }
32
+ .cm-s-tomorrow-night-eighties span.cm-bracket { color: #CCCCCC; }
33
+ .cm-s-tomorrow-night-eighties span.cm-tag { color: #f2777a; }
34
+ .cm-s-tomorrow-night-eighties span.cm-link { color: #a16a94; }
35
+ .cm-s-tomorrow-night-eighties span.cm-error { background: #f2777a; color: #6A6A6A; }
36
+
37
+ .cm-s-tomorrow-night-eighties .CodeMirror-activeline-background { background: #343600; }
38
+ .cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
js/codemirror/theme/ttcn.css ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-ttcn .cm-quote { color: #090; }
2
+ .cm-s-ttcn .cm-negative { color: #d44; }
3
+ .cm-s-ttcn .cm-positive { color: #292; }
4
+ .cm-s-ttcn .cm-header, .cm-strong { font-weight: bold; }
5
+ .cm-s-ttcn .cm-em { font-style: italic; }
6
+ .cm-s-ttcn .cm-link { text-decoration: underline; }
7
+ .cm-s-ttcn .cm-strikethrough { text-decoration: line-through; }
8
+ .cm-s-ttcn .cm-header { color: #00f; font-weight: bold; }
9
+
10
+ .cm-s-ttcn .cm-atom { color: #219; }
11
+ .cm-s-ttcn .cm-attribute { color: #00c; }
12
+ .cm-s-ttcn .cm-bracket { color: #997; }
13
+ .cm-s-ttcn .cm-comment { color: #333333; }
14
+ .cm-s-ttcn .cm-def { color: #00f; }
15
+ .cm-s-ttcn .cm-em { font-style: italic; }
16
+ .cm-s-ttcn .cm-error { color: #f00; }
17
+ .cm-s-ttcn .cm-hr { color: #999; }
18
+ .cm-s-ttcn .cm-invalidchar { color: #f00; }
19
+ .cm-s-ttcn .cm-keyword { font-weight:bold; }
20
+ .cm-s-ttcn .cm-link { color: #00c; text-decoration: underline; }
21
+ .cm-s-ttcn .cm-meta { color: #555; }
22
+ .cm-s-ttcn .cm-negative { color: #d44; }
23
+ .cm-s-ttcn .cm-positive { color: #292; }
24
+ .cm-s-ttcn .cm-qualifier { color: #555; }
25
+ .cm-s-ttcn .cm-strikethrough { text-decoration: line-through; }
26
+ .cm-s-ttcn .cm-string { color: #006400; }
27
+ .cm-s-ttcn .cm-string-2 { color: #f50; }
28
+ .cm-s-ttcn .cm-strong { font-weight: bold; }
29
+ .cm-s-ttcn .cm-tag { color: #170; }
30
+ .cm-s-ttcn .cm-variable { color: #8B2252; }
31
+ .cm-s-ttcn .cm-variable-2 { color: #05a; }
32
+ .cm-s-ttcn .cm-variable-3 { color: #085; }
33
+
34
+ .cm-s-ttcn .cm-invalidchar { color: #f00; }
35
+
36
+ /* ASN */
37
+ .cm-s-ttcn .cm-accessTypes,
38
+ .cm-s-ttcn .cm-compareTypes { color: #27408B; }
39
+ .cm-s-ttcn .cm-cmipVerbs { color: #8B2252; }
40
+ .cm-s-ttcn .cm-modifier { color:#D2691E; }
41
+ .cm-s-ttcn .cm-status { color:#8B4545; }
42
+ .cm-s-ttcn .cm-storage { color:#A020F0; }
43
+ .cm-s-ttcn .cm-tags { color:#006400; }
44
+
45
+ /* CFG */
46
+ .cm-s-ttcn .cm-externalCommands { color: #8B4545; font-weight:bold; }
47
+ .cm-s-ttcn .cm-fileNCtrlMaskOptions,
48
+ .cm-s-ttcn .cm-sectionTitle { color: #2E8B57; font-weight:bold; }
49
+
50
+ /* TTCN */
51
+ .cm-s-ttcn .cm-booleanConsts,
52
+ .cm-s-ttcn .cm-otherConsts,
53
+ .cm-s-ttcn .cm-verdictConsts { color: #006400; }
54
+ .cm-s-ttcn .cm-configOps,
55
+ .cm-s-ttcn .cm-functionOps,
56
+ .cm-s-ttcn .cm-portOps,
57
+ .cm-s-ttcn .cm-sutOps,
58
+ .cm-s-ttcn .cm-timerOps,
59
+ .cm-s-ttcn .cm-verdictOps { color: #0000FF; }
60
+ .cm-s-ttcn .cm-preprocessor,
61
+ .cm-s-ttcn .cm-templateMatch,
62
+ .cm-s-ttcn .cm-ttcn3Macros { color: #27408B; }
63
+ .cm-s-ttcn .cm-types { color: #A52A2A; font-weight:bold; }
64
+ .cm-s-ttcn .cm-visibilityModifiers { font-weight:bold; }
js/codemirror/theme/twilight.css ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/
2
+ .cm-s-twilight div.CodeMirror-selected { background: #323232; } /**/
3
+ .cm-s-twilight .CodeMirror-line::selection, .cm-s-twilight .CodeMirror-line > span::selection, .cm-s-twilight .CodeMirror-line > span > span::selection { background: rgba(50, 50, 50, 0.99); }
4
+ .cm-s-twilight .CodeMirror-line::-moz-selection, .cm-s-twilight .CodeMirror-line > span::-moz-selection, .cm-s-twilight .CodeMirror-line > span > span::-moz-selection { background: rgba(50, 50, 50, 0.99); }
5
+
6
+ .cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; }
7
+ .cm-s-twilight .CodeMirror-guttermarker { color: white; }
8
+ .cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; }
9
+ .cm-s-twilight .CodeMirror-linenumber { color: #aaa; }
10
+ .cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white; }
11
+
12
+ .cm-s-twilight .cm-keyword { color: #f9ee98; } /**/
13
+ .cm-s-twilight .cm-atom { color: #FC0; }
14
+ .cm-s-twilight .cm-number { color: #ca7841; } /**/
15
+ .cm-s-twilight .cm-def { color: #8DA6CE; }
16
+ .cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/
17
+ .cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def { color: #607392; } /**/
18
+ .cm-s-twilight .cm-operator { color: #cda869; } /**/
19
+ .cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/
20
+ .cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/
21
+ .cm-s-twilight .cm-string-2 { color:#bd6b18; } /*?*/
22
+ .cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/
23
+ .cm-s-twilight .cm-builtin { color: #cda869; } /*?*/
24
+ .cm-s-twilight .cm-tag { color: #997643; } /**/
25
+ .cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/
26
+ .cm-s-twilight .cm-header { color: #FF6400; }
27
+ .cm-s-twilight .cm-hr { color: #AEAEAE; }
28
+ .cm-s-twilight .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } /**/
29
+ .cm-s-twilight .cm-error { border-bottom: 1px solid red; }
30
+
31
+ .cm-s-twilight .CodeMirror-activeline-background { background: #27282E; }
32
+ .cm-s-twilight .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }
js/codemirror/theme/vibrant-ink.css ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Taken from the popular Visual Studio Vibrant Ink Schema */
2
+
3
+ .cm-s-vibrant-ink.CodeMirror { background: black; color: white; }
4
+ .cm-s-vibrant-ink div.CodeMirror-selected { background: #35493c; }
5
+ .cm-s-vibrant-ink .CodeMirror-line::selection, .cm-s-vibrant-ink .CodeMirror-line > span::selection, .cm-s-vibrant-ink .CodeMirror-line > span > span::selection { background: rgba(53, 73, 60, 0.99); }
6
+ .cm-s-vibrant-ink .CodeMirror-line::-moz-selection, .cm-s-vibrant-ink .CodeMirror-line > span::-moz-selection, .cm-s-vibrant-ink .CodeMirror-line > span > span::-moz-selection { background: rgba(53, 73, 60, 0.99); }
7
+
8
+ .cm-s-vibrant-ink .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; }
9
+ .cm-s-vibrant-ink .CodeMirror-guttermarker { color: white; }
10
+ .cm-s-vibrant-ink .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
11
+ .cm-s-vibrant-ink .CodeMirror-linenumber { color: #d0d0d0; }
12
+ .cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white; }
13
+
14
+ .cm-s-vibrant-ink .cm-keyword { color: #CC7832; }
15
+ .cm-s-vibrant-ink .cm-atom { color: #FC0; }
16
+ .cm-s-vibrant-ink .cm-number { color: #FFEE98; }
17
+ .cm-s-vibrant-ink .cm-def { color: #8DA6CE; }
18
+ .cm-s-vibrant-ink span.cm-variable-2, .cm-s-vibrant span.cm-tag { color: #FFC66D; }
19
+ .cm-s-vibrant-ink span.cm-variable-3, .cm-s-vibrant span.cm-def { color: #FFC66D; }
20
+ .cm-s-vibrant-ink .cm-operator { color: #888; }
21
+ .cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; }
22
+ .cm-s-vibrant-ink .cm-string { color: #A5C25C; }
23
+ .cm-s-vibrant-ink .cm-string-2 { color: red; }
24
+ .cm-s-vibrant-ink .cm-meta { color: #D8FA3C; }
25
+ .cm-s-vibrant-ink .cm-builtin { color: #8DA6CE; }
26
+ .cm-s-vibrant-ink .cm-tag { color: #8DA6CE; }
27
+ .cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; }
28
+ .cm-s-vibrant-ink .cm-header { color: #FF6400; }
29
+ .cm-s-vibrant-ink .cm-hr { color: #AEAEAE; }
30
+ .cm-s-vibrant-ink .cm-link { color: blue; }
31
+ .cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; }
32
+
33
+ .cm-s-vibrant-ink .CodeMirror-activeline-background { background: #27282E; }
34
+ .cm-s-vibrant-ink .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }
js/codemirror/theme/xq-dark.css ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright (C) 2011 by MarkLogic Corporation
3
+ Author: Mike Brevoort <mike@brevoort.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+ */
23
+ .cm-s-xq-dark.CodeMirror { background: #0a001f; color: #f8f8f8; }
24
+ .cm-s-xq-dark div.CodeMirror-selected { background: #27007A; }
25
+ .cm-s-xq-dark .CodeMirror-line::selection, .cm-s-xq-dark .CodeMirror-line > span::selection, .cm-s-xq-dark .CodeMirror-line > span > span::selection { background: rgba(39, 0, 122, 0.99); }
26
+ .cm-s-xq-dark .CodeMirror-line::-moz-selection, .cm-s-xq-dark .CodeMirror-line > span::-moz-selection, .cm-s-xq-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(39, 0, 122, 0.99); }
27
+ .cm-s-xq-dark .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; }
28
+ .cm-s-xq-dark .CodeMirror-guttermarker { color: #FFBD40; }
29
+ .cm-s-xq-dark .CodeMirror-guttermarker-subtle { color: #f8f8f8; }
30
+ .cm-s-xq-dark .CodeMirror-linenumber { color: #f8f8f8; }
31
+ .cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white; }
32
+
33
+ .cm-s-xq-dark span.cm-keyword { color: #FFBD40; }
34
+ .cm-s-xq-dark span.cm-atom { color: #6C8CD5; }
35
+ .cm-s-xq-dark span.cm-number { color: #164; }
36
+ .cm-s-xq-dark span.cm-def { color: #FFF; text-decoration:underline; }
37
+ .cm-s-xq-dark span.cm-variable { color: #FFF; }
38
+ .cm-s-xq-dark span.cm-variable-2 { color: #EEE; }
39
+ .cm-s-xq-dark span.cm-variable-3 { color: #DDD; }
40
+ .cm-s-xq-dark span.cm-property {}
41
+ .cm-s-xq-dark span.cm-operator {}
42
+ .cm-s-xq-dark span.cm-comment { color: gray; }
43
+ .cm-s-xq-dark span.cm-string { color: #9FEE00; }
44
+ .cm-s-xq-dark span.cm-meta { color: yellow; }
45
+ .cm-s-xq-dark span.cm-qualifier { color: #FFF700; }
46
+ .cm-s-xq-dark span.cm-builtin { color: #30a; }
47
+ .cm-s-xq-dark span.cm-bracket { color: #cc7; }
48
+ .cm-s-xq-dark span.cm-tag { color: #FFBD40; }
49
+ .cm-s-xq-dark span.cm-attribute { color: #FFF700; }
50
+ .cm-s-xq-dark span.cm-error { color: #f00; }
51
+
52
+ .cm-s-xq-dark .CodeMirror-activeline-background { background: #27282E; }
53
+ .cm-s-xq-dark .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; }
js/codemirror/theme/xq-light.css ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright (C) 2011 by MarkLogic Corporation
3
+ Author: Mike Brevoort <mike@brevoort.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
22
+ */
23
+ .cm-s-xq-light span.cm-keyword { line-height: 1em; font-weight: bold; color: #5A5CAD; }
24
+ .cm-s-xq-light span.cm-atom { color: #6C8CD5; }
25
+ .cm-s-xq-light span.cm-number { color: #164; }
26
+ .cm-s-xq-light span.cm-def { text-decoration:underline; }
27
+ .cm-s-xq-light span.cm-variable { color: black; }
28
+ .cm-s-xq-light span.cm-variable-2 { color:black; }
29
+ .cm-s-xq-light span.cm-variable-3 { color: black; }
30
+ .cm-s-xq-light span.cm-property {}
31
+ .cm-s-xq-light span.cm-operator {}
32
+ .cm-s-xq-light span.cm-comment { color: #0080FF; font-style: italic; }
33
+ .cm-s-xq-light span.cm-string { color: red; }
34
+ .cm-s-xq-light span.cm-meta { color: yellow; }
35
+ .cm-s-xq-light span.cm-qualifier { color: grey; }
36
+ .cm-s-xq-light span.cm-builtin { color: #7EA656; }
37
+ .cm-s-xq-light span.cm-bracket { color: #cc7; }
38
+ .cm-s-xq-light span.cm-tag { color: #3F7F7F; }
39
+ .cm-s-xq-light span.cm-attribute { color: #7F007F; }
40
+ .cm-s-xq-light span.cm-error { color: #f00; }
41
+
42
+ .cm-s-xq-light .CodeMirror-activeline-background { background: #e8f2ff; }
43
+ .cm-s-xq-light .CodeMirror-matchingbracket { outline:1px solid grey;color:black !important;background:yellow; }
js/codemirror/theme/yeti.css ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Name: yeti
4
+ Author: Michael Kaminsky (http://github.com/mkaminsky11)
5
+
6
+ Original yeti color scheme by Jesse Weed (https://github.com/jesseweed/yeti-syntax)
7
+
8
+ */
9
+
10
+
11
+ .cm-s-yeti.CodeMirror {
12
+ background-color: #ECEAE8 !important;
13
+ color: #d1c9c0 !important;
14
+ border: none;
15
+ }
16
+
17
+ .cm-s-yeti .CodeMirror-gutters {
18
+ color: #adaba6;
19
+ background-color: #E5E1DB;
20
+ border: none;
21
+ }
22
+ .cm-s-yeti .CodeMirror-cursor { border-left: solid thin #d1c9c0; }
23
+ .cm-s-yeti .CodeMirror-linenumber { color: #adaba6; }
24
+ .cm-s-yeti.CodeMirror-focused div.CodeMirror-selected { background: #DCD8D2; }
25
+ .cm-s-yeti .CodeMirror-line::selection, .cm-s-yeti .CodeMirror-line > span::selection, .cm-s-yeti .CodeMirror-line > span > span::selection { background: #DCD8D2; }
26
+ .cm-s-yeti .CodeMirror-line::-moz-selection, .cm-s-yeti .CodeMirror-line > span::-moz-selection, .cm-s-yeti .CodeMirror-line > span > span::-moz-selection { background: #DCD8D2; }
27
+ .cm-s-yeti span.cm-comment { color: #d4c8be; }
28
+ .cm-s-yeti span.cm-string, .cm-s-yeti span.cm-string-2 { color: #96c0d8; }
29
+ .cm-s-yeti span.cm-number { color: #a074c4; }
30
+ .cm-s-yeti span.cm-variable { color: #55b5db; }
31
+ .cm-s-yeti span.cm-variable-2 { color: #a074c4; }
32
+ .cm-s-yeti span.cm-def { color: #55b5db; }
33
+ .cm-s-yeti span.cm-operator { color: #9fb96e; }
34
+ .cm-s-yeti span.cm-keyword { color: #9fb96e; }
35
+ .cm-s-yeti span.cm-atom { color: #a074c4; }
36
+ .cm-s-yeti span.cm-meta { color: #96c0d8; }
37
+ .cm-s-yeti span.cm-tag { color: #96c0d8; }
38
+ .cm-s-yeti span.cm-attribute { color: #9fb96e; }
39
+ .cm-s-yeti span.cm-qualifier { color: #96c0d8; }
40
+ .cm-s-yeti span.cm-property { color: #a074c4; }
41
+ .cm-s-yeti span.cm-builtin { color: #a074c4; }
42
+ .cm-s-yeti span.cm-variable-3 { color: #96c0d8; }
43
+ .cm-s-yeti .CodeMirror-activeline-background { background: #E7E4E0; }
44
+ .cm-s-yeti .CodeMirror-matchingbracket { text-decoration: underline; }
js/codemirror/theme/zenburn.css ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * "
3
+ * Using Zenburn color palette from the Emacs Zenburn Theme
4
+ * https://github.com/bbatsov/zenburn-emacs/blob/master/zenburn-theme.el
5
+ *
6
+ * Also using parts of https://github.com/xavi/coderay-lighttable-theme
7
+ * "
8
+ * From: https://github.com/wisenomad/zenburn-lighttable-theme/blob/master/zenburn.css
9
+ */
10
+
11
+ .cm-s-zenburn .CodeMirror-gutters { background: #3f3f3f !important; }
12
+ .cm-s-zenburn .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { color: #999; }
13
+ .cm-s-zenburn .CodeMirror-cursor { border-left: 1px solid white; }
14
+ .cm-s-zenburn { background-color: #3f3f3f; color: #dcdccc; }
15
+ .cm-s-zenburn span.cm-builtin { color: #dcdccc; font-weight: bold; }
16
+ .cm-s-zenburn span.cm-comment { color: #7f9f7f; }
17
+ .cm-s-zenburn span.cm-keyword { color: #f0dfaf; font-weight: bold; }
18
+ .cm-s-zenburn span.cm-atom { color: #bfebbf; }
19
+ .cm-s-zenburn span.cm-def { color: #dcdccc; }
20
+ .cm-s-zenburn span.cm-variable { color: #dfaf8f; }
21
+ .cm-s-zenburn span.cm-variable-2 { color: #dcdccc; }
22
+ .cm-s-zenburn span.cm-string { color: #cc9393; }
23
+ .cm-s-zenburn span.cm-string-2 { color: #cc9393; }
24
+ .cm-s-zenburn span.cm-number { color: #dcdccc; }
25
+ .cm-s-zenburn span.cm-tag { color: #93e0e3; }
26
+ .cm-s-zenburn span.cm-property { color: #dfaf8f; }
27
+ .cm-s-zenburn span.cm-attribute { color: #dfaf8f; }
28
+ .cm-s-zenburn span.cm-qualifier { color: #7cb8bb; }
29
+ .cm-s-zenburn span.cm-meta { color: #f0dfaf; }
30
+ .cm-s-zenburn span.cm-header { color: #f0efd0; }
31
+ .cm-s-zenburn span.cm-operator { color: #f0efd0; }
32
+ .cm-s-zenburn span.CodeMirror-matchingbracket { box-sizing: border-box; background: transparent; border-bottom: 1px solid; }
33
+ .cm-s-zenburn span.CodeMirror-nonmatchingbracket { border-bottom: 1px solid; background: none; }
34
+ .cm-s-zenburn .CodeMirror-activeline { background: #000000; }
35
+ .cm-s-zenburn .CodeMirror-activeline-background { background: #000000; }
36
+ .cm-s-zenburn div.CodeMirror-selected { background: #545454; }
37
+ .cm-s-zenburn .CodeMirror-focused div.CodeMirror-selected { background: #4f4f4f; }
js/codemirror/vbscript.js ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ /*
5
+ For extra ASP classic objects, initialize CodeMirror instance with this option:
6
+ isASP: true
7
+
8
+ E.G.:
9
+ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
10
+ lineNumbers: true,
11
+ isASP: true
12
+ });
13
+ */
14
+
15
+ (function(mod) {
16
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
17
+ mod(require("../../lib/codemirror"));
18
+ else if (typeof define == "function" && define.amd) // AMD
19
+ define(["../../lib/codemirror"], mod);
20
+ else // Plain browser env
21
+ mod(CodeMirror);
22
+ })(function(CodeMirror) {
23
+ "use strict";
24
+
25
+ CodeMirror.defineMode("vbscript", function(conf, parserConf) {
26
+ var ERRORCLASS = 'error';
27
+
28
+ function wordRegexp(words) {
29
+ return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
30
+ }
31
+
32
+ var singleOperators = new RegExp("^[\\+\\-\\*/&\\\\\\^<>=]");
33
+ var doubleOperators = new RegExp("^((<>)|(<=)|(>=))");
34
+ var singleDelimiters = new RegExp('^[\\.,]');
35
+ var brakets = new RegExp('^[\\(\\)]');
36
+ var identifiers = new RegExp("^[A-Za-z][_A-Za-z0-9]*");
37
+
38
+ var openingKeywords = ['class','sub','select','while','if','function', 'property', 'with', 'for'];
39
+ var middleKeywords = ['else','elseif','case'];
40
+ var endKeywords = ['next','loop','wend'];
41
+
42
+ var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp']);
43
+ var commonkeywords = ['dim', 'redim', 'then', 'until', 'randomize',
44
+ 'byval','byref','new','property', 'exit', 'in',
45
+ 'const','private', 'public',
46
+ 'get','set','let', 'stop', 'on error resume next', 'on error goto 0', 'option explicit', 'call', 'me'];
47
+
48
+ //This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx
49
+ var atomWords = ['true', 'false', 'nothing', 'empty', 'null'];
50
+ //This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx
51
+ var builtinFuncsWords = ['abs', 'array', 'asc', 'atn', 'cbool', 'cbyte', 'ccur', 'cdate', 'cdbl', 'chr', 'cint', 'clng', 'cos', 'csng', 'cstr', 'date', 'dateadd', 'datediff', 'datepart',
52
+ 'dateserial', 'datevalue', 'day', 'escape', 'eval', 'execute', 'exp', 'filter', 'formatcurrency', 'formatdatetime', 'formatnumber', 'formatpercent', 'getlocale', 'getobject',
53
+ 'getref', 'hex', 'hour', 'inputbox', 'instr', 'instrrev', 'int', 'fix', 'isarray', 'isdate', 'isempty', 'isnull', 'isnumeric', 'isobject', 'join', 'lbound', 'lcase', 'left',
54
+ 'len', 'loadpicture', 'log', 'ltrim', 'rtrim', 'trim', 'maths', 'mid', 'minute', 'month', 'monthname', 'msgbox', 'now', 'oct', 'replace', 'rgb', 'right', 'rnd', 'round',
55
+ 'scriptengine', 'scriptenginebuildversion', 'scriptenginemajorversion', 'scriptengineminorversion', 'second', 'setlocale', 'sgn', 'sin', 'space', 'split', 'sqr', 'strcomp',
56
+ 'string', 'strreverse', 'tan', 'time', 'timer', 'timeserial', 'timevalue', 'typename', 'ubound', 'ucase', 'unescape', 'vartype', 'weekday', 'weekdayname', 'year'];
57
+
58
+ //This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx
59
+ var builtinConsts = ['vbBlack', 'vbRed', 'vbGreen', 'vbYellow', 'vbBlue', 'vbMagenta', 'vbCyan', 'vbWhite', 'vbBinaryCompare', 'vbTextCompare',
60
+ 'vbSunday', 'vbMonday', 'vbTuesday', 'vbWednesday', 'vbThursday', 'vbFriday', 'vbSaturday', 'vbUseSystemDayOfWeek', 'vbFirstJan1', 'vbFirstFourDays', 'vbFirstFullWeek',
61
+ 'vbGeneralDate', 'vbLongDate', 'vbShortDate', 'vbLongTime', 'vbShortTime', 'vbObjectError',
62
+ 'vbOKOnly', 'vbOKCancel', 'vbAbortRetryIgnore', 'vbYesNoCancel', 'vbYesNo', 'vbRetryCancel', 'vbCritical', 'vbQuestion', 'vbExclamation', 'vbInformation', 'vbDefaultButton1', 'vbDefaultButton2',
63
+ 'vbDefaultButton3', 'vbDefaultButton4', 'vbApplicationModal', 'vbSystemModal', 'vbOK', 'vbCancel', 'vbAbort', 'vbRetry', 'vbIgnore', 'vbYes', 'vbNo',
64
+ 'vbCr', 'VbCrLf', 'vbFormFeed', 'vbLf', 'vbNewLine', 'vbNullChar', 'vbNullString', 'vbTab', 'vbVerticalTab', 'vbUseDefault', 'vbTrue', 'vbFalse',
65
+ 'vbEmpty', 'vbNull', 'vbInteger', 'vbLong', 'vbSingle', 'vbDouble', 'vbCurrency', 'vbDate', 'vbString', 'vbObject', 'vbError', 'vbBoolean', 'vbVariant', 'vbDataObject', 'vbDecimal', 'vbByte', 'vbArray'];
66
+ //This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx
67
+ var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp'];
68
+ var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count'];
69
+ var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit'];
70
+
71
+ var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application'];
72
+ var aspKnownProperties = ['buffer', 'cachecontrol', 'charset', 'contenttype', 'expires', 'expiresabsolute', 'isclientconnected', 'pics', 'status', //response
73
+ 'clientcertificate', 'cookies', 'form', 'querystring', 'servervariables', 'totalbytes', //request
74
+ 'contents', 'staticobjects', //application
75
+ 'codepage', 'lcid', 'sessionid', 'timeout', //session
76
+ 'scripttimeout']; //server
77
+ var aspKnownMethods = ['addheader', 'appendtolog', 'binarywrite', 'end', 'flush', 'redirect', //response
78
+ 'binaryread', //request
79
+ 'remove', 'removeall', 'lock', 'unlock', //application
80
+ 'abandon', //session
81
+ 'getlasterror', 'htmlencode', 'mappath', 'transfer', 'urlencode']; //server
82
+
83
+ var knownWords = knownMethods.concat(knownProperties);
84
+
85
+ builtinObjsWords = builtinObjsWords.concat(builtinConsts);
86
+
87
+ if (conf.isASP){
88
+ builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords);
89
+ knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties);
90
+ };
91
+
92
+ var keywords = wordRegexp(commonkeywords);
93
+ var atoms = wordRegexp(atomWords);
94
+ var builtinFuncs = wordRegexp(builtinFuncsWords);
95
+ var builtinObjs = wordRegexp(builtinObjsWords);
96
+ var known = wordRegexp(knownWords);
97
+ var stringPrefixes = '"';
98
+
99
+ var opening = wordRegexp(openingKeywords);
100
+ var middle = wordRegexp(middleKeywords);
101
+ var closing = wordRegexp(endKeywords);
102
+ var doubleClosing = wordRegexp(['end']);
103
+ var doOpening = wordRegexp(['do']);
104
+ var noIndentWords = wordRegexp(['on error resume next', 'exit']);
105
+ var comment = wordRegexp(['rem']);
106
+
107
+
108
+ function indent(_stream, state) {
109
+ state.currentIndent++;
110
+ }
111
+
112
+ function dedent(_stream, state) {
113
+ state.currentIndent--;
114
+ }
115
+ // tokenizers
116
+ function tokenBase(stream, state) {
117
+ if (stream.eatSpace()) {
118
+ return 'space';
119
+ //return null;
120
+ }
121
+
122
+ var ch = stream.peek();
123
+
124
+ // Handle Comments
125
+ if (ch === "'") {
126
+ stream.skipToEnd();
127
+ return 'comment';
128
+ }
129
+ if (stream.match(comment)){
130
+ stream.skipToEnd();
131
+ return 'comment';
132
+ }
133
+
134
+
135
+ // Handle Number Literals
136
+ if (stream.match(/^((&H)|(&O))?[0-9\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\.]+[a-z_]/i, false)) {
137
+ var floatLiteral = false;
138
+ // Floats
139
+ if (stream.match(/^\d*\.\d+/i)) { floatLiteral = true; }
140
+ else if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
141
+ else if (stream.match(/^\.\d+/)) { floatLiteral = true; }
142
+
143
+ if (floatLiteral) {
144
+ // Float literals may be "imaginary"
145
+ stream.eat(/J/i);
146
+ return 'number';
147
+ }
148
+ // Integers
149
+ var intLiteral = false;
150
+ // Hex
151
+ if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }
152
+ // Octal
153
+ else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }
154
+ // Decimal
155
+ else if (stream.match(/^[1-9]\d*F?/)) {
156
+ // Decimal literals may be "imaginary"
157
+ stream.eat(/J/i);
158
+ // TODO - Can you have imaginary longs?
159
+ intLiteral = true;
160
+ }
161
+ // Zero by itself with no other piece of number.
162
+ else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
163
+ if (intLiteral) {
164
+ // Integer literals may be "long"
165
+ stream.eat(/L/i);
166
+ return 'number';
167
+ }
168
+ }
169
+
170
+ // Handle Strings
171
+ if (stream.match(stringPrefixes)) {
172
+ state.tokenize = tokenStringFactory(stream.current());
173
+ return state.tokenize(stream, state);
174
+ }
175
+
176
+ // Handle operators and Delimiters
177
+ if (stream.match(doubleOperators)
178
+ || stream.match(singleOperators)
179
+ || stream.match(wordOperators)) {
180
+ return 'operator';
181
+ }
182
+ if (stream.match(singleDelimiters)) {
183
+ return null;
184
+ }
185
+
186
+ if (stream.match(brakets)) {
187
+ return "bracket";
188
+ }
189
+
190
+ if (stream.match(noIndentWords)) {
191
+ state.doInCurrentLine = true;
192
+
193
+ return 'keyword';
194
+ }
195
+
196
+ if (stream.match(doOpening)) {
197
+ indent(stream,state);
198
+ state.doInCurrentLine = true;
199
+
200
+ return 'keyword';
201
+ }
202
+ if (stream.match(opening)) {
203
+ if (! state.doInCurrentLine)
204
+ indent(stream,state);
205
+ else
206
+ state.doInCurrentLine = false;
207
+
208
+ return 'keyword';
209
+ }
210
+ if (stream.match(middle)) {
211
+ return 'keyword';
212
+ }
213
+
214
+
215
+ if (stream.match(doubleClosing)) {
216
+ dedent(stream,state);
217
+ dedent(stream,state);
218
+
219
+ return 'keyword';
220
+ }
221
+ if (stream.match(closing)) {
222
+ if (! state.doInCurrentLine)
223
+ dedent(stream,state);
224
+ else
225
+ state.doInCurrentLine = false;
226
+
227
+ return 'keyword';
228
+ }
229
+
230
+ if (stream.match(keywords)) {
231
+ return 'keyword';
232
+ }
233
+
234
+ if (stream.match(atoms)) {
235
+ return 'atom';
236
+ }
237
+
238
+ if (stream.match(known)) {
239
+ return 'variable-2';
240
+ }
241
+
242
+ if (stream.match(builtinFuncs)) {
243
+ return 'builtin';
244
+ }
245
+
246
+ if (stream.match(builtinObjs)){
247
+ return 'variable-2';
248
+ }
249
+
250
+ if (stream.match(identifiers)) {
251
+ return 'variable';
252
+ }
253
+
254
+ // Handle non-detected items
255
+ stream.next();
256
+ return ERRORCLASS;
257
+ }
258
+
259
+ function tokenStringFactory(delimiter) {
260
+ var singleline = delimiter.length == 1;
261
+ var OUTCLASS = 'string';
262
+
263
+ return function(stream, state) {
264
+ while (!stream.eol()) {
265
+ stream.eatWhile(/[^'"]/);
266
+ if (stream.match(delimiter)) {
267
+ state.tokenize = tokenBase;
268
+ return OUTCLASS;
269
+ } else {
270
+ stream.eat(/['"]/);
271
+ }
272
+ }
273
+ if (singleline) {
274
+ if (parserConf.singleLineStringErrors) {
275
+ return ERRORCLASS;
276
+ } else {
277
+ state.tokenize = tokenBase;
278
+ }
279
+ }
280
+ return OUTCLASS;
281
+ };
282
+ }
283
+
284
+
285
+ function tokenLexer(stream, state) {
286
+ var style = state.tokenize(stream, state);
287
+ var current = stream.current();
288
+
289
+ // Handle '.' connected identifiers
290
+ if (current === '.') {
291
+ style = state.tokenize(stream, state);
292
+
293
+ current = stream.current();
294
+ if (style && (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword')){//|| knownWords.indexOf(current.substring(1)) > -1) {
295
+ if (style === 'builtin' || style === 'keyword') style='variable';
296
+ if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2';
297
+
298
+ return style;
299
+ } else {
300
+ return ERRORCLASS;
301
+ }
302
+ }
303
+
304
+ return style;
305
+ }
306
+
307
+ var external = {
308
+ electricChars:"dDpPtTfFeE ",
309
+ startState: function() {
310
+ return {
311
+ tokenize: tokenBase,
312
+ lastToken: null,
313
+ currentIndent: 0,
314
+ nextLineIndent: 0,
315
+ doInCurrentLine: false,
316
+ ignoreKeyword: false
317
+
318
+
319
+ };
320
+ },
321
+
322
+ token: function(stream, state) {
323
+ if (stream.sol()) {
324
+ state.currentIndent += state.nextLineIndent;
325
+ state.nextLineIndent = 0;
326
+ state.doInCurrentLine = 0;
327
+ }
328
+ var style = tokenLexer(stream, state);
329
+
330
+ state.lastToken = {style:style, content: stream.current()};
331
+
332
+ if (style==='space') style=null;
333
+
334
+ return style;
335
+ },
336
+
337
+ indent: function(state, textAfter) {
338
+ var trueText = textAfter.replace(/^\s+|\s+$/g, '') ;
339
+ if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);
340
+ if(state.currentIndent < 0) return 0;
341
+ return state.currentIndent * conf.indentUnit;
342
+ }
343
+
344
+ };
345
+ return external;
346
+ });
347
+
348
+ CodeMirror.defineMIME("text/vbscript", "vbscript");
349
+
350
+ });
js/codemirror/xml.js ADDED
@@ -0,0 +1,394 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // CodeMirror, copyright (c) by Marijn Haverbeke and others
2
+ // Distributed under an MIT license: http://codemirror.net/LICENSE
3
+
4
+ (function(mod) {
5
+ if (typeof exports == "object" && typeof module == "object") // CommonJS
6
+ mod(require("../../lib/codemirror"));
7
+ else if (typeof define == "function" && define.amd) // AMD
8
+ define(["../../lib/codemirror"], mod);
9
+ else // Plain browser env
10
+ mod(CodeMirror);
11
+ })(function(CodeMirror) {
12
+ "use strict";
13
+
14
+ var htmlConfig = {
15
+ autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
16
+ 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true,
17
+ 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true,
18
+ 'track': true, 'wbr': true, 'menuitem': true},
19
+ implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true,
20
+ 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true,
21
+ 'th': true, 'tr': true},
22
+ contextGrabbers: {
23
+ 'dd': {'dd': true, 'dt': true},
24
+ 'dt': {'dd': true, 'dt': true},
25
+ 'li': {'li': true},
26
+ 'option': {'option': true, 'optgroup': true},
27
+ 'optgroup': {'optgroup': true},
28
+ 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true,
29
+ 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true,
30
+ 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true,
31
+ 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true,
32
+ 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true},
33
+ 'rp': {'rp': true, 'rt': true},
34
+ 'rt': {'rp': true, 'rt': true},
35
+ 'tbody': {'tbody': true, 'tfoot': true},
36
+ 'td': {'td': true, 'th': true},
37
+ 'tfoot': {'tbody': true},
38
+ 'th': {'td': true, 'th': true},
39
+ 'thead': {'tbody': true, 'tfoot': true},
40
+ 'tr': {'tr': true}
41
+ },
42
+ doNotIndent: {"pre": true},
43
+ allowUnquoted: true,
44
+ allowMissing: true,
45
+ caseFold: true
46
+ }
47
+
48
+ var xmlConfig = {
49
+ autoSelfClosers: {},
50
+ implicitlyClosed: {},
51
+ contextGrabbers: {},
52
+ doNotIndent: {},
53
+ allowUnquoted: false,
54
+ allowMissing: false,
55
+ caseFold: false
56
+ }
57
+
58
+ CodeMirror.defineMode("xml", function(editorConf, config_) {
59
+ var indentUnit = editorConf.indentUnit
60
+ var config = {}
61
+ var defaults = config_.htmlMode ? htmlConfig : xmlConfig
62
+ for (var prop in defaults) config[prop] = defaults[prop]
63
+ for (var prop in config_) config[prop] = config_[prop]
64
+
65
+ // Return variables for tokenizers
66
+ var type, setStyle;
67
+
68
+ function inText(stream, state) {
69
+ function chain(parser) {
70
+ state.tokenize = parser;
71
+ return parser(stream, state);
72
+ }
73
+
74
+ var ch = stream.next();
75
+ if (ch == "<") {
76
+ if (stream.eat("!")) {
77
+ if (stream.eat("[")) {
78
+ if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>"));
79
+ else return null;
80
+ } else if (stream.match("--")) {
81
+ return chain(inBlock("comment", "-->"));
82
+ } else if (stream.match("DOCTYPE", true, true)) {
83
+ stream.eatWhile(/[\w\._\-]/);
84
+ return chain(doctype(1));
85
+ } else {
86
+ return null;
87
+ }
88
+ } else if (stream.eat("?")) {
89
+ stream.eatWhile(/[\w\._\-]/);
90
+ state.tokenize = inBlock("meta", "?>");
91
+ return "meta";
92
+ } else {
93
+ type = stream.eat("/") ? "closeTag" : "openTag";
94
+ state.tokenize = inTag;
95
+ return "tag bracket";
96
+ }
97
+ } else if (ch == "&") {
98
+ var ok;
99
+ if (stream.eat("#")) {
100
+ if (stream.eat("x")) {
101
+ ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";");
102
+ } else {
103
+ ok = stream.eatWhile(/[\d]/) && stream.eat(";");
104
+ }
105
+ } else {
106
+ ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";");
107
+ }
108
+ return ok ? "atom" : "error";
109
+ } else {
110
+ stream.eatWhile(/[^&<]/);
111
+ return null;
112
+ }
113
+ }
114
+ inText.isInText = true;
115
+
116
+ function inTag(stream, state) {
117
+ var ch = stream.next();
118
+ if (ch == ">" || (ch == "/" && stream.eat(">"))) {
119
+ state.tokenize = inText;
120
+ type = ch == ">" ? "endTag" : "selfcloseTag";
121
+ return "tag bracket";
122
+ } else if (ch == "=") {
123
+ type = "equals";
124
+ return null;
125
+ } else if (ch == "<") {
126
+ state.tokenize = inText;
127
+ state.state = baseState;
128
+ state.tagName = state.tagStart = null;
129
+ var next = state.tokenize(stream, state);
130
+ return next ? next + " tag error" : "tag error";
131
+ } else if (/[\'\"]/.test(ch)) {
132
+ state.tokenize = inAttribute(ch);
133
+ state.stringStartCol = stream.column();
134
+ return state.tokenize(stream, state);
135
+ } else {
136
+ stream.match(/^[^\s\u00a0=<>\"\'\-]*[^\s\u00a0=<>\"\'\/\-]/);
137
+ return "word";
138
+ }
139
+ }
140
+
141
+ function inAttribute(quote) {
142
+ var closure = function(stream, state) {
143
+ while (!stream.eol()) {
144
+ if (stream.next() == quote) {
145
+ state.tokenize = inTag;
146
+ break;
147
+ }
148
+ }
149
+ return "string";
150
+ };
151
+ closure.isInAttribute = true;
152
+ return closure;
153
+ }
154
+
155
+ function inBlock(style, terminator) {
156
+ return function(stream, state) {
157
+ while (!stream.eol()) {
158
+ if (stream.match(terminator)) {
159
+ state.tokenize = inText;
160
+ break;
161
+ }
162
+ stream.next();
163
+ }
164
+ return style;
165
+ };
166
+ }
167
+ function doctype(depth) {
168
+ return function(stream, state) {
169
+ var ch;
170
+ while ((ch = stream.next()) != null) {
171
+ if (ch == "<") {
172
+ state.tokenize = doctype(depth + 1);
173
+ return state.tokenize(stream, state);
174
+ } else if (ch == ">") {
175
+ if (depth == 1) {
176
+ state.tokenize = inText;
177
+ break;
178
+ } else {
179
+ state.tokenize = doctype(depth - 1);
180
+ return state.tokenize(stream, state);
181
+ }
182
+ }
183
+ }
184
+ return "meta";
185
+ };
186
+ }
187
+
188
+ function Context(state, tagName, startOfLine) {
189
+ this.prev = state.context;
190
+ this.tagName = tagName;
191
+ this.indent = state.indented;
192
+ this.startOfLine = startOfLine;
193
+ if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent))
194
+ this.noIndent = true;
195
+ }
196
+ function popContext(state) {
197
+ if (state.context) state.context = state.context.prev;
198
+ }
199
+ function maybePopContext(state, nextTagName) {
200
+ var parentTagName;
201
+ while (true) {
202
+ if (!state.context) {
203
+ return;
204
+ }
205
+ parentTagName = state.context.tagName;
206
+ if (!config.contextGrabbers.hasOwnProperty(parentTagName) ||
207
+ !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) {
208
+ return;
209
+ }
210
+ popContext(state);
211
+ }
212
+ }
213
+
214
+ function baseState(type, stream, state) {
215
+ if (type == "openTag") {
216
+ state.tagStart = stream.column();
217
+ return tagNameState;
218
+ } else if (type == "closeTag") {
219
+ return closeTagNameState;
220
+ } else {
221
+ return baseState;
222
+ }
223
+ }
224
+ function tagNameState(type, stream, state) {
225
+ if (type == "word") {
226
+ state.tagName = stream.current();
227
+ setStyle = "tag";
228
+ return attrState;
229
+ } else {
230
+ setStyle = "error";
231
+ return tagNameState;
232
+ }
233
+ }
234
+ function closeTagNameState(type, stream, state) {
235
+ if (type == "word") {
236
+ var tagName = stream.current();
237
+ if (state.context && state.context.tagName != tagName &&
238
+ config.implicitlyClosed.hasOwnProperty(state.context.tagName))
239
+ popContext(state);
240
+ if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) {
241
+ setStyle = "tag";
242
+ return closeState;
243
+ } else {
244
+ setStyle = "tag error";
245
+ return closeStateErr;
246
+ }
247
+ } else {
248
+ setStyle = "error";
249
+ return closeStateErr;
250
+ }
251
+ }
252
+
253
+ function closeState(type, _stream, state) {
254
+ if (type != "endTag") {
255
+ setStyle = "error";
256
+ return closeState;
257
+ }
258
+ popContext(state);
259
+ return baseState;
260
+ }
261
+ function closeStateErr(type, stream, state) {
262
+ setStyle = "error";
263
+ return closeState(type, stream, state);
264
+ }
265
+
266
+ function attrState(type, _stream, state) {
267
+ if (type == "word") {
268
+ setStyle = "attribute";
269
+ return attrEqState;
270
+ } else if (type == "endTag" || type == "selfcloseTag") {
271
+ var tagName = state.tagName, tagStart = state.tagStart;
272
+ state.tagName = state.tagStart = null;
273
+ if (type == "selfcloseTag" ||
274
+ config.autoSelfClosers.hasOwnProperty(tagName)) {
275
+ maybePopContext(state, tagName);
276
+ } else {
277
+ maybePopContext(state, tagName);
278
+ state.context = new Context(state, tagName, tagStart == state.indented);
279
+ }
280
+ return baseState;
281
+ }
282
+ setStyle = "error";
283
+ return attrState;
284
+ }
285
+ function attrEqState(type, stream, state) {
286
+ if (type == "equals") return attrValueState;
287
+ if (!config.allowMissing) setStyle = "error";
288
+ return attrState(type, stream, state);
289
+ }
290
+ function attrValueState(type, stream, state) {
291
+ if (type == "string") return attrContinuedState;
292
+ if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;}
293
+ setStyle = "error";
294
+ return attrState(type, stream, state);
295
+ }
296
+ function attrContinuedState(type, stream, state) {
297
+ if (type == "string") return attrContinuedState;
298
+ return attrState(type, stream, state);
299
+ }
300
+
301
+ return {
302
+ startState: function(baseIndent) {
303
+ var state = {tokenize: inText,
304
+ state: baseState,
305
+ indented: baseIndent || 0,
306
+ tagName: null, tagStart: null,
307
+ context: null}
308
+ if (baseIndent != null) state.baseIndent = baseIndent
309
+ return state
310
+ },
311
+
312
+ token: function(stream, state) {
313
+ if (!state.tagName && stream.sol())
314
+ state.indented = stream.indentation();
315
+
316
+ if (stream.eatSpace()) return null;
317
+ type = null;
318
+ var style = state.tokenize(stream, state);
319
+ if ((style || type) && style != "comment") {
320
+ setStyle = null;
321
+ state.state = state.state(type || style, stream, state);
322
+ if (setStyle)
323
+ style = setStyle == "error" ? style + " error" : setStyle;
324
+ }
325
+ return style;
326
+ },
327
+
328
+ indent: function(state, textAfter, fullLine) {
329
+ var context = state.context;
330
+ // Indent multi-line strings (e.g. css).
331
+ if (state.tokenize.isInAttribute) {
332
+ if (state.tagStart == state.indented)
333
+ return state.stringStartCol + 1;
334
+ else
335
+ return state.indented + indentUnit;
336
+ }
337
+ if (context && context.noIndent) return CodeMirror.Pass;
338
+ if (state.tokenize != inTag && state.tokenize != inText)
339
+ return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
340
+ // Indent the starts of attribute names.
341
+ if (state.tagName) {
342
+ if (config.multilineTagIndentPastTag !== false)
343
+ return state.tagStart + state.tagName.length + 2;
344
+ else
345
+ return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1);
346
+ }
347
+ if (config.alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
348
+ var tagAfter = textAfter && /^<(\/)?([\w_:\.-]*)/.exec(textAfter);
349
+ if (tagAfter && tagAfter[1]) { // Closing tag spotted
350
+ while (context) {
351
+ if (context.tagName == tagAfter[2]) {
352
+ context = context.prev;
353
+ break;
354
+ } else if (config.implicitlyClosed.hasOwnProperty(context.tagName)) {
355
+ context = context.prev;
356
+ } else {
357
+ break;
358
+ }
359
+ }
360
+ } else if (tagAfter) { // Opening tag spotted
361
+ while (context) {
362
+ var grabbers = config.contextGrabbers[context.tagName];
363
+ if (grabbers && grabbers.hasOwnProperty(tagAfter[2]))
364
+ context = context.prev;
365
+ else
366
+ break;
367
+ }
368
+ }
369
+ while (context && context.prev && !context.startOfLine)
370
+ context = context.prev;
371
+ if (context) return context.indent + indentUnit;
372
+ else return state.baseIndent || 0;
373
+ },
374
+
375
+ electricInput: /<\/[\s\w:]+>$/,
376
+ blockCommentStart: "<!--",
377
+ blockCommentEnd: "-->",
378
+
379
+ configuration: config.htmlMode ? "html" : "xml",
380
+ helperType: config.htmlMode ? "html" : "xml",
381
+
382
+ skipAttribute: function(state) {
383
+ if (state.state == attrValueState)
384
+ state.state = attrState
385
+ }
386
+ };
387
+ });
388
+
389
+ CodeMirror.defineMIME("text/xml", "xml");
390
+ CodeMirror.defineMIME("application/xml", "xml");
391
+ if (!CodeMirror.mimeModes.hasOwnProperty("text/html"))
392
+ CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true});
393
+
394
+ });
js/jquery.sticky.js ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Sticky Plugin v1.0.4 for jQuery
2
+ // =============
3
+ // Author: Anthony Garand
4
+ // Improvements by German M. Bravo (Kronuz) and Ruud Kamphuis (ruudk)
5
+ // Improvements by Leonardo C. Daronco (daronco)
6
+ // Created: 02/14/2011
7
+ // Date: 07/20/2015
8
+ // Website: http://stickyjs.com/
9
+ // Description: Makes an element on the page stick on the screen as you scroll
10
+ // It will only set the 'top' and 'position' of your element, you
11
+ // might need to adjust the width in some cases.
12
+
13
+ (function (factory) {
14
+ if (typeof define === 'function' && define.amd) {
15
+ // AMD. Register as an anonymous module.
16
+ define(['jquery'], factory);
17
+ } else if (typeof module === 'object' && module.exports) {
18
+ // Node/CommonJS
19
+ module.exports = factory(require('jquery'));
20
+ } else {
21
+ // Browser globals
22
+ factory(jQuery);
23
+ }
24
+ }(function ($) {
25
+ var slice = Array.prototype.slice; // save ref to original slice()
26
+ var splice = Array.prototype.splice; // save ref to original slice()
27
+
28
+ var defaults = {
29
+ topSpacing: 0,
30
+ bottomSpacing: 0,
31
+ className: 'is-sticky',
32
+ wrapperClassName: 'sticky-wrapper',
33
+ center: false,
34
+ getWidthFrom: '',
35
+ widthFromWrapper: true, // works only when .getWidthFrom is empty
36
+ responsiveWidth: true,
37
+ zIndex: 'auto'
38
+ },
39
+ $window = $(window),
40
+ $document = $(document),
41
+ sticked = [],
42
+ windowHeight = $window.height(),
43
+ scroller = function() {
44
+ var scrollTop = $window.scrollTop(),
45
+ documentHeight = $document.height(),
46
+ dwh = documentHeight - windowHeight,
47
+ extra = (scrollTop > dwh) ? dwh - scrollTop : 0;
48
+
49
+ for (var i = 0, l = sticked.length; i < l; i++) {
50
+ var s = sticked[i],
51
+ elementTop = s.stickyWrapper.offset().top,
52
+ etse = elementTop - s.topSpacing - extra;
53
+
54
+ //update height in case of dynamic content
55
+ s.stickyWrapper.css('height', s.stickyElement.outerHeight());
56
+
57
+ if (scrollTop <= etse) {
58
+ if (s.currentTop !== null) {
59
+ s.stickyElement
60
+ .css({
61
+ 'width': '',
62
+ 'position': '',
63
+ 'top': '',
64
+ 'background-color': '',
65
+ 'border-bottom': '',
66
+ 'z-index': ''
67
+ });
68
+ s.stickyElement.parent().removeClass(s.className);
69
+ s.stickyElement.trigger('sticky-end', [s]);
70
+ s.currentTop = null;
71
+ }
72
+ }
73
+ else {
74
+ var newTop = documentHeight - s.stickyElement.outerHeight()
75
+ - s.topSpacing - s.bottomSpacing - scrollTop - extra;
76
+ if (newTop < 0) {
77
+ newTop = newTop + s.topSpacing;
78
+ } else {
79
+ newTop = s.topSpacing;
80
+ }
81
+ if (s.currentTop !== newTop) {
82
+ var newWidth;
83
+ if (s.getWidthFrom) {
84
+ newWidth = $(s.getWidthFrom).width() || null;
85
+ } else if (s.widthFromWrapper) {
86
+ newWidth = s.stickyWrapper.width();
87
+ }
88
+ if (newWidth == null) {
89
+ newWidth = s.stickyElement.width();
90
+ }
91
+ s.stickyElement
92
+ .css('width', newWidth)
93
+ .css('position', 'fixed')
94
+ .css('top', newTop)
95
+ .css('left', '')
96
+ .css('background-color', '')
97
+ .css('border-bottom', 'none')
98
+ .css('z-index', s.zIndex);
99
+
100
+ s.stickyElement.parent().addClass(s.className);
101
+
102
+ if (s.currentTop === null) {
103
+ s.stickyElement.trigger('sticky-start', [s]);
104
+ } else {
105
+ // sticky is started but it have to be repositioned
106
+ s.stickyElement.trigger('sticky-update', [s]);
107
+ }
108
+
109
+ if (s.currentTop === s.topSpacing && s.currentTop > newTop || s.currentTop === null && newTop < s.topSpacing) {
110
+ // just reached bottom || just started to stick but bottom is already reached
111
+ s.stickyElement.trigger('sticky-bottom-reached', [s]);
112
+ } else if(s.currentTop !== null && newTop === s.topSpacing && s.currentTop < newTop) {
113
+ // sticky is started && sticked at topSpacing && overflowing from top just finished
114
+ s.stickyElement.trigger('sticky-bottom-unreached', [s]);
115
+ }
116
+
117
+ s.currentTop = newTop;
118
+ }
119
+
120
+ // Check if sticky has reached end of container and stop sticking
121
+ var stickyWrapperContainer = s.stickyWrapper.parent();
122
+ var unstick = (s.stickyElement.offset().top + s.stickyElement.outerHeight() >= stickyWrapperContainer.offset().top + stickyWrapperContainer.outerHeight()) && (s.stickyElement.offset().top <= s.topSpacing);
123
+
124
+ if( unstick ) {
125
+ s.stickyElement
126
+ .css('position', 'absolute')
127
+ .css('top', '')
128
+ .css('bottom', 0)
129
+ .css('background-color', '')
130
+ .css('z-index', '');
131
+ } else {
132
+ s.stickyElement
133
+ .css('position', 'fixed')
134
+ .css('top', newTop)
135
+ .css('bottom', '')
136
+ .css('background-color', '#fdfdfd')
137
+ .css('border-bottom', '3px solid #ddd')
138
+ .css('z-index', s.zIndex);
139
+ }
140
+ }
141
+ }
142
+ },
143
+ resizer = function() {
144
+ windowHeight = $window.height();
145
+
146
+ for (var i = 0, l = sticked.length; i < l; i++) {
147
+ var s = sticked[i];
148
+ var newWidth = null;
149
+ if (s.getWidthFrom) {
150
+ if (s.responsiveWidth) {
151
+ newWidth = $(s.getWidthFrom).width();
152
+ }
153
+ } else if(s.widthFromWrapper) {
154
+ newWidth = s.stickyWrapper.width();
155
+ }
156
+ if (newWidth != null) {
157
+ s.stickyElement.css('width', newWidth);
158
+ }
159
+ }
160
+ },
161
+ methods = {
162
+ init: function(options) {
163
+ return this.each(function() {
164
+ var o = $.extend({}, defaults, options);
165
+ var stickyElement = $(this);
166
+
167
+ var stickyId = stickyElement.attr('id');
168
+ var wrapperId = stickyId ? stickyId + '-' + defaults.wrapperClassName : defaults.wrapperClassName;
169
+ var wrapper = $('<div></div>')
170
+ .attr('id', wrapperId)
171
+ .addClass(o.wrapperClassName);
172
+
173
+ stickyElement.wrapAll(function() {
174
+ if ($(this).parent("#" + wrapperId).length == 0) {
175
+ return wrapper;
176
+ }
177
+ });
178
+
179
+ var stickyWrapper = stickyElement.parent();
180
+
181
+ if (o.center) {
182
+ stickyWrapper.css({width:stickyElement.outerWidth(),marginLeft:"auto",marginRight:"auto"});
183
+ }
184
+
185
+ if (stickyElement.css("float") === "right") {
186
+ stickyElement.css({"float":"none"}).parent().css({"float":"right"});
187
+ }
188
+
189
+ o.stickyElement = stickyElement;
190
+ o.stickyWrapper = stickyWrapper;
191
+ o.currentTop = null;
192
+
193
+ sticked.push(o);
194
+
195
+ methods.setWrapperHeight(this);
196
+ methods.setupChangeListeners(this);
197
+ });
198
+ },
199
+
200
+ setWrapperHeight: function(stickyElement) {
201
+ var element = $(stickyElement);
202
+ var stickyWrapper = element.parent();
203
+ if (stickyWrapper) {
204
+ stickyWrapper.css('height', element.outerHeight());
205
+ }
206
+ },
207
+
208
+ setupChangeListeners: function(stickyElement) {
209
+ if (window.MutationObserver) {
210
+ var mutationObserver = new window.MutationObserver(function(mutations) {
211
+ if (mutations[0].addedNodes.length || mutations[0].removedNodes.length) {
212
+ methods.setWrapperHeight(stickyElement);
213
+ }
214
+ });
215
+ mutationObserver.observe(stickyElement, {subtree: true, childList: true});
216
+ } else {
217
+ if (window.addEventListener) {
218
+ stickyElement.addEventListener('DOMNodeInserted', function() {
219
+ methods.setWrapperHeight(stickyElement);
220
+ }, false);
221
+ stickyElement.addEventListener('DOMNodeRemoved', function() {
222
+ methods.setWrapperHeight(stickyElement);
223
+ }, false);
224
+ } else if (window.attachEvent) {
225
+ stickyElement.attachEvent('onDOMNodeInserted', function() {
226
+ methods.setWrapperHeight(stickyElement);
227
+ });
228
+ stickyElement.attachEvent('onDOMNodeRemoved', function() {
229
+ methods.setWrapperHeight(stickyElement);
230
+ });
231
+ }
232
+ }
233
+ },
234
+ update: scroller,
235
+ unstick: function(options) {
236
+ return this.each(function() {
237
+ var that = this;
238
+ var unstickyElement = $(that);
239
+
240
+ var removeIdx = -1;
241
+ var i = sticked.length;
242
+ while (i-- > 0) {
243
+ if (sticked[i].stickyElement.get(0) === that) {
244
+ splice.call(sticked,i,1);
245
+ removeIdx = i;
246
+ }
247
+ }
248
+ if(removeIdx !== -1) {
249
+ unstickyElement.unwrap();
250
+ unstickyElement
251
+ .css({
252
+ 'width': '',
253
+ 'position': '',
254
+ 'top': '',
255
+ 'float': '',
256
+ 'background-color': '',
257
+ 'border-bottom': '',
258
+ 'z-index': ''
259
+ })
260
+ ;
261
+ }
262
+ });
263
+ }
264
+ };
265
+
266
+ // should be more efficient than using $window.scroll(scroller) and $window.resize(resizer):
267
+ if (window.addEventListener) {
268
+ window.addEventListener('scroll', scroller, false);
269
+ window.addEventListener('resize', resizer, false);
270
+ } else if (window.attachEvent) {
271
+ window.attachEvent('onscroll', scroller);
272
+ window.attachEvent('onresize', resizer);
273
+ }
274
+
275
+ $.fn.sticky = function(method) {
276
+ if (methods[method]) {
277
+ return methods[method].apply(this, slice.call(arguments, 1));
278
+ } else if (typeof method === 'object' || !method ) {
279
+ return methods.init.apply( this, arguments );
280
+ } else {
281
+ $.error('Method ' + method + ' does not exist on jQuery.sticky');
282
+ }
283
+ };
284
+
285
+ $.fn.unstick = function(method) {
286
+ if (methods[method]) {
287
+ return methods[method].apply(this, slice.call(arguments, 1));
288
+ } else if (typeof method === 'object' || !method ) {
289
+ return methods.unstick.apply( this, arguments );
290
+ } else {
291
+ $.error('Method ' + method + ' does not exist on jQuery.sticky');
292
+ }
293
+ };
294
+ $(function() {
295
+ setTimeout(scroller, 0);
296
+ });
297
+ }));
js/wpm-cpt-script.js CHANGED
@@ -47,7 +47,7 @@ function CountBack(secs) {
47
  }
48
 
49
  function putspan(BackColor, ForeColor) {
50
- document.write("<div class='cptR-rec_countdown'><span id='cntdwn' style='font-family:" + FontFamily + ";background-color:" + BackColor + "; color:" + ForeColor + ";'></span></div>");
51
  }
52
 
53
  if (typeof(BackColor)=="undefined")
47
  }
48
 
49
  function putspan(BackColor, ForeColor) {
50
+ document.write("<div class='cptR-rec_countdown'><span id='cntdwn' style='font-family:" + FontFamily + ";background-color:" + BackColor + "; color:" + ForeColor + "; font-size:" + FontSize + "px;'></span></div>");
51
  }
52
 
53
  if (typeof(BackColor)=="undefined")
js/wpm-script.js CHANGED
@@ -94,3 +94,53 @@ jQuery(document).ready(function() {
94
 
95
  });
96
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
  });
96
 
97
+ jQuery(window).load(function(){
98
+ jQuery("#wpmcontainer").sticky({ topSpacing: 32, zIndex:9980, left:0, getWidthFrom:'#divwpmcontainer' });
99
+ });
100
+
101
+ function AfficherTexte(texte) {
102
+ document.getElementById(texte).style.display = "block";
103
+ }
104
+ function CacherTexte(texte) {
105
+ document.getElementById(texte).style.display = "none";
106
+ }
107
+
108
+ function AfficherCacher(texte) {
109
+ var divid = document.getElementById(texte).style.display;
110
+ if (divid == "block")
111
+ {
112
+ document.getElementById(texte).style.display = "none";
113
+ }
114
+ else
115
+ {
116
+ document.getElementById(texte).style.display = "block";
117
+ }
118
+ }
119
+
120
+ /*jQuery(document).ready(function() {
121
+ var taille = document.getElementById('date_cpt_size').value;
122
+ var augmentation = 1;
123
+ var tailleMax = 90;
124
+ var tailleMin= 10;
125
+
126
+ jQuery('#agrandir').click(function() {
127
+ taille +=1;
128
+ if(taille >= tailleMax)
129
+ {
130
+ taille = tailleMax;
131
+ }
132
+ jQuery('#text').stop().animate({fontSize: taille+"px"},300);
133
+ jQuery('#date_cpt_size').val(taille);
134
+ });
135
+
136
+ jQuery('#diminuer').click(function() {
137
+ taille -=1;
138
+ if(taille <= tailleMin)
139
+ {
140
+ taille = tailleMin;
141
+ }
142
+ jQuery('#text').stop().animate({fontSize: taille+"px"},300);
143
+ jQuery('#date_cpt_size').val(taille);
144
+ });
145
+ });*/
146
+
languages/wp-maintenance-fr_CA.mo DELETED
Binary file
languages/wp-maintenance-fr_CA.po DELETED
@@ -1,737 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: WP Maintenance\n"
4
- "POT-Creation-Date: 2016-09-27 18:17+0200\n"
5
- "PO-Revision-Date: 2016-09-27 18:17+0200\n"
6
- "Last-Translator: Florent Maillefaud <contact@restezconnectes.fr>\n"
7
- "Language-Team: Florent Maillefaud <contact@restezconnectes.fr>\n"
8
- "Language: fr\n"
9
- "MIME-Version: 1.0\n"
10
- "Content-Type: text/plain; charset=UTF-8\n"
11
- "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.9\n"
13
- "X-Poedit-KeywordsList: _e;__\n"
14
- "X-Poedit-Basepath: .\n"
15
- "Plural-Forms: nplurals=2; plural=n>1;\n"
16
- "X-Poedit-SourceCharset: UTF-8\n"
17
- "X-Poedit-SearchPath-0: .\n"
18
-
19
- #: wp-maintenance-admin.php:35
20
- msgid "Options saved."
21
- msgstr "Options sauvegardées."
22
-
23
- #: wp-maintenance-admin.php:74
24
- msgid "The Style Sheet has been reset!"
25
- msgstr "Feuille de style réinitialisée !"
26
-
27
- #: wp-maintenance-admin.php:115
28
- msgid "WP Maintenance Settings"
29
- msgstr "Paramètres WP Maintenance"
30
-
31
- #: wp-maintenance-admin.php:120
32
- msgid "General"
33
- msgstr "Général"
34
-
35
- #: wp-maintenance-admin.php:121
36
- msgid "Colors & Fonts"
37
- msgstr "Couleurs et Fonts"
38
-
39
- #: wp-maintenance-admin.php:122
40
- msgid "Picture"
41
- msgstr "Image"
42
-
43
- #: wp-maintenance-admin.php:123
44
- msgid "CountDown"
45
- msgstr "Compte à rebours"
46
-
47
- #: wp-maintenance-admin.php:124
48
- msgid "CSS Style"
49
- msgstr "Style CSS"
50
-
51
- #: wp-maintenance-admin.php:125 wp-maintenance.php:79
52
- msgid "Settings"
53
- msgstr "Réglages"
54
-
55
- #: wp-maintenance-admin.php:126
56
- msgid "About"
57
- msgstr "A propos"
58
-
59
- #: wp-maintenance-admin.php:139
60
- msgid "Enable maintenance mode:"
61
- msgstr "Activer le mode maintenance :"
62
-
63
- #: wp-maintenance-admin.php:140 wp-maintenance-admin.php:158
64
- #: wp-maintenance-admin.php:168 wp-maintenance-admin.php:235
65
- #: wp-maintenance-admin.php:527 wp-maintenance-admin.php:531
66
- #: wp-maintenance-admin.php:625 wp-maintenance-admin.php:808
67
- msgid "Yes"
68
- msgstr "Oui"
69
-
70
- #: wp-maintenance-admin.php:141 wp-maintenance-admin.php:528
71
- #: wp-maintenance-admin.php:532 wp-maintenance-admin.php:809
72
- msgid "No"
73
- msgstr "Non"
74
-
75
- #: wp-maintenance-admin.php:145
76
- msgid "Title and text for the maintenance page:"
77
- msgstr "Titre et Texte de la page maintenance :"
78
-
79
- #: wp-maintenance-admin.php:146
80
- msgid "Title:"
81
- msgstr "Titre :"
82
-
83
- #: wp-maintenance-admin.php:147 wp-maintenance-admin.php:149
84
- #: wp-maintenance-admin.php:574
85
- msgid "Text:"
86
- msgstr "Texte :"
87
-
88
- #: wp-maintenance-admin.php:148
89
- msgid "Text in the bottom of maintenance page:"
90
- msgstr "Texte du bas de page :"
91
-
92
- #: wp-maintenance-admin.php:150
93
- msgid "Enable login access in the bottom ?"
94
- msgstr "Activer l'accès au Tableau de bord en bas de page ?"
95
-
96
- #: wp-maintenance-admin.php:151
97
- msgid "Enter a text to go to the dashboard:"
98
- msgstr "Entrer une phrase pour aller au tableau de bord :"
99
-
100
- #: wp-maintenance-admin.php:153
101
- msgid "Eg: connect to %DASHBOARD% here!"
102
- msgstr "Ex : Connectez-vous au %DASHBOARD%"
103
-
104
- #: wp-maintenance-admin.php:153
105
- msgid ""
106
- "(%DASHBOARD% will be replaced with the link to the dashboard and the word "
107
- "\"Dashboard\")"
108
- msgstr ""
109
- "(%DASHBOARD% sera remplacé par le mot \"Tableau de bord\" et le lien vers "
110
- "celui-ci)"
111
-
112
- #: wp-maintenance-admin.php:157
113
- msgid "Enable Google Analytics:"
114
- msgstr "Activer Google Analytics :"
115
-
116
- #: wp-maintenance-admin.php:159
117
- msgid "Enter your Google analytics tracking ID here:"
118
- msgstr "Enter votre ID de suivi de Google Analytics ici :"
119
-
120
- #: wp-maintenance-admin.php:161
121
- msgid "Enter your domain URL:"
122
- msgstr "Entrer votre domain :"
123
-
124
- #: wp-maintenance-admin.php:167
125
- msgid "Enable Social Networks:"
126
- msgstr "Activer les icônes des réseaux sociaux :"
127
-
128
- #: wp-maintenance-admin.php:169
129
- msgid "Enter text for the title icons:"
130
- msgstr "Entrez un texte pour la balise title des icônes :"
131
-
132
- #: wp-maintenance-admin.php:170
133
- msgid "Follow me on"
134
- msgstr "Suivez-moi sur"
135
-
136
- #: wp-maintenance-admin.php:172
137
- msgid "Drad and drop the lines to put in the order you want:"
138
- msgstr ""
139
- "Cliquez et glisser les lignes pour mettre dans l'ordre que vous souhaitez :"
140
-
141
- #: wp-maintenance-admin.php:199
142
- msgid "Choose icons size:"
143
- msgstr "Choisissez la taille des icônes :"
144
-
145
- #: wp-maintenance-admin.php:211 wp-maintenance-admin.php:535
146
- msgid "Position:"
147
- msgstr "Position :"
148
-
149
- #: wp-maintenance-admin.php:213
150
- msgid "Top"
151
- msgstr "Haut"
152
-
153
- #: wp-maintenance-admin.php:214
154
- msgid "Bottom"
155
- msgstr "Bas"
156
-
157
- #: wp-maintenance-admin.php:218
158
- msgid "Align:"
159
- msgstr "Alignement :"
160
-
161
- #: wp-maintenance-admin.php:220
162
- msgid "Left"
163
- msgstr "Gauche"
164
-
165
- #: wp-maintenance-admin.php:221
166
- msgid "Center"
167
- msgstr "Centre"
168
-
169
- #: wp-maintenance-admin.php:222
170
- msgid "Right"
171
- msgstr "Droite"
172
-
173
- #: wp-maintenance-admin.php:225
174
- msgid "You have your own icons? Enter the folder name of your theme here:"
175
- msgstr ""
176
- "Vous avez vos propres icônes ? Entrez le nom du dossier de votre thème ici :"
177
-
178
- #: wp-maintenance-admin.php:228
179
- msgid "Reset Social Icon?"
180
- msgstr "Réinitialiser les icônes des réseaux sociaux ?"
181
-
182
- #: wp-maintenance-admin.php:234
183
- msgid "Enable Newletter:"
184
- msgstr "Activer l'encart de newletter :"
185
-
186
- #: wp-maintenance-admin.php:236
187
- msgid "Enter title for the newletter block:"
188
- msgstr "Entrez un titre pour l'encart de la newsletter"
189
-
190
- #: wp-maintenance-admin.php:238
191
- msgid "Enter your newletter shortcode here:"
192
- msgstr "Entrez le Shortcode de la newletter ici :"
193
-
194
- #: wp-maintenance-admin.php:240
195
- msgid "Or enter your newletter iframe code here:"
196
- msgstr "Ou entrez le code iframe de la newsletter ici :"
197
-
198
- #: wp-maintenance-admin.php:262
199
- msgid "Choice general colors:"
200
- msgstr "Choix des couleurs générales :"
201
-
202
- #: wp-maintenance-admin.php:263
203
- msgid "Background page color:"
204
- msgstr "Couleur du fond de page :"
205
-
206
- #: wp-maintenance-admin.php:264
207
- msgid "Header color:"
208
- msgstr "Couleur d'entête"
209
-
210
- #: wp-maintenance-admin.php:268
211
- msgid "Choice texts fonts and colors:"
212
- msgstr "Choix des polices et couleurs des textes :"
213
-
214
- #: wp-maintenance-admin.php:269
215
- msgid "Text color:"
216
- msgstr "Couleur du texte :"
217
-
218
- #: wp-maintenance-admin.php:271
219
- msgid "Title font settings"
220
- msgstr "Paramètres de la police du titre"
221
-
222
- #: wp-maintenance-admin.php:285 wp-maintenance-admin.php:306
223
- #: wp-maintenance-admin.php:345 wp-maintenance-admin.php:376
224
- #: wp-maintenance-admin.php:395
225
- msgid "Size:"
226
- msgstr "Taille :"
227
-
228
- #: wp-maintenance-admin.php:301 wp-maintenance-admin.php:340
229
- msgid "Text font settings"
230
- msgstr "Paramètres de la police du texte"
231
-
232
- #: wp-maintenance-admin.php:322
233
- msgid "Frame settings"
234
- msgstr "Paramètres du cadre"
235
-
236
- #: wp-maintenance-admin.php:324
237
- msgid "Activate"
238
- msgstr "Activé"
239
-
240
- #: wp-maintenance-admin.php:324
241
- msgid "Color:"
242
- msgstr "Couleur :"
243
-
244
- #: wp-maintenance-admin.php:325
245
- msgid "Opacity:"
246
- msgstr "Opacité :"
247
-
248
- #: wp-maintenance-admin.php:327 wp-maintenance-admin.php:523
249
- msgid "Width:"
250
- msgstr "Largeur :"
251
-
252
- #: wp-maintenance-admin.php:335
253
- msgid "Choice fonts and colors bottom page:"
254
- msgstr "Choix des polices et couleurs du bas de page"
255
-
256
- #: wp-maintenance-admin.php:336
257
- msgid "Bottom color:"
258
- msgstr "Couleur du fond :"
259
-
260
- #: wp-maintenance-admin.php:337
261
- msgid "Text bottom color:"
262
- msgstr "Couleur du texte :"
263
-
264
- #: wp-maintenance-admin.php:364
265
- msgid "Choice countdown fonts and colors:"
266
- msgstr "Choix des polices et couleurs du compte à rebours :"
267
-
268
- #: wp-maintenance-admin.php:365
269
- msgid "Countdown text color:"
270
- msgstr "Couleur du texte du compteur :"
271
-
272
- #: wp-maintenance-admin.php:366
273
- msgid "Countdown background color:"
274
- msgstr "Couleur du fond du compteur :"
275
-
276
- #: wp-maintenance-admin.php:371
277
- msgid "Countdown font settings"
278
- msgstr "Paramètres de la police du compte à rebours"
279
-
280
- #: wp-maintenance-admin.php:388
281
- msgid "Choice form color:"
282
- msgstr "Choisir les couleurs du formulaire :"
283
-
284
- #: wp-maintenance-admin.php:409
285
- msgid "Field text color:"
286
- msgstr "Couleur du texte dans les champs :"
287
-
288
- #: wp-maintenance-admin.php:411
289
- msgid "Field border color:"
290
- msgstr "Couleur de bordure des champs :"
291
-
292
- #: wp-maintenance-admin.php:413
293
- msgid "Field background color:"
294
- msgstr "Couleur de fond des champs :"
295
-
296
- #: wp-maintenance-admin.php:416
297
- msgid "Button text color:"
298
- msgstr "Couleur du texte dans le bouton :"
299
-
300
- #: wp-maintenance-admin.php:419
301
- msgid "Button color:"
302
- msgstr "Couleur du bouton :"
303
-
304
- #: wp-maintenance-admin.php:422
305
- msgid "Button color hover:"
306
- msgstr "Couleur du bouton au survol :"
307
-
308
- #: wp-maintenance-admin.php:424
309
- msgid "Button color onclick:"
310
- msgstr "Couleur du bouton au click :"
311
-
312
- #: wp-maintenance-admin.php:454
313
- msgid "Upload a picture"
314
- msgstr "Uploader une image"
315
-
316
- #: wp-maintenance-admin.php:456
317
- msgid "You use this picture:"
318
- msgstr "Image actuelle : "
319
-
320
- #: wp-maintenance-admin.php:458 wp-maintenance-admin.php:476
321
- msgid "Enter a URL or upload an image."
322
- msgstr "Entrez une url ou uploadez une image."
323
-
324
- #: wp-maintenance-admin.php:459 wp-maintenance-admin.php:475
325
- #: wp-maintenance-admin.php:545
326
- msgid "Select or Upload your picture"
327
- msgstr "Sélectionnez / Uploader votre image"
328
-
329
- #: wp-maintenance-admin.php:465
330
- msgid "Upload a background picture"
331
- msgstr "Uploader une image de fond"
332
-
333
- #: wp-maintenance-admin.php:466
334
- msgid "Enable image background"
335
- msgstr "Activer l'image de fond"
336
-
337
- #: wp-maintenance-admin.php:468
338
- msgid "You use this background picture:"
339
- msgstr "Image de fond actuelle : "
340
-
341
- #: wp-maintenance-admin.php:472
342
- msgid "You use this pattern:"
343
- msgstr "Vous utilisez ce pattern : "
344
-
345
- #: wp-maintenance-admin.php:477
346
- msgid "Or choose a pattern:"
347
- msgstr "Ou choisissez un pattern de fond :"
348
-
349
- #: wp-maintenance-admin.php:481
350
- msgid "NO PATTERN"
351
- msgstr "AUCUN PATTERN"
352
-
353
- #: wp-maintenance-admin.php:494
354
- msgid "Background picture options"
355
- msgstr "Options de l'image de fond"
356
-
357
- #: wp-maintenance-admin.php:501
358
- msgid "Fixed"
359
- msgstr "Fixe"
360
-
361
- #: wp-maintenance-admin.php:506
362
- msgid "Slider image options"
363
- msgstr "Options du Slider"
364
-
365
- #: wp-maintenance-admin.php:507
366
- msgid "Enable Slider"
367
- msgstr "Activer le Slider"
368
-
369
- #: wp-maintenance-admin.php:522
370
- msgid "Speed:"
371
- msgstr "Vitesse :"
372
-
373
- #: wp-maintenance-admin.php:526
374
- msgid "Display Auto Slider:"
375
- msgstr "Afficher le Slider en auto :"
376
-
377
- #: wp-maintenance-admin.php:530
378
- msgid "Display button navigation:"
379
- msgstr "Afficher les boutons navigation :"
380
-
381
- #: wp-maintenance-admin.php:537
382
- msgid "Above logo"
383
- msgstr "Au-dessus du logo"
384
-
385
- #: wp-maintenance-admin.php:538
386
- msgid "Below logo"
387
- msgstr "Au-dessous du logo"
388
-
389
- #: wp-maintenance-admin.php:539
390
- msgid "Below title & text"
391
- msgstr "Au-dessous du titre & texte"
392
-
393
- #: wp-maintenance-admin.php:575
394
- msgid "Link:"
395
- msgstr "Lien :"
396
-
397
- #: wp-maintenance-admin.php:578
398
- msgid "Delete this slide"
399
- msgstr "Supprimer ce slide"
400
-
401
- #: wp-maintenance-admin.php:624
402
- msgid "Enable a countdown ?"
403
- msgstr "Activer le compte à rebours ?"
404
-
405
- #: wp-maintenance-admin.php:643
406
- msgid "Select the launch date/time"
407
- msgstr "Sélectionner une date et heure de lancement"
408
-
409
- #: wp-maintenance-admin.php:646
410
- msgid "Enable seconds ?"
411
- msgstr "Afficher les secondes ?"
412
-
413
- #: wp-maintenance-admin.php:647
414
- msgid "Disable maintenance mode at the end of the countdown?"
415
- msgstr "Désactiver le mode maintenance à la fin du compte à rebours ?"
416
-
417
- #: wp-maintenance-admin.php:648
418
- msgid "End message:"
419
- msgstr "Message de fin :"
420
-
421
- #: wp-maintenance-admin.php:664
422
- msgid "Today"
423
- msgstr "Aujourd'hui"
424
-
425
- #: wp-maintenance-admin.php:665
426
- msgid "Delete"
427
- msgstr "Supprimer"
428
-
429
- #: wp-maintenance-admin.php:666 wp-maintenance-admin.php:685
430
- msgid "Close"
431
- msgstr "Fermer"
432
-
433
- #: wp-maintenance-admin.php:669
434
- msgid "Next month"
435
- msgstr "Mois suivant"
436
-
437
- #: wp-maintenance-admin.php:670
438
- msgid "Previous month"
439
- msgstr "Mois précédent"
440
-
441
- #: wp-maintenance-admin.php:671
442
- msgid "Select a month"
443
- msgstr "Sélectionner un mois"
444
-
445
- #: wp-maintenance-admin.php:672
446
- msgid "Select a year"
447
- msgstr "Sélectionner une année"
448
-
449
- #: wp-maintenance-admin.php:715
450
- msgid "CSS style sheet code:"
451
- msgstr "Code style CSS :"
452
-
453
- #: wp-maintenance-admin.php:716
454
- msgid ""
455
- "Edit the CSS sheet of your maintenance page here. Click \"Reset\" and \"Save"
456
- "\" to retrieve the default style sheet."
457
- msgstr ""
458
- "Editer le code CSS de votre page de maintenance ici. Cliquez sur "
459
- "\"Réinitialiser\" et \"Sauvegarder\" pour remettre le style par défaut."
460
-
461
- #: wp-maintenance-admin.php:724
462
- msgid "Markers for colors"
463
- msgstr "Marqueurs pour les couleurs"
464
-
465
- #: wp-maintenance-admin.php:729
466
- msgid "Use this code for text color"
467
- msgstr "Utiliser ce code pour la couleur du texte"
468
-
469
- #: wp-maintenance-admin.php:733
470
- msgid "Use this code for background text color"
471
- msgstr "Utiliser ce code pour la couleur de fond du texte"
472
-
473
- #: wp-maintenance-admin.php:737
474
- msgid "Use this code for background color countdown"
475
- msgstr "Utiliser ce code pour la couleur du fond du compte à rebours"
476
-
477
- #: wp-maintenance-admin.php:741
478
- msgid "Use this code for size countdown"
479
- msgstr "Utiliser ce code pour la taille du compte à rebours"
480
-
481
- #: wp-maintenance-admin.php:745
482
- msgid "Use this code for countdown color"
483
- msgstr "Utiliser ce code pour la couleur du texte du compte à rebours"
484
-
485
- #: wp-maintenance-admin.php:750
486
- msgid "Need CSS code for MailPoet plugin?"
487
- msgstr "Besoin de code CSS pour le plugin MailPoet ?"
488
-
489
- #: wp-maintenance-admin.php:751 wp-maintenance-admin.php:766
490
- msgid "Click for select all"
491
- msgstr "Cliquez pour tout sélectionner"
492
-
493
- #: wp-maintenance-admin.php:765
494
- msgid "Need CSS code for MailChimp plugin?"
495
- msgstr "Besoin de code CSS pour le plugin MailChimp ?"
496
-
497
- #: wp-maintenance-admin.php:787
498
- msgid "Reset default CSS stylesheet ?"
499
- msgstr "Réinitialiser la feuille de style ?"
500
-
501
- #: wp-maintenance-admin.php:806
502
- msgid "Theme maintenance page:"
503
- msgstr "Page maintenance du thème :"
504
-
505
- #: wp-maintenance-admin.php:807
506
- msgid ""
507
- "If you would use your maintenance.php page in your theme folder, click Yes."
508
- msgstr ""
509
- "Si vous souhaitez utiliser votre page maintenance.php dans le dossier de "
510
- "votre thème, cliquez sur Oui."
511
-
512
- #: wp-maintenance-admin.php:810
513
- msgid "You can use this shortcode to include Google Analytics code:"
514
- msgstr ""
515
- "Vous pouvez utiliser ce Shortcode pour include le code Google Analytics sur "
516
- "votre page :"
517
-
518
- #: wp-maintenance-admin.php:810
519
- msgid "You can use this shortcode to include Social Networks icons:"
520
- msgstr ""
521
- "Vous pouvez utiliser ce Shortcode pour include les icons des réseaux sociaux "
522
- "sur votre page :"
523
-
524
- #: wp-maintenance-admin.php:819
525
- msgid "Roles and Capabilities:"
526
- msgstr "Rôles et capacités :"
527
-
528
- #: wp-maintenance-admin.php:820
529
- msgid "Allow the site to display these roles:"
530
- msgstr "Autoriser l'affichage du site à ces rôles :"
531
-
532
- #: wp-maintenance-admin.php:837
533
- msgid "IP autorized:"
534
- msgstr "IP autorisées :"
535
-
536
- #: wp-maintenance-admin.php:838
537
- msgid ""
538
- "Allow the site to display these IP addresses. Please, enter one IP address "
539
- "by line:"
540
- msgstr ""
541
- "Autoriser l'affichage du site à ces adresses IP. Merci d'entrer 1 adresse IP "
542
- "par ligne : "
543
-
544
- #: wp-maintenance-admin.php:843
545
- msgid "Header Code:"
546
- msgstr "Code pour le header"
547
-
548
- #: wp-maintenance-admin.php:844
549
- msgid ""
550
- "The following code will add to the <head> tag. Useful if you need to add "
551
- "additional scripts such as CSS or JS."
552
- msgstr ""
553
- "Le code suivant va être ajouter à la balise <head>. Très utile si vous avez "
554
- "besoin d'ajouter des scripts supplémentaires tels que CSS ou JS."
555
-
556
- #: wp-maintenance-admin.php:876
557
- msgid ""
558
- "This plugin has been developed for you for free by <a href=\"http://www."
559
- "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is royalty "
560
- "free, you can take it, modify it, distribute it as you see fit.<br /><br /"
561
- ">It would be desirable that I can get feedback on your potential changes to "
562
- "improve this plugin for all."
563
- msgstr ""
564
- "Cette extension a été développée gratuitement pour vous par <a href=\"http://"
565
- "www.restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. Elle est "
566
- "libre de droits, vous pouvez la prendre, la modifier, la distribuer comme "
567
- "bon vous semble.<br /><br />Il serait néanmoins souhaitable que je puisse "
568
- "avoir des retours sur vos éventuelles modifications afin d'améliorer cette "
569
- "extension pour tous."
570
-
571
- #: wp-maintenance-admin.php:880
572
- msgid "Visit"
573
- msgstr "Visitez le site web de"
574
-
575
- #: wp-maintenance-admin.php:880
576
- msgid ""
577
- "try the demo of the plugin, talk about this plugin to your surroundings!"
578
- msgstr "essayez la démo de cette extension et parlez-en à votre entourage !"
579
-
580
- #: wp-maintenance-admin.php:885
581
- msgid ""
582
- "If you want Donate (French Paypal) for my current and future developments:"
583
- msgstr ""
584
- "Si vous souhaitez me soutenir pour mes développements actuels et futurs :"
585
-
586
- #: wp-maintenance-admin.php:905
587
- msgid "WP Maintenance"
588
- msgstr "WP Maintenance"
589
-
590
- #: wp-maintenance-admin.php:905
591
- msgid "is brought to you by"
592
- msgstr "vous est proposé par"
593
-
594
- #: wp-maintenance-admin.php:905
595
- msgid "If you found this plugin useful"
596
- msgstr "Si vous avez trouvé cette extension utile,"
597
-
598
- #: wp-maintenance-admin.php:905
599
- msgid "give it 5 &#9733; on WordPress.org"
600
- msgstr "donnez-lui 5 &#9733; sur WordPress.org"
601
-
602
- #: wp-maintenance.php:125
603
- msgid "Maintenance mode activated!"
604
- msgstr "Maintenance activée !"
605
-
606
- #: wp-maintenance.php:162
607
- msgid "This site is down for maintenance"
608
- msgstr "Ce site est en maintenance"
609
-
610
- #: wp-maintenance.php:163
611
- msgid "Come back quickly !"
612
- msgstr "Revenez vite nous voir !"
613
-
614
- #: wp-maintenance.php:235 wp-maintenance.php:237
615
- msgid "Options for the maintenance page"
616
- msgstr "Options pour la page maintenance"
617
-
618
- #: wp-maintenance.php:263
619
- msgid "Choose This Image"
620
- msgstr "Choisir cette image"
621
-
622
- #: wp-maintenance.php:264
623
- msgid "Choose Image"
624
- msgstr "Choisissez une image"
625
-
626
- #: wp-maintenance.php:715
627
- msgid "Dashboard"
628
- msgstr "Tableau de bord"
629
-
630
- #: wp-maintenance.php:814
631
- msgid "Days"
632
- msgstr "Jours"
633
-
634
- #: wp-maintenance.php:814
635
- msgid "Hours"
636
- msgstr "Heures"
637
-
638
- #: wp-maintenance.php:814
639
- msgid "Minutes"
640
- msgstr "Minutes"
641
-
642
- #: wp-maintenance.php:816
643
- msgid "Seconds"
644
- msgstr "Secondes"
645
-
646
- #: wp-maintenance.php:1008
647
- msgid "Previous"
648
- msgstr "Précédent"
649
-
650
- #: wp-maintenance.php:1009
651
- msgid "Next"
652
- msgstr "Suivant"
653
-
654
- #~ msgid "Save this settings"
655
- #~ msgstr "Sauvegarder ces paramètres"
656
-
657
- #~ msgid ""
658
- #~ "This plugin has been developed for you for free by <a href=\"http://www."
659
- #~ "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</ a>. It is "
660
- #~ "royalty free, you can take it, modify it, distribute it as you see fit. "
661
- #~ "<br /> <br />It would be desirable that I can get feedback on your "
662
- #~ "potential changes to improve this plugin for all."
663
- #~ msgstr ""
664
- #~ "Cette extension a été développée gratuitement pour vous par <a href="
665
- #~ "\"http://www.restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</"
666
- #~ "a>. Elle est libre de droits, vous pouvez la prendre, la modifier, la "
667
- #~ "distribuer comme bon vous semble.<br /><br />Il serait néanmoins "
668
- #~ "souhaitable que je puisse avoir des retours sur vos éventuelles "
669
- #~ "modifications afin d'améliorer cette extension pour tous."
670
-
671
- #~ msgid "WP Maintenance is brought to you by"
672
- #~ msgstr "WP Maintenance est un plugin proposé par"
673
-
674
- #~ msgid "Font size:"
675
- #~ msgstr "Taille de la police :"
676
-
677
- #~ msgid "Enter the launch date"
678
- #~ msgstr "Entrez la date de lancement"
679
-
680
- #~ msgid "Please, enter one IP address by line:"
681
- #~ msgstr "Merci d'entrer 1 adresse IP par ligne : "
682
-
683
- #~ msgid "Enter title for the admin access login block:"
684
- #~ msgstr "Entrer une phrase pour aller au tableau de bord"
685
-
686
- #~ msgid ""
687
- #~ "website, try the demo of the plugin, speak what this plugin to your "
688
- #~ "surroundings!"
689
- #~ msgstr ""
690
- #~ ", essayer la démonstration du plugin, parlez ce ce plugin à votre "
691
- #~ "entourage !"
692
-
693
- #~ msgid "Demo mode:"
694
- #~ msgstr "Mode démo :"
695
-
696
- #~ msgid "Be careful, in demo mode, the plugin can be modified by all users"
697
- #~ msgstr ""
698
- #~ "Attention, en mode démo, le plugin peut-être modifié par tous les "
699
- #~ "utilisateurs"
700
-
701
- #~ msgid "Active this plugin in demo mode?"
702
- #~ msgstr "Activer ce plugin en mode démo ?"
703
-
704
- #~ msgid "Choice texts colors:"
705
- #~ msgstr "Choix des couleurs des textes :"
706
-
707
- #~ msgid "Choice countdown colors:"
708
- #~ msgstr "Choix des couleurs du compte à rebours :"
709
-
710
- #~ msgid "Choice texts bottom colors:"
711
- #~ msgstr "Choix des couleurs du bas de page :"
712
-
713
- #~ msgid "Text font on the bottom page:"
714
- #~ msgstr "Paramètres de la police du texte du bas de page :"
715
-
716
- #~ msgid "Go to Admin Panel"
717
- #~ msgstr "Aller au panneau d'admin"
718
-
719
- #~ msgid "Choose those that do not display the maintenance page."
720
- #~ msgstr "Choisissez ceux qui n'auront pas la page de maintenance"
721
-
722
- #~ msgid "Note : "
723
- #~ msgstr "Note :"
724
-
725
- #~ msgid "Use this code for add color texte"
726
- #~ msgstr "Utiliser ce code pour la couleur du texte"
727
-
728
- #, fuzzy
729
- #~ msgid ""
730
- #~ "If this parameter is set to Yes, this is the maintenance.php page of your "
731
- #~ "theme to be displayed"
732
- #~ msgstr ""
733
- #~ "Si ce paramètre est sur Oui, c'est la page maintenance.php de votre thème "
734
- #~ "qui sera affichée"
735
-
736
- #~ msgid "Day"
737
- #~ msgstr "Jour"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/wp-maintenance-fr_FR.mo CHANGED
Binary file
languages/wp-maintenance-fr_FR.po CHANGED
@@ -1,107 +1,269 @@
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: WP Maintenance\n"
4
- "POT-Creation-Date: 2016-12-23 09:50+0100\n"
5
- "PO-Revision-Date: 2016-12-23 09:51+0100\n"
6
- "Last-Translator: Florent Maillefaud <contact@restezconnectes.fr>\n"
7
- "Language-Team: Florent Maillefaud <contact@restezconnectes.fr>\n"
8
- "Language: fr\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "X-Generator: Poedit 1.8.11\n"
13
- "X-Poedit-KeywordsList: _e;__\n"
14
- "X-Poedit-Basepath: .\n"
15
- "Plural-Forms: nplurals=2; plural=n>1;\n"
 
16
  "X-Poedit-SourceCharset: UTF-8\n"
 
 
 
17
  "X-Poedit-SearchPath-0: .\n"
 
18
 
19
- #: wp-maintenance-admin.php:35
20
- msgid "Options saved."
21
- msgstr "Options sauvegardées."
22
 
23
- #: wp-maintenance-admin.php:74
24
- msgid "The Style Sheet has been reset!"
25
- msgstr "Feuille de style réinitialisée !"
26
 
27
- #: wp-maintenance-admin.php:115
28
- msgid "WP Maintenance Settings"
29
- msgstr "Paramètres WP Maintenance"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
- #: wp-maintenance-admin.php:120
 
32
  msgid "General"
33
  msgstr "Général"
34
 
35
- #: wp-maintenance-admin.php:121
 
36
  msgid "Colors & Fonts"
37
- msgstr "Couleurs et Fonts"
38
 
39
- #: wp-maintenance-admin.php:122
40
- msgid "Picture"
41
- msgstr "Image"
42
 
43
- #: wp-maintenance-admin.php:123
44
  msgid "CountDown"
45
  msgstr "Compte à rebours"
46
 
47
- #: wp-maintenance-admin.php:124
 
48
  msgid "CSS Style"
49
  msgstr "Style CSS"
50
 
51
- #: wp-maintenance-admin.php:125 wp-maintenance.php:51
52
- msgid "Settings"
53
- msgstr "Réglages"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- #: wp-maintenance-admin.php:126
 
 
 
 
 
 
 
 
56
  msgid "About"
57
  msgstr "A propos"
58
 
59
- #: wp-maintenance-admin.php:139
60
  msgid "Enable maintenance mode:"
61
  msgstr "Activer le mode maintenance :"
62
 
63
- #: wp-maintenance-admin.php:140 wp-maintenance-admin.php:158
64
- #: wp-maintenance-admin.php:168 wp-maintenance-admin.php:235
65
- #: wp-maintenance-admin.php:529 wp-maintenance-admin.php:533
66
- #: wp-maintenance-admin.php:627 wp-maintenance-admin.php:810
 
 
 
 
 
 
 
 
 
 
67
  msgid "Yes"
68
  msgstr "Oui"
69
 
70
- #: wp-maintenance-admin.php:141 wp-maintenance-admin.php:530
71
- #: wp-maintenance-admin.php:534 wp-maintenance-admin.php:811
 
 
 
 
 
 
 
 
 
 
72
  msgid "No"
73
  msgstr "Non"
74
 
75
- #: wp-maintenance-admin.php:145
76
  msgid "Title and text for the maintenance page:"
77
  msgstr "Titre et Texte de la page maintenance :"
78
 
79
- #: wp-maintenance-admin.php:146
80
  msgid "Title:"
81
  msgstr "Titre :"
82
 
83
- #: wp-maintenance-admin.php:147 wp-maintenance-admin.php:149
84
- #: wp-maintenance-admin.php:576
 
85
  msgid "Text:"
86
  msgstr "Texte :"
87
 
88
- #: wp-maintenance-admin.php:148
89
  msgid "Text in the bottom of maintenance page:"
90
- msgstr "Texte du bas de page :"
91
 
92
- #: wp-maintenance-admin.php:150
93
  msgid "Enable login access in the bottom ?"
94
- msgstr "Activer l'accès au Tableau de bord en bas de page ?"
95
 
96
- #: wp-maintenance-admin.php:151
97
  msgid "Enter a text to go to the dashboard:"
98
  msgstr "Entrer une phrase pour aller au tableau de bord :"
99
 
100
- #: wp-maintenance-admin.php:153
101
  msgid "Eg: connect to %DASHBOARD% here!"
102
- msgstr "Ex : Connectez-vous au %DASHBOARD%"
103
 
104
- #: wp-maintenance-admin.php:153
105
  msgid ""
106
  "(%DASHBOARD% will be replaced with the link to the dashboard and the word "
107
  "\"Dashboard\")"
@@ -109,348 +271,357 @@ msgstr ""
109
  "(%DASHBOARD% sera remplacé par le mot \"Tableau de bord\" et le lien vers "
110
  "celui-ci)"
111
 
112
- #: wp-maintenance-admin.php:157
113
  msgid "Enable Google Analytics:"
114
  msgstr "Activer Google Analytics :"
115
 
116
- #: wp-maintenance-admin.php:159
117
  msgid "Enter your Google analytics tracking ID here:"
118
  msgstr "Enter votre ID de suivi de Google Analytics ici :"
119
 
120
- #: wp-maintenance-admin.php:161
121
  msgid "Enter your domain URL:"
122
- msgstr "Entrer votre domain :"
123
 
124
- #: wp-maintenance-admin.php:167
125
  msgid "Enable Social Networks:"
126
- msgstr "Activer les icônes des réseaux sociaux :"
127
 
128
- #: wp-maintenance-admin.php:169
129
  msgid "Enter text for the title icons:"
130
  msgstr "Entrez un texte pour la balise title des icônes :"
131
 
132
- #: wp-maintenance-admin.php:170
133
  msgid "Follow me on"
134
  msgstr "Suivez-moi sur"
135
 
136
- #: wp-maintenance-admin.php:172
137
  msgid "Drad and drop the lines to put in the order you want:"
138
  msgstr ""
139
  "Cliquez et glisser les lignes pour mettre dans l'ordre que vous souhaitez :"
140
 
141
- #: wp-maintenance-admin.php:199
142
  msgid "Choose icons size:"
143
  msgstr "Choisissez la taille des icônes :"
144
 
145
- #: wp-maintenance-admin.php:211 wp-maintenance-admin.php:537
 
146
  msgid "Position:"
147
  msgstr "Position :"
148
 
149
- #: wp-maintenance-admin.php:213
150
  msgid "Top"
151
  msgstr "Haut"
152
 
153
- #: wp-maintenance-admin.php:214
154
  msgid "Bottom"
155
  msgstr "Bas"
156
 
157
- #: wp-maintenance-admin.php:218
158
  msgid "Align:"
159
  msgstr "Alignement :"
160
 
161
- #: wp-maintenance-admin.php:220
162
  msgid "Left"
163
  msgstr "Gauche"
164
 
165
- #: wp-maintenance-admin.php:221
166
  msgid "Center"
167
  msgstr "Centre"
168
 
169
- #: wp-maintenance-admin.php:222
170
  msgid "Right"
171
  msgstr "Droite"
172
 
173
- #: wp-maintenance-admin.php:225
174
  msgid "You have your own icons? Enter the folder name of your theme here:"
175
  msgstr ""
176
  "Vous avez vos propres icônes ? Entrez le nom du dossier de votre thème ici :"
177
 
178
- #: wp-maintenance-admin.php:228
179
  msgid "Reset Social Icon?"
180
  msgstr "Réinitialiser les icônes des réseaux sociaux ?"
181
 
182
- #: wp-maintenance-admin.php:234
183
  msgid "Enable Newletter:"
184
  msgstr "Activer l'encart de newletter :"
185
 
186
- #: wp-maintenance-admin.php:236
187
  msgid "Enter title for the newletter block:"
188
- msgstr "Entrez un titre pour l'encart de la newsletter"
189
 
190
- #: wp-maintenance-admin.php:238
191
  msgid "Enter your newletter shortcode here:"
192
  msgstr "Entrez le Shortcode de la newletter ici :"
193
 
194
- #: wp-maintenance-admin.php:240
195
  msgid "Or enter your newletter iframe code here:"
196
  msgstr "Ou entrez le code iframe de la newsletter ici :"
197
 
198
- #: wp-maintenance-admin.php:262
199
  msgid "Choice general colors:"
200
  msgstr "Choix des couleurs générales :"
201
 
202
- #: wp-maintenance-admin.php:263
203
  msgid "Background page color:"
204
  msgstr "Couleur du fond de page :"
205
 
206
- #: wp-maintenance-admin.php:264
207
  msgid "Header color:"
208
- msgstr "Couleur d'entête"
209
 
210
- #: wp-maintenance-admin.php:268
211
  msgid "Choice texts fonts and colors:"
212
  msgstr "Choix des polices et couleurs des textes :"
213
 
214
- #: wp-maintenance-admin.php:269
215
  msgid "Text color:"
216
  msgstr "Couleur du texte :"
217
 
218
- #: wp-maintenance-admin.php:271
219
  msgid "Title font settings"
220
  msgstr "Paramètres de la police du titre"
221
 
222
- #: wp-maintenance-admin.php:285 wp-maintenance-admin.php:306
223
- #: wp-maintenance-admin.php:345 wp-maintenance-admin.php:376
224
- #: wp-maintenance-admin.php:395
 
 
225
  msgid "Size:"
226
  msgstr "Taille :"
227
 
228
- #: wp-maintenance-admin.php:301 wp-maintenance-admin.php:340
 
229
  msgid "Text font settings"
230
  msgstr "Paramètres de la police du texte"
231
 
232
- #: wp-maintenance-admin.php:322
233
  msgid "Frame settings"
234
  msgstr "Paramètres du cadre"
235
 
236
- #: wp-maintenance-admin.php:324
237
  msgid "Activate"
238
  msgstr "Activé"
239
 
240
- #: wp-maintenance-admin.php:324
241
  msgid "Color:"
242
  msgstr "Couleur :"
243
 
244
- #: wp-maintenance-admin.php:325
245
  msgid "Opacity:"
246
  msgstr "Opacité :"
247
 
248
- #: wp-maintenance-admin.php:327 wp-maintenance-admin.php:525
 
249
  msgid "Width:"
250
  msgstr "Largeur :"
251
 
252
- #: wp-maintenance-admin.php:335
253
  msgid "Choice fonts and colors bottom page:"
254
- msgstr "Choix des polices et couleurs du bas de page"
255
 
256
- #: wp-maintenance-admin.php:336
257
  msgid "Bottom color:"
258
  msgstr "Couleur du fond :"
259
 
260
- #: wp-maintenance-admin.php:337
261
  msgid "Text bottom color:"
262
  msgstr "Couleur du texte :"
263
 
264
- #: wp-maintenance-admin.php:364
265
  msgid "Choice countdown fonts and colors:"
266
  msgstr "Choix des polices et couleurs du compte à rebours :"
267
 
268
- #: wp-maintenance-admin.php:365
269
  msgid "Countdown text color:"
270
  msgstr "Couleur du texte du compteur :"
271
 
272
- #: wp-maintenance-admin.php:366
273
  msgid "Countdown background color:"
274
  msgstr "Couleur du fond du compteur :"
275
 
276
- #: wp-maintenance-admin.php:371
277
  msgid "Countdown font settings"
278
  msgstr "Paramètres de la police du compte à rebours"
279
 
280
- #: wp-maintenance-admin.php:388
281
  msgid "Choice form color:"
282
  msgstr "Choisir les couleurs du formulaire :"
283
 
284
- #: wp-maintenance-admin.php:409
285
  msgid "Field text color:"
286
  msgstr "Couleur du texte dans les champs :"
287
 
288
- #: wp-maintenance-admin.php:411
289
  msgid "Field border color:"
290
  msgstr "Couleur de bordure des champs :"
291
 
292
- #: wp-maintenance-admin.php:413
293
  msgid "Field background color:"
294
  msgstr "Couleur de fond des champs :"
295
 
296
- #: wp-maintenance-admin.php:416
297
  msgid "Button text color:"
298
  msgstr "Couleur du texte dans le bouton :"
299
 
300
- #: wp-maintenance-admin.php:419
301
  msgid "Button color:"
302
  msgstr "Couleur du bouton :"
303
 
304
- #: wp-maintenance-admin.php:422
305
  msgid "Button color hover:"
306
  msgstr "Couleur du bouton au survol :"
307
 
308
- #: wp-maintenance-admin.php:424
309
  msgid "Button color onclick:"
310
  msgstr "Couleur du bouton au click :"
311
 
312
- #: wp-maintenance-admin.php:456
313
  msgid "Upload a picture"
314
- msgstr "Uploader une image"
315
 
316
- #: wp-maintenance-admin.php:458
317
  msgid "You use this picture:"
318
- msgstr "Image actuelle : "
319
 
320
- #: wp-maintenance-admin.php:460 wp-maintenance-admin.php:478
 
321
  msgid "Enter a URL or upload an image."
322
- msgstr "Entrez une url ou uploadez une image."
323
 
324
- #: wp-maintenance-admin.php:461 wp-maintenance-admin.php:477
325
- #: wp-maintenance-admin.php:547
 
326
  msgid "Select or Upload your picture"
327
- msgstr "Sélectionnez / Uploader votre image"
328
 
329
- #: wp-maintenance-admin.php:467
330
  msgid "Upload a background picture"
331
- msgstr "Uploader une image de fond"
332
 
333
- #: wp-maintenance-admin.php:468
334
  msgid "Enable image background"
335
  msgstr "Activer l'image de fond"
336
 
337
- #: wp-maintenance-admin.php:470
338
  msgid "You use this background picture:"
339
- msgstr "Image de fond actuelle : "
340
 
341
- #: wp-maintenance-admin.php:474
342
  msgid "You use this pattern:"
343
- msgstr "Vous utilisez ce pattern : "
344
 
345
- #: wp-maintenance-admin.php:479
346
  msgid "Or choose a pattern:"
347
  msgstr "Ou choisissez un pattern de fond :"
348
 
349
- #: wp-maintenance-admin.php:483
350
  msgid "NO PATTERN"
351
  msgstr "AUCUN PATTERN"
352
 
353
- #: wp-maintenance-admin.php:496
354
  msgid "Background picture options"
355
  msgstr "Options de l'image de fond"
356
 
357
- #: wp-maintenance-admin.php:503
358
  msgid "Fixed"
359
  msgstr "Fixe"
360
 
361
- #: wp-maintenance-admin.php:508
362
  msgid "Slider image options"
363
  msgstr "Options du Slider"
364
 
365
- #: wp-maintenance-admin.php:509
366
  msgid "Enable Slider"
367
  msgstr "Activer le Slider"
368
 
369
- #: wp-maintenance-admin.php:524
370
  msgid "Speed:"
371
  msgstr "Vitesse :"
372
 
373
- #: wp-maintenance-admin.php:528
374
  msgid "Display Auto Slider:"
375
  msgstr "Afficher le Slider en auto :"
376
 
377
- #: wp-maintenance-admin.php:532
378
  msgid "Display button navigation:"
379
  msgstr "Afficher les boutons navigation :"
380
 
381
- #: wp-maintenance-admin.php:539
382
  msgid "Above logo"
383
  msgstr "Au-dessus du logo"
384
 
385
- #: wp-maintenance-admin.php:540
386
  msgid "Below logo"
387
  msgstr "Au-dessous du logo"
388
 
389
- #: wp-maintenance-admin.php:541
390
  msgid "Below title & text"
391
  msgstr "Au-dessous du titre & texte"
392
 
393
- #: wp-maintenance-admin.php:577
394
  msgid "Link:"
395
  msgstr "Lien :"
396
 
397
- #: wp-maintenance-admin.php:580
398
  msgid "Delete this slide"
399
  msgstr "Supprimer ce slide"
400
 
401
- #: wp-maintenance-admin.php:626
402
  msgid "Enable a countdown ?"
403
  msgstr "Activer le compte à rebours ?"
404
 
405
- #: wp-maintenance-admin.php:645
406
  msgid "Select the launch date/time"
407
  msgstr "Sélectionner une date et heure de lancement"
408
 
409
- #: wp-maintenance-admin.php:648
410
  msgid "Enable seconds ?"
411
  msgstr "Afficher les secondes ?"
412
 
413
- #: wp-maintenance-admin.php:649
414
  msgid "Disable maintenance mode at the end of the countdown?"
415
  msgstr "Désactiver le mode maintenance à la fin du compte à rebours ?"
416
 
417
- #: wp-maintenance-admin.php:650
418
  msgid "End message:"
419
  msgstr "Message de fin :"
420
 
421
- #: wp-maintenance-admin.php:666
422
  msgid "Today"
423
  msgstr "Aujourd'hui"
424
 
425
- #: wp-maintenance-admin.php:667
426
  msgid "Delete"
427
  msgstr "Supprimer"
428
 
429
- #: wp-maintenance-admin.php:668 wp-maintenance-admin.php:687
 
 
430
  msgid "Close"
431
  msgstr "Fermer"
432
 
433
- #: wp-maintenance-admin.php:671
434
  msgid "Next month"
435
  msgstr "Mois suivant"
436
 
437
- #: wp-maintenance-admin.php:672
438
  msgid "Previous month"
439
  msgstr "Mois précédent"
440
 
441
- #: wp-maintenance-admin.php:673
442
  msgid "Select a month"
443
  msgstr "Sélectionner un mois"
444
 
445
- #: wp-maintenance-admin.php:674
446
  msgid "Select a year"
447
  msgstr "Sélectionner une année"
448
 
449
- #: wp-maintenance-admin.php:717
450
  msgid "CSS style sheet code:"
451
  msgstr "Code style CSS :"
452
 
453
- #: wp-maintenance-admin.php:718
454
  msgid ""
455
  "Edit the CSS sheet of your maintenance page here. Click \"Reset\" and \"Save"
456
  "\" to retrieve the default style sheet."
@@ -458,94 +629,95 @@ msgstr ""
458
  "Editer le code CSS de votre page de maintenance ici. Cliquez sur "
459
  "\"Réinitialiser\" et \"Sauvegarder\" pour remettre le style par défaut."
460
 
461
- #: wp-maintenance-admin.php:726
462
  msgid "Markers for colors"
463
  msgstr "Marqueurs pour les couleurs"
464
 
465
- #: wp-maintenance-admin.php:731
466
  msgid "Use this code for text color"
467
  msgstr "Utiliser ce code pour la couleur du texte"
468
 
469
- #: wp-maintenance-admin.php:735
470
  msgid "Use this code for background text color"
471
  msgstr "Utiliser ce code pour la couleur de fond du texte"
472
 
473
- #: wp-maintenance-admin.php:739
474
  msgid "Use this code for background color countdown"
475
  msgstr "Utiliser ce code pour la couleur du fond du compte à rebours"
476
 
477
- #: wp-maintenance-admin.php:743
478
  msgid "Use this code for size countdown"
479
  msgstr "Utiliser ce code pour la taille du compte à rebours"
480
 
481
- #: wp-maintenance-admin.php:747
482
  msgid "Use this code for countdown color"
483
  msgstr "Utiliser ce code pour la couleur du texte du compte à rebours"
484
 
485
- #: wp-maintenance-admin.php:752
486
  msgid "Need CSS code for MailPoet plugin?"
487
  msgstr "Besoin de code CSS pour le plugin MailPoet ?"
488
 
489
- #: wp-maintenance-admin.php:753 wp-maintenance-admin.php:768
 
490
  msgid "Click for select all"
491
  msgstr "Cliquez pour tout sélectionner"
492
 
493
- #: wp-maintenance-admin.php:767
494
  msgid "Need CSS code for MailChimp plugin?"
495
  msgstr "Besoin de code CSS pour le plugin MailChimp ?"
496
 
497
- #: wp-maintenance-admin.php:789
498
  msgid "Reset default CSS stylesheet ?"
499
  msgstr "Réinitialiser la feuille de style ?"
500
 
501
- #: wp-maintenance-admin.php:808
502
  msgid "Theme maintenance page:"
503
  msgstr "Page maintenance du thème :"
504
 
505
- #: wp-maintenance-admin.php:809
506
  msgid ""
507
  "If you would use your maintenance.php page in your theme folder, click Yes."
508
  msgstr ""
509
  "Si vous souhaitez utiliser votre page maintenance.php dans le dossier de "
510
  "votre thème, cliquez sur Oui."
511
 
512
- #: wp-maintenance-admin.php:812
513
  msgid "You can use this shortcode to include Google Analytics code:"
514
  msgstr ""
515
  "Vous pouvez utiliser ce Shortcode pour include le code Google Analytics sur "
516
  "votre page :"
517
 
518
- #: wp-maintenance-admin.php:812
519
  msgid "You can use this shortcode to include Social Networks icons:"
520
  msgstr ""
521
  "Vous pouvez utiliser ce Shortcode pour include les icons des réseaux sociaux "
522
  "sur votre page :"
523
 
524
- #: wp-maintenance-admin.php:821
525
  msgid "Roles and Capabilities:"
526
  msgstr "Rôles et capacités :"
527
 
528
- #: wp-maintenance-admin.php:822
529
  msgid "Allow the site to display these roles:"
530
  msgstr "Autoriser l'affichage du site à ces rôles :"
531
 
532
- #: wp-maintenance-admin.php:839
533
  msgid "IP autorized:"
534
  msgstr "IP autorisées :"
535
 
536
- #: wp-maintenance-admin.php:840
537
  msgid ""
538
  "Allow the site to display these IP addresses. Please, enter one IP address "
539
  "by line:"
540
  msgstr ""
541
  "Autoriser l'affichage du site à ces adresses IP. Merci d'entrer 1 adresse IP "
542
- "par ligne : "
543
 
544
- #: wp-maintenance-admin.php:846
545
  msgid "ID pages autorized:"
546
  msgstr "ID de pages autorisées :"
547
 
548
- #: wp-maintenance-admin.php:847
549
  msgid ""
550
  "Allow the site to display these ID pages. Please, enter the ID pages "
551
  "separate with comma :"
@@ -553,11 +725,11 @@ msgstr ""
553
  "Autoriser le site à afficher des pages d'ID. Merci d'entrer les ID de pages "
554
  "séparées par une virgule :"
555
 
556
- #: wp-maintenance-admin.php:852
557
  msgid "Header Code:"
558
- msgstr "Code pour le header"
559
 
560
- #: wp-maintenance-admin.php:853
561
  msgid ""
562
  "The following code will add to the <head> tag. Useful if you need to add "
563
  "additional scripts such as CSS or JS."
@@ -565,7 +737,7 @@ msgstr ""
565
  "Le code suivant va être ajouter à la balise <head>. Très utile si vous avez "
566
  "besoin d'ajouter des scripts supplémentaires tels que CSS ou JS."
567
 
568
- #: wp-maintenance-admin.php:885
569
  msgid ""
570
  "This plugin has been developed for you for free by <a href=\"https://"
571
  "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is royalty "
@@ -580,184 +752,161 @@ msgstr ""
580
  "puisse avoir des retours sur vos éventuelles modifications afin d'améliorer "
581
  "cette extension pour tous."
582
 
583
- #: wp-maintenance-admin.php:889
584
- msgid "Visit"
585
- msgstr "Visitez le site web de"
586
-
587
- #: wp-maintenance-admin.php:889
588
- msgid ""
589
- "try the demo of the plugin, talk about this plugin to your surroundings!"
590
- msgstr "essayez la démo de cette extension et parlez-en à votre entourage !"
591
-
592
- #: wp-maintenance-admin.php:894
593
  msgid ""
594
  "If you want Donate (French Paypal) for my current and future developments:"
595
  msgstr ""
596
  "Si vous souhaitez me soutenir pour mes développements actuels et futurs :"
597
 
598
- #: wp-maintenance-admin.php:913
599
- msgid "WP Maintenance"
600
- msgstr "WP Maintenance"
601
 
602
- #: wp-maintenance-admin.php:913
603
- msgid "is brought to you by"
604
- msgstr "vous est proposé par"
 
605
 
606
- #: wp-maintenance-admin.php:913
607
- msgid "If you found this plugin useful"
608
- msgstr "Si vous avez trouvé cette extension utile,"
609
 
610
- #: wp-maintenance-admin.php:913
611
- msgid "give it 5 &#9733; on WordPress.org"
612
- msgstr "donnez-lui 5 &#9733; sur WordPress.org"
 
613
 
614
- #: wp-maintenance.php:97
615
- msgid "Maintenance mode activated!"
616
- msgstr "Maintenance activée !"
617
 
618
- #: wp-maintenance.php:134
619
- msgid "This site is down for maintenance"
620
- msgstr "Ce site est en maintenance"
621
 
622
- #: wp-maintenance.php:135
623
- msgid "Come back quickly !"
624
- msgstr "Revenez vite nous voir !"
625
 
626
- #: wp-maintenance.php:207 wp-maintenance.php:209
627
- msgid "Options for the maintenance page"
628
- msgstr "Options pour la page maintenance"
629
 
630
- #: wp-maintenance.php:235
631
- msgid "Choose This Image"
632
- msgstr "Choisir cette image"
633
 
634
- #: wp-maintenance.php:236
635
- msgid "Choose Image"
636
- msgstr "Choisissez une image"
637
 
638
- #: wp-maintenance.php:698
639
- msgid "Dashboard"
640
- msgstr "Tableau de bord"
641
 
642
- #: wp-maintenance.php:797
643
- msgid "Days"
644
- msgstr "Jours"
645
 
646
- #: wp-maintenance.php:797
647
- msgid "Hours"
648
- msgstr "Heures"
649
 
650
- #: wp-maintenance.php:797
651
- msgid "Minutes"
652
- msgstr "Minutes"
653
 
654
- #: wp-maintenance.php:799
655
- msgid "Seconds"
656
- msgstr "Secondes"
657
 
658
- #: wp-maintenance.php:991
659
- msgid "Previous"
660
- msgstr "Précédent"
661
 
662
- #: wp-maintenance.php:992
663
- msgid "Next"
664
- msgstr "Suivant"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
665
 
666
- #~ msgid ""
667
- #~ "This plugin has been developed for you for free by <a href=\"http://www."
668
- #~ "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is "
669
- #~ "royalty free, you can take it, modify it, distribute it as you see fit."
670
- #~ "<br /><br />It would be desirable that I can get feedback on your "
671
- #~ "potential changes to improve this plugin for all."
672
- #~ msgstr ""
673
- #~ "Cette extension a été développée gratuitement pour vous par <a href="
674
- #~ "\"http://www.restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</"
675
- #~ "a>. Elle est libre de droits, vous pouvez la prendre, la modifier, la "
676
- #~ "distribuer comme bon vous semble.<br /><br />Il serait néanmoins "
677
- #~ "souhaitable que je puisse avoir des retours sur vos éventuelles "
678
- #~ "modifications afin d'améliorer cette extension pour tous."
679
-
680
- #~ msgid "Save this settings"
681
- #~ msgstr "Sauvegarder ces paramètres"
682
-
683
- #~ msgid ""
684
- #~ "This plugin has been developed for you for free by <a href=\"http://www."
685
- #~ "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</ a>. It is "
686
- #~ "royalty free, you can take it, modify it, distribute it as you see fit. "
687
- #~ "<br /> <br />It would be desirable that I can get feedback on your "
688
- #~ "potential changes to improve this plugin for all."
689
- #~ msgstr ""
690
- #~ "Cette extension a été développée gratuitement pour vous par <a href="
691
- #~ "\"http://www.restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</"
692
- #~ "a>. Elle est libre de droits, vous pouvez la prendre, la modifier, la "
693
- #~ "distribuer comme bon vous semble.<br /><br />Il serait néanmoins "
694
- #~ "souhaitable que je puisse avoir des retours sur vos éventuelles "
695
- #~ "modifications afin d'améliorer cette extension pour tous."
696
-
697
- #~ msgid "WP Maintenance is brought to you by"
698
- #~ msgstr "WP Maintenance est un plugin proposé par"
699
-
700
- #~ msgid "Font size:"
701
- #~ msgstr "Taille de la police :"
702
-
703
- #~ msgid "Enter the launch date"
704
- #~ msgstr "Entrez la date de lancement"
705
-
706
- #~ msgid "Please, enter one IP address by line:"
707
- #~ msgstr "Merci d'entrer 1 adresse IP par ligne : "
708
-
709
- #~ msgid "Enter title for the admin access login block:"
710
- #~ msgstr "Entrer une phrase pour aller au tableau de bord"
711
-
712
- #~ msgid ""
713
- #~ "website, try the demo of the plugin, speak what this plugin to your "
714
- #~ "surroundings!"
715
- #~ msgstr ""
716
- #~ ", essayer la démonstration du plugin, parlez ce ce plugin à votre "
717
- #~ "entourage !"
718
-
719
- #~ msgid "Demo mode:"
720
- #~ msgstr "Mode démo :"
721
-
722
- #~ msgid "Be careful, in demo mode, the plugin can be modified by all users"
723
- #~ msgstr ""
724
- #~ "Attention, en mode démo, le plugin peut-être modifié par tous les "
725
- #~ "utilisateurs"
726
-
727
- #~ msgid "Active this plugin in demo mode?"
728
- #~ msgstr "Activer ce plugin en mode démo ?"
729
-
730
- #~ msgid "Choice texts colors:"
731
- #~ msgstr "Choix des couleurs des textes :"
732
-
733
- #~ msgid "Choice countdown colors:"
734
- #~ msgstr "Choix des couleurs du compte à rebours :"
735
-
736
- #~ msgid "Choice texts bottom colors:"
737
- #~ msgstr "Choix des couleurs du bas de page :"
738
-
739
- #~ msgid "Text font on the bottom page:"
740
- #~ msgstr "Paramètres de la police du texte du bas de page :"
741
-
742
- #~ msgid "Go to Admin Panel"
743
- #~ msgstr "Aller au panneau d'admin"
744
-
745
- #~ msgid "Choose those that do not display the maintenance page."
746
- #~ msgstr "Choisissez ceux qui n'auront pas la page de maintenance"
747
-
748
- #~ msgid "Note : "
749
- #~ msgstr "Note :"
750
-
751
- #~ msgid "Use this code for add color texte"
752
- #~ msgstr "Utiliser ce code pour la couleur du texte"
753
-
754
- #, fuzzy
755
- #~ msgid ""
756
- #~ "If this parameter is set to Yes, this is the maintenance.php page of your "
757
- #~ "theme to be displayed"
758
- #~ msgstr ""
759
- #~ "Si ce paramètre est sur Oui, c'est la page maintenance.php de votre thème "
760
- #~ "qui sera affichée"
761
-
762
- #~ msgid "Day"
763
- #~ msgstr "Jour"
1
  msgid ""
2
  msgstr ""
3
  "Project-Id-Version: WP Maintenance\n"
4
+ "POT-Creation-Date: 2017-04-04 17:25+0100\n"
5
+ "PO-Revision-Date: 2017-04-04 17:29+0100\n"
6
+ "Last-Translator: \n"
7
+ "Language-Team: \n"
8
+ "Language: fr_FR\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=UTF-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "X-Generator: Poedit 2.0\n"
13
+ "X-Poedit-Basepath: ..\n"
14
+ "Plural-Forms: nplurals=2; plural=(n > 1);\n"
15
+ "X-Poedit-Flags-xgettext: --add-comments=translators:\n"
16
+ "X-Poedit-WPHeader: wp-maintenance.php\n"
17
  "X-Poedit-SourceCharset: UTF-8\n"
18
+ "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
19
+ "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
20
+ "_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
21
  "X-Poedit-SearchPath-0: .\n"
22
+ "X-Poedit-SearchPathExcluded-0: *.js\n"
23
 
24
+ #: classes/countdown.php:34
25
+ msgid "Days"
26
+ msgstr "Jours"
27
 
28
+ #: classes/countdown.php:34
29
+ msgid "Hours"
30
+ msgstr "Heures"
31
 
32
+ #: classes/countdown.php:34
33
+ msgid "Minutes"
34
+ msgstr "Minutes"
35
+
36
+ #: classes/countdown.php:36
37
+ msgid "Seconds"
38
+ msgstr "Secondes"
39
+
40
+ #: classes/slider.php:90
41
+ msgid "Previous"
42
+ msgstr "Précédent"
43
+
44
+ #: classes/slider.php:91
45
+ msgid "Next"
46
+ msgstr "Suivant"
47
+
48
+ #: classes/wp-maintenance.php:43 classes/wp-maintenance.php:274
49
+ msgid "This site is down for maintenance"
50
+ msgstr "Ce site est fermé pour maintenance"
51
+
52
+ #: classes/wp-maintenance.php:44 classes/wp-maintenance.php:275
53
+ msgid "Come back quickly!"
54
+ msgstr "Nous revenons rapidement !"
55
+
56
+ #: classes/wp-maintenance.php:148 classes/wp-maintenance.php:264
57
+ #: views/wp-maintenance-admin.php:129 views/wp-maintenance-settings.php:30
58
+ msgid "Settings"
59
+ msgstr "Réglages"
60
+
61
+ #: classes/wp-maintenance.php:207
62
+ msgid "Maintenance mode activated!"
63
+ msgstr "Maintenance activée !"
64
 
65
+ #: classes/wp-maintenance.php:254 views/wp-maintenance-admin.php:124
66
+ #: views/wp-maintenance-dashboard.php:47
67
  msgid "General"
68
  msgstr "Général"
69
 
70
+ #: classes/wp-maintenance.php:256 views/wp-maintenance-admin.php:125
71
+ #: views/wp-maintenance-colors.php:34
72
  msgid "Colors & Fonts"
73
+ msgstr "Coleurs & Polices"
74
 
75
+ #: classes/wp-maintenance.php:258
76
+ msgid "Pictures"
77
+ msgstr "Images"
78
 
79
+ #: classes/wp-maintenance.php:260 views/wp-maintenance-admin.php:127
80
  msgid "CountDown"
81
  msgstr "Compte à rebours"
82
 
83
+ #: classes/wp-maintenance.php:262 views/wp-maintenance-admin.php:128
84
+ #: views/wp-maintenance-css.php:36
85
  msgid "CSS Style"
86
  msgstr "Style CSS"
87
 
88
+ #: classes/wp-maintenance.php:394
89
+ msgid "Choose This Image"
90
+ msgstr "Choisir cette image"
91
+
92
+ #: classes/wp-maintenance.php:395
93
+ msgid "Choose Image"
94
+ msgstr "Choisir une image"
95
+
96
+ #: classes/wp-maintenance.php:411 classes/wp-maintenance.php:419
97
+ #: classes/wp-maintenance.php:427 classes/wp-maintenance.php:436
98
+ #: classes/wp-maintenance.php:445 classes/wp-maintenance.php:454
99
+ msgid "You do not have sufficient privileges to access this page."
100
+ msgstr ""
101
+ "Vous n'avez pas les autorisations suffisantes pour accéder à cette page."
102
+
103
+ #: classes/wp-maintenance.php:693
104
+ msgid "Dashboard"
105
+ msgstr "Tableau de bord"
106
+
107
+ #: includes/functions.php:25 views/wp-maintenance-admin.php:35
108
+ msgid "Options saved."
109
+ msgstr "Options sauvegardées."
110
+
111
+ #: includes/functions.php:57
112
+ msgid "Go to Generals options"
113
+ msgstr "Aller aux options générales"
114
+
115
+ #: includes/functions.php:62
116
+ msgid "Go to Colors and Fonts options"
117
+ msgstr "Aller aux options de couleurs et polices"
118
+
119
+ #: includes/functions.php:67
120
+ msgid "Go to Pictures options"
121
+ msgstr "Aller aux options des images"
122
+
123
+ #: includes/functions.php:72
124
+ msgid "Go to Countdown options"
125
+ msgstr "Aller aux options du compte à rebours"
126
+
127
+ #: includes/functions.php:77
128
+ msgid "Go to CSS options"
129
+ msgstr "Aller aux options de la feuille de style CSS"
130
+
131
+ #: includes/functions.php:82
132
+ msgid "Go to Settings options"
133
+ msgstr "Aller aux paramètrages"
134
+
135
+ #: includes/functions.php:136
136
+ msgid "ABOUT"
137
+ msgstr "A PROPOS"
138
+
139
+ #: includes/functions.php:138
140
+ msgid ""
141
+ "This plugin has been developed for you for free by <a href=\"https://"
142
+ "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is royalty "
143
+ "free, you can take it, modify it, distribute it as you see fit."
144
+ msgstr ""
145
+ "Cette extension a été développée gratuitement pour vous par <a href="
146
+ "\"https://restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. "
147
+ "Elle est libre de droits, vous pouvez la prendre, la modifier, la distribuer "
148
+ "comme bon vous semble."
149
+
150
+ #: includes/functions.php:139 views/wp-maintenance-admin.php:934
151
+ msgid "Visit"
152
+ msgstr "Visitez"
153
+
154
+ #: includes/functions.php:139 views/wp-maintenance-admin.php:934
155
+ msgid ""
156
+ "try the demo of the plugin, talk about this plugin to your surroundings!"
157
+ msgstr "essayez la démo de cette extension et parlez-en à votre entourage !"
158
+
159
+ #: includes/functions.php:141
160
+ msgid "Support this extension and my other developments (French Paypal):"
161
+ msgstr "Soutenez cette extension et mes autres développements (PayPal) :"
162
+
163
+ #: includes/functions.php:153
164
+ msgid "DISCOVER"
165
+ msgstr "DÉCOUVRIR"
166
+
167
+ #. Plugin Name of the plugin/theme
168
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
169
+ msgid "WP Maintenance"
170
+ msgstr "WP Maintenance"
171
+
172
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
173
+ msgid "is brought to you by"
174
+ msgstr "vous est proposé par"
175
+
176
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
177
+ msgid "If you found this plugin useful"
178
+ msgstr "Si vous avez trouvé cette extension utile"
179
+
180
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
181
+ msgid "give it 5 &#9733; on WordPress.org"
182
+ msgstr "donnez-lui 5 &#9733; sur WordPress.org"
183
+
184
+ #: views/wp-maintenance-admin.php:74
185
+ msgid "The Style Sheet has been reset!"
186
+ msgstr "La feuille de style a bien été réinitilisée !"
187
 
188
+ #: views/wp-maintenance-admin.php:119
189
+ msgid "WP Maintenance Settings"
190
+ msgstr "Paramètres WP Maintenance"
191
+
192
+ #: views/wp-maintenance-admin.php:126 views/wp-maintenance-picture.php:60
193
+ msgid "Picture"
194
+ msgstr "Image"
195
+
196
+ #: views/wp-maintenance-admin.php:130
197
  msgid "About"
198
  msgstr "A propos"
199
 
200
+ #: views/wp-maintenance-admin.php:143 views/wp-maintenance-dashboard.php:55
201
  msgid "Enable maintenance mode:"
202
  msgstr "Activer le mode maintenance :"
203
 
204
+ #: views/wp-maintenance-admin.php:144 views/wp-maintenance-admin.php:200
205
+ #: views/wp-maintenance-admin.php:210 views/wp-maintenance-admin.php:277
206
+ #: views/wp-maintenance-admin.php:571 views/wp-maintenance-admin.php:575
207
+ #: views/wp-maintenance-admin.php:669 views/wp-maintenance-admin.php:854
208
+ #: views/wp-maintenance-colors.php:109 views/wp-maintenance-countdown.php:58
209
+ #: views/wp-maintenance-countdown.php:96 views/wp-maintenance-countdown.php:108
210
+ #: views/wp-maintenance-css.php:57 views/wp-maintenance-dashboard.php:59
211
+ #: views/wp-maintenance-dashboard.php:119
212
+ #: views/wp-maintenance-dashboard.php:143
213
+ #: views/wp-maintenance-dashboard.php:166
214
+ #: views/wp-maintenance-dashboard.php:243 views/wp-maintenance-picture.php:92
215
+ #: views/wp-maintenance-picture.php:152 views/wp-maintenance-picture.php:184
216
+ #: views/wp-maintenance-picture.php:191 views/wp-maintenance-settings.php:42
217
+ #: views/wp-maintenance-settings.php:61
218
  msgid "Yes"
219
  msgstr "Oui"
220
 
221
+ #: views/wp-maintenance-admin.php:145 views/wp-maintenance-admin.php:572
222
+ #: views/wp-maintenance-admin.php:576 views/wp-maintenance-admin.php:855
223
+ #: views/wp-maintenance-colors.php:111 views/wp-maintenance-countdown.php:60
224
+ #: views/wp-maintenance-countdown.php:98 views/wp-maintenance-countdown.php:110
225
+ #: views/wp-maintenance-css.php:59 views/wp-maintenance-dashboard.php:61
226
+ #: views/wp-maintenance-dashboard.php:121
227
+ #: views/wp-maintenance-dashboard.php:145
228
+ #: views/wp-maintenance-dashboard.php:168
229
+ #: views/wp-maintenance-dashboard.php:245 views/wp-maintenance-picture.php:94
230
+ #: views/wp-maintenance-picture.php:154 views/wp-maintenance-picture.php:186
231
+ #: views/wp-maintenance-picture.php:193 views/wp-maintenance-settings.php:44
232
+ #: views/wp-maintenance-settings.php:63
233
  msgid "No"
234
  msgstr "Non"
235
 
236
+ #: views/wp-maintenance-admin.php:149 views/wp-maintenance-dashboard.php:69
237
  msgid "Title and text for the maintenance page:"
238
  msgstr "Titre et Texte de la page maintenance :"
239
 
240
+ #: views/wp-maintenance-admin.php:150 views/wp-maintenance-dashboard.php:70
241
  msgid "Title:"
242
  msgstr "Titre :"
243
 
244
+ #: views/wp-maintenance-admin.php:153 views/wp-maintenance-admin.php:173
245
+ #: views/wp-maintenance-admin.php:618 views/wp-maintenance-dashboard.php:71
246
+ #: views/wp-maintenance-picture.php:238
247
  msgid "Text:"
248
  msgstr "Texte :"
249
 
250
+ #: views/wp-maintenance-admin.php:172 views/wp-maintenance-dashboard.php:91
251
  msgid "Text in the bottom of maintenance page:"
252
+ msgstr "Texte du bas de la page de maintenance :"
253
 
254
+ #: views/wp-maintenance-admin.php:192 views/wp-maintenance-dashboard.php:115
255
  msgid "Enable login access in the bottom ?"
256
+ msgstr "Permettre laccès de connexion en bas de page ?"
257
 
258
+ #: views/wp-maintenance-admin.php:193 views/wp-maintenance-dashboard.php:129
259
  msgid "Enter a text to go to the dashboard:"
260
  msgstr "Entrer une phrase pour aller au tableau de bord :"
261
 
262
+ #: views/wp-maintenance-admin.php:195 views/wp-maintenance-dashboard.php:131
263
  msgid "Eg: connect to %DASHBOARD% here!"
264
+ msgstr "Ex : Connectez-vous au %DASHBOARD% !"
265
 
266
+ #: views/wp-maintenance-admin.php:195 views/wp-maintenance-dashboard.php:131
267
  msgid ""
268
  "(%DASHBOARD% will be replaced with the link to the dashboard and the word "
269
  "\"Dashboard\")"
271
  "(%DASHBOARD% sera remplacé par le mot \"Tableau de bord\" et le lien vers "
272
  "celui-ci)"
273
 
274
+ #: views/wp-maintenance-admin.php:199 views/wp-maintenance-dashboard.php:139
275
  msgid "Enable Google Analytics:"
276
  msgstr "Activer Google Analytics :"
277
 
278
+ #: views/wp-maintenance-admin.php:201 views/wp-maintenance-dashboard.php:153
279
  msgid "Enter your Google analytics tracking ID here:"
280
  msgstr "Enter votre ID de suivi de Google Analytics ici :"
281
 
282
+ #: views/wp-maintenance-admin.php:203 views/wp-maintenance-dashboard.php:155
283
  msgid "Enter your domain URL:"
284
+ msgstr "Entrer l'URL de votre domaine :"
285
 
286
+ #: views/wp-maintenance-admin.php:209 views/wp-maintenance-dashboard.php:162
287
  msgid "Enable Social Networks:"
288
+ msgstr "Activer les réseaux sociaux :"
289
 
290
+ #: views/wp-maintenance-admin.php:211 views/wp-maintenance-dashboard.php:176
291
  msgid "Enter text for the title icons:"
292
  msgstr "Entrez un texte pour la balise title des icônes :"
293
 
294
+ #: views/wp-maintenance-admin.php:212 views/wp-maintenance-dashboard.php:177
295
  msgid "Follow me on"
296
  msgstr "Suivez-moi sur"
297
 
298
+ #: views/wp-maintenance-admin.php:214 views/wp-maintenance-dashboard.php:179
299
  msgid "Drad and drop the lines to put in the order you want:"
300
  msgstr ""
301
  "Cliquez et glisser les lignes pour mettre dans l'ordre que vous souhaitez :"
302
 
303
+ #: views/wp-maintenance-admin.php:241 views/wp-maintenance-dashboard.php:206
304
  msgid "Choose icons size:"
305
  msgstr "Choisissez la taille des icônes :"
306
 
307
+ #: views/wp-maintenance-admin.php:253 views/wp-maintenance-admin.php:579
308
+ #: views/wp-maintenance-dashboard.php:217 views/wp-maintenance-picture.php:199
309
  msgid "Position:"
310
  msgstr "Position :"
311
 
312
+ #: views/wp-maintenance-admin.php:255 views/wp-maintenance-dashboard.php:219
313
  msgid "Top"
314
  msgstr "Haut"
315
 
316
+ #: views/wp-maintenance-admin.php:256 views/wp-maintenance-dashboard.php:220
317
  msgid "Bottom"
318
  msgstr "Bas"
319
 
320
+ #: views/wp-maintenance-admin.php:260 views/wp-maintenance-dashboard.php:223
321
  msgid "Align:"
322
  msgstr "Alignement :"
323
 
324
+ #: views/wp-maintenance-admin.php:262 views/wp-maintenance-dashboard.php:225
325
  msgid "Left"
326
  msgstr "Gauche"
327
 
328
+ #: views/wp-maintenance-admin.php:263 views/wp-maintenance-dashboard.php:226
329
  msgid "Center"
330
  msgstr "Centre"
331
 
332
+ #: views/wp-maintenance-admin.php:264 views/wp-maintenance-dashboard.php:227
333
  msgid "Right"
334
  msgstr "Droite"
335
 
336
+ #: views/wp-maintenance-admin.php:267 views/wp-maintenance-dashboard.php:230
337
  msgid "You have your own icons? Enter the folder name of your theme here:"
338
  msgstr ""
339
  "Vous avez vos propres icônes ? Entrez le nom du dossier de votre thème ici :"
340
 
341
+ #: views/wp-maintenance-admin.php:270 views/wp-maintenance-dashboard.php:232
342
  msgid "Reset Social Icon?"
343
  msgstr "Réinitialiser les icônes des réseaux sociaux ?"
344
 
345
+ #: views/wp-maintenance-admin.php:276 views/wp-maintenance-dashboard.php:239
346
  msgid "Enable Newletter:"
347
  msgstr "Activer l'encart de newletter :"
348
 
349
+ #: views/wp-maintenance-admin.php:278 views/wp-maintenance-dashboard.php:253
350
  msgid "Enter title for the newletter block:"
351
+ msgstr "Entrez un titre pour l'encart de la newsletter :"
352
 
353
+ #: views/wp-maintenance-admin.php:280 views/wp-maintenance-dashboard.php:255
354
  msgid "Enter your newletter shortcode here:"
355
  msgstr "Entrez le Shortcode de la newletter ici :"
356
 
357
+ #: views/wp-maintenance-admin.php:282 views/wp-maintenance-dashboard.php:257
358
  msgid "Or enter your newletter iframe code here:"
359
  msgstr "Ou entrez le code iframe de la newsletter ici :"
360
 
361
+ #: views/wp-maintenance-admin.php:304 views/wp-maintenance-colors.php:44
362
  msgid "Choice general colors:"
363
  msgstr "Choix des couleurs générales :"
364
 
365
+ #: views/wp-maintenance-admin.php:305 views/wp-maintenance-colors.php:45
366
  msgid "Background page color:"
367
  msgstr "Couleur du fond de page :"
368
 
369
+ #: views/wp-maintenance-admin.php:306 views/wp-maintenance-colors.php:46
370
  msgid "Header color:"
371
+ msgstr "Couleur d'entête :"
372
 
373
+ #: views/wp-maintenance-admin.php:310 views/wp-maintenance-colors.php:49
374
  msgid "Choice texts fonts and colors:"
375
  msgstr "Choix des polices et couleurs des textes :"
376
 
377
+ #: views/wp-maintenance-admin.php:311 views/wp-maintenance-colors.php:50
378
  msgid "Text color:"
379
  msgstr "Couleur du texte :"
380
 
381
+ #: views/wp-maintenance-admin.php:313 views/wp-maintenance-colors.php:52
382
  msgid "Title font settings"
383
  msgstr "Paramètres de la police du titre"
384
 
385
+ #: views/wp-maintenance-admin.php:327 views/wp-maintenance-admin.php:348
386
+ #: views/wp-maintenance-admin.php:387 views/wp-maintenance-admin.php:418
387
+ #: views/wp-maintenance-admin.php:437 views/wp-maintenance-colors.php:66
388
+ #: views/wp-maintenance-colors.php:87 views/wp-maintenance-colors.php:135
389
+ #: views/wp-maintenance-colors.php:154 views/wp-maintenance-colors.php:186
390
  msgid "Size:"
391
  msgstr "Taille :"
392
 
393
+ #: views/wp-maintenance-admin.php:343 views/wp-maintenance-admin.php:382
394
+ #: views/wp-maintenance-colors.php:82 views/wp-maintenance-colors.php:149
395
  msgid "Text font settings"
396
  msgstr "Paramètres de la police du texte"
397
 
398
+ #: views/wp-maintenance-admin.php:364
399
  msgid "Frame settings"
400
  msgstr "Paramètres du cadre"
401
 
402
+ #: views/wp-maintenance-admin.php:366
403
  msgid "Activate"
404
  msgstr "Activé"
405
 
406
+ #: views/wp-maintenance-admin.php:366 views/wp-maintenance-colors.php:116
407
  msgid "Color:"
408
  msgstr "Couleur :"
409
 
410
+ #: views/wp-maintenance-admin.php:367 views/wp-maintenance-colors.php:117
411
  msgid "Opacity:"
412
  msgstr "Opacité :"
413
 
414
+ #: views/wp-maintenance-admin.php:369 views/wp-maintenance-admin.php:567
415
+ #: views/wp-maintenance-colors.php:119 views/wp-maintenance-picture.php:176
416
  msgid "Width:"
417
  msgstr "Largeur :"
418
 
419
+ #: views/wp-maintenance-admin.php:377 views/wp-maintenance-colors.php:144
420
  msgid "Choice fonts and colors bottom page:"
421
+ msgstr "Choix des polices et couleurs du bas de page :"
422
 
423
+ #: views/wp-maintenance-admin.php:378 views/wp-maintenance-colors.php:145
424
  msgid "Bottom color:"
425
  msgstr "Couleur du fond :"
426
 
427
+ #: views/wp-maintenance-admin.php:379 views/wp-maintenance-colors.php:146
428
  msgid "Text bottom color:"
429
  msgstr "Couleur du texte :"
430
 
431
+ #: views/wp-maintenance-admin.php:406 views/wp-maintenance-colors.php:126
432
  msgid "Choice countdown fonts and colors:"
433
  msgstr "Choix des polices et couleurs du compte à rebours :"
434
 
435
+ #: views/wp-maintenance-admin.php:407 views/wp-maintenance-colors.php:127
436
  msgid "Countdown text color:"
437
  msgstr "Couleur du texte du compteur :"
438
 
439
+ #: views/wp-maintenance-admin.php:408 views/wp-maintenance-colors.php:128
440
  msgid "Countdown background color:"
441
  msgstr "Couleur du fond du compteur :"
442
 
443
+ #: views/wp-maintenance-admin.php:413 views/wp-maintenance-colors.php:130
444
  msgid "Countdown font settings"
445
  msgstr "Paramètres de la police du compte à rebours"
446
 
447
+ #: views/wp-maintenance-admin.php:430 views/wp-maintenance-colors.php:171
448
  msgid "Choice form color:"
449
  msgstr "Choisir les couleurs du formulaire :"
450
 
451
+ #: views/wp-maintenance-admin.php:451 views/wp-maintenance-colors.php:200
452
  msgid "Field text color:"
453
  msgstr "Couleur du texte dans les champs :"
454
 
455
+ #: views/wp-maintenance-admin.php:453 views/wp-maintenance-colors.php:202
456
  msgid "Field border color:"
457
  msgstr "Couleur de bordure des champs :"
458
 
459
+ #: views/wp-maintenance-admin.php:455 views/wp-maintenance-colors.php:204
460
  msgid "Field background color:"
461
  msgstr "Couleur de fond des champs :"
462
 
463
+ #: views/wp-maintenance-admin.php:458 views/wp-maintenance-colors.php:207
464
  msgid "Button text color:"
465
  msgstr "Couleur du texte dans le bouton :"
466
 
467
+ #: views/wp-maintenance-admin.php:461 views/wp-maintenance-colors.php:210
468
  msgid "Button color:"
469
  msgstr "Couleur du bouton :"
470
 
471
+ #: views/wp-maintenance-admin.php:464 views/wp-maintenance-colors.php:213
472
  msgid "Button color hover:"
473
  msgstr "Couleur du bouton au survol :"
474
 
475
+ #: views/wp-maintenance-admin.php:466 views/wp-maintenance-colors.php:215
476
  msgid "Button color onclick:"
477
  msgstr "Couleur du bouton au click :"
478
 
479
+ #: views/wp-maintenance-admin.php:498
480
  msgid "Upload a picture"
481
+ msgstr "Mettre en ligne une image"
482
 
483
+ #: views/wp-maintenance-admin.php:500 views/wp-maintenance-picture.php:81
484
  msgid "You use this picture:"
485
+ msgstr "Image actuelle :"
486
 
487
+ #: views/wp-maintenance-admin.php:502 views/wp-maintenance-admin.php:520
488
+ #: views/wp-maintenance-picture.php:76 views/wp-maintenance-picture.php:104
489
  msgid "Enter a URL or upload an image."
490
+ msgstr "Entrez une url ou mettez en ligne une image."
491
 
492
+ #: views/wp-maintenance-admin.php:503 views/wp-maintenance-admin.php:519
493
+ #: views/wp-maintenance-admin.php:589 views/wp-maintenance-picture.php:77
494
+ #: views/wp-maintenance-picture.php:105 views/wp-maintenance-picture.php:209
495
  msgid "Select or Upload your picture"
496
+ msgstr "Sélectionnez / Mettre en ligne votre image"
497
 
498
+ #: views/wp-maintenance-admin.php:509
499
  msgid "Upload a background picture"
500
+ msgstr "Mettre en ligne une image de fond"
501
 
502
+ #: views/wp-maintenance-admin.php:510
503
  msgid "Enable image background"
504
  msgstr "Activer l'image de fond"
505
 
506
+ #: views/wp-maintenance-admin.php:512 views/wp-maintenance-picture.php:116
507
  msgid "You use this background picture:"
508
+ msgstr "Image de fond actuelle :"
509
 
510
+ #: views/wp-maintenance-admin.php:516 views/wp-maintenance-picture.php:140
511
  msgid "You use this pattern:"
512
+ msgstr "Vous utilisez ce modèle :"
513
 
514
+ #: views/wp-maintenance-admin.php:521 views/wp-maintenance-picture.php:124
515
  msgid "Or choose a pattern:"
516
  msgstr "Ou choisissez un pattern de fond :"
517
 
518
+ #: views/wp-maintenance-admin.php:525 views/wp-maintenance-picture.php:127
519
  msgid "NO PATTERN"
520
  msgstr "AUCUN PATTERN"
521
 
522
+ #: views/wp-maintenance-admin.php:538 views/wp-maintenance-picture.php:106
523
  msgid "Background picture options"
524
  msgstr "Options de l'image de fond"
525
 
526
+ #: views/wp-maintenance-admin.php:545 views/wp-maintenance-picture.php:112
527
  msgid "Fixed"
528
  msgstr "Fixe"
529
 
530
+ #: views/wp-maintenance-admin.php:550 views/wp-maintenance-picture.php:161
531
  msgid "Slider image options"
532
  msgstr "Options du Slider"
533
 
534
+ #: views/wp-maintenance-admin.php:551 views/wp-maintenance-picture.php:148
535
  msgid "Enable Slider"
536
  msgstr "Activer le Slider"
537
 
538
+ #: views/wp-maintenance-admin.php:566 views/wp-maintenance-picture.php:175
539
  msgid "Speed:"
540
  msgstr "Vitesse :"
541
 
542
+ #: views/wp-maintenance-admin.php:570 views/wp-maintenance-picture.php:181
543
  msgid "Display Auto Slider:"
544
  msgstr "Afficher le Slider en auto :"
545
 
546
+ #: views/wp-maintenance-admin.php:574 views/wp-maintenance-picture.php:188
547
  msgid "Display button navigation:"
548
  msgstr "Afficher les boutons navigation :"
549
 
550
+ #: views/wp-maintenance-admin.php:581 views/wp-maintenance-picture.php:201
551
  msgid "Above logo"
552
  msgstr "Au-dessus du logo"
553
 
554
+ #: views/wp-maintenance-admin.php:582 views/wp-maintenance-picture.php:202
555
  msgid "Below logo"
556
  msgstr "Au-dessous du logo"
557
 
558
+ #: views/wp-maintenance-admin.php:583 views/wp-maintenance-picture.php:203
559
  msgid "Below title & text"
560
  msgstr "Au-dessous du titre & texte"
561
 
562
+ #: views/wp-maintenance-admin.php:619 views/wp-maintenance-picture.php:239
563
  msgid "Link:"
564
  msgstr "Lien :"
565
 
566
+ #: views/wp-maintenance-admin.php:622 views/wp-maintenance-picture.php:242
567
  msgid "Delete this slide"
568
  msgstr "Supprimer ce slide"
569
 
570
+ #: views/wp-maintenance-admin.php:668 views/wp-maintenance-countdown.php:50
571
  msgid "Enable a countdown ?"
572
  msgstr "Activer le compte à rebours ?"
573
 
574
+ #: views/wp-maintenance-admin.php:687 views/wp-maintenance-countdown.php:89
575
  msgid "Select the launch date/time"
576
  msgstr "Sélectionner une date et heure de lancement"
577
 
578
+ #: views/wp-maintenance-admin.php:690 views/wp-maintenance-countdown.php:101
579
  msgid "Enable seconds ?"
580
  msgstr "Afficher les secondes ?"
581
 
582
+ #: views/wp-maintenance-admin.php:691 views/wp-maintenance-countdown.php:113
583
  msgid "Disable maintenance mode at the end of the countdown?"
584
  msgstr "Désactiver le mode maintenance à la fin du compte à rebours ?"
585
 
586
+ #: views/wp-maintenance-admin.php:692 views/wp-maintenance-countdown.php:117
587
  msgid "End message:"
588
  msgstr "Message de fin :"
589
 
590
+ #: views/wp-maintenance-admin.php:708 views/wp-maintenance-countdown.php:151
591
  msgid "Today"
592
  msgstr "Aujourd'hui"
593
 
594
+ #: views/wp-maintenance-admin.php:709 views/wp-maintenance-countdown.php:152
595
  msgid "Delete"
596
  msgstr "Supprimer"
597
 
598
+ #: views/wp-maintenance-admin.php:710 views/wp-maintenance-admin.php:729
599
+ #: views/wp-maintenance-countdown.php:153
600
+ #: views/wp-maintenance-countdown.php:172
601
  msgid "Close"
602
  msgstr "Fermer"
603
 
604
+ #: views/wp-maintenance-admin.php:713 views/wp-maintenance-countdown.php:156
605
  msgid "Next month"
606
  msgstr "Mois suivant"
607
 
608
+ #: views/wp-maintenance-admin.php:714 views/wp-maintenance-countdown.php:157
609
  msgid "Previous month"
610
  msgstr "Mois précédent"
611
 
612
+ #: views/wp-maintenance-admin.php:715 views/wp-maintenance-countdown.php:158
613
  msgid "Select a month"
614
  msgstr "Sélectionner un mois"
615
 
616
+ #: views/wp-maintenance-admin.php:716 views/wp-maintenance-countdown.php:159
617
  msgid "Select a year"
618
  msgstr "Sélectionner une année"
619
 
620
+ #: views/wp-maintenance-admin.php:759
621
  msgid "CSS style sheet code:"
622
  msgstr "Code style CSS :"
623
 
624
+ #: views/wp-maintenance-admin.php:760 views/wp-maintenance-css.php:45
625
  msgid ""
626
  "Edit the CSS sheet of your maintenance page here. Click \"Reset\" and \"Save"
627
  "\" to retrieve the default style sheet."
629
  "Editer le code CSS de votre page de maintenance ici. Cliquez sur "
630
  "\"Réinitialiser\" et \"Sauvegarder\" pour remettre le style par défaut."
631
 
632
+ #: views/wp-maintenance-admin.php:770 views/wp-maintenance-css.php:68
633
  msgid "Markers for colors"
634
  msgstr "Marqueurs pour les couleurs"
635
 
636
+ #: views/wp-maintenance-admin.php:775 views/wp-maintenance-css.php:73
637
  msgid "Use this code for text color"
638
  msgstr "Utiliser ce code pour la couleur du texte"
639
 
640
+ #: views/wp-maintenance-admin.php:779 views/wp-maintenance-css.php:77
641
  msgid "Use this code for background text color"
642
  msgstr "Utiliser ce code pour la couleur de fond du texte"
643
 
644
+ #: views/wp-maintenance-admin.php:783 views/wp-maintenance-css.php:81
645
  msgid "Use this code for background color countdown"
646
  msgstr "Utiliser ce code pour la couleur du fond du compte à rebours"
647
 
648
+ #: views/wp-maintenance-admin.php:787 views/wp-maintenance-css.php:85
649
  msgid "Use this code for size countdown"
650
  msgstr "Utiliser ce code pour la taille du compte à rebours"
651
 
652
+ #: views/wp-maintenance-admin.php:791 views/wp-maintenance-css.php:89
653
  msgid "Use this code for countdown color"
654
  msgstr "Utiliser ce code pour la couleur du texte du compte à rebours"
655
 
656
+ #: views/wp-maintenance-admin.php:796 views/wp-maintenance-css.php:94
657
  msgid "Need CSS code for MailPoet plugin?"
658
  msgstr "Besoin de code CSS pour le plugin MailPoet ?"
659
 
660
+ #: views/wp-maintenance-admin.php:797 views/wp-maintenance-admin.php:812
661
+ #: views/wp-maintenance-css.php:95 views/wp-maintenance-css.php:110
662
  msgid "Click for select all"
663
  msgstr "Cliquez pour tout sélectionner"
664
 
665
+ #: views/wp-maintenance-admin.php:811 views/wp-maintenance-css.php:109
666
  msgid "Need CSS code for MailChimp plugin?"
667
  msgstr "Besoin de code CSS pour le plugin MailChimp ?"
668
 
669
+ #: views/wp-maintenance-admin.php:833 views/wp-maintenance-css.php:53
670
  msgid "Reset default CSS stylesheet ?"
671
  msgstr "Réinitialiser la feuille de style ?"
672
 
673
+ #: views/wp-maintenance-admin.php:852
674
  msgid "Theme maintenance page:"
675
  msgstr "Page maintenance du thème :"
676
 
677
+ #: views/wp-maintenance-admin.php:853 views/wp-maintenance-settings.php:38
678
  msgid ""
679
  "If you would use your maintenance.php page in your theme folder, click Yes."
680
  msgstr ""
681
  "Si vous souhaitez utiliser votre page maintenance.php dans le dossier de "
682
  "votre thème, cliquez sur Oui."
683
 
684
+ #: views/wp-maintenance-admin.php:856 views/wp-maintenance-settings.php:51
685
  msgid "You can use this shortcode to include Google Analytics code:"
686
  msgstr ""
687
  "Vous pouvez utiliser ce Shortcode pour include le code Google Analytics sur "
688
  "votre page :"
689
 
690
+ #: views/wp-maintenance-admin.php:856 views/wp-maintenance-settings.php:51
691
  msgid "You can use this shortcode to include Social Networks icons:"
692
  msgstr ""
693
  "Vous pouvez utiliser ce Shortcode pour include les icons des réseaux sociaux "
694
  "sur votre page :"
695
 
696
+ #: views/wp-maintenance-admin.php:865 views/wp-maintenance-settings.php:71
697
  msgid "Roles and Capabilities:"
698
  msgstr "Rôles et capacités :"
699
 
700
+ #: views/wp-maintenance-admin.php:866 views/wp-maintenance-settings.php:72
701
  msgid "Allow the site to display these roles:"
702
  msgstr "Autoriser l'affichage du site à ces rôles :"
703
 
704
+ #: views/wp-maintenance-admin.php:883 views/wp-maintenance-settings.php:91
705
  msgid "IP autorized:"
706
  msgstr "IP autorisées :"
707
 
708
+ #: views/wp-maintenance-admin.php:884 views/wp-maintenance-settings.php:92
709
  msgid ""
710
  "Allow the site to display these IP addresses. Please, enter one IP address "
711
  "by line:"
712
  msgstr ""
713
  "Autoriser l'affichage du site à ces adresses IP. Merci d'entrer 1 adresse IP "
714
+ "par ligne :"
715
 
716
+ #: views/wp-maintenance-admin.php:890 views/wp-maintenance-settings.php:98
717
  msgid "ID pages autorized:"
718
  msgstr "ID de pages autorisées :"
719
 
720
+ #: views/wp-maintenance-admin.php:891 views/wp-maintenance-settings.php:99
721
  msgid ""
722
  "Allow the site to display these ID pages. Please, enter the ID pages "
723
  "separate with comma :"
725
  "Autoriser le site à afficher des pages d'ID. Merci d'entrer les ID de pages "
726
  "séparées par une virgule :"
727
 
728
+ #: views/wp-maintenance-admin.php:897 views/wp-maintenance-settings.php:105
729
  msgid "Header Code:"
730
+ msgstr "Code pour le header :"
731
 
732
+ #: views/wp-maintenance-admin.php:898 views/wp-maintenance-settings.php:106
733
  msgid ""
734
  "The following code will add to the <head> tag. Useful if you need to add "
735
  "additional scripts such as CSS or JS."
737
  "Le code suivant va être ajouter à la balise <head>. Très utile si vous avez "
738
  "besoin d'ajouter des scripts supplémentaires tels que CSS ou JS."
739
 
740
+ #: views/wp-maintenance-admin.php:930
741
  msgid ""
742
  "This plugin has been developed for you for free by <a href=\"https://"
743
  "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is royalty "
752
  "puisse avoir des retours sur vos éventuelles modifications afin d'améliorer "
753
  "cette extension pour tous."
754
 
755
+ #: views/wp-maintenance-admin.php:939
 
 
 
 
 
 
 
 
 
756
  msgid ""
757
  "If you want Donate (French Paypal) for my current and future developments:"
758
  msgstr ""
759
  "Si vous souhaitez me soutenir pour mes développements actuels et futurs :"
760
 
761
+ #: views/wp-maintenance-colors.php:105
762
+ msgid "Activate Frame"
763
+ msgstr "Activer le cadre"
764
 
765
+ #: views/wp-maintenance-colors.php:219
766
+ #, php-format
767
+ msgid "Enable %s to customize the forms"
768
+ msgstr "Activer %s pour personnaliser les formulaires"
769
 
770
+ #: views/wp-maintenance-colors.php:219
771
+ msgid "newsletter option"
772
+ msgstr "options de newsletter"
773
 
774
+ #: views/wp-maintenance-colors.php:223
775
+ msgid "Enable Mailpoet or MailChimp extensions to customize the forms"
776
+ msgstr ""
777
+ "Activer les extensions Mailpoet ou MailChimp personnaliser les formulaires"
778
 
779
+ #: views/wp-maintenance-countdown.php:24
780
+ msgid "Countdown"
781
+ msgstr "Compte à rebours"
782
 
783
+ #: views/wp-maintenance-countdown.php:70
784
+ msgid "Personnalize Colors and Fonts"
785
+ msgstr "Personnaliser les couleurs et polices"
786
 
787
+ #: views/wp-maintenance-countdown.php:89
788
+ msgid "at"
789
+ msgstr "à"
790
 
791
+ #: views/wp-maintenance-countdown.php:148
792
+ msgid "January"
793
+ msgstr "Janvier"
794
 
795
+ #: views/wp-maintenance-countdown.php:148
796
+ msgid "February"
797
+ msgstr "Février"
798
 
799
+ #: views/wp-maintenance-countdown.php:148
800
+ msgid "March"
801
+ msgstr "Mars"
802
 
803
+ #: views/wp-maintenance-countdown.php:148
804
+ msgid "April"
805
+ msgstr "Avril"
806
 
807
+ #: views/wp-maintenance-countdown.php:148
808
+ msgid "May"
809
+ msgstr "Mai"
810
 
811
+ #: views/wp-maintenance-countdown.php:148
812
+ msgid "June"
813
+ msgstr "Juin"
814
 
815
+ #: views/wp-maintenance-countdown.php:148
816
+ msgid "July"
817
+ msgstr "Juillet"
818
 
819
+ #: views/wp-maintenance-countdown.php:148
820
+ msgid "August"
821
+ msgstr "Août"
822
 
823
+ #: views/wp-maintenance-countdown.php:148
824
+ msgid "September"
825
+ msgstr "Septembre"
826
 
827
+ #: views/wp-maintenance-countdown.php:148
828
+ msgid "October"
829
+ msgstr "Octobre"
830
+
831
+ #: views/wp-maintenance-countdown.php:148
832
+ msgid "November"
833
+ msgstr "Novembre"
834
+
835
+ #: views/wp-maintenance-countdown.php:148
836
+ msgid "December"
837
+ msgstr "Décembre"
838
+
839
+ #: views/wp-maintenance-countdown.php:150
840
+ msgid "Sunday"
841
+ msgstr "Dimanche"
842
+
843
+ #: views/wp-maintenance-countdown.php:150
844
+ msgid "Monday"
845
+ msgstr "Lundi"
846
+
847
+ #: views/wp-maintenance-countdown.php:150
848
+ msgid "Tuesday"
849
+ msgstr "Mardi"
850
+
851
+ #: views/wp-maintenance-countdown.php:150
852
+ msgid "Wednesday"
853
+ msgstr "Mercredi"
854
+
855
+ #: views/wp-maintenance-countdown.php:150
856
+ msgid "Thurday"
857
+ msgstr "Jeudi"
858
+
859
+ #: views/wp-maintenance-countdown.php:150
860
+ msgid "Friday"
861
+ msgstr "Vendredi"
862
+
863
+ #: views/wp-maintenance-countdown.php:150
864
+ msgid "Saturday"
865
+ msgstr "Samedi"
866
+
867
+ #: views/wp-maintenance-picture.php:75
868
+ msgid "Header picture"
869
+ msgstr "Image d'entête"
870
+
871
+ #: views/wp-maintenance-picture.php:88
872
+ msgid "Background picture or pattern"
873
+ msgstr "Image de fond ou un modèle"
874
+
875
+ #: views/wp-maintenance-settings.php:38
876
+ msgid "Theme maintenance page"
877
+ msgstr "Page maintenance du thème"
878
+
879
+ #: views/wp-maintenance-settings.php:57
880
+ msgid "Delete custom settings upon plugin deactivation?"
881
+ msgstr ""
882
+ "Effacer les réglages personnalisés lors de la désactivation de l'extension ?"
883
+
884
+ #: views/wp-maintenance-settings.php:57
885
+ msgid ""
886
+ "If you set \"Yes\" all custom settings will be deleted from database upon "
887
+ "plugin deactivation"
888
+ msgstr ""
889
+ "Si vous laissez sur \"oui\" tous les réglages personnalisés seront effacés "
890
+ "de la base de données lors de la désactivation de l'extension"
891
+
892
+ #. Plugin URI of the plugin/theme
893
+ msgid "https://fr.wordpress.org/plugins/wp-maintenance/"
894
+ msgstr "https://fr.wordpress.org/plugins/wp-maintenance/"
895
+
896
+ #. Description of the plugin/theme
897
+ msgid ""
898
+ "The WP Maintenance plugin allows you to put your website on the waiting time "
899
+ "for you to do maintenance or launch your website. Personalize this page with "
900
+ "picture, countdown..."
901
+ msgstr ""
902
+ "Le plugin WP entretien vous permet de mettre votre site Web sur les temps "
903
+ "d’attente pour vous de faire l’entretien ou de lancer votre site Web. "
904
+ "Personnaliser cette page avec photo, compte à rebours..."
905
+
906
+ #. Author of the plugin/theme
907
+ msgid "Florent Maillefaud"
908
+ msgstr "Florent Maillefaud"
909
 
910
+ #. Author URI of the plugin/theme
911
+ msgid "https://wpmaintenance.info"
912
+ msgstr "https://wpmaintenance.info"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/wp-maintenance.pot CHANGED
@@ -2,7 +2,7 @@
2
  msgid ""
3
  msgstr ""
4
  "Project-Id-Version: WP Maintenance\n"
5
- "POT-Creation-Date: 2016-12-23 09:49+0100\n"
6
  "PO-Revision-Date: 2015-03-19 11:19+0100\n"
7
  "Last-Translator: Florent Maillefaud <contact@restezconnectes.fr>\n"
8
  "Language-Team: Florent Maillefaud <contact@restezconnectes.fr>\n"
@@ -10,545 +10,706 @@ msgstr ""
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
- "X-Generator: Poedit 1.8.11\n"
14
  "X-Poedit-KeywordsList: __;_e\n"
15
  "X-Poedit-Basepath: ..\n"
16
  "Plural-Forms: nplurals=2; plural=n>1;\n"
17
  "X-Poedit-SourceCharset: UTF-8\n"
18
  "X-Poedit-SearchPath-0: .\n"
19
 
20
- #: wp-maintenance-admin.php:35
21
- msgid "Options saved."
22
  msgstr ""
23
 
24
- #: wp-maintenance-admin.php:74
25
- msgid "The Style Sheet has been reset!"
26
  msgstr ""
27
 
28
- #: wp-maintenance-admin.php:115
29
- msgid "WP Maintenance Settings"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  msgstr ""
31
 
32
- #: wp-maintenance-admin.php:120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  msgid "General"
34
  msgstr ""
35
 
36
- #: wp-maintenance-admin.php:121
 
37
  msgid "Colors & Fonts"
38
  msgstr ""
39
 
40
- #: wp-maintenance-admin.php:122
41
- msgid "Picture"
42
  msgstr ""
43
 
44
- #: wp-maintenance-admin.php:123
45
  msgid "CountDown"
46
  msgstr ""
47
 
48
- #: wp-maintenance-admin.php:124
 
49
  msgid "CSS Style"
50
  msgstr ""
51
 
52
- #: wp-maintenance-admin.php:125 wp-maintenance.php:51
53
- msgid "Settings"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  msgstr ""
55
 
56
- #: wp-maintenance-admin.php:126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  msgid "About"
58
  msgstr ""
59
 
60
- #: wp-maintenance-admin.php:139
61
  msgid "Enable maintenance mode:"
62
  msgstr ""
63
 
64
- #: wp-maintenance-admin.php:140 wp-maintenance-admin.php:158
65
- #: wp-maintenance-admin.php:168 wp-maintenance-admin.php:235
66
- #: wp-maintenance-admin.php:529 wp-maintenance-admin.php:533
67
- #: wp-maintenance-admin.php:627 wp-maintenance-admin.php:810
 
 
 
 
 
 
 
 
 
 
68
  msgid "Yes"
69
  msgstr ""
70
 
71
- #: wp-maintenance-admin.php:141 wp-maintenance-admin.php:530
72
- #: wp-maintenance-admin.php:534 wp-maintenance-admin.php:811
 
 
 
 
 
 
 
 
 
 
73
  msgid "No"
74
  msgstr ""
75
 
76
- #: wp-maintenance-admin.php:145
77
  msgid "Title and text for the maintenance page:"
78
  msgstr ""
79
 
80
- #: wp-maintenance-admin.php:146
81
  msgid "Title:"
82
  msgstr ""
83
 
84
- #: wp-maintenance-admin.php:147 wp-maintenance-admin.php:149
85
- #: wp-maintenance-admin.php:576
 
86
  msgid "Text:"
87
  msgstr ""
88
 
89
- #: wp-maintenance-admin.php:148
90
  msgid "Text in the bottom of maintenance page:"
91
  msgstr ""
92
 
93
- #: wp-maintenance-admin.php:150
94
  msgid "Enable login access in the bottom ?"
95
  msgstr ""
96
 
97
- #: wp-maintenance-admin.php:151
98
  msgid "Enter a text to go to the dashboard:"
99
  msgstr ""
100
 
101
- #: wp-maintenance-admin.php:153
102
  msgid "Eg: connect to %DASHBOARD% here!"
103
  msgstr ""
104
 
105
- #: wp-maintenance-admin.php:153
106
  msgid ""
107
  "(%DASHBOARD% will be replaced with the link to the dashboard and the word "
108
  "\"Dashboard\")"
109
  msgstr ""
110
 
111
- #: wp-maintenance-admin.php:157
112
  msgid "Enable Google Analytics:"
113
  msgstr ""
114
 
115
- #: wp-maintenance-admin.php:159
116
  msgid "Enter your Google analytics tracking ID here:"
117
  msgstr ""
118
 
119
- #: wp-maintenance-admin.php:161
120
  msgid "Enter your domain URL:"
121
  msgstr ""
122
 
123
- #: wp-maintenance-admin.php:167
124
  msgid "Enable Social Networks:"
125
  msgstr ""
126
 
127
- #: wp-maintenance-admin.php:169
128
  msgid "Enter text for the title icons:"
129
  msgstr ""
130
 
131
- #: wp-maintenance-admin.php:170
132
  msgid "Follow me on"
133
  msgstr ""
134
 
135
- #: wp-maintenance-admin.php:172
136
  msgid "Drad and drop the lines to put in the order you want:"
137
  msgstr ""
138
 
139
- #: wp-maintenance-admin.php:199
140
  msgid "Choose icons size:"
141
  msgstr ""
142
 
143
- #: wp-maintenance-admin.php:211 wp-maintenance-admin.php:537
 
144
  msgid "Position:"
145
  msgstr ""
146
 
147
- #: wp-maintenance-admin.php:213
148
  msgid "Top"
149
  msgstr ""
150
 
151
- #: wp-maintenance-admin.php:214
152
  msgid "Bottom"
153
  msgstr ""
154
 
155
- #: wp-maintenance-admin.php:218
156
  msgid "Align:"
157
  msgstr ""
158
 
159
- #: wp-maintenance-admin.php:220
160
  msgid "Left"
161
  msgstr ""
162
 
163
- #: wp-maintenance-admin.php:221
164
  msgid "Center"
165
  msgstr ""
166
 
167
- #: wp-maintenance-admin.php:222
168
  msgid "Right"
169
  msgstr ""
170
 
171
- #: wp-maintenance-admin.php:225
172
  msgid "You have your own icons? Enter the folder name of your theme here:"
173
  msgstr ""
174
 
175
- #: wp-maintenance-admin.php:228
176
  msgid "Reset Social Icon?"
177
  msgstr ""
178
 
179
- #: wp-maintenance-admin.php:234
180
  msgid "Enable Newletter:"
181
  msgstr ""
182
 
183
- #: wp-maintenance-admin.php:236
184
  msgid "Enter title for the newletter block:"
185
  msgstr ""
186
 
187
- #: wp-maintenance-admin.php:238
188
  msgid "Enter your newletter shortcode here:"
189
  msgstr ""
190
 
191
- #: wp-maintenance-admin.php:240
192
  msgid "Or enter your newletter iframe code here:"
193
  msgstr ""
194
 
195
- #: wp-maintenance-admin.php:262
196
  msgid "Choice general colors:"
197
  msgstr ""
198
 
199
- #: wp-maintenance-admin.php:263
200
  msgid "Background page color:"
201
  msgstr ""
202
 
203
- #: wp-maintenance-admin.php:264
204
  msgid "Header color:"
205
  msgstr ""
206
 
207
- #: wp-maintenance-admin.php:268
208
  msgid "Choice texts fonts and colors:"
209
  msgstr ""
210
 
211
- #: wp-maintenance-admin.php:269
212
  msgid "Text color:"
213
  msgstr ""
214
 
215
- #: wp-maintenance-admin.php:271
216
  msgid "Title font settings"
217
  msgstr ""
218
 
219
- #: wp-maintenance-admin.php:285 wp-maintenance-admin.php:306
220
- #: wp-maintenance-admin.php:345 wp-maintenance-admin.php:376
221
- #: wp-maintenance-admin.php:395
 
 
222
  msgid "Size:"
223
  msgstr ""
224
 
225
- #: wp-maintenance-admin.php:301 wp-maintenance-admin.php:340
 
226
  msgid "Text font settings"
227
  msgstr ""
228
 
229
- #: wp-maintenance-admin.php:322
230
  msgid "Frame settings"
231
  msgstr ""
232
 
233
- #: wp-maintenance-admin.php:324
234
  msgid "Activate"
235
  msgstr ""
236
 
237
- #: wp-maintenance-admin.php:324
238
  msgid "Color:"
239
  msgstr ""
240
 
241
- #: wp-maintenance-admin.php:325
242
  msgid "Opacity:"
243
  msgstr ""
244
 
245
- #: wp-maintenance-admin.php:327 wp-maintenance-admin.php:525
 
246
  msgid "Width:"
247
  msgstr ""
248
 
249
- #: wp-maintenance-admin.php:335
250
  msgid "Choice fonts and colors bottom page:"
251
  msgstr ""
252
 
253
- #: wp-maintenance-admin.php:336
254
  msgid "Bottom color:"
255
  msgstr ""
256
 
257
- #: wp-maintenance-admin.php:337
258
  msgid "Text bottom color:"
259
  msgstr ""
260
 
261
- #: wp-maintenance-admin.php:364
262
  msgid "Choice countdown fonts and colors:"
263
  msgstr ""
264
 
265
- #: wp-maintenance-admin.php:365
266
  msgid "Countdown text color:"
267
  msgstr ""
268
 
269
- #: wp-maintenance-admin.php:366
270
  msgid "Countdown background color:"
271
  msgstr ""
272
 
273
- #: wp-maintenance-admin.php:371
274
  msgid "Countdown font settings"
275
  msgstr ""
276
 
277
- #: wp-maintenance-admin.php:388
278
  msgid "Choice form color:"
279
  msgstr ""
280
 
281
- #: wp-maintenance-admin.php:409
282
  msgid "Field text color:"
283
  msgstr ""
284
 
285
- #: wp-maintenance-admin.php:411
286
  msgid "Field border color:"
287
  msgstr ""
288
 
289
- #: wp-maintenance-admin.php:413
290
  msgid "Field background color:"
291
  msgstr ""
292
 
293
- #: wp-maintenance-admin.php:416
294
  msgid "Button text color:"
295
  msgstr ""
296
 
297
- #: wp-maintenance-admin.php:419
298
  msgid "Button color:"
299
  msgstr ""
300
 
301
- #: wp-maintenance-admin.php:422
302
  msgid "Button color hover:"
303
  msgstr ""
304
 
305
- #: wp-maintenance-admin.php:424
306
  msgid "Button color onclick:"
307
  msgstr ""
308
 
309
- #: wp-maintenance-admin.php:456
310
  msgid "Upload a picture"
311
  msgstr ""
312
 
313
- #: wp-maintenance-admin.php:458
314
  msgid "You use this picture:"
315
  msgstr ""
316
 
317
- #: wp-maintenance-admin.php:460 wp-maintenance-admin.php:478
 
318
  msgid "Enter a URL or upload an image."
319
  msgstr ""
320
 
321
- #: wp-maintenance-admin.php:461 wp-maintenance-admin.php:477
322
- #: wp-maintenance-admin.php:547
 
323
  msgid "Select or Upload your picture"
324
  msgstr ""
325
 
326
- #: wp-maintenance-admin.php:467
327
  msgid "Upload a background picture"
328
  msgstr ""
329
 
330
- #: wp-maintenance-admin.php:468
331
  msgid "Enable image background"
332
  msgstr ""
333
 
334
- #: wp-maintenance-admin.php:470
335
  msgid "You use this background picture:"
336
  msgstr ""
337
 
338
- #: wp-maintenance-admin.php:474
339
  msgid "You use this pattern:"
340
  msgstr ""
341
 
342
- #: wp-maintenance-admin.php:479
343
  msgid "Or choose a pattern:"
344
  msgstr ""
345
 
346
- #: wp-maintenance-admin.php:483
347
  msgid "NO PATTERN"
348
  msgstr ""
349
 
350
- #: wp-maintenance-admin.php:496
351
  msgid "Background picture options"
352
  msgstr ""
353
 
354
- #: wp-maintenance-admin.php:503
355
  msgid "Fixed"
356
  msgstr ""
357
 
358
- #: wp-maintenance-admin.php:508
359
  msgid "Slider image options"
360
  msgstr ""
361
 
362
- #: wp-maintenance-admin.php:509
363
  msgid "Enable Slider"
364
  msgstr ""
365
 
366
- #: wp-maintenance-admin.php:524
367
  msgid "Speed:"
368
  msgstr ""
369
 
370
- #: wp-maintenance-admin.php:528
371
  msgid "Display Auto Slider:"
372
  msgstr ""
373
 
374
- #: wp-maintenance-admin.php:532
375
  msgid "Display button navigation:"
376
  msgstr ""
377
 
378
- #: wp-maintenance-admin.php:539
379
  msgid "Above logo"
380
  msgstr ""
381
 
382
- #: wp-maintenance-admin.php:540
383
  msgid "Below logo"
384
  msgstr ""
385
 
386
- #: wp-maintenance-admin.php:541
387
  msgid "Below title & text"
388
  msgstr ""
389
 
390
- #: wp-maintenance-admin.php:577
391
  msgid "Link:"
392
  msgstr ""
393
 
394
- #: wp-maintenance-admin.php:580
395
  msgid "Delete this slide"
396
  msgstr ""
397
 
398
- #: wp-maintenance-admin.php:626
399
  msgid "Enable a countdown ?"
400
  msgstr ""
401
 
402
- #: wp-maintenance-admin.php:645
403
  msgid "Select the launch date/time"
404
  msgstr ""
405
 
406
- #: wp-maintenance-admin.php:648
407
  msgid "Enable seconds ?"
408
  msgstr ""
409
 
410
- #: wp-maintenance-admin.php:649
411
  msgid "Disable maintenance mode at the end of the countdown?"
412
  msgstr ""
413
 
414
- #: wp-maintenance-admin.php:650
415
  msgid "End message:"
416
  msgstr ""
417
 
418
- #: wp-maintenance-admin.php:666
419
  msgid "Today"
420
  msgstr ""
421
 
422
- #: wp-maintenance-admin.php:667
423
  msgid "Delete"
424
  msgstr ""
425
 
426
- #: wp-maintenance-admin.php:668 wp-maintenance-admin.php:687
 
 
427
  msgid "Close"
428
  msgstr ""
429
 
430
- #: wp-maintenance-admin.php:671
431
  msgid "Next month"
432
  msgstr ""
433
 
434
- #: wp-maintenance-admin.php:672
435
  msgid "Previous month"
436
  msgstr ""
437
 
438
- #: wp-maintenance-admin.php:673
439
  msgid "Select a month"
440
  msgstr ""
441
 
442
- #: wp-maintenance-admin.php:674
443
  msgid "Select a year"
444
  msgstr ""
445
 
446
- #: wp-maintenance-admin.php:717
447
  msgid "CSS style sheet code:"
448
  msgstr ""
449
 
450
- #: wp-maintenance-admin.php:718
451
  msgid ""
452
  "Edit the CSS sheet of your maintenance page here. Click \"Reset\" and \"Save"
453
  "\" to retrieve the default style sheet."
454
  msgstr ""
455
 
456
- #: wp-maintenance-admin.php:726
457
  msgid "Markers for colors"
458
  msgstr ""
459
 
460
- #: wp-maintenance-admin.php:731
461
  msgid "Use this code for text color"
462
  msgstr ""
463
 
464
- #: wp-maintenance-admin.php:735
465
  msgid "Use this code for background text color"
466
  msgstr ""
467
 
468
- #: wp-maintenance-admin.php:739
469
  msgid "Use this code for background color countdown"
470
  msgstr ""
471
 
472
- #: wp-maintenance-admin.php:743
473
  msgid "Use this code for size countdown"
474
  msgstr ""
475
 
476
- #: wp-maintenance-admin.php:747
477
  msgid "Use this code for countdown color"
478
  msgstr ""
479
 
480
- #: wp-maintenance-admin.php:752
481
  msgid "Need CSS code for MailPoet plugin?"
482
  msgstr ""
483
 
484
- #: wp-maintenance-admin.php:753 wp-maintenance-admin.php:768
 
485
  msgid "Click for select all"
486
  msgstr ""
487
 
488
- #: wp-maintenance-admin.php:767
489
  msgid "Need CSS code for MailChimp plugin?"
490
  msgstr ""
491
 
492
- #: wp-maintenance-admin.php:789
493
  msgid "Reset default CSS stylesheet ?"
494
  msgstr ""
495
 
496
- #: wp-maintenance-admin.php:808
497
  msgid "Theme maintenance page:"
498
  msgstr ""
499
 
500
- #: wp-maintenance-admin.php:809
501
  msgid ""
502
  "If you would use your maintenance.php page in your theme folder, click Yes."
503
  msgstr ""
504
 
505
- #: wp-maintenance-admin.php:812
506
  msgid "You can use this shortcode to include Google Analytics code:"
507
  msgstr ""
508
 
509
- #: wp-maintenance-admin.php:812
510
  msgid "You can use this shortcode to include Social Networks icons:"
511
  msgstr ""
512
 
513
- #: wp-maintenance-admin.php:821
514
  msgid "Roles and Capabilities:"
515
  msgstr ""
516
 
517
- #: wp-maintenance-admin.php:822
518
  msgid "Allow the site to display these roles:"
519
  msgstr ""
520
 
521
- #: wp-maintenance-admin.php:839
522
  msgid "IP autorized:"
523
  msgstr ""
524
 
525
- #: wp-maintenance-admin.php:840
526
  msgid ""
527
  "Allow the site to display these IP addresses. Please, enter one IP address "
528
  "by line:"
529
  msgstr ""
530
 
531
- #: wp-maintenance-admin.php:846
532
  msgid "ID pages autorized:"
533
  msgstr ""
534
 
535
- #: wp-maintenance-admin.php:847
536
  msgid ""
537
  "Allow the site to display these ID pages. Please, enter the ID pages "
538
  "separate with comma :"
539
  msgstr ""
540
 
541
- #: wp-maintenance-admin.php:852
542
  msgid "Header Code:"
543
  msgstr ""
544
 
545
- #: wp-maintenance-admin.php:853
546
  msgid ""
547
  "The following code will add to the <head> tag. Useful if you need to add "
548
  "additional scripts such as CSS or JS."
549
  msgstr ""
550
 
551
- #: wp-maintenance-admin.php:885
552
  msgid ""
553
  "This plugin has been developed for you for free by <a href=\"https://"
554
  "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is royalty "
@@ -557,84 +718,134 @@ msgid ""
557
  "improve this plugin for all."
558
  msgstr ""
559
 
560
- #: wp-maintenance-admin.php:889
561
- msgid "Visit"
 
562
  msgstr ""
563
 
564
- #: wp-maintenance-admin.php:889
565
- msgid ""
566
- "try the demo of the plugin, talk about this plugin to your surroundings!"
567
  msgstr ""
568
 
569
- #: wp-maintenance-admin.php:894
570
- msgid ""
571
- "If you want Donate (French Paypal) for my current and future developments:"
572
  msgstr ""
573
 
574
- #: wp-maintenance-admin.php:913
575
- msgid "WP Maintenance"
576
  msgstr ""
577
 
578
- #: wp-maintenance-admin.php:913
579
- msgid "is brought to you by"
580
  msgstr ""
581
 
582
- #: wp-maintenance-admin.php:913
583
- msgid "If you found this plugin useful"
584
  msgstr ""
585
 
586
- #: wp-maintenance-admin.php:913
587
- msgid "give it 5 &#9733; on WordPress.org"
588
  msgstr ""
589
 
590
- #: wp-maintenance.php:97
591
- msgid "Maintenance mode activated!"
592
  msgstr ""
593
 
594
- #: wp-maintenance.php:134
595
- msgid "This site is down for maintenance"
596
  msgstr ""
597
 
598
- #: wp-maintenance.php:135
599
- msgid "Come back quickly !"
600
  msgstr ""
601
 
602
- #: wp-maintenance.php:207 wp-maintenance.php:209
603
- msgid "Options for the maintenance page"
604
  msgstr ""
605
 
606
- #: wp-maintenance.php:235
607
- msgid "Choose This Image"
608
  msgstr ""
609
 
610
- #: wp-maintenance.php:236
611
- msgid "Choose Image"
612
  msgstr ""
613
 
614
- #: wp-maintenance.php:698
615
- msgid "Dashboard"
616
  msgstr ""
617
 
618
- #: wp-maintenance.php:797
619
- msgid "Days"
620
  msgstr ""
621
 
622
- #: wp-maintenance.php:797
623
- msgid "Hours"
624
  msgstr ""
625
 
626
- #: wp-maintenance.php:797
627
- msgid "Minutes"
628
  msgstr ""
629
 
630
- #: wp-maintenance.php:799
631
- msgid "Seconds"
632
  msgstr ""
633
 
634
- #: wp-maintenance.php:991
635
- msgid "Previous"
636
  msgstr ""
637
 
638
- #: wp-maintenance.php:992
639
- msgid "Next"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
640
  msgstr ""
2
  msgid ""
3
  msgstr ""
4
  "Project-Id-Version: WP Maintenance\n"
5
+ "POT-Creation-Date: 2017-04-04 17:25+0100\n"
6
  "PO-Revision-Date: 2015-03-19 11:19+0100\n"
7
  "Last-Translator: Florent Maillefaud <contact@restezconnectes.fr>\n"
8
  "Language-Team: Florent Maillefaud <contact@restezconnectes.fr>\n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Generator: Poedit 2.0\n"
14
  "X-Poedit-KeywordsList: __;_e\n"
15
  "X-Poedit-Basepath: ..\n"
16
  "Plural-Forms: nplurals=2; plural=n>1;\n"
17
  "X-Poedit-SourceCharset: UTF-8\n"
18
  "X-Poedit-SearchPath-0: .\n"
19
 
20
+ #: classes/countdown.php:34
21
+ msgid "Days"
22
  msgstr ""
23
 
24
+ #: classes/countdown.php:34
25
+ msgid "Hours"
26
  msgstr ""
27
 
28
+ #: classes/countdown.php:34
29
+ msgid "Minutes"
30
+ msgstr ""
31
+
32
+ #: classes/countdown.php:36
33
+ msgid "Seconds"
34
+ msgstr ""
35
+
36
+ #: classes/slider.php:90
37
+ msgid "Previous"
38
+ msgstr ""
39
+
40
+ #: classes/slider.php:91
41
+ msgid "Next"
42
+ msgstr ""
43
+
44
+ #: classes/wp-maintenance.php:43 classes/wp-maintenance.php:274
45
+ msgid "This site is down for maintenance"
46
  msgstr ""
47
 
48
+ #: classes/wp-maintenance.php:44 classes/wp-maintenance.php:275
49
+ msgid "Come back quickly!"
50
+ msgstr ""
51
+
52
+ #: classes/wp-maintenance.php:148 classes/wp-maintenance.php:264
53
+ #: views/wp-maintenance-admin.php:129 views/wp-maintenance-settings.php:30
54
+ msgid "Settings"
55
+ msgstr ""
56
+
57
+ #: classes/wp-maintenance.php:207
58
+ msgid "Maintenance mode activated!"
59
+ msgstr ""
60
+
61
+ #: classes/wp-maintenance.php:254 views/wp-maintenance-admin.php:124
62
+ #: views/wp-maintenance-dashboard.php:47
63
  msgid "General"
64
  msgstr ""
65
 
66
+ #: classes/wp-maintenance.php:256 views/wp-maintenance-admin.php:125
67
+ #: views/wp-maintenance-colors.php:34
68
  msgid "Colors & Fonts"
69
  msgstr ""
70
 
71
+ #: classes/wp-maintenance.php:258
72
+ msgid "Pictures"
73
  msgstr ""
74
 
75
+ #: classes/wp-maintenance.php:260 views/wp-maintenance-admin.php:127
76
  msgid "CountDown"
77
  msgstr ""
78
 
79
+ #: classes/wp-maintenance.php:262 views/wp-maintenance-admin.php:128
80
+ #: views/wp-maintenance-css.php:36
81
  msgid "CSS Style"
82
  msgstr ""
83
 
84
+ #: classes/wp-maintenance.php:394
85
+ msgid "Choose This Image"
86
+ msgstr ""
87
+
88
+ #: classes/wp-maintenance.php:395
89
+ msgid "Choose Image"
90
+ msgstr ""
91
+
92
+ #: classes/wp-maintenance.php:411 classes/wp-maintenance.php:419
93
+ #: classes/wp-maintenance.php:427 classes/wp-maintenance.php:436
94
+ #: classes/wp-maintenance.php:445 classes/wp-maintenance.php:454
95
+ msgid "You do not have sufficient privileges to access this page."
96
+ msgstr ""
97
+
98
+ #: classes/wp-maintenance.php:693
99
+ msgid "Dashboard"
100
+ msgstr ""
101
+
102
+ #: includes/functions.php:25 views/wp-maintenance-admin.php:35
103
+ msgid "Options saved."
104
+ msgstr ""
105
+
106
+ #: includes/functions.php:57
107
+ msgid "Go to Generals options"
108
+ msgstr ""
109
+
110
+ #: includes/functions.php:62
111
+ msgid "Go to Colors and Fonts options"
112
+ msgstr ""
113
+
114
+ #: includes/functions.php:67
115
+ msgid "Go to Pictures options"
116
+ msgstr ""
117
+
118
+ #: includes/functions.php:72
119
+ msgid "Go to Countdown options"
120
+ msgstr ""
121
+
122
+ #: includes/functions.php:77
123
+ msgid "Go to CSS options"
124
+ msgstr ""
125
+
126
+ #: includes/functions.php:82
127
+ msgid "Go to Settings options"
128
+ msgstr ""
129
+
130
+ #: includes/functions.php:136
131
+ msgid "ABOUT"
132
+ msgstr ""
133
+
134
+ #: includes/functions.php:138
135
+ msgid ""
136
+ "This plugin has been developed for you for free by <a href=\"https://"
137
+ "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is royalty "
138
+ "free, you can take it, modify it, distribute it as you see fit."
139
+ msgstr ""
140
+
141
+ #: includes/functions.php:139 views/wp-maintenance-admin.php:934
142
+ msgid "Visit"
143
+ msgstr ""
144
+
145
+ #: includes/functions.php:139 views/wp-maintenance-admin.php:934
146
+ msgid ""
147
+ "try the demo of the plugin, talk about this plugin to your surroundings!"
148
+ msgstr ""
149
+
150
+ #: includes/functions.php:141
151
+ msgid "Support this extension and my other developments (French Paypal):"
152
+ msgstr ""
153
+
154
+ #: includes/functions.php:153
155
+ msgid "DISCOVER"
156
+ msgstr ""
157
+
158
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
159
+ msgid "WP Maintenance"
160
+ msgstr ""
161
+
162
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
163
+ msgid "is brought to you by"
164
+ msgstr ""
165
+
166
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
167
+ msgid "If you found this plugin useful"
168
  msgstr ""
169
 
170
+ #: includes/functions.php:174 views/wp-maintenance-admin.php:958
171
+ msgid "give it 5 &#9733; on WordPress.org"
172
+ msgstr ""
173
+
174
+ #: views/wp-maintenance-admin.php:74
175
+ msgid "The Style Sheet has been reset!"
176
+ msgstr ""
177
+
178
+ #: views/wp-maintenance-admin.php:119
179
+ msgid "WP Maintenance Settings"
180
+ msgstr ""
181
+
182
+ #: views/wp-maintenance-admin.php:126 views/wp-maintenance-picture.php:60
183
+ msgid "Picture"
184
+ msgstr ""
185
+
186
+ #: views/wp-maintenance-admin.php:130
187
  msgid "About"
188
  msgstr ""
189
 
190
+ #: views/wp-maintenance-admin.php:143 views/wp-maintenance-dashboard.php:55
191
  msgid "Enable maintenance mode:"
192
  msgstr ""
193
 
194
+ #: views/wp-maintenance-admin.php:144 views/wp-maintenance-admin.php:200
195
+ #: views/wp-maintenance-admin.php:210 views/wp-maintenance-admin.php:277
196
+ #: views/wp-maintenance-admin.php:571 views/wp-maintenance-admin.php:575
197
+ #: views/wp-maintenance-admin.php:669 views/wp-maintenance-admin.php:854
198
+ #: views/wp-maintenance-colors.php:109 views/wp-maintenance-countdown.php:58
199
+ #: views/wp-maintenance-countdown.php:96 views/wp-maintenance-countdown.php:108
200
+ #: views/wp-maintenance-css.php:57 views/wp-maintenance-dashboard.php:59
201
+ #: views/wp-maintenance-dashboard.php:119
202
+ #: views/wp-maintenance-dashboard.php:143
203
+ #: views/wp-maintenance-dashboard.php:166
204
+ #: views/wp-maintenance-dashboard.php:243 views/wp-maintenance-picture.php:92
205
+ #: views/wp-maintenance-picture.php:152 views/wp-maintenance-picture.php:184
206
+ #: views/wp-maintenance-picture.php:191 views/wp-maintenance-settings.php:42
207
+ #: views/wp-maintenance-settings.php:61
208
  msgid "Yes"
209
  msgstr ""
210
 
211
+ #: views/wp-maintenance-admin.php:145 views/wp-maintenance-admin.php:572
212
+ #: views/wp-maintenance-admin.php:576 views/wp-maintenance-admin.php:855
213
+ #: views/wp-maintenance-colors.php:111 views/wp-maintenance-countdown.php:60
214
+ #: views/wp-maintenance-countdown.php:98 views/wp-maintenance-countdown.php:110
215
+ #: views/wp-maintenance-css.php:59 views/wp-maintenance-dashboard.php:61
216
+ #: views/wp-maintenance-dashboard.php:121
217
+ #: views/wp-maintenance-dashboard.php:145
218
+ #: views/wp-maintenance-dashboard.php:168
219
+ #: views/wp-maintenance-dashboard.php:245 views/wp-maintenance-picture.php:94
220
+ #: views/wp-maintenance-picture.php:154 views/wp-maintenance-picture.php:186
221
+ #: views/wp-maintenance-picture.php:193 views/wp-maintenance-settings.php:44
222
+ #: views/wp-maintenance-settings.php:63
223
  msgid "No"
224
  msgstr ""
225
 
226
+ #: views/wp-maintenance-admin.php:149 views/wp-maintenance-dashboard.php:69
227
  msgid "Title and text for the maintenance page:"
228
  msgstr ""
229
 
230
+ #: views/wp-maintenance-admin.php:150 views/wp-maintenance-dashboard.php:70
231
  msgid "Title:"
232
  msgstr ""
233
 
234
+ #: views/wp-maintenance-admin.php:153 views/wp-maintenance-admin.php:173
235
+ #: views/wp-maintenance-admin.php:618 views/wp-maintenance-dashboard.php:71
236
+ #: views/wp-maintenance-picture.php:238
237
  msgid "Text:"
238
  msgstr ""
239
 
240
+ #: views/wp-maintenance-admin.php:172 views/wp-maintenance-dashboard.php:91
241
  msgid "Text in the bottom of maintenance page:"
242
  msgstr ""
243
 
244
+ #: views/wp-maintenance-admin.php:192 views/wp-maintenance-dashboard.php:115
245
  msgid "Enable login access in the bottom ?"
246
  msgstr ""
247
 
248
+ #: views/wp-maintenance-admin.php:193 views/wp-maintenance-dashboard.php:129
249
  msgid "Enter a text to go to the dashboard:"
250
  msgstr ""
251
 
252
+ #: views/wp-maintenance-admin.php:195 views/wp-maintenance-dashboard.php:131
253
  msgid "Eg: connect to %DASHBOARD% here!"
254
  msgstr ""
255
 
256
+ #: views/wp-maintenance-admin.php:195 views/wp-maintenance-dashboard.php:131
257
  msgid ""
258
  "(%DASHBOARD% will be replaced with the link to the dashboard and the word "
259
  "\"Dashboard\")"
260
  msgstr ""
261
 
262
+ #: views/wp-maintenance-admin.php:199 views/wp-maintenance-dashboard.php:139
263
  msgid "Enable Google Analytics:"
264
  msgstr ""
265
 
266
+ #: views/wp-maintenance-admin.php:201 views/wp-maintenance-dashboard.php:153
267
  msgid "Enter your Google analytics tracking ID here:"
268
  msgstr ""
269
 
270
+ #: views/wp-maintenance-admin.php:203 views/wp-maintenance-dashboard.php:155
271
  msgid "Enter your domain URL:"
272
  msgstr ""
273
 
274
+ #: views/wp-maintenance-admin.php:209 views/wp-maintenance-dashboard.php:162
275
  msgid "Enable Social Networks:"
276
  msgstr ""
277
 
278
+ #: views/wp-maintenance-admin.php:211 views/wp-maintenance-dashboard.php:176
279
  msgid "Enter text for the title icons:"
280
  msgstr ""
281
 
282
+ #: views/wp-maintenance-admin.php:212 views/wp-maintenance-dashboard.php:177
283
  msgid "Follow me on"
284
  msgstr ""
285
 
286
+ #: views/wp-maintenance-admin.php:214 views/wp-maintenance-dashboard.php:179
287
  msgid "Drad and drop the lines to put in the order you want:"
288
  msgstr ""
289
 
290
+ #: views/wp-maintenance-admin.php:241 views/wp-maintenance-dashboard.php:206
291
  msgid "Choose icons size:"
292
  msgstr ""
293
 
294
+ #: views/wp-maintenance-admin.php:253 views/wp-maintenance-admin.php:579
295
+ #: views/wp-maintenance-dashboard.php:217 views/wp-maintenance-picture.php:199
296
  msgid "Position:"
297
  msgstr ""
298
 
299
+ #: views/wp-maintenance-admin.php:255 views/wp-maintenance-dashboard.php:219
300
  msgid "Top"
301
  msgstr ""
302
 
303
+ #: views/wp-maintenance-admin.php:256 views/wp-maintenance-dashboard.php:220
304
  msgid "Bottom"
305
  msgstr ""
306
 
307
+ #: views/wp-maintenance-admin.php:260 views/wp-maintenance-dashboard.php:223
308
  msgid "Align:"
309
  msgstr ""
310
 
311
+ #: views/wp-maintenance-admin.php:262 views/wp-maintenance-dashboard.php:225
312
  msgid "Left"
313
  msgstr ""
314
 
315
+ #: views/wp-maintenance-admin.php:263 views/wp-maintenance-dashboard.php:226
316
  msgid "Center"
317
  msgstr ""
318
 
319
+ #: views/wp-maintenance-admin.php:264 views/wp-maintenance-dashboard.php:227
320
  msgid "Right"
321
  msgstr ""
322
 
323
+ #: views/wp-maintenance-admin.php:267 views/wp-maintenance-dashboard.php:230
324
  msgid "You have your own icons? Enter the folder name of your theme here:"
325
  msgstr ""
326
 
327
+ #: views/wp-maintenance-admin.php:270 views/wp-maintenance-dashboard.php:232
328
  msgid "Reset Social Icon?"
329
  msgstr ""
330
 
331
+ #: views/wp-maintenance-admin.php:276 views/wp-maintenance-dashboard.php:239
332
  msgid "Enable Newletter:"
333
  msgstr ""
334
 
335
+ #: views/wp-maintenance-admin.php:278 views/wp-maintenance-dashboard.php:253
336
  msgid "Enter title for the newletter block:"
337
  msgstr ""
338
 
339
+ #: views/wp-maintenance-admin.php:280 views/wp-maintenance-dashboard.php:255
340
  msgid "Enter your newletter shortcode here:"
341
  msgstr ""
342
 
343
+ #: views/wp-maintenance-admin.php:282 views/wp-maintenance-dashboard.php:257
344
  msgid "Or enter your newletter iframe code here:"
345
  msgstr ""
346
 
347
+ #: views/wp-maintenance-admin.php:304 views/wp-maintenance-colors.php:44
348
  msgid "Choice general colors:"
349
  msgstr ""
350
 
351
+ #: views/wp-maintenance-admin.php:305 views/wp-maintenance-colors.php:45
352
  msgid "Background page color:"
353
  msgstr ""
354
 
355
+ #: views/wp-maintenance-admin.php:306 views/wp-maintenance-colors.php:46
356
  msgid "Header color:"
357
  msgstr ""
358
 
359
+ #: views/wp-maintenance-admin.php:310 views/wp-maintenance-colors.php:49
360
  msgid "Choice texts fonts and colors:"
361
  msgstr ""
362
 
363
+ #: views/wp-maintenance-admin.php:311 views/wp-maintenance-colors.php:50
364
  msgid "Text color:"
365
  msgstr ""
366
 
367
+ #: views/wp-maintenance-admin.php:313 views/wp-maintenance-colors.php:52
368
  msgid "Title font settings"
369
  msgstr ""
370
 
371
+ #: views/wp-maintenance-admin.php:327 views/wp-maintenance-admin.php:348
372
+ #: views/wp-maintenance-admin.php:387 views/wp-maintenance-admin.php:418
373
+ #: views/wp-maintenance-admin.php:437 views/wp-maintenance-colors.php:66
374
+ #: views/wp-maintenance-colors.php:87 views/wp-maintenance-colors.php:135
375
+ #: views/wp-maintenance-colors.php:154 views/wp-maintenance-colors.php:186
376
  msgid "Size:"
377
  msgstr ""
378
 
379
+ #: views/wp-maintenance-admin.php:343 views/wp-maintenance-admin.php:382
380
+ #: views/wp-maintenance-colors.php:82 views/wp-maintenance-colors.php:149
381
  msgid "Text font settings"
382
  msgstr ""
383
 
384
+ #: views/wp-maintenance-admin.php:364
385
  msgid "Frame settings"
386
  msgstr ""
387
 
388
+ #: views/wp-maintenance-admin.php:366
389
  msgid "Activate"
390
  msgstr ""
391
 
392
+ #: views/wp-maintenance-admin.php:366 views/wp-maintenance-colors.php:116
393
  msgid "Color:"
394
  msgstr ""
395
 
396
+ #: views/wp-maintenance-admin.php:367 views/wp-maintenance-colors.php:117
397
  msgid "Opacity:"
398
  msgstr ""
399
 
400
+ #: views/wp-maintenance-admin.php:369 views/wp-maintenance-admin.php:567
401
+ #: views/wp-maintenance-colors.php:119 views/wp-maintenance-picture.php:176
402
  msgid "Width:"
403
  msgstr ""
404
 
405
+ #: views/wp-maintenance-admin.php:377 views/wp-maintenance-colors.php:144
406
  msgid "Choice fonts and colors bottom page:"
407
  msgstr ""
408
 
409
+ #: views/wp-maintenance-admin.php:378 views/wp-maintenance-colors.php:145
410
  msgid "Bottom color:"
411
  msgstr ""
412
 
413
+ #: views/wp-maintenance-admin.php:379 views/wp-maintenance-colors.php:146
414
  msgid "Text bottom color:"
415
  msgstr ""
416
 
417
+ #: views/wp-maintenance-admin.php:406 views/wp-maintenance-colors.php:126
418
  msgid "Choice countdown fonts and colors:"
419
  msgstr ""
420
 
421
+ #: views/wp-maintenance-admin.php:407 views/wp-maintenance-colors.php:127
422
  msgid "Countdown text color:"
423
  msgstr ""
424
 
425
+ #: views/wp-maintenance-admin.php:408 views/wp-maintenance-colors.php:128
426
  msgid "Countdown background color:"
427
  msgstr ""
428
 
429
+ #: views/wp-maintenance-admin.php:413 views/wp-maintenance-colors.php:130
430
  msgid "Countdown font settings"
431
  msgstr ""
432
 
433
+ #: views/wp-maintenance-admin.php:430 views/wp-maintenance-colors.php:171
434
  msgid "Choice form color:"
435
  msgstr ""
436
 
437
+ #: views/wp-maintenance-admin.php:451 views/wp-maintenance-colors.php:200
438
  msgid "Field text color:"
439
  msgstr ""
440
 
441
+ #: views/wp-maintenance-admin.php:453 views/wp-maintenance-colors.php:202
442
  msgid "Field border color:"
443
  msgstr ""
444
 
445
+ #: views/wp-maintenance-admin.php:455 views/wp-maintenance-colors.php:204
446
  msgid "Field background color:"
447
  msgstr ""
448
 
449
+ #: views/wp-maintenance-admin.php:458 views/wp-maintenance-colors.php:207
450
  msgid "Button text color:"
451
  msgstr ""
452
 
453
+ #: views/wp-maintenance-admin.php:461 views/wp-maintenance-colors.php:210
454
  msgid "Button color:"
455
  msgstr ""
456
 
457
+ #: views/wp-maintenance-admin.php:464 views/wp-maintenance-colors.php:213
458
  msgid "Button color hover:"
459
  msgstr ""
460
 
461
+ #: views/wp-maintenance-admin.php:466 views/wp-maintenance-colors.php:215
462
  msgid "Button color onclick:"
463
  msgstr ""
464
 
465
+ #: views/wp-maintenance-admin.php:498
466
  msgid "Upload a picture"
467
  msgstr ""
468
 
469
+ #: views/wp-maintenance-admin.php:500 views/wp-maintenance-picture.php:81
470
  msgid "You use this picture:"
471
  msgstr ""
472
 
473
+ #: views/wp-maintenance-admin.php:502 views/wp-maintenance-admin.php:520
474
+ #: views/wp-maintenance-picture.php:76 views/wp-maintenance-picture.php:104
475
  msgid "Enter a URL or upload an image."
476
  msgstr ""
477
 
478
+ #: views/wp-maintenance-admin.php:503 views/wp-maintenance-admin.php:519
479
+ #: views/wp-maintenance-admin.php:589 views/wp-maintenance-picture.php:77
480
+ #: views/wp-maintenance-picture.php:105 views/wp-maintenance-picture.php:209
481
  msgid "Select or Upload your picture"
482
  msgstr ""
483
 
484
+ #: views/wp-maintenance-admin.php:509
485
  msgid "Upload a background picture"
486
  msgstr ""
487
 
488
+ #: views/wp-maintenance-admin.php:510
489
  msgid "Enable image background"
490
  msgstr ""
491
 
492
+ #: views/wp-maintenance-admin.php:512 views/wp-maintenance-picture.php:116
493
  msgid "You use this background picture:"
494
  msgstr ""
495
 
496
+ #: views/wp-maintenance-admin.php:516 views/wp-maintenance-picture.php:140
497
  msgid "You use this pattern:"
498
  msgstr ""
499
 
500
+ #: views/wp-maintenance-admin.php:521 views/wp-maintenance-picture.php:124
501
  msgid "Or choose a pattern:"
502
  msgstr ""
503
 
504
+ #: views/wp-maintenance-admin.php:525 views/wp-maintenance-picture.php:127
505
  msgid "NO PATTERN"
506
  msgstr ""
507
 
508
+ #: views/wp-maintenance-admin.php:538 views/wp-maintenance-picture.php:106
509
  msgid "Background picture options"
510
  msgstr ""
511
 
512
+ #: views/wp-maintenance-admin.php:545 views/wp-maintenance-picture.php:112
513
  msgid "Fixed"
514
  msgstr ""
515
 
516
+ #: views/wp-maintenance-admin.php:550 views/wp-maintenance-picture.php:161
517
  msgid "Slider image options"
518
  msgstr ""
519
 
520
+ #: views/wp-maintenance-admin.php:551 views/wp-maintenance-picture.php:148
521
  msgid "Enable Slider"
522
  msgstr ""
523
 
524
+ #: views/wp-maintenance-admin.php:566 views/wp-maintenance-picture.php:175
525
  msgid "Speed:"
526
  msgstr ""
527
 
528
+ #: views/wp-maintenance-admin.php:570 views/wp-maintenance-picture.php:181
529
  msgid "Display Auto Slider:"
530
  msgstr ""
531
 
532
+ #: views/wp-maintenance-admin.php:574 views/wp-maintenance-picture.php:188
533
  msgid "Display button navigation:"
534
  msgstr ""
535
 
536
+ #: views/wp-maintenance-admin.php:581 views/wp-maintenance-picture.php:201
537
  msgid "Above logo"
538
  msgstr ""
539
 
540
+ #: views/wp-maintenance-admin.php:582 views/wp-maintenance-picture.php:202
541
  msgid "Below logo"
542
  msgstr ""
543
 
544
+ #: views/wp-maintenance-admin.php:583 views/wp-maintenance-picture.php:203
545
  msgid "Below title & text"
546
  msgstr ""
547
 
548
+ #: views/wp-maintenance-admin.php:619 views/wp-maintenance-picture.php:239
549
  msgid "Link:"
550
  msgstr ""
551
 
552
+ #: views/wp-maintenance-admin.php:622 views/wp-maintenance-picture.php:242
553
  msgid "Delete this slide"
554
  msgstr ""
555
 
556
+ #: views/wp-maintenance-admin.php:668 views/wp-maintenance-countdown.php:50
557
  msgid "Enable a countdown ?"
558
  msgstr ""
559
 
560
+ #: views/wp-maintenance-admin.php:687 views/wp-maintenance-countdown.php:89
561
  msgid "Select the launch date/time"
562
  msgstr ""
563
 
564
+ #: views/wp-maintenance-admin.php:690 views/wp-maintenance-countdown.php:101
565
  msgid "Enable seconds ?"
566
  msgstr ""
567
 
568
+ #: views/wp-maintenance-admin.php:691 views/wp-maintenance-countdown.php:113
569
  msgid "Disable maintenance mode at the end of the countdown?"
570
  msgstr ""
571
 
572
+ #: views/wp-maintenance-admin.php:692 views/wp-maintenance-countdown.php:117
573
  msgid "End message:"
574
  msgstr ""
575
 
576
+ #: views/wp-maintenance-admin.php:708 views/wp-maintenance-countdown.php:151
577
  msgid "Today"
578
  msgstr ""
579
 
580
+ #: views/wp-maintenance-admin.php:709 views/wp-maintenance-countdown.php:152
581
  msgid "Delete"
582
  msgstr ""
583
 
584
+ #: views/wp-maintenance-admin.php:710 views/wp-maintenance-admin.php:729
585
+ #: views/wp-maintenance-countdown.php:153
586
+ #: views/wp-maintenance-countdown.php:172
587
  msgid "Close"
588
  msgstr ""
589
 
590
+ #: views/wp-maintenance-admin.php:713 views/wp-maintenance-countdown.php:156
591
  msgid "Next month"
592
  msgstr ""
593
 
594
+ #: views/wp-maintenance-admin.php:714 views/wp-maintenance-countdown.php:157
595
  msgid "Previous month"
596
  msgstr ""
597
 
598
+ #: views/wp-maintenance-admin.php:715 views/wp-maintenance-countdown.php:158
599
  msgid "Select a month"
600
  msgstr ""
601
 
602
+ #: views/wp-maintenance-admin.php:716 views/wp-maintenance-countdown.php:159
603
  msgid "Select a year"
604
  msgstr ""
605
 
606
+ #: views/wp-maintenance-admin.php:759
607
  msgid "CSS style sheet code:"
608
  msgstr ""
609
 
610
+ #: views/wp-maintenance-admin.php:760 views/wp-maintenance-css.php:45
611
  msgid ""
612
  "Edit the CSS sheet of your maintenance page here. Click \"Reset\" and \"Save"
613
  "\" to retrieve the default style sheet."
614
  msgstr ""
615
 
616
+ #: views/wp-maintenance-admin.php:770 views/wp-maintenance-css.php:68
617
  msgid "Markers for colors"
618
  msgstr ""
619
 
620
+ #: views/wp-maintenance-admin.php:775 views/wp-maintenance-css.php:73
621
  msgid "Use this code for text color"
622
  msgstr ""
623
 
624
+ #: views/wp-maintenance-admin.php:779 views/wp-maintenance-css.php:77
625
  msgid "Use this code for background text color"
626
  msgstr ""
627
 
628
+ #: views/wp-maintenance-admin.php:783 views/wp-maintenance-css.php:81
629
  msgid "Use this code for background color countdown"
630
  msgstr ""
631
 
632
+ #: views/wp-maintenance-admin.php:787 views/wp-maintenance-css.php:85
633
  msgid "Use this code for size countdown"
634
  msgstr ""
635
 
636
+ #: views/wp-maintenance-admin.php:791 views/wp-maintenance-css.php:89
637
  msgid "Use this code for countdown color"
638
  msgstr ""
639
 
640
+ #: views/wp-maintenance-admin.php:796 views/wp-maintenance-css.php:94
641
  msgid "Need CSS code for MailPoet plugin?"
642
  msgstr ""
643
 
644
+ #: views/wp-maintenance-admin.php:797 views/wp-maintenance-admin.php:812
645
+ #: views/wp-maintenance-css.php:95 views/wp-maintenance-css.php:110
646
  msgid "Click for select all"
647
  msgstr ""
648
 
649
+ #: views/wp-maintenance-admin.php:811 views/wp-maintenance-css.php:109
650
  msgid "Need CSS code for MailChimp plugin?"
651
  msgstr ""
652
 
653
+ #: views/wp-maintenance-admin.php:833 views/wp-maintenance-css.php:53
654
  msgid "Reset default CSS stylesheet ?"
655
  msgstr ""
656
 
657
+ #: views/wp-maintenance-admin.php:852
658
  msgid "Theme maintenance page:"
659
  msgstr ""
660
 
661
+ #: views/wp-maintenance-admin.php:853 views/wp-maintenance-settings.php:38
662
  msgid ""
663
  "If you would use your maintenance.php page in your theme folder, click Yes."
664
  msgstr ""
665
 
666
+ #: views/wp-maintenance-admin.php:856 views/wp-maintenance-settings.php:51
667
  msgid "You can use this shortcode to include Google Analytics code:"
668
  msgstr ""
669
 
670
+ #: views/wp-maintenance-admin.php:856 views/wp-maintenance-settings.php:51
671
  msgid "You can use this shortcode to include Social Networks icons:"
672
  msgstr ""
673
 
674
+ #: views/wp-maintenance-admin.php:865 views/wp-maintenance-settings.php:71
675
  msgid "Roles and Capabilities:"
676
  msgstr ""
677
 
678
+ #: views/wp-maintenance-admin.php:866 views/wp-maintenance-settings.php:72
679
  msgid "Allow the site to display these roles:"
680
  msgstr ""
681
 
682
+ #: views/wp-maintenance-admin.php:883 views/wp-maintenance-settings.php:91
683
  msgid "IP autorized:"
684
  msgstr ""
685
 
686
+ #: views/wp-maintenance-admin.php:884 views/wp-maintenance-settings.php:92
687
  msgid ""
688
  "Allow the site to display these IP addresses. Please, enter one IP address "
689
  "by line:"
690
  msgstr ""
691
 
692
+ #: views/wp-maintenance-admin.php:890 views/wp-maintenance-settings.php:98
693
  msgid "ID pages autorized:"
694
  msgstr ""
695
 
696
+ #: views/wp-maintenance-admin.php:891 views/wp-maintenance-settings.php:99
697
  msgid ""
698
  "Allow the site to display these ID pages. Please, enter the ID pages "
699
  "separate with comma :"
700
  msgstr ""
701
 
702
+ #: views/wp-maintenance-admin.php:897 views/wp-maintenance-settings.php:105
703
  msgid "Header Code:"
704
  msgstr ""
705
 
706
+ #: views/wp-maintenance-admin.php:898 views/wp-maintenance-settings.php:106
707
  msgid ""
708
  "The following code will add to the <head> tag. Useful if you need to add "
709
  "additional scripts such as CSS or JS."
710
  msgstr ""
711
 
712
+ #: views/wp-maintenance-admin.php:930
713
  msgid ""
714
  "This plugin has been developed for you for free by <a href=\"https://"
715
  "restezconnectes.fr\" target=\"_blank\">Florent Maillefaud</a>. It is royalty "
718
  "improve this plugin for all."
719
  msgstr ""
720
 
721
+ #: views/wp-maintenance-admin.php:939
722
+ msgid ""
723
+ "If you want Donate (French Paypal) for my current and future developments:"
724
  msgstr ""
725
 
726
+ #: views/wp-maintenance-colors.php:105
727
+ msgid "Activate Frame"
 
728
  msgstr ""
729
 
730
+ #: views/wp-maintenance-colors.php:219
731
+ #, php-format
732
+ msgid "Enable %s to customize the forms"
733
  msgstr ""
734
 
735
+ #: views/wp-maintenance-colors.php:219
736
+ msgid "newsletter option"
737
  msgstr ""
738
 
739
+ #: views/wp-maintenance-colors.php:223
740
+ msgid "Enable Mailpoet or MailChimp extensions to customize the forms"
741
  msgstr ""
742
 
743
+ #: views/wp-maintenance-countdown.php:24
744
+ msgid "Countdown"
745
  msgstr ""
746
 
747
+ #: views/wp-maintenance-countdown.php:70
748
+ msgid "Personnalize Colors and Fonts"
749
  msgstr ""
750
 
751
+ #: views/wp-maintenance-countdown.php:89
752
+ msgid "at"
753
  msgstr ""
754
 
755
+ #: views/wp-maintenance-countdown.php:148
756
+ msgid "January"
757
  msgstr ""
758
 
759
+ #: views/wp-maintenance-countdown.php:148
760
+ msgid "February"
761
  msgstr ""
762
 
763
+ #: views/wp-maintenance-countdown.php:148
764
+ msgid "March"
765
  msgstr ""
766
 
767
+ #: views/wp-maintenance-countdown.php:148
768
+ msgid "April"
769
  msgstr ""
770
 
771
+ #: views/wp-maintenance-countdown.php:148
772
+ msgid "May"
773
  msgstr ""
774
 
775
+ #: views/wp-maintenance-countdown.php:148
776
+ msgid "June"
777
  msgstr ""
778
 
779
+ #: views/wp-maintenance-countdown.php:148
780
+ msgid "July"
781
  msgstr ""
782
 
783
+ #: views/wp-maintenance-countdown.php:148
784
+ msgid "August"
785
  msgstr ""
786
 
787
+ #: views/wp-maintenance-countdown.php:148
788
+ msgid "September"
789
  msgstr ""
790
 
791
+ #: views/wp-maintenance-countdown.php:148
792
+ msgid "October"
793
  msgstr ""
794
 
795
+ #: views/wp-maintenance-countdown.php:148
796
+ msgid "November"
797
  msgstr ""
798
 
799
+ #: views/wp-maintenance-countdown.php:148
800
+ msgid "December"
801
+ msgstr ""
802
+
803
+ #: views/wp-maintenance-countdown.php:150
804
+ msgid "Sunday"
805
+ msgstr ""
806
+
807
+ #: views/wp-maintenance-countdown.php:150
808
+ msgid "Monday"
809
+ msgstr ""
810
+
811
+ #: views/wp-maintenance-countdown.php:150
812
+ msgid "Tuesday"
813
+ msgstr ""
814
+
815
+ #: views/wp-maintenance-countdown.php:150
816
+ msgid "Wednesday"
817
+ msgstr ""
818
+
819
+ #: views/wp-maintenance-countdown.php:150
820
+ msgid "Thurday"
821
+ msgstr ""
822
+
823
+ #: views/wp-maintenance-countdown.php:150
824
+ msgid "Friday"
825
+ msgstr ""
826
+
827
+ #: views/wp-maintenance-countdown.php:150
828
+ msgid "Saturday"
829
+ msgstr ""
830
+
831
+ #: views/wp-maintenance-picture.php:75
832
+ msgid "Header picture"
833
+ msgstr ""
834
+
835
+ #: views/wp-maintenance-picture.php:88
836
+ msgid "Background picture or pattern"
837
+ msgstr ""
838
+
839
+ #: views/wp-maintenance-settings.php:38
840
+ msgid "Theme maintenance page"
841
+ msgstr ""
842
+
843
+ #: views/wp-maintenance-settings.php:57
844
+ msgid "Delete custom settings upon plugin deactivation?"
845
+ msgstr ""
846
+
847
+ #: views/wp-maintenance-settings.php:57
848
+ msgid ""
849
+ "If you set \"Yes\" all custom settings will be deleted from database upon "
850
+ "plugin deactivation"
851
  msgstr ""
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === Plugin Name ===
2
  Contributors: Florent73
3
  Donate link: https://wpmaintenance.info/a-propos/
4
- Tags: WordPress.com, maintenance, atttente, pause, travaux, construction, launch, coming soon
5
  Requires at least: 3.0
6
  Tested up to: 4.7
7
- Stable tag: 2.8.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -27,35 +27,47 @@ maintenance.pot file available
27
  == Installation ==
28
  1. Upload the full directory into your '/wp-content/plugins' directory
29
  2. Activate the plugin at the plugin administration page
30
- 3. Open the plugin configuration page, which is located under 'Option -> WP Maintenance'
 
31
 
32
  == Screenshots ==
33
  1. General view
34
  2. View by visitors to your site
35
- 3. Color selection
36
- 4. Upload a personnal picture
37
  5. Countdown settings
38
- 6. Various settings
 
39
 
40
  == Frequently Asked Questions ==
41
 
42
- = This plugin is free ? =
43
 
44
- Yes. If you want, you can support this project here : https://wpmaintenance.info/a-propos/
45
 
46
  = Can I change the plugin code? =
47
 
48
  Yes. Thank you for submitting your changes to update the plugin.
49
 
 
 
 
 
 
 
50
  == Upgrade Notice ==
51
 
52
- = 2.8.4 =
53
  This version is stable
54
 
55
  == Changelog ==
56
 
57
- = 2.8.4 =
58
- * Fixed bug with Divi theme
 
 
 
 
59
 
60
  = 2.8.3 =
61
  * Allow the site to display pages by ID
1
  === Plugin Name ===
2
  Contributors: Florent73
3
  Donate link: https://wpmaintenance.info/a-propos/
4
+ Tags: Maintenance, Construction, Launch, Coming soon
5
  Requires at least: 3.0
6
  Tested up to: 4.7
7
+ Stable tag: 3.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
27
  == Installation ==
28
  1. Upload the full directory into your '/wp-content/plugins' directory
29
  2. Activate the plugin at the plugin administration page
30
+
31
+ You will find 'WP Maintenance' menu in your WordPress admin panel
32
 
33
  == Screenshots ==
34
  1. General view
35
  2. View by visitors to your site
36
+ 3. Colors and fonts settings
37
+ 4. Upload a personal header, background and slides picture
38
  5. Countdown settings
39
+ 6. CSS settings
40
+ 7. Others settings
41
 
42
  == Frequently Asked Questions ==
43
 
44
+ = WP Maintenance Needs Your Support =
45
 
46
+ It is hard to continue development and support for this free plugin without contributions from users like you. If you enjoy using WP Maintenance and find it useful, please consider <a href="https://www.paypal.me/RestezConnectes/25">making a donation</a>. Your donation will help encourage and support the plugin's continued development and better user support.
47
 
48
  = Can I change the plugin code? =
49
 
50
  Yes. Thank you for submitting your changes to update the plugin.
51
 
52
+ = Translations =
53
+
54
+
55
+
56
+ You can translate WP Maintenance on [__translate.wordpress.org__](https://translate.wordpress.org/projects/wp-plugins/wp-maintenance).
57
+
58
  == Upgrade Notice ==
59
 
60
+ = 3.0 =
61
  This version is stable
62
 
63
  == Changelog ==
64
 
65
+ = 3.0 =
66
+ * Rebuilt plugin core from the ground up
67
+ * Add CodeMirror for codes options
68
+ * Add WordPress editor for texts and titles options
69
+ * Add new options
70
+ * Add new design
71
 
72
  = 2.8.3 =
73
  * Allow the site to display pages by ID
screenshot-1.png CHANGED
Binary file
screenshot-2.png CHANGED
Binary file
screenshot-3.png CHANGED
Binary file
screenshot-4.png CHANGED
Binary file
screenshot-5.png CHANGED
Binary file
screenshot-6.png CHANGED
Binary file
screenshot-7.png ADDED
Binary file
uninstall.php DELETED
@@ -1,18 +0,0 @@
1
- <?php
2
-
3
- defined( 'ABSPATH' )
4
- or die( 'No direct load ! ' );
5
- /**
6
- * Désinstallation du plugin WP Maintenance
7
- */
8
- function wpm_uninstall() {
9
- //if(get_option('wp_maintenance_settings')) { delete_option('wp_maintenance_settings'); }
10
- //if(get_option('wp_maintenance_version')) { delete_option('wp_maintenance_version'); }
11
- //if(get_option('wp_maintenance_style')) { delete_option('wp_maintenance_style'); }
12
- //delete_option('wp_maintenance_limit');
13
- delete_option('wp_maintenance_active');
14
- //if(get_option('wp_maintenance_social')) { delete_option('wp_maintenance_social'); }
15
- //if(get_option('wp_maintenance_social_options')) { delete_option('wp_maintenance_social_options'); }
16
-
17
- }
18
- register_deactivation_hook(__FILE__, 'wpm_uninstall');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
views/wp-maintenance-colors.php ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die( 'Not allowed' );
4
+
5
+ $messageUpdate = 0;
6
+ /* Update des paramètres */
7
+ if( isset($_POST['action']) && $_POST['action'] == 'update_colors' ) {
8
+
9
+ $options_saved = wpm_update_settings($_POST["wp_maintenance_settings"]);
10
+ $options_saved = true;
11
+ $messageUpdate = 1;
12
+ }
13
+
14
+ // Récupère les paramètres sauvegardés
15
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
16
+ $paramMMode = get_option('wp_maintenance_settings');
17
+
18
+ ?>
19
+ <script type="text/javascript">
20
+ jQuery(document).ready(function() {
21
+ jQuery('#font_title').fontselect();
22
+ jQuery('#font_text').fontselect();
23
+ jQuery('#font_text_bottom').fontselect();
24
+ jQuery('#font_text_cpt').fontselect('Pacifico');
25
+ jQuery('#font_text_newletter').fontselect();
26
+ });
27
+ </script>
28
+ <div class="wrap">
29
+
30
+ <form method="post" action="" name="valide_settings">
31
+ <input type="hidden" name="action" value="update_colors" />
32
+
33
+ <!-- HEADER -->
34
+ <?php echo wpm_get_header( __('Colors & Fonts', 'wp-maintenance'), 'dashicons-art', $messageUpdate ) ?>
35
+ <!-- END HEADER -->
36
+
37
+ <div style="margin-top: 80px;">
38
+
39
+ <div style="float:left;width:73%;margin-right:1%;border: 1px solid #ddd;background-color:#fff;padding:10px;">
40
+
41
+
42
+
43
+ <!-- COULEUR DU FOND DE PAGE -->
44
+ <h3><?php _e('Choice general colors:', 'wp-maintenance'); ?></h3>
45
+ <em><?php _e('Background page color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php if( isset($paramMMode['color_bg']) && $paramMMode['color_bg']!='' ) { echo $paramMMode['color_bg']; } ?>" name="wp_maintenance_settings[color_bg]" class="wpm-color-field" data-default-color="#f1f1f1" /> <br />
46
+ <em><?php _e('Header color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php if( isset($paramMMode['color_bg_header']) && $paramMMode['color_bg_header']!='' ) { echo $paramMMode['color_bg_header']; } ?>" name="wp_maintenance_settings[color_bg_header]" class="wpm-color-field" data-default-color="#333333" />
47
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
48
+
49
+ <h3><?php _e('Choice texts fonts and colors:', 'wp-maintenance'); ?></h3>
50
+ <em><?php _e('Text color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php if( isset($paramMMode['color_txt']) && $paramMMode['color_txt']!='' ) { echo $paramMMode['color_txt']; } else { echo '#333333'; } ?>" name="wp_maintenance_settings[color_txt]" class="wpm-color-field" data-default-color="#333333" /><br /><br />
51
+ <!-- POLICE DU TITRE -->
52
+ <em><stong><?php _e('Title font settings', 'wp-maintenance'); ?></stong></em>
53
+ <table cellspacing="10">
54
+ <tr>
55
+ <td valign="top" align="left"><input name="wp_maintenance_settings[font_title]" id="font_title" type="text" value="<?php if( isset($paramMMode['font_title']) && $paramMMode['font_title']!='' ) { echo $paramMMode['font_title']; } else { echo 'PT Sans'; } ?>" />
56
+
57
+ <div id="fontSelect" class="fontSelect">
58
+ <div class="arrow-down"></div>
59
+ </div>
60
+
61
+ <div id="fontSelect2" class="fontSelect">
62
+ <div class="arrow-down"></div>
63
+ </div>
64
+ </td>
65
+ <td>
66
+ <?php _e('Size:', 'wp-maintenance'); ?>
67
+ <input type="text" class="wpm-form-field" size="3" name="wp_maintenance_settings[font_title_size]" value="<?php if( isset($paramMMode['font_title_size']) && $paramMMode['font_title_size']!='' ) { echo stripslashes($paramMMode['font_title_size']); } else { echo '16'; } ?>" />px
68
+
69
+ </td>
70
+ </tr>
71
+ <tr>
72
+ <td rowspan="2">
73
+ <input type="radio" name="wp_maintenance_settings[font_title_weigth]" value="normal" <?php if( (isset($paramMMode['font_title_weigth']) && $paramMMode['font_title_weigth']=='normal') || empty($paramMMode['font_title_weigth']) ) { echo 'checked'; } ?> >Normal
74
+ <input type="radio" name="wp_maintenance_settings[font_title_weigth]" value="bold" <?php if( isset($paramMMode['font_title_weigth']) && $paramMMode['font_title_weigth']=='bold') { echo 'checked'; } ?>>Bold
75
+ <input type="checkbox" name="wp_maintenance_settings[font_title_style]" value="italic" <?php if( isset($paramMMode['font_title_style']) && $paramMMode['font_title_style']=='italic') { echo 'checked'; } ?>>Italic
76
+ </td>
77
+ </tr>
78
+ </table>
79
+ <!-- FIN POLICE DU TITRE-->
80
+
81
+ <!-- POLICE DU TEXTE -->
82
+ <br /><em><?php _e('Text font settings', 'wp-maintenance'); ?></em>
83
+ <table cellspacing="10">
84
+ <tr>
85
+ <td valign="top" align="left"><input name="wp_maintenance_settings[font_text]" id="font_text" type="text" value="<?php if( isset($paramMMode['font_text']) && $paramMMode['font_text']!='' ) { echo $paramMMode['font_text']; } else { echo 'PT Sans'; } ?>" /></td>
86
+ <td>
87
+ <?php _e('Size:', 'wp-maintenance'); ?>
88
+ <input type="text" class="wpm-form-field" size="3" name="wp_maintenance_settings[font_text_size]" value="<?php if( isset($paramMMode['font_text_size']) && $paramMMode['font_text_size']!='' ) { echo stripslashes($paramMMode['font_text_size']); } else { echo '14'; }?>" />px
89
+
90
+ </td>
91
+ </tr>
92
+ <tr>
93
+ <td rowspan="2">
94
+ <input type="radio" name="wp_maintenance_settings[font_text_weigth]" value="normal" <?php if( (isset($paramMMode['font_text_weigth']) && $paramMMode['font_text_weigth']=='normal') || empty($paramMMode['font_text_weigth']) ) { echo 'checked'; } ?> >Normal
95
+ <input type="radio" name="wp_maintenance_settings[font_text_weigth]" value="bold" <?php if( isset($paramMMode['font_text_weigth']) && $paramMMode['font_text_weigth']=='bold') { echo 'checked'; } ?>>Bold
96
+ <input type="checkbox" name="wp_maintenance_settings[font_text_style]" value="italic" <?php if( isset($paramMMode['font_text_style']) && $paramMMode['font_text_style']=='italic') { echo 'checked'; } ?>>Italic
97
+ </td>
98
+ </tr>
99
+ </table>
100
+ <!-- FIN POLICE DU TEXTE -->
101
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
102
+
103
+ <!-- CADRE -->
104
+ <div>
105
+ <div style="float:left; width:70%;"><h3><?php _e('Activate Frame', 'wp-maintenance'); ?></h3></div>
106
+ <div style="float:left; width:30%;text-align:right;padding-top: 5px;">
107
+ <div class="switch-field">
108
+ <input class="switch_left" type="radio" onclick="AfficherTexte('option-container');" id="switch_container" name="wp_maintenance_settings[container_active]" value="1" <?php if( empty($paramMMode['container_active']) || isset($paramMMode['container_active']) && $paramMMode['container_active']==1) { echo ' checked'; } ?>/>
109
+ <label for="switch_container"><?php _e('Yes', 'wp-maintenance'); ?></label>
110
+ <input class="switch_right" type="radio" onclick="CacherTexte('option-container');" id="switch_container_no" name="wp_maintenance_settings[container_active]" value="0" <?php if( empty($paramMMode['container_active']) || isset($paramMMode['container_active']) && $paramMMode['container_active']==0) { echo ' checked'; } ?> />
111
+ <label for="switch_container_no"><?php _e('No', 'wp-maintenance'); ?></label>
112
+ </div>
113
+ </div>
114
+ <div class="clear"></div><a name="countdown"></a>
115
+ </div>
116
+ <?php _e('Color:', 'wp-maintenance'); ?><br /> <input type="text" value="<?php if( isset($paramMMode['container_color']) && $paramMMode['container_color']!='' ) { echo $paramMMode['container_color']; } else { echo '#ffffff'; }?>" name="wp_maintenance_settings[container_color]" class="wpm-color-field" data-default-color="#ffffff" /><br />
117
+ <?php _e('Opacity:', 'wp-maintenance'); ?>
118
+ <input type="text" class="wpm-form-field" size="3" name="wp_maintenance_settings[container_opacity]" value="<?php if( isset($paramMMode['container_opacity']) && $paramMMode['container_opacity']!='' ) { echo $paramMMode['container_opacity']; } else { echo '0.5'; } ?>" />
119
+ <?php _e('Width:', 'wp-maintenance'); ?>
120
+ <input type="text" class="wpm-form-field" size="2" name="wp_maintenance_settings[container_width]" value="<?php if( isset($paramMMode['container_width']) && $paramMMode['container_width']!='' ) { echo $paramMMode['container_width']; } else { echo '80'; } ?>" />%
121
+ <!-- FIN CADRE -->
122
+
123
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
124
+ <a name="countdown"></a>
125
+ <!-- COMPTE A REBOURS -->
126
+ <h3><?php _e('Choice countdown fonts and colors:', 'wp-maintenance'); ?></h3>
127
+ <em><?php _e('Countdown text color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php if( isset($paramMMode['color_cpt']) && $paramMMode['color_cpt']!='' ) { echo $paramMMode['color_cpt']; } else { echo '#333333'; } ?>" name="wp_maintenance_settings[color_cpt]" class="wpm-color-field" data-default-color="#333333" /><br />
128
+ <em><?php _e('Countdown background color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php if( isset($paramMMode['color_cpt_bg']) && $paramMMode['color_cpt_bg']!='' ) { echo $paramMMode['color_cpt_bg']; } ?>" name="wp_maintenance_settings[color_cpt_bg]" class="wpm-color-field" data-default-color="#ffffff" /><br /><br />
129
+ <!-- POLICE DU COMPTEUR -->
130
+ <em><?php _e('Countdown font settings', 'wp-maintenance'); ?></em>
131
+ <table cellspacing="10">
132
+ <tr>
133
+ <td valign="top" align="left"><input name="wp_maintenance_settings[font_cpt]" id="font_text_cpt" type="text" value="<?php if( isset($paramMMode['font_cpt']) && $paramMMode['font_cpt']!='' ) { echo $paramMMode['font_cpt']; } else { echo 'Pacifico'; } ?>" /></td>
134
+ <td>
135
+ <?php _e('Size:', 'wp-maintenance'); ?>
136
+ <input type="text" size="3" class="wpm-form-field" id="date_cpt_size" name="wp_maintenance_settings[date_cpt_size]" value="<?php if( isset($paramMMode['date_cpt_size']) && $paramMMode['date_cpt_size']!='' ) { echo trim($paramMMode['date_cpt_size']); } else { echo '16'; } ?>" />px
137
+
138
+ </td>
139
+ </tr>
140
+ </table>
141
+ <!-- FIN POLICE DU COMPTEUR -->
142
+
143
+ <!-- BOTTOM PAGE -->
144
+ <h3><?php _e('Choice fonts and colors bottom page:', 'wp-maintenance'); ?></h3>
145
+ <em><?php _e('Bottom color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php if( isset($paramMMode['color_bg_bottom']) && $paramMMode['color_bg_bottom']!='' ) { echo $paramMMode['color_bg_bottom']; } else { echo '#333333'; } ?>" name="wp_maintenance_settings[color_bg_bottom]" class="wpm-color-field" data-default-color="#333333" /> <br />
146
+ <em><?php _e('Text bottom color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php if( isset($paramMMode['color_text_bottom']) && $paramMMode['color_text_bottom']!='' ) { echo $paramMMode['color_text_bottom']; } else { echo '#FFFFFF'; } ?>" name="wp_maintenance_settings[color_text_bottom]" class="wpm-color-field" data-default-color="#ffffff" /><br /><br />
147
+
148
+ <!-- POLICE DU TEXTE BAS DE PAGE -->
149
+ <em><?php _e('Text font settings', 'wp-maintenance'); ?></em>
150
+ <table cellspacing="10">
151
+ <tr>
152
+ <td valign="top" align="left"><input name="wp_maintenance_settings[font_text_bottom]" id="font_text_bottom" type="text" value="<?php if( isset($paramMMode['font_text_bottom']) && $paramMMode['font_text_bottom']!='' ) { echo $paramMMode['font_text_bottom']; } else { echo 'PT Sans'; } ?>" /></td>
153
+ <td>
154
+ <?php _e('Size:', 'wp-maintenance'); ?>
155
+ <input type="text" class="wpm-form-field" size="3" name="wp_maintenance_settings[font_bottom_size]" value="<?php if( isset($paramMMode['font_bottom_size']) && $paramMMode['font_bottom_size']!='' ) { echo stripslashes($paramMMode['font_bottom_size']); } else { echo '12'; } ?>" />px
156
+
157
+ </td>
158
+ </tr>
159
+ <tr>
160
+ <td rowspan="2">
161
+ <input type="radio" name="wp_maintenance_settings[font_bottom_weigth]" value="normal" <?php if( (isset($paramMMode['font_bottom_weigth']) && $paramMMode['font_bottom_weigth']=='normal') || empty($paramMMode['font_bottom_weigth']) ) { echo 'checked'; } ?> >Normal
162
+ <input type="radio" name="wp_maintenance_settings[font_bottom_weigth]" value="bold" <?php if( isset($paramMMode['font_bottom_weigth']) && $paramMMode['font_bottom_weigth']=='bold') { echo 'checked'; } ?>>Bold
163
+ <input type="checkbox" name="wp_maintenance_settings[font_bottom_style]" value="italic" <?php if( isset($paramMMode['font_bottom_style']) && $paramMMode['font_bottom_style']=='italic') { echo 'checked'; } ?>>Italic
164
+ </td>
165
+ </tr>
166
+ </table>
167
+ <!-- FIN POLICE DU TEXTE BAS DE PAGE -->
168
+
169
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
170
+
171
+ <h3><?php _e('Choice form color:', 'wp-maintenance'); ?></h3>
172
+ <?php
173
+ if (
174
+ is_plugin_active( 'wysija-newsletters/index.php' ) || is_plugin_active( 'mailchimp-for-wp/mailchimp-for-wp.php' )
175
+
176
+ ) {
177
+
178
+ if ( isset($paramMMode['newletter']) && $paramMMode['newletter']==1 ) {
179
+ //if( isset($paramMMode['code_newletter']) && (strpos($paramMMode['code_newletter'], 'wysija_form')!=false || strpos($paramMMode['code_newletter'], 'mc4wp_form')!=false ) && (
180
+ ?>
181
+ <!-- COULEUR WYJIYA -->
182
+ <table cellspacing="10">
183
+ <tr>
184
+ <td valign="top" align="left"><input name="wp_maintenance_settings[newletter_font_text]" id="font_text_newletter" type="text" value="<?php if( isset($paramMMode['newletter_font_text']) && $paramMMode['newletter_font_text']!='' ) { echo $paramMMode['newletter_font_text']; } ?>" /></td>
185
+ <td>
186
+ <?php _e('Size:', 'wp-maintenance'); ?>
187
+ <input type="text" class="wpm-form-field" size="3" name="wp_maintenance_settings[newletter_size]" value="<?php if( isset($paramMMode['newletter_size']) && $paramMMode['newletter_size']!='') { echo stripslashes($paramMMode['newletter_size']); } else { echo '14'; } ?>" />px
188
+
189
+ </td>
190
+ </tr>
191
+ <tr>
192
+ <td rowspan="2">
193
+ <input type="radio" name="wp_maintenance_settings[newletter_font_weigth]" value="normal" <?php if( (isset($paramMMode['newletter_font_weigth']) && $paramMMode['newletter_font_weigth']=='normal') || empty($paramMMode['newletter_font_weigth']) ) { echo 'checked'; } ?> >Normal
194
+ <input type="radio" name="wp_maintenance_settings[newletter_font_weigth]" value="bold" <?php if( isset($paramMMode['newletter_font_weigth']) && $paramMMode['newletter_font_weigth']=='bold') { echo 'checked'; } ?>>Bold
195
+ <input type="checkbox" name="wp_maintenance_settings[newletter_font_style]" value="italic" <?php if( isset($paramMMode['newletter_font_style']) && $paramMMode['newletter_font_style']=='italic') { echo 'checked'; } ?>>Italic
196
+ </td>
197
+ </tr>
198
+ </table>
199
+ <br />
200
+ <em><?php _e('Field text color:', 'wp-maintenance'); ?></em> <br />
201
+ <input type="text" value="<?php if( isset($paramMMode['color_field_text']) && $paramMMode['color_field_text']!='' ) { echo $paramMMode['color_field_text']; } else { echo '#333333'; } ?>" name="wp_maintenance_settings[color_field_text]" class="wpm-color-field" data-default-color="#333333" /><br />
202
+ <em><?php _e('Field border color:', 'wp-maintenance'); ?></em> <br />
203
+ <input type="text" value="<?php if( isset($paramMMode['color_field_border']) && $paramMMode['color_field_border']!='' ) { echo $paramMMode['color_field_border']; } else { echo '#333333'; } ?>" name="wp_maintenance_settings[color_field_border]" class="wpm-color-field" data-default-color="#333333" /><br />
204
+ <em><?php _e('Field background color:', 'wp-maintenance'); ?></em> <br />
205
+ <input type="text" value="<?php if( isset($paramMMode['color_field_background']) && $paramMMode['color_field_background']!='' ) { echo $paramMMode['color_field_background']; } else { echo '#cccccc'; } ?>" name="wp_maintenance_settings[color_field_background]" class="wpm-color-field" data-default-color="#cccccc" />
206
+ <br />
207
+ <em><?php _e('Button text color:', 'wp-maintenance'); ?></em> <br />
208
+ <input type="text" value="<?php if( isset($paramMMode['color_text_button']) && $paramMMode['color_text_button']!='' ) { echo $paramMMode['color_text_button']; } else { echo '#ffffff'; } ?>" name="wp_maintenance_settings[color_text_button]" class="wpm-color-field" data-default-color="#ffffff" />
209
+ <br />
210
+ <em><?php _e('Button color:', 'wp-maintenance'); ?></em> <br />
211
+ <input type="text" value="<?php if( isset($paramMMode['color_button']) && $paramMMode['color_button']!='' ) { echo $paramMMode['color_button']; } else { echo '#1e73be'; } ?>" name="wp_maintenance_settings[color_button]" class="wpm-color-field" data-default-color="#1e73be" />
212
+ <br />
213
+ <em><?php _e('Button color hover:', 'wp-maintenance'); ?></em> <br />
214
+ <input type="text" value="<?php if( isset($paramMMode['color_button_hover']) && $paramMMode['color_button_hover']!='' ) { echo $paramMMode['color_button_hover']; } else { echo '#ffffff'; } ?>" name="wp_maintenance_settings[color_button_hover]" class="wpm-color-field" data-default-color="#ffffff" /><br />
215
+ <em><?php _e('Button color onclick:', 'wp-maintenance'); ?></em> <br />
216
+ <input type="text" value="<?php if( isset($paramMMode['color_button_onclick']) && $paramMMode['color_button_onclick']!='' ) { echo $paramMMode['color_button_onclick']; } else { echo '#ffffff'; } ?>" name="wp_maintenance_settings[color_button_onclick]" class="wpm-color-field" data-default-color="#ffffff" />
217
+ <?php
218
+ } else {
219
+ printf( __('Enable %s to customize the forms', 'wp-maintenance'), '<a href="'.admin_url().'?page=wp-maintenance#newsletter">'.__('newsletter option', 'wp-maintenance').'</a>' );
220
+ }
221
+
222
+ } else {
223
+ _e('Enable Mailpoet or MailChimp extensions to customize the forms', 'wp-maintenance');
224
+
225
+ } ?>
226
+
227
+ <p>
228
+ <?php submit_button(); ?>
229
+ </p>
230
+
231
+ </div>
232
+
233
+ <?php echo wpm_sidebar(); ?>
234
+
235
+ </div>
236
+ </form>
237
+ <?php echo wpm_footer(); ?>
238
+ </div>
views/wp-maintenance-countdown.php ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die( 'Not allowed' );
4
+
5
+ $messageUpdate = 0;
6
+ /* Update des paramètres */
7
+ if( isset($_POST['action']) && $_POST['action'] == 'update_countdown' ) {
8
+
9
+ $options_saved = wpm_update_settings($_POST["wp_maintenance_settings"]);
10
+ $messageUpdate = 1;
11
+ }
12
+
13
+ // Récupère les paramètres sauvegardés
14
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
15
+ $paramMMode = get_option('wp_maintenance_settings');
16
+ ?>
17
+
18
+ <div class="wrap">
19
+
20
+ <form method="post" action="" name="valide_settings">
21
+ <input type="hidden" name="action" value="update_countdown" />
22
+
23
+ <!-- HEADER -->
24
+ <?php echo wpm_get_header( __('Countdown', 'wp-maintenance'), 'dashicons-clock', $messageUpdate ) ?>
25
+ <!-- END HEADER -->
26
+
27
+ <div style="margin-top: 80px;">
28
+
29
+ <div style="float:left;width:73%;margin-right:1%;border: 1px solid #ddd;background-color:#fff;padding:10px;">
30
+
31
+ <!-- ACTIVER COMPTEUR -->
32
+ <?php
33
+
34
+ // Old version compte à rebours
35
+ if( isset($paramMMode['date_cpt_jj']) && empty($paramMMode['cptdate']) ) {
36
+ $paramMMode['cptdate'] = $paramMMode['date_cpt_aa'].'/'.$paramMMode['date_cpt_mm'].'/'.$paramMMode['date_cpt_jj'];
37
+ } else if ( empty($paramMMode['cptdate']) ) {
38
+ $paramMMode['cptdate'] = date('d').'/'.date('m').'/'.date('Y');
39
+ }
40
+
41
+ if( isset($paramMMode['date_cpt_hh']) && empty($paramMMode['cpttime']) ) {
42
+ $paramMMode['cpttime'] = $paramMMode['date_cpt_hh'].':'.$paramMMode['date_cpt_mn'];
43
+ } else if ( empty($paramMMode['cpttime']) ) {
44
+ $paramMMode['cpttime'] = date( 'H:i', (time()+3600) );
45
+ }
46
+
47
+ ?>
48
+ <div>
49
+ <div style="float:left; width:70%;">
50
+ <h3><?php _e('Enable a countdown ?', 'wp-maintenance'); ?>
51
+ <?php if( isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==1 ) { ?>
52
+ <?php } ?>
53
+ </h3>
54
+ </div>
55
+ <div style="float:left; width:30%;text-align:right;margin-top:5px;">
56
+ <div class="switch-field">
57
+ <input class="switch_left" type="radio" onclick="AfficherTexte('option-countdown');" id="switch_countdown" name="wp_maintenance_settings[active_cpt]" value="1" <?php if( isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==1) { echo ' checked'; } ?>/>
58
+ <label for="switch_countdown"><?php _e('Yes', 'wp-maintenance'); ?></label>
59
+ <input class="switch_right" type="radio" onclick="CacherTexte('option-countdown');" id="switch_countdown_no" name="wp_maintenance_settings[active_cpt]" value="0" <?php if( empty($paramMMode['active_cpt']) || isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==0) { echo ' checked'; } ?> />
60
+ <label for="switch_countdown_no"><?php _e('No', 'wp-maintenance'); ?></label>
61
+ </div>
62
+ </div>
63
+ <div class="clear"></div>
64
+ </div>
65
+
66
+
67
+ <div id="option-countdown" style="<?php if( empty($paramMMode['active_cpt']) || isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==0) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
68
+
69
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
70
+ <div style="text-align:right;"><a href="<?php echo admin_url() ?>admin.php?page=wp-maintenance-colors#countdown" title="<?php _e('Personnalize Colors and Fonts', 'wp-maintenance'); ?>" alt="<?php _e('Personnalize Colors and Fonts', 'wp-maintenance'); ?>" class="wpmadashicons"><span class="dashicons dashicons-art"></span> <?php _e('Personnalize Colors and Fonts', 'wp-maintenance'); ?></a></div>
71
+
72
+ <?php
73
+ if( isset($paramMMode['cptdate']) && !empty($paramMMode['cptdate']) ) {
74
+ $startDate = $paramMMode['cptdate'];
75
+ }
76
+ if( isset($paramMMode['cpttime']) && !empty($paramMMode['cpttime']) ) {
77
+ $startHour = $paramMMode['cpttime'];
78
+ }
79
+ if( (isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==0) || empty($paramMMode['active_cpt']) ) {
80
+ $startDate = date_i18n( date("Y").'/'.date("m").'/'.date("d") );
81
+ $timeFormats = array_unique( apply_filters( 'time_formats', array( 'H:i' ) ) );
82
+ foreach ( $timeFormats as $format ) {
83
+ $startHour = date_i18n( $format );
84
+ }
85
+ $newMin = explode(':', $startHour);
86
+ //$startHour = $newMin[0].':'.ceil($newMin[1]/5)*5;
87
+ }
88
+ ?>
89
+ <small><?php _e('Select the launch date/time', 'wp-maintenance'); ?></small><br /><img src="<?php echo WP_PLUGIN_URL.'/wp-maintenance/images/schedule_clock.png'; ?>" class="datepicker" width="48" height="48" style="vertical-align: middle;margin-right:5px;">&nbsp;<input id="cptdate" class="datepicker" name="wp_maintenance_settings[cptdate]" type="text" autofocuss data-value="<?php echo $startDate; ?>"> <?php _e('at', 'wp-maintenance'); ?> <input id="cpttime" class="timepicker" type="time" name="wp_maintenance_settings[cpttime]" value="<?php echo $startHour; ?>" size="4" autofocuss>
90
+ <div id="wpmdatecontainer"></div>
91
+ <br /><br />
92
+ <div>
93
+ <div style="float:left;width:190px;">
94
+ <div class="switch-field" style="margin-left:0px!important;">
95
+ <input class="switch_left" type="radio" id="switch_left" name="wp_maintenance_settings[active_cpt_s]" value="1" <?php if( isset($paramMMode['active_cpt_s']) && $paramMMode['active_cpt_s']==1) { echo ' checked'; } ?>/>
96
+ <label for="switch_left"><?php _e('Yes', 'wp-maintenance'); ?></label>
97
+ <input class="switch_right" type="radio" id="switch_right" name="wp_maintenance_settings[active_cpt_s]" value="0" <?php if( empty($paramMMode['active_cpt_s']) || isset($paramMMode['active_cpt_s']) && $paramMMode['active_cpt_s']==0) { echo ' checked'; } ?> />
98
+ <label for="switch_right"><?php _e('No', 'wp-maintenance'); ?></label>
99
+ </div>
100
+ </div>
101
+ <div style="float:left;margin-top:12px;"><?php _e('Enable seconds ?', 'wp-maintenance'); ?></div>
102
+ <div class="clear"></div>
103
+ </div>
104
+ <div>
105
+ <div style="float:left;width:190px;">
106
+ <div class="switch-field" style="margin-left:0px!important;">
107
+ <input class="switch_left" type="radio" id="switch_disable" name="wp_maintenance_settings[disable]" value="1" <?php if( isset($paramMMode['disable']) && $paramMMode['disable']==1) { echo ' checked'; } ?>/>
108
+ <label for="switch_disable"><?php _e('Yes', 'wp-maintenance'); ?></label>
109
+ <input class="switch_right" type="radio" id="switch_disable_no" name="wp_maintenance_settings[disable]" value="0" <?php if( empty($paramMMode['disable']) || isset($paramMMode['disable']) && $paramMMode['disable']==0) { echo ' checked'; } ?> />
110
+ <label for="switch_disable_no"><?php _e('No', 'wp-maintenance'); ?></label>
111
+ </div>
112
+ </div>
113
+ <div style="float:left;margin-top:12px;"><?php _e('Disable maintenance mode at the end of the countdown?', 'wp-maintenance'); ?></div>
114
+ <div class="clear"></div>
115
+ </div>
116
+ <br />
117
+ <?php _e('End message:', 'wp-maintenance'); ?><br />
118
+ <?php
119
+ $settingsCountdown = array(
120
+ 'wpautop' => true, // use wpautop?
121
+ 'media_buttons' => false, // show insert/upload button(s)
122
+ 'textarea_name' => 'wp_maintenance_settings[message_cpt_fin]', // set the textarea name to something different, square brackets [] can be used here
123
+ 'textarea_rows' => get_option('default_post_edit_rows', 10), // rows="..."
124
+ 'tabindex' => '',
125
+ 'editor_css' => '', // extra styles for both visual and HTML editors buttons,
126
+ 'editor_class' => 'message_cpt_fin', // add extra class(es) to the editor textarea
127
+ 'teeny' => true, // output the minimal editor config used in Press This
128
+ 'dfw' => false, // replace the default fullscreen with DFW (supported on the front-end in WordPress 3.4)
129
+ 'tinymce' => true, // load TinyMCE, can be used to pass settings directly to TinyMCE using an array()
130
+ 'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array()
131
+ );
132
+ $textCpt_fin = '';
133
+ if( isset($paramMMode['message_cpt_fin']) ) { $textCpt_fin = stripslashes($paramMMode['message_cpt_fin']); }
134
+ ?>
135
+ <?php wp_editor( nl2br($textCpt_fin), 'message_cpt_fin', $settingsCountdown ); ?><br />
136
+
137
+ <script type="text/javascript">
138
+
139
+ jQuery(document).ready(function() {
140
+
141
+ var $input = jQuery( '.datepicker' ).pickadate({
142
+ formatSubmit: 'yyyy/mm/dd',
143
+ container: '#wpmdatecontainer',
144
+ closeOnSelect: true,
145
+ closeOnClear: false,
146
+ firstDay: 1,
147
+ min: new Date(<?php echo date('Y').','.(date('m')-1).','.date('d'); ?>),
148
+ monthsFull: [ '<?php _e('January', 'wp-maintenance'); ?>', '<?php _e('February', 'wp-maintenance'); ?>', '<?php _e('March', 'wp-maintenance'); ?>', '<?php _e('April', 'wp-maintenance'); ?>', '<?php _e('May', 'wp-maintenance'); ?>', '<?php _e('June', 'wp-maintenance'); ?>', '<?php _e('July', 'wp-maintenance'); ?>', '<?php _e('August', 'wp-maintenance'); ?>', '<?php _e('September', 'wp-maintenance'); ?>', '<?php _e('October', 'wp-maintenance'); ?>', '<?php _e('November', 'wp-maintenance'); ?>', '<?php _e('December', 'wp-maintenance'); ?>' ],
149
+ monthsShort: [ 'Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Aou', 'Sep', 'Oct', 'Nov', 'Dec' ],
150
+ weekdaysShort: [ '<?php _e('Sunday', 'wp-maintenance'); ?>', '<?php _e('Monday', 'wp-maintenance'); ?>', '<?php _e('Tuesday', 'wp-maintenance'); ?>', '<?php _e('Wednesday', 'wp-maintenance'); ?>', '<?php _e('Thurday', 'wp-maintenance'); ?>', '<?php _e('Friday', 'wp-maintenance'); ?>', '<?php _e('Saturday', 'wp-maintenance'); ?>' ],
151
+ today: "<?php _e('Today', 'wp-maintenance'); ?>",
152
+ clear: '<?php _e('Delete', 'wp-maintenance'); ?>',
153
+ close: '<?php _e('Close', 'wp-maintenance'); ?>',
154
+
155
+ // Accessibility labels
156
+ labelMonthNext: '<?php _e('Next month', 'wp-maintenance'); ?>',
157
+ labelMonthPrev: '<?php _e('Previous month', 'wp-maintenance'); ?>',
158
+ labelMonthSelect: '<?php _e('Select a month', 'wp-maintenance'); ?>',
159
+ labelYearSelect: '<?php _e('Select a year', 'wp-maintenance'); ?>',
160
+
161
+ selectMonths: true,
162
+ selectYears: true,
163
+
164
+
165
+ })
166
+
167
+ var picker = $input.pickadate('picker')
168
+
169
+
170
+ var $input = jQuery( '.timepicker' ).pickatime({
171
+ //container: '#wpmtimecontainer',
172
+ clear: '<?php _e('Close', 'wp-maintenance'); ?>',
173
+ interval: 5,
174
+ editable: undefined,
175
+ format: 'HH:i', // retour ce format dans le input
176
+ formatSubmit: 'HH:i', // return ce format en post
177
+ formatLabel: '<b>HH</b>:i', // Affichage
178
+
179
+ })
180
+ var picker = $input.pickatime('picker')
181
+
182
+ });
183
+
184
+ </script>
185
+ <?php submit_button(); ?>
186
+ </div>
187
+ </div>
188
+
189
+ <?php echo wpm_sidebar(); ?>
190
+
191
+ </div>
192
+ </form>
193
+
194
+ <?php echo wpm_footer(); ?>
195
+
196
+ </div>
views/wp-maintenance-css.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die( 'Not allowed' );
4
+
5
+ $messageUpdate = 0;
6
+ /* Update des paramètres */
7
+ if( isset($_POST['action']) && $_POST['action'] == 'update_css' ) {
8
+
9
+ update_option('wp_maintenance_style', stripslashes($_POST["wp_maintenance_style"]));
10
+ $options_saved = true;
11
+
12
+ $messageUpdate = 1;
13
+ }
14
+
15
+ /* Si on réinitialise les feuille de styles */
16
+ if( isset($_POST['wpm_initcss']) && $_POST['wpm_initcss']==1) {
17
+ update_option( 'wp_maintenance_style', wpm_print_style() );
18
+ $options_saved = true;
19
+ //echo '<div id="message" class="updated fade"><p><strong>'.__('The Style Sheet has been reset!', 'wp-maintenance').'</strong></p></div>';
20
+ }
21
+
22
+ ?>
23
+ <style>
24
+ .CodeMirror {
25
+ border: 1px solid #eee;
26
+ height: 550px;
27
+ }
28
+
29
+ </style>
30
+ <div class="wrap">
31
+
32
+ <form method="post" action="" name="valide_settings">
33
+ <input type="hidden" name="action" value="update_css" />
34
+
35
+ <!-- HEADER -->
36
+ <?php echo wpm_get_header( __('CSS Style', 'wp-maintenance'), 'dashicons-media-code', $messageUpdate ) ?>
37
+ <!-- END HEADER -->
38
+
39
+ <div style="margin-top: 80px;">
40
+
41
+ <div style="float:left;width:73%;margin-right:1%;border: 1px solid #ddd;background-color:#fff;padding:10px;">
42
+
43
+
44
+ <!-- UTILISER UNE FEUILLE DE STYLE PERSO -->
45
+ <?php _e('Edit the CSS sheet of your maintenance page here. Click "Reset" and "Save" to retrieve the default style sheet.', 'wp-maintenance'); ?><br /><br />
46
+ <div style="float:left;width:100%;margin-right:15px;">
47
+ <TEXTAREA NAME="wp_maintenance_style" id="wpmaintenancestyle" COLS=70 ROWS=24 style="height:250px;"><?php echo stripslashes(trim(get_option('wp_maintenance_style'))); ?></TEXTAREA>
48
+ </div>
49
+
50
+ <div class="clear"></div>
51
+ <br />
52
+ <div>
53
+ <div style="float:left; width:70%;"><h4><?php _e('Reset default CSS stylesheet ?', 'wp-maintenance'); ?></h4></div>
54
+ <div style="float:left; width:30%;text-align:right;">
55
+ <div class="switch-field">
56
+ <input class="switch_left" type="radio" id="switch_left" name="wpm_initcss" value="1" />
57
+ <label for="switch_left"><?php _e('Yes', 'wp-maintenance'); ?></label>
58
+ <input class="switch_right_no" type="radio" id="switch_right" name="wpm_initcss" value="0" checked />
59
+ <label for="switch_right"><?php _e('No', 'wp-maintenance'); ?></label>
60
+ </div>
61
+ </div>
62
+ <div class="clear"></div>
63
+ </div>
64
+
65
+ <table class="wp-list-table widefat fixed" cellspacing="0">
66
+ <tbody id="the-list">
67
+ <tr>
68
+ <td><h3 class="hndle"><span><strong><?php _e('Markers for colors', 'wp-maintenance'); ?></strong></span></h3></td>
69
+ <td></td>
70
+ </tr>
71
+ <tr>
72
+ <td>#_COLORTXT</td>
73
+ <td><?php _e('Use this code for text color', 'wp-maintenance'); ?></td>
74
+ </tr>
75
+ <tr>
76
+ <td>#_COLORBG</td>
77
+ <td><?php _e('Use this code for background text color', 'wp-maintenance'); ?></td>
78
+ </tr>
79
+ <tr>
80
+ <td>#_COLORCPTBG</td>
81
+ <td><?php _e('Use this code for background color countdown', 'wp-maintenance'); ?></td>
82
+ </tr>
83
+ <tr>
84
+ <td>#_DATESIZE</td>
85
+ <td><?php _e('Use this code for size countdown', 'wp-maintenance'); ?></td>
86
+ </tr>
87
+ <tr>
88
+ <td>#_COLORCPT</td>
89
+ <td><?php _e('Use this code for countdown color', 'wp-maintenance'); ?></td>
90
+ </tr>
91
+ </tbody>
92
+ </table>
93
+ <br />
94
+ <a href="" onclick="AfficherCacher('divcss'); return false" ><?php _e('Need CSS code for MailPoet plugin?', 'wp-maintenance'); ?></a>
95
+ <div id="divcss" style="display:none;"><i><?php _e('Click for select all', 'wp-maintenance'); ?></i><br />
96
+ <textarea id="css-mailpoet" onclick="select()" rows="15" cols="50%">
97
+ .abs-req { display: none; }
98
+ .widget_wysija_cont .wysija-submit { }
99
+ .widget_wysija input { }
100
+ .wysija-submit-field { }
101
+ .wysija-submit-field:hover { }
102
+ .widget_wysija input:focus { }
103
+ .wysija-submit-field:active { }
104
+ .widget_wysija .wysija-submit, .widget_wysija .wysija-paragraph { }
105
+ .wysija-submit-field { }
106
+ </textarea>
107
+ </div>
108
+ <br />
109
+ <a href="" onclick="AfficherCacher('divcss2'); return false" ><?php _e('Need CSS code for MailChimp plugin?', 'wp-maintenance'); ?></a>
110
+ <div id="divcss2" style="display:none;"><i><?php _e('Click for select all', 'wp-maintenance'); ?></i><br />
111
+ <textarea id="css-mailchimp" onclick="select()" rows="15" cols="50%">
112
+ .mc4wp-form { } /* the form element */
113
+ .mc4wp-form p { } /* form paragraphs */
114
+ .mc4wp-form label { } /* labels */
115
+ .mc4wp-form input { } /* input fields */
116
+ .mc4wp-form input[type="checkbox"] { } /* checkboxes */
117
+ .mc4wp-form input[type="submit"] { } /* submit button */
118
+ .mc4wp-form input[type="submit"]:hover { }
119
+ .mc4wp-form input[type="submit"]:active { }
120
+ .mc4wp-alert { } /* success & error messages */
121
+ .mc4wp-success { } /* success message */
122
+ .mc4wp-error { } /* error messages */
123
+ </textarea>
124
+ </div>
125
+ <p>
126
+ <?php submit_button(); ?>
127
+ </p>
128
+ </div>
129
+
130
+ <?php echo wpm_sidebar(); ?>
131
+
132
+ </div>
133
+ </form>
134
+ <script>
135
+ var editor = CodeMirror.fromTextArea(document.getElementById("wpmaintenancestyle"), {
136
+ lineNumbers: true,
137
+ matchBrackets: true,
138
+ textWrapping: true,
139
+ lineWrapping: true,
140
+ mode: "text/x-scss",
141
+ theme:"material"
142
+ });
143
+ </script>
144
+
145
+ <?php echo wpm_footer(); ?>
146
+
147
+ </div>
views/wp-maintenance-dashboard.php ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die( 'Not allowed' );
4
+
5
+
6
+ $messageUpdate = 0;
7
+ /* Update des paramètres */
8
+ if( isset($_POST['action']) && $_POST['action'] == 'update_general' ) {
9
+
10
+ if( isset($_POST["wp_maintenance_social_options"]['reset']) && $_POST["wp_maintenance_social_options"]['reset'] ==1 ) {
11
+ unset($_POST["wp_maintenance_social"]);
12
+ $_POST["wp_maintenance_social"] = '';
13
+ }
14
+ update_option('wp_maintenance_social', $_POST["wp_maintenance_social"]);
15
+ update_option('wp_maintenance_social_options', $_POST["wp_maintenance_social_options"]);
16
+ update_option('wp_maintenance_active', $_POST["wp_maintenance_active"]);
17
+
18
+ $options_saved = wpm_update_settings($_POST["wp_maintenance_settings"]);
19
+
20
+ $messageUpdate = 1;
21
+ }
22
+
23
+ // Récupère les paramètres sauvegardés
24
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
25
+ $paramMMode = get_option('wp_maintenance_settings');
26
+
27
+ // Récupère si le status est actif ou non
28
+ $statusActive = get_option('wp_maintenance_active');
29
+
30
+ // Récupère les Reseaux Sociaux
31
+ $paramSocial = get_option('wp_maintenance_social');
32
+ if(get_option('wp_maintenance_social_options')) { extract(get_option('wp_maintenance_social_options')); }
33
+ $paramSocialOption = get_option('wp_maintenance_social_options');
34
+
35
+ ?>
36
+ <style>
37
+ .sortable { list-style-type: none; margin: 0; padding: 0; width: 100%; }
38
+ .sortable li { padding: 0.4em; height: 40px;cursor: pointer; cursor: move; }
39
+ .sortable li span { font-size: 15px;margin-right: 0.8em;cursor: move; }
40
+ .sortable li:hover { background-color: #d2d2d2; }
41
+ .CodeMirror {
42
+ border: 1px solid #eee;
43
+ height: auto;
44
+ }
45
+ </style>
46
+
47
+
48
+ <div class="clear"></div>
49
+ <div class="wrap">
50
+ <form method="post" action="" id="valide_settings" name="valide_settings">
51
+ <input type="hidden" name="action" value="update_general" />
52
+
53
+ <!-- HEADER -->
54
+ <?php echo wpm_get_header( __('General', 'wp-maintenance'), 'dashicons-admin-settings', $messageUpdate ) ?>
55
+ <!-- END HEADER -->
56
+
57
+ <div style="margin-top: 80px;">
58
+
59
+ <div style="float:left;width:73%;margin-right:1%;border: 1px solid #ddd;background-color:#fff;padding:10px;">
60
+
61
+ <div>
62
+ <div style="float:left; width:70%;"><h3><?php _e('Enable maintenance mode:', 'wp-maintenance'); ?></h3></div>
63
+ <div style="float:left; width:30%;text-align:right;">
64
+ <div class="switch-field">
65
+ <input class="switch_left" type="radio" id="switch_left" name="wp_maintenance_active" value="1" <?php if( isset($statusActive) && $statusActive==1) { echo ' checked'; } ?>/>
66
+ <label for="switch_left"><?php _e('Yes', 'wp-maintenance'); ?></label>
67
+ <input class="switch_right" type="radio" id="switch_right" name="wp_maintenance_active" value="0" <?php if( empty($statusActive) || isset($statusActive) && $statusActive==0) { echo ' checked'; } ?> />
68
+ <label for="switch_right"><?php _e('No', 'wp-maintenance'); ?></label>
69
+ </div>
70
+ </div>
71
+ <div class="clear"></div>
72
+ </div>
73
+
74
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
75
+
76
+ <h3><?php _e('Title and text for the maintenance page:', 'wp-maintenance'); ?></h3>
77
+ <?php _e('Title:', 'wp-maintenance'); ?><br /><input class="wpm-form-field" type="text" size="100%" name="wp_maintenance_settings[titre_maintenance]" value="<?php if( isset($paramMMode['titre_maintenance']) && $paramMMode['titre_maintenance']!='' ) { echo stripslashes($paramMMode['titre_maintenance']); } ?>" /><br /><br />
78
+ <?php _e('Text:', 'wp-maintenance'); ?><br />
79
+ <?php
80
+ $settingsTextmaintenance = array(
81
+ 'wpautop' => true, // use wpautop?
82
+ 'media_buttons' => false, // show insert/upload button(s)
83
+ 'textarea_name' => 'wp_maintenance_settings[text_maintenance]', // set the textarea name to something different, square brackets [] can be used here
84
+ 'textarea_rows' => get_option('default_post_edit_rows', 10), // rows="..."
85
+ 'tabindex' => '',
86
+ 'editor_css' => '', // extra styles for both visual and HTML editors buttons,
87
+ 'editor_class' => 'wpm-textmaintenance', // add extra class(es) to the editor textarea
88
+ 'teeny' => true, // output the minimal editor config used in Press This
89
+ 'dfw' => false, // replace the default fullscreen with DFW (supported on the front-end in WordPress 3.4)
90
+ 'tinymce' => true, // load TinyMCE, can be used to pass settings directly to TinyMCE using an array()
91
+ 'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array()
92
+ );
93
+ $textWpm = '';
94
+ if( isset($paramMMode['text_maintenance']) && $paramMMode['text_maintenance']!='' ) { $textWpm = stripslashes($paramMMode['text_maintenance']); }
95
+ ?>
96
+ <?php wp_editor( nl2br($textWpm), 'wpm-textmaintenance', $settingsTextmaintenance ); ?>
97
+ <br />
98
+ <h3><?php _e('Text in the bottom of maintenance page:', 'wp-maintenance'); ?></h3>
99
+ <?php
100
+ $settingsTextmaintenance = array(
101
+ 'wpautop' => true, // use wpautop?
102
+ 'media_buttons' => false, // show insert/upload button(s)
103
+ 'textarea_name' => 'wp_maintenance_settings[text_bt_maintenance]', // set the textarea name to something different, square brackets [] can be used here
104
+ 'textarea_rows' => get_option('default_post_edit_rows', 10), // rows="..."
105
+ 'tabindex' => '',
106
+ 'editor_css' => '', // extra styles for both visual and HTML editors buttons,
107
+ 'editor_class' => 'wpm-textbtmaintenance', // add extra class(es) to the editor textarea
108
+ 'teeny' => true, // output the minimal editor config used in Press This
109
+ 'dfw' => false, // replace the default fullscreen with DFW (supported on the front-end in WordPress 3.4)
110
+ 'tinymce' => true, // load TinyMCE, can be used to pass settings directly to TinyMCE using an array()
111
+ 'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array()
112
+ );
113
+ $textBt = '';
114
+ if( isset($paramMMode['text_bt_maintenance']) && $paramMMode['text_bt_maintenance']!='' ) { $textBt = stripslashes($paramMMode['text_bt_maintenance']); }
115
+ ?>
116
+ <?php wp_editor( nl2br($textBt), 'wpm-textbtmaintenance', $settingsTextmaintenance ); ?>
117
+ <br />
118
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
119
+
120
+ <!-- GOOGLE LOGIN -->
121
+ <div>
122
+ <div style="float:left; width:70%;"><h3><?php _e('Enable login access in the bottom ?', 'wp-maintenance'); ?></h3></div>
123
+ <div style="float:left; width:30%;text-align:right;">
124
+ <div class="switch-field">
125
+ <input class="switch_left" type="radio" onclick="AfficherTexte('option-wplogin');" id="switch_wplogin" name="wp_maintenance_settings[add_wplogin]" value="1" <?php if( isset($paramMMode['add_wplogin']) && $paramMMode['add_wplogin']==1) { echo ' checked'; } ?>/>
126
+ <label for="switch_wplogin"><?php _e('Yes', 'wp-maintenance'); ?></label>
127
+ <input class="switch_right" type="radio" onclick="CacherTexte('option-wplogin');" id="switch_wplogin_no" name="wp_maintenance_settings[add_wplogin]" value="0" <?php if( empty($paramMMode['add_wplogin']) || isset($paramMMode['add_wplogin']) && $paramMMode['add_wplogin']==0) { echo ' checked'; } ?> />
128
+ <label for="switch_wplogin_no"><?php _e('No', 'wp-maintenance'); ?></label>
129
+ </div>
130
+ </div>
131
+ <div class="clear"></div>
132
+ </div>
133
+
134
+ <div id="option-wplogin" style="<?php if( empty($paramMMode['add_wplogin']) || isset($paramMMode['add_wplogin']) && $paramMMode['add_wplogin']==0) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
135
+
136
+ <?php _e('Enter a text to go to the dashboard:', 'wp-maintenance'); ?><br />
137
+ <input type="text" class="wpm-form-field" name="wp_maintenance_settings[add_wplogin_title]" size="60%" value="<?php if( isset($paramMMode['add_wplogin_title']) && $paramMMode['add_wplogin_title']!='' ) { echo stripslashes(trim($paramMMode['add_wplogin_title'])); } ?>" /><br />
138
+ <small><?php _e('Eg: connect to %DASHBOARD% here!', 'wp-maintenance'); ?> <?php _e('(%DASHBOARD% will be replaced with the link to the dashboard and the word "Dashboard")', 'wp-maintenance'); ?></small>
139
+
140
+ </div>
141
+
142
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
143
+
144
+ <!-- GOOGLE ANALYTICS -->
145
+ <div>
146
+ <div style="float:left; width:70%;"><h3><?php _e('Enable Google Analytics:', 'wp-maintenance'); ?></h3></div>
147
+ <div style="float:left; width:30%;text-align:right;">
148
+ <div class="switch-field">
149
+ <input class="switch_left" type="radio" onclick="AfficherTexte('option-analytics');" id="switch_analytics" name="wp_maintenance_settings[analytics]" value="1" <?php if( isset($paramMMode['analytics']) && $paramMMode['analytics']==1) { echo ' checked'; } ?>/>
150
+ <label for="switch_analytics"><?php _e('Yes', 'wp-maintenance'); ?></label>
151
+ <input class="switch_right" type="radio" onclick="CacherTexte('option-analytics');" id="switch_analytics_no" name="wp_maintenance_settings[analytics]" value="0" <?php if( empty($paramMMode['analytics']) || isset($paramMMode['analytics']) && $paramMMode['analytics']==0) { echo ' checked'; } ?> />
152
+ <label for="switch_analytics_no"><?php _e('No', 'wp-maintenance'); ?></label>
153
+ </div>
154
+ </div>
155
+ <div class="clear"></div>
156
+ </div>
157
+
158
+ <div id="option-analytics" style="<?php if( empty($paramMMode['analytics']) || isset($paramMMode['analytics']) && $paramMMode['analytics']==0) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
159
+
160
+ <?php _e('Enter your Google analytics tracking ID here:', 'wp-maintenance'); ?><br />
161
+ <input type="text" class="wpm-form-field" name="wp_maintenance_settings[code_analytics]" value="<?php if( isset($paramMMode['code_analytics']) && $paramMMode['code_analytics']!='' ) { echo stripslashes(trim($paramMMode['code_analytics'])); } ?>"><br />
162
+ <?php _e('Enter your domain URL:', 'wp-maintenance'); ?><br />
163
+ <input type="text" class="wpm-form-field" name="wp_maintenance_settings[domain_analytics]" value="<?php if( isset($paramMMode['domain_analytics']) && $paramMMode['domain_analytics']!='' ) { echo stripslashes(trim($paramMMode['domain_analytics'])); } else { echo $_SERVER['SERVER_NAME']; } ?>">
164
+ </div>
165
+
166
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
167
+ <!-- ICONS RESEAUX SOCIAUX -->
168
+ <div>
169
+ <div style="float:left; width:70%;"><h3><?php _e('Enable Social Networks:', 'wp-maintenance'); ?></h3></div>
170
+ <div style="float:left; width:30%;text-align:right;">
171
+ <div class="switch-field">
172
+ <input class="switch_left" type="radio" onclick="AfficherTexte('option-socials');" id="switch_socials" name="wp_maintenance_social_options[enable]" value="1" <?php if( isset($paramSocialOption['enable']) && $paramSocialOption['enable']==1) { echo ' checked'; } ?>/>
173
+ <label for="switch_socials"><?php _e('Yes', 'wp-maintenance'); ?></label>
174
+ <input class="switch_right" type="radio" onclick="CacherTexte('option-socials');" id="switch_socials_no" name="wp_maintenance_social_options[enable]" value="0" <?php if( empty($paramSocialOption['enable']) || isset($paramSocialOption['enable']) && $paramSocialOption['enable']==0) { echo ' checked'; } ?> />
175
+ <label for="switch_socials_no"><?php _e('No', 'wp-maintenance'); ?></label>
176
+ </div>
177
+ </div>
178
+ <div class="clear"></div>
179
+ </div>
180
+
181
+ <div id="option-socials" style="<?php if( empty($paramSocialOption['enable']) || isset($paramSocialOption['enable']) && $paramSocialOption['enable']==0) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
182
+
183
+ <?php _e('Enter text for the title icons:', 'wp-maintenance'); ?>
184
+ <input type="text" class="wpm-form-field" name="wp_maintenance_social_options[texte]" value="<?php if($paramSocialOption['texte']=='' && $paramSocialOption['texte']!='') { _e('Follow me on', 'wp-maintenance'); } else { echo stripslashes(trim($paramSocialOption['texte'])); } ?>" /><br /><br />
185
+ <!-- Liste des réseaux sociaux -->
186
+ <?php _e('Drad and drop the lines to put in the order you want:', 'wp-maintenance'); ?><br /><br />
187
+ <ul class="sortable">
188
+ <?php
189
+ if( isset($paramSocial) && !empty($paramSocial) ) {
190
+
191
+ foreach($paramSocial as $socialName=>$socialUrl) {
192
+ ?>
193
+ <li><span>::</span><img src="<?php echo WPM_ICONS_URL; ?>24x24/<?php echo $socialName; ?>.png" hspace="3" valign="middle" /><?php echo ucfirst($socialName); ?> <input type= "text" class="wpm-form-field" name="wp_maintenance_social[<?php echo $socialName; ?>]" value="<?php echo $socialUrl; ?>" size="50" onclick="select()" /></li>
194
+ <?php
195
+ }
196
+
197
+ } else {
198
+
199
+ $wpmTabSocial = array('facebook', 'twitter', 'linkedin', 'flickr', 'youtube', 'pinterest', 'vimeo', 'instagram', 'google_plus', 'about_me', 'soundcloud');
200
+
201
+ foreach ($wpmTabSocial as &$iconSocial) {
202
+ echo '<li><span>::</span><img src="'.WPM_ICONS_URL.'24x24/'.$iconSocial.'.png" valign="middle" hspace="3"/>'.ucfirst($iconSocial).' <input type="text" class="wpm-form-field" size="50" name="wp_maintenance_social['.$iconSocial.']" value="" onclick="select()" ><br />';
203
+ }
204
+
205
+ }
206
+ ?>
207
+ </ul>
208
+ <script src="<?php echo WPM_PLUGIN_URL; ?>js/jquery.sortable.js"></script>
209
+ <script>
210
+ jQuery('.sortable').sortable();
211
+ </script>
212
+ <br />
213
+ <?php _e('Choose icons size:', 'wp-maintenance'); ?>
214
+ <select name="wp_maintenance_social_options[size]" class="wpm-form-field" >
215
+ <?php
216
+ $wpm_tabIcon = array(16, 24, 32, 48, 64, 128);
217
+ foreach($wpm_tabIcon as $wpm_icon) {
218
+ if($paramSocialOption['size']==$wpm_icon) { $selected = ' selected'; } else { $selected = ''; }
219
+ echo '<option value="'.$wpm_icon.'" '.$selected.'>'.$wpm_icon.'</option>';
220
+ }
221
+ ?>
222
+ </select>
223
+
224
+ <?php _e('Position:', 'wp-maintenance'); ?>
225
+ <select name="wp_maintenance_social_options[position]" class="wpm-form-field" >
226
+ <option value="top"<?php if( isset($paramSocialOption['position']) && $paramSocialOption['position']=='top') { echo ' selected'; } ?>><?php _e('Top', 'wp-maintenance'); ?></option>
227
+ <option value="bottom"<?php if( empty($paramSocialOption['position']) or (isset($paramSocialOption['position']) && $paramSocialOption['position']=='bottom') ) { echo ' selected'; } ?>><?php _e('Bottom', 'wp-maintenance'); ?></option>
228
+ </select>
229
+
230
+ <?php _e('Align:', 'wp-maintenance'); ?>
231
+ <select name="wp_maintenance_social_options[align]" class="wpm-form-field">
232
+ <option value="left"<?php if(isset($paramSocialOption['align']) && $paramSocialOption['align']=='left') { echo ' selected'; } ?>><?php _e('Left', 'wp-maintenance'); ?></option>
233
+ <option value="center"<?php if( empty($paramSocialOption['align']) or ( isset($paramSocialOption['align']) && $paramSocialOption['align']=='center') ) { echo ' selected'; } ?>><?php _e('Center', 'wp-maintenance'); ?></option>
234
+ <option value="right"<?php if( isset($paramSocialOption['align']) && $paramSocialOption['align']=='right') { echo ' selected'; } ?>><?php _e('Right', 'wp-maintenance'); ?></option>
235
+ </select>
236
+ <br /><br />
237
+ <?php _e('You have your own icons? Enter the folder name of your theme here:', 'wp-maintenance'); ?><br /><strong><?php echo get_stylesheet_directory_uri(); ?>/</strong><input class="wpm-form-field" type="text" value="<?php if( isset($paramSocialOption['theme']) && $paramSocialOption['theme']!='' ) { echo stripslashes(trim($paramSocialOption['theme'])); } ?>" name="wp_maintenance_social_options[theme]" /><br /><br />
238
+
239
+ <div>
240
+ <div style="float:left; width:70%;"><h3><?php _e('Reset Social Icon?', 'wp-maintenance'); ?></h3></div>
241
+ <div style="float:left; width:30%;text-align:right;">
242
+ <div class="switch-field">
243
+ <input class="switch_left" type="radio" id="switch_reset" name="wp_maintenance_social_options[reset]" value="1" />
244
+ <label for="switch_reset"><?php _e('Yes', 'wp-maintenance'); ?></label>
245
+ <input class="switch_right" type="radio" id="switch_reset_no" name="wp_maintenance_social_options[reset]" value="0" checked />
246
+ <label for="switch_reset_no"><?php _e('No', 'wp-maintenance'); ?></label>
247
+ </div>
248
+ </div>
249
+ <div class="clear"></div>
250
+ </div>
251
+ </div>
252
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
253
+
254
+ <!-- Encart Newletter -->
255
+ <a name="newsletter"></a>
256
+ <div>
257
+ <div style="float:left; width:70%;"><h3><?php _e('Enable Newletter:', 'wp-maintenance'); ?></h3></div>
258
+ <div style="float:left; width:30%;text-align:right;">
259
+ <div class="switch-field">
260
+ <input class="switch_left" type="radio" onclick="AfficherTexte('option-newletter');" id="switch_newletter" name="wp_maintenance_settings[newletter]" value="1" <?php if( isset($paramMMode['newletter']) && $paramMMode['newletter']==1 ) { echo ' checked'; } ?>/>
261
+ <label for="switch_newletter"><?php _e('Yes', 'wp-maintenance'); ?></label>
262
+ <input class="switch_right" type="radio" onclick="CacherTexte('option-newletter');" id="switch_newletter_no" name="wp_maintenance_settings[newletter]" value="0" <?php if( empty($paramMMode['newletter']) || isset($paramMMode['newletter']) && $paramMMode['newletter']==0) { echo ' checked'; } ?> />
263
+ <label for="switch_newletter_no"><?php _e('No', 'wp-maintenance'); ?></label>
264
+ </div>
265
+ </div>
266
+ <div class="clear"></div>
267
+ </div>
268
+
269
+ <div id="option-newletter" style="<?php if( empty($paramMMode['newletter']) || isset($paramMMode['newletter']) && $paramMMode['newletter']==0) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
270
+
271
+ <?php _e('Enter title for the newletter block:', 'wp-maintenance'); ?><br />
272
+ <input type="text" class="wpm-form-field" name="wp_maintenance_settings[title_newletter]" size="100%" value="<?php if( isset($paramMMode['title_newletter']) && $paramMMode['title_newletter']!='' ) { echo stripslashes(trim($paramMMode['title_newletter'])); } ?>" /><br /><br />
273
+ <input type="radio" class="wpm-form-field" name="wp_maintenance_settings[type_newletter]" value="shortcode" <?php if( isset($paramMMode['type_newletter']) && $paramMMode['type_newletter']=='shortcode' ) { echo 'checked'; } if( empty($paramMMode['type_newletter']) ) { echo 'checked'; } ?> /><?php _e('Enter your newletter shortcode here:', 'wp-maintenance'); ?><br />
274
+ <input type="text" size="100%" class="wpm-form-field" name="wp_maintenance_settings[code_newletter]" value='<?php if( isset($paramMMode['code_newletter']) && $paramMMode['code_newletter']!='' ) { echo stripslashes(trim($paramMMode['code_newletter'])); } ?>' onclick="select()" /><br /><br />
275
+ <input type="radio" class="wpm-form-field" name="wp_maintenance_settings[type_newletter]" value="iframe" <?php if( isset($paramMMode['type_newletter']) && $paramMMode['type_newletter']=='iframe' ) { echo 'checked'; } ?>/> <?php _e('Or enter your newletter iframe code here:', 'wp-maintenance'); ?><br />
276
+ <textarea class="wpm-form-field" id="iframe_newletter" cols="60" rows="10" name="wp_maintenance_settings[iframe_newletter]"><?php if( isset($paramMMode['iframe_newletter']) && $paramMMode['iframe_newletter']!='' ) { echo stripslashes(trim($paramMMode['iframe_newletter'])); } ?></textarea>
277
+
278
+ </div>
279
+
280
+ <p>
281
+ <?php submit_button(); ?>
282
+ </p>
283
+
284
+ </div>
285
+
286
+ <?php echo wpm_sidebar(); ?>
287
+
288
+ </div>
289
+
290
+ </form>
291
+
292
+ <?php echo wpm_footer(); ?>
293
+
294
+ </div>
views/wp-maintenance-picture.php ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die( 'Not allowed' );
4
+
5
+ $messageUpdate = 0;
6
+ /* Update des paramètres */
7
+ if( isset($_POST['action']) && $_POST['action'] == 'update_pictures' ) {
8
+
9
+ if( isset($_POST["wpm_maintenance_detete"]) && is_array($_POST["wpm_maintenance_detete"]) ) {
10
+ foreach($_POST["wpm_maintenance_detete"] as $delSlideId=>$delSlideTrue) {
11
+ if (array_key_exists($delSlideId, $_POST["wp_maintenance_slider"]["slider_image"])) {
12
+ unset($_POST["wp_maintenance_slider"]["slider_image"][$delSlideId]);
13
+ unset($_POST["wp_maintenance_slider"]["slider_text"][$delSlideId]);
14
+ unset($_POST["wp_maintenance_slider"]["slider_link"][$delSlideId]);
15
+ }
16
+ }
17
+ }
18
+
19
+ $options_saved = wpm_update_settings($_POST["wp_maintenance_settings"]);
20
+ update_option('wp_maintenance_slider', $_POST["wp_maintenance_slider"]);
21
+ update_option('wp_maintenance_slider_options', $_POST["wp_maintenance_slider_options"]);
22
+
23
+ $messageUpdate = 1;
24
+ }
25
+
26
+ // Récupère les paramètres sauvegardés
27
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
28
+ $paramMMode = get_option('wp_maintenance_settings');
29
+
30
+ if(get_option('wp_maintenance_slider')) { extract(get_option('wp_maintenance_slider')); }
31
+ $paramSlider = get_option('wp_maintenance_slider');
32
+
33
+ if(get_option('wp_maintenance_slider_options')) { extract(get_option('wp_maintenance_slider_options')); }
34
+ $paramSliderOptions = get_option('wp_maintenance_slider_options');
35
+
36
+ ?>
37
+ <style>
38
+ #pattern { text-align: left; margin: 5px 0; word-spacing: -1em;list-style-type: none; }
39
+ #pattern li { display: inline-block; list-style: none;margin-right:15px;text-align:center; }
40
+ #pattern li.current { background: #66CC00; color: #fff; }
41
+ </style>
42
+ <script type="text/javascript">
43
+ function toggleTable(texte) {
44
+ var elem=document.getElementById(texte);
45
+ var hide = elem.style.display == "none";
46
+ if (hide) {
47
+ elem.style.display="block";
48
+ }
49
+ else {
50
+ elem.style.display="none";
51
+ }
52
+ }
53
+ </script>
54
+ <div class="wrap">
55
+
56
+ <form method="post" action="" name="valide_settings">
57
+ <input type="hidden" name="action" value="update_pictures" />
58
+
59
+ <!-- HEADER -->
60
+ <?php echo wpm_get_header( __('Picture', 'wp-maintenance'), 'dashicons-format-gallery', $messageUpdate ) ?>
61
+ <!-- END HEADER -->
62
+
63
+ <div style="margin-top: 80px;">
64
+ <div style="float:left;width:73%;margin-right:1%;border: 1px solid #ddd;background-color:#fff;padding:10px;">
65
+
66
+ <div style="float:left;width:68%;margin-right:10px;">
67
+ <?php
68
+ if( isset($paramMMode['image']) && $paramMMode['image']!='' && ini_get('allow_url_fopen')==1 ) {
69
+ list($logoWidth, $logoHeight, $logoType, $logoAttr) = getimagesize($paramMMode['image']);
70
+ } else {
71
+ $logoWidth = 200;
72
+ }
73
+ ?>
74
+ <h3><?php _e('Header picture', 'wp-maintenance'); ?></h3>
75
+ <small><?php _e('Enter a URL or upload an image.', 'wp-maintenance'); ?></small><br />
76
+ <input id="upload_image" size="80%" name="wp_maintenance_settings[image]" value="<?php if( isset($paramMMode['image']) && $paramMMode['image']!='' ) { echo $paramMMode['image']; } ?>" type="text" class="wpm-form-field" /><br /><a href="#" id="upload_image_button" class="button" OnClick="this.blur();"><span> <?php _e('Select or Upload your picture', 'wp-maintenance'); ?> </span></a>
77
+ </div>
78
+ <div style="float:left;width:30%;text-align:center;">
79
+ <?php if( isset($paramMMode['image']) && $paramMMode['image']!='' ) { ?>
80
+ <?php _e('You use this picture:', 'wp-maintenance'); ?><br /> <img src="<?php echo $paramMMode['image']; ?>" width="200" id="image_visuel" style="padding:3px;" />
81
+ <?php } ?>
82
+ </div>
83
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
84
+
85
+
86
+ <div id="encart-option-background">
87
+ <div style="float:left; width:70%;"><h3><?php _e('Background picture or pattern', 'wp-maintenance'); ?></h3></div>
88
+ <div style="float:left; width:30%;text-align:right;">
89
+ <div class="switch-field">
90
+ <input class="switch_left" onclick="AfficherTexte('option-background');" type="radio" id="switch_background" name="wp_maintenance_settings[b_enable_image]" value="1" <?php if( isset($paramMMode['b_enable_image']) && $paramMMode['b_enable_image']==1) { echo ' checked'; } ?>/>
91
+ <label for="switch_background" ><?php _e('Yes', 'wp-maintenance'); ?></label>
92
+ <input class="switch_right" onclick="CacherTexte('option-background');" type="radio" id="switch_background_no" name="wp_maintenance_settings[b_enable_image]" value="0" <?php if( empty($paramMMode['b_enable_image']) || (isset($paramMMode['b_enable_image']) && $paramMMode['b_enable_image']==0) ) { echo ' checked'; } ?> />
93
+ <label for="switch_background_no"><?php _e('No', 'wp-maintenance'); ?></label>
94
+ </div>
95
+ </div>
96
+ <div class="clear"></div>
97
+ </div>
98
+
99
+ <div id="option-background" style="<?php if( empty($paramMMode['b_enable_image']) || (isset($paramMMode['b_enable_image']) && $paramMMode['b_enable_image']==0) ) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
100
+
101
+ <!-- UPLOADER UNE IMAGE DE FOND -->
102
+ <div style="float:left;width:68%;margin-right:10px;">
103
+ <small><?php _e('Enter a URL or upload an image.', 'wp-maintenance'); ?></small><br />
104
+ <input id="upload_b_image" class="wpm-form-field" size="80%" name="wp_maintenance_settings[b_image]" value="<?php if( isset($paramMMode['b_image']) && $paramMMode['b_image']!='' ) { echo $paramMMode['b_image']; } ?>" type="text" /><br /><a href="#" id="upload_b_image_button" class="button" OnClick="this.blur();"><span> <?php _e('Select or Upload your picture', 'wp-maintenance'); ?> </span></a>
105
+ <h4><?php _e('Background picture options', 'wp-maintenance'); ?></h4>
106
+ <select name="wp_maintenance_settings[b_repeat_image]" class="wpm-form-field" >
107
+ <option value="repeat"<?php if( (isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='repeat') or empty($paramMMode['b_repeat_image']) ) { echo ' selected'; } ?>>repeat</option>
108
+ <option value="no-repeat"<?php if( isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='no-repeat') { echo ' selected'; } ?>>no-repeat</option>
109
+ <option value="repeat-x"<?php if( isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='repeat-x') { echo ' selected'; } ?>>repeat-x</option>
110
+ <option value="repeat-y"<?php if( isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='repeat-y') { echo ' selected'; } ?>>repeat-y</option>
111
+ </select> <input type= "checkbox" name="wp_maintenance_settings[b_fixed_image]" value="1" <?php if( isset($paramMMode['b_fixed_image']) && $paramMMode['b_fixed_image']==1) { echo ' checked'; } ?>>&nbsp;<?php _e('Fixed', 'wp-maintenance'); ?>
112
+ </div>
113
+ <div style="float:left;width:30%;text-align:center;">
114
+ <?php if( isset($paramMMode['b_image']) && $paramMMode['b_image']!='' && (!$paramMMode['b_pattern'] or $paramMMode['b_pattern']==0) ) { ?>
115
+ <?php _e('You use this background picture:', 'wp-maintenance'); ?><br />
116
+ <img src="<?php echo $paramMMode['b_image']; ?>" width="200" /><br />
117
+ <?php } ?>
118
+ </div>
119
+ <div class="clear"></div>
120
+
121
+ <!-- CHOIX PATTERN -->
122
+ <div style="float:left;width:68%;margin-right:10px;">
123
+ <h4><?php _e('Or choose a pattern:', 'wp-maintenance'); ?></h4>
124
+ <ul id="pattern">
125
+ <li>
126
+ <div style="width:50px;height:50px;border:1px solid #333;background-color:#ffffff;font-size:0.8em;"><?php _e('NO PATTERN', 'wp-maintenance'); ?></div>
127
+ <input type="radio" value="0" <?php if( empty($paramMMode['b_pattern']) or $paramMMode['b_pattern']==0) { echo 'checked'; } ?> name="wp_maintenance_settings[b_pattern]" />
128
+ </li>
129
+ <?php for ($p = 1; $p <= 12; $p++) { ?>
130
+ <li>
131
+ <div style="width:50px;height:50px;border:1px solid #333;background:url('<?php echo WP_PLUGIN_URL ?>/wp-maintenance/images/pattern<?php echo $p ?>.png');"></div>
132
+ <input type="radio" value="<?php echo $p; ?>" <?php if( isset($paramMMode['b_pattern']) && $paramMMode['b_pattern']==$p) { echo 'checked'; } ?> name="wp_maintenance_settings[b_pattern]" />
133
+ </li>
134
+ <?php } ?>
135
+ </ul>
136
+ </div>
137
+ <div style="float:left;width:30%;text-align:center;">
138
+ <?php if( isset($paramMMode['b_pattern']) && $paramMMode['b_pattern']>0) { ?>
139
+ <?php _e('You use this pattern:', 'wp-maintenance'); ?><br />
140
+ <div style="background: url('<?php echo WP_PLUGIN_URL ?>/wp-maintenance/images/pattern<?php echo $paramMMode['b_pattern']; ?>.png');width:200px;height:200px;border:1px solid #ddd;margin-left:auto;margin-right:auto;"></div>
141
+ <?php } ?>
142
+ </div>
143
+ <div class="clear"></div>
144
+ </div>
145
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
146
+
147
+ <div>
148
+ <div style="float:left; width:70%;"><h3><?php _e('Enable Slider', 'wp-maintenance'); ?></h3></div>
149
+ <div style="float:left; width:30%;text-align:right;">
150
+ <div class="switch-field">
151
+ <input type="radio" onclick="AfficherTexte('option-diaporama');" id="switch_diaporama" name="wp_maintenance_settings[enable_slider]" value="1" <?php if( isset($paramMMode['enable_slider']) && $paramMMode['enable_slider']==1 ) { echo ' checked'; } ?>/>
152
+ <label for="switch_diaporama"><?php _e('Yes', 'wp-maintenance'); ?></label>
153
+ <input type="radio" onclick="CacherTexte('option-diaporama');" id="switch_diaporama_no" name="wp_maintenance_settings[enable_slider]" value="0" <?php if( empty($paramMMode['enable_slider']) || (isset($paramMMode['enable_slider']) && $paramMMode['enable_slider']==0) ) { echo ' checked'; } ?> />
154
+ <label for="switch_diaporama_no"><?php _e('No', 'wp-maintenance'); ?></label>
155
+ </div>
156
+ </div>
157
+ <div class="clear"></div>
158
+ </div>
159
+
160
+ <div id="option-diaporama" style="<?php if( empty($paramMMode['enable_slider']) || (isset($paramMMode['enable_slider']) && $paramMMode['enable_slider']==0) ) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
161
+ <h4><?php _e('Slider image options', 'wp-maintenance'); ?></h4>
162
+ <?php
163
+
164
+ if( $paramSlider!==null ) {
165
+
166
+ if( $paramSlider['slider_image'] ) {
167
+ $lastKeySlide = key($paramSlider['slider_image']);
168
+ $countSlide = ( $lastKeySlide + 1 );
169
+ } else {
170
+ $countSlide = 1;
171
+ }
172
+ ?>
173
+ <div style="margin-bottom:15px;width:100%;">
174
+ <div style="width:30%;float:left;">
175
+ <?php _e('Speed:', 'wp-maintenance'); ?> <input type="text" name="wp_maintenance_slider_options[slider_speed]" class="wpm-form-field" size="4" value="<?php if( isset($paramSliderOptions['slider_speed']) && $paramSliderOptions['slider_speed'] !='') { echo $paramSliderOptions['slider_speed']; } else { echo 500; } ?>" />ms<br />
176
+ <?php _e('Width:', 'wp-maintenance'); ?> <input type="text" name="wp_maintenance_slider_options[slider_width]" class="wpm-form-field" size="3" value="<?php if( isset($paramSliderOptions['slider_width']) && $paramSliderOptions['slider_width'] !='') { echo $paramSliderOptions['slider_width']; } else { echo 50; } ?>" />%
177
+ </div>
178
+ <div style="width:30%;float:left;padding-left:5px;">
179
+
180
+ <div id="encart-option-sliderauto">
181
+ <?php _e('Display Auto Slider:', 'wp-maintenance'); ?><br />
182
+ <div class="switch-field" style="margin-left: 0px;">
183
+ <input class="switch_left" type="radio" id="switch_sliderauto" name="wp_maintenance_slider_options[slider_auto]" value="1" <?php if( isset($paramSliderOptions['slider_auto']) && $paramSliderOptions['slider_auto']=='true') { echo ' checked'; } ?>/>
184
+ <label for="switch_sliderauto" ><?php _e('Yes', 'wp-maintenance'); ?></label>
185
+ <input class="switch_right" type="radio" id="switch_sliderauto_no" name="wp_maintenance_slider_options[slider_auto]" value="0" <?php if( empty($paramSliderOptions['slider_auto']) || (isset($paramSliderOptions['slider_auto']) && $paramSliderOptions['slider_auto']=='false') ) { echo ' checked'; } ?> />
186
+ <label for="switch_sliderauto_no"><?php _e('No', 'wp-maintenance'); ?></label>
187
+ </div>
188
+ <?php _e('Display button navigation:', 'wp-maintenance'); ?><br />
189
+ <div class="switch-field" style="margin-left: 0px;">
190
+ <input class="switch_left" type="radio" id="switch_slidernav" name="wp_maintenance_slider_options[slider_nav]" value="1" <?php if( isset($paramSliderOptions['slider_nav']) && $paramSliderOptions['slider_nav']=='true') { echo ' checked'; } ?>/>
191
+ <label for="switch_slidernav" ><?php _e('Yes', 'wp-maintenance'); ?></label>
192
+ <input class="switch_right" type="radio" id="switch_slidernav_no" name="wp_maintenance_slider_options[slider_nav]" value="0" <?php if( empty($paramSliderOptions['slider_nav']) || (isset($paramSliderOptions['slider_nav']) && $paramSliderOptions['slider_nav']=='false') ) { echo ' checked'; } ?> />
193
+ <label for="switch_slidernav_no"><?php _e('No', 'wp-maintenance'); ?></label>
194
+ </div>
195
+ </div>
196
+
197
+ </div>
198
+ <div style="width:30%;float:left;padding-left:5px;">
199
+ <?php _e('Position:', 'wp-maintenance'); ?>
200
+ <select name="wp_maintenance_slider_options[slider_position]" class="wpm-form-field" >
201
+ <option value="abovelogo" <?php if( isset($paramSliderOptions['slider_position']) && $paramSliderOptions['slider_position']=='abovelogo' ) { echo 'selected'; } ?>>+<?php _e('Above logo', 'wp-maintenance'); ?></option>
202
+ <option value="belowlogo" <?php if( isset($paramSliderOptions['slider_position']) && $paramSliderOptions['slider_position']=='belowlogo' ) { echo 'selected'; } ?>><?php _e('Below logo', 'wp-maintenance'); ?></option>
203
+ <option value="belowtext" <?php if( ( isset($paramSliderOptions['slider_position']) && $paramSliderOptions['slider_position']=='belowtext' ) || empty($paramSliderOptions['slider_position']) ) { echo 'selected'; } ?>><?php _e('Below title & text', 'wp-maintenance'); ?></option>
204
+ </select>
205
+ </div>
206
+ <div class="clear"></div>
207
+ </div>
208
+
209
+ <input id="upload_slider_image" size="80%" class="wpm-form-field" name="wp_maintenance_slider[slider_image][<?php echo $countSlide; ?>][image]" value="" type="text" /><br /><a href="#" id="upload_slider_image_button" class="button" OnClick="this.blur();"><span> <?php _e('Select or Upload your picture', 'wp-maintenance'); ?> </span></a><br /><br />
210
+
211
+ <div style="width:100%">
212
+ <?php
213
+ if( !empty($paramSlider['slider_image']) ) {
214
+ foreach($paramSlider['slider_image'] as $numSlide=>$slide) {
215
+
216
+ if( $paramSlider['slider_image'][$numSlide]['image'] != '' ) {
217
+
218
+ $slideImg = '';
219
+ if( isset($paramSlider['slider_image'][$numSlide]['image']) ) {
220
+ $slideImg = $paramSlider['slider_image'][$numSlide]['image'];
221
+ }
222
+ $slideText = '';
223
+ if( isset($paramSlider['slider_image'][$numSlide]['text']) ) {
224
+ $slideText = stripslashes($paramSlider['slider_image'][$numSlide]['text']);
225
+ }
226
+ $slideLink = '';
227
+ if( isset($paramSlider['slider_image'][$numSlide]['link']) ) {
228
+ $slideLink = $paramSlider['slider_image'][$numSlide]['link'];
229
+ }
230
+ echo '<div style="float:left;width:45%;border: 1px solid #ececec;padding:0.8em;margin-right:1%;margin-bottom:1%">';
231
+
232
+ echo '<div style="float:left;margin-right:0.8em;">';
233
+ echo '<img src="'.$slideImg.'" width="360" />';
234
+ echo '</div>';
235
+
236
+ echo '<div style="float:left;">';
237
+ echo '<input class="wpm-form-field" type="hidden" name="wp_maintenance_slider[slider_image]['.$numSlide.'][image]" value="'.$slideImg.'" />';
238
+ echo __('Text:', 'wp-maintenance').'<br /> <input type="text" name="wp_maintenance_slider[slider_image]['.$numSlide.'][text]" class="wpm-form-field" size="50%" value="'.$slideText.'" /><br />';
239
+ echo __('Link:', 'wp-maintenance').'<br /> <input type="text" name="wp_maintenance_slider[slider_image]['.$numSlide.'][link]" class="wpm-form-field" size="50%" value="'.$slideLink.'" />';
240
+ echo '</div>';
241
+ echo '<div class="clear"></div>';
242
+ echo '<div style="text-align:right;"><input type="checkbox" name="wpm_maintenance_detete['.$numSlide.']" value="true" /><small>'.__('Delete this slide', 'wp-maintenance').'</small></div>';
243
+ echo '</div>';
244
+
245
+ }
246
+
247
+ }
248
+ }
249
+ }
250
+ ?>
251
+ </div>
252
+ </div>
253
+ <div class="clear"></div>
254
+
255
+ <?php submit_button(); ?>
256
+
257
+ </div>
258
+
259
+ <?php echo wpm_sidebar(); ?>
260
+ </div>
261
+ </form>
262
+ <?php echo wpm_footer(); ?>
263
+
264
+ </div>
views/wp-maintenance-settings.php ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ defined( 'ABSPATH' ) or die( 'Not allowed' );
4
+
5
+ $messageUpdate = 0;
6
+ /* Update des paramètres */
7
+ if( isset($_POST['action']) && $_POST['action'] == 'update_settings' ) {
8
+
9
+ update_option('wp_maintenance_limit', $_POST["wp_maintenance_limit"]);
10
+ update_option('wp_maintenance_ipaddresses', $_POST["wp_maintenance_ipaddresses"]);
11
+
12
+ $options_saved = wpm_update_settings($_POST["wp_maintenance_settings"]);
13
+ $messageUpdate = 1;
14
+ }
15
+
16
+ // Récupère les paramètres sauvegardés
17
+ if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
18
+ $paramMMode = get_option('wp_maintenance_settings');
19
+
20
+ // Récupère les Rôles et capabilités
21
+ if(get_option('wp_maintenance_limit')) { extract(get_option('wp_maintenance_limit')); }
22
+ $paramLimit = get_option('wp_maintenance_limit');
23
+
24
+ // Récupère les ip autorisee
25
+ $paramIpAddress = get_option('wp_maintenance_ipaddresses');
26
+
27
+ ?>
28
+ <style>
29
+ .CodeMirror {
30
+ border: 1px solid #eee;
31
+ height: auto;
32
+ }
33
+ </style>
34
+ <div class="wrap">
35
+
36
+ <form method="post" action="" name="valide_settings">
37
+ <input type="hidden" name="action" value="update_settings" />
38
+
39
+ <!-- HEADER -->
40
+ <?php echo wpm_get_header( __('Settings', 'wp-maintenance'), 'dashicons-admin-generic', $messageUpdate ) ?>
41
+ <!-- END HEADER -->
42
+
43
+ <div style="margin-top:80px;">
44
+
45
+ <div style="float:left;width:73%;margin-right:1%;border: 1px solid #ddd;background-color:#fff;padding:10px;">
46
+
47
+ <div>
48
+ <div style="float:left; width:70%;"><h3><?php _e('Theme maintenance page', 'wp-maintenance'); ?></h3><p><?php _e('If you would use your maintenance.php page in your theme folder, click Yes.', 'wp-maintenance'); ?></p></div>
49
+ <div style="float:left; width:30%;margin-top:25px;text-align:right;">
50
+ <div class="switch-field">
51
+ <input class="switch_left" onclick="AfficherTexte('option-pageperso');" type="radio" id="switch_pageperso" name="wp_maintenance_settings[pageperso]" value="1" <?php if( isset($paramMMode['pageperso']) && $paramMMode['pageperso']==1 ) { echo ' checked'; } ?>/>
52
+ <label for="switch_pageperso"><?php _e('Yes', 'wp-maintenance'); ?></label>
53
+ <input class="switch_right" onclick="CacherTexte('option-pageperso');" type="radio" id="switch_pageperso_no" name="wp_maintenance_settings[pageperso]" value="0" <?php if( empty($paramMMode['pageperso']) || (isset($paramMMode['pageperso']) && $paramMMode['pageperso']==0) ) { echo ' checked'; } ?> />
54
+ <label for="switch_pageperso_no"><?php _e('No', 'wp-maintenance'); ?></label>
55
+ </div>
56
+ </div>
57
+ <div class="clear"></div>
58
+ </div>
59
+
60
+ <div id="option-pageperso" style="<?php if( empty($paramMMode['pageperso']) || isset($paramMMode['pageperso']) && $paramMMode['pageperso']==0) { echo ' display:none;'; } else { echo 'display:block'; } ?>">
61
+ <?php _e('You can use this shortcode to include Google Analytics code:', 'wp-maintenance'); ?> <input type="text" value="do_shortcode('[wpm_analytics']);" onclick="select()" style="width:250px;" /><br /><?php _e('You can use this shortcode to include Social Networks icons:', 'wp-maintenance'); ?> <input type="text" value="do_shortcode('[wpm_social]');" onclick="select()" style="width:250px;" /><br />
62
+ </div>
63
+
64
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
65
+
66
+ <div>
67
+ <div style="float:left; width:70%;"><h3><?php _e('Delete custom settings upon plugin deactivation?', 'wp-maintenance'); ?></h3><span class="description"><?php _e( 'If you set "Yes" all custom settings will be deleted from database upon plugin deactivation', 'wp-maintenance' ); ?></span></div>
68
+ <div style="float:left; width:30%;margin-top:25px;text-align:right;">
69
+ <div class="switch-field">
70
+ <input class="switch_left" type="radio" id="switch_deletedb" name="wp_maintenance_settings[dashboard_delete_db]" value="Yes" <?php if( isset($paramMMode['dashboard_delete_db']) && $paramMMode['dashboard_delete_db']=='Yes' ) { echo ' checked'; } ?>/>
71
+ <label for="switch_deletedb"><?php _e('Yes', 'wp-maintenance'); ?></label>
72
+ <input class="switch_right" type="radio" id="switch_deletedb_no" name="wp_maintenance_settings[dashboard_delete_db]" value="No" <?php if( empty($paramMMode['dashboard_delete_db']) || (isset($paramMMode['dashboard_delete_db']) && $paramMMode['dashboard_delete_db']=='No') ) { echo ' checked'; } ?> />
73
+ <label for="switch_deletedb_no"><?php _e('No', 'wp-maintenance'); ?></label>
74
+ </div>
75
+ </div>
76
+ <div class="clear"></div>
77
+ </div>
78
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
79
+
80
+ <!-- Roles and Capabilities -->
81
+ <h3><?php _e('Roles and Capabilities:', 'wp-maintenance'); ?></h3>
82
+ <?php _e('Allow the site to display these roles:', 'wp-maintenance'); ?>&nbsp;<br /><br />
83
+ <input type="hidden" name="wp_maintenance_limit[administrator]" value="administrator" />
84
+ <div style="text-align:left;">
85
+ <?php
86
+ $roles = wpm_get_roles();
87
+ foreach($roles as $role=>$name) {
88
+ $limitCheck = '';
89
+ if( isset($paramLimit[$role]) && $paramLimit[$role]==$role) { $limitCheck = ' checked'; }
90
+ if( $role=='administrator') {
91
+ $limitCheck = 'checked disabled="disabled"';
92
+ }
93
+ ?>
94
+ <input type="checkbox" class="switch-field" name="wp_maintenance_limit[<?php echo $role; ?>]" value="<?php echo $role; ?>"<?php echo $limitCheck; ?> /><?php echo $name; ?>&nbsp;
95
+ <?php }//end foreach ?>
96
+ </div>
97
+
98
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
99
+
100
+ <!-- IP addresses autorized -->
101
+ <h3><?php _e('IP autorized:', 'wp-maintenance'); ?></h3>
102
+ <?php _e('Allow the site to display these IP addresses. Please, enter one IP address by line:', 'wp-maintenance'); ?>&nbsp;<br /><br />
103
+ <textarea name="wp_maintenance_ipaddresses" class="wpm-form-field" ROWS="5" style="width:80%;"><?php if( isset($paramIpAddress) && $paramIpAddress!='' ) { echo $paramIpAddress; } ?></textarea>
104
+
105
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
106
+
107
+ <!-- ID pages autorized -->
108
+ <h3><?php _e('ID pages autorized:', 'wp-maintenance'); ?></h3>
109
+ <?php _e('Allow the site to display these ID pages. Please, enter the ID pages separate with comma :', 'wp-maintenance'); ?>&nbsp;<br /><br />
110
+ <input name="wp_maintenance_settings[id_pages]" class="wpm-form-field" size="70" value="<?php if( isset($paramMMode['id_pages']) && $paramMMode['id_pages']!='' ) { echo $paramMMode['id_pages']; } ?>" />
111
+
112
+ <div style="margin-top:15px;margin-bottom:15px;"><hr /></div>
113
+
114
+ <!-- Header Code -->
115
+ <h3><?php _e('Header Code:', 'wp-maintenance'); ?></h3>
116
+ <?php _e('The following code will add to the <head> tag. Useful if you need to add additional scripts such as CSS or JS.', 'wp-maintenance'); ?>&nbsp;<br /><br />
117
+ <textarea id="headercode" name="wp_maintenance_settings[headercode]" COLS=50 ROWS=2><?php if( isset($paramMMode['headercode']) && $paramMMode['headercode']!='' ) { echo stripslashes($paramMMode['headercode']); } ?></textarea><br />
118
+
119
+
120
+
121
+
122
+ <?php submit_button(); ?>
123
+
124
+
125
+ </div>
126
+
127
+ <?php echo wpm_sidebar(); ?>
128
+
129
+ </div>
130
+ </form>
131
+ <script>
132
+ var editor = CodeMirror.fromTextArea(document.getElementById("headercode"), {
133
+ lineNumbers: true,
134
+ matchBrackets: true,
135
+ textWrapping: true,
136
+ lineWrapping: true,
137
+ mode: "text/x-scss",
138
+ theme:"material"
139
+ });
140
+ </script>
141
+ <?php echo wpm_footer(); ?>
142
+
143
+ </div>
wp-maintenance-admin.php DELETED
@@ -1,917 +0,0 @@
1
- <?php
2
-
3
- defined( 'ABSPATH' )
4
- or die( 'No direct load ! ' );
5
-
6
- if(!defined('WPM_PLUGIN_URL')) { define('WPM_PLUGIN_URL', WP_CONTENT_URL.'/plugins/wp-maintenance/'); }
7
- if(!defined('WPM_ICONS_URL')) { define('WPM_ICONS_URL', WP_CONTENT_URL.'/plugins/wp-maintenance/socialicons/'); }
8
-
9
- /* Update des paramètres */
10
- if( isset($_POST['action']) && $_POST['action'] == 'update' && $_POST["wp_maintenance_settings"]!='') {
11
-
12
- if( isset($_POST["wpm_maintenance_detete"]) && is_array($_POST["wpm_maintenance_detete"]) ) {
13
- foreach($_POST["wpm_maintenance_detete"] as $delSlideId=>$delSlideTrue) {
14
- if (array_key_exists($delSlideId, $_POST["wp_maintenance_slider"]["slider_image"])) {
15
- unset($_POST["wp_maintenance_slider"]["slider_image"][$delSlideId]);
16
- unset($_POST["wp_maintenance_slider"]["slider_text"][$delSlideId]);
17
- unset($_POST["wp_maintenance_slider"]["slider_link"][$delSlideId]);
18
- }
19
- }
20
- }
21
- if( isset($_POST["wp_maintenance_social_options"]['reset']) && $_POST["wp_maintenance_social_options"]['reset'] ==1 ) {
22
- unset($_POST["wp_maintenance_social"]);
23
- }
24
-
25
- update_option('wp_maintenance_slider', $_POST["wp_maintenance_slider"]);
26
- update_option('wp_maintenance_settings', $_POST["wp_maintenance_settings"]);
27
- update_option('wp_maintenance_slider_options', $_POST["wp_maintenance_slider_options"]);
28
- update_option('wp_maintenance_style', stripslashes($_POST["wp_maintenance_style"]));
29
- update_option('wp_maintenance_limit', $_POST["wp_maintenance_limit"]);
30
- update_option('wp_maintenance_ipaddresses', $_POST["wp_maintenance_ipaddresses"]);
31
- update_option('wp_maintenance_active', $_POST["wp_maintenance_active"]);
32
- update_option('wp_maintenance_social', $_POST["wp_maintenance_social"]);
33
- update_option('wp_maintenance_social_options', $_POST["wp_maintenance_social_options"]);
34
- $options_saved = true;
35
- echo '<div id="message" class="updated fade"><p><strong>'.__('Options saved.', 'wp-maintenance').'</strong></p></div>';
36
- }
37
-
38
- // Récupère les paramètres sauvegardés
39
- if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
40
- $paramMMode = get_option('wp_maintenance_settings');
41
-
42
- if( isset($paramMMode) && !empty($paramMMode) ) {
43
- foreach($paramMMode as $variable=>$value) {
44
- if( !isset($paramMMode[$variable]) ) { $paramMMode[$variable] = $value; }
45
- }
46
- }
47
-
48
- if(get_option('wp_maintenance_slider')) { extract(get_option('wp_maintenance_slider')); }
49
- $paramSlider = get_option('wp_maintenance_slider');
50
-
51
- if(get_option('wp_maintenance_slider_options')) { extract(get_option('wp_maintenance_slider_options')); }
52
- $paramSliderOptions = get_option('wp_maintenance_slider_options');
53
-
54
- // Récupère les Rôles et capabilités
55
- if(get_option('wp_maintenance_limit')) { extract(get_option('wp_maintenance_limit')); }
56
- $paramLimit = get_option('wp_maintenance_limit');
57
-
58
- // Récupère les ip autorisee
59
- $paramIpAddress = get_option('wp_maintenance_ipaddresses');
60
-
61
- // Récupère si le status est actif ou non
62
- $statusActive = get_option('wp_maintenance_active');
63
-
64
- // Récupère les Reseaux Sociaux
65
- $paramSocial = get_option('wp_maintenance_social');
66
- if(get_option('wp_maintenance_social_options')) { extract(get_option('wp_maintenance_social_options')); }
67
- $paramSocialOption = get_option('wp_maintenance_social_options');
68
-
69
-
70
- /* Si on réinitialise les feuille de styles */
71
- if( isset($_POST['wpm_initcss']) && $_POST['wpm_initcss']==1) {
72
- update_option( 'wp_maintenance_style', wpm_print_style() );
73
- $options_saved = true;
74
- echo '<div id="message" class="updated fade"><p><strong>'.__('The Style Sheet has been reset!', 'wp-maintenance').'</strong></p></div>';
75
- }
76
-
77
- ?>
78
- <style>
79
- .sortable { list-style-type: none; margin: 0; padding: 0; width: 60%; }
80
- .sortable li { padding: 0.4em; padding-left: 1.5em; height: 30px;cursor: pointer; cursor: move; }
81
- .sortable li span { font-size: 15px;margin-right: 0.8em;cursor: move; }
82
- .sortable li:hover { background-color: #d2d2d2; }
83
- #pattern { text-align: left; margin: 5px 0; word-spacing: -1em;list-style-type: none; }
84
- #pattern li { display: inline-block; list-style: none;margin-right:15px;text-align:center; }
85
- #pattern li.current { background: #66CC00; color: #fff; }
86
- </style>
87
- <style type="text/css">.postbox h3 { cursor:pointer; }</style>
88
- <!--<script src="<?php //echo WP_PLUGIN_URL; ?>/wp-maintenance/js/jquery-ui-timepicker-addon.js"></script>-->
89
- <script type="text/javascript">
90
- jQuery(document).ready(function() {
91
- jQuery('#font_title').fontselect();
92
- jQuery('#font_text').fontselect();
93
- jQuery('#font_text_bottom').fontselect();
94
- jQuery('#font_text_cpt').fontselect();
95
- jQuery('#font_text_newletter').fontselect();
96
- });
97
-
98
- function AfficherCacher(texte) {
99
- var test = document.getElementById(texte).style.display;
100
- if (test == "block")
101
- {
102
- document.getElementById(texte).style.display = "none";
103
- }
104
- else
105
- {
106
- document.getElementById(texte).style.display = "block";
107
- }
108
- }
109
-
110
-
111
- </script>
112
- <div class="wrap">
113
-
114
- <h2 style="font-size: 23px;font-weight: 400;padding: 9px 15px 4px 0px;line-height: 29px;">
115
- <?php echo __('WP Maintenance Settings', 'wp-maintenance'); ?>
116
- </h2>
117
-
118
- <!-- TABS OPTIONS -->
119
- <h2 class="nav-tab-wrapper">
120
- <a id="wpm-menu-general" class="nav-tab nav-tab-active" href="#general" onfocus="this.blur();"><?php _e('General', 'wp-maintenance'); ?></a>
121
- <a id="wpm-menu-couleurs" class="nav-tab" href="#couleurs" onfocus="this.blur();"><?php _e('Colors & Fonts', 'wp-maintenance'); ?></a>
122
- <a id="wpm-menu-image" class="nav-tab" href="#image" onfocus="this.blur();"><?php _e('Picture', 'wp-maintenance'); ?></a>
123
- <a id="wpm-menu-compte" class="nav-tab" href="#compte" onfocus="this.blur();"><?php _e('CountDown', 'wp-maintenance'); ?></a>
124
- <a id="wpm-menu-styles" class="nav-tab" href="#styles" onfocus="this.blur();"><?php _e('CSS Style', 'wp-maintenance'); ?></a>
125
- <a id="wpm-menu-options" class="nav-tab" href="#options" onfocus="this.blur();"><?php _e('Settings', 'wp-maintenance'); ?></a>
126
- <a id="wpm-menu-apropos" class="nav-tab" href="#apropos" onfocus="this.blur();"><?php _e('About', 'wp-maintenance'); ?></a>
127
- </h2>
128
-
129
- <div style="margin-left: 0px;margin-top: 5px;background-color: #ffffff;border: 1px solid #cccccc;padding: 10px;">
130
- <form method="post" action="" name="valide_maintenance">
131
- <input type="hidden" name="action" value="update" />
132
-
133
- <!-- GENERAL -->
134
- <div class="wpm-menu-general wpm-menu-group">
135
- <div id="wpm-opt-general" >
136
- <ul>
137
- <!-- CHOIX ACTIVATION MAINTENANCE -->
138
- <li>
139
- <h3><?php _e('Enable maintenance mode:', 'wp-maintenance'); ?></h3>
140
- <input type= "radio" name="wp_maintenance_active" value="1" <?php if($statusActive==1) { echo ' checked'; } ?>>&nbsp;<?php _e('Yes', 'wp-maintenance'); ?>&nbsp;&nbsp;&nbsp;
141
- <input type= "radio" name="wp_maintenance_active" value="0" <?php if($statusActive==0) { echo ' checked'; } ?>>&nbsp;<?php _e('No', 'wp-maintenance'); ?>
142
- </li>
143
- <!-- TEXTE PERSONNEL POUR LA PAGE -->
144
- <li>
145
- <h3><?php _e('Title and text for the maintenance page:', 'wp-maintenance'); ?></h3>
146
- <?php _e('Title:', 'wp-maintenance'); ?><br /><input type="text" name="wp_maintenance_settings[titre_maintenance]" value="<?php if( isset($paramMMode['titre_maintenance']) ) { echo stripslashes($paramMMode['titre_maintenance']); } ?>" size="70" /><br />
147
- <?php _e('Text:', 'wp-maintenance'); ?><br /><TEXTAREA NAME="wp_maintenance_settings[text_maintenance]" COLS=70 ROWS=4><?php echo stripslashes($paramMMode['text_maintenance']); ?></TEXTAREA>
148
- <h3><?php _e('Text in the bottom of maintenance page:', 'wp-maintenance'); ?></h3>
149
- <?php _e('Text:', 'wp-maintenance'); ?><br /><TEXTAREA NAME="wp_maintenance_settings[text_bt_maintenance]" COLS=70 ROWS=4><?php if( isset($paramMMode['text_bt_maintenance']) ) { echo stripslashes($paramMMode['text_bt_maintenance']); } ?></TEXTAREA><br /><br />
150
- <input type= "checkbox" name="wp_maintenance_settings[add_wplogin]" value="1" <?php if( isset($paramMMode['add_wplogin']) && $paramMMode['add_wplogin']==1 ) { echo ' checked'; } ?>> <?php _e('Enable login access in the bottom ?', 'wp-maintenance'); ?><br /><br />
151
- <?php _e('Enter a text to go to the dashboard:', 'wp-maintenance'); ?><br />
152
- <input type="text" name="wp_maintenance_settings[add_wplogin_title]" size="60" value="<?php echo stripslashes(trim($paramMMode['add_wplogin_title'])); ?>" /><br />
153
- <small><?php _e('Eg: connect to %DASHBOARD% here!', 'wp-maintenance'); ?> <?php _e('(%DASHBOARD% will be replaced with the link to the dashboard and the word "Dashboard")', 'wp-maintenance'); ?></small>
154
- </li>
155
-
156
- <li>
157
- <h3><?php _e('Enable Google Analytics:', 'wp-maintenance'); ?></h3>
158
- <input type= "checkbox" name="wp_maintenance_settings[analytics]" value="1" <?php if( isset($paramMMode['analytics']) && $paramMMode['analytics'] ==1) { echo ' checked'; } ?>><?php _e('Yes', 'wp-maintenance'); ?><br /><br />
159
- <?php _e('Enter your Google analytics tracking ID here:', 'wp-maintenance'); ?><br />
160
- <input type="text" name="wp_maintenance_settings[code_analytics]" value="<?php echo stripslashes(trim($paramMMode['code_analytics'])); ?>"><br />
161
- <?php _e('Enter your domain URL:', 'wp-maintenance'); ?><br />
162
- <input type="text" size="40" name="wp_maintenance_settings[domain_analytics]" value="<?php echo stripslashes(trim($paramMMode['domain_analytics'])); ?>">
163
- </li>
164
- <li>&nbsp;</li>
165
-
166
- <li>
167
- <h3><?php _e('Enable Social Networks:', 'wp-maintenance'); ?></h3>
168
- <input type= "checkbox" name="wp_maintenance_social_options[enable]" value="1" <?php if( isset($paramSocialOption['enable']) && $paramSocialOption['enable']==1) { echo ' checked'; } ?>><?php _e('Yes', 'wp-maintenance'); ?><br /><br />
169
- <?php _e('Enter text for the title icons:', 'wp-maintenance'); ?>
170
- <input type="text" name="wp_maintenance_social_options[texte]" value="<?php if($paramSocialOption['texte']=='') { _e('Follow me on', 'wp-maintenance'); } else { echo stripslashes(trim($paramSocialOption['texte'])); } ?>" /><br /><br />
171
- <!-- Liste des réseaux sociaux -->
172
- <?php _e('Drad and drop the lines to put in the order you want:', 'wp-maintenance'); ?><br /><br />
173
- <ul class="sortable">
174
- <?php
175
- if( isset($paramSocial) && !empty($paramSocial) ) {
176
-
177
- foreach($paramSocial as $socialName=>$socialUrl) {
178
- ?>
179
- <li><span>::</span><img src="<?php echo WPM_ICONS_URL; ?>24x24/<?php echo $socialName; ?>.png" hspace="3" valign="middle" /><?php echo ucfirst($socialName); ?> <input type= "text" name="wp_maintenance_social[<?php echo $socialName; ?>]" value="<?php echo $socialUrl; ?>" size="50" onclick="select()" /></li>
180
- <?php
181
- }
182
-
183
- } else {
184
-
185
- $wpmTabSocial = array('facebook', 'twitter', 'linkedin', 'flickr', 'youtube', 'pinterest', 'vimeo', 'instagram', 'google_plus', 'about_me', 'soundcloud');
186
-
187
- foreach ($wpmTabSocial as &$iconSocial) {
188
- echo '<li><span>::</span><img src="'.WPM_ICONS_URL.'24x24/'.$iconSocial.'.png" valign="middle" hspace="3"/>'.ucfirst($iconSocial).' <input type="text" size="50" name="wp_maintenance_social['.$iconSocial.']" value="" onclick="select()" ><br />';
189
- }
190
-
191
- }
192
- ?>
193
- </ul>
194
- <script src="<?php echo WPM_PLUGIN_URL; ?>js/jquery.sortable.js"></script>
195
- <script>
196
- jQuery('.sortable').sortable();
197
- </script>
198
- <br />
199
- <?php _e('Choose icons size:', 'wp-maintenance'); ?>
200
- <select name="wp_maintenance_social_options[size]">
201
- <?php
202
- $wpm_tabIcon = array(16, 24, 32, 48, 64, 128);
203
- foreach($wpm_tabIcon as $wpm_icon) {
204
- if($paramSocialOption['size']==$wpm_icon) { $selected = ' selected'; } else { $selected = ''; }
205
- echo '<option value="'.$wpm_icon.'" '.$selected.'>'.$wpm_icon.'</option>';
206
- }
207
- ?>
208
- </select>
209
- </li>
210
- <li>
211
- <?php _e('Position:', 'wp-maintenance'); ?>
212
- <select name="wp_maintenance_social_options[position]">
213
- <option value="top"<?php if($paramSocialOption['position']=='top') { echo ' selected'; } ?>><?php _e('Top', 'wp-maintenance'); ?></option>
214
- <option value="bottom"<?php if(!$paramSocialOption['position'] or $paramSocialOption['position']=='bottom') { echo ' selected'; } ?>><?php _e('Bottom', 'wp-maintenance'); ?></option>
215
- </select>
216
- </li>
217
- <li>
218
- <?php _e('Align:', 'wp-maintenance'); ?>
219
- <select name="wp_maintenance_social_options[align]">
220
- <option value="left"<?php if($paramSocialOption['align']=='left') { echo ' selected'; } ?>><?php _e('Left', 'wp-maintenance'); ?></option>
221
- <option value="center"<?php if($paramSocialOption['align']=='' or $paramSocialOption['align']=='center') { echo ' selected'; } ?>><?php _e('Center', 'wp-maintenance'); ?></option>
222
- <option value="right"<?php if($paramSocialOption['align']=='right') { echo ' selected'; } ?>><?php _e('Right', 'wp-maintenance'); ?></option>
223
- </select>
224
- <br /><br />
225
- <?php _e('You have your own icons? Enter the folder name of your theme here:', 'wp-maintenance'); ?><br /><strong><?php echo get_stylesheet_directory_uri(); ?>/</strong><input type="text" value="<?php echo stripslashes(trim($paramSocialOption['theme'])); ?>" name="wp_maintenance_social_options[theme]" /><br /><br />
226
- </li>
227
- <li>
228
- <input type="checkbox" name="wp_maintenance_social_options[reset]" value="1" /> <i><?php _e('Reset Social Icon?', 'wp-maintenance'); ?></i>
229
- </li>
230
- <li>&nbsp;</li>
231
-
232
- <!-- Encart Newletter -->
233
- <li>
234
- <h3><?php _e('Enable Newletter:', 'wp-maintenance'); ?></h3>
235
- <input type= "checkbox" name="wp_maintenance_settings[newletter]" value="1" <?php if( isset($paramMMode['newletter']) && $paramMMode['newletter']==1) { echo ' checked'; } ?>><?php _e('Yes', 'wp-maintenance'); ?><br /><br />
236
- <?php _e('Enter title for the newletter block:', 'wp-maintenance'); ?><br />
237
- <input type="text" name="wp_maintenance_settings[title_newletter]" size="60" value="<?php echo stripslashes(trim($paramMMode['title_newletter'])); ?>" /><br /><br />
238
- <input type="radio" name="wp_maintenance_settings[type_newletter]" value="shortcode" <?php if( isset($paramMMode['type_newletter']) && $paramMMode['type_newletter']=='shortcode' ) { echo 'checked'; } if( empty($paramMMode['type_newletter']) ) { echo 'checked'; } ?> /><?php _e('Enter your newletter shortcode here:', 'wp-maintenance'); ?><br />
239
- <input type="text" name="wp_maintenance_settings[code_newletter]" value='<?php echo stripslashes(trim($paramMMode['code_newletter'])); ?>' onclick="select()" /><br /><br />
240
- <input type="radio" name="wp_maintenance_settings[type_newletter]" value="iframe" <?php if( isset($paramMMode['type_newletter']) && $paramMMode['type_newletter']=='iframe' ) { echo 'checked'; } ?>/> <?php _e('Or enter your newletter iframe code here:', 'wp-maintenance'); ?><br />
241
- <textarea cols="60" rows="10" name="wp_maintenance_settings[iframe_newletter]"><?php if( isset($paramMMode['iframe_newletter'])) { echo stripslashes(trim($paramMMode['iframe_newletter'])); } ?></textarea>
242
- </li>
243
- <li>&nbsp;</li>
244
-
245
- <li>
246
- <p>
247
- <?php submit_button(); ?>
248
- </p>
249
- </li>
250
- </ul>
251
- </div>
252
- </div>
253
- <!-- fin options 1 -->
254
-
255
-
256
- <!-- Couleurs -->
257
- <div class="wpm-menu-couleurs wpm-menu-group" style="display: none;">
258
- <div id="wpm-opt-couleurs">
259
- <ul>
260
- <!-- COULEUR DU FOND DE PAGE -->
261
- <li>
262
- <h3><?php _e('Choice general colors:', 'wp-maintenance'); ?></h3>
263
- <em><?php _e('Background page color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php echo $paramMMode['color_bg']; ?>" name="wp_maintenance_settings[color_bg]" class="wpm-color-field" data-default-color="#f1f1f1" /> <br />
264
- <em><?php _e('Header color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php echo $paramMMode['color_bg_header']; ?>" name="wp_maintenance_settings[color_bg_header]" class="wpm-color-field" data-default-color="#333333" />
265
- </li>
266
-
267
- <li>
268
- <h3><?php _e('Choice texts fonts and colors:', 'wp-maintenance'); ?></h3>
269
- <em><?php _e('Text color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php echo $paramMMode['color_txt']; ?>" name="wp_maintenance_settings[color_txt]" class="wpm-color-field" data-default-color="#888888" /><br /><br />
270
- <!-- POLICE DU TITRE -->
271
- <em><stong><?php _e('Title font settings', 'wp-maintenance'); ?></stong></em>
272
- <table cellspacing="10">
273
- <tr>
274
- <td valign="top" align="left"><input name="wp_maintenance_settings[font_title]" id="font_title" type="text" value="<?php echo $paramMMode['font_title']; ?>" />
275
-
276
- <div id="fontSelect" class="fontSelect">
277
- <div class="arrow-down"></div>
278
- </div>
279
-
280
- <div id="fontSelect2" class="fontSelect">
281
- <div class="arrow-down"></div>
282
- </div>
283
- </td>
284
- <td>
285
- <?php _e('Size:', 'wp-maintenance'); ?>
286
- <input type="text" size="3" name="wp_maintenance_settings[font_title_size]" value="<?php echo stripslashes($paramMMode['font_title_size']); ?>" />px
287
-
288
- </td>
289
- </tr>
290
- <tr>
291
- <td rowspan="2">
292
- <input type="radio" name="wp_maintenance_settings[font_title_weigth]" value="normal" <?php if( isset($paramMMode['font_title_weigth']) && $paramMMode['font_title_weigth']=='normal') { echo 'checked'; } ?> >Normal
293
- <input type="radio" name="wp_maintenance_settings[font_title_weigth]" value="bold" <?php if( isset($paramMMode['font_title_weigth']) && $paramMMode['font_title_weigth']=='bold') { echo 'checked'; } ?>>Bold
294
- <input type="checkbox" name="wp_maintenance_settings[font_title_style]" value="italic" <?php if( isset($paramMMode['font_title_style']) && $paramMMode['font_title_style']=='italic') { echo 'checked'; } ?>>Italic
295
- </td>
296
- </tr>
297
- </table>
298
- <!-- FIN POLICE DU TITRE-->
299
-
300
- <!-- POLICE DU TEXTE -->
301
- <br /><em><?php _e('Text font settings', 'wp-maintenance'); ?></em>
302
- <table cellspacing="10">
303
- <tr>
304
- <td valign="top" align="left"><input name="wp_maintenance_settings[font_text]" id="font_text" type="text" value="<?php echo $paramMMode['font_text']; ?>" /></td>
305
- <td>
306
- <?php _e('Size:', 'wp-maintenance'); ?>
307
- <input type="text" size="3" name="wp_maintenance_settings[font_text_size]" value="<?php echo stripslashes($paramMMode['font_text_size']); ?>" />px
308
-
309
- </td>
310
- </tr>
311
- <tr>
312
- <td rowspan="2">
313
- <input type="radio" name="wp_maintenance_settings[font_text_weigth]" value="normal" <?php if( isset($paramMMode['font_text_weigth']) && $paramMMode['font_text_weigth']=='normal') { echo 'checked'; } ?> >Normal
314
- <input type="radio" name="wp_maintenance_settings[font_text_weigth]" value="bold" <?php if( isset($paramMMode['font_text_weigth']) && $paramMMode['font_text_weigth']=='bold') { echo 'checked'; } ?>>Bold
315
- <input type="checkbox" name="wp_maintenance_settings[font_text_style]" value="italic" <?php if( isset($paramMMode['font_text_style']) && $paramMMode['font_text_style']=='italic') { echo 'checked'; } ?>>Italic
316
- </td>
317
- </tr>
318
- </table>
319
- <!-- FIN POLICE DU TEXTE -->
320
-
321
- <!-- CADRE -->
322
- <br /><em><?php _e('Frame settings', 'wp-maintenance'); ?></em><br /><br />
323
-
324
- <input type="checkbox" name="wp_maintenance_settings[container_active]" value="1" <?php if( isset($paramMMode['container_active']) && $paramMMode['container_active']==1) { echo 'checked'; } ?>> <?php _e('Activate', 'wp-maintenance'); ?><br /><br /><?php _e('Color:', 'wp-maintenance'); ?><br /> <input type="text" value="<?php if( isset($paramMMode['container_color'])) { echo $paramMMode['container_color']; } else { echo '#ffffff'; }?>" name="wp_maintenance_settings[container_color]" class="wpm-color-field" data-default-color="#ffffff" /><br />
325
- <?php _e('Opacity:', 'wp-maintenance'); ?>
326
- <input type="text" size="3" name="wp_maintenance_settings[container_opacity]" value="<?php if( isset($paramMMode['container_opacity']) ) { echo $paramMMode['container_opacity']; } else { echo '0.5'; } ?>" />
327
- <?php _e('Width:', 'wp-maintenance'); ?>
328
- <input type="text" size="2" name="wp_maintenance_settings[container_width]" value="<?php if( isset($paramMMode['container_width']) ) { echo $paramMMode['container_width']; } else { echo '80'; } ?>" />%
329
- <!-- FIN CADRE -->
330
-
331
- </li>
332
-
333
- <!-- BOTTOM PAGE -->
334
- <li>
335
- <h3><?php _e('Choice fonts and colors bottom page:', 'wp-maintenance'); ?></h3>
336
- <em><?php _e('Bottom color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php echo $paramMMode['color_bg_bottom']; ?>" name="wp_maintenance_settings[color_bg_bottom]" class="wpm-color-field" data-default-color="#333333" /> <br />
337
- <em><?php _e('Text bottom color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php echo $paramMMode['color_text_bottom']; ?>" name="wp_maintenance_settings[color_text_bottom]" class="wpm-color-field" data-default-color="#ffffff" /><br /><br />
338
-
339
- <!-- POLICE DU TEXTE BAS DE PAGE -->
340
- <em><?php _e('Text font settings', 'wp-maintenance'); ?></em>
341
- <table cellspacing="10">
342
- <tr>
343
- <td valign="top" align="left"><input name="wp_maintenance_settings[font_text_bottom]" id="font_text_bottom" type="text" value="<?php echo $paramMMode['font_text_bottom']; ?>" /></td>
344
- <td>
345
- <?php _e('Size:', 'wp-maintenance'); ?>
346
- <input type="text" size="3" name="wp_maintenance_settings[font_bottom_size]" value="<?php echo stripslashes($paramMMode['font_bottom_size']); ?>" />px
347
-
348
- </td>
349
- </tr>
350
- <tr>
351
- <td rowspan="2">
352
- <input type="radio" name="wp_maintenance_settings[font_bottom_weigth]" value="normal" <?php if( isset($paramMMode['font_bottom_weigth']) && $paramMMode['font_bottom_weigth']=='normal') { echo 'checked'; } ?> >Normal
353
- <input type="radio" name="wp_maintenance_settings[font_bottom_weigth]" value="bold" <?php if( isset($paramMMode['font_bottom_weigth']) && $paramMMode['font_bottom_weigth']=='bold') { echo 'checked'; } ?>>Bold
354
- <input type="checkbox" name="wp_maintenance_settings[font_bottom_style]" value="italic" <?php if( isset($paramMMode['font_bottom_style']) && $paramMMode['font_bottom_style']=='italic') { echo 'checked'; } ?>>Italic
355
- </td>
356
- </tr>
357
- </table>
358
- <br />
359
- <!-- FIN POLICE DU TEXTE BAS DE PAGE -->
360
-
361
- </li>
362
-
363
- <li>
364
- <h3><?php _e('Choice countdown fonts and colors:', 'wp-maintenance'); ?></h3>
365
- <em><?php _e('Countdown text color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php echo $paramMMode['color_cpt']; ?>" name="wp_maintenance_settings[color_cpt]" class="wpm-color-field" data-default-color="#888888" /><br />
366
- <em><?php _e('Countdown background color:', 'wp-maintenance'); ?></em> <br /><input type="text" value="<?php echo $paramMMode['color_cpt_bg']; ?>" name="wp_maintenance_settings[color_cpt_bg]" class="wpm-color-field" data-default-color="#888888" /><br /><br />
367
- </li>
368
-
369
- <li>
370
- <!-- POLICE DU COMPTEUR -->
371
- <em><?php _e('Countdown font settings', 'wp-maintenance'); ?></em>
372
- <table cellspacing="10">
373
- <tr>
374
- <td valign="top" align="left"><input name="wp_maintenance_settings[font_cpt]" id="font_text_cpt" type="text" value="<?php echo $paramMMode['font_cpt']; ?>" /></td>
375
- <td>
376
- <?php _e('Size:', 'wp-maintenance'); ?>
377
- <input type="text" size="3" id="date_cpt_size" name="wp_maintenance_settings[date_cpt_size]" value="<?php echo trim($paramMMode['date_cpt_size']); ?>" />px
378
-
379
- </td>
380
- </tr>
381
- </table>
382
- <!-- FIN POLICE DU COMPTEUR -->
383
- </li>
384
- <?php
385
- if( (strpos($paramMMode['code_newletter'], 'wysija_form')!=false || strpos($paramMMode['code_newletter'], 'mc4wp_form')!=false ) && (is_plugin_active( 'wysija-newsletters/index.php' ) || is_plugin_active( 'mailchimp-for-wp/mailchimp-for-wp.php' ) ) ) {
386
- ?>
387
- <li>
388
- <h3><?php _e('Choice form color:', 'wp-maintenance'); ?></h3>
389
-
390
- <!-- COULEUR WYJIYA -->
391
- <table cellspacing="10">
392
- <tr>
393
- <td valign="top" align="left"><input name="wp_maintenance_settings[newletter_font_text]" id="font_text_newletter" type="text" value="<?php if( isset($paramMMode['newletter_font_text']) ) { echo $paramMMode['newletter_font_text']; } ?>" /></td>
394
- <td>
395
- <?php _e('Size:', 'wp-maintenance'); ?>
396
- <input type="text" size="3" name="wp_maintenance_settings[newletter_size]" value="<?php if( isset($paramMMode['newletter_size']) && $paramMMode['newletter_size']) { echo stripslashes($paramMMode['newletter_size']); } else { echo 14; } ?>" />px
397
-
398
- </td>
399
- </tr>
400
- <tr>
401
- <td rowspan="2">
402
- <input type="radio" name="wp_maintenance_settings[newletter_font_weigth]" value="normal" <?php if( isset($paramMMode['newletter_font_weigth']) && $paramMMode['newletter_font_weigth']=='normal') { echo 'checked'; } ?> >Normal
403
- <input type="radio" name="wp_maintenance_settings[newletter_font_weigth]" value="bold" <?php if( isset($paramMMode['newletter_font_weigth']) && $paramMMode['newletter_font_weigth']=='bold') { echo 'checked'; } ?>>Bold
404
- <input type="checkbox" name="wp_maintenance_settings[newletter_font_style]" value="italic" <?php if( isset($paramMMode['newletter_font_style']) && $paramMMode['newletter_font_style']=='italic') { echo 'checked'; } ?>>Italic
405
- </td>
406
- </tr>
407
- </table>
408
- <br />
409
- <em><?php _e('Field text color:', 'wp-maintenance'); ?></em> <br />
410
- <input type="text" value="<?php if( isset($paramMMode['color_field_text']) ) { echo $paramMMode['color_field_text']; } else { echo '#333333'; } ?>" name="wp_maintenance_settings[color_field_text]" class="wpm-color-field" data-default-color="#333333" /><br />
411
- <em><?php _e('Field border color:', 'wp-maintenance'); ?></em> <br />
412
- <input type="text" value="<?php if( isset($paramMMode['color_field_border']) ) { echo $paramMMode['color_field_border']; } else { echo '#333333'; } ?>" name="wp_maintenance_settings[color_field_border]" class="wpm-color-field" data-default-color="#333333" /><br />
413
- <em><?php _e('Field background color:', 'wp-maintenance'); ?></em> <br />
414
- <input type="text" value="<?php if( isset($paramMMode['color_field_background']) ) { echo $paramMMode['color_field_background']; } else { echo '#cccccc'; } ?>" name="wp_maintenance_settings[color_field_background]" class="wpm-color-field" data-default-color="#cccccc" />
415
- <br />
416
- <em><?php _e('Button text color:', 'wp-maintenance'); ?></em> <br />
417
- <input type="text" value="<?php if( isset($paramMMode['color_text_button']) ) { echo $paramMMode['color_text_button'];} else { echo '#ffffff'; } ?>" name="wp_maintenance_settings[color_text_button]" class="wpm-color-field" data-default-color="#ffffff" />
418
- <br />
419
- <em><?php _e('Button color:', 'wp-maintenance'); ?></em> <br />
420
- <input type="text" value="<?php if( isset($paramMMode['color_button']) ) { echo $paramMMode['color_button']; } else { echo '#1e73be'; } ?>" name="wp_maintenance_settings[color_button]" class="wpm-color-field" data-default-color="#1e73be" />
421
- <br />
422
- <em><?php _e('Button color hover:', 'wp-maintenance'); ?></em> <br />
423
- <input type="text" value="<?php if( isset($paramMMode['color_button_hover']) ) { echo $paramMMode['color_button_hover']; } else { echo '#ffffff'; } ?>" name="wp_maintenance_settings[color_button_hover]" class="wpm-color-field" data-default-color="#ffffff" /><br />
424
- <em><?php _e('Button color onclick:', 'wp-maintenance'); ?></em> <br />
425
- <input type="text" value="<?php if( isset($paramMMode['color_button_onclick']) ) { echo $paramMMode['color_button_onclick']; } else { echo '#ffffff'; } ?>" name="wp_maintenance_settings[color_button_onclick]" class="wpm-color-field" data-default-color="#ffffff" />
426
-
427
- </li>
428
- <?php } ?>
429
-
430
- <li>&nbsp;</li>
431
-
432
- <li>
433
- <p>
434
- <?php submit_button(); ?>
435
- </p>
436
- </li>
437
-
438
- </ul>
439
- </div>
440
- </div>
441
- <!-- fin options 2 -->
442
-
443
- <!-- Onglet options 3 -->
444
- <div class="wpm-menu-image wpm-menu-group" style="display: none;">
445
- <div id="wpm-opt-image" >
446
- <ul>
447
- <!-- UPLOADER UNE IMAGE -->
448
- <?php
449
- if( isset($paramMMode['image']) && $paramMMode['image']!='' && ini_get('allow_url_fopen')==1 ) {
450
- list($logoWidth, $logoHeight, $logoType, $logoAttr) = getimagesize($paramMMode['image']);
451
- } else {
452
- $logoWidth = 250;
453
- }
454
- ?>
455
- <li>
456
- <h3><?php _e('Upload a picture', 'wp-maintenance'); ?></h3>
457
- <?php if($paramMMode['image']) { ?>
458
- <?php _e('You use this picture:', 'wp-maintenance'); ?><br /> <img src="<?php echo $paramMMode['image']; ?>" width="<?php echo $logoWidth; ?>" height="<?php echo $logoHeight; ?>" id="image_visuel" style="border:1px solid #333;padding:3px;" /><br />
459
- <?php } ?>
460
- <br /><small><?php _e('Enter a URL or upload an image.', 'wp-maintenance'); ?></small><br />
461
- <input id="upload_image" size="36" name="wp_maintenance_settings[image]" value="<?php echo $paramMMode['image']; ?>" type="text" /> <a href="#" id="upload_image_button" class="button" OnClick="this.blur();"><span> <?php _e('Select or Upload your picture', 'wp-maintenance'); ?> </span></a>
462
- </li>
463
- <li>&nbsp;</li>
464
-
465
- <!-- UPLOADER UNE IMAGE DE FOND -->
466
- <li>
467
- <h3><?php _e('Upload a background picture', 'wp-maintenance'); ?></h3>
468
- <input type= "checkbox" name="wp_maintenance_settings[b_enable_image]" value="1" <?php if( isset($paramMMode['b_enable_image']) && $paramMMode['b_enable_image']==1) { echo ' checked'; } ?>> <?php _e('Enable image background', 'wp-maintenance'); ?><br /><br />
469
- <?php if( isset($paramMMode['b_image']) && $paramMMode['b_image']!='' && (!$paramMMode['b_pattern'] or $paramMMode['b_pattern']==0) ) { ?>
470
- <?php _e('You use this background picture:', 'wp-maintenance'); ?><br />
471
- <img src="<?php echo $paramMMode['b_image']; ?>" width="300" style="border:1px solid #333;padding:3px;background: url('<?php echo $paramMMode['b_image']; ?>');" /><br />
472
- <?php } ?>
473
- <?php if( isset($paramMMode['b_pattern']) && $paramMMode['b_pattern']>0) { ?>
474
- <?php _e('You use this pattern:', 'wp-maintenance'); ?><br />
475
- <div style="background: url('<?php echo WP_PLUGIN_URL ?>/wp-maintenance/images/pattern<?php echo $paramMMode['b_pattern']; ?>.png');width:250px;height:250px;border:1px solid #333;"></div>
476
- <?php } ?>
477
- <input id="upload_b_image" size="36" name="wp_maintenance_settings[b_image]" value="<?php if( isset($paramMMode['b_image']) && !empty($paramMMode['b_image']) ) { echo $paramMMode['b_image']; } ?>" type="text" /> <a href="#" id="upload_b_image_button" class="button" OnClick="this.blur();"><span> <?php _e('Select or Upload your picture', 'wp-maintenance'); ?> </span></a>
478
- <br /><small><?php _e('Enter a URL or upload an image.', 'wp-maintenance'); ?></small><br /><br />
479
- <?php _e('Or choose a pattern:', 'wp-maintenance'); ?>
480
-
481
- <ul id="pattern">
482
- <li>
483
- <div style="width:50px;height:50px;border:1px solid #333;background-color:#ffffff;font-size:0.8em;"><?php _e('NO PATTERN', 'wp-maintenance'); ?></div>
484
- <input type="radio" value="0" <?php if( empty($paramMMode['b_pattern']) or $paramMMode['b_pattern']==0) { echo 'checked'; } ?> name="wp_maintenance_settings[b_pattern]" />
485
- </li>
486
- <?php for ($p = 1; $p <= 12; $p++) { ?>
487
- <li>
488
- <div style="width:50px;height:50px;border:1px solid #333;background:url('<?php echo WP_PLUGIN_URL ?>/wp-maintenance/images/pattern<?php echo $p ?>.png');"></div>
489
- <input type="radio" value="<?php echo $p; ?>" <?php if( isset($paramMMode['b_pattern']) && $paramMMode['b_pattern']==$p) { echo 'checked'; } ?> name="wp_maintenance_settings[b_pattern]" />
490
- </li>
491
- <?php } ?>
492
- </ul>
493
- </li>
494
-
495
- <li>
496
- <h3><?php _e('Background picture options', 'wp-maintenance'); ?></h3>
497
- <select name="wp_maintenance_settings[b_repeat_image]" >
498
- <option value="repeat"<?php if( isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='repeat' or $paramMMode['b_repeat_image']=='') { echo ' selected'; } ?>>repeat</option>
499
- <option value="no-repeat"<?php if( isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='no-repeat') { echo ' selected'; } ?>>no-repeat</option>
500
- <option value="repeat-x"<?php if( isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='repeat-x') { echo ' selected'; } ?>>repeat-x</option>
501
- <option value="repeat-y"<?php if( isset($paramMMode['b_repeat_image']) && $paramMMode['b_repeat_image']=='repeat-y') { echo ' selected'; } ?>>repeat-y</option>
502
- </select><br /><br />
503
- <input type= "checkbox" name="wp_maintenance_settings[b_fixed_image]" value="1" <?php if( isset($paramMMode['b_fixed_image']) && $paramMMode['b_fixed_image']==1) { echo ' checked'; } ?>>&nbsp;<?php _e('Fixed', 'wp-maintenance'); ?><br />
504
- </li>
505
- <li>&nbsp;</li>
506
-
507
- <li>
508
- <h3><?php _e('Slider image options', 'wp-maintenance'); ?></h3>
509
- <input type= "checkbox" name="wp_maintenance_settings[enable_slider]" value="1" <?php if( isset($paramMMode['enable_slider']) && $paramMMode['enable_slider']==1) { echo ' checked'; } ?>> <?php _e('Enable Slider', 'wp-maintenance'); ?><br /><br />
510
-
511
- <?php
512
-
513
- if( $paramSlider!==null ) {
514
-
515
- if( $paramSlider['slider_image'] ) {
516
- $lastKeySlide = key($paramSlider['slider_image']); $countSlide = ( $lastKeySlide + 1 );
517
- } else {
518
- $countSlide = 1;
519
- }
520
-
521
- ?>
522
- <div style="margin-bottom:15px;width:70%;">
523
- <div style="width:30%;float:left;">
524
- <?php _e('Speed:', 'wp-maintenance'); ?> <input type="text" name="wp_maintenance_slider_options[slider_speed]" size="4" value="<?php if( isset($paramSliderOptions['slider_speed']) && $paramSliderOptions['slider_speed'] !='') { echo $paramSliderOptions['slider_speed']; } else { echo 500; } ?>" />ms<br />
525
- <?php _e('Width:', 'wp-maintenance'); ?> <input type="text" name="wp_maintenance_slider_options[slider_width]" size="3" value="<?php if( isset($paramSliderOptions['slider_width']) && $paramSliderOptions['slider_width'] !='') { echo $paramSliderOptions['slider_width']; } else { echo 50; } ?>" />%
526
- </div>
527
- <div style="width:30%;float:left;padding-left:5px;">
528
- <?php _e('Display Auto Slider:', 'wp-maintenance'); ?><br />
529
- <input type= "radio" name="wp_maintenance_slider_options[slider_auto]" value="true" <?php if( (isset($paramSliderOptions['slider_auto']) && $paramSliderOptions['slider_auto'] == 'true') || empty($paramSliderOptions['slider_auto']) ) { echo "checked"; } ?>>&nbsp;<?php _e('Yes', 'wp-maintenance'); ?>&nbsp;&nbsp;&nbsp;
530
- <input type= "radio" name="wp_maintenance_slider_options[slider_auto]" value="false" <?php if( isset($paramSliderOptions['slider_auto']) && $paramSliderOptions['slider_auto'] == 'false' ) { echo "checked"; } ?>>&nbsp;<?php _e('No', 'wp-maintenance'); ?><br />
531
-
532
- <?php _e('Display button navigation:', 'wp-maintenance'); ?><br />
533
- <input type= "radio" name="wp_maintenance_slider_options[slider_nav]" value="true" <?php if( (isset($paramSliderOptions['slider_nav']) && $paramSliderOptions['slider_nav'] == 'true') || empty($paramSliderOptions['slider_nav']) ) { echo "checked"; } ?>>&nbsp;<?php _e('Yes', 'wp-maintenance'); ?>&nbsp;&nbsp;&nbsp;
534
- <input type= "radio" name="wp_maintenance_slider_options[slider_nav]" value="false" <?php if( isset($paramSliderOptions['slider_nav']) && $paramSliderOptions['slider_nav'] == 'false' ) { echo "checked"; } ?>>&nbsp;<?php _e('No', 'wp-maintenance'); ?>
535
- </div>
536
- <div style="width:30%;float:left;padding-left:5px;">
537
- <?php _e('Position:', 'wp-maintenance'); ?>
538
- <select name="wp_maintenance_slider_options[slider_position]">
539
- <option value="abovelogo" <?php if( isset($paramSliderOptions['slider_position']) && $paramSliderOptions['slider_position']=='abovelogo' ) { echo 'selected'; } ?></option><?php _e('Above logo', 'wp-maintenance'); ?></option>
540
- <option value="belowlogo" <?php if( isset($paramSliderOptions['slider_position']) && $paramSliderOptions['slider_position']=='belowlogo' ) { echo 'selected'; } ?>><?php _e('Below logo', 'wp-maintenance'); ?></option>
541
- <option value="belowtext" <?php if( ( isset($paramSliderOptions['slider_position']) && $paramSliderOptions['slider_position']=='belowtext' ) || empty($paramSliderOptions['slider_position']) ) { echo 'selected'; } ?>><?php _e('Below title & text', 'wp-maintenance'); ?></option>
542
- </select>
543
- </div>
544
- <div class="clear"></div>
545
- </div>
546
-
547
- <input id="upload_slider_image" size="36" name="wp_maintenance_slider[slider_image][<?php echo $countSlide; ?>][image]" value="" type="text" /> <a href="#" id="upload_slider_image_button" class="button" OnClick="this.blur();"><span> <?php _e('Select or Upload your picture', 'wp-maintenance'); ?> </span></a><br /><br />
548
-
549
- <div style="width:100%">
550
- <?php
551
- if( !empty($paramSlider['slider_image']) ) {
552
- foreach($paramSlider['slider_image'] as $numSlide=>$slide) {
553
-
554
- if( $paramSlider['slider_image'][$numSlide]['image'] != '' ) {
555
-
556
- $slideImg = '';
557
- if( isset($paramSlider['slider_image'][$numSlide]['image']) ) {
558
- $slideImg = $paramSlider['slider_image'][$numSlide]['image'];
559
- }
560
- $slideText = '';
561
- if( isset($paramSlider['slider_image'][$numSlide]['text']) ) {
562
- $slideText = stripslashes($paramSlider['slider_image'][$numSlide]['text']);
563
- }
564
- $slideLink = '';
565
- if( isset($paramSlider['slider_image'][$numSlide]['link']) ) {
566
- $slideLink = $paramSlider['slider_image'][$numSlide]['link'];
567
- }
568
- echo '<div style="float:left;width:45%;border: 1px solid #ececec;padding:0.8em;margin-right:1%;margin-bottom:1%">';
569
-
570
- echo '<div style="float:left;margin-right:0.8em;">';
571
- echo '<img src="'.$slideImg.'" width="200" />';
572
- echo '</div>';
573
-
574
- echo '<div style="float:left;">';
575
- echo '<input type="hidden" name="wp_maintenance_slider[slider_image]['.$numSlide.'][image]" value="'.$slideImg.'" />';
576
- echo __('Text:', 'wp-maintenance').'<br /> <input type="text" name="wp_maintenance_slider[slider_image]['.$numSlide.'][text]" value="'.$slideText.'" /><br />';
577
- echo __('Link:', 'wp-maintenance').'<br /> <input type="text" name="wp_maintenance_slider[slider_image]['.$numSlide.'][link]" value="'.$slideLink.'" />';
578
- echo '</div>';
579
- echo '<div class="clear"></div>';
580
- echo '<div style="text-align:right;"><input type="checkbox" name="wpm_maintenance_detete['.$numSlide.']" value="true" /><small>'.__('Delete this slide', 'wp-maintenance').'</small></div>';
581
- echo '</div>';
582
-
583
- }
584
-
585
- }
586
- }
587
-
588
- ?>
589
- </div>
590
- <div class="clear"></div>
591
- <?php } ?>
592
- </li>
593
-
594
- <li>
595
- <p>
596
- <?php submit_button(); ?>
597
- </p>
598
- </li>
599
-
600
- </ul>
601
- </div>
602
- </div>
603
- <!-- fin options 3 -->
604
-
605
- <!-- Onglet options 4 -->
606
- <div class="wpm-menu-compte wpm-menu-group" style="display: none;">
607
- <div id="wpm-opt-compte" >
608
- <ul>
609
- <!-- ACTIVER COMPTEUR -->
610
- <?php
611
-
612
- // Old version compte à rebours
613
- if( isset($paramMMode['date_cpt_jj']) && empty($paramMMode['cptdate']) ) {
614
- $paramMMode['cptdate'] = $paramMMode['date_cpt_aa'].'/'.$paramMMode['date_cpt_mm'].'/'.$paramMMode['date_cpt_jj'];
615
- } else if ( empty($paramMMode['cptdate']) ) {
616
- $paramMMode['cptdate'] = date('d').'/'.date('m').'/'.date('Y');
617
- }
618
-
619
- if( isset($paramMMode['date_cpt_hh']) && empty($paramMMode['cpttime']) ) {
620
- $paramMMode['cpttime'] = $paramMMode['date_cpt_hh'].':'.$paramMMode['date_cpt_mn'];
621
- } else if ( empty($paramMMode['cpttime']) ) {
622
- $paramMMode['cpttime'] = date( 'H:i', (time()+3600) );
623
- }
624
-
625
- ?>
626
- <li><h3><?php _e('Enable a countdown ?', 'wp-maintenance'); ?></h3>
627
- <input type= "checkbox" name="wp_maintenance_settings[active_cpt]" value="1" <?php if( isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==1 ) { echo ' checked'; } ?>>&nbsp;<?php _e('Yes', 'wp-maintenance'); ?><br /><br />
628
- <?php
629
- if( isset($paramMMode['cptdate']) && !empty($paramMMode['cptdate']) ) {
630
- $startDate = $paramMMode['cptdate'];
631
- }
632
- if( isset($paramMMode['cpttime']) && !empty($paramMMode['cpttime']) ) {
633
- $startHour = $paramMMode['cpttime'];
634
- }
635
- if( (isset($paramMMode['active_cpt']) && $paramMMode['active_cpt']==0) || empty($paramMMode['active_cpt']) ) {
636
- $startDate = date_i18n( date("Y").'/'.date("m").'/'.date("d") );
637
- $timeFormats = array_unique( apply_filters( 'time_formats', array( 'H:i' ) ) );
638
- foreach ( $timeFormats as $format ) {
639
- $startHour = date_i18n( $format );
640
- }
641
- $newMin = explode(':', $startHour);
642
- $startHour = $newMin[0].':'.ceil($newMin[1]/5)*5;
643
- }
644
- ?>
645
- <small><?php _e('Select the launch date/time', 'wp-maintenance'); ?></small><br /><img src="<?php echo WP_PLUGIN_URL.'/wp-maintenance/images/schedule_clock.png'; ?>" class="datepicker" width="48" height="48" style="vertical-align: middle;margin-right:5px;">&nbsp;<input id="cptdate" class="datepicker" name="wp_maintenance_settings[cptdate]" type="text" autofocuss data-value="<?php echo $startDate; ?>"> à <input id="cpttime" class="timepicker" type="time" name="wp_maintenance_settings[cpttime]" value="<?php echo $startHour; ?>" size="4" autofocuss>
646
- <div id="wpmdatecontainer"></div>
647
- <br /><br />
648
- <input type= "checkbox" name="wp_maintenance_settings[active_cpt_s]" value="1" <?php if( isset($paramMMode['active_cpt_s']) && $paramMMode['active_cpt_s']==1) { echo ' checked'; } ?>>&nbsp;<?php _e('Enable seconds ?', 'wp-maintenance'); ?><br /><br />
649
- <input type= "checkbox" name="wp_maintenance_settings[disable]" value="1" <?php if( isset($paramMMode['disable']) && $paramMMode['disable']==1) { echo ' checked'; } ?>>&nbsp;<?php _e('Disable maintenance mode at the end of the countdown?', 'wp-maintenance'); ?><br /><br />
650
- <?php _e('End message:', 'wp-maintenance'); ?><br /><TEXTAREA NAME="wp_maintenance_settings[message_cpt_fin]" COLS=70 ROWS=4><?php echo stripslashes($paramMMode['message_cpt_fin']); ?></TEXTAREA><br />
651
-
652
- <script type="text/javascript">
653
-
654
- jQuery(document).ready(function() {
655
-
656
- var $input = jQuery( '.datepicker' ).pickadate({
657
- formatSubmit: 'yyyy/mm/dd',
658
- container: '#wpmdatecontainer',
659
- closeOnSelect: true,
660
- closeOnClear: false,
661
- firstDay: 1,
662
- min: new Date(<?php echo date('Y').','.(date('m')-1).','.date('d'); ?>),
663
- monthsFull: [ 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre' ],
664
- monthsShort: [ 'Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Juin', 'Juil', 'Aou', 'Sep', 'Oct', 'Nov', 'Dec' ],
665
- weekdaysShort: [ 'Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam' ],
666
- today: "<?php _e('Today', 'wp-maintenance'); ?>",
667
- clear: '<?php _e('Delete', 'wp-maintenance'); ?>',
668
- close: '<?php _e('Close', 'wp-maintenance'); ?>',
669
-
670
- // Accessibility labels
671
- labelMonthNext: '<?php _e('Next month', 'wp-maintenance'); ?>',
672
- labelMonthPrev: '<?php _e('Previous month', 'wp-maintenance'); ?>',
673
- labelMonthSelect: '<?php _e('Select a month', 'wp-maintenance'); ?>',
674
- labelYearSelect: '<?php _e('Select a year', 'wp-maintenance'); ?>',
675
-
676
- selectMonths: true,
677
- selectYears: true,
678
-
679
-
680
- })
681
-
682
- var picker = $input.pickadate('picker')
683
-
684
-
685
- var $input = jQuery( '.timepicker' ).pickatime({
686
- //container: '#wpmtimecontainer',
687
- clear: '<?php _e('Close', 'wp-maintenance'); ?>',
688
- interval: 5,
689
- editable: undefined,
690
- format: 'HH:i', // retour ce format dans le input
691
- formatSubmit: 'HH:i', // return ce format en post
692
- formatLabel: '<b>HH</b>:i', // Affichage
693
-
694
- })
695
- var picker = $input.pickatime('picker')
696
-
697
- });
698
-
699
- </script>
700
- </li>
701
- <li>&nbsp;</li>
702
- <li>
703
- <p>
704
- <?php submit_button(); ?>
705
- </p>
706
- </li>
707
- </ul>
708
- </div>
709
- </div>
710
- <!-- fin options 4 -->
711
-
712
- <!-- Onglet options 5 -->
713
- <div class="wpm-menu-styles wpm-menu-group" style="display: none;">
714
- <div id="wpm-opt-styles" >
715
- <ul>
716
- <!-- UTILISER UNE FEUILLE DE STYLE PERSO -->
717
- <li><h3><?php _e('CSS style sheet code:', 'wp-maintenance'); ?></h3>
718
- <?php _e('Edit the CSS sheet of your maintenance page here. Click "Reset" and "Save" to retrieve the default style sheet.', 'wp-maintenance'); ?><br /><br />
719
- <div style="float:left;width:55%;margin-right:15px;">
720
- <TEXTAREA NAME="wp_maintenance_style" COLS=70 ROWS=24 style="width:100%;"><?php echo stripslashes(trim(get_option('wp_maintenance_style'))); ?></TEXTAREA>
721
- </div>
722
- <div style="float:left;position:relative;width:40%;">
723
- <table class="wp-list-table widefat fixed" cellspacing="0">
724
- <tbody id="the-list">
725
- <tr>
726
- <td><h3 class="hndle"><span><strong><?php _e('Markers for colors', 'wp-maintenance'); ?></strong></span></h3></td>
727
- <td></td>
728
- </tr>
729
- <tr>
730
- <td>#_COLORTXT</td>
731
- <td><?php _e('Use this code for text color', 'wp-maintenance'); ?></td>
732
- </tr>
733
- <tr>
734
- <td>#_COLORBG</td>
735
- <td><?php _e('Use this code for background text color', 'wp-maintenance'); ?></td>
736
- </tr>
737
- <tr>
738
- <td>#_COLORCPTBG</td>
739
- <td><?php _e('Use this code for background color countdown', 'wp-maintenance'); ?></td>
740
- </tr>
741
- <tr>
742
- <td>#_DATESIZE</td>
743
- <td><?php _e('Use this code for size countdown', 'wp-maintenance'); ?></td>
744
- </tr>
745
- <tr>
746
- <td>#_COLORCPT</td>
747
- <td><?php _e('Use this code for countdown color', 'wp-maintenance'); ?></td>
748
- </tr>
749
- </tbody>
750
- </table>
751
- <br />
752
- <a href="" onclick="AfficherCacher('divcss'); return false" ><?php _e('Need CSS code for MailPoet plugin?', 'wp-maintenance'); ?></a>
753
- <div id="divcss" style="display:none;"><i><?php _e('Click for select all', 'wp-maintenance'); ?></i>
754
- <textarea onclick="select()" rows="15" cols="50%">
755
- .abs-req { display: none; }
756
- .widget_wysija_cont .wysija-submit { }
757
- .widget_wysija input { }
758
- .wysija-submit-field { }
759
- .wysija-submit-field:hover { }
760
- .widget_wysija input:focus { }
761
- .wysija-submit-field:active { }
762
- .widget_wysija .wysija-submit, .widget_wysija .wysija-paragraph { }
763
- .wysija-submit-field { }
764
- </textarea>
765
- </div>
766
- <br />
767
- <a href="" onclick="AfficherCacher('divcss2'); return false" ><?php _e('Need CSS code for MailChimp plugin?', 'wp-maintenance'); ?></a>
768
- <div id="divcss2" style="display:none;"><i><?php _e('Click for select all', 'wp-maintenance'); ?></i>
769
- <textarea onclick="select()" rows="15" cols="50%">
770
- .mc4wp-form { } /* the form element */
771
- .mc4wp-form p { } /* form paragraphs */
772
- .mc4wp-form label { } /* labels */
773
- .mc4wp-form input { } /* input fields */
774
- .mc4wp-form input[type="checkbox"] { } /* checkboxes */
775
- .mc4wp-form input[type="submit"] { } /* submit button */
776
- .mc4wp-form input[type="submit"]:hover { }
777
- .mc4wp-form input[type="submit"]:active { }
778
- .mc4wp-alert { } /* success & error messages */
779
- .mc4wp-success { } /* success message */
780
- .mc4wp-error { } /* error messages */
781
- </textarea>
782
- </div>
783
- </div>
784
-
785
- <div class="clear"></div>
786
- <br />
787
- </li>
788
- <li>
789
- <input type= "checkbox" name="wpm_initcss" value="1" id="initcss" >&nbsp;<label for="wpm_initcss"><?php _e('Reset default CSS stylesheet ?', 'wp-maintenance'); ?></label><br />
790
- </li>
791
- <li>&nbsp;</li>
792
-
793
- <li>
794
- <p>
795
- <?php submit_button(); ?>
796
- </p>
797
- </li>
798
- </ul>
799
- </div>
800
- </div>
801
- <!-- fin options 5 -->
802
-
803
- <!-- Onglet options 6 -->
804
- <div class="wpm-menu-options wpm-menu-group" style="display: none;">
805
- <div id="wpm-opt-options" >
806
- <ul>
807
- <!-- UTILISER UNE PAGE MAINTENANCE.PHP -->
808
- <li><h3><?php _e('Theme maintenance page:', 'wp-maintenance'); ?></h3>
809
- <?php _e('If you would use your maintenance.php page in your theme folder, click Yes.', 'wp-maintenance'); ?>&nbsp;<br /><br />
810
- <input type= "radio" name="wp_maintenance_settings[pageperso]" value="1" <?php if($paramMMode['pageperso']==1) { echo ' checked'; } ?>>&nbsp;<?php _e('Yes', 'wp-maintenance'); ?>&nbsp;&nbsp;&nbsp;
811
- <input type= "radio" name="wp_maintenance_settings[pageperso]" value="0" <?php if(!$paramMMode['pageperso'] or $paramMMode['pageperso']==0) { echo ' checked'; } ?>>&nbsp;<?php _e('No', 'wp-maintenance'); ?><br /><br />
812
- <?php _e('You can use this shortcode to include Google Analytics code:', 'wp-maintenance'); ?> <input type="text" value="do_shortcode('[wpm_analytics']);" onclick="select()" style="width:250px;" /><br /><?php _e('You can use this shortcode to include Social Networks icons:', 'wp-maintenance'); ?> <input type="text" value="do_shortcode('[wpm_social]');" onclick="select()" style="width:250px;" /><br />
813
- </li>
814
- <li>&nbsp;</li>
815
-
816
- <?php
817
- /* Secure for demo mode */
818
- if ( current_user_can( 'manage_options' ) ) {
819
- ?>
820
- <li>
821
- <h3><?php _e('Roles and Capabilities:', 'wp-maintenance'); ?></h3>
822
- <?php _e('Allow the site to display these roles:', 'wp-maintenance'); ?>&nbsp;<br /><br />
823
- <input type="hidden" name="wp_maintenance_limit[administrator]" value="administrator" />
824
- <?php
825
- $roles = wpm_get_roles();
826
- foreach($roles as $role=>$name) {
827
- $limitCheck = '';
828
- if( isset($paramLimit[$role]) && $paramLimit[$role]==$role) { $limitCheck = ' checked'; }
829
- if( $role=='administrator') {
830
- $limitCheck = 'checked disabled="disabled"';
831
- }
832
- ?>
833
- <input type="checkbox" name="wp_maintenance_limit[<?php echo $role; ?>]" value="<?php echo $role; ?>"<?php echo $limitCheck; ?> /><?php echo $name; ?>&nbsp;
834
- <?php }//end foreach ?>
835
- </li>
836
- <li>&nbsp;</li>
837
-
838
- <li>
839
- <h3><?php _e('IP autorized:', 'wp-maintenance'); ?></h3>
840
- <?php _e('Allow the site to display these IP addresses. Please, enter one IP address by line:', 'wp-maintenance'); ?>&nbsp;<br /><br />
841
- <textarea name="wp_maintenance_ipaddresses" ROWS="5" style="width:80%;"><?php if( isset($paramIpAddress) ) { echo $paramIpAddress; } ?></textarea>
842
- </li>
843
- <li>&nbsp;</li>
844
-
845
- <li>
846
- <h3><?php _e('ID pages autorized:', 'wp-maintenance'); ?></h3>
847
- <?php _e('Allow the site to display these ID pages. Please, enter the ID pages separate with comma :', 'wp-maintenance'); ?>&nbsp;<br /><br />
848
- <input name="wp_maintenance_settings[id_pages]" size="70" value="<?php if( isset($paramMMode['id_pages']) ) { echo $paramMMode['id_pages']; } ?>" />
849
- </li>
850
- <li>&nbsp;</li>
851
-
852
- <li><h3><?php _e('Header Code:', 'wp-maintenance'); ?></h3>
853
- <?php _e('The following code will add to the <head> tag. Useful if you need to add additional scripts such as CSS or JS.', 'wp-maintenance'); ?>&nbsp;<br /><br />
854
- <TEXTAREA NAME="wp_maintenance_settings[headercode]" COLS=70 ROWS=14 style="width:80%;"><?php if( isset($paramMMode['headercode']) ) { echo stripslashes($paramMMode['headercode']); } ?></TEXTAREA>
855
- </li>
856
- <li>&nbsp;</li>
857
-
858
- <!--<li><h3><?php //_e('Demo mode:', 'wp-maintenance'); ?></h3>
859
- <p><?php //_e('Be careful, in demo mode, the plugin can be modified by all users', 'wp-maintenance'); ?></p>
860
- <input type= "checkbox" name="wp_maintenance_settings[enable_demo]" value="1" <?php //if($paramMMode['enable_demo']==1) { echo ' checked'; } ?>> <?php //_e('Active this plugin in demo mode?', 'wp-maintenance'); ?>&nbsp;<br />
861
-
862
- </li>
863
- <li>&nbsp;</li>-->
864
- <?php } // End secure for demo mode ?>
865
-
866
- <li>
867
- <p>
868
- <?php submit_button(); ?>
869
- </p>
870
- </li>
871
-
872
- </ul>
873
- </div>
874
- </div>
875
- <!-- fin options 6 -->
876
-
877
- </form>
878
-
879
- <!-- Onglet options 7 -->
880
- <div class="wpm-menu-apropos wpm-menu-group" style="display: none;">
881
- <div id="wpm-opt-apropos" >
882
- <ul>
883
-
884
- <li>
885
- <?php _e('This plugin has been developed for you for free by <a href="https://restezconnectes.fr" target="_blank">Florent Maillefaud</a>. It is royalty free, you can take it, modify it, distribute it as you see fit.<br /><br />It would be desirable that I can get feedback on your potential changes to improve this plugin for all.', 'wp-maintenance'); ?>
886
- </li>
887
- <li>&nbsp;</li>
888
- <li>
889
- <?php _e('Visit', 'wp-maintenance'); ?> <a href="https://wpmaintenance.info" target="_blank">WP Maintenance</a>, <?php _e('try the demo of the plugin, talk about this plugin to your surroundings!', 'wp-maintenance'); ?>
890
- </li>
891
- <li>&nbsp;</li>
892
- <li>
893
- <!-- FAIRE UN DON SUR PAYPAL -->
894
- <div><?php _e('If you want Donate (French Paypal) for my current and future developments:', 'wp-maintenance'); ?><br /><br />
895
- <div style="width:350px;margin-left:auto;margin-right:auto;padding:5px;">
896
- <a href="https://paypal.me/RestezConnectes/10" target="_blank" class="wpmclassname">
897
- <img src="<?php echo WP_PLUGIN_URL.'/wp-maintenance/images/donate.png'; ?>" valign="bottom" width="64" /> Donate now!
898
- </a>
899
- </div>
900
- </div>
901
- <!-- FIN FAIRE UN DON -->
902
- </li>
903
- <li>&nbsp;</li>
904
- </ul>
905
- </div>
906
- </div>
907
- <!-- fin options 7 -->
908
-
909
- </div><!-- -->
910
-
911
- <div style="margin-top:40px;">
912
-
913
- <a href="https://wpmaintenance.info/" target="_blank"><?php _e('WP Maintenance','wp-maintenance'); ?></a> <?php _e('is brought to you by','wp-maintenance'); ?> <a href="https://restezconnectes.fr/" target="_blank">Restez Connectés</a> - <?php _e('If you found this plugin useful','wp-maintenance'); ?> <a href="https://wordpress.org/support/view/plugin-reviews/wp-maintenance" target="_blank"><?php _e('give it 5 &#9733; on WordPress.org','wp-maintenance'); ?></a>
914
-
915
- </div>
916
-
917
- </div><!-- wrap -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wp-maintenance.php CHANGED
@@ -1,12 +1,11 @@
1
  <?php
2
-
3
  /*
4
  * Plugin Name: WP Maintenance
5
  * Plugin URI: https://fr.wordpress.org/plugins/wp-maintenance/
6
- * Description: Le plugin WP Maintenance vous permet de mettre votre site en attente le temps pour vous de faire une maintenance ou du lancement de votre site. Personnalisez cette page de maintenance avec une image, un compte à rebours, etc... / The WP Maintenance plugin allows you to put your website on the waiting time for you to do maintenance or launch your website. Personalize this page with picture, countdown...
7
  * Author: Florent Maillefaud
8
  * Author URI: https://wpmaintenance.info
9
- * Version: 2.8.4
10
  * Text Domain: wp-maintenance
11
  * Domain Path: /languages/
12
  */
@@ -28,1081 +27,37 @@
28
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
  */
30
 
31
-
32
  defined( 'ABSPATH' )
33
  or die( 'No direct load ! ' );
34
 
35
- if(!defined('WP_CONTENT_URL')) { define('WP_CONTENT_URL', get_option( 'siteurl') . '/wp-content'); }
36
- if(!defined('WP_CONTENT_DIR')) { define('WP_CONTENT_DIR', ABSPATH . 'wp-content'); }
37
- if(!defined('WP_PLUGIN_URL')) { define('WP_PLUGIN_URL', WP_CONTENT_URL.'/plugins'); }
38
- if(!defined('WP_PLUGIN_DIR')) { define('WP_PLUGIN_DIR', WP_CONTENT_DIR.'/plugins'); }
39
- if(!defined( 'WPM_BASENAME')) { define( 'WPM_BASENAME', plugin_basename(__FILE__) ); }
40
-
41
- /* Ajout réglages au plugin */
42
- $wpmaintenance_dashboard = ( is_admin() ) ? 'options-general.php?page=wp-maintenance/wp-maintenance.php' : '';
43
- define( 'WPM_SETTINGS', $wpmaintenance_dashboard);
44
-
45
- include("uninstall.php");
46
- include("wpm_fonctions.php");
47
-
48
- // Add "Réglages" link on plugins page
49
- add_filter( 'plugin_action_links_' . WPM_BASENAME, 'wpm_plugin_actions' );
50
- function wpm_plugin_actions ( $links ) {
51
- $settings_link = '<a href="'.WPM_SETTINGS.'">'.__('Settings', 'wp-maintenance').'</a>';
52
- array_unshift ( $links, $settings_link );
53
- return $links;
54
- }
55
-
56
- /* DATEPICKER */
57
- add_action( 'init', 'wpm_date_picker' );
58
- function wpm_date_picker() {
59
- if (isset($_GET['page']) && $_GET['page'] == 'wp-maintenance') {
60
- wp_enqueue_script( 'jquery' );
61
- wp_enqueue_script('jquery-ui-datepicker');
62
- wp_enqueue_style('jquery-style', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');
63
- }
64
-
65
- }
66
-
67
- // multilingue
68
- add_action( 'init', 'wpm_make_multilang' );
69
- function wpm_make_multilang() {
70
- load_plugin_textdomain('wp-maintenance', false, dirname( plugin_basename( __FILE__ ) ).'/languages');
71
- }
72
-
73
- /* Ajoute la version dans les options */
74
- define('WPM_VERSION', '2.8.4');
75
- $option['wp_maintenance_version'] = WPM_VERSION;
76
- if( !get_option('wp_maintenance_version') ) {
77
- add_option('wp_maintenance_version', $option);
78
- } else if ( get_option('wp_maintenance_version') != WPM_VERSION ) {
79
- update_option('wp_maintenance_version', WPM_VERSION);
80
- }
81
-
82
- //récupère le formulaire d'administration du plugin
83
- function wpm_admin_panel() {
84
- include("wp-maintenance-admin.php");
85
- }
86
-
87
- /* Ajout feuille CSS pour l'admin barre */
88
- function wpm_admin_head() {
89
- echo '<link rel="stylesheet" type="text/css" media="all" href="' .plugins_url('css/wpm-admin.css', __FILE__). '">';
90
- }
91
- add_action('admin_head', 'wpm_admin_head');
92
-
93
- /* Ajout Notification admin barre */
94
- add_action( 'admin_bar_menu', 'wpm_add_menu_admin_bar', 999 );
95
- function wpm_add_menu_admin_bar( $wp_admin_bar ) {
96
-
97
- $checkActive = get_option('wp_maintenance_active');
98
- if( isset($checkActive) && $checkActive==1 && !is_network_admin() ) {
99
- $textAdmin = '<img src="'.WP_PLUGIN_URL.'/wp-maintenance/images/lock.png" style="padding: 6px 0;float:left;margin-right: 6px;">'.__('Maintenance mode activated!', 'wp-maintenance');
100
- $args = array(
101
- 'id' => 'wpm-info', // id of the existing child node (New > Post)
102
- 'title' => $textAdmin, // alter the title of existing node
103
- 'href' => WPM_SETTINGS, // Lien du menu
104
- 'parent' => false, // set parent to false to make it a top level (parent) node
105
- 'meta' => array(
106
- 'class' => 'wpmbackground'
107
- )
108
- );
109
- $wp_admin_bar->add_node( $args );
110
- }
111
- }
112
-
113
- /* Liste les différents Rôles */
114
- function wpm_get_roles() {
115
-
116
- $wp_roles = new WP_Roles();
117
- $roles = $wp_roles->get_names();
118
- $roles = array_map( 'translate_user_role', $roles );
119
-
120
- return $roles;
121
- }
122
-
123
- /* Retourne la vraie adresse IP */
124
- function wpm_get_ip() {
125
- return (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
126
- }
127
-
128
- function wpm_add_admin() {
129
-
130
- $wp_maintenanceAdminOptions = array(
131
- 'enable' => 0,
132
- 'color_bg' => "#f1f1f1",
133
- 'color_txt' => '#888888',
134
- 'color_bg_bottom' => '#333333',
135
- 'color_text_bottom' => '#FFFFFF',
136
- 'titre_maintenance' => __('This site is down for maintenance', 'wp-maintenance'),
137
- 'text_maintenance' => __('Come back quickly !', 'wp-maintenance'),
138
- 'userlimit' => 'administrator',
139
- 'image' => WP_PLUGIN_URL.'/wp-maintenance/images/default.png',
140
- 'font_title' => 'Pacifico',
141
- 'font_title_size' => 40,
142
- 'font_title_weigth' => 'normal',
143
- 'font_title_style' => '',
144
- 'font_text_style' => '',
145
- 'font_text' => 'Metrophobic',
146
- 'font_text_size' => 18,
147
- 'font_text_bottom' => 'Pacifico',
148
- 'font_text_weigth' => 'normal',
149
- 'font_bottom_size' => 12,
150
- 'font_bottom_weigth' => 'normal',
151
- 'font_bottom_style' => '',
152
- 'font_cpt' => 'Pacifico',
153
- 'color_cpt' => '#333333',
154
- 'enable_demo' => 0,
155
- 'color_field_text' => '#333333',
156
- 'color_text_button' => '#ffffff',
157
- 'color_field_background' => '#F1F1F1',
158
- 'color_field_border' => '#333333',
159
- 'color_button_onclick' => '#333333',
160
- 'color_button_hover' => '#cccccc',
161
- 'color_button' => '#1e73be',
162
- 'image_width' => 250,
163
- 'image_height' => 100,
164
- 'newletter' => 0,
165
- 'active_cpt' => 0,
166
- 'newletter_font_text' => 'Pacifico',
167
- 'newletter_size' => 18,
168
- 'newletter_font_style' => '',
169
- 'newletter_font_weigth' => 'normal',
170
- 'type_newletter' => 'shortcode',
171
- 'title_newletter' => '',
172
- 'code_newletter' => '',
173
- 'code_analytics' => '',
174
- 'domain_analytics' => $_SERVER['SERVER_NAME'],
175
- 'text_bt_maintenance' => '',
176
- 'add_wplogin' => '',
177
- 'b_enable_image' => 0,
178
- 'disable' => 0,
179
- 'pageperso' => 0,
180
- 'date_cpt_size' => 40,
181
- 'color_bg_header' => '#f1f1f1',
182
- 'add_wplogin_title' => '',
183
- 'headercode' => '',
184
- 'message_cpt_fin' => '',
185
- 'b_repeat_image' => '',
186
- 'color_cpt_bg' => '',
187
- 'enable_slider' => 0,
188
- 'container_active' => 0,
189
- 'container_color' => '#ffffff',
190
- 'container_opacity' => '0.5',
191
- 'container_width' => 80
192
-
193
- );
194
- $getMaintenanceSettings = get_option('wp_maintenance_settings');
195
- if (!empty($getMaintenanceSettings)) {
196
- foreach ($getMaintenanceSettings as $key => $option) {
197
- $wp_maintenanceAdminOptions[$key] = $option;
198
- }
199
- }
200
- update_option('wp_maintenance_settings', $wp_maintenanceAdminOptions);
201
- if(!get_option('wp_maintenance_active')) { update_option('wp_maintenance_active', 0); }
202
-
203
- if(!get_option('wp_maintenance_style') or get_option('wp_maintenance_style')=='') {
204
- update_option('wp_maintenance_style', wpm_print_style());
205
- }
206
-
207
- $getMaintenanceSettings = extract(get_option('wp_maintenance_settings'));
208
- if( $getMaintenanceSettings['enable_demo']==1 ) {
209
- $hook = add_options_page(__( 'Options for the maintenance page', 'wp-maintenance' ), "WP Maintenance", 'read', __FILE__, "wpm_admin_panel");
210
- } else {
211
- $hook = add_options_page(__( 'Options for the maintenance page', 'wp-maintenance' ), "WP Maintenance", 'manage_options', __FILE__, "wpm_admin_panel");
212
- }
213
-
214
- }
215
- /* recupere le protocole */
216
- function wpm_protocole() {
217
- return $_SERVER['HTTPS'];
218
- }
219
-
220
- function wpm_admin_scripts() {
221
-
222
- wp_enqueue_script('media-upload');
223
- wp_enqueue_script('thickbox');
224
-
225
- wp_register_script('wpm-my-upload', WP_PLUGIN_URL.'/wp-maintenance/js/wpm-script.js', array('jquery','media-upload','thickbox'));
226
- wp_enqueue_script('wpm-my-upload');
227
-
228
- wp_enqueue_style('jquery-defaut-style', WP_PLUGIN_URL.'/wp-maintenance/js/lib/themes/default.css');
229
- wp_enqueue_style('jquery-date-style', WP_PLUGIN_URL.'/wp-maintenance/js/lib/themes/default.date.css');
230
- wp_enqueue_style('jquery-time-style', WP_PLUGIN_URL.'/wp-maintenance/js/lib/themes/default.time.css');
231
- wp_enqueue_style('jquery-fontselect-style', WP_PLUGIN_URL.'/wp-maintenance/js/fontselect/fontselect.css');
232
- // If you're not including an image upload then you can leave this function call out
233
- wp_enqueue_media();
234
-
235
- // Now we can localize the script with our data.
236
- wp_localize_script( 'wpm-my-upload', 'Data', array(
237
- 'textebutton' => __( 'Choose This Image', 'wp-maintenance' ),
238
- 'title' => __( 'Choose Image', 'wp-maintenance' ),
239
- ) );
240
-
241
- wp_register_script('wpm-admin-fontselect', WP_PLUGIN_URL.'/wp-maintenance/js/fontselect/jquery.fontselect.min.js');
242
- wp_enqueue_script('wpm-admin-fontselect');
243
-
244
- //if( wpm_protocole()=='' ) {
245
- wp_register_script('wpm-admin-settings', WP_PLUGIN_URL.'/wp-maintenance/js/wpm-admin-settings.js');
246
- wp_enqueue_script('wpm-admin-settings');
247
- //}
248
- }
249
-
250
- //}
251
- function wpm_print_footer_scripts() {
252
- wp_register_script('wpm-picker', WP_PLUGIN_URL.'/wp-maintenance/js/lib/picker.js');
253
- wp_enqueue_script('wpm-picker');
254
- wp_register_script('wpm-datepicker', WP_PLUGIN_URL.'/wp-maintenance/js/lib/picker.date.js');
255
- wp_enqueue_script('wpm-datepicker');
256
- wp_register_script('wpm-timepicker', WP_PLUGIN_URL.'/wp-maintenance/js/lib/picker.time.js');
257
- wp_enqueue_script('wpm-timepicker');
258
- wp_register_script('wpm-legacy', WP_PLUGIN_URL.'/wp-maintenance/js/lib/legacy.js');
259
- wp_enqueue_script('wpm-legacy');
260
- }
261
-
262
- add_action( 'admin_enqueue_scripts', 'wpm_enqueue_color_picker' );
263
- function wpm_enqueue_color_picker( $hook_suffix ) {
264
- // first check that $hook_suffix is appropriate for your admin page
265
- wp_enqueue_style( 'wp-color-picker' );
266
- wp_enqueue_script( 'my-script-handle', plugins_url('js/wpm-color-options.js', __FILE__ ), array( 'wp-color-picker' ), false, true );
267
- }
268
-
269
- function wpm_admin_styles() {
270
- wp_enqueue_style('thickbox');
271
- wp_enqueue_style('jquery-style', 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/smoothness/jquery-ui.css');
272
- }
273
-
274
- if (isset($_GET['page']) && $_GET['page'] == 'wp-maintenance/wp-maintenance.php') {
275
- add_action('admin_footer', 'wpm_print_footer_scripts');
276
- add_action('admin_print_scripts', 'wpm_admin_scripts');
277
- add_action('admin_print_styles', 'wpm_admin_styles');
278
- add_action('admin_print_scripts', 'wpm_admin_scripts');
279
- }
280
-
281
- function wpm_change_active($value = 0) {
282
-
283
- update_option('wp_maintenance_active', $value);
284
- $statusActive = get_option('wp_maintenance_active');
285
- if( isset($statusActive) ) {
286
- return $statusActive;
287
- }
288
- }
289
-
290
- function wpm_array_value_count ($array) {
291
- $count = 0;
292
-
293
- foreach ($array as $key => $value)
294
- {
295
- if($value) { $count++; }
296
- }
297
-
298
- return $count;
299
- }
300
-
301
- function wpm_analytics_shortcode( $atts ) {
302
-
303
- if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
304
- $paramMMode = get_option('wp_maintenance_settings');
305
-
306
- // Attributes
307
- extract( shortcode_atts(
308
- array(
309
- 'enable' => 0,
310
- 'code' => $paramMMode['code_analytics'],
311
- 'domain' => ''.$_SERVER['SERVER_NAME'].''
312
- ), $atts )
313
- );
314
-
315
- if( isset($enable) && $enable==1 && $code!='') {
316
- return "<script>
317
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
318
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
319
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
320
- })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
321
-
322
- ga('create', '".$code."', '".$domain."');
323
- ga('send', 'pageview');
324
-
325
- </script>";
326
- } else {
327
- // Code
328
- return '';
329
- }
330
- }
331
- add_shortcode( 'wpm_analytics', 'wpm_analytics_shortcode' );
332
-
333
- function wpm_social_shortcode( $atts ) {
334
-
335
- if(get_option('wp_maintenance_social')) { extract(get_option('wp_maintenance_social')); }
336
- $paramSocial = get_option('wp_maintenance_social');
337
- $paramSocialOption = get_option('wp_maintenance_social_options');
338
- $countSocial = wpm_array_value_count($paramSocial);
339
- $contentSocial = '';
340
- // Si on est en mobile on réduit les icones
341
- if ( wp_is_mobile() ) {
342
- $paramSocialOption['size'] = 24;
343
- }
344
-
345
- // Attributes
346
- extract( shortcode_atts(
347
- array(
348
- 'size' => 48,
349
- 'enable' => 0
350
- ), $atts )
351
- );
352
- if($paramSocialOption['theme']!='') {
353
- $srcIcon = get_stylesheet_directory_uri().'/'.$paramSocialOption['theme'].'/';
354
- $iconSize = 'width='.$paramSocialOption['size'];
355
- } else {
356
- $srcIcon = WP_CONTENT_URL.'/plugins/wp-maintenance/socialicons/'.$paramSocialOption['size'].'x'.$paramSocialOption['size'].'/';
357
- $iconSize = '';
358
- }
359
- if( isset($paramSocialOption['enable']) && $paramSocialOption['enable']==1 && $countSocial>=1) {
360
- $contentSocial .= '<div id="wpm-social-footer" class="wpm_social"><ul class="wpm_horizontal">';
361
- foreach($paramSocial as $socialName=>$socialUrl) {
362
- if($socialUrl!='') {
363
- $contentSocial .= '<li><a href="'.$socialUrl.'" target="_blank"><img src="'.$srcIcon.$socialName.'.png" alt="'.$paramSocialOption['texte'].' '.ucfirst($socialName).'" '.$iconSize.' title="'.$paramSocialOption['texte'].' '.ucfirst($socialName).'" /></a></li>';
364
- }
365
- }
366
- $contentSocial .='</ul></div>';
367
- return $contentSocial;
368
- } else {
369
- // Code
370
- return '';
371
- }
372
- }
373
- add_shortcode( 'wpm_social', 'wpm_social_shortcode' );
374
-
375
- function wpm_get_template() {
376
-
377
- return '
378
- <!DOCTYPE html>
379
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
380
- <head>
381
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
382
- <meta name="viewport" content="width=device-width, user-scalable=yes" />
383
- <title>%TITLE%</title>
384
-
385
- <style type=\'text/css\'>
386
- /* VERSION %VERSION% */
387
- %ADDFONTS%
388
- html,
389
- body {
390
- margin:0;
391
- padding:0;
392
- height:100%;
393
- font-size:100%;
394
- }
395
- #wrapper {
396
- min-height:100%;
397
- position:relative;
398
- }
399
- #header {
400
- padding:10px;
401
- }
402
- #content {
403
- padding-bottom:100px; /* Height of the footer element */
404
- }
405
- #footer {
406
- width:100%;
407
- height:60px;
408
- line-height:60px;
409
- position:absolute;
410
- bottom:0;
411
- left:0;
412
- text-align: center;
413
- }
414
- #logo {
415
- max-width: 100%;
416
- height: auto;
417
- text-align: center;
418
- }
419
- img, object, embed, canvas, video, audio, picture {
420
- max-width: 100%;
421
- height: auto;
422
- }
423
- div.bloc {
424
- width:80%; /* largeur du bloc */
425
- padding:10px; /* aération interne du bloc */
426
- vertical-align:middle;
427
- display:inline-block;
428
- line-height:1.2; /* on rétablit le line-height */
429
- text-align:center; /* ... et l\'alignement du texte */
430
- }
431
- .wpm_social {
432
- padding: 0 45px;
433
- text-align: center;
434
- }
435
- @media (max-width: 640px) {
436
- body {
437
- font-size:1.2rem;
438
- }
439
- }
440
- @media (min-width: 640px) {
441
- body {
442
- font-size:1rem;
443
- }
444
- }
445
- @media (min-width:960px) {
446
- body {
447
- font-size:1.2rem;
448
- }
449
- }
450
- @media (min-width:1100px) {
451
- body {
452
- font-size:1.5rem;
453
- }
454
- }
455
- /* On ajoute les styles */
456
- %ADDSTYLEWYSIJA%
457
- %ADDSTYLE%
458
-
459
- </style>
460
-
461
- <!--[if lt IE 7]>
462
- <style type="text/css">
463
- #wrapper { height:100%; }
464
- div.bloc { display:inline; /* correctif inline-block*/ }
465
- div.conteneur > span { zoom:1; /* layout */ }
466
- </style>
467
- <![endif]-->
468
- %ANALYTICS%
469
- %HEADERCODE%
470
- %CSSSLIDER%
471
- %SCRIPTSLIDER%
472
- %SCRIPTSLIDESHOW%
473
- </head>
474
-
475
- <body>
476
-
477
- <div id="wrapper">
478
-
479
- %TOPSOCIALICON%
480
- <!-- #header -->
481
-
482
- <div id="content">
483
- %SLIDESHOWAL%
484
- %LOGOIMAGE%
485
- %SLIDESHOWBL%
486
- <div id="sscontent">
487
- <h3>%TITRE%</h3>
488
- <p>%TEXTE%</p>
489
- %SLIDESHOWBT%
490
- %COUNTER%
491
- %NEWSLETTER%
492
- </div>
493
- %BOTTOMSOCIALICON%
494
- </div><!-- #content -->
495
-
496
- <div id="footer">
497
- <div class="bloc">%COPYRIGHT%</div>
498
- <span></span>
499
- </div><!-- #footer -->
500
-
501
- </div><!-- #wrapper -->
502
-
503
- </body>
504
-
505
- </html>
506
- ';
507
-
508
- }
509
-
510
- /* Mode Maintenance */
511
- function wpm_maintenance_mode() {
512
-
513
- global $current_user;
514
-
515
- if(get_option('wp_maintenance_settings')) { extract(get_option('wp_maintenance_settings')); }
516
- $paramMMode = get_option('wp_maintenance_settings');
517
-
518
- if( isset($paramMMode) && !empty($paramMMode) ) {
519
- foreach($paramMMode as $var =>$value) {
520
- $paramMMode[$var] = ''.$value.'';
521
- }
522
- }
523
-
524
- if(get_option('wp_maintenance_slider')) { extract(get_option('wp_maintenance_slider')); }
525
- $paramSlider = get_option('wp_maintenance_slider');
526
-
527
- if(get_option('wp_maintenance_slider_options')) { extract(get_option('wp_maintenance_slider_options')); }
528
- $paramSliderOptions = get_option('wp_maintenance_slider_options');
529
-
530
- if(get_option('wp_maintenance_limit')) { extract(get_option('wp_maintenance_limit')); }
531
- $paramLimit = get_option('wp_maintenance_limit');
532
- $statusActive = get_option('wp_maintenance_active');
533
-
534
- // Récupère les ip autorisee
535
- $paramIpAddress = get_option('wp_maintenance_ipaddresses');
536
-
537
- if( !isset($paramMMode['active']) ) { $paramMMode['active'] = 0 ; }
538
- if( !isset($statusA
1
  <?php
 
2
  /*
3
  * Plugin Name: WP Maintenance
4
  * Plugin URI: https://fr.wordpress.org/plugins/wp-maintenance/
5
+ * Description: The WP Maintenance plugin allows you to put your website on the waiting time for you to do maintenance or launch your website. Personalize this page with picture, countdown...
6
  * Author: Florent Maillefaud
7
  * Author URI: https://wpmaintenance.info
8
+ * Version: 3.0
9
  * Text Domain: wp-maintenance
10
  * Domain Path: /languages/
11
  */
27
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28
  */
29
 
 
30
  defined( 'ABSPATH' )
31
  or die( 'No direct load ! ' );
32